diff --git a/DEPS b/DEPS index e2f7355..a7d7a58 100644 --- a/DEPS +++ b/DEPS
@@ -318,7 +318,7 @@ }, 'src/third_party/depot_tools': - Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '6c5a1c4c3c97b568c79ee44a7b1d7ffac17e30d3', + Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '17995a9f128290b66e16f2fdfba96b4369425f8c', # DevTools node modules. Used on Linux buildbots only. 'src/third_party/devtools-node-modules': {
diff --git a/ash/login/ui/lock_debug_view.cc b/ash/login/ui/lock_debug_view.cc index 7a84ef99..f6180d4 100644 --- a/ash/login/ui/lock_debug_view.cc +++ b/ash/login/ui/lock_debug_view.cc
@@ -182,14 +182,11 @@ debug_dispatcher_.SetLockScreenNoteState(lock_screen_note_state_); } - void ToggleLockScreenDevChannelInfo() { - show_dev_channel_info_ = !show_dev_channel_info_; - if (show_dev_channel_info_) { - debug_dispatcher_.SetDevChannelInfo(kDebugOsVersion, kDebugEnterpriseInfo, - kDebugBluetoothName); - } else { - debug_dispatcher_.SetDevChannelInfo("", "", ""); - } + void AddLockScreenDevChannelInfo(const std::string& os_version, + const std::string& enterprise_info, + const std::string& bluetooth_name) { + debug_dispatcher_.SetDevChannelInfo(os_version, enterprise_info, + bluetooth_name); } // LoginDataDispatcher::Observer: @@ -251,9 +248,6 @@ // The current lock screen note action state. mojom::TrayActionState lock_screen_note_state_; - // If the dev channel info is being shown. - bool show_dev_channel_info_ = false; - DISALLOW_COPY_AND_ASSIGN(DebugDataDispatcherTransformer); }; @@ -284,8 +278,8 @@ toggle_blur_ = AddButton("Blur"); toggle_note_action_ = AddButton("Toggle note action"); - toggle_dev_channel_info_ = AddButton("Toggle dev channel info"); toggle_caps_lock_ = AddButton("Toggle caps lock"); + add_dev_channel_info_ = AddButton("Add dev channel info"); add_user_ = AddButton("Add user"); remove_user_ = AddButton("Remove user"); toggle_auth_ = AddButton("Auth (allowed)"); @@ -316,12 +310,6 @@ return; } - // Enable or disable dev channel info. - if (sender == toggle_dev_channel_info_) { - debug_data_dispatcher_->ToggleLockScreenDevChannelInfo(); - return; - } - // Enable or disable caps lock. if (sender == toggle_caps_lock_) { chromeos::input_method::ImeKeyboard* keyboard = @@ -330,6 +318,25 @@ return; } + // Iteratively adds more info to the dev channel labels to test 7 permutations + // and then disables the button. + if (sender == add_dev_channel_info_) { + DCHECK(num_dev_channel_info_clicks_ < 7u); + ++num_dev_channel_info_clicks_; + if (num_dev_channel_info_clicks_ == 7u) + add_dev_channel_info_->SetEnabled(false); + + std::string os_version = + num_dev_channel_info_clicks_ / 4 ? kDebugOsVersion : ""; + std::string enterprise_info = + (num_dev_channel_info_clicks_ % 4) / 2 ? kDebugEnterpriseInfo : ""; + std::string bluetooth_name = + num_dev_channel_info_clicks_ % 2 ? kDebugBluetoothName : ""; + debug_data_dispatcher_->AddLockScreenDevChannelInfo( + os_version, enterprise_info, bluetooth_name); + return; + } + // Add or remove a user. if (sender == add_user_ || sender == remove_user_) { if (sender == add_user_)
diff --git a/ash/login/ui/lock_debug_view.h b/ash/login/ui/lock_debug_view.h index 16fa56e..3e1bb40 100644 --- a/ash/login/ui/lock_debug_view.h +++ b/ash/login/ui/lock_debug_view.h
@@ -59,8 +59,8 @@ views::View* debug_row_ = nullptr; views::MdTextButton* toggle_blur_ = nullptr; views::MdTextButton* toggle_note_action_ = nullptr; - views::MdTextButton* toggle_dev_channel_info_ = nullptr; views::MdTextButton* toggle_caps_lock_ = nullptr; + views::MdTextButton* add_dev_channel_info_ = nullptr; views::MdTextButton* add_user_ = nullptr; views::MdTextButton* remove_user_ = nullptr; views::MdTextButton* toggle_auth_ = nullptr; @@ -68,6 +68,7 @@ // Debug dispatcher and cached data for the UI. std::unique_ptr<DebugDataDispatcherTransformer> const debug_data_dispatcher_; size_t num_users_ = 1u; + size_t num_dev_channel_info_clicks_ = 0u; LoginScreenController::ForceFailAuth force_fail_auth_ = LoginScreenController::ForceFailAuth::kOff;
diff --git a/ash/public/cpp/ash_pref_names.cc b/ash/public/cpp/ash_pref_names.cc index 1be3dfd..f5e57e5 100644 --- a/ash/public/cpp/ash_pref_names.cc +++ b/ash/public/cpp/ash_pref_names.cc
@@ -133,6 +133,9 @@ // a confirmation dialog. const char kLogoutDialogDurationMs[] = "logout_dialog_duration_ms"; +// A dictionary pref that maps usernames to wallpaper info. +const char kUserWallpaperInfo[] = "user_wallpaper_info"; + // A dictionary pref that maps wallpaper file paths to their prominent colors. const char kWallpaperColors[] = "ash.wallpaper.prominent_colors";
diff --git a/ash/public/cpp/ash_pref_names.h b/ash/public/cpp/ash_pref_names.h index 5a800ccd..72106378 100644 --- a/ash/public/cpp/ash_pref_names.h +++ b/ash/public/cpp/ash_pref_names.h
@@ -50,6 +50,7 @@ ASH_PUBLIC_EXPORT extern const char kShowLogoutButtonInTray[]; ASH_PUBLIC_EXPORT extern const char kLogoutDialogDurationMs[]; +ASH_PUBLIC_EXPORT extern const char kUserWallpaperInfo[]; ASH_PUBLIC_EXPORT extern const char kWallpaperColors[]; ASH_PUBLIC_EXPORT extern const char kUserBluetoothAdapterEnabled[];
diff --git a/ash/shell.cc b/ash/shell.cc index b4560b2..3a74570 100644 --- a/ash/shell.cc +++ b/ash/shell.cc
@@ -1103,11 +1103,6 @@ if (config != Config::MASH) virtual_keyboard_controller_.reset(new VirtualKeyboardController); - // Initialize the wallpaper after the RootWindowController has been created, - // otherwise the widget will not paint when restoring after a browser crash. - // Also, initialize after display initialization to ensure correct sizing. - wallpaper_delegate_->InitializeWallpaper(); - if (cursor_manager_) { if (initially_hide_cursor_) cursor_manager_->HideCursor();
diff --git a/ash/system/screen_layout_observer.cc b/ash/system/screen_layout_observer.cc index 076fe9ac..30ddeca 100644 --- a/ash/system/screen_layout_observer.cc +++ b/ash/system/screen_layout_observer.cc
@@ -69,7 +69,9 @@ } // Callback to handle a user selecting the notification view. -void OpenSettingsFromNotification() { +void OpenSettingsFromNotification(base::Optional<int> button_index) { + DCHECK(!button_index); + Shell::Get()->metrics()->RecordUserMetricsAction( UMA_STATUS_AREA_DISPLAY_NOTIFICATION_SELECTED); // Settings may be blocked, e.g. at the lock screen. @@ -358,7 +360,7 @@ message_center::NotifierId::SYSTEM_COMPONENT, system_notifier::kNotifierDisplay), message_center::RichNotificationData(), - new message_center::HandleNotificationClickedDelegate( + new message_center::HandleNotificationClickDelegate( base::Bind(&OpenSettingsFromNotification)), kNotificationScreenIcon, message_center::SystemNotificationWarningLevel::NORMAL);
diff --git a/ash/wallpaper/wallpaper_controller.cc b/ash/wallpaper/wallpaper_controller.cc index d45cd2c4..3783dd1 100644 --- a/ash/wallpaper/wallpaper_controller.cc +++ b/ash/wallpaper/wallpaper_controller.cc
@@ -25,6 +25,7 @@ #include "base/command_line.h" #include "base/logging.h" #include "base/sequenced_task_runner.h" +#include "base/strings/string_number_conversions.h" #include "base/task_scheduler/post_task.h" #include "base/values.h" #include "components/prefs/pref_registry_simple.h" @@ -43,11 +44,18 @@ using color_utils::LumaRange; using color_utils::SaturationRange; using wallpaper::ColorProfileType; +using wallpaper::WallpaperInfo; namespace ash { namespace { +// Names of nodes with wallpaper info in |kUserWallpaperInfo| dictionary. +const char kNewWallpaperDateNodeName[] = "date"; +const char kNewWallpaperLayoutNodeName[] = "layout"; +const char kNewWallpaperLocationNodeName[] = "file"; +const char kNewWallpaperTypeNodeName[] = "type"; + // How long to wait reloading the wallpaper after the display size has changed. constexpr int kWallpaperReloadDelayMs = 100; @@ -57,10 +65,9 @@ // Caches color calculation results in local state pref service. void CacheProminentColors(const std::vector<SkColor>& colors, const std::string& current_location) { - // Local state can be null during startup. - if (!Shell::Get()->GetLocalStatePrefService()) { + // Local state can be null in tests. + if (!Shell::Get()->GetLocalStatePrefService()) return; - } DictionaryPrefUpdate wallpaper_colors_update( Shell::Get()->GetLocalStatePrefService(), prefs::kWallpaperColors); auto wallpaper_colors = std::make_unique<base::ListValue>(); @@ -76,7 +83,7 @@ const std::string& current_location) { base::Optional<std::vector<SkColor>> cached_colors_out; const base::ListValue* prominent_colors = nullptr; - // Local state can be null during startup. + // Local state can be null in tests. if (!Shell::Get()->GetLocalStatePrefService() || !Shell::Get() ->GetLocalStatePrefService() @@ -185,7 +192,8 @@ // static void WallpaperController::RegisterLocalStatePrefs( PrefRegistrySimple* registry) { - registry->RegisterForeignPref(prefs::kWallpaperColors); + registry->RegisterDictionaryPref(prefs::kUserWallpaperInfo); + registry->RegisterDictionaryPref(prefs::kWallpaperColors); } void WallpaperController::BindRequest( @@ -226,9 +234,8 @@ return wallpaper::WALLPAPER_LAYOUT_CENTER_CROPPED; } -void WallpaperController::SetWallpaperImage( - const gfx::ImageSkia& image, - const wallpaper::WallpaperInfo& info) { +void WallpaperController::SetWallpaperImage(const gfx::ImageSkia& image, + const WallpaperInfo& info) { wallpaper::WallpaperLayout layout = info.layout; VLOG(1) << "SetWallpaper: image_id=" << wallpaper::WallpaperResizer::GetImageId(image) @@ -254,6 +261,7 @@ observer.OnWallpaperDataChanged(); wallpaper_mode_ = WALLPAPER_IMAGE; InstallDesktopControllerForAllWindows(); + wallpaper_count_for_testing_++; } void WallpaperController::CreateEmptyWallpaper() { @@ -297,7 +305,7 @@ void WallpaperController::OnLocalStatePrefServiceInitialized( PrefService* pref_service) { - CalculateWallpaperColors(); + Shell::Get()->wallpaper_delegate()->InitializeWallpaper(); } void WallpaperController::OnSessionStateChanged( @@ -387,6 +395,134 @@ switches::kAshDisableLoginDimAndBlur); } +void WallpaperController::SetUserWallpaperInfo(const AccountId& account_id, + const WallpaperInfo& info, + bool is_persistent) { + current_user_wallpaper_info_ = info; + if (!is_persistent) + return; + + PrefService* local_state = Shell::Get()->GetLocalStatePrefService(); + // Local state can be null in tests. + if (!local_state) + return; + WallpaperInfo old_info; + if (GetUserWallpaperInfo(account_id, &old_info, is_persistent)) { + // Remove the color cache of the previous wallpaper if it exists. + DictionaryPrefUpdate wallpaper_colors_update(local_state, + prefs::kWallpaperColors); + wallpaper_colors_update->RemoveWithoutPathExpansion(old_info.location, + nullptr); + } + DictionaryPrefUpdate wallpaper_update(local_state, prefs::kUserWallpaperInfo); + + auto wallpaper_info_dict = std::make_unique<base::DictionaryValue>(); + wallpaper_info_dict->SetString( + kNewWallpaperDateNodeName, + base::Int64ToString(info.date.ToInternalValue())); + wallpaper_info_dict->SetString(kNewWallpaperLocationNodeName, info.location); + wallpaper_info_dict->SetInteger(kNewWallpaperLayoutNodeName, info.layout); + wallpaper_info_dict->SetInteger(kNewWallpaperTypeNodeName, info.type); + wallpaper_update->SetWithoutPathExpansion(account_id.GetUserEmail(), + std::move(wallpaper_info_dict)); +} + +bool WallpaperController::GetUserWallpaperInfo(const AccountId& account_id, + WallpaperInfo* info, + bool is_persistent) { + if (!is_persistent) { + // Default to the values cached in memory. + *info = current_user_wallpaper_info_; + + // Ephemeral users do not save anything to local state. But we have got + // wallpaper info from memory. Returns true. + return true; + } + + PrefService* local_state = Shell::Get()->GetLocalStatePrefService(); + // Local state can be null in tests. + if (!local_state) + return false; + const base::DictionaryValue* info_dict; + if (!local_state->GetDictionary(prefs::kUserWallpaperInfo) + ->GetDictionaryWithoutPathExpansion(account_id.GetUserEmail(), + &info_dict)) { + return false; + } + + // Use temporary variables to keep |info| untouched in the error case. + std::string location; + if (!info_dict->GetString(kNewWallpaperLocationNodeName, &location)) + return false; + int layout; + if (!info_dict->GetInteger(kNewWallpaperLayoutNodeName, &layout)) + return false; + int type; + if (!info_dict->GetInteger(kNewWallpaperTypeNodeName, &type)) + return false; + std::string date_string; + if (!info_dict->GetString(kNewWallpaperDateNodeName, &date_string)) + return false; + int64_t date_val; + if (!base::StringToInt64(date_string, &date_val)) + return false; + + info->location = location; + info->layout = static_cast<wallpaper::WallpaperLayout>(layout); + info->type = static_cast<wallpaper::WallpaperType>(type); + info->date = base::Time::FromInternalValue(date_val); + return true; +} + +void WallpaperController::RemoveUserWallpaperInfo(const AccountId& account_id, + bool is_persistent) { + if (wallpaper_cache_map_.find(account_id) != wallpaper_cache_map_.end()) + wallpaper_cache_map_.erase(account_id); + + PrefService* local_state = Shell::Get()->GetLocalStatePrefService(); + // Local state can be null in tests. + if (!local_state) + return; + WallpaperInfo info; + GetUserWallpaperInfo(account_id, &info, is_persistent); + DictionaryPrefUpdate prefs_wallpapers_info_update(local_state, + prefs::kUserWallpaperInfo); + prefs_wallpapers_info_update->RemoveWithoutPathExpansion( + account_id.GetUserEmail(), nullptr); + // Remove the color cache of the previous wallpaper if it exists. + DictionaryPrefUpdate wallpaper_colors_update(local_state, + prefs::kWallpaperColors); + wallpaper_colors_update->RemoveWithoutPathExpansion(info.location, nullptr); +} + +bool WallpaperController::GetWallpaperFromCache(const AccountId& account_id, + gfx::ImageSkia* image) { + CustomWallpaperMap::const_iterator it = wallpaper_cache_map_.find(account_id); + if (it != wallpaper_cache_map_.end() && !it->second.second.isNull()) { + *image = it->second.second; + return true; + } + return false; +} + +bool WallpaperController::GetPathFromCache(const AccountId& account_id, + base::FilePath* path) { + CustomWallpaperMap::const_iterator it = wallpaper_cache_map_.find(account_id); + if (it != wallpaper_cache_map_.end()) { + *path = (*it).second.first; + return true; + } + return false; +} + +wallpaper::WallpaperInfo* WallpaperController::GetCurrentUserWallpaperInfo() { + return ¤t_user_wallpaper_info_; +} + +CustomWallpaperMap* WallpaperController::GetWallpaperCacheMap() { + return &wallpaper_cache_map_; +} + void WallpaperController::SetClient( mojom::WallpaperControllerClientPtr client) { wallpaper_controller_client_ = std::move(client); @@ -409,7 +545,28 @@ const std::string& url, wallpaper::WallpaperLayout layout, bool show_wallpaper) { - NOTIMPLEMENTED(); + DCHECK(Shell::Get()->session_controller()->IsActiveUserSessionStarted()); + + // There is no visible wallpaper in kiosk mode. + base::Optional<user_manager::UserType> user_type = + Shell::Get()->session_controller()->GetUserType(); + if (!user_type || *user_type == user_manager::USER_TYPE_KIOSK_APP) + return; + + WallpaperInfo info = {url, layout, wallpaper::ONLINE, + base::Time::Now().LocalMidnight()}; + SetUserWallpaperInfo(user_info->account_id, info, !user_info->is_ephemeral); + + if (show_wallpaper) { + // TODO(crbug.com/776464): This should ideally go through PendingWallpaper. + SetWallpaper(image, info); + } + + // Leave the file path empty, because in most cases the file path is not used + // when fetching cache, but in case it needs to be checked, we should avoid + // confusing the URL with a real file path. + wallpaper_cache_map_[user_info->account_id] = CustomWallpaperElement( + base::FilePath(), gfx::ImageSkia::CreateFrom1xBitmap(image)); } void WallpaperController::SetDefaultWallpaper( @@ -440,7 +597,7 @@ } void WallpaperController::SetWallpaper(const SkBitmap& wallpaper, - const wallpaper::WallpaperInfo& info) { + const WallpaperInfo& info) { if (wallpaper.isNull()) return; SetWallpaperImage(gfx::ImageSkia::CreateFrom1xBitmap(wallpaper), info); @@ -467,6 +624,8 @@ void WallpaperController::OnColorCalculationComplete() { const std::vector<SkColor> colors = color_calculator_->prominent_colors(); color_calculator_.reset(); + // TODO(crbug.com/787134): The prominent colors of wallpapers with empty + // location should be cached as well. if (!current_location_.empty()) CacheProminentColors(colors, current_location_); SetProminentColors(colors);
diff --git a/ash/wallpaper/wallpaper_controller.h b/ash/wallpaper/wallpaper_controller.h index 80ecc31..e225fb5 100644 --- a/ash/wallpaper/wallpaper_controller.h +++ b/ash/wallpaper/wallpaper_controller.h
@@ -12,6 +12,7 @@ #include "ash/public/interfaces/wallpaper.mojom.h" #include "ash/session/session_observer.h" #include "ash/shell_observer.h" +#include "base/files/file_path.h" #include "base/memory/ref_counted.h" #include "base/observer_list.h" #include "base/timer/timer.h" @@ -21,6 +22,7 @@ #include "mojo/public/cpp/bindings/binding_set.h" #include "mojo/public/cpp/bindings/interface_ptr_set.h" #include "ui/compositor/compositor_lock.h" +#include "ui/gfx/image/image_skia.h" class PrefRegistrySimple; @@ -41,6 +43,12 @@ class WallpaperControllerObserver; +// The |CustomWallpaperElement| contains |first| the path of the image which +// is currently being loaded and or in progress of being loaded and |second| +// the image itself. +using CustomWallpaperElement = std::pair<base::FilePath, gfx::ImageSkia>; +using CustomWallpaperMap = std::map<AccountId, CustomWallpaperElement>; + // Controls the desktop background wallpaper: // - Sets a wallpaper image and layout; // - Handles display change (add/remove display, configuration change etc); @@ -137,6 +145,39 @@ // Returns whether the current wallpaper is blurred. bool IsWallpaperBlurred() const { return is_wallpaper_blurred_; } + // TODO(crbug.com/776464): Make this private. WallpaperInfo should be an + // internal concept. In addition, change |is_persistent| to |is_ephemeral| to + // be consistent with |mojom::WallpaperUserInfo|. + // Sets wallpaper info for |account_id| and saves it to local state if + // |is_persistent| is true. + void SetUserWallpaperInfo(const AccountId& account_id, + const wallpaper::WallpaperInfo& info, + bool is_persistent); + + // Gets wallpaper info of |account_id| from local state, or memory if + // |is_persistent| is false. Returns false if wallpaper info is not found. + bool GetUserWallpaperInfo(const AccountId& account_id, + wallpaper::WallpaperInfo* info, + bool is_persistent); + + // Removes |account_id|'s wallpaper info and color cache if it exists. + void RemoveUserWallpaperInfo(const AccountId& account_id, bool is_persistent); + + // Gets encoded wallpaper from cache. Returns true if success. + bool GetWallpaperFromCache(const AccountId& account_id, + gfx::ImageSkia* image); + + // Gets path of encoded wallpaper from cache. Returns true if success. + bool GetPathFromCache(const AccountId& account_id, base::FilePath* path); + + // TODO(crbug.com/776464): Remove this after WallpaperManager is removed. + // Returns the pointer of |current_user_wallpaper_info_|. + wallpaper::WallpaperInfo* GetCurrentUserWallpaperInfo(); + + // TODO(crbug.com/776464): Remove this after WallpaperManager is removed. + // Returns the pointer of |wallpaper_cache_map_|. + CustomWallpaperMap* GetWallpaperCacheMap(); + // mojom::WallpaperController overrides: void SetClient(mojom::WallpaperControllerClientPtr client) override; void SetCustomWallpaper(mojom::WallpaperUserInfoPtr user_info, @@ -254,6 +295,12 @@ // Caches the color profiles that need to do wallpaper color extracting. const std::vector<color_utils::ColorProfile> color_profiles_; + // Cached logged-in user wallpaper info. + wallpaper::WallpaperInfo current_user_wallpaper_info_; + + // Cached wallpapers of users. + CustomWallpaperMap wallpaper_cache_map_; + // Location (see WallpaperInfo::location) used by the current wallpaper. // Used as a key for storing |prominent_colors_| in the // wallpaper::kWallpaperColors pref. An empty string disables color caching. @@ -273,6 +320,9 @@ std::unique_ptr<ui::CompositorLock> compositor_lock_; + // Tracks how many wallpapers have been set, for testing purpose. + int wallpaper_count_for_testing_ = 0; + DISALLOW_COPY_AND_ASSIGN(WallpaperController); };
diff --git a/ash/wallpaper/wallpaper_controller_unittest.cc b/ash/wallpaper/wallpaper_controller_unittest.cc index f8745778..ee12d9a 100644 --- a/ash/wallpaper/wallpaper_controller_unittest.cc +++ b/ash/wallpaper/wallpaper_controller_unittest.cc
@@ -32,6 +32,7 @@ #include "ui/gfx/canvas.h" #include "ui/views/widget/widget.h" +using wallpaper::WallpaperLayout; using wallpaper::WALLPAPER_LAYOUT_CENTER; using wallpaper::WALLPAPER_LAYOUT_CENTER_CROPPED; using wallpaper::WALLPAPER_LAYOUT_STRETCH; @@ -240,15 +241,36 @@ // Helper function to create a |WallpaperInfo| struct with dummy values // given the desired layout. - wallpaper::WallpaperInfo CreateWallpaperInfo( - wallpaper::WallpaperLayout layout) { + wallpaper::WallpaperInfo CreateWallpaperInfo(WallpaperLayout layout) { return wallpaper::WallpaperInfo("", layout, wallpaper::DEFAULT, base::Time::Now().LocalMidnight()); } + // Helper function to create a new |mojom::WallpaperUserInfoPtr| instance with + // default values. In addition, remove the previous wallpaper info (if any) + // and clear the wallpaper count. May be called multiple times for the + // same |account_id|. + mojom::WallpaperUserInfoPtr InitializeUser(const AccountId& account_id) { + mojom::WallpaperUserInfoPtr wallpaper_user_info = + mojom::WallpaperUserInfo::New(); + wallpaper_user_info->account_id = account_id; + wallpaper_user_info->type = user_manager::USER_TYPE_REGULAR; + wallpaper_user_info->is_ephemeral = false; + wallpaper_user_info->has_gaia_account = true; + + controller_->RemoveUserWallpaperInfo(account_id, + !wallpaper_user_info->is_ephemeral); + controller_->current_user_wallpaper_info_ = wallpaper::WallpaperInfo(); + controller_->wallpaper_count_for_testing_ = 0; + + return wallpaper_user_info; + } + // Wrapper for private ShouldCalculateColors() bool ShouldCalculateColors() { return controller_->ShouldCalculateColors(); } + int GetWallpaperCount() { return controller_->wallpaper_count_for_testing_; } + WallpaperController* controller_; // Not owned. TestWallpaperDelegate* wallpaper_delegate_; @@ -592,4 +614,99 @@ EXPECT_EQ(2, observer.wallpaper_colors_changed_count()); } +TEST_F(WallpaperControllerTest, SetOnlineWallpaper) { + gfx::ImageSkia image = CreateImage(640, 480, kCustomWallpaperColor); + const std::string url = "dummy_url"; + const std::string user_email = "user@test.com"; + const AccountId account_id = AccountId::FromUserEmail(user_email); + WallpaperLayout layout = WALLPAPER_LAYOUT_CENTER; + + SimulateUserLogin(user_email); + + // Verify the wallpaper is set successfully and wallpaper info is updated. + mojom::WallpaperUserInfoPtr wallpaper_user_info = InitializeUser(account_id); + controller_->SetOnlineWallpaper(std::move(wallpaper_user_info), + *image.bitmap(), url, layout, + true /* show_wallpaper */); + RunAllTasksUntilIdle(); + EXPECT_EQ(1, GetWallpaperCount()); + wallpaper::WallpaperInfo wallpaper_info; + EXPECT_TRUE(controller_->GetUserWallpaperInfo(account_id, &wallpaper_info, + true /* is_persistent */)); + wallpaper::WallpaperInfo expected_wallpaper_info( + url, layout, wallpaper::ONLINE, base::Time::Now().LocalMidnight()); + EXPECT_EQ(wallpaper_info, expected_wallpaper_info); + + // Verify that the wallpaper is not set when |show_wallpaper| is false, but + // wallpaper info is updated properly. + wallpaper_user_info = InitializeUser(account_id); + controller_->SetOnlineWallpaper(std::move(wallpaper_user_info), + *image.bitmap(), url, layout, + false /* show_wallpaper */); + RunAllTasksUntilIdle(); + EXPECT_EQ(0, GetWallpaperCount()); + EXPECT_TRUE(controller_->GetUserWallpaperInfo(account_id, &wallpaper_info, + true /* is_persistent */)); + EXPECT_EQ(wallpaper_info, expected_wallpaper_info); +} + +TEST_F(WallpaperControllerTest, IgnoreWallpaperRequestInKioskMode) { + gfx::ImageSkia image = CreateImage(640, 480, kCustomWallpaperColor); + const std::string kiosk_app = "kiosk"; + const AccountId account_id = AccountId::FromUserEmail("user@test.com"); + + // Simulate kiosk login. + TestSessionControllerClient* session = GetSessionControllerClient(); + session->AddUserSession(kiosk_app, user_manager::USER_TYPE_KIOSK_APP); + session->SwitchActiveUser(AccountId::FromUserEmail(kiosk_app)); + session->SetSessionState(SessionState::ACTIVE); + + // Verify that the wallpaper request is ignored in kiosk mode, and + // |account_id|'s wallpaper info is not updated. + controller_->SetOnlineWallpaper(InitializeUser(account_id), *image.bitmap(), + "dummy_url", WALLPAPER_LAYOUT_CENTER, + true /* show_wallpaper */); + RunAllTasksUntilIdle(); + EXPECT_EQ(0, GetWallpaperCount()); + wallpaper::WallpaperInfo wallpaper_info; + EXPECT_FALSE(controller_->GetUserWallpaperInfo(account_id, &wallpaper_info, + true /* is_persistent */)); +} + +TEST_F(WallpaperControllerTest, VerifyWallpaperCache) { + gfx::ImageSkia image = CreateImage(640, 480, kCustomWallpaperColor); + const std::string user1 = "user1@test.com"; + + SimulateUserLogin(user1); + + // |user1| doesn't have wallpaper cache in the beginning. + gfx::ImageSkia cached_wallpaper; + EXPECT_FALSE(controller_->GetWallpaperFromCache( + AccountId::FromUserEmail(user1), &cached_wallpaper)); + base::FilePath path; + EXPECT_FALSE( + controller_->GetPathFromCache(AccountId::FromUserEmail(user1), &path)); + + // Verify |SetOnlineWallpaper| updates wallpaper cache for |user1|. + mojom::WallpaperUserInfoPtr wallpaper_user_info = + InitializeUser(AccountId::FromUserEmail(user1)); + controller_->SetOnlineWallpaper( + std::move(wallpaper_user_info), *image.bitmap(), "dummy_file_location", + WALLPAPER_LAYOUT_CENTER, true /* show_wallpaper */); + RunAllTasksUntilIdle(); + EXPECT_TRUE(controller_->GetWallpaperFromCache( + AccountId::FromUserEmail(user1), &cached_wallpaper)); + EXPECT_TRUE( + controller_->GetPathFromCache(AccountId::FromUserEmail(user1), &path)); + + // After |user2| is logged in, |user1|'s wallpaper cache should still be kept + // (crbug.com/339576). Note the active user is still |user1|. + TestSessionControllerClient* session = GetSessionControllerClient(); + session->AddUserSession("user2@test.com"); + EXPECT_TRUE(controller_->GetWallpaperFromCache( + AccountId::FromUserEmail(user1), &cached_wallpaper)); + EXPECT_TRUE( + controller_->GetPathFromCache(AccountId::FromUserEmail(user1), &path)); +} + } // namespace ash
diff --git a/chrome/browser/android/vr_shell/BUILD.gn b/chrome/browser/android/vr_shell/BUILD.gn index 4e51490..00febf3 100644 --- a/chrome/browser/android/vr_shell/BUILD.gn +++ b/chrome/browser/android/vr_shell/BUILD.gn
@@ -20,6 +20,8 @@ "autocomplete_controller.cc", "autocomplete_controller.h", "gl_browser_interface.h", + "gvr_keyboard_delegate.cc", + "gvr_keyboard_delegate.h", "gvr_keyboard_shim.cc", "gvr_util.cc", "gvr_util.h",
diff --git a/chrome/browser/android/vr_shell/gvr_keyboard_delegate.cc b/chrome/browser/android/vr_shell/gvr_keyboard_delegate.cc new file mode 100644 index 0000000..a4467b3 --- /dev/null +++ b/chrome/browser/android/vr_shell/gvr_keyboard_delegate.cc
@@ -0,0 +1,183 @@ +// 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/android/vr_shell/gvr_keyboard_delegate.h" + +#include "base/bind.h" +#include "base/memory/ptr_util.h" +#include "base/strings/utf_string_conversions.h" +#include "chrome/browser/android/vr_shell/gvr_util.h" +#include "chrome/browser/vr/model/camera_model.h" +#include "chrome/browser/vr/model/text_input_info.h" +#include "third_party/gvr-android-sdk/src/libraries/headers/vr/gvr/capi/include/gvr.h" +#include "third_party/gvr-android-sdk/src/libraries/headers/vr/gvr/capi/include/gvr_types.h" +#include "ui/gfx/geometry/point3_f.h" +#include "ui/gfx/geometry/vector3d_f.h" + +namespace vr_shell { + +namespace { + +void OnKeyboardEvent(void* closure, GvrKeyboardDelegate::EventType event) { + auto* callback = + reinterpret_cast<GvrKeyboardDelegate::OnEventCallback*>(closure); + if (callback) + callback->Run(event); +} + +} // namespace + +std::unique_ptr<GvrKeyboardDelegate> GvrKeyboardDelegate::Create() { + auto delegate = base::WrapUnique(new GvrKeyboardDelegate()); + void* callback = reinterpret_cast<void*>(&delegate->keyboard_event_callback_); + auto* gvr_keyboard = gvr_keyboard_create(callback, OnKeyboardEvent); + if (!gvr_keyboard) + return nullptr; + delegate->Init(gvr_keyboard); + return delegate; +} + +GvrKeyboardDelegate::GvrKeyboardDelegate() { + keyboard_event_callback_ = base::BindRepeating( + &GvrKeyboardDelegate::OnGvrKeyboardEvent, base::Unretained(this)); +} + +void GvrKeyboardDelegate::Init(gvr_keyboard_context* keyboard_context) { + DCHECK(keyboard_context); + gvr_keyboard_ = keyboard_context; + + gvr_mat4f matrix; + gvr_keyboard_get_recommended_world_from_keyboard_matrix(2.0f, &matrix); + gvr_keyboard_set_world_from_keyboard_matrix(gvr_keyboard_, &matrix); +} + +GvrKeyboardDelegate::~GvrKeyboardDelegate() { + if (gvr_keyboard_) + gvr_keyboard_destroy(&gvr_keyboard_); +} + +void GvrKeyboardDelegate::SetController(VrController* controller) { + controller_ = controller; +} + +void GvrKeyboardDelegate::SetUiInterface(vr::KeyboardUiInterface* ui) { + ui_ = ui; +} + +void GvrKeyboardDelegate::OnBeginFrame() { + gvr::ClockTimePoint target_time = gvr::GvrApi::GetTimePointNow(); + gvr_keyboard_set_frame_time(gvr_keyboard_, &target_time); + gvr_keyboard_advance_frame(gvr_keyboard_); + + if (controller_) { + bool pressed = controller_->ButtonUpHappened( + gvr::ControllerButton::GVR_CONTROLLER_BUTTON_CLICK); + gvr_keyboard_update_button_state( + gvr_keyboard_, gvr::ControllerButton::GVR_CONTROLLER_BUTTON_CLICK, + pressed); + } +} + +void GvrKeyboardDelegate::ShowKeyboard() { + gvr_keyboard_show(gvr_keyboard_); +} + +void GvrKeyboardDelegate::HideKeyboard() { + gvr_keyboard_hide(gvr_keyboard_); +} + +void GvrKeyboardDelegate::SetTransform(const gfx::Transform& transform) { + gvr_mat4f matrix; + TransformToGvrMat(transform, &matrix); + gvr_keyboard_set_world_from_keyboard_matrix(gvr_keyboard_, &matrix); +} + +bool GvrKeyboardDelegate::HitTest(const gfx::Point3F& ray_origin, + const gfx::Point3F& ray_target, + gfx::Point3F* hit_position) { + gvr_vec3f start; + start.x = ray_origin.x(); + start.y = ray_origin.y(); + start.z = ray_origin.z(); + gvr_vec3f end; + end.x = ray_target.x(); + end.y = ray_target.y(); + end.z = ray_target.z(); + gvr_vec3f hit_point; + bool hits = gvr_keyboard_update_controller_ray(gvr_keyboard_, &start, &end, + &hit_point); + if (hits) + hit_position->SetPoint(hit_point.x, hit_point.y, hit_point.z); + return hits; +} + +void GvrKeyboardDelegate::Draw(const vr::CameraModel& model) { + int eye = model.eye_type; + gvr::Mat4f view_matrix; + TransformToGvrMat(model.view_matrix, &view_matrix); + gvr_keyboard_set_eye_from_world_matrix(gvr_keyboard_, eye, &view_matrix); + + gvr::Mat4f proj_matrix; + TransformToGvrMat(model.proj_matrix, &proj_matrix); + gvr_keyboard_set_projection_matrix(gvr_keyboard_, eye, &proj_matrix); + + gfx::Rect viewport_rect = model.viewport; + const gvr::Recti viewport = {viewport_rect.x(), viewport_rect.right(), + viewport_rect.y(), viewport_rect.bottom()}; + gvr_keyboard_set_viewport(gvr_keyboard_, eye, &viewport); + gvr_keyboard_render(gvr_keyboard_, eye); +} + +void GvrKeyboardDelegate::UpdateInput(const vr::TextInputInfo& info) { + gvr_keyboard_set_text(gvr_keyboard_, base::UTF16ToUTF8(info.text).c_str()); + gvr_keyboard_set_selection_indices(gvr_keyboard_, info.selection_start, + info.selection_end); +} + +void GvrKeyboardDelegate::OnGvrKeyboardEvent(EventType event) { + DCHECK(ui_ != nullptr); + switch (event) { + case GVR_KEYBOARD_ERROR_UNKNOWN: + LOG(ERROR) << "Unknown GVR keyboard error."; + break; + case GVR_KEYBOARD_ERROR_SERVICE_NOT_CONNECTED: + LOG(ERROR) << "GVR keyboard service not connected."; + break; + case GVR_KEYBOARD_ERROR_NO_LOCALES_FOUND: + LOG(ERROR) << "No GVR keyboard locales found."; + break; + case GVR_KEYBOARD_ERROR_SDK_LOAD_FAILED: + LOG(ERROR) << "GVR keyboard sdk load failed."; + break; + case GVR_KEYBOARD_SHOWN: + break; + case GVR_KEYBOARD_HIDDEN: + ui_->OnKeyboardHidden(); + break; + case GVR_KEYBOARD_TEXT_UPDATED: + ui_->OnInputEdited(GetTextInfo()); + break; + case GVR_KEYBOARD_TEXT_COMMITTED: + ui_->OnInputCommitted(GetTextInfo()); + break; + } +} + +vr::TextInputInfo GvrKeyboardDelegate::GetTextInfo() { + vr::TextInputInfo info; + // Get text. Note that we wrap the text in a unique ptr since we're + // responsible for freeing the memory allocated by gvr_keyboard_get_text. + std::unique_ptr<char, decltype(std::free)*> scoped_text{ + gvr_keyboard_get_text(gvr_keyboard_), std::free}; + std::string text(scoped_text.get()); + info.text = base::UTF8ToUTF16(text); + // Get selection indices. + size_t start, end; + gvr_keyboard_get_selection_indices(gvr_keyboard_, &start, &end); + info.selection_start = start; + info.selection_end = end; + return info; +} + +} // namespace vr_shell
diff --git a/chrome/browser/android/vr_shell/gvr_keyboard_delegate.h b/chrome/browser/android/vr_shell/gvr_keyboard_delegate.h new file mode 100644 index 0000000..7a3ffeff --- /dev/null +++ b/chrome/browser/android/vr_shell/gvr_keyboard_delegate.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_ANDROID_VR_SHELL_GVR_KEYBOARD_DELEGATE_H_ +#define CHROME_BROWSER_ANDROID_VR_SHELL_GVR_KEYBOARD_DELEGATE_H_ + +#include "base/callback.h" +#include "base/macros.h" +#include "chrome/browser/android/vr_shell/vr_controller.h" +#include "chrome/browser/vr/keyboard_delegate.h" +#include "chrome/browser/vr/keyboard_ui_interface.h" +#include "third_party/gvr-android-keyboard/src/libraries/headers/vr/gvr/capi/include/gvr_keyboard.h" + +namespace vr { +struct TextInputInfo; +} + +namespace vr_shell { + +class GvrKeyboardDelegate : public vr::KeyboardDelegate { + public: + // Constructs a GvrKeyboardDelegate by dynamically loading the GVR keyboard + // api. A null pointer is returned upon failure. + static std::unique_ptr<GvrKeyboardDelegate> Create(); + ~GvrKeyboardDelegate() override; + + void SetController(VrController* controller); + void SetUiInterface(vr::KeyboardUiInterface* ui); + + typedef int32_t EventType; + typedef base::RepeatingCallback<void(EventType)> OnEventCallback; + + // vr::KeyboardDelegate implementation. + void OnBeginFrame() override; + void ShowKeyboard() override; + void HideKeyboard() override; + void SetTransform(const gfx::Transform& transform) override; + bool HitTest(const gfx::Point3F& ray_origin, + const gfx::Point3F& ray_target, + gfx::Point3F* hit_position) override; + void Draw(const vr::CameraModel& model) override; + + // Called to update GVR keyboard with the given text input info. + void UpdateInput(const vr::TextInputInfo& info); + + private: + GvrKeyboardDelegate(); + void Init(gvr_keyboard_context* keyboard_context); + void OnGvrKeyboardEvent(EventType); + vr::TextInputInfo GetTextInfo(); + + VrController* controller_; + vr::KeyboardUiInterface* ui_; + gvr_keyboard_context* gvr_keyboard_ = nullptr; + OnEventCallback keyboard_event_callback_; + + DISALLOW_COPY_AND_ASSIGN(GvrKeyboardDelegate); +}; + +} // namespace vr_shell + +#endif // CHROME_BROWSER_ANDROID_VR_SHELL_GVR_KEYBOARD_DELEGATE_H_
diff --git a/chrome/browser/android/vr_shell/gvr_util.cc b/chrome/browser/android/vr_shell/gvr_util.cc index e78198e..d90d2b0 100644 --- a/chrome/browser/android/vr_shell/gvr_util.cc +++ b/chrome/browser/android/vr_shell/gvr_util.cc
@@ -112,4 +112,20 @@ gvr::Rectf{left_degrees, right_degrees, bottom_degrees, top_degrees}; } +void TransformToGvrMat(const gfx::Transform& in, gvr::Mat4f* out) { + for (int i = 0; i < 4; ++i) { + for (int j = 0; j < 4; ++j) { + out->m[i][j] = in.matrix().get(i, j); + } + } +} + +void GvrMatToTransform(const gvr::Mat4f& in, gfx::Transform* out) { + for (int i = 0; i < 4; ++i) { + for (int j = 0; j < 4; ++j) { + out->matrix().set(i, j, in.m[i][j]); + } + } +} + } // namespace vr_shell
diff --git a/chrome/browser/android/vr_shell/gvr_util.h b/chrome/browser/android/vr_shell/gvr_util.h index ef28479..535c6e0 100644 --- a/chrome/browser/android/vr_shell/gvr_util.h +++ b/chrome/browser/android/vr_shell/gvr_util.h
@@ -39,6 +39,12 @@ float z_near, gvr::Rectf* out_fov); +// Transforms the given gfx::Transform to gvr::Mat4f. +void TransformToGvrMat(const gfx::Transform& in, gvr::Mat4f* out); + +// Transforms the given vr::Mat4f to gfx::Transform. +void GvrMatToTransform(const gvr::Mat4f& in, gfx::Transform* out); + } // namespace vr_shell #endif // CHROME_BROWSER_ANDROID_VR_SHELL_GVR_UTIL_H_
diff --git a/chrome/browser/android/vr_shell/vr_gl_thread.cc b/chrome/browser/android/vr_shell/vr_gl_thread.cc index 13eed5e..6bf7d72c 100644 --- a/chrome/browser/android/vr_shell/vr_gl_thread.cc +++ b/chrome/browser/android/vr_shell/vr_gl_thread.cc
@@ -14,6 +14,7 @@ #include "chrome/browser/vr/model/omnibox_suggestions.h" #include "chrome/browser/vr/model/toolbar_state.h" #include "chrome/browser/vr/ui.h" +#include "chrome/common/chrome_features.h" #include "third_party/skia/include/core/SkBitmap.h" namespace vr_shell { @@ -42,10 +43,31 @@ } void VrGLThread::Init() { - auto ui = base::MakeUnique<vr::Ui>(this, this, ui_initial_state_); + bool keyboard_enabled = + base::FeatureList::IsEnabled(features::kVrBrowserKeyboard); + if (keyboard_enabled) { + keyboard_delegate_ = GvrKeyboardDelegate::Create(); + text_input_delegate_ = base::MakeUnique<vr::TextInputDelegate>(); + } + auto* keyboard_delegate = + !keyboard_delegate_ ? nullptr : keyboard_delegate_.get(); + auto ui = + base::MakeUnique<vr::Ui>(this, this, keyboard_delegate, + text_input_delegate_.get(), ui_initial_state_); + if (keyboard_enabled) { + text_input_delegate_->SetRequestFocusCallback( + base::BindRepeating(&vr::Ui::RequestFocus, base::Unretained(ui.get()))); + if (keyboard_delegate) { + keyboard_delegate_->SetUiInterface(ui.get()); + text_input_delegate_->SetUpdateInputCallback( + base::BindRepeating(&GvrKeyboardDelegate::UpdateInput, + base::Unretained(keyboard_delegate_.get()))); + } + } + vr_shell_gl_ = base::MakeUnique<VrShellGl>( this, std::move(ui), gvr_api_, reprojected_rendering_, daydream_support_, - ui_initial_state_.in_web_vr); + ui_initial_state_.in_web_vr, keyboard_delegate_.get()); browser_ui_ = vr_shell_gl_->GetBrowserUiWeakPtr();
diff --git a/chrome/browser/android/vr_shell/vr_gl_thread.h b/chrome/browser/android/vr_shell/vr_gl_thread.h index 6becaed..908280a 100644 --- a/chrome/browser/android/vr_shell/vr_gl_thread.h +++ b/chrome/browser/android/vr_shell/vr_gl_thread.h
@@ -12,8 +12,10 @@ #include "base/memory/weak_ptr.h" #include "base/single_thread_task_runner.h" #include "chrome/browser/android/vr_shell/gl_browser_interface.h" +#include "chrome/browser/android/vr_shell/gvr_keyboard_delegate.h" #include "chrome/browser/vr/browser_ui_interface.h" #include "chrome/browser/vr/content_input_delegate.h" +#include "chrome/browser/vr/text_input_delegate.h" #include "chrome/browser/vr/ui.h" #include "chrome/browser/vr/ui_browser_interface.h" #include "third_party/gvr-android-sdk/src/libraries/headers/vr/gvr/capi/include/gvr_types.h" @@ -101,6 +103,8 @@ // Created on GL thread. std::unique_ptr<VrShellGl> vr_shell_gl_; + std::unique_ptr<GvrKeyboardDelegate> keyboard_delegate_; + std::unique_ptr<vr::TextInputDelegate> text_input_delegate_; base::WeakPtr<VrShell> weak_vr_shell_; base::WeakPtr<vr::BrowserUiInterface> browser_ui_;
diff --git a/chrome/browser/android/vr_shell/vr_shell_gl.cc b/chrome/browser/android/vr_shell/vr_shell_gl.cc index 86d5647..a7f6aac 100644 --- a/chrome/browser/android/vr_shell/vr_shell_gl.cc +++ b/chrome/browser/android/vr_shell/vr_shell_gl.cc
@@ -103,46 +103,6 @@ static constexpr float kRedrawSceneAngleDeltaDegrees = 1.0; -static gvr_keyboard_context* keyboard_context; - -// TODO(ymalik,crbug.com/780318): This callback is temporary until we have an -// editable input field. -void OnKeyboardEvent(void*, int32_t event) { - switch (event) { - case GVR_KEYBOARD_ERROR_UNKNOWN: - LOG(ERROR) << "Unknown GVR keyboard error."; - break; - case GVR_KEYBOARD_ERROR_SERVICE_NOT_CONNECTED: - LOG(ERROR) << "GVR keyboard service not connected."; - break; - case GVR_KEYBOARD_ERROR_NO_LOCALES_FOUND: - LOG(ERROR) << "No GVR keyboard locales found."; - break; - case GVR_KEYBOARD_ERROR_SDK_LOAD_FAILED: - LOG(ERROR) << "GVR keyboard sdk load failed."; - break; - case GVR_KEYBOARD_SHOWN: - DVLOG(1) << "GVR keyboard shown."; - break; - case GVR_KEYBOARD_HIDDEN: - DVLOG(1) << "GVR keyboard hidden."; - break; - case GVR_KEYBOARD_TEXT_UPDATED: { - char* text = gvr_keyboard_get_text(keyboard_context); - DVLOG(1) << "GVR keyboard text updated: " << text; - free(reinterpret_cast<void*>(text)); - } break; - case GVR_KEYBOARD_TEXT_COMMITTED: { - char* text = gvr_keyboard_get_text(keyboard_context); - DVLOG(1) << "GVR keyboard text updated: " << text; - free(reinterpret_cast<void*>(text)); - gvr_keyboard_set_text(keyboard_context, ""); - } break; - default: - NOTREACHED(); - } -} - gfx::Transform PerspectiveMatrixFromView(const gvr::Rectf& fov, float z_near, float z_far) { @@ -175,22 +135,6 @@ return result; } -void TransformToGvrMat(const gfx::Transform& in, gvr::Mat4f* out) { - for (int i = 0; i < 4; ++i) { - for (int j = 0; j < 4; ++j) { - out->m[i][j] = in.matrix().get(i, j); - } - } -} - -void GvrMatToTransform(const gvr::Mat4f& in, gfx::Transform* out) { - for (int i = 0; i < 4; ++i) { - for (int j = 0; j < 4; ++j) { - out->matrix().set(i, j, in.m[i][j]); - } - } -} - gvr::Rectf UVFromGfxRect(gfx::RectF rect) { return {rect.x(), rect.x() + rect.width(), 1.0f - rect.bottom(), 1.0f - rect.y()}; @@ -219,7 +163,8 @@ gvr_context* gvr_api, bool reprojected_rendering, bool daydream_support, - bool start_in_web_vr_mode) + bool start_in_web_vr_mode, + GvrKeyboardDelegate* keyboard_delegate) : ui_(std::move(ui)), web_vr_mode_(start_in_web_vr_mode), surfaceless_rendering_(reprojected_rendering), @@ -227,6 +172,7 @@ task_runner_(base::ThreadTaskRunnerHandle::Get()), binding_(this), browser_(browser_interface), + keyboard_delegate_(keyboard_delegate), fps_meter_(new vr::FPSMeter()), webvr_js_time_(new vr::SlidingTimeDeltaAverage(kWebVRSlidingAverageSize)), webvr_render_time_( @@ -237,9 +183,6 @@ VrShellGl::~VrShellGl() { ClosePresentationBindings(); - if (keyboard_enabled_) { - gvr_keyboard_destroy(&gvr_keyboard_); - } } void VrShellGl::Initialize() { @@ -501,6 +444,8 @@ gvr_api_ = gvr::GvrApi::WrapNonOwned(gvr_api); controller_.reset(new VrController(gvr_api)); ui_->OnPlatformControllerInitialized(controller_.get()); + if (keyboard_delegate_) + keyboard_delegate_->SetController(controller_.get()); VrMetricsUtil::LogVrViewerType(gvr_api_->GetViewerType()); @@ -513,7 +458,6 @@ void VrShellGl::InitializeRenderer() { gvr_api_->InitializeGl(); - CreateKeyboard(); gfx::Transform head_pose; device::GvrDelegate::GetGvrPoseWithNeckModel(gvr_api_.get(), &head_pose); webvr_head_pose_.assign(kPoseRingBufferSize, head_pose); @@ -695,18 +639,6 @@ if (controller_->ButtonUpHappened( gvr::ControllerButton::GVR_CONTROLLER_BUTTON_APP)) { - // TODO(ymalik,crbug.com/780318): We temporarily show and hide the keyboard - // when the app button is pressed. This behavior is behind a runtime enabled - // feature and should go away as soon as we have editable input fields. - show_keyboard_ = keyboard_enabled_ && !show_keyboard_; - if (keyboard_enabled_) { - if (show_keyboard_) { - gvr_keyboard_show(gvr_keyboard_); - } else { - gvr_keyboard_hide(gvr_keyboard_); - } - } - // A gesture is a movement of the controller while holding the App button. // If the angle of the movement is within a threshold, the action is // considered a regular click @@ -955,10 +887,6 @@ // while the splash screen is up ShouldDrawWebVr() will return false. if (!ShouldDrawWebVr()) { ui_->ui_renderer()->Draw(render_info_primary_); - - // Draw keyboard. TODO(ymalik,crbug.com/780135): Keyboard should be a UI - // element and this special rendering logic should move out of here. - DrawKeyboard(); } content_frame_available_ = false; @@ -1039,77 +967,6 @@ } } -void VrShellGl::CreateKeyboard() { - if (gvr_keyboard_) - return; - - keyboard_enabled_ = - base::FeatureList::IsEnabled(features::kVrBrowserKeyboard); - if (!keyboard_enabled_) - return; - - gvr_keyboard_ = gvr_keyboard_create(nullptr, OnKeyboardEvent); - if (!gvr_keyboard_) { - keyboard_enabled_ = false; - return; - } - keyboard_context = gvr_keyboard_; - - gvr_mat4f matrix; - gvr_keyboard_get_recommended_world_from_keyboard_matrix(2.0f, &matrix); - gvr_keyboard_set_world_from_keyboard_matrix(gvr_keyboard_, &matrix); -} - -void VrShellGl::DrawKeyboard() { - if (!keyboard_enabled_) - return; - - // Note that according to the keyboard API, these functions must be called - // every frame after the keyboard is created to process events, regardless of - // keyboard visibility. - gvr::ClockTimePoint target_time = gvr::GvrApi::GetTimePointNow(); - gvr_keyboard_set_frame_time(gvr_keyboard_, &target_time); - gvr_keyboard_advance_frame(gvr_keyboard_); - - if (!show_keyboard_) - return; - - bool pressed = controller_->ButtonUpHappened( - gvr::ControllerButton::GVR_CONTROLLER_BUTTON_CLICK); - gvr_keyboard_update_button_state( - gvr_keyboard_, gvr::ControllerButton::GVR_CONTROLLER_BUTTON_CLICK, - pressed); - - gvr_vec3f start; - start.x = controller_model_.laser_origin.x(); - start.y = controller_model_.laser_origin.y(); - start.z = controller_model_.laser_origin.z(); - gvr_vec3f end; - end.x = start.x + controller_model_.laser_direction.x(); - end.y = start.y + controller_model_.laser_direction.y(); - end.z = start.z + controller_model_.laser_direction.z(); - gvr_vec3f hit_point; - gvr_keyboard_update_controller_ray(gvr_keyboard_, &start, &end, &hit_point); - for (auto eye : {GVR_LEFT_EYE, GVR_RIGHT_EYE}) { - vr::CameraModel& eye_info = (eye == GVR_LEFT_EYE) - ? render_info_primary_.left_eye_model - : render_info_primary_.right_eye_model; - gvr::Mat4f view_matrix; - TransformToGvrMat(eye_info.view_matrix, &view_matrix); - gvr_keyboard_set_eye_from_world_matrix(gvr_keyboard_, eye, &view_matrix); - - gvr::Mat4f proj_matrix; - TransformToGvrMat(eye_info.proj_matrix, &proj_matrix); - gvr_keyboard_set_projection_matrix(gvr_keyboard_, eye, &proj_matrix); - - gfx::Rect viewport_rect = eye_info.viewport; - const gvr::Recti viewport = {viewport_rect.x(), viewport_rect.right(), - viewport_rect.y(), viewport_rect.bottom()}; - gvr_keyboard_set_viewport(gvr_keyboard_, eye, &viewport); - gvr_keyboard_render(gvr_keyboard_, eye); - } -} - void VrShellGl::DrawFrameSubmitWhenReady( int16_t frame_index, const gfx::Transform& head_pose,
diff --git a/chrome/browser/android/vr_shell/vr_shell_gl.h b/chrome/browser/android/vr_shell/vr_shell_gl.h index 8896d79..66e66e4 100644 --- a/chrome/browser/android/vr_shell/vr_shell_gl.h +++ b/chrome/browser/android/vr_shell/vr_shell_gl.h
@@ -16,6 +16,7 @@ #include "base/memory/weak_ptr.h" #include "base/single_thread_task_runner.h" #include "chrome/browser/android/vr_shell/android_vsync_helper.h" +#include "chrome/browser/android/vr_shell/gvr_keyboard_delegate.h" #include "chrome/browser/android/vr_shell/vr_controller.h" #include "chrome/browser/vr/content_input_delegate.h" #include "chrome/browser/vr/controller_mesh.h" @@ -24,7 +25,6 @@ #include "chrome/browser/vr/ui_renderer.h" #include "device/vr/vr_service.mojom.h" #include "mojo/public/cpp/bindings/binding.h" -#include "third_party/gvr-android-keyboard/src/libraries/headers/vr/gvr/capi/include/gvr_keyboard.h" #include "third_party/gvr-android-sdk/src/libraries/headers/vr/gvr/capi/include/gvr.h" #include "third_party/gvr-android-sdk/src/libraries/headers/vr/gvr/capi/include/gvr_types.h" #include "ui/gfx/geometry/quaternion.h" @@ -81,7 +81,8 @@ gvr_context* gvr_api, bool reprojected_rendering, bool daydream_support, - bool start_in_web_vr_mode); + bool start_in_web_vr_mode, + GvrKeyboardDelegate* keyboard_delegate); ~VrShellGl() override; void Initialize(); @@ -90,8 +91,6 @@ void OnTriggerEvent(); void OnPause(); void OnResume(); - void DrawKeyboard(); - void CreateKeyboard(); base::WeakPtr<vr::BrowserUiInterface> GetBrowserUiWeakPtr(); @@ -232,7 +231,6 @@ bool is_exiting_ = false; std::unique_ptr<VrController> controller_; - gvr_keyboard_context* gvr_keyboard_ = nullptr; scoped_refptr<base::SingleThreadTaskRunner> task_runner_; @@ -243,6 +241,7 @@ device::mojom::VRSubmitFrameClientPtr submit_client_; GlBrowserInterface* browser_; + GvrKeyboardDelegate* keyboard_delegate_; uint8_t frame_index_ = 0; // Larger than frame_index_ so it can be initialized out-of-band. @@ -275,8 +274,6 @@ bool content_frame_available_ = false; gfx::Transform last_used_head_pose_; - bool keyboard_enabled_ = false; - bool show_keyboard_ = false; vr::ControllerModel controller_model_; base::WeakPtrFactory<VrShellGl> weak_ptr_factory_;
diff --git a/chrome/browser/chromeos/arc/wallpaper/arc_wallpaper_service_unittest.cc b/chrome/browser/chromeos/arc/wallpaper/arc_wallpaper_service_unittest.cc index ce93bc5..f765447 100644 --- a/chrome/browser/chromeos/arc/wallpaper/arc_wallpaper_service_unittest.cc +++ b/chrome/browser/chromeos/arc/wallpaper/arc_wallpaper_service_unittest.cc
@@ -74,18 +74,9 @@ // Prefs TestingBrowserProcess::GetGlobal()->SetLocalState(&pref_service_); pref_service_.registry()->RegisterDictionaryPref( - ash::prefs::kWallpaperColors); + ash::prefs::kUserWallpaperInfo); pref_service_.registry()->RegisterDictionaryPref( - chromeos::kUsersWallpaperInfo); - - // Ash prefs - auto pref_service = std::make_unique<TestingPrefServiceSimple>(); - ash::Shell::RegisterLocalStatePrefs(pref_service->registry()); - pref_service->registry()->SetDefaultForeignPrefValue( - ash::prefs::kWallpaperColors, std::make_unique<base::DictionaryValue>(), - 0); - ash::ShellTestApi().OnLocalStatePrefServiceInitialized( - std::move(pref_service)); + ash::prefs::kWallpaperColors); // User user_manager_->AddUser(user_manager::StubAccountId());
diff --git a/chrome/browser/chromeos/extensions/wallpaper_private_api.cc b/chrome/browser/chromeos/extensions/wallpaper_private_api.cc index 0ee3b574..d052a65 100644 --- a/chrome/browser/chromeos/extensions/wallpaper_private_api.cc +++ b/chrome/browser/chromeos/extensions/wallpaper_private_api.cc
@@ -31,6 +31,7 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/sync/profile_sync_service_factory.h" #include "chrome/browser/ui/ash/ash_util.h" +#include "chrome/browser/ui/ash/wallpaper_controller_client.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/pref_names.h" #include "chrome/grit/generated_resources.h" @@ -333,16 +334,14 @@ // Set unsafe_wallpaper_decoder_ to null since the decoding already finished. unsafe_wallpaper_decoder_ = NULL; - chromeos::WallpaperManager* wallpaper_manager = - chromeos::WallpaperManager::Get(); wallpaper::WallpaperLayout layout = wallpaper_api_util::GetLayoutEnum( wallpaper_base::ToString(params->layout)); bool update_wallpaper = account_id_ == user_manager::UserManager::Get()->GetActiveUser()->GetAccountId(); - wallpaper_manager->SetOnlineWallpaper(account_id_, image, params->url, layout, - update_wallpaper); + WallpaperControllerClient::Get()->SetOnlineWallpaper( + account_id_, image, params->url, layout, update_wallpaper); SetResult(base::MakeUnique<base::Value>(true)); Profile* profile = Profile::FromBrowserContext(browser_context()); // This API is only available to the component wallpaper picker. We do not @@ -432,17 +431,14 @@ void WallpaperPrivateSetWallpaperFunction::SetDecodedWallpaper( std::unique_ptr<gfx::ImageSkia> image) { - chromeos::WallpaperManager* wallpaper_manager = - chromeos::WallpaperManager::Get(); - wallpaper::WallpaperLayout layout = wallpaper_api_util::GetLayoutEnum( wallpaper_base::ToString(params->layout)); bool update_wallpaper = account_id_ == user_manager::UserManager::Get()->GetActiveUser()->GetAccountId(); - wallpaper_manager->SetOnlineWallpaper(account_id_, *image.get(), params->url, - layout, update_wallpaper); + WallpaperControllerClient::Get()->SetOnlineWallpaper( + account_id_, *image.get(), params->url, layout, update_wallpaper); Profile* profile = Profile::FromBrowserContext(browser_context()); // This API is only available to the component wallpaper picker. We do not
diff --git a/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager.cc b/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager.cc index 34b0add..fa60c08 100644 --- a/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager.cc +++ b/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager.cc
@@ -12,7 +12,6 @@ #include "ash/public/cpp/window_properties.h" #include "ash/public/interfaces/constants.mojom.h" #include "ash/shell.h" -#include "ash/wallpaper/wallpaper_controller.h" #include "ash/wallpaper/wallpaper_window_state_manager.h" #include "base/bind.h" #include "base/bind_helpers.h" @@ -51,9 +50,7 @@ #include "chrome/common/pref_names.h" #include "chromeos/chromeos_switches.h" #include "chromeos/cryptohome/system_salt_getter.h" -#include "components/prefs/pref_registry_simple.h" #include "components/prefs/pref_service.h" -#include "components/prefs/scoped_user_pref_update.h" #include "components/signin/core/account_id/account_id.h" #include "components/user_manager/known_user.h" #include "components/user_manager/user.h" @@ -89,12 +86,6 @@ const int kCacheWallpaperDelayMs = 500; -// Names of nodes with wallpaper info in |kUserWallpapersInfo| dictionary. -const char kNewWallpaperDateNodeName[] = "date"; -const char kNewWallpaperLayoutNodeName[] = "layout"; -const char kNewWallpaperLocationNodeName[] = "file"; -const char kNewWallpaperTypeNodeName[] = "type"; - // Known user keys. const char kWallpaperFilesId[] = "wallpaper-files-id"; @@ -353,8 +344,6 @@ const int kWallpaperThumbnailWidth = 108; const int kWallpaperThumbnailHeight = 68; -const char kUsersWallpaperInfo[] = "user_wallpaper_info"; - // This is "wallpaper either scheduled to load, or loading right now". // // While enqueued, it defines moment in the future, when it will be loaded. @@ -603,8 +592,8 @@ const base::FilePath& path, const gfx::ImageSkia& image) { DCHECK(!image.isNull()); - wallpaper_manager_->wallpaper_cache_[account_id] = - CustomWallpaperElement(path, image); + (*wallpaper_manager_->GetWallpaperCacheMap())[account_id] = + ash::CustomWallpaperElement(path, image); } void WallpaperManager::TestApi::ClearDisposableWallpaperCache() { @@ -661,11 +650,6 @@ } // static -void WallpaperManager::RegisterPrefs(PrefRegistrySimple* registry) { - registry->RegisterDictionaryPref(kUsersWallpaperInfo); -} - -// static bool WallpaperManager::ResizeImage(const gfx::ImageSkia& image, wallpaper::WallpaperLayout layout, int preferred_width, @@ -812,34 +796,8 @@ if (show_wallpaper) GetPendingWallpaper()->SetWallpaperFromImage(account_id, image, info); - wallpaper_cache_[account_id] = CustomWallpaperElement(wallpaper_path, image); -} - -void WallpaperManager::SetOnlineWallpaper(const AccountId& account_id, - const gfx::ImageSkia& image, - const std::string& url, - wallpaper::WallpaperLayout layout, - bool show_wallpaper) { - DCHECK(user_manager::UserManager::Get()->IsUserLoggedIn()); - - // There is no visible wallpaper in kiosk mode. - if (user_manager::UserManager::Get()->IsLoggedInAsKioskApp()) - return; - - WallpaperInfo info = {url, layout, wallpaper::ONLINE, - base::Time::Now().LocalMidnight()}; - bool is_persistent = !user_manager::UserManager::Get() - ->IsCurrentUserNonCryptohomeDataEphemeral(); - SetUserWallpaperInfo(account_id, info, is_persistent); - - if (show_wallpaper) - GetPendingWallpaper()->SetWallpaperFromImage(account_id, image, info); - - // Leave the file path empty, because in most cases the file path is not used - // when fetching cache, but in case it needs to be checked, we should avoid - // confusing the URL with a real file path. - wallpaper_cache_[account_id] = - CustomWallpaperElement(base::FilePath(), image); + (*GetWallpaperCacheMap())[account_id] = + ash::CustomWallpaperElement(wallpaper_path, image); } void WallpaperManager::SetDefaultWallpaper(const AccountId& account_id, @@ -930,7 +888,7 @@ } gfx::ImageSkia user_wallpaper; - current_user_wallpaper_info_ = info; + *GetCachedWallpaperInfo() = info; if (GetWallpaperFromCache(account_id, &user_wallpaper)) { GetPendingWallpaper()->SetWallpaperFromImage(account_id, user_wallpaper, info); @@ -959,16 +917,19 @@ wallpaper_path = GetDeviceWallpaperFilePath(); } - CustomWallpaperMap::iterator it = wallpaper_cache_.find(account_id); + ash::CustomWallpaperMap* wallpaper_cache_map = GetWallpaperCacheMap(); + ash::CustomWallpaperMap::iterator it = + wallpaper_cache_map->find(account_id); // Do not try to load the wallpaper if the path is the same. Since loading // could still be in progress, we ignore the existence of the image. - if (it != wallpaper_cache_.end() && it->second.first == wallpaper_path) + if (it != wallpaper_cache_map->end() && + it->second.first == wallpaper_path) return; // Set the new path and reset the existing image - the image will be // added once it becomes available. - wallpaper_cache_[account_id] = - CustomWallpaperElement(wallpaper_path, gfx::ImageSkia()); + (*wallpaper_cache_map)[account_id] = + ash::CustomWallpaperElement(wallpaper_path, gfx::ImageSkia()); loaded_wallpapers_for_test_++; GetPendingWallpaper()->SetWallpaperFromPath(account_id, info, @@ -990,22 +951,16 @@ } void WallpaperManager::RemoveUserWallpaper(const AccountId& account_id) { - if (wallpaper_cache_.find(account_id) != wallpaper_cache_.end()) - wallpaper_cache_.erase(account_id); - - PrefService* prefs = g_browser_process->local_state(); - // PrefService could be NULL in tests. - if (!prefs) - return; - WallpaperInfo info; - GetUserWallpaperInfo(account_id, &info); - DictionaryPrefUpdate prefs_wallpapers_info_update(prefs, kUsersWallpaperInfo); - prefs_wallpapers_info_update->RemoveWithoutPathExpansion( - account_id.GetUserEmail(), NULL); - // Remove the color cache of the previous wallpaper if it exists. - DictionaryPrefUpdate wallpaper_colors_update(prefs, - ash::prefs::kWallpaperColors); - wallpaper_colors_update->RemoveWithoutPathExpansion(info.location, nullptr); + if (ash::Shell::HasInstance() && !ash_util::IsRunningInMash()) { + // Some unit tests come here without a Shell instance. + // TODO(crbug.com/776464): This is intended not to work under mash. Make it + // work again after WallpaperManager is removed. + bool is_persistent = + !user_manager::UserManager::Get()->IsUserNonCryptohomeDataEphemeral( + account_id); + ash::Shell::Get()->wallpaper_controller()->RemoveUserWallpaperInfo( + account_id, is_persistent); + } DeleteUserWallpapers(account_id); } @@ -1013,30 +968,14 @@ const WallpaperInfo& info, bool is_persistent) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - current_user_wallpaper_info_ = info; - if (!is_persistent) + if (!ash::Shell::HasInstance() || ash_util::IsRunningInMash()) { + // Some unit tests come here without a Shell instance. + // TODO(crbug.com/776464): This is intended not to work under mash. Make it + // work again after WallpaperManager is removed. return; - - PrefService* local_state = g_browser_process->local_state(); - // Remove the color cache of the previous wallpaper if it exists. - WallpaperInfo old_info; - if (GetUserWallpaperInfo(account_id, &old_info)) { - DictionaryPrefUpdate wallpaper_colors_update(local_state, - ash::prefs::kWallpaperColors); - wallpaper_colors_update->RemoveWithoutPathExpansion(old_info.location, - nullptr); } - DictionaryPrefUpdate wallpaper_update(local_state, kUsersWallpaperInfo); - - auto wallpaper_info_dict = base::MakeUnique<base::DictionaryValue>(); - wallpaper_info_dict->SetString( - kNewWallpaperDateNodeName, - base::Int64ToString(info.date.ToInternalValue())); - wallpaper_info_dict->SetString(kNewWallpaperLocationNodeName, info.location); - wallpaper_info_dict->SetInteger(kNewWallpaperLayoutNodeName, info.layout); - wallpaper_info_dict->SetInteger(kNewWallpaperTypeNodeName, info.type); - wallpaper_update->SetWithoutPathExpansion(account_id.GetUserEmail(), - std::move(wallpaper_info_dict)); + ash::Shell::Get()->wallpaper_controller()->SetUserWallpaperInfo( + account_id, info, is_persistent); } void WallpaperManager::InitializeWallpaper() { @@ -1096,7 +1035,7 @@ for (auto& observer : observers_) observer.OnUpdateWallpaperForTesting(); if (clear_cache) - wallpaper_cache_.clear(); + GetWallpaperCacheMap()->clear(); if (!device_wallpaper_set) ShowUserWallpaper(last_selected_user_); } @@ -1124,12 +1063,11 @@ DCHECK(thread_checker_.CalledOnValidThread()); if (user_manager::UserManager::Get()->IsLoggedInAsStub()) { - info->location = current_user_wallpaper_info_.location = ""; - info->layout = current_user_wallpaper_info_.layout = - wallpaper::WALLPAPER_LAYOUT_CENTER_CROPPED; - info->type = current_user_wallpaper_info_.type = wallpaper::DEFAULT; - info->date = current_user_wallpaper_info_.date = - base::Time::Now().LocalMidnight(); + info->location = ""; + info->layout = wallpaper::WALLPAPER_LAYOUT_CENTER_CROPPED; + info->type = wallpaper::DEFAULT; + info->date = base::Time::Now().LocalMidnight(); + *GetCachedWallpaperInfo() = *info; return true; } @@ -1162,7 +1100,7 @@ UMA_HISTOGRAM_ENUMERATION("Ash.Wallpaper.Type", info.type, wallpaper::WALLPAPER_TYPE_COUNT); RecordWallpaperAppType(); - if (info == current_user_wallpaper_info_) + if (info == *GetCachedWallpaperInfo()) return; } ShowUserWallpaper( @@ -1506,23 +1444,27 @@ bool WallpaperManager::GetWallpaperFromCache(const AccountId& account_id, gfx::ImageSkia* image) { DCHECK(thread_checker_.CalledOnValidThread()); - CustomWallpaperMap::const_iterator it = wallpaper_cache_.find(account_id); - if (it != wallpaper_cache_.end() && !(*it).second.second.isNull()) { - *image = (*it).second.second; - return true; + if (!ash::Shell::HasInstance() || ash_util::IsRunningInMash()) { + // Some unit tests come here without a Shell instance. + // TODO(crbug.com/776464): This is intended not to work under mash. Make it + // work again after WallpaperManager is removed. + return false; } - return false; + return ash::Shell::Get()->wallpaper_controller()->GetWallpaperFromCache( + account_id, image); } bool WallpaperManager::GetPathFromCache(const AccountId& account_id, base::FilePath* path) { DCHECK(thread_checker_.CalledOnValidThread()); - CustomWallpaperMap::const_iterator it = wallpaper_cache_.find(account_id); - if (it != wallpaper_cache_.end()) { - *path = (*it).second.first; - return true; + if (!ash::Shell::HasInstance() || ash_util::IsRunningInMash()) { + // Some unit tests come here without a Shell instance. + // TODO(crbug.com/776464): This is intended not to work under mash. Make it + // work again after WallpaperManager is removed. + return false; } - return false; + return ash::Shell::Get()->wallpaper_controller()->GetPathFromCache(account_id, + path); } int WallpaperManager::loaded_wallpapers_for_test() const { @@ -1547,8 +1489,9 @@ void WallpaperManager::CacheUserWallpaper(const AccountId& account_id) { DCHECK(thread_checker_.CalledOnValidThread()); - CustomWallpaperMap::iterator it = wallpaper_cache_.find(account_id); - if (it != wallpaper_cache_.end() && !it->second.second.isNull()) + ash::CustomWallpaperMap* wallpaper_cache_map = GetWallpaperCacheMap(); + ash::CustomWallpaperMap::iterator it = wallpaper_cache_map->find(account_id); + if (it != wallpaper_cache_map->end() && !it->second.second.isNull()) return; WallpaperInfo info; if (GetUserWallpaperInfo(account_id, &info)) { @@ -1567,8 +1510,8 @@ wallpaper_path = GetCustomWallpaperDir(sub_dir).Append(info.location); } // Set the path to the cache. - wallpaper_cache_[account_id] = - CustomWallpaperElement(wallpaper_path, gfx::ImageSkia()); + (*wallpaper_cache_map)[account_id] = + ash::CustomWallpaperElement(wallpaper_path, gfx::ImageSkia()); task_runner_->PostTask( FROM_HERE, base::Bind(&WallpaperManager::GetCustomWallpaperInternal, account_id, @@ -1595,15 +1538,16 @@ logged_in_user_account_ids.insert((*it)->GetAccountId()); } - CustomWallpaperMap logged_in_users_cache; - for (CustomWallpaperMap::iterator it = wallpaper_cache_.begin(); - it != wallpaper_cache_.end(); ++it) { + ash::CustomWallpaperMap logged_in_users_cache; + ash::CustomWallpaperMap* wallpaper_cache_map = GetWallpaperCacheMap(); + for (ash::CustomWallpaperMap::iterator it = wallpaper_cache_map->begin(); + it != wallpaper_cache_map->end(); ++it) { if (logged_in_user_account_ids.find(it->first) != logged_in_user_account_ids.end()) { logged_in_users_cache.insert(*it); } } - wallpaper_cache_ = logged_in_users_cache; + *wallpaper_cache_map = logged_in_users_cache; } void WallpaperManager::DeleteUserWallpapers(const AccountId& account_id) { @@ -1719,9 +1663,11 @@ // If the wallpaper exists and it contains already the correct image we can // return immediately. - CustomWallpaperMap::iterator it = wallpaper_cache_.find(account_id); - if (it != wallpaper_cache_.end() && it->second.first == wallpaper_path && - !it->second.second.isNull()) + ash::CustomWallpaperMap* wallpaper_cache_map = GetWallpaperCacheMap(); + ash::CustomWallpaperMap::iterator it = + wallpaper_cache_map->find(account_id); + if (it != wallpaper_cache_map->end() && + it->second.first == wallpaper_path && !it->second.second.isNull()) return; loaded_wallpapers_for_test_++; @@ -1781,47 +1727,17 @@ bool WallpaperManager::GetUserWallpaperInfo(const AccountId& account_id, WallpaperInfo* info) const { DCHECK_CURRENTLY_ON(BrowserThread::UI); - - if (user_manager::UserManager::Get()->IsUserNonCryptohomeDataEphemeral( - account_id)) { - // Default to the values cached in memory. - *info = current_user_wallpaper_info_; - - // Ephemeral users do not save anything to local state. But we have got - // wallpaper info from memory. Returns true. - return true; - } - - const base::DictionaryValue* info_dict; - if (!g_browser_process->local_state() - ->GetDictionary(kUsersWallpaperInfo) - ->GetDictionaryWithoutPathExpansion(account_id.GetUserEmail(), - &info_dict)) { + if (!ash::Shell::HasInstance() || ash_util::IsRunningInMash()) { + // Some unit tests come here without a Shell instance. + // TODO(crbug.com/776464): This is intended not to work under mash. Make it + // work again after WallpaperManager is removed. return false; } - - // Use temporary variables to keep |info| untouched in the error case. - std::string location; - if (!info_dict->GetString(kNewWallpaperLocationNodeName, &location)) - return false; - int layout; - if (!info_dict->GetInteger(kNewWallpaperLayoutNodeName, &layout)) - return false; - int type; - if (!info_dict->GetInteger(kNewWallpaperTypeNodeName, &type)) - return false; - std::string date_string; - if (!info_dict->GetString(kNewWallpaperDateNodeName, &date_string)) - return false; - int64_t date_val; - if (!base::StringToInt64(date_string, &date_val)) - return false; - - info->location = location; - info->layout = static_cast<wallpaper::WallpaperLayout>(layout); - info->type = static_cast<wallpaper::WallpaperType>(type); - info->date = base::Time::FromInternalValue(date_val); - return true; + bool is_persistent = + !user_manager::UserManager::Get()->IsUserNonCryptohomeDataEphemeral( + account_id); + return ash::Shell::Get()->wallpaper_controller()->GetUserWallpaperInfo( + account_id, info, is_persistent); } bool WallpaperManager::ShouldSetDeviceWallpaper(const AccountId& account_id, @@ -1883,7 +1799,7 @@ } // Update the image, but keep the path which was set earlier. - wallpaper_cache_[account_id].second = user_image->image(); + (*GetWallpaperCacheMap())[account_id].second = user_image->image(); if (update_wallpaper) SetWallpaper(user_image->image(), info); @@ -1896,7 +1812,7 @@ // There is no visible wallpaper in kiosk mode. if (user_manager::UserManager::Get()->IsLoggedInAsKioskApp()) return; - wallpaper_cache_.erase(account_id); + GetWallpaperCacheMap()->erase(account_id); WallpaperResolution resolution = GetAppropriateResolution(); const bool use_small = (resolution == WALLPAPER_RESOLUTION_SMALL); @@ -1957,8 +1873,8 @@ if (update_wallpaper) { // We are now about to change the wallpaper, so update the path and remove // the existing image. - wallpaper_cache_[account_id] = - CustomWallpaperElement(wallpaper_path, gfx::ImageSkia()); + (*GetWallpaperCacheMap())[account_id] = + ash::CustomWallpaperElement(wallpaper_path, gfx::ImageSkia()); } user_image_loader::StartWithFilePath( task_runner_, wallpaper_path, ImageDecoder::ROBUST_JPEG_CODEC, @@ -2400,4 +2316,18 @@ MovableOnDestroyCallbackHolder()); } +wallpaper::WallpaperInfo* WallpaperManager::GetCachedWallpaperInfo() { + if (!ash::Shell::HasInstance() || ash_util::IsRunningInMash()) + return &dummy_current_user_wallpaper_info_; + return ash::Shell::Get() + ->wallpaper_controller() + ->GetCurrentUserWallpaperInfo(); +} + +ash::CustomWallpaperMap* WallpaperManager::GetWallpaperCacheMap() { + if (!ash::Shell::HasInstance() || ash_util::IsRunningInMash()) + return &dummy_wallpaper_cache_map_; + return ash::Shell::Get()->wallpaper_controller()->GetWallpaperCacheMap(); +} + } // namespace chromeos
diff --git a/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager.h b/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager.h index 6bbb4a7..ee4b384 100644 --- a/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager.h +++ b/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager.h
@@ -12,6 +12,7 @@ #include <string> #include <vector> +#include "ash/wallpaper/wallpaper_controller.h" #include "base/containers/circular_deque.h" #include "base/files/file_path.h" #include "base/macros.h" @@ -37,8 +38,6 @@ #include "ui/wm/public/activation_change_observer.h" #include "ui/wm/public/activation_client.h" -class PrefRegistrySimple; - namespace base { class CommandLine; class SequencedTaskRunner; @@ -91,9 +90,6 @@ extern const int kWallpaperThumbnailWidth; extern const int kWallpaperThumbnailHeight; -// A dictionary pref that maps usernames to wallpaper info. -extern const char kUsersWallpaperInfo[]; - class WallpaperManager : public content::NotificationObserver, public user_manager::UserManager::Observer, public wm::ActivationChangeObserver, @@ -212,9 +208,6 @@ // Returns custom wallpaper directory by appending corresponding |sub_dir|. static base::FilePath GetCustomWallpaperDir(const char* sub_dir); - // Registers wallpaper manager preferences. - static void RegisterPrefs(PrefRegistrySimple* registry); - // Resizes |image| to a resolution which is nearest to |preferred_width| and // |preferred_height| while respecting the |layout| choice. |output_skia| is // optional (may be NULL). Returns true on success. @@ -261,21 +254,6 @@ const gfx::ImageSkia& image, bool show_wallpaper); - // Sets wallpaper from the wallpaper picker selection, i.e., the wallpaper - // type is ONLINE. - // |account_id|: The user's account id. - // |image|: The wallpaper image. - // |url|: The url corresponding to this wallpaper. Used as a placeholder for - // the location in WallpaperInfo. - // |layout|: The layout of the wallpaper, used for wallpaper resizing. - // |show_wallpaper|: If false, don't show the new wallpaper now but only - // update cache. - void SetOnlineWallpaper(const AccountId& account_id, - const gfx::ImageSkia& image, - const std::string& url, - wallpaper::WallpaperLayout layout, - bool show_wallpaper); - // Sets |account_id|'s wallpaper to be the default wallpaper. Note: different // user types may have different default wallpapers. If |show_wallpaper| is // false, don't show the default wallpaper now. @@ -307,10 +285,7 @@ // Removes all of |account_id|'s saved wallpapers and related info. void RemoveUserWallpaper(const AccountId& account_id); - // TODO(crbug.com/776464): Make this private. WallpaperInfo should be an - // internal concept. - // Sets wallpaper info for |account_id| and saves it to local state if - // |is_persistent| is true. + // A wrapper of |WallpaperController::SetUserWallpaperInfo|. void SetUserWallpaperInfo(const AccountId& account_id, const wallpaper::WallpaperInfo& info, bool is_persistent); @@ -402,12 +377,6 @@ WallpaperManager(); - // The |CustomWallpaperElement| contains |first| the path of the image which - // is currently being loaded and or in progress of being loaded and |second| - // the image itself. - typedef std::pair<base::FilePath, gfx::ImageSkia> CustomWallpaperElement; - typedef std::map<AccountId, CustomWallpaperElement> CustomWallpaperMap; - // Saves original custom wallpaper to |path| (absolute path) on filesystem // and starts resizing operation of the custom wallpaper if necessary. static void SaveCustomWallpaper( @@ -452,11 +421,11 @@ // set the device wallpaper as the login screen wallpaper. bool SetDeviceWallpaperIfApplicable(const AccountId& account_id); - // Gets encoded wallpaper from cache. Returns true if success. + // A wrapper of |WallpaperController::GetWallpaperFromCache|. bool GetWallpaperFromCache(const AccountId& account_id, gfx::ImageSkia* image); - // Gets path of encoded wallpaper from cache. Returns true if success. + // A wrapper of |WallpaperController::GetPathFromCache|. bool GetPathFromCache(const AccountId& account_id, base::FilePath* path); // The number of wallpapers have loaded. For test only. @@ -510,9 +479,7 @@ // wallpaper_files_id is ready. void MoveLoggedInUserCustomWallpaper(); - // Gets wallpaper information of |account_id| from Local State or memory. - // Returns - // false if wallpaper information is not found. + // A wrapper of |WallpaperController::GetUserWallpaperInfo|. bool GetUserWallpaperInfo(const AccountId& account_id, wallpaper::WallpaperInfo* info) const; @@ -671,6 +638,13 @@ const base::FilePath& customized_default_wallpaper_file_large, std::unique_ptr<gfx::ImageSkia> large_wallpaper_image); + // Returns the cached logged-in user wallpaper info, or a dummy value under + // mash. + wallpaper::WallpaperInfo* GetCachedWallpaperInfo(); + + // Returns the wallpaper cache map, or a dummy value under mash. + ash::CustomWallpaperMap* GetWallpaperCacheMap(); + std::unique_ptr<CrosSettings::ObserverSubscription> show_user_name_on_signin_subscription_; @@ -687,14 +661,14 @@ // Wallpaper sequenced task runner. scoped_refptr<base::SequencedTaskRunner> task_runner_; - // Logged-in user wallpaper information. - wallpaper::WallpaperInfo current_user_wallpaper_info_; - // If non-NULL, used in place of the real command line. base::CommandLine* command_line_for_testing_ = nullptr; - // Caches wallpapers of users. Accessed only on UI thread. - CustomWallpaperMap wallpaper_cache_; + // A placeholder for |current_user_wallpaper_info_| under mash. + wallpaper::WallpaperInfo dummy_current_user_wallpaper_info_; + + // A placeholder for |wallpaper_cache_map_| under mash. + ash::CustomWallpaperMap dummy_wallpaper_cache_map_; // The last selected user on user pod row. AccountId last_selected_user_ = EmptyAccountId();
diff --git a/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager_browsertest.cc b/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager_browsertest.cc index 9ff347f..9eb8c2ea 100644 --- a/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager_browsertest.cc +++ b/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager_browsertest.cc
@@ -541,11 +541,9 @@ // Tests for crbug.com/339576. Wallpaper cache should be updated in // multi-profile mode when user: -// 1. chooses an online wallpaper from wallpaper -// picker (calls SetOnlineWallpaper); -// 2. chooses a custom wallpaper from wallpaper -// picker (calls SetCustomWallpaper); -// 3. reverts to a default wallpaper. +// 1. chooses a custom wallpaper from wallpaper picker +// (calls SetCustomWallpaper); +// 2. reverts to a default wallpaper. // Also, when user login at multi-profile mode, previous logged in users' // wallpaper cache should not be deleted. IN_PROC_BROWSER_TEST_F(WallpaperManagerBrowserTestCacheUpdate, @@ -578,18 +576,6 @@ EXPECT_TRUE(test_api->GetPathFromCache(test_account_id1_, &path)); EXPECT_EQ(original_path, path); - gfx::ImageSkia red_wallpaper = CreateTestImage(SK_ColorRED); - wallpaper_manager->SetOnlineWallpaper(test_account_id1_, red_wallpaper, - "dummy" /* dummy url */, - WALLPAPER_LAYOUT_CENTER, true); - wallpaper_manager_test_utils::WaitAsyncWallpaperLoadFinished(); - // SetOnlineWallpaper should update wallpaper cache when multi-profile is - // turned on. - EXPECT_TRUE( - test_api->GetWallpaperFromCache(test_account_id1_, &cached_wallpaper)); - EXPECT_TRUE(test_api->GetPathFromCache(test_account_id1_, &path)); - EXPECT_TRUE(cached_wallpaper.BackedBySameObjectAs(red_wallpaper)); - gfx::ImageSkia green_wallpaper = CreateTestImage(SK_ColorGREEN); wallpaper_manager->SetCustomWallpaper( test_account_id1_, test_account1_wallpaper_files_id_,
diff --git a/chrome/browser/chromeos/net/network_state_notifier.cc b/chrome/browser/chromeos/net/network_state_notifier.cc index a57384a..1b75893 100644 --- a/chrome/browser/chromeos/net/network_state_notifier.cc +++ b/chrome/browser/chromeos/net/network_state_notifier.cc
@@ -94,7 +94,7 @@ message_center::NotifierId(message_center::NotifierId::SYSTEM_COMPONENT, ash::system_notifier::kNotifierNetworkError), message_center::RichNotificationData(), - new message_center::HandleNotificationClickedDelegate(callback), + new message_center::HandleNotificationClickDelegate(callback), GetErrorNotificationVectorIcon(network_type), message_center::SystemNotificationWarningLevel::CRITICAL_WARNING); } else {
diff --git a/chrome/browser/chromeos/preferences.cc b/chrome/browser/chromeos/preferences.cc index d21804a..2e09ec2 100644 --- a/chrome/browser/chromeos/preferences.cc +++ b/chrome/browser/chromeos/preferences.cc
@@ -140,9 +140,6 @@ registry->RegisterIntegerPref( prefs::kSystemTimezoneAutomaticDetectionPolicy, enterprise_management::SystemTimezoneProto::USERS_DECIDE); - - registry->RegisterDictionaryPref(ash::prefs::kWallpaperColors, - PrefRegistry::PUBLIC); registry->RegisterStringPref(prefs::kMinimumAllowedChromeVersion, ""); }
diff --git a/chrome/browser/chromeos/status/data_promo_notification.cc b/chrome/browser/chromeos/status/data_promo_notification.cc index c103170..8588d188 100644 --- a/chrome/browser/chromeos/status/data_promo_notification.cc +++ b/chrome/browser/chromeos/status/data_promo_notification.cc
@@ -277,7 +277,7 @@ message_center::NotifierId::SYSTEM_COMPONENT, ash::system_notifier::kNotifierNetwork), message_center::RichNotificationData(), - new message_center::HandleNotificationClickedDelegate(base::Bind( + new message_center::HandleNotificationClickDelegate(base::Bind( &NotificationClicked, default_network->guid(), info_url)), kNotificationMobileDataIcon, message_center::SystemNotificationWarningLevel::NORMAL); @@ -324,7 +324,7 @@ message_center::NotifierId::SYSTEM_COMPONENT, ash::system_notifier::kNotifierNetwork), message_center::RichNotificationData(), - new message_center::HandleNotificationClickedDelegate( + new message_center::HandleNotificationClickDelegate( base::Bind(&NotificationClicked, "", kDataSaverExtensionUrl)), kNotificationMobileDataIcon, message_center::SystemNotificationWarningLevel::NORMAL);
diff --git a/chrome/browser/chromeos/ui/low_disk_notification.cc b/chrome/browser/chromeos/ui/low_disk_notification.cc index 4f2f36e..dd40e2a 100644 --- a/chrome/browser/chromeos/ui/low_disk_notification.cc +++ b/chrome/browser/chromeos/ui/low_disk_notification.cc
@@ -113,15 +113,18 @@ ash::system_notifier::kNotifierDisk); auto on_click = base::Bind( - [](Profile* profile, int button_index) { - chrome::ShowSettingsSubPageForProfile(profile, kStoragePage); + [](Profile* profile, base::Optional<int> button_index) { + if (button_index) { + DCHECK_EQ(0, *button_index); + chrome::ShowSettingsSubPageForProfile(profile, kStoragePage); + } }, profile); std::unique_ptr<message_center::Notification> notification = ash::system_notifier::CreateSystemNotification( message_center::NOTIFICATION_TYPE_SIMPLE, kLowDiskId, title, message, icon, base::string16(), GURL(), notifier_id, optional_fields, - new message_center::HandleNotificationButtonClickDelegate(on_click), + new message_center::HandleNotificationClickDelegate(on_click), kNotificationStorageFullIcon, warning_level); return notification;
diff --git a/chrome/browser/extensions/extension_storage_monitor.cc b/chrome/browser/extensions/extension_storage_monitor.cc index cb45c93..04b30718 100644 --- a/chrome/browser/extensions/extension_storage_monitor.cc +++ b/chrome/browser/extensions/extension_storage_monitor.cc
@@ -442,7 +442,7 @@ message_center::NotifierId(message_center::NotifierId::SYSTEM_COMPONENT, kSystemNotifierId), notification_data, - new message_center::HandleNotificationButtonClickDelegate( + new message_center::HandleNotificationClickDelegate( base::Bind(&ExtensionStorageMonitor::OnNotificationButtonClick, weak_ptr_factory_.GetWeakPtr(), extension_id)))); notification->SetSystemPriority(); @@ -453,8 +453,12 @@ } void ExtensionStorageMonitor::OnNotificationButtonClick( - const std::string& extension_id, int button_index) { - switch (button_index) { + const std::string& extension_id, + base::Optional<int> button_index) { + if (!button_index) + return; + + switch (*button_index) { case BUTTON_DISABLE_NOTIFICATION: { DisableStorageMonitoring(extension_id); break;
diff --git a/chrome/browser/extensions/extension_storage_monitor.h b/chrome/browser/extensions/extension_storage_monitor.h index 2e9cafb..664b9f7 100644 --- a/chrome/browser/extensions/extension_storage_monitor.h +++ b/chrome/browser/extensions/extension_storage_monitor.h
@@ -12,6 +12,7 @@ #include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" +#include "base/optional.h" #include "base/scoped_observer.h" #include "chrome/browser/extensions/extension_uninstall_dialog.h" #include "components/keyed_service/core/keyed_service.h" @@ -86,7 +87,7 @@ int64_t current_usage, const gfx::Image& image); void OnNotificationButtonClick(const std::string& extension_id, - int button_index); + base::Optional<int> button_index); void DisableStorageMonitoring(const std::string& extension_id); void StartMonitoringStorage(const Extension* extension);
diff --git a/chrome/browser/notifications/native_notification_display_service.cc b/chrome/browser/notifications/native_notification_display_service.cc index 3f1e48b..f235c09 100644 --- a/chrome/browser/notifications/native_notification_display_service.cc +++ b/chrome/browser/notifications/native_notification_display_service.cc
@@ -54,8 +54,7 @@ void NativeNotificationDisplayService::OnNotificationPlatformBridgeReady( bool success) { UMA_HISTOGRAM_BOOLEAN("Notifications.UsingNativeNotificationCenter", success); - if (success) - notification_bridge_ready_ = true; + notification_bridge_ready_ = success; // TODO(estade): this shouldn't be necessary in the succesful case, but some // notification bridges can't handle TRANSIENT notifications and still have to
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc index 535debe..e0cee2a 100644 --- a/chrome/browser/prefs/browser_prefs.cc +++ b/chrome/browser/prefs/browser_prefs.cc
@@ -434,7 +434,6 @@ chromeos::TimeZoneResolver::RegisterPrefs(registry); chromeos::UserImageManager::RegisterPrefs(registry); chromeos::UserSessionManager::RegisterPrefs(registry); - chromeos::WallpaperManager::RegisterPrefs(registry); chromeos::echo_offer::RegisterPrefs(registry); extensions::ExtensionAssetsManagerChromeOS::RegisterPrefs(registry); extensions::lock_screen_data::LockScreenItemStorage::RegisterLocalState(
diff --git a/chrome/browser/resource_coordinator/page_signal_receiver.h b/chrome/browser/resource_coordinator/page_signal_receiver.h index 11510ce8..8d61c11 100644 --- a/chrome/browser/resource_coordinator/page_signal_receiver.h +++ b/chrome/browser/resource_coordinator/page_signal_receiver.h
@@ -21,6 +21,9 @@ class PageSignalObserver { public: virtual ~PageSignalObserver() = default; + // PageSignalReceiver will deliver signals with a |web_contents| even it's not + // managed by the client. Thus the clients are responsible for checking the + // passed |web_contents| by themselves. virtual void OnPageAlmostIdle(content::WebContents* web_contents) {} virtual void OnExpectedTaskQueueingDurationSet( content::WebContents* web_contents,
diff --git a/chrome/browser/resource_coordinator/tab_manager_resource_coordinator_signal_observer.cc b/chrome/browser/resource_coordinator/tab_manager_resource_coordinator_signal_observer.cc index 2058084..a2d9927 100644 --- a/chrome/browser/resource_coordinator/tab_manager_resource_coordinator_signal_observer.cc +++ b/chrome/browser/resource_coordinator/tab_manager_resource_coordinator_signal_observer.cc
@@ -27,6 +27,8 @@ content::WebContents* web_contents) { auto* web_contents_data = TabManager::WebContentsData::FromWebContents(web_contents); + if (!web_contents_data) + return; web_contents_data->NotifyTabIsLoaded(); }
diff --git a/chrome/browser/resource_coordinator/tab_manager_unittest.cc b/chrome/browser/resource_coordinator/tab_manager_unittest.cc index ef93a0e..a9576b2 100644 --- a/chrome/browser/resource_coordinator/tab_manager_unittest.cc +++ b/chrome/browser/resource_coordinator/tab_manager_unittest.cc
@@ -26,6 +26,7 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/resource_coordinator/background_tab_navigation_throttle.h" #include "chrome/browser/resource_coordinator/tab_manager_features.h" +#include "chrome/browser/resource_coordinator/tab_manager_resource_coordinator_signal_observer.h" #include "chrome/browser/resource_coordinator/tab_manager_stats_collector.h" #include "chrome/browser/resource_coordinator/tab_manager_web_contents_data.h" #include "chrome/browser/resource_coordinator/tab_stats.h" @@ -1260,6 +1261,8 @@ EXPECT_TRUE(base::FeatureList::IsEnabled(features::kPageAlmostIdle)); TabManager* tab_manager = g_browser_process->GetTabManager(); + tab_manager->resource_coordinator_signal_observer_.reset( + new TabManager::ResourceCoordinatorSignalObserver()); tab_manager->ResetMemoryPressureListenerForTest(); EXPECT_EQ(TabManager::BackgroundTabLoadingMode::kStaggered, @@ -1291,7 +1294,8 @@ // Simulate tab 1 has finished loading by receiving idle signal from resource // coordinator. Since the page idle signal feature is enabled, this should // start next loading. - tab_manager->GetWebContentsData(contents1_.get())->NotifyTabIsLoaded(); + tab_manager->resource_coordinator_signal_observer_->OnPageAlmostIdle( + contents1_.get()); // Tab 2 should start loading right away. EXPECT_TRUE(tab_manager->IsTabLoadingForTest(contents2_.get())); @@ -1303,11 +1307,21 @@ // Simulate tab 2 has finished loading by receiving idle signal from resource // coordinator. - tab_manager->GetWebContentsData(contents2_.get())->NotifyTabIsLoaded(); + tab_manager->resource_coordinator_signal_observer_->OnPageAlmostIdle( + contents2_.get()); // Tab 3 should start loading now in staggered loading mode. EXPECT_TRUE(tab_manager->IsTabLoadingForTest(contents3_.get())); EXPECT_FALSE(tab_manager->IsNavigationDelayedForTest(nav_handle3_.get())); + + // |ignored_web_contents| is not managed by TabManager, thus will be ignored + // and shouldn't cause any crash or side effect. + WebContents* ignored_web_contents = + WebContentsTester::CreateTestWebContents(browser_context(), nullptr); + tab_manager->resource_coordinator_signal_observer_->OnPageAlmostIdle( + ignored_web_contents); + EXPECT_TRUE(tab_manager->IsTabLoadingForTest(contents3_.get())); + EXPECT_FALSE(tab_manager->IsNavigationDelayedForTest(nav_handle3_.get())); } } // namespace resource_coordinator
diff --git a/chrome/browser/signin/signin_error_notifier_ash.cc b/chrome/browser/signin/signin_error_notifier_ash.cc index 18747d3..6a5547c9 100644 --- a/chrome/browser/signin/signin_error_notifier_ash.cc +++ b/chrome/browser/signin/signin_error_notifier_ash.cc
@@ -10,11 +10,11 @@ #include "base/strings/utf_string_conversions.h" #include "build/build_config.h" #include "chrome/app/vector_icons/vector_icons.h" -#include "chrome/browser/browser_process.h" #include "chrome/browser/chromeos/login/user_flow.h" #include "chrome/browser/chromeos/login/users/chrome_user_manager.h" #include "chrome/browser/lifetime/application_lifetime.h" -#include "chrome/browser/notifications/notification_ui_manager.h" +#include "chrome/browser/notifications/notification_common.h" +#include "chrome/browser/notifications/notification_display_service.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/ash/multi_user/multi_user_util.h" #include "chrome/browser/ui/browser_tabstrip.h" @@ -37,34 +37,7 @@ const char kProfileSigninNotificationId[] = "chrome://settings/signin/"; -// A notification delegate for the sign-out button. -// TODO(estade): should this use a generic notification delegate? -class SigninNotificationDelegate : public message_center::NotificationDelegate { - public: - SigninNotificationDelegate(); - - // NotificationDelegate: - void Click() override; - void ButtonClick(int button_index) override; - - protected: - ~SigninNotificationDelegate() override; - - private: - // Unique id of the notification. - const std::string id_; - - DISALLOW_COPY_AND_ASSIGN(SigninNotificationDelegate); -}; - -SigninNotificationDelegate::SigninNotificationDelegate() = default; -SigninNotificationDelegate::~SigninNotificationDelegate() = default; - -void SigninNotificationDelegate::Click() { - chrome::AttemptUserExit(); -} - -void SigninNotificationDelegate::ButtonClick(int button_index) { +void HandleNotificationClick(base::Optional<int> button_index) { chrome::AttemptUserExit(); } @@ -93,16 +66,9 @@ } void SigninErrorNotifier::OnErrorChanged() { - NotificationUIManager* notification_ui_manager = - g_browser_process->notification_ui_manager(); - - // notification_ui_manager() may return NULL when shutting down. - if (!notification_ui_manager) - return; - if (!error_controller_->HasError()) { - g_browser_process->notification_ui_manager()->CancelById( - notification_id_, NotificationUIManager::GetProfileID(profile_)); + NotificationDisplayService::GetForProfile(profile_)->Close( + NotificationHandler::Type::TRANSIENT, notification_id_); return; } @@ -122,7 +88,6 @@ data.buttons.push_back(message_center::ButtonInfo( l10n_util::GetStringUTF16(IDS_SYNC_RELOGIN_LINK_LABEL))); - message_center::NotifierId notifier_id( message_center::NotifierId::SYSTEM_COMPONENT, kProfileSigninNotificationId); @@ -141,7 +106,8 @@ IDR_NOTIFICATION_ALERT), l10n_util::GetStringUTF16(IDS_SIGNIN_ERROR_DISPLAY_SOURCE), GURL(notification_id_), notifier_id, data, - new SigninNotificationDelegate()); + new message_center::HandleNotificationClickDelegate( + base::Bind(&HandleNotificationClick))); if (message_center::IsNewStyleNotificationEnabled()) { notification.set_accent_color( message_center::kSystemNotificationColorWarning); @@ -153,7 +119,8 @@ notification.SetSystemPriority(); // Update or add the notification. - notification_ui_manager->Add(notification, profile_); + NotificationDisplayService::GetForProfile(profile_)->Display( + NotificationHandler::Type::TRANSIENT, notification); } base::string16 SigninErrorNotifier::GetMessageBody() const {
diff --git a/chrome/browser/sync/sync_error_notifier_ash.cc b/chrome/browser/sync/sync_error_notifier_ash.cc index 20db1d380..38ed1e4c 100644 --- a/chrome/browser/sync/sync_error_notifier_ash.cc +++ b/chrome/browser/sync/sync_error_notifier_ash.cc
@@ -10,7 +10,8 @@ #include "chrome/browser/browser_process.h" #include "chrome/browser/chromeos/login/user_flow.h" #include "chrome/browser/chromeos/login/users/chrome_user_manager.h" -#include "chrome/browser/notifications/notification_ui_manager.h" +#include "chrome/browser/notifications/notification_common.h" +#include "chrome/browser/notifications/notification_display_service.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/ash/multi_user/multi_user_util.h" #include "chrome/browser/ui/chrome_pages.h" @@ -101,20 +102,14 @@ } void SyncErrorNotifier::OnErrorChanged() { - NotificationUIManager* notification_ui_manager = - g_browser_process->notification_ui_manager(); - - // notification_ui_manager() may return null when shutting down. - if (!notification_ui_manager) - return; - if (error_controller_->HasError() == notification_displayed_) return; + auto* display_service = NotificationDisplayService::GetForProfile(profile_); if (!error_controller_->HasError()) { notification_displayed_ = false; - g_browser_process->notification_ui_manager()->CancelById( - notification_id_, NotificationUIManager::GetProfileID(profile_)); + display_service->Close(NotificationHandler::Type::TRANSIENT, + notification_id_); return; } @@ -132,9 +127,6 @@ // Error state just got triggered. There shouldn't be previous notification. // Let's display one. DCHECK(!notification_displayed_ && error_controller_->HasError()); - DCHECK(notification_ui_manager->FindById( - notification_id_, NotificationUIManager::GetProfileID(profile_)) == - nullptr); message_center::NotifierId notifier_id( message_center::NotifierId::SYSTEM_COMPONENT, kProfileSyncNotificationId); @@ -165,6 +157,6 @@ notification.set_vector_small_image(kNotificationWarningIcon); } - notification_ui_manager->Add(notification, profile_); + display_service->Display(NotificationHandler::Type::TRANSIENT, notification); notification_displayed_ = true; }
diff --git a/chrome/browser/ui/ash/chrome_screenshot_grabber.cc b/chrome/browser/ui/ash/chrome_screenshot_grabber.cc index 7b26f8e9..74757217 100644 --- a/chrome/browser/ui/ash/chrome_screenshot_grabber.cc +++ b/chrome/browser/ui/ash/chrome_screenshot_grabber.cc
@@ -29,7 +29,7 @@ #include "chrome/browser/chromeos/file_manager/open_util.h" #include "chrome/browser/chromeos/note_taking_helper.h" #include "chrome/browser/download/download_prefs.h" -#include "chrome/browser/notifications/notification_ui_manager.h" +#include "chrome/browser/notifications/notification_display_service.h" #include "chrome/browser/platform_util.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_manager.h" @@ -560,8 +560,8 @@ const std::string notification_id(kNotificationId); // We cancel a previous screenshot notification, if any, to ensure we get // a fresh notification pop-up. - g_browser_process->notification_ui_manager()->CancelById( - notification_id, NotificationUIManager::GetProfileID(GetProfile())); + NotificationDisplayService::GetForProfile(GetProfile()) + ->Close(NotificationHandler::Type::TRANSIENT, notification_id); const bool success = (result == ui::ScreenshotGrabberObserver::SCREENSHOT_SUCCESS); @@ -618,7 +618,8 @@ notification.set_vector_small_image(kNotificationImageIcon); } - g_browser_process->notification_ui_manager()->Add(notification, GetProfile()); + NotificationDisplayService::GetForProfile(GetProfile()) + ->Display(NotificationHandler::Type::TRANSIENT, notification); } Profile* ChromeScreenshotGrabber::GetProfile() {
diff --git a/chrome/browser/ui/extensions/extension_installed_notification.cc b/chrome/browser/ui/extensions/extension_installed_notification.cc index a889531..a4f33faa 100644 --- a/chrome/browser/ui/extensions/extension_installed_notification.cc +++ b/chrome/browser/ui/extensions/extension_installed_notification.cc
@@ -8,7 +8,8 @@ #include "chrome/app/vector_icons/vector_icons.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/extensions/extension_util.h" -#include "chrome/browser/notifications/notification_ui_manager.h" +#include "chrome/browser/notifications/notification_common.h" +#include "chrome/browser/notifications/notification_display_service.h" #include "chrome/browser/ui/extensions/app_launch_params.h" #include "chrome/browser/ui/extensions/application_launch.h" #include "chrome/grit/generated_resources.h" @@ -34,7 +35,6 @@ void ExtensionInstalledNotification::Show( const extensions::Extension* extension, Profile* profile) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - DCHECK(g_browser_process->notification_ui_manager()); // It's lifetime is managed by the parent class NotificationDelegate. new ExtensionInstalledNotification(extension, profile); @@ -43,8 +43,6 @@ ExtensionInstalledNotification::ExtensionInstalledNotification( const extensions::Extension* extension, Profile* profile) : extension_id_(extension->id()), profile_(profile) { - - message_center::RichNotificationData optional_field; message_center::Notification notification( message_center::NOTIFICATION_TYPE_SIMPLE, extension_id_, base::UTF8ToUTF16(extension->name()), @@ -55,7 +53,7 @@ GURL(extension_urls::kChromeWebstoreBaseURL) /* origin_url */, message_center::NotifierId(message_center::NotifierId::SYSTEM_COMPONENT, kNotifierId), - optional_field, this); + {}, this); if (message_center::IsNewStyleNotificationEnabled()) { notification.set_icon(gfx::Image()); notification.set_accent_color( @@ -65,7 +63,8 @@ message_center::kSystemNotificationColorNormal))); notification.set_vector_small_image(kNotificationInstalledIcon); } - g_browser_process->notification_ui_manager()->Add(notification, profile_); + NotificationDisplayService::GetForProfile(profile_)->Display( + NotificationHandler::Type::TRANSIENT, notification); } ExtensionInstalledNotification::~ExtensionInstalledNotification() {}
diff --git a/chrome/browser/vr/BUILD.gn b/chrome/browser/vr/BUILD.gn index afadab0..f1971bf 100644 --- a/chrome/browser/vr/BUILD.gn +++ b/chrome/browser/vr/BUILD.gn
@@ -57,6 +57,8 @@ "elements/grid.h", "elements/invisible_hit_target.cc", "elements/invisible_hit_target.h", + "elements/keyboard.cc", + "elements/keyboard.h", "elements/laser.cc", "elements/laser.h", "elements/linear_layout.cc", @@ -122,10 +124,13 @@ "gltf_asset.h", "gltf_parser.cc", "gltf_parser.h", + "keyboard_delegate.h", + "keyboard_ui_interface.h", "macros.h", "metrics_helper.cc", "metrics_helper.h", "mode.h", + "model/camera_model.h", "model/color_scheme.cc", "model/color_scheme.h", "model/controller_model.h", @@ -138,6 +143,8 @@ "model/permissions_model.h", "model/reticle_model.h", "model/speech_recognition_model.h", + "model/text_input_info.cc", + "model/text_input_info.h", "model/toolbar_state.cc", "model/toolbar_state.h", "model/web_vr_timeout_state.h", @@ -169,6 +176,8 @@ "speech_recognizer.h", "target_property.cc", "target_property.h", + "text_input_delegate.cc", + "text_input_delegate.h", "toolbar_helper.cc", "toolbar_helper.h", "transition.cc", @@ -260,6 +269,7 @@ "test/run_all_unittests.cc", "test/ui_test.cc", "test/ui_test.h", + "text_input_unittest.cc", "ui_input_manager_unittest.cc", "ui_scene_unittest.cc", "ui_unittest.cc",
diff --git a/chrome/browser/vr/elements/keyboard.cc b/chrome/browser/vr/elements/keyboard.cc new file mode 100644 index 0000000..01b6126 --- /dev/null +++ b/chrome/browser/vr/elements/keyboard.cc
@@ -0,0 +1,99 @@ +// 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/vr/elements/keyboard.h" + +#include "chrome/browser/vr/controller_mesh.h" +#include "chrome/browser/vr/model/controller_model.h" +#include "chrome/browser/vr/ui_element_renderer.h" + +namespace vr { + +Keyboard::Keyboard() { + set_name(kKeyboard); + SetVisibleImmediately(false); +} + +Keyboard::~Keyboard() = default; + +void Keyboard::SetKeyboardDelegate(KeyboardDelegate* keyboard_delegate) { + delegate_ = keyboard_delegate; + UpdateDelegateVisibility(); +} + +void Keyboard::HitTest(const HitTestRequest& request, + HitTestResult* result) const { + if (!delegate_) + return; + + result->type = HitTestResult::Type::kNone; + gfx::Point3F hit_point; + if (!delegate_->HitTest(request.ray_origin, request.ray_target, &hit_point)) + return; + + float distance_to_plane = (hit_point - request.ray_origin).Length(); + if (distance_to_plane < 0 || + distance_to_plane > request.max_distance_to_plane) { + return; + } + + result->type = HitTestResult::Type::kHits; + result->distance_to_plane = distance_to_plane; + result->hit_point = hit_point; + // The local hit point is unused since the keyboard delegate does the + // local hittesting for us. + result->local_hit_point = gfx::PointF(0, 0); +} + +void Keyboard::NotifyClientFloatAnimated(float value, + int target_property_id, + cc::Animation* animation) { + DCHECK(target_property_id == OPACITY); + UiElement::NotifyClientFloatAnimated(value, target_property_id, animation); + UpdateDelegateVisibility(); +} + +void Keyboard::NotifyClientTransformOperationsAnimated( + const cc::TransformOperations& operations, + int target_property_id, + cc::Animation* animation) { + UiElement::NotifyClientTransformOperationsAnimated( + operations, target_property_id, animation); + if (!delegate_) + return; + + delegate_->SetTransform(LocalTransform()); +} + +bool Keyboard::OnBeginFrame(const base::TimeTicks& time, + const gfx::Vector3dF& head_direction) { + if (!delegate_) + return false; + + delegate_->OnBeginFrame(); + // We return false here because any visible changes to the keyboard, such as + // hover effects and showing/hiding of the keyboard will be drawn by the + // controller's dirtyness, so it's safe to assume not visual changes here. + return false; +} + +void Keyboard::Render(UiElementRenderer* renderer, + const CameraModel& camera_model) const { + if (!delegate_) + return; + + delegate_->Draw(camera_model); +} + +void Keyboard::UpdateDelegateVisibility() { + if (!delegate_) + return; + + if (opacity() > 0) + delegate_->ShowKeyboard(); + else + delegate_->HideKeyboard(); +} + +} // namespace vr
diff --git a/chrome/browser/vr/elements/keyboard.h b/chrome/browser/vr/elements/keyboard.h new file mode 100644 index 0000000..a052730 --- /dev/null +++ b/chrome/browser/vr/elements/keyboard.h
@@ -0,0 +1,47 @@ +// 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_VR_ELEMENTS_KEYBOARD_H_ +#define CHROME_BROWSER_VR_ELEMENTS_KEYBOARD_H_ + +#include "base/macros.h" +#include "chrome/browser/vr/elements/ui_element.h" +#include "chrome/browser/vr/keyboard_delegate.h" + +namespace vr { + +// Represents the virtual keyboard. This element is a proxy to the +// platform-specific keyboard implementation. +class Keyboard : public UiElement { + public: + Keyboard(); + ~Keyboard() override; + + void SetKeyboardDelegate(KeyboardDelegate* keyboard_delegate); + void HitTest(const HitTestRequest& request, + HitTestResult* result) const final; + void NotifyClientFloatAnimated(float value, + int target_property_id, + cc::Animation* animation) override; + void NotifyClientTransformOperationsAnimated( + const cc::TransformOperations& operations, + int target_property_id, + cc::Animation* animation) override; + + private: + bool OnBeginFrame(const base::TimeTicks& time, + const gfx::Vector3dF& head_direction) override; + void Render(UiElementRenderer* renderer, + const CameraModel& camera_model) const final; + + void UpdateDelegateVisibility(); + + KeyboardDelegate* delegate_ = nullptr; + + DISALLOW_COPY_AND_ASSIGN(Keyboard); +}; + +} // namespace vr + +#endif // CHROME_BROWSER_VR_ELEMENTS_KEYBOARD_H_
diff --git a/chrome/browser/vr/elements/text_input.cc b/chrome/browser/vr/elements/text_input.cc index 07d35b5c..cbd93505 100644 --- a/chrome/browser/vr/elements/text_input.cc +++ b/chrome/browser/vr/elements/text_input.cc
@@ -83,39 +83,72 @@ TextInput::TextInput(int maximum_width_pixels, float font_height_meters, - float text_width_meters) + float text_width_meters, + OnFocusChangedCallback focus_changed_callback, + OnInputEditedCallback input_edit_callback) : TexturedElement(maximum_width_pixels), texture_(base::MakeUnique<TextInputTexture>(font_height_meters, - text_width_meters)) { + text_width_meters)), + focus_changed_callback_(focus_changed_callback), + input_edit_callback_(input_edit_callback) { SetSize(text_width_meters, font_height_meters); } + TextInput::~TextInput() {} -void TextInput::SetText(const base::string16& text) { - if (text_ == text) +void TextInput::SetTextInputDelegate(TextInputDelegate* text_input_delegate) { + delegate_ = text_input_delegate; +} + +bool TextInput::IsEditable() { + return true; +} + +void TextInput::OnButtonUp(const gfx::PointF& position) { + if (!delegate_) return; - text_ = text; - texture_->SetText(text); - if (text_changed_callback_) - text_changed_callback_.Run(text); + + delegate_->RequestFocus(id()); } -void TextInput::SetCursorPosition(int position) { - texture_->SetCursorPosition(position); +void TextInput::OnFocusChanged(bool focused) { + focused_ = focused; + texture_->SetCursorVisible(focused); + // Update the keyboard with the current text. + if (delegate_ && focused) + delegate_->UpdateInput(text_info_); + + focus_changed_callback_.Run(focused); } -void TextInput::SetTextChangedCallback(const TextInputCallback& callback) { - text_changed_callback_ = callback; +void TextInput::OnInputEdited(const TextInputInfo& info) { + input_edit_callback_.Run(info); } +void TextInput::OnInputCommitted(const TextInputInfo& info) {} + void TextInput::SetColor(SkColor color) { texture_->SetColor(color); } +void TextInput::UpdateInput(const TextInputInfo& info) { + if (text_info_ == info) + return; + + text_info_ = info; + texture_->SetText(info.text); + texture_->SetCursorPosition(info.selection_end); + + if (delegate_ && focused_) + delegate_->UpdateInput(info); +} + bool TextInput::OnBeginFrame(const base::TimeTicks& time, const gfx::Vector3dF& look_at) { base::TimeDelta delta = time - base::TimeTicks(); - texture_->SetCursorVisible(delta.InMilliseconds() / 500 % 2); + if (focused_) + texture_->SetCursorVisible(delta.InMilliseconds() / 500 % 2); + return false; }
diff --git a/chrome/browser/vr/elements/text_input.h b/chrome/browser/vr/elements/text_input.h index c3416d4..f998643 100644 --- a/chrome/browser/vr/elements/text_input.h +++ b/chrome/browser/vr/elements/text_input.h
@@ -10,6 +10,8 @@ #include "base/callback.h" #include "chrome/browser/vr/elements/textured_element.h" #include "chrome/browser/vr/elements/ui_texture.h" +#include "chrome/browser/vr/model/text_input_info.h" +#include "chrome/browser/vr/text_input_delegate.h" #include "third_party/skia/include/core/SkColor.h" namespace vr { @@ -21,17 +23,27 @@ // the keyboard and omnibox. class TextInput : public TexturedElement { public: + // Called when this element recieves focus. + typedef base::RepeatingCallback<void(bool)> OnFocusChangedCallback; + // Called when the user enters text while this element is focused. + typedef base::RepeatingCallback<void(const TextInputInfo&)> + OnInputEditedCallback; TextInput(int maximum_width_pixels, float font_height_meters, - float text_width_meters); + float text_width_meters, + OnFocusChangedCallback focus_changed_callback, + OnInputEditedCallback input_edit_callback); ~TextInput() override; - void SetText(const base::string16& text); - void SetCursorPosition(int position); - void SetColor(SkColor color); + bool IsEditable() override; + void OnButtonUp(const gfx::PointF& position) override; + void OnFocusChanged(bool focused) override; + void OnInputEdited(const TextInputInfo& info) override; + void OnInputCommitted(const TextInputInfo& info) override; - typedef base::Callback<void(const base::string16& text)> TextInputCallback; - void SetTextChangedCallback(const TextInputCallback& callback); + void SetTextInputDelegate(TextInputDelegate* text_input_delegate); + void SetColor(SkColor color); + void UpdateInput(const TextInputInfo& info); bool OnBeginFrame(const base::TimeTicks& time, const gfx::Vector3dF& look_at) override; @@ -40,8 +52,11 @@ UiTexture* GetTexture() const override; std::unique_ptr<TextInputTexture> texture_; - TextInputCallback text_changed_callback_; - base::string16 text_; + OnFocusChangedCallback focus_changed_callback_; + OnInputEditedCallback input_edit_callback_; + TextInputDelegate* delegate_ = nullptr; + TextInputInfo text_info_; + bool focused_ = false; DISALLOW_COPY_AND_ASSIGN(TextInput); };
diff --git a/chrome/browser/vr/elements/ui_element.cc b/chrome/browser/vr/elements/ui_element.cc index a9585e0..39b56dd 100644 --- a/chrome/browser/vr/elements/ui_element.cc +++ b/chrome/browser/vr/elements/ui_element.cc
@@ -11,6 +11,7 @@ #include "base/stl_util.h" #include "base/strings/stringprintf.h" #include "base/time/time.h" +#include "chrome/browser/vr/model/camera_model.h" #include "third_party/WebKit/public/platform/WebGestureEvent.h" #include "third_party/skia/include/core/SkRRect.h" #include "third_party/skia/include/core/SkRect.h" @@ -148,6 +149,18 @@ void UiElement::OnScrollEnd(std::unique_ptr<blink::WebGestureEvent> gesture, const gfx::PointF& position) {} +void UiElement::OnFocusChanged(bool focused) { + NOTREACHED(); +} + +void UiElement::OnInputEdited(const TextInputInfo& info) { + NOTREACHED(); +} + +void UiElement::OnInputCommitted(const TextInputInfo& info) { + NOTREACHED(); +} + bool UiElement::PrepareToDraw() { return false; } @@ -177,6 +190,10 @@ return IsVisible() && hit_testable_; } +bool UiElement::IsEditable() { + return false; +} + void UiElement::SetSize(float width, float height) { animation_player_.TransitionSizeTo(last_frame_time_, BOUNDS, size_, gfx::SizeF(width, height));
diff --git a/chrome/browser/vr/elements/ui_element.h b/chrome/browser/vr/elements/ui_element.h index f51d9b7..34a2325 100644 --- a/chrome/browser/vr/elements/ui_element.h +++ b/chrome/browser/vr/elements/ui_element.h
@@ -43,6 +43,7 @@ class SkiaSurfaceProvider; class UiElementRenderer; struct CameraModel; +struct TextInputInfo; enum LayoutAlignment { NONE = 0, @@ -139,6 +140,10 @@ // Indicates whether the element should be tested for cursor input. bool IsHitTestable() const; + // Indicates whether the element is an editable element. Editable elements + // such as the input field should override this. + virtual bool IsEditable(); + virtual void Render(UiElementRenderer* renderer, const CameraModel& model) const; @@ -172,7 +177,8 @@ // Performs a hit test for the ray supplied in the request and populates the // result. The ray is in the world coordinate space. - void HitTest(const HitTestRequest& request, HitTestResult* result) const; + virtual void HitTest(const HitTestRequest& request, + HitTestResult* result) const; int id() const { return id_; } @@ -205,6 +211,11 @@ event_handlers_ = event_handlers; } + // Editable elements should override these functions. + virtual void OnFocusChanged(bool focused); + virtual void OnInputEdited(const TextInputInfo& info); + virtual void OnInputCommitted(const TextInputInfo& info); + gfx::SizeF size() const; void SetSize(float width, float hight); virtual void OnSetSize(gfx::SizeF size);
diff --git a/chrome/browser/vr/elements/ui_element_name.cc b/chrome/browser/vr/elements/ui_element_name.cc index c93fad07..73fd82b31 100644 --- a/chrome/browser/vr/elements/ui_element_name.cc +++ b/chrome/browser/vr/elements/ui_element_name.cc
@@ -27,6 +27,7 @@ "kLaser", "kController", "kReticle", + "kKeyboard", "kBackplane", "kCeiling", "kFloor",
diff --git a/chrome/browser/vr/elements/ui_element_name.h b/chrome/browser/vr/elements/ui_element_name.h index 658a647..debe1898 100644 --- a/chrome/browser/vr/elements/ui_element_name.h +++ b/chrome/browser/vr/elements/ui_element_name.h
@@ -26,6 +26,7 @@ kLaser, kController, kReticle, + kKeyboard, kBackplane, kCeiling, kFloor,
diff --git a/chrome/browser/vr/elements/ui_texture.cc b/chrome/browser/vr/elements/ui_texture.cc index d5aa73a..a426b79 100644 --- a/chrome/browser/vr/elements/ui_texture.cc +++ b/chrome/browser/vr/elements/ui_texture.cc
@@ -51,7 +51,7 @@ Draw(canvas, texture_size); } -bool UiTexture::HitTest(const gfx::PointF& point) const { +bool UiTexture::LocalHitTest(const gfx::PointF& point) const { return false; }
diff --git a/chrome/browser/vr/elements/ui_texture.h b/chrome/browser/vr/elements/ui_texture.h index d16c3887b..bf5c55c 100644 --- a/chrome/browser/vr/elements/ui_texture.h +++ b/chrome/browser/vr/elements/ui_texture.h
@@ -36,7 +36,7 @@ void DrawAndLayout(SkCanvas* canvas, const gfx::Size& texture_size); virtual gfx::Size GetPreferredTextureSize(int maximum_width) const = 0; virtual gfx::SizeF GetDrawnSize() const = 0; - virtual bool HitTest(const gfx::PointF& point) const; + virtual bool LocalHitTest(const gfx::PointF& point) const; bool dirty() const { return dirty_; }
diff --git a/chrome/browser/vr/keyboard_delegate.h b/chrome/browser/vr/keyboard_delegate.h new file mode 100644 index 0000000..b2ccf9f0 --- /dev/null +++ b/chrome/browser/vr/keyboard_delegate.h
@@ -0,0 +1,35 @@ +// 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_VR_KEYBOARD_DELEGATE_H_ +#define CHROME_BROWSER_VR_KEYBOARD_DELEGATE_H_ + +#include "base/memory/weak_ptr.h" + +namespace gfx { +class Point3F; +class Transform; +} // namespace gfx + +namespace vr { + +struct CameraModel; + +class KeyboardDelegate { + public: + virtual ~KeyboardDelegate() {} + + virtual void ShowKeyboard() = 0; + virtual void HideKeyboard() = 0; + virtual void SetTransform(const gfx::Transform&) = 0; + virtual bool HitTest(const gfx::Point3F& ray_origin, + const gfx::Point3F& ray_target, + gfx::Point3F* hit_position) = 0; + virtual void OnBeginFrame() {} + virtual void Draw(const CameraModel&) = 0; +}; + +} // namespace vr + +#endif // CHROME_BROWSER_VR_KEYBOARD_DELEGATE_H_
diff --git a/chrome/browser/vr/keyboard_ui_interface.h b/chrome/browser/vr/keyboard_ui_interface.h new file mode 100644 index 0000000..d16c4b23 --- /dev/null +++ b/chrome/browser/vr/keyboard_ui_interface.h
@@ -0,0 +1,26 @@ +// 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_VR_KEYBOARD_UI_INTERFACE_H_ +#define CHROME_BROWSER_VR_KEYBOARD_UI_INTERFACE_H_ + +#include "chrome/browser/vr/model/text_input_info.h" + +namespace vr { + +// The keyboard communicates state changes to the VR UI via this interface. Note +// that we have this interface to restrict the UI API to keyboard-specific +// callback functions because the keyboard delegate doesn't need access to all +// of the UI. +class KeyboardUiInterface { + public: + virtual ~KeyboardUiInterface() {} + virtual void OnInputEdited(const TextInputInfo& info) = 0; + virtual void OnInputCommitted(const TextInputInfo& info) = 0; + virtual void OnKeyboardHidden() = 0; +}; + +} // namespace vr + +#endif // CHROME_BROWSER_VR_KEYBOARD_UI_INTERFACE_H_
diff --git a/chrome/browser/vr/model/model.h b/chrome/browser/vr/model/model.h index 4ac415e..c0fc8e43 100644 --- a/chrome/browser/vr/model/model.h +++ b/chrome/browser/vr/model/model.h
@@ -12,6 +12,7 @@ #include "chrome/browser/vr/model/permissions_model.h" #include "chrome/browser/vr/model/reticle_model.h" #include "chrome/browser/vr/model/speech_recognition_model.h" +#include "chrome/browser/vr/model/text_input_info.h" #include "chrome/browser/vr/model/toolbar_state.h" #include "chrome/browser/vr/model/web_vr_timeout_state.h" #include "chrome/browser/vr/ui_element_renderer.h" @@ -60,6 +61,10 @@ } WebVrTimeoutState web_vr_timeout_state = kWebVrNoTimeoutPending; + // Focused text state. + bool editing_input = false; + TextInputInfo omnibox_text_field_info; + // Controller state. ControllerModel controller; ReticleModel reticle;
diff --git a/chrome/browser/vr/model/text_input_info.cc b/chrome/browser/vr/model/text_input_info.cc new file mode 100644 index 0000000..263721d --- /dev/null +++ b/chrome/browser/vr/model/text_input_info.cc
@@ -0,0 +1,22 @@ +// 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/vr/model/text_input_info.h" + +namespace vr { + +TextInputInfo::TextInputInfo() : selection_start(0), selection_end(0) {} +TextInputInfo::TextInputInfo(base::string16 t) + : text(t), selection_start(t.length()), selection_end(t.length()) {} + +bool TextInputInfo::operator==(const TextInputInfo& other) const { + return text == other.text && selection_start == other.selection_start && + selection_end == other.selection_end; +} + +bool TextInputInfo::operator!=(const TextInputInfo& other) const { + return !(*this == other); +} + +} // namespace vr
diff --git a/chrome/browser/vr/model/text_input_info.h b/chrome/browser/vr/model/text_input_info.h new file mode 100644 index 0000000..3a6f836 --- /dev/null +++ b/chrome/browser/vr/model/text_input_info.h
@@ -0,0 +1,35 @@ +// 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_VR_MODEL_TEXT_INPUT_INFO_H_ +#define CHROME_BROWSER_VR_MODEL_TEXT_INPUT_INFO_H_ + +#include "base/strings/string16.h" + +namespace vr { + +// Represents the state of an editable text field. +struct TextInputInfo { + public: + TextInputInfo(); + explicit TextInputInfo(base::string16 t); + + bool operator==(const TextInputInfo& other) const; + bool operator!=(const TextInputInfo& other) const; + + // The value of the input field. + base::string16 text; + + // The cursor position of the current selection start, or the caret position + // if nothing is selected. + int selection_start; + + // The cursor position of the current selection end, or the caret position + // if nothing is selected. + int selection_end; +}; + +} // namespace vr + +#endif // CHROME_BROWSER_VR_MODEL_TEXT_INPUT_INFO_H_
diff --git a/chrome/browser/vr/test/ui_pixel_test.cc b/chrome/browser/vr/test/ui_pixel_test.cc index 261e103..3dc9f59 100644 --- a/chrome/browser/vr/test/ui_pixel_test.cc +++ b/chrome/browser/vr/test/ui_pixel_test.cc
@@ -56,7 +56,8 @@ void UiPixelTest::MakeUi(const UiInitialState& ui_initial_state, const ToolbarState& toolbar_state) { - ui_ = base::MakeUnique<Ui>(browser_.get(), nullptr, ui_initial_state); + ui_ = base::MakeUnique<Ui>(browser_.get(), nullptr, nullptr, nullptr, + ui_initial_state); ui_->OnGlInitialized(content_texture_, vr::UiElementRenderer::kTextureLocationLocal, true); ui_->GetBrowserUiWeakPtr()->SetToolbarState(toolbar_state);
diff --git a/chrome/browser/vr/test/ui_test.cc b/chrome/browser/vr/test/ui_test.cc index db680d5..4fbeac6c 100644 --- a/chrome/browser/vr/test/ui_test.cc +++ b/chrome/browser/vr/test/ui_test.cc
@@ -248,9 +248,9 @@ ui_initial_state.in_cct = in_cct; ui_initial_state.in_web_vr = in_web_vr; ui_initial_state.web_vr_autopresentation_expected = web_vr_autopresented; - ui_ = - base::MakeUnique<Ui>(std::move(browser_.get()), - std::move(content_input_delegate), ui_initial_state); + ui_ = base::MakeUnique<Ui>(std::move(browser_.get()), + std::move(content_input_delegate), nullptr, + nullptr, ui_initial_state); scene_ = ui_->scene(); model_ = ui_->model_for_test();
diff --git a/chrome/browser/vr/testapp/vr_test_context.cc b/chrome/browser/vr/testapp/vr_test_context.cc index f3726a2..d70b00c2 100644 --- a/chrome/browser/vr/testapp/vr_test_context.cc +++ b/chrome/browser/vr/testapp/vr_test_context.cc
@@ -64,7 +64,7 @@ base::i18n::InitializeICU(); - ui_ = base::MakeUnique<Ui>(this, nullptr, UiInitialState()); + ui_ = base::MakeUnique<Ui>(this, nullptr, nullptr, nullptr, UiInitialState()); model_ = ui_->model_for_test(); ToolbarState state(GURL("https://dangerous.com/dir/file.html"),
diff --git a/chrome/browser/vr/text_input_delegate.cc b/chrome/browser/vr/text_input_delegate.cc new file mode 100644 index 0000000..b293d2e --- /dev/null +++ b/chrome/browser/vr/text_input_delegate.cc
@@ -0,0 +1,34 @@ +// 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/vr/text_input_delegate.h" +#include "chrome/browser/vr/model/text_input_info.h" + +namespace vr { + +TextInputDelegate::TextInputDelegate() {} + +TextInputDelegate::~TextInputDelegate() = default; + +void TextInputDelegate::SetRequestFocusCallback( + const RequestFocusCallback& callback) { + request_focus_callback_ = callback; +} + +void TextInputDelegate::SetUpdateInputCallback( + const UpdateInputCallback& callback) { + update_input_callback_ = callback; +} + +void TextInputDelegate::RequestFocus(int element_id) { + if (!request_focus_callback_.is_null()) + request_focus_callback_.Run(element_id); +} + +void TextInputDelegate::UpdateInput(const vr::TextInputInfo& info) { + if (!update_input_callback_.is_null()) + update_input_callback_.Run(info); +} + +} // namespace vr
diff --git a/chrome/browser/vr/text_input_delegate.h b/chrome/browser/vr/text_input_delegate.h new file mode 100644 index 0000000..001f386c6 --- /dev/null +++ b/chrome/browser/vr/text_input_delegate.h
@@ -0,0 +1,42 @@ +// 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_VR_TEXT_INPUT_DELEGATE_H_ +#define CHROME_BROWSER_VR_TEXT_INPUT_DELEGATE_H_ + +#include "base/callback.h" +#include "base/macros.h" + +namespace vr { + +struct TextInputInfo; + +class TextInputDelegate { + public: + TextInputDelegate(); + virtual ~TextInputDelegate(); + + // RequestFocusCallback gets called when an element request's focus. + typedef base::RepeatingCallback<void(int)> RequestFocusCallback; + // UpdateInputCallback gets called when the text input info changes for the + // element being edited. + typedef base::RepeatingCallback<void(const TextInputInfo&)> + UpdateInputCallback; + + void SetRequestFocusCallback(const RequestFocusCallback& callback); + void SetUpdateInputCallback(const UpdateInputCallback& callback); + + virtual void RequestFocus(int element_id); + virtual void UpdateInput(const TextInputInfo& info); + + private: + RequestFocusCallback request_focus_callback_; + UpdateInputCallback update_input_callback_; + + DISALLOW_COPY_AND_ASSIGN(TextInputDelegate); +}; + +} // namespace vr + +#endif // CHROME_BROWSER_VR_TEXT_INPUT_DELEGATE_H_
diff --git a/chrome/browser/vr/text_input_unittest.cc b/chrome/browser/vr/text_input_unittest.cc new file mode 100644 index 0000000..094ad9b3 --- /dev/null +++ b/chrome/browser/vr/text_input_unittest.cc
@@ -0,0 +1,148 @@ +// 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/vr/ui_input_manager.h" + +#include <memory> + +#include "base/memory/ptr_util.h" +#include "base/strings/utf_string_conversions.h" +#include "build/build_config.h" +#include "chrome/browser/vr/databinding/binding.h" +#include "chrome/browser/vr/elements/keyboard.h" +#include "chrome/browser/vr/elements/ui_element.h" +#include "chrome/browser/vr/keyboard_delegate.h" +#include "chrome/browser/vr/model/camera_model.h" +#include "chrome/browser/vr/model/model.h" +#include "chrome/browser/vr/test/constants.h" +#include "chrome/browser/vr/test/ui_test.h" +#include "chrome/browser/vr/text_input_delegate.h" +#include "chrome/browser/vr/ui_scene.h" +#include "chrome/browser/vr/ui_scene_constants.h" +#include "chrome/browser/vr/ui_scene_creator.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "third_party/WebKit/public/platform/WebGestureEvent.h" + +using ::testing::_; +using ::testing::InSequence; +using ::testing::StrictMock; + +namespace vr { + +namespace { + +#if defined(OS_LINUX) +// The purpose here is to catch forgetting to update operator==. Ideally this +// should go in TextInputInfo, but the size of base::string16 varies accross +// platforms (i.e 24 bytes on linux and 20 bytes on android), so we can't add it +// there in a generic way. +static constexpr size_t kTextInputInfoSize = 32; +static_assert(kTextInputInfoSize == sizeof(TextInputInfo), + "If new fields are added to TextInputInfo, we must explicitly " + "bump this size and update operator== below"); +#endif + +} // namespace + +class MockTextInputDelegate : public TextInputDelegate { + public: + MockTextInputDelegate() = default; + ~MockTextInputDelegate() override = default; + + MOCK_METHOD1(UpdateInput, void(const TextInputInfo& info)); + MOCK_METHOD1(RequestFocus, void(int)); + + private: + DISALLOW_COPY_AND_ASSIGN(MockTextInputDelegate); +}; + +class MockKeyboardDelegate : public KeyboardDelegate { + public: + MockKeyboardDelegate() = default; + ~MockKeyboardDelegate() override = default; + + MOCK_METHOD0(ShowKeyboard, void()); + MOCK_METHOD0(HideKeyboard, void()); + MOCK_METHOD1(SetTransform, void(const gfx::Transform&)); + MOCK_METHOD3(HitTest, + bool(const gfx::Point3F&, const gfx::Point3F&, gfx::Point3F*)); + MOCK_METHOD0(OnBeginFrame, void()); + MOCK_METHOD1(Draw, void(const CameraModel&)); + + private: + DISALLOW_COPY_AND_ASSIGN(MockKeyboardDelegate); +}; + +class TextInputTest : public UiTest { + public: + void SetUp() override { + UiTest::SetUp(); + CreateScene(kNotInCct, kNotInWebVr); + + // Make test text input. + text_input_delegate_ = + base::MakeUnique<StrictMock<MockTextInputDelegate>>(); + text_input_info_ = base::MakeUnique<TextInputInfo>(); + auto text_input = UiSceneCreator::CreateTextInput( + 512, 1, 1, model_, text_input_info_.get(), text_input_delegate_.get()); + text_input_ = text_input.get(); + scene_->AddUiElement(k2dBrowsingForeground, std::move(text_input)); + EXPECT_TRUE(OnBeginFrame()); + } + + protected: + TextInput* text_input_; + std::unique_ptr<StrictMock<MockTextInputDelegate>> text_input_delegate_; + std::unique_ptr<TextInputInfo> text_input_info_; + testing::Sequence in_sequence_; +}; + +TEST_F(TextInputTest, InputFieldFocus) { + // Set mock delegates. + auto* kb = static_cast<Keyboard*>(scene_->GetUiElementByName(kKeyboard)); + auto kb_delegate = base::MakeUnique<StrictMock<MockKeyboardDelegate>>(); + EXPECT_CALL(*kb_delegate, HideKeyboard()).InSequence(in_sequence_); + kb->SetKeyboardDelegate(kb_delegate.get()); + + // Clicking on the text field should request focus. + EXPECT_CALL(*text_input_delegate_, RequestFocus(_)).InSequence(in_sequence_); + text_input_->OnButtonUp(gfx::PointF()); + + // Focusing on an input field should show the keyboard and tell the delegate + // the field's content. + EXPECT_CALL(*text_input_delegate_, UpdateInput(_)).InSequence(in_sequence_); + text_input_->OnFocusChanged(true); + EXPECT_CALL(*kb_delegate, ShowKeyboard()).InSequence(in_sequence_); + EXPECT_CALL(*kb_delegate, OnBeginFrame()).InSequence(in_sequence_); + EXPECT_CALL(*kb_delegate, SetTransform(_)).InSequence(in_sequence_); + EXPECT_TRUE(OnBeginFrame()); + + // Focusing out of an input field should hide the keyboard. + text_input_->OnFocusChanged(false); + EXPECT_CALL(*kb_delegate, HideKeyboard()).InSequence(in_sequence_); + EXPECT_CALL(*kb_delegate, OnBeginFrame()).InSequence(in_sequence_); + EXPECT_CALL(*kb_delegate, SetTransform(_)).InSequence(in_sequence_); + EXPECT_TRUE(OnBeginFrame()); +} + +TEST_F(TextInputTest, InputFieldEdit) { + // UpdateInput should not be called if the text input doesn't have focus. + EXPECT_CALL(*text_input_delegate_, UpdateInput(_)) + .Times(0) + .InSequence(in_sequence_); + text_input_->OnFocusChanged(false); + + // Focus on input field. + EXPECT_CALL(*text_input_delegate_, UpdateInput(_)).InSequence(in_sequence_); + text_input_->OnFocusChanged(true); + + // Edits from the keyboard update the underlying text input model. + EXPECT_CALL(*text_input_delegate_, UpdateInput(_)).InSequence(in_sequence_); + TextInputInfo info(base::ASCIIToUTF16("asdfg")); + text_input_->OnInputEdited(info); + EXPECT_TRUE(OnBeginFrame()); + EXPECT_EQ(info, *text_input_info_); +} + +} // namespace vr
diff --git a/chrome/browser/vr/ui.cc b/chrome/browser/vr/ui.cc index 9688e79..7a3c296 100644 --- a/chrome/browser/vr/ui.cc +++ b/chrome/browser/vr/ui.cc
@@ -12,7 +12,9 @@ #include "base/threading/thread_task_runner_handle.h" #include "chrome/browser/vr/content_input_delegate.h" #include "chrome/browser/vr/cpu_surface_provider.h" +#include "chrome/browser/vr/elements/text_input.h" #include "chrome/browser/vr/ganesh_surface_provider.h" +#include "chrome/browser/vr/keyboard_delegate.h" #include "chrome/browser/vr/model/model.h" #include "chrome/browser/vr/model/omnibox_suggestions.h" #include "chrome/browser/vr/speech_recognizer.h" @@ -28,13 +30,19 @@ Ui::Ui(UiBrowserInterface* browser, ContentInputForwarder* content_input_forwarder, + vr::KeyboardDelegate* keyboard_delegate, + vr::TextInputDelegate* text_input_delegate, const UiInitialState& ui_initial_state) : Ui(browser, base::MakeUnique<ContentInputDelegate>(content_input_forwarder), + keyboard_delegate, + text_input_delegate, ui_initial_state) {} Ui::Ui(UiBrowserInterface* browser, std::unique_ptr<ContentInputDelegate> content_input_delegate, + vr::KeyboardDelegate* keyboard_delegate, + vr::TextInputDelegate* text_input_delegate, const UiInitialState& ui_initial_state) : browser_(browser), scene_(base::MakeUnique<UiScene>()), @@ -44,7 +52,7 @@ weak_ptr_factory_(this) { InitializeModel(ui_initial_state); UiSceneCreator(browser, scene_.get(), content_input_delegate_.get(), - model_.get()) + keyboard_delegate, text_input_delegate, model_.get()) .CreateScene(); } @@ -185,6 +193,22 @@ model_->content_location = content_location; } +void Ui::RequestFocus(int element_id) { + input_manager_->RequestFocus(element_id); +} + +void Ui::OnInputEdited(const TextInputInfo& info) { + input_manager_->OnInputEdited(info); +} + +void Ui::OnInputCommitted(const TextInputInfo& info) { + input_manager_->OnInputCommitted(info); +} + +void Ui::OnKeyboardHidden() { + input_manager_->OnKeyboardHidden(); +} + void Ui::OnAppButtonClicked() { // App button clicks should be a no-op when auto-presenting WebVR. if (model_->web_vr_started_for_autopresentation) {
diff --git a/chrome/browser/vr/ui.h b/chrome/browser/vr/ui.h index a1b8a7c..d0f2ed4 100644 --- a/chrome/browser/vr/ui.h +++ b/chrome/browser/vr/ui.h
@@ -10,6 +10,7 @@ #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "chrome/browser/vr/browser_ui_interface.h" +#include "chrome/browser/vr/keyboard_ui_interface.h" #include "chrome/browser/vr/platform_controller.h" #include "chrome/browser/vr/ui_element_renderer.h" @@ -17,7 +18,9 @@ class BrowserUiInterface; class ContentInputDelegate; class ContentInputForwarder; +class KeyboardDelegate; class SkiaSurfaceProvider; +class TextInputDelegate; class UiBrowserInterface; class UiInputManager; class UiRenderer; @@ -38,14 +41,18 @@ // This class manages all GLThread owned objects and GL rendering for VrShell. // It is not threadsafe and must only be used on the GL thread. -class Ui : public BrowserUiInterface { +class Ui : public BrowserUiInterface, public KeyboardUiInterface { public: Ui(UiBrowserInterface* browser, ContentInputForwarder* content_input_forwarder, + vr::KeyboardDelegate* keyboard_delegate, + vr::TextInputDelegate* text_input_delegate, const UiInitialState& ui_initial_state); Ui(UiBrowserInterface* browser, std::unique_ptr<ContentInputDelegate> content_input_delegate, + vr::KeyboardDelegate* keyboard_delegate, + vr::TextInputDelegate* text_input_delegate, const UiInitialState& ui_initial_state); ~Ui() override; @@ -106,6 +113,12 @@ void Dump(); + // Keyboard input related. + void RequestFocus(int element_id); + void OnInputEdited(const TextInputInfo& info) override; + void OnInputCommitted(const TextInputInfo& info) override; + void OnKeyboardHidden() override; + private: void InitializeModel(const UiInitialState& ui_initial_state); UiBrowserInterface* browser_;
diff --git a/chrome/browser/vr/ui_input_manager.cc b/chrome/browser/vr/ui_input_manager.cc index 7fee3b3..7a883b4 100644 --- a/chrome/browser/vr/ui_input_manager.cc +++ b/chrome/browser/vr/ui_input_manager.cc
@@ -11,6 +11,7 @@ #include "chrome/browser/vr/elements/ui_element.h" #include "chrome/browser/vr/model/controller_model.h" #include "chrome/browser/vr/model/reticle_model.h" +#include "chrome/browser/vr/model/text_input_info.h" #include "chrome/browser/vr/ui_renderer.h" #include "chrome/browser/vr/ui_scene.h" // TODO(tiborg): Remove include once we use a generic type to pass scroll/fling @@ -322,6 +323,12 @@ if (target) { target->OnButtonDown(target_point); input_locked_element_id_ = target->id(); + // Clicking outside of the focused element causes it to lose focus. + // TODO(ymalik): We will lose focus if we hit an element inside the focused + // element, which is incorrect behavior. + if (target->id() != focused_element_id_ && target->name() != kKeyboard) { + UnfocusFocusedElement(); + } } else { input_locked_element_id_ = 0; } @@ -421,4 +428,47 @@ } } +void UiInputManager::UnfocusFocusedElement() { + if (!focused_element_id_) + return; + + UiElement* focused = scene_->GetUiElementById(focused_element_id_); + if (focused && focused->IsEditable()) { + focused->OnFocusChanged(false); + } + focused_element_id_ = -1; +} + +void UiInputManager::RequestFocus(int element_id) { + if (element_id == focused_element_id_) + return; + + UnfocusFocusedElement(); + + UiElement* focused = scene_->GetUiElementById(element_id); + if (!focused || !focused->IsEditable()) + return; + + focused_element_id_ = element_id; + focused->OnFocusChanged(true); +} + +void UiInputManager::OnInputEdited(const TextInputInfo& info) { + UiElement* focused = scene_->GetUiElementById(focused_element_id_); + if (!focused || !focused->IsEditable()) + return; + focused->OnInputEdited(info); +} + +void UiInputManager::OnInputCommitted(const TextInputInfo& info) { + UiElement* focused = scene_->GetUiElementById(focused_element_id_); + if (!focused || !focused->IsEditable()) + return; + focused->OnInputCommitted(info); +} + +void UiInputManager::OnKeyboardHidden() { + UnfocusFocusedElement(); +} + } // namespace vr
diff --git a/chrome/browser/vr/ui_input_manager.h b/chrome/browser/vr/ui_input_manager.h index 0ed4aee..8fb3578 100644 --- a/chrome/browser/vr/ui_input_manager.h +++ b/chrome/browser/vr/ui_input_manager.h
@@ -24,6 +24,7 @@ class UiElement; struct ControllerModel; struct ReticleModel; +struct TextInputInfo; using GestureList = std::vector<std::unique_ptr<blink::WebGestureEvent>>; @@ -55,6 +56,12 @@ ReticleModel* reticle_model, GestureList* gesture_list); + // Text input related. + void RequestFocus(int element_id); + void OnInputEdited(const TextInputInfo& info); + void OnInputCommitted(const TextInputInfo& info); + void OnKeyboardHidden(); + bool controller_quiescent() const { return controller_quiescent_; } void set_hit_test_strategy(HitTestStrategy strategy) { @@ -86,6 +93,8 @@ void UpdateQuiescenceState(base::TimeTicks current_time, const ControllerModel& controller_model); + void UnfocusFocusedElement(); + UiScene* scene_; int hover_target_id_ = 0; // TODO(mthiesse): We shouldn't have a fling target. Elements should fling @@ -95,8 +104,10 @@ int input_locked_element_id_ = 0; bool in_click_ = false; bool in_scroll_ = false; + int focused_element_id_ = 0; HitTestStrategy hit_test_strategy_ = HitTestStrategy::PROJECT_TO_WORLD_ORIGIN; + ButtonState previous_button_state_ = ButtonState::UP; base::TimeTicks last_significant_controller_update_time_;
diff --git a/chrome/browser/vr/ui_input_manager_unittest.cc b/chrome/browser/vr/ui_input_manager_unittest.cc index f73b45f..8c2bf22 100644 --- a/chrome/browser/vr/ui_input_manager_unittest.cc +++ b/chrome/browser/vr/ui_input_manager_unittest.cc
@@ -7,6 +7,7 @@ #include <memory> #include "base/memory/ptr_util.h" +#include "base/strings/utf_string_conversions.h" #include "base/time/time.h" #include "cc/test/geometry_test_utils.h" #include "chrome/browser/vr/content_input_delegate.h" @@ -51,6 +52,24 @@ DISALLOW_COPY_AND_ASSIGN(MockRect); }; +class MockTextInput : public TextInput { + public: + MockTextInput() + : TextInput(512, + 1, + 1, + base::RepeatingCallback<void(bool)>(), + base::RepeatingCallback<void(const TextInputInfo&)>()) {} + ~MockTextInput() override = default; + + MOCK_METHOD1(OnFocusChanged, void(bool)); + MOCK_METHOD1(OnInputEdited, void(const TextInputInfo&)); + MOCK_METHOD1(OnInputCommitted, void(const TextInputInfo&)); + + private: + DISALLOW_COPY_AND_ASSIGN(MockTextInput); +}; + class UiInputManagerTest : public testing::Test { public: void SetUp() override { @@ -68,6 +87,16 @@ return p_element; } + StrictMock<MockTextInput>* CreateMockInputElement(float z_position) { + auto element = base::MakeUnique<StrictMock<MockTextInput>>(); + StrictMock<MockTextInput>* p_element = element.get(); + element->SetTranslate(0, 0, z_position); + element->SetVisible(true); + scene_->AddUiElement(kRoot, std::move(element)); + scene_->OnBeginFrame(base::TimeTicks(), kForwardVector); + return p_element; + } + void HandleInput(const gfx::Vector3dF& laser_direction, UiInputManager::ButtonState button_state) { HandleInput({0, 0, 0}, laser_direction, button_state); @@ -104,6 +133,30 @@ UiInputManager* input_manager_; }; +TEST_F(UiInputManagerTest, FocusedElement) { + StrictMock<MockTextInput>* p_element1 = CreateMockInputElement(-5.f); + StrictMock<MockTextInput>* p_element2 = CreateMockInputElement(-5.f); + TextInputInfo edit(base::ASCIIToUTF16("asdfg")); + + // Focus request triggers OnFocusChanged. + testing::Sequence s; + EXPECT_CALL(*p_element1, OnFocusChanged(true)).InSequence(s); + input_manager_->RequestFocus(p_element1->id()); + + // Edit goes to focused element. + EXPECT_CALL(*p_element1, OnInputEdited(edit)).InSequence(s); + input_manager_->OnInputEdited(edit); + + // Commit goes to focused element. + EXPECT_CALL(*p_element1, OnInputCommitted(edit)).InSequence(s); + input_manager_->OnInputCommitted(edit); + + // Focus on a different element triggers OnFocusChanged. + EXPECT_CALL(*p_element1, OnFocusChanged(false)).InSequence(s); + EXPECT_CALL(*p_element2, OnFocusChanged(true)).InSequence(s); + input_manager_->RequestFocus(p_element2->id()); +} + TEST_F(UiInputManagerTest, ReticleRenderTarget) { auto element = base::MakeUnique<Rect>(); UiElement* p_element = element.get();
diff --git a/chrome/browser/vr/ui_renderer.cc b/chrome/browser/vr/ui_renderer.cc index 57aeacd..507797c 100644 --- a/chrome/browser/vr/ui_renderer.cc +++ b/chrome/browser/vr/ui_renderer.cc
@@ -23,7 +23,7 @@ void UiRenderer::Draw(const RenderInfo& render_info) { Draw2dBrowsing(render_info); DrawSplashScreen(render_info); - DrawController(render_info); + DrawInputModalElements(render_info); } void UiRenderer::Draw2dBrowsing(const RenderInfo& render_info) { @@ -66,13 +66,16 @@ // another buffer that is size optimized. } -void UiRenderer::DrawController(const RenderInfo& render_info) { +void UiRenderer::DrawInputModalElements(const RenderInfo& render_info) { + const auto& keyboard_elements = scene_->GetVisibleKeyboardElements(); const auto& controller_elements = scene_->GetVisibleControllerElements(); - if (controller_elements.empty()) - return; - - glEnable(GL_CULL_FACE); - DrawUiView(render_info, controller_elements); + if (!keyboard_elements.empty()) { + DrawUiView(render_info, keyboard_elements); + } + if (!controller_elements.empty()) { + glEnable(GL_CULL_FACE); + DrawUiView(render_info, controller_elements); + } } void UiRenderer::DrawWebVrOverlayForeground(const RenderInfo& render_info) {
diff --git a/chrome/browser/vr/ui_renderer.h b/chrome/browser/vr/ui_renderer.h index 70f4350..b33ba6ca 100644 --- a/chrome/browser/vr/ui_renderer.h +++ b/chrome/browser/vr/ui_renderer.h
@@ -44,7 +44,7 @@ private: void Draw2dBrowsing(const RenderInfo& render_info); void DrawSplashScreen(const RenderInfo& render_info); - void DrawController(const RenderInfo& render_info); + void DrawInputModalElements(const RenderInfo& render_info); void DrawUiView(const RenderInfo& render_info, const std::vector<const UiElement*>& elements);
diff --git a/chrome/browser/vr/ui_scene.cc b/chrome/browser/vr/ui_scene.cc index ffb789b..378464e 100644 --- a/chrome/browser/vr/ui_scene.cc +++ b/chrome/browser/vr/ui_scene.cc
@@ -15,6 +15,7 @@ #include "base/values.h" #include "chrome/browser/vr/databinding/binding_base.h" #include "chrome/browser/vr/elements/draw_phase.h" +#include "chrome/browser/vr/elements/keyboard.h" #include "chrome/browser/vr/elements/reticle.h" #include "chrome/browser/vr/elements/ui_element.h" #include "ui/gfx/transform.h" @@ -80,11 +81,8 @@ CHECK_GE(element->id(), 0); CHECK_EQ(GetUiElementById(element->id()), nullptr); CHECK_GE(element->draw_phase(), 0); - if (gl_initialized_) { - for (auto& child : *element) { - child.Initialize(provider_); - } - } + if (gl_initialized_) + element->Initialize(provider_); GetUiElementByName(parent)->AddChild(std::move(element)); is_dirty_ = true; } @@ -267,6 +265,14 @@ }); } +UiScene::Elements UiScene::GetVisibleKeyboardElements() const { + return GetVisibleElements(GetUiElementByName(kKeyboard), + GetUiElementByName(kReticle), + [](UiElement* element) { + return element->draw_phase() == kPhaseForeground; + }); +} + UiScene::Elements UiScene::GetPotentiallyVisibleElements() const { UiScene::Elements elements; for (auto& element : *root_element_) { @@ -289,9 +295,8 @@ void UiScene::OnGlInitialized(SkiaSurfaceProvider* provider) { gl_initialized_ = true; provider_ = provider; - for (auto& element : *root_element_) - element.Initialize(provider); + element.Initialize(provider_); } } // namespace vr
diff --git a/chrome/browser/vr/ui_scene.h b/chrome/browser/vr/ui_scene.h index bc7dffe..33a0773 100644 --- a/chrome/browser/vr/ui_scene.h +++ b/chrome/browser/vr/ui_scene.h
@@ -13,6 +13,7 @@ #include "chrome/browser/vr/elements/ui_element.h" #include "chrome/browser/vr/elements/ui_element_iterator.h" #include "chrome/browser/vr/elements/ui_element_name.h" +#include "chrome/browser/vr/keyboard_delegate.h" #include "third_party/skia/include/core/SkColor.h" namespace base { @@ -58,6 +59,7 @@ Elements GetVisibleSplashScreenElements() const; Elements GetVisibleWebVrOverlayForegroundElements() const; Elements GetVisibleControllerElements() const; + Elements GetVisibleKeyboardElements() const; Elements GetPotentiallyVisibleElements() const; float background_distance() const { return background_distance_; } @@ -74,6 +76,8 @@ void OnGlInitialized(SkiaSurfaceProvider* provider); private: + void InitializeElement(UiElement* element); + std::unique_ptr<UiElement> root_element_; float background_distance_ = 10.0f;
diff --git a/chrome/browser/vr/ui_scene_constants.h b/chrome/browser/vr/ui_scene_constants.h index 66140bba..10c0e99 100644 --- a/chrome/browser/vr/ui_scene_constants.h +++ b/chrome/browser/vr/ui_scene_constants.h
@@ -212,6 +212,9 @@ static constexpr float kModalPromptFadeOpacity = 0.5f; +static constexpr float kKeyboardDistance = 1.0f; +static constexpr float kKeyboardVerticalOffset = -0.45f * kKeyboardDistance; + } // namespace vr #endif // CHROME_BROWSER_VR_UI_SCENE_CONSTANTS_H_
diff --git a/chrome/browser/vr/ui_scene_creator.cc b/chrome/browser/vr/ui_scene_creator.cc index ac6988b..620209d7 100644 --- a/chrome/browser/vr/ui_scene_creator.cc +++ b/chrome/browser/vr/ui_scene_creator.cc
@@ -19,6 +19,7 @@ #include "chrome/browser/vr/elements/full_screen_rect.h" #include "chrome/browser/vr/elements/grid.h" #include "chrome/browser/vr/elements/invisible_hit_target.h" +#include "chrome/browser/vr/elements/keyboard.h" #include "chrome/browser/vr/elements/laser.h" #include "chrome/browser/vr/elements/linear_layout.h" #include "chrome/browser/vr/elements/rect.h" @@ -38,6 +39,7 @@ #include "chrome/browser/vr/elements/vector_icon.h" #include "chrome/browser/vr/elements/viewport_aware_root.h" #include "chrome/browser/vr/elements/webvr_url_toast.h" +#include "chrome/browser/vr/keyboard_delegate.h" #include "chrome/browser/vr/model/model.h" #include "chrome/browser/vr/speech_recognizer.h" #include "chrome/browser/vr/target_property.h" @@ -204,10 +206,14 @@ UiSceneCreator::UiSceneCreator(UiBrowserInterface* browser, UiScene* scene, ContentInputDelegate* content_input_delegate, + KeyboardDelegate* keyboard_delegate, + TextInputDelegate* text_input_delegate, Model* model) : browser_(browser), scene_(scene), content_input_delegate_(content_input_delegate), + keyboard_delegate_(keyboard_delegate), + text_input_delegate_(text_input_delegate), model_(model) {} UiSceneCreator::~UiSceneCreator() {} @@ -232,6 +238,7 @@ CreateUnderDevelopmentNotice(); CreateVoiceSearchUiGroup(); CreateController(); + CreateKeyboard(); } void UiSceneCreator::Create2dBrowsingSubtreeRoots() { @@ -971,6 +978,47 @@ scene_->AddUiElement(kControllerGroup, std::move(reticle)); } +std::unique_ptr<TextInput> UiSceneCreator::CreateTextInput( + int maximum_width_pixels, + float font_height_meters, + float text_width_meters, + Model* model, + TextInputInfo* text_input_model, + TextInputDelegate* text_input_delegate) { + auto text_input = base::MakeUnique<TextInput>( + maximum_width_pixels, font_height_meters, text_width_meters, + base::BindRepeating( + [](Model* model, bool focused) { model->editing_input = focused; }, + base::Unretained(model)), + base::BindRepeating( + [](TextInputInfo* model, const TextInputInfo& text_input_info) { + *model = text_input_info; + }, + base::Unretained(text_input_model))); + text_input->set_draw_phase(kPhaseForeground); + text_input->SetTextInputDelegate(text_input_delegate); + text_input->set_hit_testable(true); + text_input->AddBinding(base::MakeUnique<Binding<TextInputInfo>>( + base::BindRepeating([](TextInputInfo* info) { return *info; }, + base::Unretained(text_input_model)), + base::BindRepeating( + [](TextInput* e, const TextInputInfo& value) { + e->UpdateInput(value); + }, + base::Unretained(text_input.get())))); + return text_input; +} + +void UiSceneCreator::CreateKeyboard() { + auto keyboard = base::MakeUnique<Keyboard>(); + keyboard->SetKeyboardDelegate(keyboard_delegate_); + keyboard->set_draw_phase(kPhaseForeground); + keyboard->SetTranslate(0.0, kKeyboardVerticalOffset, -kKeyboardDistance); + keyboard->AddBinding(VR_BIND_FUNC(bool, Model, model_, editing_input, + UiElement, keyboard.get(), SetVisible)); + scene_->AddUiElement(kRoot, std::move(keyboard)); +} + void UiSceneCreator::CreateUrlBar() { auto url_bar = base::MakeUnique<UrlBar>( 512, @@ -1067,16 +1115,16 @@ float width = kOmniboxWidthDMM - 2 * kOmniboxTextMarginDMM; auto omnibox_text_field = - base::MakeUnique<TextInput>(1024, kOmniboxTextHeightDMM, width); + CreateTextInput(1024, kOmniboxTextHeightDMM, width, model_, + &model_->omnibox_text_field_info, text_input_delegate_); + omnibox_text_field->AddBinding( + VR_BIND(TextInputInfo, Model, model_, omnibox_text_field_info, + UiBrowserInterface, browser_, StartAutocomplete(value.text))); omnibox_text_field->SetSize(width, 0); omnibox_text_field->set_name(kOmniboxTextField); - omnibox_text_field->set_draw_phase(kPhaseForeground); omnibox_text_field->set_x_anchoring(LEFT); omnibox_text_field->set_x_centering(LEFT); omnibox_text_field->SetTranslate(kOmniboxTextMarginDMM, 0, 0); - - omnibox_text_field->SetTextChangedCallback(base::Bind( - &UiBrowserInterface::StartAutocomplete, base::Unretained(browser_))); scene_->AddUiElement(kOmniboxContainer, std::move(omnibox_text_field)); auto close_button = Create<Button>(
diff --git a/chrome/browser/vr/ui_scene_creator.h b/chrome/browser/vr/ui_scene_creator.h index 3d7ce7d..e1762c5 100644 --- a/chrome/browser/vr/ui_scene_creator.h +++ b/chrome/browser/vr/ui_scene_creator.h
@@ -6,7 +6,9 @@ #define CHROME_BROWSER_VR_UI_SCENE_CREATOR_H_ #include "base/macros.h" +#include "chrome/browser/vr/elements/text_input.h" #include "chrome/browser/vr/elements/ui_element_name.h" +#include "chrome/browser/vr/keyboard_delegate.h" namespace vr { @@ -21,11 +23,21 @@ UiSceneCreator(UiBrowserInterface* browser, UiScene* scene, ContentInputDelegate* content_input_delegate, + KeyboardDelegate* keyboard_delegate, + TextInputDelegate* text_input_delegate, Model* model); ~UiSceneCreator(); void CreateScene(); + static std::unique_ptr<TextInput> CreateTextInput( + int maximum_width_pixels, + float font_height_meters, + float text_width_meters, + Model* model, + TextInputInfo* text_input_model, + TextInputDelegate* text_input_delegate); + private: void Create2dBrowsingSubtreeRoots(); void CreateWebVrRoot(); @@ -46,10 +58,13 @@ void CreateToasts(); void CreateVoiceSearchUiGroup(); void CreateController(); + void CreateKeyboard(); UiBrowserInterface* browser_; UiScene* scene_; ContentInputDelegate* content_input_delegate_; + KeyboardDelegate* keyboard_delegate_; + TextInputDelegate* text_input_delegate_; Model* model_; DISALLOW_COPY_AND_ASSIGN(UiSceneCreator);
diff --git a/chrome/browser/vr/ui_unittest.cc b/chrome/browser/vr/ui_unittest.cc index 5f294aba..3b5ed0c 100644 --- a/chrome/browser/vr/ui_unittest.cc +++ b/chrome/browser/vr/ui_unittest.cc
@@ -54,6 +54,7 @@ kFloor, kCeiling, kBackplane, + kKeyboard, kContentQuad, kAudioCaptureIndicator, kVideoCaptureIndicator, @@ -140,6 +141,7 @@ "kController", "kLaser", "kReticle", + "kKeyboard", "kExitWarning", "kWebVrUrlToast", "kExclusiveScreenToastViewportAware",
diff --git a/components/wallpaper/wallpaper_info.h b/components/wallpaper/wallpaper_info.h index d323882..054faf7 100644 --- a/components/wallpaper/wallpaper_info.h +++ b/components/wallpaper/wallpaper_info.h
@@ -63,7 +63,7 @@ ~WallpaperInfo() {} - bool operator==(const WallpaperInfo& other) { + bool operator==(const WallpaperInfo& other) const { return (location == other.location) && (layout == other.layout) && (type == other.type); }
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc index b472d9d..b7509cd 100644 --- a/content/browser/frame_host/render_frame_host_impl.cc +++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -916,8 +916,6 @@ OnDidAddContentSecurityPolicies) IPC_MESSAGE_HANDLER(FrameHostMsg_EnforceInsecureRequestPolicy, OnEnforceInsecureRequestPolicy) - IPC_MESSAGE_HANDLER(FrameHostMsg_UpdateToUniqueOrigin, - OnUpdateToUniqueOrigin) IPC_MESSAGE_HANDLER(FrameHostMsg_DidChangeFramePolicy, OnDidChangeFramePolicy) IPC_MESSAGE_HANDLER(FrameHostMsg_DidChangeFrameOwnerProperties, @@ -2272,17 +2270,6 @@ frame_tree_node()->SetInsecureRequestPolicy(policy); } -void RenderFrameHostImpl::OnUpdateToUniqueOrigin( - bool is_potentially_trustworthy_unique_origin) { - TRACE_EVENT1("navigation", "RenderFrameHostImpl::OnUpdateToUniqueOrigin", - "frame_tree_node", frame_tree_node_->frame_tree_node_id()); - - url::Origin origin; - DCHECK(origin.unique()); - frame_tree_node()->SetCurrentOrigin(origin, - is_potentially_trustworthy_unique_origin); -} - FrameTreeNode* RenderFrameHostImpl::FindAndVerifyChild( int32_t child_frame_routing_id, bad_message::BadMessageReason reason) {
diff --git a/content/browser/frame_host/render_frame_host_impl.h b/content/browser/frame_host/render_frame_host_impl.h index a2db91d..2f1613d 100644 --- a/content/browser/frame_host/render_frame_host_impl.h +++ b/content/browser/frame_host/render_frame_host_impl.h
@@ -807,7 +807,6 @@ const std::vector<ContentSecurityPolicy>& policies); void OnEnforceInsecureRequestPolicy(blink::WebInsecureRequestPolicy policy); - void OnUpdateToUniqueOrigin(bool is_potentially_trustworthy_unique_origin); void OnDidChangeFramePolicy(int32_t frame_routing_id, const blink::FramePolicy& frame_policy); void OnDidChangeFrameOwnerProperties(int32_t frame_routing_id,
diff --git a/content/common/frame_messages.h b/content/common/frame_messages.h index e939706..ebc3a5b 100644 --- a/content/common/frame_messages.h +++ b/content/common/frame_messages.h
@@ -1189,13 +1189,6 @@ IPC_MESSAGE_ROUTED1(FrameHostMsg_EnforceInsecureRequestPolicy, blink::WebInsecureRequestPolicy) -// Sent when the frame is set to a unique origin. TODO(estark): this IPC -// only exists to support dynamic sandboxing via a CSP delivered in a -// <meta> tag. This is not supposed to be allowed per the CSP spec and -// should be ripped out. https://crbug.com/594645 -IPC_MESSAGE_ROUTED1(FrameHostMsg_UpdateToUniqueOrigin, - bool /* is potentially trustworthy unique origin */) - // Sent when the renderer changed the progress of a load. IPC_MESSAGE_ROUTED1(FrameHostMsg_DidChangeLoadProgress, double /* load_progress */)
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc index 20785b44..bd485e59 100644 --- a/content/renderer/render_frame_impl.cc +++ b/content/renderer/render_frame_impl.cc
@@ -3578,12 +3578,6 @@ Send(new FrameHostMsg_EnforceInsecureRequestPolicy(routing_id_, policy)); } -void RenderFrameImpl::DidUpdateToUniqueOrigin( - bool is_potentially_trustworthy_unique_origin) { - Send(new FrameHostMsg_UpdateToUniqueOrigin( - routing_id_, is_potentially_trustworthy_unique_origin)); -} - void RenderFrameImpl::DidChangeFramePolicy( blink::WebFrame* child_frame, blink::WebSandboxFlags flags,
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h index a06fdcd..01a93e2 100644 --- a/content/renderer/render_frame_impl.h +++ b/content/renderer/render_frame_impl.h
@@ -571,8 +571,6 @@ void DidChangeName(const blink::WebString& name) override; void DidEnforceInsecureRequestPolicy( blink::WebInsecureRequestPolicy policy) override; - void DidUpdateToUniqueOrigin( - bool is_potentially_trustworthy_unique_origin) override; void DidChangeFramePolicy( blink::WebFrame* child_frame, blink::WebSandboxFlags flags,
diff --git a/content/renderer/render_frame_proxy.cc b/content/renderer/render_frame_proxy.cc index 44c2ee0..6d74f5d7 100644 --- a/content/renderer/render_frame_proxy.cc +++ b/content/renderer/render_frame_proxy.cc
@@ -268,12 +268,32 @@ void RenderFrameProxy::SetReplicatedState(const FrameReplicationState& state) { DCHECK(web_frame_); - web_frame_->SetReplicatedOrigin(state.origin); + + web_frame_->SetReplicatedOrigin( + state.origin, state.has_potentially_trustworthy_unique_origin); + +#if DCHECK_IS_ON() + blink::WebSecurityOrigin security_origin_before_sandbox_flags = + web_frame_->GetSecurityOrigin(); +#endif + web_frame_->SetReplicatedSandboxFlags(state.active_sandbox_flags); + +#if DCHECK_IS_ON() + // If |state.has_potentially_trustworthy_unique_origin| is set, + // - |state.origin| should be unique (this is checked in + // blink::SecurityOrigin::SetUniqueOriginIsPotentiallyTrustworthy() in + // SetReplicatedOrigin()), and thus + // - The security origin is not updated by SetReplicatedSandboxFlags() and + // thus we don't have to apply |has_potentially_trustworthy_unique_origin| + // flag after SetReplicatedSandboxFlags(). + if (state.has_potentially_trustworthy_unique_origin) + DCHECK(security_origin_before_sandbox_flags == + web_frame_->GetSecurityOrigin()); +#endif + web_frame_->SetReplicatedName(blink::WebString::FromUTF8(state.name)); web_frame_->SetReplicatedInsecureRequestPolicy(state.insecure_request_policy); - web_frame_->SetReplicatedPotentiallyTrustworthyUniqueOrigin( - state.has_potentially_trustworthy_unique_origin); web_frame_->SetReplicatedFeaturePolicyHeader(state.feature_policy_header); if (state.has_received_user_gesture) web_frame_->SetHasReceivedUserGesture(); @@ -464,9 +484,8 @@ void RenderFrameProxy::OnDidUpdateOrigin( const url::Origin& origin, bool is_potentially_trustworthy_unique_origin) { - web_frame_->SetReplicatedOrigin(origin); - web_frame_->SetReplicatedPotentiallyTrustworthyUniqueOrigin( - is_potentially_trustworthy_unique_origin); + web_frame_->SetReplicatedOrigin(origin, + is_potentially_trustworthy_unique_origin); } void RenderFrameProxy::OnSetPageFocus(bool is_focused) {
diff --git a/gpu/config/gpu_driver_bug_list.json b/gpu/config/gpu_driver_bug_list.json index 873db32..179ee65 100644 --- a/gpu/config/gpu_driver_bug_list.json +++ b/gpu/config/gpu_driver_bug_list.json
@@ -1897,6 +1897,10 @@ "os": { "type": "win" }, + "driver_version": { + "op": "<", + "value": "21.21.13.7576" + }, "vendor_id": "0x10de", "features": [ "disable_dxgi_zero_copy_video"
diff --git a/net/http/http_stream_factory_impl_job_controller.cc b/net/http/http_stream_factory_impl_job_controller.cc index 94e72c27..262b34ed 100644 --- a/net/http/http_stream_factory_impl_job_controller.cc +++ b/net/http/http_stream_factory_impl_job_controller.cc
@@ -567,7 +567,7 @@ } void HttpStreamFactoryImpl::JobController::ResumeMainJob() { - if (main_job_is_resumed_) + if (main_job_is_resumed_ || !main_job_) return; main_job_is_resumed_ = true;
diff --git a/third_party/WebKit/Source/core/dom/Document.cpp b/third_party/WebKit/Source/core/dom/Document.cpp index 7f7457c..3d35a5a1 100644 --- a/third_party/WebKit/Source/core/dom/Document.cpp +++ b/third_party/WebKit/Source/core/dom/Document.cpp
@@ -6252,8 +6252,6 @@ GetSecurityOrigin()->IsUnique()) { GetSecurityOrigin()->SetUniqueOriginIsPotentiallyTrustworthy( stand_in_origin->IsPotentiallyTrustworthy()); - if (GetFrame()) - GetFrame()->Client()->DidUpdateToUniqueOrigin(); } }
diff --git a/third_party/WebKit/Source/core/exported/LocalFrameClientImpl.cpp b/third_party/WebKit/Source/core/exported/LocalFrameClientImpl.cpp index d58d53d..3f685c8 100644 --- a/third_party/WebKit/Source/core/exported/LocalFrameClientImpl.cpp +++ b/third_party/WebKit/Source/core/exported/LocalFrameClientImpl.cpp
@@ -927,14 +927,6 @@ web_frame_->Client()->DidEnforceInsecureRequestPolicy(policy); } -void LocalFrameClientImpl::DidUpdateToUniqueOrigin() { - if (!web_frame_->Client()) - return; - DCHECK(web_frame_->GetSecurityOrigin().IsUnique()); - web_frame_->Client()->DidUpdateToUniqueOrigin( - web_frame_->GetSecurityOrigin().IsPotentiallyTrustworthy()); -} - void LocalFrameClientImpl::DidChangeFramePolicy( Frame* child_frame, SandboxFlags flags,
diff --git a/third_party/WebKit/Source/core/exported/LocalFrameClientImpl.h b/third_party/WebKit/Source/core/exported/LocalFrameClientImpl.h index 052c61a..4642775 100644 --- a/third_party/WebKit/Source/core/exported/LocalFrameClientImpl.h +++ b/third_party/WebKit/Source/core/exported/LocalFrameClientImpl.h
@@ -185,7 +185,6 @@ void FrameFocused() const override; void DidChangeName(const String&) override; void DidEnforceInsecureRequestPolicy(WebInsecureRequestPolicy) override; - void DidUpdateToUniqueOrigin() override; void DidChangeFramePolicy(Frame* child_frame, SandboxFlags, const ParsedFeaturePolicy&) override;
diff --git a/third_party/WebKit/Source/core/exported/WebFrameTest.cpp b/third_party/WebKit/Source/core/exported/WebFrameTest.cpp index deb8cf2..35b83f8 100644 --- a/third_party/WebKit/Source/core/exported/WebFrameTest.cpp +++ b/third_party/WebKit/Source/core/exported/WebFrameTest.cpp
@@ -9268,7 +9268,8 @@ WebRemoteFrame* remote_frame = FrameTestHelpers::CreateRemote(); WebFrame* target_frame = MainFrame()->FirstChild(); target_frame->Swap(remote_frame); - remote_frame->SetReplicatedOrigin(SecurityOrigin::CreateUnique()); + remote_frame->SetReplicatedOrigin( + WebSecurityOrigin(SecurityOrigin::CreateUnique()), false); // Invoking setTimeout should throw a security error. { @@ -9349,7 +9350,8 @@ // accessing a named property doesn't crash. WebRemoteFrame* remote_frame = FrameTestHelpers::CreateRemote(); LastChild(MainFrame())->Swap(remote_frame); - remote_frame->SetReplicatedOrigin(SecurityOrigin::CreateUnique()); + remote_frame->SetReplicatedOrigin( + WebSecurityOrigin(SecurityOrigin::CreateUnique()), false); v8::Local<v8::Value> remote_window_property = MainFrame()->ExecuteScriptAndReturnValue( WebScriptSource("window[2].foo")); @@ -9376,7 +9378,8 @@ WebRemoteFrame* remote_parent_frame = FrameTestHelpers::CreateRemote(); MainFrame()->Swap(remote_parent_frame); - remote_parent_frame->SetReplicatedOrigin(SecurityOrigin::CreateUnique()); + remote_parent_frame->SetReplicatedOrigin( + WebSecurityOrigin(SecurityOrigin::CreateUnique()), false); WebLocalFrame* child_frame = FrameTestHelpers::CreateLocalChild(*remote_parent_frame); @@ -9403,7 +9406,8 @@ WebRemoteFrame* remote_parent_frame = FrameTestHelpers::CreateRemote(); MainFrame()->Swap(remote_parent_frame); - remote_parent_frame->SetReplicatedOrigin(SecurityOrigin::CreateUnique()); + remote_parent_frame->SetReplicatedOrigin( + WebSecurityOrigin(SecurityOrigin::CreateUnique()), false); WebLocalFrame* child_frame = FrameTestHelpers::CreateLocalChild(*remote_parent_frame); @@ -9514,7 +9518,7 @@ ASSERT_EQ(MainFrame()->FirstChild(), remote_frame); remote_frame->SetReplicatedOrigin( - WebSecurityOrigin::CreateFromString("http://127.0.0.1")); + WebSecurityOrigin::CreateFromString("http://127.0.0.1"), false); MainFrame()->ExecuteScript( WebScriptSource("document.getElementsByTagName('iframe')[0]." "contentWindow.location = 'data:text/html,hi'")); @@ -9530,7 +9534,8 @@ RemoteNavigationClient remote_client; WebRemoteFrame* remote_frame = FrameTestHelpers::CreateRemote(&remote_client); MainFrame()->FirstChild()->Swap(remote_frame); - remote_frame->SetReplicatedOrigin(SecurityOrigin::CreateUnique()); + remote_frame->SetReplicatedOrigin( + WebSecurityOrigin(SecurityOrigin::CreateUnique()), false); ASSERT_TRUE(MainFrame()->FirstChild()->IsWebRemoteFrame()); LocalDOMWindow* main_window =
diff --git a/third_party/WebKit/Source/core/exported/WebRemoteFrameImpl.cpp b/third_party/WebKit/Source/core/exported/WebRemoteFrameImpl.cpp index 495226a..263d498d8 100644 --- a/third_party/WebKit/Source/core/exported/WebRemoteFrameImpl.cpp +++ b/third_party/WebKit/Source/core/exported/WebRemoteFrameImpl.cpp
@@ -213,9 +213,14 @@ return client->GetWebFrame(); } -void WebRemoteFrameImpl::SetReplicatedOrigin(const WebSecurityOrigin& origin) { +void WebRemoteFrameImpl::SetReplicatedOrigin( + const WebSecurityOrigin& origin, + bool is_potentially_trustworthy_unique_origin) { DCHECK(GetFrame()); - GetFrame()->GetSecurityContext()->SetReplicatedOrigin(origin); + scoped_refptr<SecurityOrigin> security_origin = origin.Get()->IsolatedCopy(); + security_origin->SetUniqueOriginIsPotentiallyTrustworthy( + is_potentially_trustworthy_unique_origin); + GetFrame()->GetSecurityContext()->SetReplicatedOrigin(security_origin); // If the origin of a remote frame changed, the accessibility object for the // owner element now points to a different child. @@ -283,20 +288,6 @@ GetFrame()->GetSecurityContext()->SetInsecureRequestPolicy(policy); } -void WebRemoteFrameImpl::SetReplicatedPotentiallyTrustworthyUniqueOrigin( - bool is_unique_origin_potentially_trustworthy) { - DCHECK(GetFrame()); - // If |isUniqueOriginPotentiallyTrustworthy| is true, then the origin must be - // unique. - DCHECK(!is_unique_origin_potentially_trustworthy || - GetFrame()->GetSecurityContext()->GetSecurityOrigin()->IsUnique()); - GetFrame() - ->GetSecurityContext() - ->GetSecurityOrigin() - ->SetUniqueOriginIsPotentiallyTrustworthy( - is_unique_origin_potentially_trustworthy); -} - void WebRemoteFrameImpl::DispatchLoadEventOnFrameOwner() { DCHECK(GetFrame()->Owner()->IsLocal()); GetFrame()->Owner()->DispatchLoad();
diff --git a/third_party/WebKit/Source/core/exported/WebRemoteFrameImpl.h b/third_party/WebKit/Source/core/exported/WebRemoteFrameImpl.h index 6439c08..a24e3db 100644 --- a/third_party/WebKit/Source/core/exported/WebRemoteFrameImpl.h +++ b/third_party/WebKit/Source/core/exported/WebRemoteFrameImpl.h
@@ -57,7 +57,9 @@ WebRemoteFrameClient*, WebFrame* opener) override; void SetWebLayer(WebLayer*) override; - void SetReplicatedOrigin(const WebSecurityOrigin&) override; + void SetReplicatedOrigin( + const WebSecurityOrigin&, + bool is_potentially_trustworthy_unique_origin) override; void SetReplicatedSandboxFlags(WebSandboxFlags) override; void SetReplicatedName(const WebString&) override; void SetReplicatedFeaturePolicyHeader( @@ -68,7 +70,6 @@ WebContentSecurityPolicySource) override; void ResetReplicatedContentSecurityPolicy() override; void SetReplicatedInsecureRequestPolicy(WebInsecureRequestPolicy) override; - void SetReplicatedPotentiallyTrustworthyUniqueOrigin(bool) override; void DispatchLoadEventOnFrameOwner() override; void DidStartLoading() override; void DidStopLoading() override;
diff --git a/third_party/WebKit/Source/core/frame/LocalFrameClient.h b/third_party/WebKit/Source/core/frame/LocalFrameClient.h index 4c0595c..b4df206 100644 --- a/third_party/WebKit/Source/core/frame/LocalFrameClient.h +++ b/third_party/WebKit/Source/core/frame/LocalFrameClient.h
@@ -275,8 +275,6 @@ virtual void DidEnforceInsecureRequestPolicy(WebInsecureRequestPolicy) {} - virtual void DidUpdateToUniqueOrigin() {} - virtual void DidChangeFramePolicy(Frame* child_frame, SandboxFlags, const ParsedFeaturePolicy&) {}
diff --git a/third_party/WebKit/Source/core/loader/DocumentThreadableLoader.cpp b/third_party/WebKit/Source/core/loader/DocumentThreadableLoader.cpp index 2fe43cf7..aa9626d 100644 --- a/third_party/WebKit/Source/core/loader/DocumentThreadableLoader.cpp +++ b/third_party/WebKit/Source/core/loader/DocumentThreadableLoader.cpp
@@ -53,6 +53,7 @@ #include "platform/loader/fetch/FetchUtils.h" #include "platform/loader/fetch/Resource.h" #include "platform/loader/fetch/ResourceFetcher.h" +#include "platform/loader/fetch/ResourceLoader.h" #include "platform/loader/fetch/ResourceLoaderOptions.h" #include "platform/loader/fetch/ResourceRequest.h" #include "platform/weborigin/SchemeRegistry.h" @@ -536,7 +537,7 @@ DocumentThreadableLoader::~DocumentThreadableLoader() { CHECK(!client_); - DCHECK(!resource_); + DCHECK(!GetResource()); } void DocumentThreadableLoader::OverrideTimeout( @@ -585,14 +586,16 @@ } void DocumentThreadableLoader::SetDefersLoading(bool value) { - if (GetResource()) - GetResource()->SetDefersLoading(value); + if (GetResource() && GetResource()->Loader()) + GetResource()->Loader()->SetDefersLoading(value); } void DocumentThreadableLoader::Clear() { client_ = nullptr; timeout_timer_.Stop(); request_started_seconds_ = 0.0; + if (GetResource()) + checker_.WillRemoveClient(); ClearResource(); } @@ -734,6 +737,8 @@ // FIXME: consider combining this with CORS redirect handling performed by // CrossOriginAccessControl::handleRedirect(). + if (GetResource()) + checker_.WillRemoveClient(); ClearResource(); // If @@ -1101,6 +1106,8 @@ } void DocumentThreadableLoader::LoadFallbackRequestForServiceWorker() { + if (GetResource()) + checker_.WillRemoveClient(); ClearResource(); ResourceRequest fallback_request(fallback_request_for_service_worker_); fallback_request_for_service_worker_ = ResourceRequest(); @@ -1116,6 +1123,8 @@ actual_request_ = ResourceRequest(); actual_options_ = ResourceLoaderOptions(); + if (GetResource()) + checker_.WillRemoveClient(); ClearResource(); PrepareCrossOriginRequest(actual_request); @@ -1200,6 +1209,8 @@ } else { SetResource(RawResource::Fetch(new_params, fetcher)); } + if (GetResource()) + checker_.WillAddClient(); if (!GetResource()) { probe::documentThreadableLoaderFailedToStartLoadingForClient( @@ -1365,7 +1376,6 @@ } void DocumentThreadableLoader::Trace(blink::Visitor* visitor) { - visitor->Trace(resource_); visitor->Trace(loading_context_); ThreadableLoader::Trace(visitor); RawResourceClient::Trace(visitor);
diff --git a/third_party/WebKit/Source/core/loader/DocumentThreadableLoader.h b/third_party/WebKit/Source/core/loader/DocumentThreadableLoader.h index 89b55c0..73cadb9 100644 --- a/third_party/WebKit/Source/core/loader/DocumentThreadableLoader.h +++ b/third_party/WebKit/Source/core/loader/DocumentThreadableLoader.h
@@ -57,8 +57,9 @@ // TODO(horo): We are using this class not only in documents, but also in // workers. We should change the name to ThreadableLoaderImpl. -class CORE_EXPORT DocumentThreadableLoader final : public ThreadableLoader, - private RawResourceClient { +class CORE_EXPORT DocumentThreadableLoader final + : public ThreadableLoader, + private ResourceOwner<RawResource> { USING_GARBAGE_COLLECTED_MIXIN(DocumentThreadableLoader); public: @@ -203,32 +204,6 @@ void LoadRequest(ResourceRequest&, ResourceLoaderOptions); bool IsAllowedRedirect(network::mojom::FetchRequestMode, const KURL&) const; - // TODO(hiroshige): After crbug.com/633696 is fixed, - // - Remove RawResourceClientStateChecker logic, - // - Make DocumentThreadableLoader to be a ResourceOwner and remove this - // re-implementation of ResourceOwner, and - // - Consider re-applying RawResourceClientStateChecker in a more - // general fashion (crbug.com/640291). - RawResource* GetResource() const { return resource_.Get(); } - void ClearResource() { SetResource(nullptr); } - void SetResource(RawResource* new_resource) { - if (new_resource == resource_) - return; - - if (RawResource* old_resource = resource_.Release()) { - checker_.WillRemoveClient(); - old_resource->RemoveClient(this); - } - - if (new_resource) { - resource_ = new_resource; - checker_.WillAddClient(); - resource_->AddClient(this); - } - } - Member<RawResource> resource_; - // End of ResourceOwner re-implementation, see above. - SecurityOrigin* GetSecurityOrigin() const; // Returns null if the loader is not associated with Document.
diff --git a/third_party/WebKit/Source/core/page/scrolling/RootScrollerTest.cpp b/third_party/WebKit/Source/core/page/scrolling/RootScrollerTest.cpp index b594ed9..929b3c9 100644 --- a/third_party/WebKit/Source/core/page/scrolling/RootScrollerTest.cpp +++ b/third_party/WebKit/Source/core/page/scrolling/RootScrollerTest.cpp
@@ -785,7 +785,8 @@ { WebRemoteFrameImpl* remote_main_frame = FrameTestHelpers::CreateRemote(); helper_.LocalMainFrame()->Swap(remote_main_frame); - remote_main_frame->SetReplicatedOrigin(SecurityOrigin::CreateUnique()); + remote_main_frame->SetReplicatedOrigin( + WebSecurityOrigin(SecurityOrigin::CreateUnique()), false); local_frame = FrameTestHelpers::CreateLocalChild(*remote_main_frame); FrameTestHelpers::LoadFrame(local_frame,
diff --git a/third_party/WebKit/Source/platform/exported/WebSecurityOrigin.cpp b/third_party/WebKit/Source/platform/exported/WebSecurityOrigin.cpp index 1bf54ff4..3f08bb7 100644 --- a/third_party/WebKit/Source/platform/exported/WebSecurityOrigin.cpp +++ b/third_party/WebKit/Source/platform/exported/WebSecurityOrigin.cpp
@@ -149,4 +149,10 @@ return Get()->ToUrlOrigin(); } +#if DCHECK_IS_ON() +bool WebSecurityOrigin::operator==(const WebSecurityOrigin& other) const { + return Get() == other.Get(); +} +#endif + } // namespace blink
diff --git a/third_party/WebKit/Source/platform/loader/fetch/RawResource.cpp b/third_party/WebKit/Source/platform/loader/fetch/RawResource.cpp index 7b634398..f06f0904 100644 --- a/third_party/WebKit/Source/platform/loader/fetch/RawResource.cpp +++ b/third_party/WebKit/Source/platform/loader/fetch/RawResource.cpp
@@ -31,7 +31,6 @@ #include "platform/loader/fetch/MemoryCache.h" #include "platform/loader/fetch/ResourceClientWalker.h" #include "platform/loader/fetch/ResourceFetcher.h" -#include "platform/loader/fetch/ResourceLoader.h" #include "platform/network/http_names.h" #include "platform/scheduler/child/web_scheduler.h" #include "public/platform/Platform.h" @@ -296,11 +295,6 @@ Resource::NotifyFinished(); } -void RawResource::SetDefersLoading(bool defers) { - if (Loader()) - Loader()->SetDefersLoading(defers); -} - static bool ShouldIgnoreHeaderForCacheReuse(AtomicString header_name) { // FIXME: This list of headers that don't affect cache policy almost certainly // isn't complete.
diff --git a/third_party/WebKit/Source/platform/loader/fetch/RawResource.h b/third_party/WebKit/Source/platform/loader/fetch/RawResource.h index 8d59b043..b81d484 100644 --- a/third_party/WebKit/Source/platform/loader/fetch/RawResource.h +++ b/third_party/WebKit/Source/platform/loader/fetch/RawResource.h
@@ -66,12 +66,6 @@ return CreateForTest(KURL(url), type); } - // FIXME: AssociatedURLLoader shouldn't be a DocumentThreadableLoader and - // therefore shouldn't use RawResource. However, it is, and it needs to be - // able to defer loading. This can be fixed by splitting CORS preflighting out - // of DocumentThreadableLoader. - void SetDefersLoading(bool); - // Resource implementation bool CanReuse(const FetchParameters&) const override; bool WillFollowRedirect(const ResourceRequest&,
diff --git a/third_party/WebKit/public/platform/WebSecurityOrigin.h b/third_party/WebKit/public/platform/WebSecurityOrigin.h index 1b44129..d7a3086 100644 --- a/third_party/WebKit/public/platform/WebSecurityOrigin.h +++ b/third_party/WebKit/public/platform/WebSecurityOrigin.h
@@ -119,6 +119,10 @@ BLINK_PLATFORM_EXPORT WebSecurityOrigin(const url::Origin&); BLINK_PLATFORM_EXPORT operator url::Origin() const; +#if DCHECK_IS_ON() + BLINK_PLATFORM_EXPORT bool operator==(const WebSecurityOrigin&) const; +#endif + private: // Present only to facilitate conversion from 'url::Origin'; this constructor // shouldn't be used anywhere else.
diff --git a/third_party/WebKit/public/web/WebFrameClient.h b/third_party/WebKit/public/web/WebFrameClient.h index 979921b..411ec23 100644 --- a/third_party/WebKit/public/web/WebFrameClient.h +++ b/third_party/WebKit/public/web/WebFrameClient.h
@@ -259,15 +259,6 @@ // This frame has set an insecure request policy. virtual void DidEnforceInsecureRequestPolicy(WebInsecureRequestPolicy) {} - // This frame has been updated to a unique origin, which should be - // considered potentially trustworthy if - // |isPotentiallyTrustworthyUniqueOrigin| is true. TODO(estark): - // this method only exists to support dynamic sandboxing via a CSP - // delivered in a <meta> tag. This is not supposed to be allowed per - // the CSP spec and should be ripped out. https://crbug.com/594645 - virtual void DidUpdateToUniqueOrigin( - bool is_potentially_trustworthy_unique_origin) {} - // The sandbox flags or container policy have changed for a child frame of // this frame. virtual void DidChangeFramePolicy(
diff --git a/third_party/WebKit/public/web/WebRemoteFrame.h b/third_party/WebKit/public/web/WebRemoteFrame.h index 5a2beb69..e73a801 100644 --- a/third_party/WebKit/public/web/WebRemoteFrame.h +++ b/third_party/WebKit/public/web/WebRemoteFrame.h
@@ -62,7 +62,9 @@ virtual void SetWebLayer(WebLayer*) = 0; // Set security origin replicated from another process. - virtual void SetReplicatedOrigin(const WebSecurityOrigin&) = 0; + virtual void SetReplicatedOrigin( + const WebSecurityOrigin&, + bool is_potentially_trustworthy_unique_origin) = 0; // Set sandbox flags replicated from another process. virtual void SetReplicatedSandboxFlags(WebSandboxFlags) = 0; @@ -86,10 +88,6 @@ // process. virtual void SetReplicatedInsecureRequestPolicy(WebInsecureRequestPolicy) = 0; - // Set the frame to a unique origin that is potentially trustworthy, - // replicated from another process. - virtual void SetReplicatedPotentiallyTrustworthyUniqueOrigin(bool) = 0; - virtual void DispatchLoadEventOnFrameOwner() = 0; virtual void DidStartLoading() = 0;
diff --git a/ui/message_center/notification.cc b/ui/message_center/notification.cc index 4ef3cb6..af6bd704 100644 --- a/ui/message_center/notification.cc +++ b/ui/message_center/notification.cc
@@ -251,7 +251,7 @@ base::string16() /* display_source */, GURL(), NotifierId(NotifierId::SYSTEM_COMPONENT, system_component_id), RichNotificationData(), - new HandleNotificationClickedDelegate(click_callback), gfx::kNoneIcon, + new HandleNotificationClickDelegate(click_callback), gfx::kNoneIcon, SystemNotificationWarningLevel::CRITICAL_WARNING); notification->set_clickable(true); notification->SetSystemPriority();
diff --git a/ui/message_center/notification_delegate.cc b/ui/message_center/notification_delegate.cc index 95b3fe3e..ba57dc743 100644 --- a/ui/message_center/notification_delegate.cc +++ b/ui/message_center/notification_delegate.cc
@@ -4,6 +4,7 @@ #include "ui/message_center/notification_delegate.h" +#include "base/bind.h" #include "base/logging.h" namespace message_center { @@ -27,33 +28,36 @@ void NotificationDelegate::DisableNotification() {} -// HandleNotificationClickedDelegate: +// HandleNotificationClickDelegate: -HandleNotificationClickedDelegate::HandleNotificationClickedDelegate( - const base::Closure& closure) - : closure_(closure) { +HandleNotificationClickDelegate::HandleNotificationClickDelegate( + const base::Closure& callback) { + if (!callback.is_null()) { + // Create a callback that consumes and ignores the button index parameter, + // and just runs the provided closure. + callback_ = base::Bind( + [](const base::Closure& closure, base::Optional<int> button_index) { + DCHECK(!button_index); + closure.Run(); + }, + callback); + } } -HandleNotificationClickedDelegate::~HandleNotificationClickedDelegate() {} +HandleNotificationClickDelegate::HandleNotificationClickDelegate( + const ButtonClickCallback& callback) + : callback_(callback) {} -void HandleNotificationClickedDelegate::Click() { - if (!closure_.is_null()) - closure_.Run(); +HandleNotificationClickDelegate::~HandleNotificationClickDelegate() {} + +void HandleNotificationClickDelegate::Click() { + if (!callback_.is_null()) + callback_.Run(base::nullopt); } -// HandleNotificationButtonClickDelegate: - -HandleNotificationButtonClickDelegate::HandleNotificationButtonClickDelegate( - const ButtonClickCallback& button_callback) - : button_callback_(button_callback) { -} - -HandleNotificationButtonClickDelegate:: - ~HandleNotificationButtonClickDelegate() {} - -void HandleNotificationButtonClickDelegate::ButtonClick(int button_index) { - if (!button_callback_.is_null()) - button_callback_.Run(button_index); +void HandleNotificationClickDelegate::ButtonClick(int button_index) { + if (!callback_.is_null()) + callback_.Run(button_index); } } // namespace message_center
diff --git a/ui/message_center/notification_delegate.h b/ui/message_center/notification_delegate.h index 97108481..79f8ce4 100644 --- a/ui/message_center/notification_delegate.h +++ b/ui/message_center/notification_delegate.h
@@ -11,6 +11,7 @@ #include "base/callback.h" #include "base/macros.h" #include "base/memory/ref_counted.h" +#include "base/optional.h" #include "base/strings/string16.h" #include "ui/message_center/message_center_export.h" @@ -55,45 +56,33 @@ friend class base::RefCountedThreadSafe<NotificationDelegate>; }; -// A simple notification delegate which invokes the passed closure when clicked. -class MESSAGE_CENTER_EXPORT HandleNotificationClickedDelegate +// A simple notification delegate which invokes the passed closure when the body +// or a button is clicked. +class MESSAGE_CENTER_EXPORT HandleNotificationClickDelegate : public NotificationDelegate { public: - explicit HandleNotificationClickedDelegate(const base::Closure& closure); + // The parameter is the index of the button that was clicked, or nullopt if + // the body was clicked. + using ButtonClickCallback = base::Callback<void(base::Optional<int>)>; + + // Creates a delegate that handles clicks on a button or on the body. + explicit HandleNotificationClickDelegate(const ButtonClickCallback& callback); + + // Creates a delegate that only handles clicks on the body of the + // notification. + explicit HandleNotificationClickDelegate(const base::Closure& closure); // message_center::NotificationDelegate overrides: void Click() override; - - protected: - ~HandleNotificationClickedDelegate() override; - - private: - std::string id_; - base::Closure closure_; - - DISALLOW_COPY_AND_ASSIGN(HandleNotificationClickedDelegate); -}; - -// A notification delegate which invokes a callback when a notification button -// has been clicked. -class MESSAGE_CENTER_EXPORT HandleNotificationButtonClickDelegate - : public NotificationDelegate { - public: - typedef base::Callback<void(int)> ButtonClickCallback; - - explicit HandleNotificationButtonClickDelegate( - const ButtonClickCallback& button_callback); - - // message_center::NotificationDelegate overrides: void ButtonClick(int button_index) override; protected: - ~HandleNotificationButtonClickDelegate() override; + ~HandleNotificationClickDelegate() override; private: - ButtonClickCallback button_callback_; + ButtonClickCallback callback_; - DISALLOW_COPY_AND_ASSIGN(HandleNotificationButtonClickDelegate); + DISALLOW_COPY_AND_ASSIGN(HandleNotificationClickDelegate); }; } // namespace message_center
diff --git a/ui/message_center/notification_delegate_unittest.cc b/ui/message_center/notification_delegate_unittest.cc index d168cfe..c45ee0b 100644 --- a/ui/message_center/notification_delegate_unittest.cc +++ b/ui/message_center/notification_delegate_unittest.cc
@@ -14,56 +14,53 @@ class NotificationDelegateTest : public testing::Test { public: - NotificationDelegateTest(); - ~NotificationDelegateTest() override; + NotificationDelegateTest() = default; + ~NotificationDelegateTest() override = default; - void ClickCallback(); + void BodyClickCallback() { ++callback_count_; } - int GetClickedCallbackAndReset(); + void ButtonClickCallback(base::Optional<int> button_index) { + ++callback_count_; + last_button_index_ = button_index; + } + + protected: + int callback_count_ = 0; + base::Optional<int> last_button_index_; private: - int callback_count_; - DISALLOW_COPY_AND_ASSIGN(NotificationDelegateTest); }; -NotificationDelegateTest::NotificationDelegateTest() : callback_count_(0) {} - -NotificationDelegateTest::~NotificationDelegateTest() {} - -void NotificationDelegateTest::ClickCallback() { - ++callback_count_; -} - -int NotificationDelegateTest::GetClickedCallbackAndReset() { - int result = callback_count_; - callback_count_ = 0; - return result; -} - -TEST_F(NotificationDelegateTest, ClickedDelegate) { - scoped_refptr<HandleNotificationClickedDelegate> delegate( - new HandleNotificationClickedDelegate( - base::Bind(&NotificationDelegateTest::ClickCallback, - base::Unretained(this)))); +TEST_F(NotificationDelegateTest, ClickDelegate) { + auto delegate = base::MakeRefCounted<HandleNotificationClickDelegate>( + base::Bind(&NotificationDelegateTest::BodyClickCallback, + base::Unretained(this))); delegate->Click(); - EXPECT_EQ(1, GetClickedCallbackAndReset()); - - // ButtonClick doesn't call the callback. - delegate->ButtonClick(0); - EXPECT_EQ(0, GetClickedCallbackAndReset()); + EXPECT_EQ(1, callback_count_); } -TEST_F(NotificationDelegateTest, NullClickedDelegate) { - scoped_refptr<HandleNotificationClickedDelegate> delegate( - new HandleNotificationClickedDelegate(base::Closure())); +TEST_F(NotificationDelegateTest, NullClickDelegate) { + auto delegate = + base::MakeRefCounted<HandleNotificationClickDelegate>(base::Closure()); delegate->Click(); - EXPECT_EQ(0, GetClickedCallbackAndReset()); + EXPECT_EQ(0, callback_count_); +} - delegate->ButtonClick(0); - EXPECT_EQ(0, GetClickedCallbackAndReset()); +TEST_F(NotificationDelegateTest, ButtonClickDelegate) { + auto delegate = base::MakeRefCounted<HandleNotificationClickDelegate>( + base::Bind(&NotificationDelegateTest::ButtonClickCallback, + base::Unretained(this))); + + delegate->Click(); + EXPECT_EQ(1, callback_count_); + EXPECT_EQ(base::nullopt, last_button_index_); + + delegate->ButtonClick(3); + EXPECT_EQ(2, callback_count_); + EXPECT_EQ(3, *last_button_index_); } } // namespace message_center