diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2017-09-12 10:27:29 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2017-09-12 08:34:13 +0000 |
commit | 53d399fe6415a96ea6986ec0d402a9c07da72453 (patch) | |
tree | ce7dbd5d170326a7d1c5f69f5dcd841c178e0dc0 /chromium/chrome/browser/ui/webui/settings/chromeos | |
parent | a3ee7849e3b0ad3d5f9595fa1cfd694c22dcee2a (diff) |
BASELINE: Update Chromium to 60.0.3112.116 and Ninja to 1.8.2
Also adds a few devtools and webui files needed for new features.
Change-Id: I431976cc9f4c209d062a925ab6a5d63ec61abcfe
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
Diffstat (limited to 'chromium/chrome/browser/ui/webui/settings/chromeos')
27 files changed, 3892 insertions, 0 deletions
diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/accessibility_handler.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/accessibility_handler.cc new file mode 100644 index 00000000000..a74053c73a4 --- /dev/null +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/accessibility_handler.cc @@ -0,0 +1,67 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/webui/settings/chromeos/accessibility_handler.h" + +#include "base/bind.h" +#include "base/bind_helpers.h" +#include "chrome/browser/extensions/extension_tab_util.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/browser_finder.h" +#include "chrome/common/extensions/extension_constants.h" +#include "content/public/browser/web_ui.h" +#include "extensions/browser/extension_registry.h" + +namespace chromeos { +namespace settings { + +AccessibilityHandler::AccessibilityHandler(content::WebUI* webui) + : profile_(Profile::FromWebUI(webui)) { +} + +AccessibilityHandler::~AccessibilityHandler() {} + +void AccessibilityHandler::RegisterMessages() { + web_ui()->RegisterMessageCallback( + "showChromeVoxSettings", + base::Bind(&AccessibilityHandler::HandleShowChromeVoxSettings, + base::Unretained(this))); + web_ui()->RegisterMessageCallback( + "showSelectToSpeakSettings", + base::Bind(&AccessibilityHandler::HandleShowSelectToSpeakSettings, + base::Unretained(this))); + web_ui()->RegisterMessageCallback( + "showSwitchAccessSettings", + base::Bind(&AccessibilityHandler::HandleShowSwitchAccessSettings, + base::Unretained(this))); +} + +void AccessibilityHandler::HandleShowChromeVoxSettings( + const base::ListValue* args) { + OpenExtensionOptionsPage(extension_misc::kChromeVoxExtensionId); +} + +void AccessibilityHandler::HandleShowSelectToSpeakSettings( + const base::ListValue* args) { + OpenExtensionOptionsPage(extension_misc::kSelectToSpeakExtensionId); +} + +void AccessibilityHandler::HandleShowSwitchAccessSettings( + const base::ListValue* args) { + OpenExtensionOptionsPage(extension_misc::kSwitchAccessExtensionId); +} + +void AccessibilityHandler::OpenExtensionOptionsPage(const char extension_id[]) { + const extensions::Extension* extension = + extensions::ExtensionRegistry::Get(profile_)->GetExtensionById( + extension_id, extensions::ExtensionRegistry::ENABLED); + if (!extension) + return; + extensions::ExtensionTabUtil::OpenOptionsPage( + extension, + chrome::FindBrowserWithWebContents(web_ui()->GetWebContents())); +} + +} // namespace settings +} // namespace chromeos diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/accessibility_handler.h b/chromium/chrome/browser/ui/webui/settings/chromeos/accessibility_handler.h new file mode 100644 index 00000000000..d03c83e2ea6 --- /dev/null +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/accessibility_handler.h @@ -0,0 +1,51 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_ACCESSIBILITY_HANDLER_H_ +#define CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_ACCESSIBILITY_HANDLER_H_ + +#include "base/macros.h" +#include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h" + +namespace base { +class ListValue; +} + +namespace content { +class WebUI; +} + +class Profile; + +namespace chromeos { +namespace settings { + +class AccessibilityHandler : public ::settings::SettingsPageUIHandler { + public: + explicit AccessibilityHandler(content::WebUI* webui); + ~AccessibilityHandler() override; + + // SettingsPageUIHandler implementation. + void RegisterMessages() override; + void OnJavascriptAllowed() override {} + void OnJavascriptDisallowed() override {} + + private: + // Callback for the messages to show settings for ChromeVox, + // Select To Speak, or Switch Access. + void HandleShowChromeVoxSettings(const base::ListValue* args); + void HandleShowSelectToSpeakSettings(const base::ListValue* args); + void HandleShowSwitchAccessSettings(const base::ListValue* args); + + void OpenExtensionOptionsPage(const char extension_id[]); + + Profile* profile_; // Weak pointer. + + DISALLOW_COPY_AND_ASSIGN(AccessibilityHandler); +}; + +} // namespace settings +} // namespace chromeos + +#endif // CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_ACCESSIBILITY_HANDLER_H_ diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/android_apps_handler.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/android_apps_handler.cc new file mode 100644 index 00000000000..51e85cb3f92 --- /dev/null +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/android_apps_handler.cc @@ -0,0 +1,103 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/webui/settings/chromeos/android_apps_handler.h" + +#include "base/values.h" +#include "chrome/browser/chromeos/arc/arc_util.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/app_list/arc/arc_app_utils.h" // kSettingsAppId +#include "ui/events/event_constants.h" + +namespace chromeos { +namespace settings { + +AndroidAppsHandler::AndroidAppsHandler(Profile* profile) + : arc_prefs_observer_(this), + arc_session_manager_observer_(this), + profile_(profile), + weak_ptr_factory_(this) {} + +AndroidAppsHandler::~AndroidAppsHandler() {} + +void AndroidAppsHandler::RegisterMessages() { + web_ui()->RegisterMessageCallback( + "requestAndroidAppsInfo", + base::Bind(&AndroidAppsHandler::HandleRequestAndroidAppsInfo, + weak_ptr_factory_.GetWeakPtr())); + web_ui()->RegisterMessageCallback( + "showAndroidAppsSettings", + base::Bind(&AndroidAppsHandler::ShowAndroidAppsSettings, + weak_ptr_factory_.GetWeakPtr())); +} + +void AndroidAppsHandler::OnJavascriptAllowed() { + ArcAppListPrefs* arc_prefs = ArcAppListPrefs::Get(profile_); + if (arc_prefs) { + arc_prefs_observer_.Add(arc_prefs); + // arc::ArcSessionManager is assosiated with primary profile. + arc_session_manager_observer_.Add(arc::ArcSessionManager::Get()); + } +} + +void AndroidAppsHandler::OnJavascriptDisallowed() { + arc_prefs_observer_.RemoveAll(); + arc_session_manager_observer_.RemoveAll(); +} + +void AndroidAppsHandler::OnAppRegistered( + const std::string& app_id, + const ArcAppListPrefs::AppInfo& app_info) { + OnAppChanged(app_id); +} + +void AndroidAppsHandler::OnAppRemoved(const std::string& app_id) { + OnAppChanged(app_id); +} + +void AndroidAppsHandler::OnAppChanged(const std::string& app_id) { + if (app_id != arc::kSettingsAppId) + return; + SendAndroidAppsInfo(); +} + +void AndroidAppsHandler::OnArcPlayStoreEnabledChanged(bool enabled) { + SendAndroidAppsInfo(); +} + +std::unique_ptr<base::DictionaryValue> +AndroidAppsHandler::BuildAndroidAppsInfo() { + std::unique_ptr<base::DictionaryValue> info(new base::DictionaryValue); + info->SetBoolean("playStoreEnabled", + arc::IsArcPlayStoreEnabledForProfile(profile_)); + info->SetBoolean( + "settingsAppAvailable", + ArcAppListPrefs::Get(profile_)->IsRegistered(arc::kSettingsAppId)); + return info; +} + +void AndroidAppsHandler::HandleRequestAndroidAppsInfo( + const base::ListValue* args) { + SendAndroidAppsInfo(); +} + +void AndroidAppsHandler::SendAndroidAppsInfo() { + AllowJavascript(); + std::unique_ptr<base::DictionaryValue> info = BuildAndroidAppsInfo(); + FireWebUIListener("android-apps-info-update", *info); +} + +void AndroidAppsHandler::ShowAndroidAppsSettings(const base::ListValue* args) { + CHECK_EQ(1U, args->GetSize()); + bool activated_from_keyboard = false; + args->GetBoolean(0, &activated_from_keyboard); + int flags = activated_from_keyboard ? ui::EF_NONE : ui::EF_LEFT_MOUSE_BUTTON; + + // Settings in secondary profile cannot access ARC. + CHECK(arc::IsArcAllowedForProfile(profile_)); + arc::LaunchAndroidSettingsApp(profile_, flags); +} + +} // namespace settings +} // namespace chromeos diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/android_apps_handler.h b/chromium/chrome/browser/ui/webui/settings/chromeos/android_apps_handler.h new file mode 100644 index 00000000000..62a530c4742 --- /dev/null +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/android_apps_handler.h @@ -0,0 +1,66 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_ANDROID_APPS_HANDLER_H_ +#define CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_ANDROID_APPS_HANDLER_H_ + +#include <memory> + +#include "base/macros.h" +#include "base/memory/weak_ptr.h" +#include "base/scoped_observer.h" +#include "chrome/browser/chromeos/arc/arc_session_manager.h" +#include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h" +#include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h" + +class Profile; + +namespace base { +class DictionaryValue; +} + +namespace chromeos { +namespace settings { + +class AndroidAppsHandler : public ::settings::SettingsPageUIHandler, + public ArcAppListPrefs::Observer, + public arc::ArcSessionManager::Observer { + public: + explicit AndroidAppsHandler(Profile* profile); + ~AndroidAppsHandler() override; + + // SettingsPageUIHandler + void RegisterMessages() override; + void OnJavascriptAllowed() override; + void OnJavascriptDisallowed() override; + + // ArcAppListPrefs::Observer + void OnAppRemoved(const std::string& app_id) override; + void OnAppRegistered(const std::string& app_id, + const ArcAppListPrefs::AppInfo& app_info) override; + + // arc::ArcSessionManager::Observer: + void OnArcPlayStoreEnabledChanged(bool enabled) override; + + private: + std::unique_ptr<base::DictionaryValue> BuildAndroidAppsInfo(); + void OnAppChanged(const std::string& app_id); + void HandleRequestAndroidAppsInfo(const base::ListValue* args); + void SendAndroidAppsInfo(); + void ShowAndroidAppsSettings(const base::ListValue* args); + + ScopedObserver<ArcAppListPrefs, ArcAppListPrefs::Observer> + arc_prefs_observer_; + ScopedObserver<arc::ArcSessionManager, arc::ArcSessionManager::Observer> + arc_session_manager_observer_; + Profile* profile_; // unowned + base::WeakPtrFactory<AndroidAppsHandler> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(AndroidAppsHandler); +}; + +} // namespace settings +} // namespace chromeos + +#endif // CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_ANDROID_APPS_HANDLER_H_ diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/change_picture_handler.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/change_picture_handler.cc new file mode 100644 index 00000000000..378b08c4b00 --- /dev/null +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/change_picture_handler.cc @@ -0,0 +1,409 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/webui/settings/chromeos/change_picture_handler.h" + +#include <utility> + +#include "base/bind.h" +#include "base/bind_helpers.h" +#include "base/command_line.h" +#include "base/metrics/histogram_macros.h" +#include "base/path_service.h" +#include "base/strings/string_util.h" +#include "base/strings/utf_string_conversions.h" +#include "base/values.h" +#include "chrome/browser/chrome_notification_types.h" +#include "chrome/browser/chromeos/accessibility/accessibility_manager.h" +#include "chrome/browser/chromeos/camera_presence_notifier.h" +#include "chrome/browser/chromeos/login/users/avatar/user_image_manager.h" +#include "chrome/browser/chromeos/login/users/chrome_user_manager.h" +#include "chrome/browser/chromeos/login/users/default_user_image/default_user_images.h" +#include "chrome/browser/chromeos/profiles/profile_helper.h" +#include "chrome/browser/ui/browser_finder.h" +#include "chrome/browser/ui/browser_window.h" +#include "chrome/browser/ui/chrome_select_file_policy.h" +#include "chrome/common/chrome_paths.h" +#include "chrome/common/chrome_switches.h" +#include "chrome/common/url_constants.h" +#include "chrome/grit/browser_resources.h" +#include "chrome/grit/generated_resources.h" +#include "chromeos/audio/chromeos_sounds.h" +#include "components/user_manager/user.h" +#include "components/user_manager/user_image/user_image.h" +#include "components/user_manager/user_manager.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/notification_service.h" +#include "content/public/browser/web_ui.h" +#include "content/public/common/url_constants.h" +#include "media/audio/sounds/sounds_manager.h" +#include "net/base/data_url.h" +#include "ui/base/l10n/l10n_util.h" +#include "ui/base/resource/resource_bundle.h" +#include "ui/base/webui/web_ui_util.h" +#include "ui/views/widget/widget.h" +#include "url/gurl.h" + +using content::BrowserThread; + +namespace chromeos { +namespace settings { + +namespace { + +// Returns info about extensions for files we support as user images. +ui::SelectFileDialog::FileTypeInfo GetUserImageFileTypeInfo() { + ui::SelectFileDialog::FileTypeInfo file_type_info; + file_type_info.extensions.resize(1); + + file_type_info.extensions[0].push_back(FILE_PATH_LITERAL("bmp")); + + file_type_info.extensions[0].push_back(FILE_PATH_LITERAL("jpg")); + file_type_info.extensions[0].push_back(FILE_PATH_LITERAL("jpeg")); + + file_type_info.extensions[0].push_back(FILE_PATH_LITERAL("png")); + + file_type_info.extensions[0].push_back(FILE_PATH_LITERAL("tif")); + file_type_info.extensions[0].push_back(FILE_PATH_LITERAL("tiff")); + + file_type_info.extension_description_overrides.resize(1); + file_type_info.extension_description_overrides[0] = + l10n_util::GetStringUTF16(IDS_IMAGE_FILES); + + return file_type_info; +} + +// Time histogram suffix for profile image download. +const char kProfileDownloadReason[] = "Preferences"; + +} // namespace + +ChangePictureHandler::ChangePictureHandler() + : previous_image_url_(url::kAboutBlankURL), + previous_image_index_(user_manager::User::USER_IMAGE_INVALID), + user_manager_observer_(this), + camera_observer_(this) { + ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance(); + media::SoundsManager* manager = media::SoundsManager::Get(); + manager->Initialize(SOUND_OBJECT_DELETE, + bundle.GetRawDataResource(IDR_SOUND_OBJECT_DELETE_WAV)); + manager->Initialize(SOUND_CAMERA_SNAP, + bundle.GetRawDataResource(IDR_SOUND_CAMERA_SNAP_WAV)); +} + +ChangePictureHandler::~ChangePictureHandler() { + if (select_file_dialog_.get()) + select_file_dialog_->ListenerDestroyed(); +} + +void ChangePictureHandler::RegisterMessages() { + web_ui()->RegisterMessageCallback( + "chooseFile", base::Bind(&ChangePictureHandler::HandleChooseFile, + base::Unretained(this))); + web_ui()->RegisterMessageCallback( + "photoTaken", base::Bind(&ChangePictureHandler::HandlePhotoTaken, + base::Unretained(this))); + web_ui()->RegisterMessageCallback( + "discardPhoto", base::Bind(&ChangePictureHandler::HandleDiscardPhoto, + base::Unretained(this))); + web_ui()->RegisterMessageCallback( + "onChangePicturePageInitialized", + base::Bind(&ChangePictureHandler::HandlePageInitialized, + base::Unretained(this))); + web_ui()->RegisterMessageCallback( + "selectImage", base::Bind(&ChangePictureHandler::HandleSelectImage, + base::Unretained(this))); +} + +void ChangePictureHandler::OnJavascriptAllowed() { + user_manager_observer_.Add(user_manager::UserManager::Get()); + camera_observer_.Add(CameraPresenceNotifier::GetInstance()); +} + +void ChangePictureHandler::OnJavascriptDisallowed() { + user_manager_observer_.Remove(user_manager::UserManager::Get()); + camera_observer_.Remove(CameraPresenceNotifier::GetInstance()); +} + +void ChangePictureHandler::SendDefaultImages() { + base::ListValue image_urls; + for (int i = default_user_image::kFirstDefaultImageIndex; + i < default_user_image::kDefaultImagesCount; ++i) { + std::unique_ptr<base::DictionaryValue> image_data( + new base::DictionaryValue); + image_data->SetString("url", default_user_image::GetDefaultImageUrl(i)); + image_data->SetString("author", + l10n_util::GetStringUTF16( + default_user_image::kDefaultImageAuthorIDs[i])); + image_data->SetString("website", + l10n_util::GetStringUTF16( + default_user_image::kDefaultImageWebsiteIDs[i])); + image_data->SetString("title", + default_user_image::GetDefaultImageDescription(i)); + image_urls.Append(std::move(image_data)); + } + FireWebUIListener("default-images-changed", image_urls); +} + +void ChangePictureHandler::HandleChooseFile(const base::ListValue* args) { + DCHECK(args && args->empty()); + select_file_dialog_ = ui::SelectFileDialog::Create( + this, new ChromeSelectFilePolicy(web_ui()->GetWebContents())); + + base::FilePath downloads_path; + if (!PathService::Get(chrome::DIR_DEFAULT_DOWNLOADS, &downloads_path)) { + NOTREACHED(); + return; + } + + // Static so we initialize it only once. + CR_DEFINE_STATIC_LOCAL(ui::SelectFileDialog::FileTypeInfo, file_type_info, + (GetUserImageFileTypeInfo())); + + select_file_dialog_->SelectFile( + ui::SelectFileDialog::SELECT_OPEN_FILE, + l10n_util::GetStringUTF16(IDS_DOWNLOAD_TITLE), downloads_path, + &file_type_info, 0, FILE_PATH_LITERAL(""), GetBrowserWindow(), NULL); +} + +void ChangePictureHandler::HandleDiscardPhoto(const base::ListValue* args) { + DCHECK(args->empty()); + AccessibilityManager::Get()->PlayEarcon( + SOUND_OBJECT_DELETE, PlaySoundOption::SPOKEN_FEEDBACK_ENABLED); +} + +void ChangePictureHandler::HandlePhotoTaken(const base::ListValue* args) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + AccessibilityManager::Get()->PlayEarcon( + SOUND_CAMERA_SNAP, PlaySoundOption::SPOKEN_FEEDBACK_ENABLED); + + std::string image_url; + if (!args || args->GetSize() != 1 || !args->GetString(0, &image_url)) + NOTREACHED(); + DCHECK(!image_url.empty()); + + std::string mime_type, charset, raw_data; + if (!net::DataURL::Parse(GURL(image_url), &mime_type, &charset, &raw_data)) + NOTREACHED(); + DCHECK_EQ("image/png", mime_type); + + user_photo_ = gfx::ImageSkia(); + user_photo_data_url_ = image_url; + + ImageDecoder::Cancel(this); + ImageDecoder::Start(this, raw_data); +} + +void ChangePictureHandler::HandlePageInitialized(const base::ListValue* args) { + DCHECK(args && args->empty()); + + AllowJavascript(); + + SendDefaultImages(); + SendSelectedImage(); + UpdateProfileImage(); +} + +void ChangePictureHandler::SendSelectedImage() { + const user_manager::User* user = GetUser(); + DCHECK(user->GetAccountId().is_valid()); + + previous_image_index_ = user->image_index(); + switch (previous_image_index_) { + case user_manager::User::USER_IMAGE_EXTERNAL: { + // User has image from camera/file, record it and add to the image list. + previous_image_ = user->GetImage(); + SendOldImage(webui::GetBitmapDataUrl(*previous_image_.bitmap())); + break; + } + case user_manager::User::USER_IMAGE_PROFILE: { + // User has their Profile image as the current image. + SendProfileImage(user->GetImage(), true); + break; + } + default: { + DCHECK(previous_image_index_ >= 0 && + previous_image_index_ < default_user_image::kDefaultImagesCount); + if (previous_image_index_ >= + default_user_image::kFirstDefaultImageIndex) { + // User has image from the current set of default images. + base::Value image_url( + default_user_image::GetDefaultImageUrl(previous_image_index_)); + FireWebUIListener("selected-image-changed", image_url); + } else { + // User has an old default image, so present it in the same manner as a + // previous image from file. + SendOldImage( + default_user_image::GetDefaultImageUrl(previous_image_index_)); + } + } + } +} + +void ChangePictureHandler::SendProfileImage(const gfx::ImageSkia& image, + bool should_select) { + base::Value data_url(webui::GetBitmapDataUrl(*image.bitmap())); + base::Value select(should_select); + FireWebUIListener("profile-image-changed", data_url, select); +} + +void ChangePictureHandler::UpdateProfileImage() { + UserImageManager* user_image_manager = + ChromeUserManager::Get()->GetUserImageManager(GetUser()->GetAccountId()); + // If we have a downloaded profile image and haven't sent it in + // |SendSelectedImage|, send it now (without selecting). + if (previous_image_index_ != user_manager::User::USER_IMAGE_PROFILE && + !user_image_manager->DownloadedProfileImage().isNull()) + SendProfileImage(user_image_manager->DownloadedProfileImage(), false); + + user_image_manager->DownloadProfileImage(kProfileDownloadReason); +} + +void ChangePictureHandler::SendOldImage(const std::string& image_url) { + previous_image_url_ = image_url; + base::Value url(image_url); + FireWebUIListener("old-image-changed", url); +} + +void ChangePictureHandler::HandleSelectImage(const base::ListValue* args) { + std::string image_url; + std::string image_type; + if (!args || args->GetSize() != 2 || !args->GetString(0, &image_url) || + !args->GetString(1, &image_type)) { + NOTREACHED(); + return; + } + // |image_url| may be empty unless |image_type| is "default". + DCHECK(!image_type.empty()); + + UserImageManager* user_image_manager = + ChromeUserManager::Get()->GetUserImageManager(GetUser()->GetAccountId()); + int image_index = user_manager::User::USER_IMAGE_INVALID; + bool waiting_for_camera_photo = false; + + if (image_type == "old") { + // Previous image (from camera or manually uploaded) re-selected. + DCHECK(!previous_image_.isNull()); + user_image_manager->SaveUserImage( + user_manager::UserImage::CreateAndEncode( + previous_image_, + user_manager::UserImage::FORMAT_JPEG)); + + UMA_HISTOGRAM_EXACT_LINEAR("UserImage.ChangeChoice", + default_user_image::kHistogramImageOld, + default_user_image::kHistogramImagesCount); + VLOG(1) << "Selected old user image"; + } else if (image_type == "default" && + default_user_image::IsDefaultImageUrl(image_url, &image_index)) { + // One of the default user images. + user_image_manager->SaveUserDefaultImageIndex(image_index); + + UMA_HISTOGRAM_EXACT_LINEAR( + "UserImage.ChangeChoice", + default_user_image::GetDefaultImageHistogramValue(image_index), + default_user_image::kHistogramImagesCount); + VLOG(1) << "Selected default user image: " << image_index; + } else if (image_type == "camera") { + // Camera image is selected. + if (user_photo_.isNull()) { + waiting_for_camera_photo = true; + VLOG(1) << "Still waiting for camera image to decode"; + } else { + SetImageFromCamera(user_photo_); + } + } else if (image_type == "profile") { + // Profile image selected. Could be previous (old) user image. + user_image_manager->SaveUserImageFromProfileImage(); + + if (previous_image_index_ == user_manager::User::USER_IMAGE_PROFILE) { + UMA_HISTOGRAM_EXACT_LINEAR("UserImage.ChangeChoice", + default_user_image::kHistogramImageOld, + default_user_image::kHistogramImagesCount); + VLOG(1) << "Selected old (profile) user image"; + } else { + UMA_HISTOGRAM_EXACT_LINEAR("UserImage.ChangeChoice", + default_user_image::kHistogramImageFromProfile, + default_user_image::kHistogramImagesCount); + VLOG(1) << "Selected profile image"; + } + } else { + NOTREACHED() << "Unexpected image type: " << image_type; + } + + // Ignore the result of the previous decoding if it's no longer needed. + if (!waiting_for_camera_photo) + ImageDecoder::Cancel(this); +} + +void ChangePictureHandler::FileSelected(const base::FilePath& path, + int index, + void* params) { + ChromeUserManager::Get() + ->GetUserImageManager(GetUser()->GetAccountId()) + ->SaveUserImageFromFile(path); + UMA_HISTOGRAM_EXACT_LINEAR("UserImage.ChangeChoice", + default_user_image::kHistogramImageFromFile, + default_user_image::kHistogramImagesCount); + VLOG(1) << "Selected image from file"; +} + +void ChangePictureHandler::SetImageFromCamera(const gfx::ImageSkia& photo) { + ChromeUserManager::Get() + ->GetUserImageManager(GetUser()->GetAccountId()) + ->SaveUserImage(user_manager::UserImage::CreateAndEncode( + photo, user_manager::UserImage::FORMAT_JPEG)); + UMA_HISTOGRAM_EXACT_LINEAR("UserImage.ChangeChoice", + default_user_image::kHistogramImageFromCamera, + default_user_image::kHistogramImagesCount); + VLOG(1) << "Selected camera photo"; +} + +void ChangePictureHandler::SetCameraPresent(bool present) { + FireWebUIListener("camera-presence-changed", base::Value(present)); +} + +void ChangePictureHandler::OnCameraPresenceCheckDone(bool is_camera_present) { + SetCameraPresent(is_camera_present); +} + +void ChangePictureHandler::OnUserImageChanged(const user_manager::User& user) { + // Not initialized yet. + if (previous_image_index_ == user_manager::User::USER_IMAGE_INVALID) + return; + SendSelectedImage(); +} + +void ChangePictureHandler::OnUserProfileImageUpdated( + const user_manager::User& user, + const gfx::ImageSkia& profile_image) { + // User profile image has been updated. + SendProfileImage(profile_image, false); +} + +gfx::NativeWindow ChangePictureHandler::GetBrowserWindow() const { + Browser* browser = + chrome::FindBrowserWithWebContents(web_ui()->GetWebContents()); + return browser->window()->GetNativeWindow(); +} + +void ChangePictureHandler::OnImageDecoded(const SkBitmap& decoded_image) { + user_photo_ = gfx::ImageSkia::CreateFrom1xBitmap(decoded_image); + SetImageFromCamera(user_photo_); +} + +void ChangePictureHandler::OnDecodeImageFailed() { + NOTREACHED() << "Failed to decode PNG image from WebUI"; +} + +const user_manager::User* ChangePictureHandler::GetUser() const { + Profile* profile = Profile::FromWebUI(web_ui()); + const user_manager::User* user = + ProfileHelper::Get()->GetUserByProfile(profile); + if (!user) + return user_manager::UserManager::Get()->GetActiveUser(); + return user; +} + +} // namespace settings +} // namespace chromeos diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/change_picture_handler.h b/chromium/chrome/browser/ui/webui/settings/chromeos/change_picture_handler.h new file mode 100644 index 00000000000..a213282241e --- /dev/null +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/change_picture_handler.h @@ -0,0 +1,139 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_CHANGE_PICTURE_HANDLER_H_ +#define CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_CHANGE_PICTURE_HANDLER_H_ + +#include "base/macros.h" +#include "base/scoped_observer.h" +#include "chrome/browser/chromeos/camera_presence_notifier.h" +#include "chrome/browser/image_decoder.h" +#include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h" +#include "components/user_manager/user_manager.h" +#include "ui/gfx/image/image_skia.h" +#include "ui/gfx/native_widget_types.h" +#include "ui/shell_dialogs/select_file_dialog.h" + +namespace base { +class ListValue; +} + +namespace user_manager { +class User; +} + +namespace chromeos { + +namespace settings { + +// ChromeOS user image settings page UI handler. +class ChangePictureHandler : public ::settings::SettingsPageUIHandler, + public ui::SelectFileDialog::Listener, + public user_manager::UserManager::Observer, + public ImageDecoder::ImageRequest, + public CameraPresenceNotifier::Observer { + public: + ChangePictureHandler(); + ~ChangePictureHandler() override; + + // WebUIMessageHandler implementation. + void RegisterMessages() override; + void OnJavascriptAllowed() override; + void OnJavascriptDisallowed() override; + + // CameraPresenceNotifier::Observer implementation: + void OnCameraPresenceCheckDone(bool is_camera_present) override; + + private: + // Sends list of available default images to the page. + void SendDefaultImages(); + + // Sends current selection to the page. + void SendSelectedImage(); + + // Sends the profile image to the page. If |should_select| is true then + // the profile image element is selected. + void SendProfileImage(const gfx::ImageSkia& image, bool should_select); + + // Starts profile image update and shows the last downloaded profile image, + // if any, on the page. Shouldn't be called before |SendProfileImage|. + void UpdateProfileImage(); + + // Sends previous user image to the page. + void SendOldImage(const std::string& image_url); + + // Starts camera presence check. + void CheckCameraPresence(); + + // Updates UI with camera presence state. + void SetCameraPresent(bool present); + + // Opens a file selection dialog to choose user image from file. + void HandleChooseFile(const base::ListValue* args); + + // Handles photo taken with WebRTC UI. + void HandlePhotoTaken(const base::ListValue* args); + + // Handles 'discard-photo' button click. + void HandleDiscardPhoto(const base::ListValue* args); + + // Gets the list of available user images and sends it to the page. + void HandleGetAvailableImages(const base::ListValue* args); + + // Handles page initialized event. + void HandlePageInitialized(const base::ListValue* args); + + // Selects one of the available images as user's. + void HandleSelectImage(const base::ListValue* args); + + // SelectFileDialog::Delegate implementation. + void FileSelected(const base::FilePath& path, + int index, + void* params) override; + + // user_manager::UserManager::Observer implementation. + void OnUserImageChanged(const user_manager::User& user) override; + void OnUserProfileImageUpdated(const user_manager::User& user, + const gfx::ImageSkia& profile_image) override; + + // Sets user image to photo taken from camera. + void SetImageFromCamera(const gfx::ImageSkia& photo); + + // Returns handle to browser window or NULL if it can't be found. + gfx::NativeWindow GetBrowserWindow() const; + + // Overriden from ImageDecoder::ImageRequest: + void OnImageDecoded(const SkBitmap& decoded_image) override; + void OnDecodeImageFailed() override; + + // Returns user related to current WebUI. If this user doesn't exist, + // returns active user. + const user_manager::User* GetUser() const; + + scoped_refptr<ui::SelectFileDialog> select_file_dialog_; + + // Previous user image from camera/file and its data URL. + gfx::ImageSkia previous_image_; + std::string previous_image_url_; + + // Index of the previous user image. + int previous_image_index_; + + // Last user photo, if taken. + gfx::ImageSkia user_photo_; + + // Data URL for |user_photo_|. + std::string user_photo_data_url_; + + ScopedObserver<user_manager::UserManager, ChangePictureHandler> + user_manager_observer_; + ScopedObserver<CameraPresenceNotifier, ChangePictureHandler> camera_observer_; + + DISALLOW_COPY_AND_ASSIGN(ChangePictureHandler); +}; + +} // namespace settings +} // namespace chromeos + +#endif // CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_CHANGE_PICTURE_HANDLER_H_ diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc new file mode 100644 index 00000000000..e5d02eb7315 --- /dev/null +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc @@ -0,0 +1,447 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.h" + +#include <utility> + +#include "base/bind.h" +#include "base/bind_helpers.h" +#include "base/files/file_util.h" +#include "base/json/json_string_value_serializer.h" +#include "base/memory/ptr_util.h" +#include "base/metrics/histogram_macros.h" +#include "base/path_service.h" +#include "base/strings/string_util.h" +#include "base/threading/sequenced_task_runner_handle.h" +#include "base/values.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/chromeos/printing/ppd_provider_factory.h" +#include "chrome/browser/chromeos/printing/printer_configurer.h" +#include "chrome/browser/chromeos/printing/printer_discoverer.h" +#include "chrome/browser/chromeos/printing/printers_manager_factory.h" +#include "chrome/browser/download/download_prefs.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/browser_finder.h" +#include "chrome/browser/ui/browser_window.h" +#include "chrome/browser/ui/chrome_select_file_policy.h" +#include "chrome/common/chrome_paths.h" +#include "chromeos/dbus/dbus_thread_manager.h" +#include "chromeos/dbus/debug_daemon_client.h" +#include "chromeos/printing/ppd_cache.h" +#include "chromeos/printing/ppd_provider.h" +#include "content/public/browser/browser_context.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/web_ui.h" +#include "google_apis/google_api_keys.h" +#include "net/base/filename_util.h" +#include "net/url_request/url_request_context_getter.h" +#include "printing/backend/print_backend.h" +#include "url/third_party/mozilla/url_parse.h" + +namespace chromeos { +namespace settings { + +namespace { + +// These values are written to logs. New enum values can be added, but existing +// enums must never be renumbered or deleted and reused. +enum PpdSourceForHistogram { kUser = 0, kScs = 1, kPpdSourceMax }; + +void RecordPpdSource(const PpdSourceForHistogram& source) { + UMA_HISTOGRAM_ENUMERATION("Printing.CUPS.PpdSource", source, kPpdSourceMax); +} + +void OnRemovedPrinter(const Printer::PrinterProtocol& protocol, bool success) { + UMA_HISTOGRAM_ENUMERATION("Printing.CUPS.PrinterRemoved", protocol, + Printer::PrinterProtocol::kProtocolMax); +} + +std::unique_ptr<base::DictionaryValue> GetPrinterInfo(const Printer& printer) { + std::unique_ptr<base::DictionaryValue> printer_info = + base::MakeUnique<base::DictionaryValue>(); + printer_info->SetString("printerId", printer.id()); + printer_info->SetString("printerName", printer.display_name()); + printer_info->SetString("printerDescription", printer.description()); + printer_info->SetString("printerManufacturer", printer.manufacturer()); + printer_info->SetString("printerModel", printer.model()); + // Get protocol, ip address and queue from the printer's URI. + const std::string printer_uri = printer.uri(); + url::Parsed parsed; + url::ParseStandardURL(printer_uri.c_str(), printer_uri.length(), &parsed); + + std::string scheme; + std::string host; + std::string path; + if (parsed.scheme.len > 0) + scheme = std::string(printer_uri, parsed.scheme.begin, parsed.scheme.len); + if (parsed.host.len > 0) + host = std::string(printer_uri, parsed.host.begin, parsed.host.len); + if (parsed.path.len > 0) + path = std::string(printer_uri, parsed.path.begin, parsed.path.len); + if (base::ToLowerASCII(scheme) == "usb") { + // USB has URI path (and, maybe, query) components that aren't really + // associated with a queue -- the mapping between printing semantics and URI + // semantics breaks down a bit here. From the user's point of view, the + // entire host/path/query block is the printer address for USB. + printer_info->SetString("printerAddress", + printer_uri.substr(parsed.host.begin)); + } else { + printer_info->SetString("printerAddress", host); + if (!path.empty()) { + printer_info->SetString("printerQueue", path.substr(1)); + } + } + printer_info->SetString("printerProtocol", base::ToLowerASCII(scheme)); + + return printer_info; +} + +} // namespace + +CupsPrintersHandler::CupsPrintersHandler(content::WebUI* webui) + : printer_discoverer_(nullptr), + profile_(Profile::FromWebUI(webui)), + weak_factory_(this) { + ppd_provider_ = printing::CreateProvider(profile_); + printer_configurer_ = chromeos::PrinterConfigurer::Create(profile_); +} + +CupsPrintersHandler::~CupsPrintersHandler() {} + +void CupsPrintersHandler::RegisterMessages() { + web_ui()->RegisterMessageCallback( + "getCupsPrintersList", + base::Bind(&CupsPrintersHandler::HandleGetCupsPrintersList, + base::Unretained(this))); + web_ui()->RegisterMessageCallback( + "updateCupsPrinter", + base::Bind(&CupsPrintersHandler::HandleUpdateCupsPrinter, + base::Unretained(this))); + web_ui()->RegisterMessageCallback( + "removeCupsPrinter", + base::Bind(&CupsPrintersHandler::HandleRemoveCupsPrinter, + base::Unretained(this))); + web_ui()->RegisterMessageCallback( + "addCupsPrinter", base::Bind(&CupsPrintersHandler::HandleAddCupsPrinter, + base::Unretained(this))); + web_ui()->RegisterMessageCallback( + "getCupsPrinterManufacturersList", + base::Bind(&CupsPrintersHandler::HandleGetCupsPrinterManufacturers, + base::Unretained(this))); + web_ui()->RegisterMessageCallback( + "getCupsPrinterModelsList", + base::Bind(&CupsPrintersHandler::HandleGetCupsPrinterModels, + base::Unretained(this))); + web_ui()->RegisterMessageCallback( + "selectPPDFile", base::Bind(&CupsPrintersHandler::HandleSelectPPDFile, + base::Unretained(this))); + web_ui()->RegisterMessageCallback( + "startDiscoveringPrinters", + base::Bind(&CupsPrintersHandler::HandleStartDiscovery, + base::Unretained(this))); + web_ui()->RegisterMessageCallback( + "stopDiscoveringPrinters", + base::Bind(&CupsPrintersHandler::HandleStopDiscovery, + base::Unretained(this))); +} + +void CupsPrintersHandler::HandleGetCupsPrintersList( + const base::ListValue* args) { + AllowJavascript(); + + CHECK_EQ(1U, args->GetSize()); + std::string callback_id; + CHECK(args->GetString(0, &callback_id)); + + std::vector<std::unique_ptr<Printer>> printers = + PrintersManagerFactory::GetForBrowserContext(profile_)->GetPrinters(); + + auto printers_list = base::MakeUnique<base::ListValue>(); + for (const std::unique_ptr<Printer>& printer : printers) { + std::unique_ptr<base::DictionaryValue> printer_info = + GetPrinterInfo(*printer.get()); + printers_list->Append(std::move(printer_info)); + } + + auto response = base::MakeUnique<base::DictionaryValue>(); + response->Set("printerList", std::move(printers_list)); + ResolveJavascriptCallback(base::Value(callback_id), *response); +} + +void CupsPrintersHandler::HandleUpdateCupsPrinter(const base::ListValue* args) { + std::string printer_id; + std::string printer_name; + CHECK(args->GetString(0, &printer_id)); + CHECK(args->GetString(1, &printer_name)); + + std::unique_ptr<Printer> printer = base::MakeUnique<Printer>(printer_id); + printer->set_display_name(printer_name); + PrintersManagerFactory::GetForBrowserContext(profile_)->RegisterPrinter( + std::move(printer)); +} + +void CupsPrintersHandler::HandleRemoveCupsPrinter(const base::ListValue* args) { + std::string printer_id; + std::string printer_name; + CHECK(args->GetString(0, &printer_id)); + CHECK(args->GetString(1, &printer_name)); + PrintersManager* prefs = + PrintersManagerFactory::GetForBrowserContext(profile_); + auto printer = prefs->GetPrinter(printer_id); + if (!printer) + return; + + Printer::PrinterProtocol protocol = printer->GetProtocol(); + prefs->RemovePrinter(printer_id); + + chromeos::DebugDaemonClient* client = + chromeos::DBusThreadManager::Get()->GetDebugDaemonClient(); + client->CupsRemovePrinter(printer_name, + base::Bind(&OnRemovedPrinter, protocol), + base::Bind(&base::DoNothing)); +} + +void CupsPrintersHandler::HandleAddCupsPrinter(const base::ListValue* args) { + AllowJavascript(); + + const base::DictionaryValue* printer_dict = nullptr; + CHECK(args->GetDictionary(0, &printer_dict)); + + std::string printer_id; + std::string printer_name; + std::string printer_description; + std::string printer_manufacturer; + std::string printer_model; + std::string printer_address; + std::string printer_protocol; + std::string printer_queue; + std::string printer_ppd_path; + CHECK(printer_dict->GetString("printerId", &printer_id)); + CHECK(printer_dict->GetString("printerName", &printer_name)); + CHECK(printer_dict->GetString("printerDescription", &printer_description)); + CHECK(printer_dict->GetString("printerManufacturer", &printer_manufacturer)); + CHECK(printer_dict->GetString("printerModel", &printer_model)); + CHECK(printer_dict->GetString("printerAddress", &printer_address)); + CHECK(printer_dict->GetString("printerProtocol", &printer_protocol)); + // printerQueue might be null for a printer whose protocol is not 'LPD'. + printer_dict->GetString("printerQueue", &printer_queue); + + // printerPPDPath might be null for an auto-discovered printer. + printer_dict->GetString("printerPPDPath", &printer_ppd_path); + std::string printer_uri = printer_protocol + "://" + printer_address; + if (!printer_queue.empty()) { + printer_uri += "/" + printer_queue; + } + + std::unique_ptr<Printer> printer = base::MakeUnique<Printer>(printer_id); + printer->set_display_name(printer_name); + printer->set_description(printer_description); + printer->set_manufacturer(printer_manufacturer); + printer->set_model(printer_model); + printer->set_uri(printer_uri); + + // Verify a valid ppd path is present. + if (!printer_ppd_path.empty()) { + RecordPpdSource(kUser); + GURL tmp = net::FilePathToFileURL(base::FilePath(printer_ppd_path)); + if (!tmp.is_valid()) { + LOG(ERROR) << "Invalid ppd path: " << printer_ppd_path; + OnAddPrinterError(); + return; + } + printer->mutable_ppd_reference()->user_supplied_ppd_url = tmp.spec(); + } else if (!printer_manufacturer.empty() && !printer_model.empty()) { + RecordPpdSource(kScs); + // Using the manufacturer and model, get a ppd reference. + if (!ppd_provider_->GetPpdReference(printer_manufacturer, printer_model, + printer->mutable_ppd_reference())) { + LOG(ERROR) << "Failed to get ppd reference"; + OnAddPrinterError(); + return; + } + } + + // Copy the printer for the configurer. Ownership needs to be transfered to + // the receiver of the callback. + const Printer printer_copy = *printer; + printer_configurer_->SetUpPrinter( + printer_copy, + base::Bind(&CupsPrintersHandler::OnAddedPrinter, + weak_factory_.GetWeakPtr(), base::Passed(&printer))); +} + +void CupsPrintersHandler::OnAddedPrinter( + std::unique_ptr<Printer> printer, + chromeos::PrinterSetupResult result_code) { + std::string printer_name = printer->display_name(); + UMA_HISTOGRAM_ENUMERATION("Printing.CUPS.PrinterSetupResult", result_code, + chromeos::PrinterSetupResult::kMaxValue); + switch (result_code) { + case chromeos::PrinterSetupResult::kSuccess: { + UMA_HISTOGRAM_ENUMERATION("Printing.CUPS.PrinterAdded", + printer->GetProtocol(), Printer::kProtocolMax); + auto* manager = PrintersManagerFactory::GetForBrowserContext(profile_); + manager->PrinterInstalled(*printer); + manager->RegisterPrinter(std::move(printer)); + break; + } + case chromeos::PrinterSetupResult::kPpdNotFound: + LOG(WARNING) << "Could not locate requested PPD"; + break; + case chromeos::PrinterSetupResult::kPpdTooLarge: + LOG(WARNING) << "PPD is too large"; + break; + case chromeos::PrinterSetupResult::kPpdUnretrievable: + LOG(WARNING) << "Could not retrieve PPD from server"; + break; + case chromeos::PrinterSetupResult::kInvalidPpd: + LOG(WARNING) << "Provided PPD is invalid."; + break; + case chromeos::PrinterSetupResult::kPrinterUnreachable: + LOG(WARNING) << "Could not contact printer for configuration"; + break; + case chromeos::PrinterSetupResult::kDbusError: + case chromeos::PrinterSetupResult::kFatalError: + LOG(ERROR) << "Unrecoverable error. Reboot required."; + break; + case chromeos::PrinterSetupResult::kMaxValue: + NOTREACHED() << "This is not an expected value"; + break; + } + CallJavascriptFunction( + "cr.webUIListenerCallback", base::Value("on-add-cups-printer"), + base::Value(result_code == chromeos::PrinterSetupResult::kSuccess), + base::Value(printer_name)); +} + +void CupsPrintersHandler::OnAddPrinterError() { + FireWebUIListener("on-add-cups-printer", base::Value(false), base::Value("")); +} + +void CupsPrintersHandler::HandleGetCupsPrinterManufacturers( + const base::ListValue* args) { + AllowJavascript(); + std::string js_callback; + CHECK_EQ(1U, args->GetSize()); + CHECK(args->GetString(0, &js_callback)); + ppd_provider_->ResolveManufacturers( + base::Bind(&CupsPrintersHandler::ResolveManufacturersDone, + weak_factory_.GetWeakPtr(), js_callback)); +} + +void CupsPrintersHandler::HandleGetCupsPrinterModels( + const base::ListValue* args) { + AllowJavascript(); + std::string js_callback; + std::string manufacturer; + CHECK_EQ(2U, args->GetSize()); + CHECK(args->GetString(0, &js_callback)); + CHECK(args->GetString(1, &manufacturer)); + + // Empty manufacturer queries may be triggered as a part of the ui + // initialization, and should just return empty results. + if (manufacturer.empty()) { + base::DictionaryValue response; + response.SetBoolean("success", true); + response.Set("models", base::MakeUnique<base::ListValue>()); + ResolveJavascriptCallback(base::Value(js_callback), response); + return; + } + + ppd_provider_->ResolvePrinters( + manufacturer, base::Bind(&CupsPrintersHandler::ResolvePrintersDone, + weak_factory_.GetWeakPtr(), js_callback)); +} + +void CupsPrintersHandler::HandleSelectPPDFile(const base::ListValue* args) { + CHECK_EQ(1U, args->GetSize()); + CHECK(args->GetString(0, &webui_callback_id_)); + + base::FilePath downloads_path = + DownloadPrefs::FromDownloadManager( + content::BrowserContext::GetDownloadManager(profile_)) + ->DownloadPath(); + + select_file_dialog_ = ui::SelectFileDialog::Create( + this, new ChromeSelectFilePolicy(web_ui()->GetWebContents())); + gfx::NativeWindow owning_window = + chrome::FindBrowserWithWebContents(web_ui()->GetWebContents()) + ->window() + ->GetNativeWindow(); + select_file_dialog_->SelectFile( + ui::SelectFileDialog::SELECT_OPEN_FILE, base::string16(), downloads_path, + nullptr, 0, FILE_PATH_LITERAL(""), owning_window, nullptr); +} + +void CupsPrintersHandler::ResolveManufacturersDone( + const std::string& js_callback, + chromeos::printing::PpdProvider::CallbackResultCode result_code, + const std::vector<std::string>& manufacturers) { + auto manufacturers_value = base::MakeUnique<base::ListValue>(); + if (result_code == chromeos::printing::PpdProvider::SUCCESS) { + manufacturers_value->AppendStrings(manufacturers); + } + base::DictionaryValue response; + response.SetBoolean("success", + result_code == chromeos::printing::PpdProvider::SUCCESS); + response.Set("manufacturers", std::move(manufacturers_value)); + ResolveJavascriptCallback(base::Value(js_callback), response); +} + +void CupsPrintersHandler::ResolvePrintersDone( + const std::string& js_callback, + chromeos::printing::PpdProvider::CallbackResultCode result_code, + const std::vector<std::string>& printers) { + auto printers_value = base::MakeUnique<base::ListValue>(); + if (result_code == chromeos::printing::PpdProvider::SUCCESS) { + printers_value->AppendStrings(printers); + } + base::DictionaryValue response; + response.SetBoolean("success", + result_code == chromeos::printing::PpdProvider::SUCCESS); + response.Set("models", std::move(printers_value)); + ResolveJavascriptCallback(base::Value(js_callback), response); +} + +void CupsPrintersHandler::FileSelected(const base::FilePath& path, + int index, + void* params) { + DCHECK(!webui_callback_id_.empty()); + ResolveJavascriptCallback(base::Value(webui_callback_id_), + base::Value(path.value())); + webui_callback_id_.clear(); +} + +void CupsPrintersHandler::HandleStartDiscovery(const base::ListValue* args) { + if (!printer_discoverer_.get()) { + printer_discoverer_ = + chromeos::PrinterDiscoverer::CreateForProfile(profile_); + } + + printer_discoverer_->AddObserver(this); +} + +void CupsPrintersHandler::HandleStopDiscovery(const base::ListValue* args) { + printer_discoverer_.reset(); +} + +void CupsPrintersHandler::OnPrintersFound( + const std::vector<Printer>& printers) { + std::unique_ptr<base::ListValue> printers_list = + base::MakeUnique<base::ListValue>(); + for (const auto& printer : printers) { + printers_list->Append(GetPrinterInfo(printer)); + } + + FireWebUIListener("on-printer-discovered", *printers_list); +} + +void CupsPrintersHandler::OnDiscoveryInitialScanDone(int printer_count) { + UMA_HISTOGRAM_COUNTS_100("Printing.CUPS.PrintersDiscovered", printer_count); + FireWebUIListener("on-printer-discovery-done"); +} + +} // namespace settings +} // namespace chromeos diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.h b/chromium/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.h new file mode 100644 index 00000000000..343daeab6df --- /dev/null +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.h @@ -0,0 +1,118 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_CUPS_PRINTERS_HANDLER_H_ +#define CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_CUPS_PRINTERS_HANDLER_H_ + +#include <memory> +#include <string> +#include <vector> + +#include "base/files/file_path.h" +#include "base/memory/weak_ptr.h" +#include "chrome/browser/chromeos/printing/printer_configurer.h" +#include "chrome/browser/chromeos/printing/printer_discoverer.h" +#include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h" +#include "chromeos/printing/ppd_provider.h" +#include "chromeos/printing/printer_configuration.h" +#include "ui/shell_dialogs/select_file_dialog.h" + +namespace base { +class ListValue; +} // namespace base + +class Profile; + +namespace chromeos { +namespace printing { +class PpdProvider; +} +namespace settings { + +// Chrome OS CUPS printing settings page UI handler. +class CupsPrintersHandler : public ::settings::SettingsPageUIHandler, + public ui::SelectFileDialog::Listener, + public chromeos::PrinterDiscoverer::Observer { + public: + explicit CupsPrintersHandler(content::WebUI* webui); + ~CupsPrintersHandler() override; + + // SettingsPageUIHandler overrides: + void RegisterMessages() override; + void OnJavascriptAllowed() override {} + void OnJavascriptDisallowed() override {} + + private: + // Gets all CUPS printers and return it to WebUI. + void HandleGetCupsPrintersList(const base::ListValue* args); + void HandleUpdateCupsPrinter(const base::ListValue* args); + void HandleRemoveCupsPrinter(const base::ListValue* args); + + void HandleAddCupsPrinter(const base::ListValue* args); + void OnAddedPrinter(std::unique_ptr<Printer> printer, + chromeos::PrinterSetupResult result); + void OnAddPrinterError(); + + // Get a list of all manufacturers for which we have at least one model of + // printer supported. Takes one argument, the callback id for the result. + // The callback will be invoked with {success: <boolean>, models: + // <Array<string>>}. + void HandleGetCupsPrinterManufacturers(const base::ListValue* args); + + // Given a manufacturer, get a list of all models of printers for which we can + // get drivers. Takes two arguments - the callback id and the manufacturer + // name for which we want to list models. The callback will be called with + // {success: <boolean>, models: Array<string>}. + void HandleGetCupsPrinterModels(const base::ListValue* args); + + void HandleSelectPPDFile(const base::ListValue* args); + + // PpdProvider callback handlers. + void ResolveManufacturersDone( + const std::string& js_callback, + chromeos::printing::PpdProvider::CallbackResultCode result_code, + const std::vector<std::string>& available); + void ResolvePrintersDone( + const std::string& js_callback, + chromeos::printing::PpdProvider::CallbackResultCode result_code, + const std::vector<std::string>& available); + + // ui::SelectFileDialog::Listener override: + void FileSelected(const base::FilePath& path, + int index, + void* params) override; + + void HandleStartDiscovery(const base::ListValue* args); + void HandleStopDiscovery(const base::ListValue* args); + + // chromeos::PrinterDiscoverer::Observer override: + void OnPrintersFound(const std::vector<Printer>& printers) override; + void OnDiscoveryInitialScanDone(int printer_count) override; + + // Invokes debugd to add the printer to CUPS. If |ipp_everywhere| is true, + // automatic configuration will be attempted and |ppd_path| is ignored. + // |ppd_path| is the path to a Postscript Printer Description file that will + // be used to configure the printer capabilities. This file must be in + // Downloads or the PPD Cache. + void AddPrinterToCups(std::unique_ptr<Printer> printer, + const base::FilePath& ppd_path, + bool ipp_everywhere); + + std::unique_ptr<chromeos::PrinterDiscoverer> printer_discoverer_; + scoped_refptr<chromeos::printing::PpdProvider> ppd_provider_; + std::unique_ptr<chromeos::PrinterConfigurer> printer_configurer_; + + Profile* profile_; + scoped_refptr<ui::SelectFileDialog> select_file_dialog_; + std::string webui_callback_id_; + + base::WeakPtrFactory<CupsPrintersHandler> weak_factory_; + + DISALLOW_COPY_AND_ASSIGN(CupsPrintersHandler); +}; + +} // namespace settings +} // namespace chromeos + +#endif // CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_CUPS_PRINTERS_HANDLER_H_ diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/date_time_handler.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/date_time_handler.cc new file mode 100644 index 00000000000..2562de268c0 --- /dev/null +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/date_time_handler.cc @@ -0,0 +1,182 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/webui/settings/chromeos/date_time_handler.h" + +#include "base/bind.h" +#include "base/command_line.h" +#include "base/values.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/chromeos/policy/proto/chrome_device_policy.pb.h" +#include "chrome/browser/chromeos/set_time_dialog.h" +#include "chrome/browser/chromeos/system/timezone_resolver_manager.h" +#include "chrome/browser/chromeos/system/timezone_util.h" +#include "chrome/common/pref_names.h" +#include "chromeos/chromeos_switches.h" +#include "chromeos/dbus/dbus_thread_manager.h" +#include "chromeos/dbus/system_clock_client.h" +#include "chromeos/settings/timezone_settings.h" +#include "components/prefs/pref_service.h" +#include "content/public/browser/web_contents.h" +#include "content/public/browser/web_ui.h" +#include "content/public/browser/web_ui_data_source.h" + +namespace chromeos { +namespace settings { + +namespace { + +// Returns whether the system time zone automatic detection policy is disabled +// by a flag. +bool IsSystemTimezoneAutomaticDetectionPolicyFlagDisabled() { + return base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kDisableSystemTimezoneAutomaticDetectionPolicy); +} + +// Returns whether the system's automatic time zone detection setting is +// managed, which may override the user's setting. +bool IsSystemTimezoneAutomaticDetectionManaged() { + if (IsSystemTimezoneAutomaticDetectionPolicyFlagDisabled()) + return false; + + return g_browser_process->local_state()->IsManagedPreference( + prefs::kSystemTimezoneAutomaticDetectionPolicy); +} + +// Returns the system's automatic time zone detection policy value, which +// corresponds to the SystemTimezoneProto's AutomaticTimezoneDetectionType +// enum and determines whether the user's setting will be overridden. +int GetSystemTimezoneAutomaticDetectionPolicyValue() { + DCHECK(IsSystemTimezoneAutomaticDetectionManaged()); + + return g_browser_process->local_state()->GetInteger( + prefs::kSystemTimezoneAutomaticDetectionPolicy); +} + +// Returns whether the user can set the automatic detection setting, based on +// flags and policies. +bool IsTimezoneAutomaticDetectionUserEditable() { + if (system::HasSystemTimezonePolicy()) + return false; + + if (IsSystemTimezoneAutomaticDetectionManaged()) { + return GetSystemTimezoneAutomaticDetectionPolicyValue() == + enterprise_management::SystemTimezoneProto::USERS_DECIDE; + } + + return true; +} + +} // namespace + +DateTimeHandler::DateTimeHandler() + : scoped_observer_(this), weak_ptr_factory_(this) {} + +DateTimeHandler::~DateTimeHandler() = default; + +DateTimeHandler* DateTimeHandler::Create( + content::WebUIDataSource* html_source) { + // Set the initial time zone to show. + html_source->AddString("timeZoneName", system::GetCurrentTimezoneName()); + html_source->AddString( + "timeZoneID", + system::TimezoneSettings::GetInstance()->GetCurrentTimezoneID()); + + if (!IsTimezoneAutomaticDetectionUserEditable()) { + html_source->AddBoolean("timeZoneAutoDetectValueFromPolicy", + g_browser_process->platform_part() + ->GetTimezoneResolverManager() + ->ShouldApplyResolvedTimezone()); + } + + return new DateTimeHandler; +} + +void DateTimeHandler::RegisterMessages() { + web_ui()->RegisterMessageCallback( + "dateTimePageReady", base::Bind(&DateTimeHandler::HandleDateTimePageReady, + base::Unretained(this))); + web_ui()->RegisterMessageCallback( + "getTimeZones", + base::Bind(&DateTimeHandler::HandleGetTimeZones, base::Unretained(this))); + web_ui()->RegisterMessageCallback( + "showSetDateTimeUI", base::Bind(&DateTimeHandler::HandleShowSetDateTimeUI, + base::Unretained(this))); +} + +void DateTimeHandler::OnJavascriptAllowed() { + SystemClockClient* system_clock_client = + DBusThreadManager::Get()->GetSystemClockClient(); + scoped_observer_.Add(system_clock_client); + SystemClockCanSetTimeChanged(system_clock_client->CanSetTime()); + + // The system time zone policy disables auto-detection entirely. (However, + // the time zone policy does not override the user's time zone itself.) + system_timezone_policy_subscription_ = + CrosSettings::Get()->AddSettingsObserver( + kSystemTimezonePolicy, + base::Bind(&DateTimeHandler::NotifyTimezoneAutomaticDetectionPolicy, + weak_ptr_factory_.GetWeakPtr())); + + if (IsSystemTimezoneAutomaticDetectionPolicyFlagDisabled()) + return; + + // The auto-detection policy can force auto-detection on or off. + local_state_pref_change_registrar_.Init(g_browser_process->local_state()); + local_state_pref_change_registrar_.Add( + prefs::kSystemTimezoneAutomaticDetectionPolicy, + base::Bind(&DateTimeHandler::NotifyTimezoneAutomaticDetectionPolicy, + base::Unretained(this))); +} + +void DateTimeHandler::OnJavascriptDisallowed() { + scoped_observer_.RemoveAll(); + system_timezone_policy_subscription_.reset(); + + if (!IsSystemTimezoneAutomaticDetectionPolicyFlagDisabled()) + local_state_pref_change_registrar_.RemoveAll(); +} + +void DateTimeHandler::HandleDateTimePageReady(const base::ListValue* args) { + AllowJavascript(); + + // Send the time zone automatic detection policy in case it changed after the + // handler was created. + NotifyTimezoneAutomaticDetectionPolicy(); +} + +void DateTimeHandler::HandleGetTimeZones(const base::ListValue* args) { + AllowJavascript(); + + CHECK_EQ(1U, args->GetSize()); + const base::Value* callback_id; + CHECK(args->Get(0, &callback_id)); + ResolveJavascriptCallback(*callback_id, *system::GetTimezoneList().release()); +} + +void DateTimeHandler::HandleShowSetDateTimeUI(const base::ListValue* args) { + // Make sure the clock status hasn't changed since the button was clicked. + if (!DBusThreadManager::Get()->GetSystemClockClient()->CanSetTime()) + return; + SetTimeDialog::ShowDialogInParent( + web_ui()->GetWebContents()->GetTopLevelNativeWindow()); +} + +void DateTimeHandler::NotifyTimezoneAutomaticDetectionPolicy() { + bool managed = !IsTimezoneAutomaticDetectionUserEditable(); + bool force_enabled = managed && + g_browser_process->platform_part() + ->GetTimezoneResolverManager() + ->ShouldApplyResolvedTimezone(); + + FireWebUIListener("time-zone-auto-detect-policy", base::Value(managed), + base::Value(force_enabled)); +} + +void DateTimeHandler::SystemClockCanSetTimeChanged(bool can_set_time) { + FireWebUIListener("can-set-date-time-changed", base::Value(can_set_time)); +} + +} // namespace settings +} // namespace chromeos diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/date_time_handler.h b/chromium/chrome/browser/ui/webui/settings/chromeos/date_time_handler.h new file mode 100644 index 00000000000..b04142f82f7 --- /dev/null +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/date_time_handler.h @@ -0,0 +1,78 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_DATE_TIME_HANDLER_H_ +#define CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_DATE_TIME_HANDLER_H_ + +#include <memory> + +#include "base/macros.h" +#include "base/memory/weak_ptr.h" +#include "base/scoped_observer.h" +#include "chrome/browser/chromeos/settings/cros_settings.h" +#include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h" +#include "chromeos/dbus/system_clock_client.h" +#include "components/prefs/pref_change_registrar.h" + +namespace base { +class ListValue; +} + +namespace content { +class WebUIDataSource; +} + +namespace chromeos { +namespace settings { + +// Chrome OS date and time settings page UI handler. +class DateTimeHandler : public ::settings::SettingsPageUIHandler, + public SystemClockClient::Observer { + public: + ~DateTimeHandler() override; + + // Adds load-time values to html_source before creating the handler. + static DateTimeHandler* Create(content::WebUIDataSource* html_source); + + // SettingsPageUIHandler implementation. + void RegisterMessages() override; + void OnJavascriptAllowed() override; + void OnJavascriptDisallowed() override; + + private: + DateTimeHandler(); + + // SystemClockClient::Observer implementation. + void SystemClockCanSetTimeChanged(bool can_set_time) override; + + // Called when the page is ready. + void HandleDateTimePageReady(const base::ListValue* args); + + // Handler to fetch the list of time zones. + void HandleGetTimeZones(const base::ListValue* args); + + // Called to show the Set Time UI. + void HandleShowSetDateTimeUI(const base::ListValue* args); + + // Updates the UI, enabling or disabling the time zone automatic detection + // setting according to policy. + void NotifyTimezoneAutomaticDetectionPolicy(); + + std::unique_ptr<chromeos::CrosSettings::ObserverSubscription> + system_timezone_policy_subscription_; + + // Used to listen to changes to the system time zone detection policy. + PrefChangeRegistrar local_state_pref_change_registrar_; + + ScopedObserver<SystemClockClient, SystemClockClient::Observer> + scoped_observer_; + base::WeakPtrFactory<DateTimeHandler> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(DateTimeHandler); +}; + +} // namespace settings +} // namespace chromeos + +#endif // CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_DATE_TIME_HANDLER_H_ diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/device_keyboard_handler.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/device_keyboard_handler.cc new file mode 100644 index 00000000000..dbd70059915 --- /dev/null +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/device_keyboard_handler.cc @@ -0,0 +1,82 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/webui/settings/chromeos/device_keyboard_handler.h" + +#include "ash/new_window_controller.h" +#include "ash/shell.h" +#include "base/bind.h" +#include "base/command_line.h" +#include "base/values.h" +#include "chrome/browser/profiles/profile.h" +#include "chromeos/chromeos_switches.h" +#include "content/public/browser/web_ui.h" +#include "ui/events/devices/input_device_manager.h" + +namespace { + +bool HasExternalKeyboard() { + for (const ui::InputDevice& keyboard : + ui::InputDeviceManager::GetInstance()->GetKeyboardDevices()) { + if (keyboard.type == ui::InputDeviceType::INPUT_DEVICE_EXTERNAL) + return true; + } + + return false; +} + +} // namespace + +namespace chromeos { +namespace settings { + +KeyboardHandler::KeyboardHandler(content::WebUI* webui) + : profile_(Profile::FromWebUI(webui)), observer_(this) {} + +KeyboardHandler::~KeyboardHandler() { +} + +void KeyboardHandler::RegisterMessages() { + web_ui()->RegisterMessageCallback( + "initializeKeyboardSettings", + base::Bind(&KeyboardHandler::HandleInitialize, + base::Unretained(this))); + web_ui()->RegisterMessageCallback( + "showKeyboardShortcutsOverlay", + base::Bind(&KeyboardHandler::HandleShowKeyboardShortcutsOverlay, + base::Unretained(this))); +} + +void KeyboardHandler::OnJavascriptAllowed() { + observer_.Add(ui::InputDeviceManager::GetInstance()); +} + +void KeyboardHandler::OnJavascriptDisallowed() { + observer_.RemoveAll(); +} + +void KeyboardHandler::OnKeyboardDeviceConfigurationChanged() { + UpdateShowKeys(); +} + +void KeyboardHandler::HandleInitialize(const base::ListValue* args) { + AllowJavascript(); + UpdateShowKeys(); +} + +void KeyboardHandler::HandleShowKeyboardShortcutsOverlay( + const base::ListValue* args) const { + ash::Shell::Get()->new_window_controller()->ShowKeyboardOverlay(); +} + +void KeyboardHandler::UpdateShowKeys() { + const base::Value has_caps_lock(HasExternalKeyboard()); + const base::Value has_diamond_key( + base::CommandLine::ForCurrentProcess()->HasSwitch( + chromeos::switches::kHasChromeOSDiamondKey)); + FireWebUIListener("show-keys-changed", has_caps_lock, has_diamond_key); +} + +} // namespace settings +} // namespace chromeos diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/device_keyboard_handler.h b/chromium/chrome/browser/ui/webui/settings/chromeos/device_keyboard_handler.h new file mode 100644 index 00000000000..7ac9d447d48 --- /dev/null +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/device_keyboard_handler.h @@ -0,0 +1,67 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_DEVICE_KEYBOARD_HANDLER_H_ +#define CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_DEVICE_KEYBOARD_HANDLER_H_ + +#include "base/macros.h" +#include "base/scoped_observer.h" +#include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h" +#include "ui/events/devices/input_device_event_observer.h" + +namespace base { +class ListValue; +} + +namespace content { +class WebUI; +} + +namespace ui { +class InputDeviceManager; +} + +class Profile; + +namespace chromeos { +namespace settings { + +// Chrome OS "Keyboard" settings page UI handler. +class KeyboardHandler + : public ::settings::SettingsPageUIHandler, + public ui::InputDeviceEventObserver { + public: + explicit KeyboardHandler(content::WebUI* webui); + ~KeyboardHandler() override; + + // SettingsPageUIHandler implementation. + void RegisterMessages() override; + void OnJavascriptAllowed() override; + void OnJavascriptDisallowed() override; + + // ui::InputDeviceEventObserver implementation. + void OnKeyboardDeviceConfigurationChanged() override; + + private: + // Initializes the page with the current keyboard information. + void HandleInitialize(const base::ListValue* args); + + // Shows the Ash keyboard shortcuts overlay. + void HandleShowKeyboardShortcutsOverlay(const base::ListValue* args) const; + + // Shows or hides the Caps Lock and Diamond key settings based on whether the + // system status. + void UpdateShowKeys(); + + Profile* profile_; // Weak pointer. + + ScopedObserver<ui::InputDeviceManager, KeyboardHandler> observer_; + + DISALLOW_COPY_AND_ASSIGN(KeyboardHandler); +}; + +} // namespace settings +} // namespace chromeos + +#endif // CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_DEVICE_KEYBOARD_HANDLER_H_ diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/device_pointer_handler.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/device_pointer_handler.cc new file mode 100644 index 00000000000..061dad6d182 --- /dev/null +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/device_pointer_handler.cc @@ -0,0 +1,51 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/webui/settings/chromeos/device_pointer_handler.h" + +#include "base/bind.h" +#include "base/values.h" +#include "content/public/browser/web_ui.h" + +namespace chromeos { +namespace settings { + +PointerHandler::PointerHandler() {} + +PointerHandler::~PointerHandler() {} + +void PointerHandler::RegisterMessages() { + web_ui()->RegisterMessageCallback( + "initializePointerSettings", + base::Bind(&PointerHandler::HandleInitialize, base::Unretained(this))); +} + +void PointerHandler::OnJavascriptAllowed() { + if (!pointer_device_observer_) { + pointer_device_observer_.reset(new system::PointerDeviceObserver()); + pointer_device_observer_->Init(); + } + + pointer_device_observer_->AddObserver(this); + pointer_device_observer_->CheckDevices(); +} + +void PointerHandler::OnJavascriptDisallowed() { + pointer_device_observer_->RemoveObserver(this); +} + +void PointerHandler::TouchpadExists(bool exists) { + FireWebUIListener("has-touchpad-changed", base::Value(exists)); +} + +void PointerHandler::MouseExists(bool exists) { + FireWebUIListener("has-mouse-changed", base::Value(exists)); +} + +void PointerHandler::HandleInitialize(const base::ListValue* args) { + AllowJavascript(); +} + +} // namespace settings +} // namespace chromeos diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/device_pointer_handler.h b/chromium/chrome/browser/ui/webui/settings/chromeos/device_pointer_handler.h new file mode 100644 index 00000000000..25f54393c73 --- /dev/null +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/device_pointer_handler.h @@ -0,0 +1,51 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_DEVICE_POINTER_HANDLER_H_ +#define CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_DEVICE_POINTER_HANDLER_H_ + +#include <memory> + +#include "base/macros.h" +#include "chrome/browser/chromeos/system/pointer_device_observer.h" +#include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h" + +namespace base { +class ListValue; +} + +namespace chromeos { +namespace settings { + +// Chrome OS "Mouse and touchpad" settings page UI handler. +class PointerHandler + : public ::settings::SettingsPageUIHandler, + public chromeos::system::PointerDeviceObserver::Observer { + public: + PointerHandler(); + ~PointerHandler() override; + + // SettingsPageUIHandler implementation. + void RegisterMessages() override; + void OnJavascriptAllowed() override; + void OnJavascriptDisallowed() override; + + private: + // PointerDeviceObserver implementation. + void TouchpadExists(bool exists) override; + void MouseExists(bool exists) override; + + // Initializes the page with the current pointer information. + void HandleInitialize(const base::ListValue* args); + + std::unique_ptr<chromeos::system::PointerDeviceObserver> + pointer_device_observer_; + + DISALLOW_COPY_AND_ASSIGN(PointerHandler); +}; + +} // namespace settings +} // namespace chromeos + +#endif // CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_DEVICE_POINTER_HANDLER_H_ diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/device_power_handler.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/device_power_handler.cc new file mode 100644 index 00000000000..535e9418eeb --- /dev/null +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/device_power_handler.cc @@ -0,0 +1,138 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/webui/settings/chromeos/device_power_handler.h" + +#include <memory> +#include <utility> + +#include "ash/resources/grit/ash_resources.h" +#include "base/bind.h" +#include "base/bind_helpers.h" +#include "base/strings/string_number_conversions.h" +#include "base/strings/utf_string_conversions.h" +#include "base/values.h" +#include "chrome/grit/generated_resources.h" +#include "content/public/browser/web_ui.h" +#include "ui/base/l10n/l10n_util.h" +#include "ui/base/l10n/time_format.h" +#include "ui/base/webui/web_ui_util.h" + +namespace chromeos { +namespace settings { +namespace { + +base::string16 GetBatteryTimeText(base::TimeDelta time_left) { + int hour = 0; + int min = 0; + ash::PowerStatus::SplitTimeIntoHoursAndMinutes(time_left, &hour, &min); + + base::string16 time_text; + if (hour == 0 || min == 0) { + // Display only one unit ("2 hours" or "10 minutes"). + return ui::TimeFormat::Simple(ui::TimeFormat::FORMAT_DURATION, + ui::TimeFormat::LENGTH_LONG, time_left); + } + + return ui::TimeFormat::Detailed(ui::TimeFormat::FORMAT_DURATION, + ui::TimeFormat::LENGTH_LONG, + -1, // force hour and minute output + time_left); +} + +} // namespace + +PowerHandler::PowerHandler() + : power_observer_(this) { + power_status_ = ash::PowerStatus::Get(); +} + +PowerHandler::~PowerHandler() {} + +void PowerHandler::RegisterMessages() { + web_ui()->RegisterMessageCallback( + "updatePowerStatus", base::Bind(&PowerHandler::HandleUpdatePowerStatus, + base::Unretained(this))); + web_ui()->RegisterMessageCallback( + "setPowerSource", + base::Bind(&PowerHandler::HandleSetPowerSource, base::Unretained(this))); +} + +void PowerHandler::OnJavascriptAllowed() { + power_observer_.Add(power_status_); +} + +void PowerHandler::OnJavascriptDisallowed() { + power_observer_.RemoveAll(); +} + +void PowerHandler::OnPowerStatusChanged() { + SendBatteryStatus(); + SendPowerSources(); +} + +void PowerHandler::HandleUpdatePowerStatus(const base::ListValue* args) { + AllowJavascript(); + power_status_->RequestStatusUpdate(); +} + +void PowerHandler::HandleSetPowerSource(const base::ListValue* args) { + AllowJavascript(); + + std::string id; + CHECK(args->GetString(0, &id)); + power_status_->SetPowerSource(id); +} + +void PowerHandler::SendBatteryStatus() { + bool charging = power_status_->IsBatteryCharging(); + bool calculating = power_status_->IsBatteryTimeBeingCalculated(); + int percent = power_status_->GetRoundedBatteryPercent(); + base::TimeDelta time_left; + bool show_time = false; + + if (!calculating) { + time_left = charging ? power_status_->GetBatteryTimeToFull() + : power_status_->GetBatteryTimeToEmpty(); + show_time = ash::PowerStatus::ShouldDisplayBatteryTime(time_left); + } + + base::string16 status_text; + if (show_time) { + status_text = l10n_util::GetStringFUTF16( + charging ? IDS_OPTIONS_BATTERY_STATUS_CHARGING + : IDS_OPTIONS_BATTERY_STATUS, + base::IntToString16(percent), GetBatteryTimeText(time_left)); + } else { + status_text = l10n_util::GetStringFUTF16(IDS_OPTIONS_BATTERY_STATUS_SHORT, + base::IntToString16(percent)); + } + + base::DictionaryValue battery_dict; + battery_dict.SetBoolean("charging", charging); + battery_dict.SetBoolean("calculating", calculating); + battery_dict.SetInteger("percent", percent); + battery_dict.SetString("statusText", status_text); + + FireWebUIListener("battery-status-changed", battery_dict); +} + +void PowerHandler::SendPowerSources() { + base::ListValue sources_list; + for (const auto& source : power_status_->GetPowerSources()) { + std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue()); + dict->SetString("id", source.id); + dict->SetInteger("type", source.type); + dict->SetString("description", + l10n_util::GetStringUTF16(source.description_id)); + sources_list.Append(std::move(dict)); + } + + FireWebUIListener("power-sources-changed", sources_list, + base::Value(power_status_->GetCurrentPowerSourceID()), + base::Value(power_status_->IsUsbChargerConnected())); +} + +} // namespace settings +} // namespace chromeos diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/device_power_handler.h b/chromium/chrome/browser/ui/webui/settings/chromeos/device_power_handler.h new file mode 100644 index 00000000000..eaaf0cc9a58 --- /dev/null +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/device_power_handler.h @@ -0,0 +1,59 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_DEVICE_POWER_HANDLER_H_ +#define CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_DEVICE_POWER_HANDLER_H_ + +#include "ash/system/power/power_status.h" +#include "base/macros.h" +#include "base/scoped_observer.h" +#include "base/strings/string16.h" +#include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h" + +namespace base { +class ListValue; +} + +namespace chromeos { +namespace settings { + +// Chrome OS battery status and power settings handler. +class PowerHandler : public ::settings::SettingsPageUIHandler, + public ash::PowerStatus::Observer { + public: + PowerHandler(); + ~PowerHandler() override; + + // SettingsPageUIHandler implementation. + void RegisterMessages() override; + void OnJavascriptAllowed() override; + void OnJavascriptDisallowed() override; + + // ash::PowerStatus::Observer implementation. + void OnPowerStatusChanged() override; + + private: + // Handler to request updating the power status. + void HandleUpdatePowerStatus(const base::ListValue* args); + + // Handler to change the power source. + void HandleSetPowerSource(const base::ListValue* args); + + // Updates the UI with the current battery status. + void SendBatteryStatus(); + + // Updates the UI with a list of available dual-role power sources. + void SendPowerSources(); + + ash::PowerStatus* power_status_; + + ScopedObserver<ash::PowerStatus, PowerHandler> power_observer_; + + DISALLOW_COPY_AND_ASSIGN(PowerHandler); +}; + +} // namespace settings +} // namespace chromeos + +#endif // CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_DEVICE_POWER_HANDLER_H_ diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/device_storage_handler.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/device_storage_handler.cc new file mode 100644 index 00000000000..5b59c57ccdb --- /dev/null +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/device_storage_handler.cc @@ -0,0 +1,370 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/webui/settings/chromeos/device_storage_handler.h" + +#include <algorithm> +#include <numeric> +#include <string> + +#include "base/files/file_util.h" +#include "base/sys_info.h" +#include "base/task_scheduler/post_task.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/browsing_data/browsing_data_appcache_helper.h" +#include "chrome/browser/browsing_data/browsing_data_cache_storage_helper.h" +#include "chrome/browser/browsing_data/browsing_data_channel_id_helper.h" +#include "chrome/browser/browsing_data/browsing_data_cookie_helper.h" +#include "chrome/browser/browsing_data/browsing_data_database_helper.h" +#include "chrome/browser/browsing_data/browsing_data_file_system_helper.h" +#include "chrome/browser/browsing_data/browsing_data_flash_lso_helper.h" +#include "chrome/browser/browsing_data/browsing_data_indexed_db_helper.h" +#include "chrome/browser/browsing_data/browsing_data_local_storage_helper.h" +#include "chrome/browser/browsing_data/browsing_data_service_worker_helper.h" +#include "chrome/browser/chromeos/arc/arc_util.h" +#include "chrome/browser/chromeos/drive/file_system_util.h" +#include "chrome/browser/chromeos/file_manager/path_util.h" +#include "chrome/browser/platform_util.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/grit/generated_resources.h" +#include "chromeos/cryptohome/homedir_methods.h" +#include "components/arc/arc_util.h" +#include "components/browsing_data/content/conditional_cache_counting_helper.h" +#include "components/drive/chromeos/file_system_interface.h" +#include "components/user_manager/user_manager.h" +#include "content/public/browser/browser_context.h" +#include "content/public/browser/storage_partition.h" +#include "ui/base/l10n/l10n_util.h" +#include "ui/base/text/bytes_formatting.h" + +namespace chromeos { +namespace settings { +namespace { + +void GetSizeStatBlocking(const base::FilePath& mount_path, + int64_t* total_size, + int64_t* available_size) { + int64_t size = base::SysInfo::AmountOfTotalDiskSpace(mount_path); + if (size >= 0) + *total_size = size; + size = base::SysInfo::AmountOfFreeDiskSpace(mount_path); + if (size >= 0) + *available_size = size; +} + +// Threshold to show a message indicating space is critically low (512 MB). +const int64_t kSpaceCriticallyLowBytes = 512 * 1024 * 1024; + +// Threshold to show a message indicating space is low (1 GB). +const int64_t kSpaceLowBytes = 1 * 1024 * 1024 * 1024; + +} // namespace + +StorageHandler::StorageHandler() + : browser_cache_size_(-1), + has_browser_cache_size_(false), + browser_site_data_size_(-1), + has_browser_site_data_size_(false), + updating_downloads_size_(false), + updating_drive_cache_size_(false), + updating_browsing_data_size_(false), + updating_android_size_(false), + updating_other_users_size_(false), + weak_ptr_factory_(this) {} + +StorageHandler::~StorageHandler() { +} + +void StorageHandler::RegisterMessages() { + DCHECK(web_ui()); + + web_ui()->RegisterMessageCallback( + "updateStorageInfo", + base::Bind(&StorageHandler::HandleUpdateStorageInfo, + base::Unretained(this))); + web_ui()->RegisterMessageCallback( + "openDownloads", + base::Bind(&StorageHandler::HandleOpenDownloads, + base::Unretained(this))); + web_ui()->RegisterMessageCallback( + "openArcStorage", + base::Bind(&StorageHandler::HandleOpenArcStorage, + base::Unretained(this))); + web_ui()->RegisterMessageCallback( + "clearDriveCache", + base::Bind(&StorageHandler::HandleClearDriveCache, + base::Unretained(this))); +} + +void StorageHandler::HandleUpdateStorageInfo(const base::ListValue* args) { + AllowJavascript(); + + UpdateSizeStat(); + UpdateDownloadsSize(); + UpdateDriveCacheSize(); + UpdateBrowsingDataSize(); + UpdateOtherUsersSize(); + UpdateAndroidSize(); +} + +void StorageHandler::HandleOpenDownloads( + const base::ListValue* unused_args) { + Profile* const profile = Profile::FromWebUI(web_ui()); + const base::FilePath downloads_path = + file_manager::util::GetDownloadsFolderForProfile(profile); + platform_util::OpenItem( + profile, + downloads_path, + platform_util::OPEN_FOLDER, + platform_util::OpenOperationCallback()); +} + +void StorageHandler::HandleOpenArcStorage( + const base::ListValue* unused_args) { + arc::ArcStorageManager::Get()->OpenPrivateVolumeSettings(); +} + +void StorageHandler::HandleClearDriveCache( + const base::ListValue* unused_args) { + drive::FileSystemInterface* const file_system = + drive::util::GetFileSystemByProfile(Profile::FromWebUI(web_ui())); + file_system->FreeDiskSpaceIfNeededFor( + std::numeric_limits<int64_t>::max(), // Removes as much as possible. + base::Bind(&StorageHandler::OnClearDriveCacheDone, + weak_ptr_factory_.GetWeakPtr())); +} + +void StorageHandler::UpdateSizeStat() { + Profile* const profile = Profile::FromWebUI(web_ui()); + const base::FilePath downloads_path = + file_manager::util::GetDownloadsFolderForProfile(profile); + + int64_t* total_size = new int64_t(0); + int64_t* available_size = new int64_t(0); + base::PostTaskWithTraitsAndReply( + FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE}, + base::Bind(&GetSizeStatBlocking, downloads_path, total_size, + available_size), + base::Bind(&StorageHandler::OnGetSizeStat, weak_ptr_factory_.GetWeakPtr(), + base::Owned(total_size), base::Owned(available_size))); +} + +void StorageHandler::OnGetSizeStat(int64_t* total_size, + int64_t* available_size) { + int64_t used_size = *total_size - *available_size; + base::DictionaryValue size_stat; + size_stat.SetString("totalSize", ui::FormatBytes(*total_size)); + size_stat.SetString("availableSize", ui::FormatBytes(*available_size)); + size_stat.SetString("usedSize", ui::FormatBytes(used_size)); + size_stat.SetDouble("usedRatio", + static_cast<double>(used_size) / *total_size); + int storage_space_state = STORAGE_SPACE_NORMAL; + if (*available_size < kSpaceCriticallyLowBytes) + storage_space_state = STORAGE_SPACE_CRITICALLY_LOW; + else if (*available_size < kSpaceLowBytes) + storage_space_state = STORAGE_SPACE_LOW; + size_stat.SetInteger("spaceState", storage_space_state); + + FireWebUIListener("storage-size-stat-changed", size_stat); +} + +void StorageHandler::UpdateDownloadsSize() { + if (updating_downloads_size_) + return; + updating_downloads_size_ = true; + + Profile* const profile = Profile::FromWebUI(web_ui()); + const base::FilePath downloads_path = + file_manager::util::GetDownloadsFolderForProfile(profile); + + base::PostTaskWithTraitsAndReplyWithResult( + FROM_HERE, {base::MayBlock(), base::TaskPriority::BACKGROUND}, + base::Bind(&base::ComputeDirectorySize, downloads_path), + base::Bind(&StorageHandler::OnGetDownloadsSize, + weak_ptr_factory_.GetWeakPtr())); +} + +void StorageHandler::OnGetDownloadsSize(int64_t size) { + updating_downloads_size_ = false; + FireWebUIListener("storage-downloads-size-changed", + base::Value(ui::FormatBytes(size))); +} + +void StorageHandler::UpdateDriveCacheSize() { + if (updating_drive_cache_size_) + return; + + drive::FileSystemInterface* const file_system = + drive::util::GetFileSystemByProfile(Profile::FromWebUI(web_ui())); + if (!file_system) + return; + + // Shows the item "Offline cache" and start calculating size. + FireWebUIListener("storage-drive-enabled-changed", base::Value(true)); + updating_drive_cache_size_ = true; + file_system->CalculateCacheSize(base::Bind( + &StorageHandler::OnGetDriveCacheSize, weak_ptr_factory_.GetWeakPtr())); +} + +void StorageHandler::OnGetDriveCacheSize(int64_t size) { + updating_drive_cache_size_ = false; + FireWebUIListener("storage-drive-cache-size-changed", + base::Value(ui::FormatBytes(size)), base::Value(size > 0)); +} + +void StorageHandler::UpdateBrowsingDataSize() { + if (updating_browsing_data_size_) + return; + updating_browsing_data_size_ = true; + + has_browser_cache_size_ = false; + has_browser_site_data_size_ = false; + Profile* const profile = Profile::FromWebUI(web_ui()); + // Fetch the size of http cache in browsing data. + // ConditionalCacheCountingHelper deletes itself when it is done. + browsing_data::ConditionalCacheCountingHelper::CreateForRange( + content::BrowserContext::GetDefaultStoragePartition(profile), + base::Time(), base::Time::Max()) + ->CountAndDestroySelfWhenFinished(base::Bind( + &StorageHandler::OnGetCacheSize, weak_ptr_factory_.GetWeakPtr())); + + // Fetch the size of site data in browsing data. + if (!site_data_size_collector_.get()) { + content::StoragePartition* storage_partition = + content::BrowserContext::GetDefaultStoragePartition(profile); + site_data_size_collector_.reset(new SiteDataSizeCollector( + storage_partition->GetPath(), + new BrowsingDataCookieHelper(profile->GetRequestContext()), + new BrowsingDataDatabaseHelper(profile), + new BrowsingDataLocalStorageHelper(profile), + new BrowsingDataAppCacheHelper(profile), + new BrowsingDataIndexedDBHelper( + storage_partition->GetIndexedDBContext()), + BrowsingDataFileSystemHelper::Create( + storage_partition->GetFileSystemContext()), + BrowsingDataChannelIDHelper::Create(profile->GetRequestContext()), + new BrowsingDataServiceWorkerHelper( + storage_partition->GetServiceWorkerContext()), + new BrowsingDataCacheStorageHelper( + storage_partition->GetCacheStorageContext()), + BrowsingDataFlashLSOHelper::Create(profile))); + } + site_data_size_collector_->Fetch( + base::Bind(&StorageHandler::OnGetBrowsingDataSize, + weak_ptr_factory_.GetWeakPtr(), true)); +} + +void StorageHandler::OnGetCacheSize(bool is_upper_limit, int64_t size) { + DCHECK(!is_upper_limit); + OnGetBrowsingDataSize(false, size); +} + +void StorageHandler::OnGetBrowsingDataSize(bool is_site_data, int64_t size) { + if (is_site_data) { + has_browser_site_data_size_ = true; + browser_site_data_size_ = size; + } else { + has_browser_cache_size_ = true; + browser_cache_size_ = size; + } + if (has_browser_cache_size_ && has_browser_site_data_size_) { + base::string16 size_string; + if (browser_cache_size_ >= 0 && browser_site_data_size_ >= 0) { + size_string = ui::FormatBytes( + browser_site_data_size_ + browser_cache_size_); + } else { + size_string = l10n_util::GetStringUTF16( + IDS_OPTIONS_SETTINGS_STORAGE_SIZE_UNKNOWN); + } + updating_browsing_data_size_ = false; + FireWebUIListener("storage-browsing-data-size-changed", + base::Value(size_string)); + } +} + +void StorageHandler::UpdateOtherUsersSize() { + if (updating_other_users_size_) + return; + updating_other_users_size_ = true; + + other_users_.clear(); + user_sizes_.clear(); + const user_manager::UserList& users = + user_manager::UserManager::Get()->GetUsers(); + for (auto* user : users) { + if (user->is_active()) + continue; + other_users_.push_back(user); + cryptohome::HomedirMethods::GetInstance()->GetAccountDiskUsage( + cryptohome::Identification(user->GetAccountId()), + base::Bind(&StorageHandler::OnGetOtherUserSize, + weak_ptr_factory_.GetWeakPtr())); + } + // We should show "0 B" if there is no other user. + if (other_users_.empty()) { + updating_other_users_size_ = false; + FireWebUIListener("storage-other-users-size-changed", + base::Value(ui::FormatBytes(0))); + } +} + +void StorageHandler::OnGetOtherUserSize(bool success, int64_t size) { + user_sizes_.push_back(success ? size : -1); + if (user_sizes_.size() == other_users_.size()) { + base::string16 size_string; + // If all the requests succeed, shows the total bytes in the UI. + if (std::count(user_sizes_.begin(), user_sizes_.end(), -1) == 0) { + size_string = ui::FormatBytes( + std::accumulate(user_sizes_.begin(), user_sizes_.end(), 0LL)); + } else { + size_string = l10n_util::GetStringUTF16( + IDS_OPTIONS_SETTINGS_STORAGE_SIZE_UNKNOWN); + } + updating_other_users_size_ = false; + FireWebUIListener("storage-other-users-size-changed", + base::Value(size_string)); + } +} + +void StorageHandler::UpdateAndroidSize() { + if (updating_android_size_) + return; + updating_android_size_ = true; + + Profile* const profile = Profile::FromWebUI(web_ui()); + if (!arc::IsArcPlayStoreEnabledForProfile(profile) || + arc::IsArcOptInVerificationDisabled()) { + return; + } + + // Shows the item "Android apps and cache" and start calculating size. + FireWebUIListener("storage-android-enabled-changed", base::Value(true)); + bool success = arc::ArcStorageManager::Get()->GetApplicationsSize(base::Bind( + &StorageHandler::OnGetAndroidSize, weak_ptr_factory_.GetWeakPtr())); + if (!success) + updating_android_size_ = false; +} + +void StorageHandler::OnGetAndroidSize(bool succeeded, + arc::mojom::ApplicationsSizePtr size) { + base::string16 size_string; + if (succeeded) { + uint64_t total_bytes = size->total_code_bytes + + size->total_data_bytes + + size->total_cache_bytes; + size_string = ui::FormatBytes(total_bytes); + } else { + size_string = l10n_util::GetStringUTF16( + IDS_OPTIONS_SETTINGS_STORAGE_SIZE_UNKNOWN); + } + updating_android_size_ = false; + FireWebUIListener("storage-android-size-changed", base::Value(size_string)); +} + +void StorageHandler::OnClearDriveCacheDone(bool success) { + UpdateDriveCacheSize(); +} + +} // namespace settings +} // namespace chromeos diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/device_storage_handler.h b/chromium/chrome/browser/ui/webui/settings/chromeos/device_storage_handler.h new file mode 100644 index 00000000000..9da1d5d437b --- /dev/null +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/device_storage_handler.h @@ -0,0 +1,127 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_DEVICE_STORAGE_HANDLER_H_ +#define CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_DEVICE_STORAGE_HANDLER_H_ + +#include <stdint.h> + +#include <memory> +#include <vector> + +#include "base/macros.h" +#include "base/memory/weak_ptr.h" +#include "chrome/browser/browsing_data/site_data_size_collector.h" +#include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h" +#include "components/arc/storage_manager/arc_storage_manager.h" +#include "components/user_manager/user.h" + +namespace chromeos { +namespace settings { + +class StorageHandler : public ::settings::SettingsPageUIHandler { + public: + // Enumeration for device state about remaining space. These values must be + // kept in sync with settings.StorageSpaceState in JS code. + enum StorageSpaceState { + STORAGE_SPACE_NORMAL = 0, + STORAGE_SPACE_LOW = 1, + STORAGE_SPACE_CRITICALLY_LOW = 2, + }; + + StorageHandler(); + ~StorageHandler() override; + + // SettingsPageUIHandler implementation. + void RegisterMessages() override; + void OnJavascriptAllowed() override {} + void OnJavascriptDisallowed() override {} + + private: + // Handlers of JS messages. + void HandleUpdateStorageInfo(const base::ListValue* unused_args); + void HandleOpenDownloads(const base::ListValue* unused_args); + void HandleOpenArcStorage(const base::ListValue* unused_args); + void HandleClearDriveCache(const base::ListValue* unused_args); + + // Requests updating disk space information. + void UpdateSizeStat(); + + // Callback to update the UI about disk space information. + void OnGetSizeStat(int64_t* total_size, int64_t* available_size); + + // Requests updating the size of Downloads directory. + void UpdateDownloadsSize(); + + // Callback to update the UI about the size of Downloads directory. + void OnGetDownloadsSize(int64_t size); + + // Requests updating the size of Drive Cache. + void UpdateDriveCacheSize(); + + // Callback to update the UI about the size of Drive Cache. + void OnGetDriveCacheSize(int64_t size); + + // Requests updating the size of browsing data. + void UpdateBrowsingDataSize(); + + // Callback to receive the cache size. + void OnGetCacheSize(bool is_upper_limit, int64_t size); + + // Callback to update the UI about the size of browsing data. + void OnGetBrowsingDataSize(bool is_site_data, int64_t size); + + // Requests updating the total size of other users' data. + void UpdateOtherUsersSize(); + + // Callback to save the fetched user sizes and update the UI. + void OnGetOtherUserSize(bool success, int64_t size); + + // Requests updating the space size used by Android apps and cache. + void UpdateAndroidSize(); + + // Callback to update the UI about Android apps and cache. + void OnGetAndroidSize(bool succeeded, arc::mojom::ApplicationsSizePtr size); + + // Callback called when clearing Drive cache is done. + void OnClearDriveCacheDone(bool success); + + // Total size of cache data in browsing data. + int64_t browser_cache_size_; + + // True if we have already received the size of http cache. + bool has_browser_cache_size_; + + // Total size of site data in browsing data. + int64_t browser_site_data_size_; + + // True if we have already received the size of site data. + bool has_browser_site_data_size_; + + // The list of other users whose directory sizes will be accumulated as the + // size of "Other users". + user_manager::UserList other_users_; + + // Fetched sizes of user directories. + std::vector<int64_t> user_sizes_; + + // Helper to compute the total size of all types of site date. + std::unique_ptr<SiteDataSizeCollector> site_data_size_collector_; + + // Flags indicating fetch operations for storage sizes are ongoing. + bool updating_downloads_size_; + bool updating_drive_cache_size_; + bool updating_browsing_data_size_; + bool updating_android_size_; + bool updating_other_users_size_; + + base::WeakPtrFactory<StorageHandler> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(StorageHandler); +}; + +} // namespace settings +} // namespace chromeos + +#endif // CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_DEVICE_STORAGE_HANDLER_H_ diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/device_stylus_handler.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/device_stylus_handler.cc new file mode 100644 index 00000000000..7f7ba9c3b47 --- /dev/null +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/device_stylus_handler.cc @@ -0,0 +1,143 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/webui/settings/chromeos/device_stylus_handler.h" + +#include <string> +#include <utility> +#include <vector> + +#include "ash/system/palette/palette_utils.h" +#include "base/bind.h" +#include "chrome/browser/chromeos/arc/arc_util.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/app_list/arc/arc_app_utils.h" +#include "ui/events/devices/input_device_manager.h" + +namespace chromeos { +namespace settings { + +namespace { + +// Keys in objects passed to onNoteTakingAppsUpdated. +constexpr char kAppNameKey[] = "name"; +constexpr char kAppIdKey[] = "value"; +constexpr char kAppPreferredKey[] = "preferred"; +constexpr char kAppLockScreenSupportKey[] = "supportsLockScreen"; + +} // namespace + +StylusHandler::StylusHandler() { + NoteTakingHelper::Get()->AddObserver(this); + ui::InputDeviceManager::GetInstance()->AddObserver(this); +} + +StylusHandler::~StylusHandler() { + ui::InputDeviceManager::GetInstance()->RemoveObserver(this); + NoteTakingHelper::Get()->RemoveObserver(this); +} + +void StylusHandler::RegisterMessages() { + DCHECK(web_ui()); + + web_ui()->RegisterMessageCallback( + "initializeStylusSettings", + base::Bind(&StylusHandler::HandleInitialize, base::Unretained(this))); + web_ui()->RegisterMessageCallback( + "requestNoteTakingApps", + base::Bind(&StylusHandler::RequestApps, base::Unretained(this))); + web_ui()->RegisterMessageCallback( + "setPreferredNoteTakingApp", + base::Bind(&StylusHandler::SetPreferredNoteTakingApp, + base::Unretained(this))); + web_ui()->RegisterMessageCallback( + "showPlayStoreApps", + base::Bind(&StylusHandler::ShowPlayStoreApps, base::Unretained(this))); +} + +void StylusHandler::OnAvailableNoteTakingAppsUpdated() { + UpdateNoteTakingApps(); +} + +void StylusHandler::OnDeviceListsComplete() { + SendHasStylus(); +} + +void StylusHandler::UpdateNoteTakingApps() { + bool waiting_for_android = false; + note_taking_app_ids_.clear(); + base::ListValue apps_list; + + NoteTakingHelper* helper = NoteTakingHelper::Get(); + if (helper->play_store_enabled() && !helper->android_apps_received()) { + // If Play Store is enabled but not ready yet, let the JS know so it can + // disable the menu and display an explanatory message. + waiting_for_android = true; + } else { + std::vector<NoteTakingAppInfo> available_apps = + helper->GetAvailableApps(Profile::FromWebUI(web_ui())); + for (const NoteTakingAppInfo& info : available_apps) { + auto dict = base::MakeUnique<base::DictionaryValue>(); + dict->SetString(kAppNameKey, info.name); + dict->SetString(kAppIdKey, info.app_id); + dict->SetBoolean(kAppPreferredKey, info.preferred); + dict->SetBoolean(kAppLockScreenSupportKey, + info.lock_screen_support != + NoteTakingLockScreenSupport::kNotSupported); + apps_list.Append(std::move(dict)); + + note_taking_app_ids_.insert(info.app_id); + } + } + + AllowJavascript(); + FireWebUIListener("onNoteTakingAppsUpdated", apps_list, + base::Value(waiting_for_android)); +} + +void StylusHandler::RequestApps(const base::ListValue* unused_args) { + UpdateNoteTakingApps(); +} + +void StylusHandler::SetPreferredNoteTakingApp(const base::ListValue* args) { + std::string app_id; + CHECK(args->GetString(0, &app_id)); + + // Sanity check: make sure that the ID we got back from WebUI is in the + // currently-available set. + if (!note_taking_app_ids_.count(app_id)) { + LOG(ERROR) << "Got unknown note-taking-app ID \"" << app_id << "\""; + return; + } + + NoteTakingHelper::Get()->SetPreferredApp(Profile::FromWebUI(web_ui()), + app_id); +} + +void StylusHandler::HandleInitialize(const base::ListValue* args) { + if (ui::InputDeviceManager::GetInstance()->AreDeviceListsComplete()) + SendHasStylus(); +} + +void StylusHandler::SendHasStylus() { + DCHECK(ui::InputDeviceManager::GetInstance()->AreDeviceListsComplete()); + AllowJavascript(); + FireWebUIListener("has-stylus-changed", + base::Value(ash::palette_utils::HasStylusInput())); +} + +void StylusHandler::ShowPlayStoreApps(const base::ListValue* args) { + std::string apps_url; + args->GetString(0, &apps_url); + Profile* profile = Profile::FromWebUI(web_ui()); + if (!arc::IsArcAllowedForProfile(profile)) { + VLOG(1) << "ARC is not enabled for this profile"; + return; + } + + arc::LaunchPlayStoreWithUrl(apps_url); +} + +} // namespace settings +} // namespace chromeos diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/device_stylus_handler.h b/chromium/chrome/browser/ui/webui/settings/chromeos/device_stylus_handler.h new file mode 100644 index 00000000000..b8cd2567f99 --- /dev/null +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/device_stylus_handler.h @@ -0,0 +1,63 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_DEVICE_STYLUS_HANDLER_H_ +#define CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_DEVICE_STYLUS_HANDLER_H_ + +#include <set> + +#include "base/macros.h" +#include "chrome/browser/chromeos/note_taking_helper.h" +#include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h" +#include "ui/events/devices/input_device_event_observer.h" + +namespace base { +class ListValue; +} + +namespace chromeos { +namespace settings { + +// Chrome OS stylus settings handler. +class StylusHandler : public ::settings::SettingsPageUIHandler, + public chromeos::NoteTakingHelper::Observer, + public ui::InputDeviceEventObserver { + public: + StylusHandler(); + ~StylusHandler() override; + + // SettingsPageUIHandler implementation. + void RegisterMessages() override; + void OnJavascriptAllowed() override {} + void OnJavascriptDisallowed() override {} + + // chromeos::NoteTakingHelper::Observer implementation. + void OnAvailableNoteTakingAppsUpdated() override; + + // ui::InputDeviceObserver: + void OnDeviceListsComplete() override; + + private: + void UpdateNoteTakingApps(); + void RequestApps(const base::ListValue* unused_args); + void SetPreferredNoteTakingApp(const base::ListValue* args); + + // Called by JS to request a |SendHasStylus| call. + void HandleInitialize(const base::ListValue* args); + // Enables or disables the stylus UI section. + void SendHasStylus(); + + // Called by JS to show the Play Store Android app. + void ShowPlayStoreApps(const base::ListValue* args); + + // IDs of available note-taking apps. + std::set<std::string> note_taking_app_ids_; + + DISALLOW_COPY_AND_ASSIGN(StylusHandler); +}; + +} // namespace settings +} // namespace chromeos + +#endif // CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_DEVICE_STYLUS_HANDLER_H_ diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/easy_unlock_settings_handler.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/easy_unlock_settings_handler.cc new file mode 100644 index 00000000000..299d20bd1b7 --- /dev/null +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/easy_unlock_settings_handler.cc @@ -0,0 +1,160 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/webui/settings/chromeos/easy_unlock_settings_handler.h" + +#include <string> + +#include "base/bind.h" +#include "base/command_line.h" +#include "base/macros.h" +#include "base/values.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/signin/easy_unlock_service.h" +#include "chrome/common/pref_names.h" +#include "components/proximity_auth/switches.h" +#include "content/public/browser/web_ui.h" +#include "content/public/browser/web_ui_data_source.h" + +namespace chromeos { +namespace settings { + +EasyUnlockSettingsHandler::EasyUnlockSettingsHandler(Profile* profile) + : profile_(profile) { + profile_pref_registrar_.Init(profile->GetPrefs()); +} + +EasyUnlockSettingsHandler::~EasyUnlockSettingsHandler() { + EasyUnlockService::Get(profile_)->RemoveObserver(this); +} + +EasyUnlockSettingsHandler* EasyUnlockSettingsHandler::Create( + content::WebUIDataSource* html_source, + Profile* profile) { + EasyUnlockService* easy_unlock_service = EasyUnlockService::Get(profile); + bool allowed = easy_unlock_service->IsAllowed(); + html_source->AddBoolean("easyUnlockAllowed", allowed); + html_source->AddBoolean("easyUnlockEnabled", + allowed ? easy_unlock_service->IsEnabled() : false); + if (!allowed) + return nullptr; + + html_source->AddBoolean( + "easyUnlockProximityDetectionAllowed", + base::CommandLine::ForCurrentProcess()->HasSwitch( + proximity_auth::switches::kEnableProximityDetection)); + + return new EasyUnlockSettingsHandler(profile); +} + +void EasyUnlockSettingsHandler::RegisterMessages() { + web_ui()->RegisterMessageCallback( + "easyUnlockGetEnabledStatus", + base::Bind(&EasyUnlockSettingsHandler::HandleGetEnabledStatus, + base::Unretained(this))); + web_ui()->RegisterMessageCallback( + "easyUnlockStartTurnOnFlow", + base::Bind(&EasyUnlockSettingsHandler::HandleStartTurnOnFlow, + base::Unretained(this))); + web_ui()->RegisterMessageCallback( + "easyUnlockGetTurnOffFlowStatus", + base::Bind(&EasyUnlockSettingsHandler::HandleGetTurnOffFlowStatus, + base::Unretained(this))); + web_ui()->RegisterMessageCallback( + "easyUnlockStartTurnOffFlow", + base::Bind(&EasyUnlockSettingsHandler::HandleStartTurnOffFlow, + base::Unretained(this))); + web_ui()->RegisterMessageCallback( + "easyUnlockCancelTurnOffFlow", + base::Bind(&EasyUnlockSettingsHandler::HandleCancelTurnOffFlow, + base::Unretained(this))); +} + +void EasyUnlockSettingsHandler::OnJavascriptAllowed() { + EasyUnlockService::Get(profile_)->AddObserver(this); + + profile_pref_registrar_.Add( + prefs::kEasyUnlockPairing, + base::Bind(&EasyUnlockSettingsHandler::SendEnabledStatus, + base::Unretained(this))); +} + +void EasyUnlockSettingsHandler::OnJavascriptDisallowed() { + EasyUnlockService::Get(profile_)->RemoveObserver(this); + profile_pref_registrar_.RemoveAll(); +} + +void EasyUnlockSettingsHandler::OnTurnOffOperationStatusChanged() { + FireWebUIListener("easy-unlock-turn-off-flow-status", + base::Value(GetTurnOffFlowStatus())); +} + +void EasyUnlockSettingsHandler::SendEnabledStatus() { + CallJavascriptFunction( + "cr.webUIListenerCallback", base::Value("easy-unlock-enabled-status"), + base::Value(EasyUnlockService::Get(profile_)->IsEnabled())); +} + +std::string EasyUnlockSettingsHandler::GetTurnOffFlowStatus() { + EasyUnlockService::TurnOffFlowStatus status = + EasyUnlockService::Get(profile_)->GetTurnOffFlowStatus(); + + // Translate status into JS UI state string. Note the translated string + // should match UIState defined in easy_unlock_turn_off_dialog.js. + std::string status_string; + switch (status) { + case EasyUnlockService::IDLE: + status_string = "idle"; + break; + case EasyUnlockService::PENDING: + status_string = "pending"; + break; + case EasyUnlockService::FAIL: + status_string = "server-error"; + break; + default: + LOG(ERROR) << "Unknown Easy unlock turn-off operation status: " << status; + status_string = "idle"; + break; + } + + return status_string; +} + +void EasyUnlockSettingsHandler::HandleGetEnabledStatus( + const base::ListValue* args) { + AllowJavascript(); + + CHECK_EQ(1U, args->GetSize()); + const base::Value* callback_id; + CHECK(args->Get(0, &callback_id)); + ResolveJavascriptCallback( + *callback_id, base::Value(EasyUnlockService::Get(profile_)->IsEnabled())); +} + +void EasyUnlockSettingsHandler::HandleStartTurnOnFlow( + const base::ListValue* args) { + EasyUnlockService::Get(profile_)->LaunchSetup(); +} + +void EasyUnlockSettingsHandler::HandleGetTurnOffFlowStatus( + const base::ListValue* args) { + CHECK_EQ(1U, args->GetSize()); + const base::Value* callback_id; + CHECK(args->Get(0, &callback_id)); + ResolveJavascriptCallback(*callback_id, base::Value(GetTurnOffFlowStatus())); +} + +void EasyUnlockSettingsHandler::HandleStartTurnOffFlow( + const base::ListValue* args) { + EasyUnlockService::Get(profile_)->RunTurnOffFlow(); +} + +void EasyUnlockSettingsHandler::HandleCancelTurnOffFlow( + const base::ListValue* args) { + EasyUnlockService::Get(profile_)->ResetTurnOffFlow(); +} + +} // namespace settings +} // namespace chromeos diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/easy_unlock_settings_handler.h b/chromium/chrome/browser/ui/webui/settings/chromeos/easy_unlock_settings_handler.h new file mode 100644 index 00000000000..3fb3706c524 --- /dev/null +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/easy_unlock_settings_handler.h @@ -0,0 +1,67 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_EASY_UNLOCK_SETTINGS_HANDLER_H_ +#define CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_EASY_UNLOCK_SETTINGS_HANDLER_H_ + +#include "base/macros.h" +#include "chrome/browser/signin/easy_unlock_service_observer.h" +#include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h" +#include "components/prefs/pref_change_registrar.h" + +namespace content { +class WebUIDataSource; +} + +class Profile; + +namespace chromeos { +namespace settings { + +class EasyUnlockSettingsHandler : public ::settings::SettingsPageUIHandler, + public EasyUnlockServiceObserver { + public: + // Returns nullptr if EasyUnlock is not allowed for this device. + static EasyUnlockSettingsHandler* Create( + content::WebUIDataSource* html_source, + Profile* profile); + + ~EasyUnlockSettingsHandler() override; + + // SettingsPageUIHandler: + void RegisterMessages() override; + void OnJavascriptAllowed() override; + void OnJavascriptDisallowed() override; + + // EasyUnlockServiceObserver: + void OnTurnOffOperationStatusChanged() override; + + protected: + explicit EasyUnlockSettingsHandler(Profile* profile); + + private: + FRIEND_TEST_ALL_PREFIXES(EasyUnlockSettingsHandlerTest, EnabledStatus); + FRIEND_TEST_ALL_PREFIXES(EasyUnlockSettingsHandlerTest, TurnOffFlowStatus); + + void SendEnabledStatus(); + std::string GetTurnOffFlowStatus(); + + // JS callbacks. + void HandleGetEnabledStatus(const base::ListValue* args); + void HandleStartTurnOnFlow(const base::ListValue* args); + void HandleGetTurnOffFlowStatus(const base::ListValue* args); + void HandleStartTurnOffFlow(const base::ListValue* args); + void HandleCancelTurnOffFlow(const base::ListValue* args); + + Profile* const profile_; + + PrefChangeRegistrar profile_pref_registrar_; + + DISALLOW_COPY_AND_ASSIGN(EasyUnlockSettingsHandler); +}; + +} // namespace settings +} // namespace chromeos + +#endif // CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_EASY_UNLOCK_SETTINGS_HANDLER_H_ diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/easy_unlock_settings_handler_unittest.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/easy_unlock_settings_handler_unittest.cc new file mode 100644 index 00000000000..d56e735aa3e --- /dev/null +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/easy_unlock_settings_handler_unittest.cc @@ -0,0 +1,264 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/webui/settings/chromeos/easy_unlock_settings_handler.h" + +#include <memory> + +#include "base/memory/ptr_util.h" +#include "chrome/browser/signin/easy_unlock_service.h" +#include "chrome/browser/signin/easy_unlock_service_factory.h" +#include "chrome/test/base/testing_profile.h" +#include "content/public/browser/web_ui_data_source.h" +#include "content/public/test/test_browser_thread_bundle.h" +#include "content/public/test/test_web_ui.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace chromeos { +namespace settings { + +namespace { + +class FakeEasyUnlockService : public EasyUnlockService { + public: + explicit FakeEasyUnlockService(Profile* profile) + : EasyUnlockService(profile), + turn_off_status_(IDLE), + is_allowed_(true), + is_enabled_(false) {} + + TurnOffFlowStatus GetTurnOffFlowStatus() const override { + return turn_off_status_; + } + + bool IsAllowed() const override { return is_allowed_; } + void set_is_allowed(bool is_allowed) { is_allowed_ = is_allowed; } + + bool IsEnabled() const override { return is_enabled_; } + void set_is_enabled(bool is_enabled) { is_enabled_ = is_enabled; } + + void RunTurnOffFlow() override { + turn_off_status_ = PENDING; + NotifyTurnOffOperationStatusChanged(); + } + + void ResetTurnOffFlow() override { + turn_off_status_ = IDLE; + NotifyTurnOffOperationStatusChanged(); + } + + void SetTurnOffFlowFailForTest() { + turn_off_status_ = FAIL; + NotifyTurnOffOperationStatusChanged(); + } + + private: + Type GetType() const override { return TYPE_REGULAR; } + AccountId GetAccountId() const override { return EmptyAccountId(); } + void LaunchSetup() override {} + const base::DictionaryValue* GetPermitAccess() const override { + return nullptr; + } + void SetPermitAccess(const base::DictionaryValue& permit) override {} + void ClearPermitAccess() override {} + + const base::ListValue* GetRemoteDevices() const override { return nullptr; } + void SetRemoteDevices(const base::ListValue& devices) override {} + void SetRemoteBleDevices(const base::ListValue& devices) override {} + + std::string GetChallenge() const override { return std::string(); } + std::string GetWrappedSecret() const override { return std::string(); } + void RecordEasySignInOutcome(const AccountId& account_id, + bool success) const override {} + void RecordPasswordLoginEvent(const AccountId& account_id) const override {} + void StartAutoPairing(const AutoPairingResultCallback& callback) override {} + void SetAutoPairingResult(bool success, const std::string& error) override {} + + void InitializeInternal() override {} + void ShutdownInternal() override {} + bool IsAllowedInternal() const override { return false; } + void OnWillFinalizeUnlock(bool success) override {} + void OnSuspendDoneInternal() override {} + + TurnOffFlowStatus turn_off_status_; + bool is_allowed_; + bool is_enabled_; +}; + +class TestEasyUnlockSettingsHandler : public EasyUnlockSettingsHandler { + public: + explicit TestEasyUnlockSettingsHandler(Profile* profile) + : EasyUnlockSettingsHandler(profile) {} + + using EasyUnlockSettingsHandler::set_web_ui; +}; + +std::unique_ptr<KeyedService> CreateEasyUnlockServiceForTest( + content::BrowserContext* context) { + return base::MakeUnique<FakeEasyUnlockService>( + Profile::FromBrowserContext(context)); +} + +} // namespace + +class EasyUnlockSettingsHandlerTest : public testing::Test { + public: + EasyUnlockSettingsHandlerTest() {} + + void SetUp() override { + TestingProfile::Builder builder; + builder.AddTestingFactory(EasyUnlockServiceFactory::GetInstance(), + &CreateEasyUnlockServiceForTest); + profile_ = builder.Build(); + } + + Profile* profile() { return profile_.get(); } + content::TestWebUI* web_ui() { return &web_ui_; } + FakeEasyUnlockService* fake_easy_unlock_service() { + return static_cast<FakeEasyUnlockService*>( + EasyUnlockService::Get(profile_.get())); + } + + void VerifyEnabledStatusCallback(size_t expected_total_calls, + bool expected_status) { + std::string event; + bool status; + + EXPECT_EQ(expected_total_calls, web_ui_.call_data().size()); + + const content::TestWebUI::CallData& data = *web_ui_.call_data().back(); + EXPECT_EQ("cr.webUIListenerCallback", data.function_name()); + ASSERT_TRUE(data.arg1()->GetAsString(&event)); + EXPECT_EQ("easy-unlock-enabled-status", event); + ASSERT_TRUE(data.arg2()->GetAsBoolean(&status)); + + EXPECT_EQ(expected_status, status); + } + + void VerifyTurnOffFlowStatusWebUIListenerCallback( + size_t expected_total_calls, + const std::string& expected_status) { + std::string event; + std::string status; + + EXPECT_EQ(expected_total_calls, web_ui_.call_data().size()); + + const content::TestWebUI::CallData& data = *web_ui_.call_data().back(); + EXPECT_EQ("cr.webUIListenerCallback", data.function_name()); + ASSERT_TRUE(data.arg1()->GetAsString(&event)); + EXPECT_EQ("easy-unlock-turn-off-flow-status", event); + ASSERT_TRUE(data.arg2()->GetAsString(&status)); + + EXPECT_EQ(expected_status, status); + } + + void VerifyTurnOffFlowStatusWebUIResponse( + size_t expected_total_calls, + const std::string& expected_callback_id, + const std::string& expected_status) { + EXPECT_EQ(expected_total_calls, web_ui()->call_data().size()); + + const content::TestWebUI::CallData& data = *web_ui()->call_data().back(); + EXPECT_EQ("cr.webUIResponse", data.function_name()); + + std::string callback_id; + ASSERT_TRUE(data.arg1()->GetAsString(&callback_id)); + EXPECT_EQ(expected_callback_id, callback_id); + + std::string actual_status; + ASSERT_TRUE(data.arg3()->GetAsString(&actual_status)); + EXPECT_EQ(expected_status, actual_status); + } + + private: + content::TestBrowserThreadBundle thread_bundle_; + std::unique_ptr<TestingProfile> profile_; + content::TestWebUI web_ui_; +}; + +TEST_F(EasyUnlockSettingsHandlerTest, OnlyCreatedWhenEasyUnlockAllowed) { + std::unique_ptr<EasyUnlockSettingsHandler> handler; + content::WebUIDataSource* data_source = + content::WebUIDataSource::Create("test-data-source"); + content::WebUIDataSource::Add(profile(), data_source); + handler.reset( + EasyUnlockSettingsHandler::Create(data_source, profile())); + EXPECT_TRUE(handler.get()); + + fake_easy_unlock_service()->set_is_allowed(false); + handler.reset(EasyUnlockSettingsHandler::Create(data_source, profile())); + EXPECT_FALSE(handler.get()); +} + +TEST_F(EasyUnlockSettingsHandlerTest, EnabledStatus) { + std::unique_ptr<EasyUnlockSettingsHandler> handler; + handler.reset(new TestEasyUnlockSettingsHandler(profile())); + handler->set_web_ui(web_ui()); + + // Test the JS -> C++ -> JS callback path. + base::ListValue list_args; + list_args.AppendString("test-callback-id"); + handler->HandleGetEnabledStatus(&list_args); + + EXPECT_EQ(1U, web_ui()->call_data().size()); + + const content::TestWebUI::CallData& data = *web_ui()->call_data().back(); + EXPECT_EQ("cr.webUIResponse", data.function_name()); + + std::string callback_id; + ASSERT_TRUE(data.arg1()->GetAsString(&callback_id)); + EXPECT_EQ("test-callback-id", callback_id); + + bool enabled_status = false; + ASSERT_TRUE(data.arg3()->GetAsBoolean(&enabled_status)); + EXPECT_FALSE(enabled_status); + + // Test the C++ -> JS push path. + handler->SendEnabledStatus(); + VerifyEnabledStatusCallback(2U, false); + + fake_easy_unlock_service()->set_is_enabled(true); + handler->SendEnabledStatus(); + VerifyEnabledStatusCallback(3U, true); +} + +TEST_F(EasyUnlockSettingsHandlerTest, TurnOffFlowStatus) { + std::unique_ptr<EasyUnlockSettingsHandler> handler; + handler.reset(new TestEasyUnlockSettingsHandler(profile())); + handler->set_web_ui(web_ui()); + + // Send an initial status query to turn on service observer. + base::ListValue list_args1; + list_args1.AppendString("test-callback-id-1"); + handler->HandleGetEnabledStatus(&list_args1); + EXPECT_EQ(1U, web_ui()->call_data().size()); + + base::ListValue list_args2; + list_args2.AppendString("test-callback-id-2"); + handler->HandleGetTurnOffFlowStatus(&list_args2); + VerifyTurnOffFlowStatusWebUIResponse(2U, "test-callback-id-2", "idle"); + + handler->HandleStartTurnOffFlow(nullptr); + VerifyTurnOffFlowStatusWebUIListenerCallback(3U, "pending"); + + base::ListValue list_args3; + list_args3.AppendString("test-callback-id-3"); + handler->HandleGetTurnOffFlowStatus(&list_args3); + VerifyTurnOffFlowStatusWebUIResponse(4U, "test-callback-id-3", "pending"); + + handler->HandleCancelTurnOffFlow(nullptr); + VerifyTurnOffFlowStatusWebUIListenerCallback(5U, "idle"); + + fake_easy_unlock_service()->SetTurnOffFlowFailForTest(); + VerifyTurnOffFlowStatusWebUIListenerCallback(6U, "server-error"); + + base::ListValue list_args4; + list_args4.AppendString("test-callback-id-4"); + handler->HandleGetTurnOffFlowStatus(&list_args4); + VerifyTurnOffFlowStatusWebUIResponse(7U, "test-callback-id-4", + "server-error"); +} + +} // namespace settings +} // namespace chromeos diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/fingerprint_handler.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/fingerprint_handler.cc new file mode 100644 index 00000000000..afcd3c13819 --- /dev/null +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/fingerprint_handler.cc @@ -0,0 +1,327 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/webui/settings/chromeos/fingerprint_handler.h" + +#include <algorithm> + +#include "base/bind.h" +#include "base/memory/ptr_util.h" +#include "base/strings/string_number_conversions.h" +#include "base/strings/utf_string_conversions.h" +#include "base/values.h" +#include "chrome/browser/chromeos/profiles/profile_helper.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/common/pref_names.h" +#include "chrome/grit/generated_resources.h" +#include "components/prefs/pref_service.h" +#include "components/session_manager/core/session_manager.h" +#include "content/public/common/service_manager_connection.h" +#include "services/device/public/interfaces/constants.mojom.h" +#include "services/service_manager/public/cpp/connector.h" +#include "ui/base/l10n/l10n_util.h" + +using session_manager::SessionManager; +using session_manager::SessionState; + +namespace chromeos { +namespace settings { +namespace { + +// The max number of fingerprints that can be stored. +const int kMaxAllowedFingerprints = 5; + +std::unique_ptr<base::DictionaryValue> GetFingerprintsInfo( + const std::vector<std::string>& fingerprints_list) { + auto response = base::MakeUnique<base::DictionaryValue>(); + auto fingerprints = base::MakeUnique<base::ListValue>(); + + DCHECK_LE(static_cast<int>(fingerprints_list.size()), + kMaxAllowedFingerprints); + for (auto& fingerprint_name: fingerprints_list) { + std::unique_ptr<base::Value> str = + base::MakeUnique<base::Value>(fingerprint_name); + fingerprints->Append(std::move(str)); + } + + response->Set("fingerprintsList", std::move(fingerprints)); + response->SetBoolean("isMaxed", static_cast<int>(fingerprints_list.size()) >= + kMaxAllowedFingerprints); + return response; +} + +} // namespace + +FingerprintHandler::FingerprintHandler(Profile* profile) + : profile_(profile), binding_(this), weak_ptr_factory_(this) { + service_manager::Connector* connector = + content::ServiceManagerConnection::GetForProcess()->GetConnector(); + connector->BindInterface(device::mojom::kServiceName, &fp_service_); + fp_service_->AddFingerprintObserver(binding_.CreateInterfacePtrAndBind()); + user_id_ = ProfileHelper::Get()->GetUserIdHashFromProfile(profile); + // SessionManager may not exist in some tests. + if (SessionManager::Get()) + SessionManager::Get()->AddObserver(this); +} + +FingerprintHandler::~FingerprintHandler() { + if (SessionManager::Get()) + SessionManager::Get()->RemoveObserver(this); +} + +void FingerprintHandler::RegisterMessages() { + web_ui()->RegisterMessageCallback( + "getFingerprintsList", + base::Bind(&FingerprintHandler::HandleGetFingerprintsList, + base::Unretained(this))); + web_ui()->RegisterMessageCallback( + "getNumFingerprints", + base::Bind(&FingerprintHandler::HandleGetNumFingerprints, + base::Unretained(this))); + web_ui()->RegisterMessageCallback( + "startEnroll", + base::Bind(&FingerprintHandler::HandleStartEnroll, + base::Unretained(this))); + web_ui()->RegisterMessageCallback( + "cancelCurrentEnroll", + base::Bind(&FingerprintHandler::HandleCancelCurrentEnroll, + base::Unretained(this))); + web_ui()->RegisterMessageCallback( + "getEnrollmentLabel", + base::Bind(&FingerprintHandler::HandleGetEnrollmentLabel, + base::Unretained(this))); + web_ui()->RegisterMessageCallback( + "removeEnrollment", + base::Bind(&FingerprintHandler::HandleRemoveEnrollment, + base::Unretained(this))); + web_ui()->RegisterMessageCallback( + "changeEnrollmentLabel", + base::Bind(&FingerprintHandler::HandleChangeEnrollmentLabel, + base::Unretained(this))); + web_ui()->RegisterMessageCallback( + "startAuthentication", + base::Bind(&FingerprintHandler::HandleStartAuthentication, + base::Unretained(this))); + web_ui()->RegisterMessageCallback( + "endCurrentAuthentication", + base::Bind(&FingerprintHandler::HandleEndCurrentAuthentication, + base::Unretained(this))); +} + +void FingerprintHandler::OnJavascriptAllowed() {} + +void FingerprintHandler::OnJavascriptDisallowed() {} + +void FingerprintHandler::OnRestarted() {} + +void FingerprintHandler::OnEnrollScanDone(uint32_t scan_result, + bool enroll_session_complete, + int percent_complete) { + AllowJavascript(); + auto scan_attempt = base::MakeUnique<base::DictionaryValue>(); + scan_attempt->SetInteger("result", scan_result); + scan_attempt->SetBoolean("isComplete", enroll_session_complete); + scan_attempt->SetInteger("percentComplete", percent_complete); + + FireWebUIListener("on-fingerprint-scan-received", *scan_attempt); +} + +void FingerprintHandler::OnAuthScanDone( + uint32_t scan_result, + const std::unordered_map<std::string, std::vector<std::string>>& matches) { + if (SessionManager::Get()->session_state() == SessionState::LOCKED) + return; + + // When the user touches the sensor, highlight the label(s) that finger is + // associated with, if it is registered with this user. + auto it = matches.find(user_id_); + if (it == matches.end() || it->second.size() < 1) + return; + + AllowJavascript(); + auto fingerprint_ids = base::MakeUnique<base::ListValue>(); + + for (const std::string& matched_path : it->second) { + auto path_it = std::find(fingerprints_paths_.begin(), + fingerprints_paths_.end(), matched_path); + DCHECK(path_it != fingerprints_paths_.end()); + fingerprint_ids->AppendInteger( + static_cast<int>(path_it - fingerprints_paths_.begin())); + } + + auto fingerprint_attempt = base::MakeUnique<base::DictionaryValue>(); + fingerprint_attempt->SetInteger("result", scan_result); + fingerprint_attempt->Set("indexes", std::move(fingerprint_ids)); + + FireWebUIListener("on-fingerprint-attempt-received", *fingerprint_attempt); +} + +void FingerprintHandler::OnSessionFailed() {} + +void FingerprintHandler::OnSessionStateChanged() { + SessionState state = SessionManager::Get()->session_state(); + + AllowJavascript(); + FireWebUIListener("on-screen-locked", + base::Value(state == SessionState::LOCKED)); +} + +void FingerprintHandler::HandleGetFingerprintsList( + const base::ListValue* args) { + CHECK_EQ(1U, args->GetSize()); + std::string callback_id; + CHECK(args->GetString(0, &callback_id)); + + fp_service_->GetRecordsForUser( + user_id_, base::Bind(&FingerprintHandler::OnGetFingerprintsList, + weak_ptr_factory_.GetWeakPtr(), callback_id)); +} + +void FingerprintHandler::OnGetFingerprintsList( + const std::string& callback_id, + const std::unordered_map<std::string, std::string>& + fingerprints_list_mapping) { + AllowJavascript(); + fingerprints_labels_.clear(); + fingerprints_paths_.clear(); + for (auto it = fingerprints_list_mapping.begin(); + it != fingerprints_list_mapping.end(); ++it) { + fingerprints_paths_.push_back(it->first); + fingerprints_labels_.push_back(it->second); + } + + profile_->GetPrefs()->SetInteger(prefs::kQuickUnlockFingerprintRecord, + fingerprints_list_mapping.size()); + + std::unique_ptr<base::DictionaryValue> fingerprint_info = + GetFingerprintsInfo(fingerprints_labels_); + ResolveJavascriptCallback(base::Value(callback_id), *fingerprint_info); +} + +void FingerprintHandler::HandleGetNumFingerprints(const base::ListValue* args) { + AllowJavascript(); + + CHECK_EQ(1U, args->GetSize()); + std::string callback_id; + CHECK(args->GetString(0, &callback_id)); + + int fingerprints_num = + profile_->GetPrefs()->GetInteger(prefs::kQuickUnlockFingerprintRecord); + + ResolveJavascriptCallback(base::Value(callback_id), + base::Value(fingerprints_num)); +} + +void FingerprintHandler::HandleStartEnroll(const base::ListValue* args) { + // Determines what the newly added fingerprint's name should be. + for (int i = 1; i <= kMaxAllowedFingerprints; ++i) { + std::string fingerprint_name = l10n_util::GetStringFUTF8( + IDS_SETTINGS_PEOPLE_LOCK_SCREEN_NEW_FINGERPRINT_DEFAULT_NAME, + base::IntToString16(i)); + if (std::find(fingerprints_labels_.begin(), fingerprints_labels_.end(), + fingerprint_name) == fingerprints_labels_.end()) { + fp_service_->StartEnrollSession(user_id_, fingerprint_name); + break; + } + } +} + +void FingerprintHandler::HandleCancelCurrentEnroll( + const base::ListValue* args) { + fp_service_->CancelCurrentEnrollSession( + base::Bind(&FingerprintHandler::OnCancelCurrentEnrollSession, + weak_ptr_factory_.GetWeakPtr())); +} + +void FingerprintHandler::OnCancelCurrentEnrollSession(bool success) { + if (!success) + LOG(ERROR) << "Failed to cancel current fingerprint enroll session."; +} + +void FingerprintHandler::HandleGetEnrollmentLabel(const base::ListValue* args) { + CHECK_EQ(2U, args->GetSize()); + std::string callback_id; + int index; + CHECK(args->GetString(0, &callback_id)); + CHECK(args->GetInteger(1, &index)); + + DCHECK_LT(index, static_cast<int>(fingerprints_labels_.size())); + fp_service_->RequestRecordLabel( + fingerprints_paths_[index], + base::Bind(&FingerprintHandler::OnRequestRecordLabel, + weak_ptr_factory_.GetWeakPtr(), callback_id)); +} + +void FingerprintHandler::OnRequestRecordLabel(const std::string& callback_id, + const std::string& label) { + AllowJavascript(); + ResolveJavascriptCallback(base::Value(callback_id), base::Value(label)); +} + +void FingerprintHandler::HandleRemoveEnrollment(const base::ListValue* args) { + CHECK_EQ(2U, args->GetSize()); + std::string callback_id; + int index; + CHECK(args->GetString(0, &callback_id)); + CHECK(args->GetInteger(1, &index)); + + DCHECK_LT(index, static_cast<int>(fingerprints_paths_.size())); + fp_service_->RemoveRecord( + fingerprints_paths_[index], + base::Bind(&FingerprintHandler::OnRemoveRecord, + weak_ptr_factory_.GetWeakPtr(), callback_id)); +} + +void FingerprintHandler::OnRemoveRecord(const std::string& callback_id, + bool success) { + if (!success) + LOG(ERROR) << "Failed to remove fingerprint record."; + AllowJavascript(); + ResolveJavascriptCallback(base::Value(callback_id), base::Value(success)); +} + +void FingerprintHandler::HandleChangeEnrollmentLabel( + const base::ListValue* args) { + CHECK_EQ(3U, args->GetSize()); + std::string callback_id; + int index; + std::string new_label; + + CHECK(args->GetString(0, &callback_id)); + CHECK(args->GetInteger(1, &index)); + CHECK(args->GetString(2, &new_label)); + + fp_service_->SetRecordLabel( + new_label, fingerprints_paths_[index], + base::Bind(&FingerprintHandler::OnSetRecordLabel, + weak_ptr_factory_.GetWeakPtr(), callback_id)); +} + +void FingerprintHandler::OnSetRecordLabel(const std::string& callback_id, + bool success) { + if (!success) + LOG(ERROR) << "Failed to set fingerprint record label."; + AllowJavascript(); + ResolveJavascriptCallback(base::Value(callback_id), base::Value(success)); +} + +void FingerprintHandler::HandleStartAuthentication( + const base::ListValue* args) { + fp_service_->StartAuthSession(); +} + +void FingerprintHandler::HandleEndCurrentAuthentication( + const base::ListValue* args) { + fp_service_->EndCurrentAuthSession( + base::Bind(&FingerprintHandler::OnEndCurrentAuthSession, + weak_ptr_factory_.GetWeakPtr())); +} + +void FingerprintHandler::OnEndCurrentAuthSession(bool success) { + if (!success) + LOG(ERROR) << "Failed to end current fingerprint authentication session."; +} + +} // namespace settings +} // namespace chromeos diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/fingerprint_handler.h b/chromium/chrome/browser/ui/webui/settings/chromeos/fingerprint_handler.h new file mode 100644 index 00000000000..5c296d69fe7 --- /dev/null +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/fingerprint_handler.h @@ -0,0 +1,90 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_FINGERPRINT_HANDLER_H_ +#define CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_FINGERPRINT_HANDLER_H_ + +#include <unordered_map> + +#include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h" +#include "components/session_manager/core/session_manager_observer.h" +#include "mojo/public/cpp/bindings/binding.h" +#include "services/device/public/interfaces/fingerprint.mojom.h" + +class Profile; + +namespace base { +class ListValue; +} // namespace base + +namespace chromeos { +namespace settings { + +// Chrome OS fingerprint setup settings page UI handler. +class FingerprintHandler : public ::settings::SettingsPageUIHandler, + public device::mojom::FingerprintObserver, + public session_manager::SessionManagerObserver { + public: + explicit FingerprintHandler(Profile* profile); + ~FingerprintHandler() override; + + // SettingsPageUIHandler overrides: + void RegisterMessages() override; + void OnJavascriptAllowed() override; + void OnJavascriptDisallowed() override; + + private: + using AttemptMatches = + std::unordered_map<std::string, std::vector<std::string>>; + + // device::mojom::FingerprintObserver: + void OnRestarted() override; + void OnEnrollScanDone(uint32_t scan_result, + bool enroll_session_complete, + int percent_complete) override; + void OnAuthScanDone(uint32_t scan_result, + const AttemptMatches& matches) override; + void OnSessionFailed() override; + + // session_manager::SessionManagerObserver: + void OnSessionStateChanged() override; + + void HandleGetFingerprintsList(const base::ListValue* args); + void HandleGetNumFingerprints(const base::ListValue* args); + void HandleStartEnroll(const base::ListValue* args); + void HandleCancelCurrentEnroll(const base::ListValue* args); + void HandleGetEnrollmentLabel(const base::ListValue* args); + void HandleRemoveEnrollment(const base::ListValue* args); + void HandleChangeEnrollmentLabel(const base::ListValue* args); + void HandleStartAuthentication(const base::ListValue* args); + void HandleEndCurrentAuthentication(const base::ListValue* args); + + void OnGetFingerprintsList(const std::string& callback_id, + const std::unordered_map<std::string, std::string>& + fingerprints_list_mapping); + void OnRequestRecordLabel(const std::string& callback_id, + const std::string& label); + void OnCancelCurrentEnrollSession(bool success); + void OnRemoveRecord(const std::string& callback_id, bool success); + void OnSetRecordLabel(const std::string& callback_id, bool success); + void OnEndCurrentAuthSession(bool success); + + Profile* profile_; // unowned + + std::vector<std::string> fingerprints_labels_; + std::vector<std::string> fingerprints_paths_; + std::string user_id_; + + device::mojom::FingerprintPtr fp_service_; + mojo::Binding<device::mojom::FingerprintObserver> binding_; + + base::WeakPtrFactory<FingerprintHandler> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(FingerprintHandler); +}; + +} // namespace settings +} // namespace chromeos + +#endif // CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_FINGERPRINT_HANDLER_H_ diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/internet_handler.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/internet_handler.cc new file mode 100644 index 00000000000..1af49e99b48 --- /dev/null +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/internet_handler.cc @@ -0,0 +1,132 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/webui/settings/chromeos/internet_handler.h" + +#include "base/bind.h" +#include "base/values.h" +#include "chrome/browser/chromeos/options/network_config_view.h" +#include "chrome/browser/chromeos/profiles/profile_helper.h" +#include "chrome/browser/chromeos/ui/choose_mobile_network_dialog.h" +#include "chrome/browser/profiles/profile.h" +#include "chromeos/network/network_state.h" +#include "chromeos/network/network_state_handler.h" +#include "components/onc/onc_constants.h" +#include "content/public/browser/web_contents.h" +#include "content/public/browser/web_ui.h" +#include "extensions/browser/api/vpn_provider/vpn_service.h" +#include "extensions/browser/api/vpn_provider/vpn_service_factory.h" +#include "third_party/cros_system_api/dbus/service_constants.h" + +namespace chromeos { + +namespace { + +const char kAddNetworkMessage[] = "addNetwork"; +const char kConfigureNetworkMessage[] = "configureNetwork"; + +std::string ServicePathFromGuid(const std::string& guid) { + const NetworkState* network = + NetworkHandler::Get()->network_state_handler()->GetNetworkStateFromGuid( + guid); + return network ? network->path() : ""; +} + +Profile* GetProfileForPrimaryUser() { + return ProfileHelper::Get()->GetProfileByUser( + user_manager::UserManager::Get()->GetPrimaryUser()); +} + +} // namespace + +namespace settings { + +InternetHandler::InternetHandler() {} + +InternetHandler::~InternetHandler() {} + +void InternetHandler::RegisterMessages() { + // TODO(stevenjb): Eliminate once network configuration UI is integrated + // into settings. + web_ui()->RegisterMessageCallback( + kAddNetworkMessage, + base::Bind(&InternetHandler::AddNetwork, base::Unretained(this))); + web_ui()->RegisterMessageCallback( + kConfigureNetworkMessage, + base::Bind(&InternetHandler::ConfigureNetwork, base::Unretained(this))); +} + +void InternetHandler::OnJavascriptAllowed() {} + +void InternetHandler::OnJavascriptDisallowed() {} + +void InternetHandler::AddNetwork(const base::ListValue* args) { + std::string onc_type; + if (args->GetSize() < 1 || !args->GetString(0, &onc_type)) { + NOTREACHED() << "Invalid args for: " << kAddNetworkMessage; + return; + } + + if (onc_type == ::onc::network_type::kVPN) { + std::string extension_id; + if (args->GetSize() >= 2) + args->GetString(1, &extension_id); + if (extension_id.empty()) { + // Show the "add network" dialog for the built-in OpenVPN/L2TP provider. + NetworkConfigView::ShowForType(shill::kTypeVPN, GetNativeWindow()); + return; + } + // Request that the third-party VPN provider identified by |provider_id| + // show its "add network" dialog. + VpnServiceFactory::GetForBrowserContext(GetProfileForPrimaryUser()) + ->SendShowAddDialogToExtension(extension_id); + } else if (onc_type == ::onc::network_type::kWiFi) { + NetworkConfigView::ShowForType(shill::kTypeWifi, GetNativeWindow()); + } else if (onc_type == ::onc::network_type::kCellular) { + ChooseMobileNetworkDialog::ShowDialog(GetNativeWindow()); + } else { + LOG(ERROR) << "Unsupported type for: " << kAddNetworkMessage; + } +} + +void InternetHandler::ConfigureNetwork(const base::ListValue* args) { + std::string guid; + if (args->GetSize() < 1 || !args->GetString(0, &guid)) { + NOTREACHED() << "Invalid args for: " << kConfigureNetworkMessage; + return; + } + + const std::string service_path = ServicePathFromGuid(guid); + if (service_path.empty()) { + LOG(ERROR) << "Network not found: " << guid; + return; + } + + const NetworkState* network = + NetworkHandler::Get()->network_state_handler()->GetNetworkState( + service_path); + if (!network) { + LOG(ERROR) << "Network not found with service_path: " << service_path; + return; + } + + if (network->type() == shill::kTypeVPN && + network->vpn_provider_type() == shill::kProviderThirdPartyVpn) { + // Request that the third-party VPN provider used by the |network| show a + // configuration dialog for it. + VpnServiceFactory::GetForBrowserContext(GetProfileForPrimaryUser()) + ->SendShowConfigureDialogToExtension( + network->third_party_vpn_provider_extension_id(), network->name()); + return; + } + + NetworkConfigView::ShowForNetworkId(network->guid(), GetNativeWindow()); +} + +gfx::NativeWindow InternetHandler::GetNativeWindow() const { + return web_ui()->GetWebContents()->GetTopLevelNativeWindow(); +} + +} // namespace settings +} // namespace chromeos diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/internet_handler.h b/chromium/chrome/browser/ui/webui/settings/chromeos/internet_handler.h new file mode 100644 index 00000000000..64ceabfe29b --- /dev/null +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/internet_handler.h @@ -0,0 +1,41 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_INTERNET_HANDLER_H_ +#define CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_INTERNET_HANDLER_H_ + +#include <memory> + +#include "base/macros.h" +#include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h" +#include "ui/gfx/native_widget_types.h" + +namespace chromeos { +namespace settings { + +// Chrome OS Internet settings page UI handler. +class InternetHandler : public ::settings::SettingsPageUIHandler { + public: + InternetHandler(); + ~InternetHandler() override; + + // SettingsPageUIHandler implementation. + void RegisterMessages() override; + void OnJavascriptAllowed() override; + void OnJavascriptDisallowed() override; + + private: + // Settings JS handlers. + void AddNetwork(const base::ListValue* args); + void ConfigureNetwork(const base::ListValue* args); + + gfx::NativeWindow GetNativeWindow() const; + + DISALLOW_COPY_AND_ASSIGN(InternetHandler); +}; + +} // namespace settings +} // namespace chromeos + +#endif // CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_INTERNET_HANDLER_H_ |