diff options
author | sriramsr <sriramsr@chromium.org> | 2015-01-26 14:45:04 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-01-26 22:46:28 +0000 |
commit | a41db560b2f4f86d1b8b05bfbad6b0684314662a (patch) | |
tree | 1d166d91dc00bfe65160b8aa59b0b4f51592ed5b | |
parent | 3a9f3a8b726c46f9907a9b1d1658f3e0c6169377 (diff) | |
download | chromium_src-a41db560b2f4f86d1b8b05bfbad6b0684314662a.zip chromium_src-a41db560b2f4f86d1b8b05bfbad6b0684314662a.tar.gz chromium_src-a41db560b2f4f86d1b8b05bfbad6b0684314662a.tar.bz2 |
Refactor fullscreen_controller.
Split FullscreenController to MouseController (and leave fullscreen related parts in original class). ExclusiveAccessManager is responsible for coordinating the different exclusive access controllers.
BUG=166928
TEST=Requires MANUAL testing of fullscreen and pointer/mouse lock is required as tests are disabled for being flaky
Review URL: https://codereview.chromium.org/836933005
Cr-Commit-Position: refs/heads/master@{#313159}
33 files changed, 988 insertions, 542 deletions
diff --git a/chrome/browser/chromeos/login/lock/screen_locker_browsertest.cc b/chrome/browser/chromeos/login/lock/screen_locker_browsertest.cc index d5558b8..8de336e 100644 --- a/chrome/browser/chromeos/login/lock/screen_locker_browsertest.cc +++ b/chrome/browser/chromeos/login/lock/screen_locker_browsertest.cc @@ -185,7 +185,10 @@ IN_PROC_BROWSER_TEST_F(ScreenLockerTest, TestFullscreenExit) { browser_window->GetNativeWindow()); { Waiter waiter(browser()); - browser()->fullscreen_controller()->ToggleBrowserFullscreenMode(); + browser() + ->exclusive_access_manager() + ->fullscreen_controller() + ->ToggleBrowserFullscreenMode(); waiter.Wait(false /* not locked */, true /* full screen */); EXPECT_TRUE(browser_window->IsFullscreen()); EXPECT_FALSE(window_state->hide_shelf_when_fullscreen()); @@ -208,7 +211,10 @@ IN_PROC_BROWSER_TEST_F(ScreenLockerTest, TestFullscreenExit) { EXPECT_FALSE(tester->IsLocked()); { Waiter waiter(browser()); - browser()->fullscreen_controller()->ToggleBrowserFullscreenMode(); + browser() + ->exclusive_access_manager() + ->fullscreen_controller() + ->ToggleBrowserFullscreenMode(); waiter.Wait(false /* not locked */, false /* fullscreen */); EXPECT_FALSE(browser_window->IsFullscreen()); } @@ -220,8 +226,10 @@ IN_PROC_BROWSER_TEST_F(ScreenLockerTest, TestFullscreenExit) { Waiter waiter(browser()); content::WebContents* web_contents = browser()->tab_strip_model()->GetActiveWebContents(); - browser()->fullscreen_controller()->EnterFullscreenModeForTab( - web_contents, GURL()); + browser() + ->exclusive_access_manager() + ->fullscreen_controller() + ->EnterFullscreenModeForTab(web_contents, GURL()); waiter.Wait(false /* not locked */, true /* fullscreen */); EXPECT_TRUE(browser_window->IsFullscreen()); EXPECT_TRUE(window_state->hide_shelf_when_fullscreen()); diff --git a/chrome/browser/ui/browser.cc b/chrome/browser/ui/browser.cc index 1745f71..76085e9 100644 --- a/chrome/browser/ui/browser.cc +++ b/chrome/browser/ui/browser.cc @@ -104,6 +104,7 @@ #include "chrome/browser/ui/chrome_pages.h" #include "chrome/browser/ui/chrome_select_file_policy.h" #include "chrome/browser/ui/exclusive_access/fullscreen_controller.h" +#include "chrome/browser/ui/exclusive_access/mouse_lock_controller.h" #include "chrome/browser/ui/fast_unload_controller.h" #include "chrome/browser/ui/find_bar/find_bar.h" #include "chrome/browser/ui/find_bar/find_bar_controller.h" @@ -444,7 +445,7 @@ Browser::Browser(const CreateParams& params) #endif // defined(OS_WIN) } - fullscreen_controller_.reset(new FullscreenController(this)); + exclusive_access_manager_.reset(new ExclusiveAccessManager(this)); // Must be initialized after window_. // Also: surprise! a modal dialog host is not necessary to host modal dialogs @@ -784,7 +785,8 @@ Browser::DownloadClosePreventionType Browser::OkToCloseWithInProgressDownloads( // Browser, Tab adding/showing functions: void Browser::WindowFullscreenStateChanged() { - fullscreen_controller_->WindowFullscreenStateChanged(); + exclusive_access_manager_->fullscreen_controller() + ->WindowFullscreenStateChanged(); command_controller_->FullscreenStateChanged(); UpdateBookmarkBarState(BOOKMARK_BAR_STATE_CHANGE_TOGGLE_FULLSCREEN); } @@ -793,8 +795,8 @@ void Browser::WindowFullscreenStateChanged() { // Browser, Assorted browser commands: void Browser::ToggleFullscreenModeWithExtension(const GURL& extension_url) { - fullscreen_controller_-> - ToggleBrowserFullscreenModeWithExtension(extension_url); + exclusive_access_manager_->fullscreen_controller() + ->ToggleBrowserFullscreenModeWithExtension(extension_url); } bool Browser::SupportsWindowFeature(WindowFeature feature) const { @@ -944,7 +946,7 @@ void Browser::TabInsertedAt(WebContents* contents, void Browser::TabClosingAt(TabStripModel* tab_strip_model, WebContents* contents, int index) { - fullscreen_controller_->OnTabClosing(contents); + exclusive_access_manager_->OnTabClosing(contents); SessionService* session_service = SessionServiceFactory::GetForProfile(profile_); if (session_service) @@ -980,7 +982,7 @@ void Browser::TabDetachedAt(WebContents* contents, int index) { } void Browser::TabDeactivated(WebContents* contents) { - fullscreen_controller_->OnTabDeactivated(contents); + exclusive_access_manager_->OnTabDeactivated(contents); search_delegate_->OnTabDeactivated(contents); SearchTabHelper::FromWebContents(contents)->OnTabDeactivated(); @@ -1008,7 +1010,7 @@ void Browser::ActiveTabChanged(WebContents* old_contents, // is updated. window_->OnActiveTabChanged(old_contents, new_contents, index, reason); - fullscreen_controller_->OnTabDetachedFromView(old_contents); + exclusive_access_manager_->OnTabDetachedFromView(old_contents); // Discarded tabs always get reloaded. if (tab_strip_model_->IsTabDiscarded(index)) { @@ -1080,7 +1082,7 @@ void Browser::TabReplacedAt(TabStripModel* tab_strip_model, WebContents* new_contents, int index) { TabDetachedAtImpl(old_contents, index, DETACH_TYPE_REPLACE); - fullscreen_controller_->OnTabClosing(old_contents); + exclusive_access_manager_->OnTabClosing(old_contents); SessionService* session_service = SessionServiceFactory::GetForProfile(profile_); if (session_service) @@ -1180,10 +1182,10 @@ bool Browser::ShouldPreserveAbortedURLs(WebContents* source) { bool Browser::PreHandleKeyboardEvent(content::WebContents* source, const NativeWebKeyboardEvent& event, bool* is_keyboard_shortcut) { - // Escape exits tabbed fullscreen mode. + // Escape exits tabbed fullscreen mode and mouse lock, and possibly others. // TODO(koz): Write a test for this http://crbug.com/100441. if (event.windowsKeyCode == 27 && - fullscreen_controller_->HandleUserPressedEscape()) { + exclusive_access_manager_->HandleUserPressedEscape()) { return true; } return window()->PreHandleKeyboardEvent(event, is_keyboard_shortcut); @@ -1261,7 +1263,7 @@ bool Browser::CanDragEnter(content::WebContents* source, } bool Browser::IsMouseLocked() const { - return fullscreen_controller_->IsMouseLocked(); + return exclusive_access_manager_->mouse_lock_controller()->IsMouseLocked(); } void Browser::OnWindowDidShow() { @@ -1665,16 +1667,19 @@ bool Browser::EmbedsFullscreenWidget() const { void Browser::EnterFullscreenModeForTab(WebContents* web_contents, const GURL& origin) { - fullscreen_controller_->EnterFullscreenModeForTab(web_contents, origin); + exclusive_access_manager_->fullscreen_controller()->EnterFullscreenModeForTab( + web_contents, origin); } void Browser::ExitFullscreenModeForTab(WebContents* web_contents) { - fullscreen_controller_->ExitFullscreenModeForTab(web_contents); + exclusive_access_manager_->fullscreen_controller()->ExitFullscreenModeForTab( + web_contents); } bool Browser::IsFullscreenForTabOrPending( const WebContents* web_contents) const { - return fullscreen_controller_->IsFullscreenForTabOrPending(web_contents); + return exclusive_access_manager_->fullscreen_controller() + ->IsFullscreenForTabOrPending(web_contents); } void Browser::RegisterProtocolHandler(WebContents* web_contents, @@ -1770,13 +1775,12 @@ void Browser::FindReply(WebContents* web_contents, void Browser::RequestToLockMouse(WebContents* web_contents, bool user_gesture, bool last_unlocked_by_target) { - fullscreen_controller_->RequestToLockMouse(web_contents, - user_gesture, - last_unlocked_by_target); + exclusive_access_manager_->mouse_lock_controller()->RequestToLockMouse( + web_contents, user_gesture, last_unlocked_by_target); } void Browser::LostMouseLock() { - fullscreen_controller_->LostMouseLock(); + exclusive_access_manager_->mouse_lock_controller()->LostMouseLock(); } void Browser::RequestMediaAccessPermission( diff --git a/chrome/browser/ui/browser.h b/chrome/browser/ui/browser.h index e7aff35..b4b3033 100644 --- a/chrome/browser/ui/browser.h +++ b/chrome/browser/ui/browser.h @@ -24,6 +24,7 @@ #include "chrome/browser/ui/bookmarks/bookmark_tab_helper_delegate.h" #include "chrome/browser/ui/browser_navigator.h" #include "chrome/browser/ui/chrome_web_modal_dialog_manager_delegate.h" +#include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h" #include "chrome/browser/ui/host_desktop.h" #include "chrome/browser/ui/search/search_tab_helper_delegate.h" #include "chrome/browser/ui/search_engines/search_engine_tab_helper_delegate.h" @@ -57,7 +58,6 @@ class BrowserToolbarModelDelegate; class BrowserTabRestoreServiceDelegate; class BrowserWindow; class FindBarController; -class FullscreenController; class PrefService; class Profile; class SearchDelegate; @@ -475,8 +475,8 @@ class Browser : public TabStripModelObserver, // Show a download on the download shelf. void ShowDownload(content::DownloadItem* download); - FullscreenController* fullscreen_controller() const { - return fullscreen_controller_.get(); + ExclusiveAccessManager* exclusive_access_manager() { + return exclusive_access_manager_.get(); } extensions::WindowController* extension_window_controller() const { @@ -954,7 +954,7 @@ class Browser : public TabStripModelObserver, BookmarkBar::State bookmark_bar_state_; - scoped_ptr<FullscreenController> fullscreen_controller_; + scoped_ptr<ExclusiveAccessManager> exclusive_access_manager_; scoped_ptr<extensions::WindowController> extension_window_controller_; diff --git a/chrome/browser/ui/browser_commands.cc b/chrome/browser/ui/browser_commands.cc index a9f6f9b..b3f36a6 100644 --- a/chrome/browser/ui/browser_commands.cc +++ b/chrome/browser/ui/browser_commands.cc @@ -1130,7 +1130,9 @@ void ToggleRequestTabletSite(Browser* browser) { void ToggleFullscreenMode(Browser* browser) { DCHECK(browser); - browser->fullscreen_controller()->ToggleBrowserFullscreenMode(); + browser->exclusive_access_manager() + ->fullscreen_controller() + ->ToggleBrowserFullscreenMode(); } void ClearCache(Browser* browser) { diff --git a/chrome/browser/ui/browser_commands_mac.cc b/chrome/browser/ui/browser_commands_mac.cc index 4974524..1cf43c6 100644 --- a/chrome/browser/ui/browser_commands_mac.cc +++ b/chrome/browser/ui/browser_commands_mac.cc @@ -16,7 +16,9 @@ namespace chrome { void ToggleFullscreenWithToolbarOrFallback(Browser* browser) { DCHECK(browser); if (chrome::mac::SupportsSystemFullscreen()) - browser->fullscreen_controller()->ToggleBrowserFullscreenWithToolbar(); + browser->exclusive_access_manager() + ->fullscreen_controller() + ->ToggleBrowserFullscreenWithToolbar(); else ToggleFullscreenMode(browser); } diff --git a/chrome/browser/ui/browser_win.cc b/chrome/browser/ui/browser_win.cc index d655621f..ad4bdab 100644 --- a/chrome/browser/ui/browser_win.cc +++ b/chrome/browser/ui/browser_win.cc @@ -7,5 +7,5 @@ #include "chrome/browser/ui/exclusive_access/fullscreen_controller.h" void Browser::SetMetroSnapMode(bool enable) { - fullscreen_controller_->SetMetroSnapMode(enable); + exclusive_access_manager_->fullscreen_controller()->SetMetroSnapMode(enable); } diff --git a/chrome/browser/ui/cocoa/browser_window_cocoa.mm b/chrome/browser/ui/cocoa/browser_window_cocoa.mm index c03fc97..c20de41 100644 --- a/chrome/browser/ui/cocoa/browser_window_cocoa.mm +++ b/chrome/browser/ui/cocoa/browser_window_cocoa.mm @@ -361,7 +361,9 @@ void BrowserWindowCocoa::Restore() { void BrowserWindowCocoa::EnterFullscreen(const GURL& url, ExclusiveAccessBubbleType bubble_type, bool with_toolbar) { - if (browser_->fullscreen_controller()->IsWindowFullscreenForTabOrPending()) + if (browser_->exclusive_access_manager() + ->fullscreen_controller() + ->IsWindowFullscreenForTabOrPending()) [controller_ enterWebContentFullscreenForURL:url bubbleType:bubble_type]; else if (!url.is_empty()) [controller_ enterExtensionFullscreenForURL:url bubbleType:bubble_type]; diff --git a/chrome/browser/ui/cocoa/browser_window_controller_private.mm b/chrome/browser/ui/cocoa/browser_window_controller_private.mm index f2c086b..1ed775b 100644 --- a/chrome/browser/ui/cocoa/browser_window_controller_private.mm +++ b/chrome/browser/ui/cocoa/browser_window_controller_private.mm @@ -426,8 +426,9 @@ willPositionSheet:(NSWindow*)sheet } - (void)configurePresentationModeController { - BOOL fullscreen_for_tab = - browser_->fullscreen_controller()->IsWindowFullscreenForTabOrPending(); + BOOL fullscreen_for_tab = browser_->exclusive_access_manager() + ->fullscreen_controller() + ->IsWindowFullscreenForTabOrPending(); BOOL kiosk_mode = base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kKioskMode); BOOL showDropdown = @@ -670,7 +671,9 @@ willPositionSheet:(NSWindow*)sheet NSWindow* window = [self window]; savedRegularWindowFrame_ = [window frame]; BOOL mode = enteringPresentationMode_ || - browser_->fullscreen_controller()->IsWindowFullscreenForTabOrPending(); + browser_->exclusive_access_manager() + ->fullscreen_controller() + ->IsWindowFullscreenForTabOrPending(); enteringAppKitFullscreen_ = YES; enteringAppKitFullscreenOnPrimaryScreen_ = [[[self window] screen] isEqual:[[NSScreen screens] objectAtIndex:0]]; diff --git a/chrome/browser/ui/cocoa/exclusive_access_bubble_window_controller.mm b/chrome/browser/ui/cocoa/exclusive_access_bubble_window_controller.mm index d6c0de1..6274888 100644 --- a/chrome/browser/ui/cocoa/exclusive_access_bubble_window_controller.mm +++ b/chrome/browser/ui/cocoa/exclusive_access_bubble_window_controller.mm @@ -96,12 +96,12 @@ const float kHideDuration = 0.7; [[self window] setIgnoresMouseEvents:YES]; DCHECK(exclusive_access_bubble::ShowButtonsForType(bubbleType_)); - browser_->fullscreen_controller()->OnAcceptFullscreenPermission(); + browser_->exclusive_access_manager()->OnAcceptExclusiveAccessPermission(); } - (void)deny:(id)sender { DCHECK(exclusive_access_bubble::ShowButtonsForType(bubbleType_)); - browser_->fullscreen_controller()->OnDenyFullscreenPermission(); + browser_->exclusive_access_manager()->OnDenyExclusiveAccessPermission(); } - (void)showButtons:(BOOL)show { @@ -151,8 +151,9 @@ const float kHideDuration = 0.7; - (BOOL)textView:(NSTextView*)textView clickedOnLink:(id)link atIndex:(NSUInteger)charIndex { - browser_->fullscreen_controller() - ->ExitTabOrBrowserFullscreenToPreviousState(); + browser_->exclusive_access_manager() + ->fullscreen_controller() + ->ExitExclusiveAccessToPreviousState(); return YES; } diff --git a/chrome/browser/ui/exclusive_access/exclusive_access_bubble.cc b/chrome/browser/ui/exclusive_access/exclusive_access_bubble.cc index 3583024..178e97d 100644 --- a/chrome/browser/ui/exclusive_access/exclusive_access_bubble.cc +++ b/chrome/browser/ui/exclusive_access/exclusive_access_bubble.cc @@ -115,16 +115,17 @@ void ExclusiveAccessBubble::CheckMousePosition() { } void ExclusiveAccessBubble::ToggleFullscreen() { - browser_->fullscreen_controller() - ->ExitTabOrBrowserFullscreenToPreviousState(); + browser_->exclusive_access_manager() + ->fullscreen_controller() + ->ExitExclusiveAccessToPreviousState(); } void ExclusiveAccessBubble::Accept() { - browser_->fullscreen_controller()->OnAcceptFullscreenPermission(); + browser_->exclusive_access_manager()->OnAcceptExclusiveAccessPermission(); } void ExclusiveAccessBubble::Cancel() { - browser_->fullscreen_controller()->OnDenyFullscreenPermission(); + browser_->exclusive_access_manager()->OnDenyExclusiveAccessPermission(); } base::string16 ExclusiveAccessBubble::GetCurrentMessageText() const { diff --git a/chrome/browser/ui/exclusive_access/exclusive_access_controller_base.cc b/chrome/browser/ui/exclusive_access/exclusive_access_controller_base.cc new file mode 100644 index 0000000..db8a243 --- /dev/null +++ b/chrome/browser/ui/exclusive_access/exclusive_access_controller_base.cc @@ -0,0 +1,93 @@ +// Copyright (c) 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/exclusive_access/exclusive_access_controller_base.h" + +#include "chrome/browser/chrome_notification_types.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_window.h" +#include "content/public/browser/navigation_details.h" +#include "content/public/browser/navigation_entry.h" +#include "content/public/browser/notification_service.h" +#include "content/public/browser/web_contents.h" + +using content::WebContents; + +ExclusiveAccessControllerBase::ExclusiveAccessControllerBase( + ExclusiveAccessManager* manager, + Browser* browser) + : manager_(manager), + browser_(browser), + profile_(browser->profile()), + tab_with_exclusive_access_(nullptr) { + DCHECK(profile_); +} + +ExclusiveAccessControllerBase::~ExclusiveAccessControllerBase() { +} + +GURL ExclusiveAccessControllerBase::GetExclusiveAccessBubbleURL() const { + return manager_->GetExclusiveAccessBubbleURL(); +} + +GURL ExclusiveAccessControllerBase::GetURLForExclusiveAccessBubble() const { + if (tab_with_exclusive_access_) + return tab_with_exclusive_access_->GetURL(); + return GURL(); +} + +void ExclusiveAccessControllerBase::OnTabDeactivated( + WebContents* web_contents) { + if (web_contents == tab_with_exclusive_access_) + ExitExclusiveAccessIfNecessary(); +} + +void ExclusiveAccessControllerBase::OnTabDetachedFromView( + WebContents* old_contents) { + // Derived class will have to implement if necessary. +} + +void ExclusiveAccessControllerBase::OnTabClosing(WebContents* web_contents) { + if (web_contents == tab_with_exclusive_access_) { + ExitExclusiveAccessIfNecessary(); + + // The call to exit exclusive access may result in asynchronous notification + // of state change (e.g. fullscreen change on Linux). We don't want to rely + // on it to call NotifyTabExclusiveAccessLost(), because at that point + // |tab_with_exclusive_access_| may not be valid. Instead, we call it here + // to clean up exclusive access tab related state. + NotifyTabExclusiveAccessLost(); + } +} + +void ExclusiveAccessControllerBase::Observe( + int type, + const content::NotificationSource& source, + const content::NotificationDetails& details) { + DCHECK_EQ(content::NOTIFICATION_NAV_ENTRY_COMMITTED, type); + if (content::Details<content::LoadCommittedDetails>(details) + ->is_navigation_to_different_page()) + ExitExclusiveAccessIfNecessary(); +} + +void ExclusiveAccessControllerBase::SetTabWithExclusiveAccess( + WebContents* tab) { + // Tab should never be replaced with another tab, or + // UpdateNotificationRegistrations would need updating. + DCHECK(tab_with_exclusive_access_ == tab || + tab_with_exclusive_access_ == nullptr || tab == nullptr); + tab_with_exclusive_access_ = tab; + UpdateNotificationRegistrations(); +} + +void ExclusiveAccessControllerBase::UpdateNotificationRegistrations() { + if (tab_with_exclusive_access_ && registrar_.IsEmpty()) { + registrar_.Add(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, + content::Source<content::NavigationController>( + &tab_with_exclusive_access_->GetController())); + } else if (!tab_with_exclusive_access_ && !registrar_.IsEmpty()) { + registrar_.RemoveAll(); + } +} diff --git a/chrome/browser/ui/exclusive_access/exclusive_access_controller_base.h b/chrome/browser/ui/exclusive_access/exclusive_access_controller_base.h new file mode 100644 index 0000000..99c5614 --- /dev/null +++ b/chrome/browser/ui/exclusive_access/exclusive_access_controller_base.h @@ -0,0 +1,101 @@ +// Copyright (c) 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_EXCLUSIVE_ACCESS_EXCLUSIVE_ACCESS_CONTROLLER_BASE_H_ +#define CHROME_BROWSER_UI_EXCLUSIVE_ACCESS_EXCLUSIVE_ACCESS_CONTROLLER_BASE_H_ + +#include "base/basictypes.h" +#include "base/memory/weak_ptr.h" +#include "chrome/browser/ui/exclusive_access/exclusive_access_bubble_type.h" +#include "content/public/browser/notification_observer.h" +#include "content/public/browser/notification_registrar.h" + +class Browser; +class BrowserWindow; +class ExclusiveAccessManager; +class GURL; +class Profile; + +namespace content { +class WebContents; +} + +// The base class for the different exclusive access controllers like the +// FullscreenController, and MouseLockController which controls lifetime for +// which the resource (screen/mouse) is held exclusively. +class ExclusiveAccessControllerBase : public content::NotificationObserver { + public: + explicit ExclusiveAccessControllerBase(ExclusiveAccessManager* manager, + Browser* browser); + ~ExclusiveAccessControllerBase() override; + + GURL GetExclusiveAccessBubbleURL() const; + virtual GURL GetURLForExclusiveAccessBubble() const; + + content::WebContents* exclusive_access_tab() const { + return tab_with_exclusive_access_; + } + + // Functions implemented by derived classes: + + // Control behavior when escape is pressed returning true if it was handled. + virtual bool HandleUserPressedEscape() = 0; + + // Called by Browser in response to call from ExclusiveAccessBubble. + virtual void ExitExclusiveAccessToPreviousState() = 0; + + // Called to indicate that the permission for this exclusive access has been + // granted if requested. Returns true if the exit bubble content should be + // updated. + virtual bool OnAcceptExclusiveAccessPermission() = 0; + + // Called to indicate that the permission for the exclusive access has been + // denied if requested. Returns true if the exit bubble content should be + // updated. + virtual bool OnDenyExclusiveAccessPermission() = 0; + + // Called by ExclusiveAccessManager in response to calls from Browser. + virtual void OnTabDeactivated(content::WebContents* web_contents); + virtual void OnTabDetachedFromView(content::WebContents* web_contents); + virtual void OnTabClosing(content::WebContents* web_contents); + + // Callbacks //////////////////////////////////////////////////////////////// + + // content::NotificationObserver to detect page navigation and exit exclusive + // access. + void Observe(int type, + const content::NotificationSource& source, + const content::NotificationDetails& details) override; + + protected: + void SetTabWithExclusiveAccess(content::WebContents* tab); + + ExclusiveAccessManager* exclusive_access_manager() const { return manager_; } + + Browser* browser() const { return browser_; } + + Profile* profile() const { return profile_; } + + // Exits exclusive access mode for the tab if currently exclusive. + virtual void ExitExclusiveAccessIfNecessary() = 0; + + // Notifies the tab that it has been forced out of exclusive access mode + // if necessary. + virtual void NotifyTabExclusiveAccessLost() = 0; + + private: + void UpdateNotificationRegistrations(); + + ExclusiveAccessManager* const manager_; + Browser* const browser_; + Profile* const profile_; + + content::NotificationRegistrar registrar_; + + content::WebContents* tab_with_exclusive_access_; + + DISALLOW_COPY_AND_ASSIGN(ExclusiveAccessControllerBase); +}; + +#endif // CHROME_BROWSER_UI_EXCLUSIVE_ACCESS_EXCLUSIVE_ACCESS_CONTROLLER_BASE_H_ diff --git a/chrome/browser/ui/exclusive_access/exclusive_access_manager.cc b/chrome/browser/ui/exclusive_access/exclusive_access_manager.cc new file mode 100644 index 0000000..56a8cc6 --- /dev/null +++ b/chrome/browser/ui/exclusive_access/exclusive_access_manager.cc @@ -0,0 +1,119 @@ +// Copyright (c) 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h" + +#include "chrome/browser/app_mode/app_mode_utils.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_window.h" +#include "chrome/browser/ui/exclusive_access/fullscreen_controller.h" +#include "chrome/browser/ui/exclusive_access/mouse_lock_controller.h" + +using content::WebContents; + +ExclusiveAccessManager::ExclusiveAccessManager(Browser* browser) + : browser_(browser), + fullscreen_controller_(this, browser), + mouse_lock_controller_(this, browser) { +} + +ExclusiveAccessManager::~ExclusiveAccessManager() { +} + +ExclusiveAccessBubbleType +ExclusiveAccessManager::GetExclusiveAccessExitBubbleType() const { + // In kiosk and exclusive app mode we always want to be fullscreen and do not + // want to show exit instructions for browser mode fullscreen. + bool app_mode = false; +#if !defined(OS_MACOSX) // App mode (kiosk) is not available on Mac yet. + app_mode = chrome::IsRunningInAppMode(); +#endif + + if (mouse_lock_controller_.IsMouseLockSilentlyAccepted() && + (!fullscreen_controller_.IsWindowFullscreenForTabOrPending() || + fullscreen_controller_.IsUserAcceptedFullscreen())) + return EXCLUSIVE_ACCESS_BUBBLE_TYPE_NONE; + + if (!fullscreen_controller_.IsWindowFullscreenForTabOrPending()) { + if (mouse_lock_controller_.IsMouseLocked()) + return EXCLUSIVE_ACCESS_BUBBLE_TYPE_MOUSELOCK_EXIT_INSTRUCTION; + if (mouse_lock_controller_.IsMouseLockRequested()) + return EXCLUSIVE_ACCESS_BUBBLE_TYPE_MOUSELOCK_BUTTONS; + if (fullscreen_controller_.IsExtensionFullscreenOrPending()) + return EXCLUSIVE_ACCESS_BUBBLE_TYPE_EXTENSION_FULLSCREEN_EXIT_INSTRUCTION; + if (fullscreen_controller_.IsControllerInitiatedFullscreen() && !app_mode) + return EXCLUSIVE_ACCESS_BUBBLE_TYPE_BROWSER_FULLSCREEN_EXIT_INSTRUCTION; + return EXCLUSIVE_ACCESS_BUBBLE_TYPE_NONE; + } + + if (fullscreen_controller_.IsUserAcceptedFullscreen()) { + if (fullscreen_controller_.IsPrivilegedFullscreenForTab()) + return EXCLUSIVE_ACCESS_BUBBLE_TYPE_NONE; + if (mouse_lock_controller_.IsMouseLocked()) + return EXCLUSIVE_ACCESS_BUBBLE_TYPE_FULLSCREEN_MOUSELOCK_EXIT_INSTRUCTION; + if (mouse_lock_controller_.IsMouseLockRequested()) + return EXCLUSIVE_ACCESS_BUBBLE_TYPE_MOUSELOCK_BUTTONS; + return EXCLUSIVE_ACCESS_BUBBLE_TYPE_FULLSCREEN_EXIT_INSTRUCTION; + } + + if (mouse_lock_controller_.IsMouseLockRequested()) + return EXCLUSIVE_ACCESS_BUBBLE_TYPE_FULLSCREEN_MOUSELOCK_BUTTONS; + return EXCLUSIVE_ACCESS_BUBBLE_TYPE_FULLSCREEN_BUTTONS; +} + +void ExclusiveAccessManager::UpdateExclusiveAccessExitBubbleContent() { + GURL url = GetExclusiveAccessBubbleURL(); + ExclusiveAccessBubbleType bubble_type = GetExclusiveAccessExitBubbleType(); + + // If bubble displays buttons, unlock mouse to allow pressing them. + if (exclusive_access_bubble::ShowButtonsForType(bubble_type) && + mouse_lock_controller_.IsMouseLocked()) + mouse_lock_controller_.UnlockMouse(); + + browser_->window()->UpdateFullscreenExitBubbleContent(url, bubble_type); +} + +GURL ExclusiveAccessManager::GetExclusiveAccessBubbleURL() const { + GURL result = fullscreen_controller_.GetURLForExclusiveAccessBubble(); + if (!result.is_valid()) + result = mouse_lock_controller_.GetURLForExclusiveAccessBubble(); + return result; +} + +void ExclusiveAccessManager::OnTabDeactivated(WebContents* web_contents) { + fullscreen_controller_.OnTabDeactivated(web_contents); + mouse_lock_controller_.OnTabDeactivated(web_contents); +} + +void ExclusiveAccessManager::OnTabDetachedFromView(WebContents* web_contents) { + fullscreen_controller_.OnTabDetachedFromView(web_contents); + mouse_lock_controller_.OnTabDetachedFromView(web_contents); +} + +void ExclusiveAccessManager::OnTabClosing(WebContents* web_contents) { + fullscreen_controller_.OnTabClosing(web_contents); + mouse_lock_controller_.OnTabClosing(web_contents); +} + +bool ExclusiveAccessManager::HandleUserPressedEscape() { + bool handled = false; + handled = fullscreen_controller_.HandleUserPressedEscape(); + handled |= mouse_lock_controller_.HandleUserPressedEscape(); + return handled; +} + +void ExclusiveAccessManager::OnAcceptExclusiveAccessPermission() { + bool updateBubble = + mouse_lock_controller_.OnAcceptExclusiveAccessPermission(); + updateBubble |= fullscreen_controller_.OnAcceptExclusiveAccessPermission(); + if (updateBubble) + UpdateExclusiveAccessExitBubbleContent(); +} + +void ExclusiveAccessManager::OnDenyExclusiveAccessPermission() { + bool updateBubble = mouse_lock_controller_.OnDenyExclusiveAccessPermission(); + updateBubble |= fullscreen_controller_.OnDenyExclusiveAccessPermission(); + if (updateBubble) + UpdateExclusiveAccessExitBubbleContent(); +} diff --git a/chrome/browser/ui/exclusive_access/exclusive_access_manager.h b/chrome/browser/ui/exclusive_access/exclusive_access_manager.h new file mode 100644 index 0000000..0c10fe5 --- /dev/null +++ b/chrome/browser/ui/exclusive_access/exclusive_access_manager.h @@ -0,0 +1,69 @@ +// Copyright (c) 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_EXCLUSIVE_ACCESS_EXCLUSIVE_ACCESS_MANAGER_H_ +#define CHROME_BROWSER_UI_EXCLUSIVE_ACCESS_EXCLUSIVE_ACCESS_MANAGER_H_ + +#include "base/memory/scoped_ptr.h" +#include "chrome/browser/ui/exclusive_access/exclusive_access_bubble_type.h" +#include "chrome/browser/ui/exclusive_access/fullscreen_controller.h" +#include "chrome/browser/ui/exclusive_access/mouse_lock_controller.h" + +class Browser; +class FullscreenController; +class GURL; +class MouseLockController; + +namespace content { +class WebContents; +} + +// This class combines the different exclusive access modes (like fullscreen and +// mouse lock) which are each handled by respective controller. It also updates +// the exit bubble to reflect the combined state. +class ExclusiveAccessManager { + public: + explicit ExclusiveAccessManager(Browser* browser); + ~ExclusiveAccessManager(); + + FullscreenController* fullscreen_controller() { + return &fullscreen_controller_; + } + + MouseLockController* mouse_lock_controller() { + return &mouse_lock_controller_; + } + + ExclusiveAccessBubbleType GetExclusiveAccessExitBubbleType() const; + void UpdateExclusiveAccessExitBubbleContent(); + + GURL GetExclusiveAccessBubbleURL() const; + + // Callbacks //////////////////////////////////////////////////////////////// + + // Called by Browser::TabDeactivated. + void OnTabDeactivated(content::WebContents* web_contents); + + // Called by Browser::ActiveTabChanged. + void OnTabDetachedFromView(content::WebContents* web_contents); + + // Called by Browser::TabClosingAt. + void OnTabClosing(content::WebContents* web_contents); + + // Called by Browser::PreHandleKeyboardEvent + bool HandleUserPressedEscape(); + + // Called by platform ExclusiveAccessExitBubble. + void OnAcceptExclusiveAccessPermission(); + void OnDenyExclusiveAccessPermission(); + + private: + Browser* const browser_; + FullscreenController fullscreen_controller_; + MouseLockController mouse_lock_controller_; + + DISALLOW_COPY_AND_ASSIGN(ExclusiveAccessManager); +}; + +#endif // CHROME_BROWSER_UI_EXCLUSIVE_ACCESS_EXCLUSIVE_ACCESS_MANAGER_H_ diff --git a/chrome/browser/ui/exclusive_access/flash_fullscreen_interactive_browsertest.cc b/chrome/browser/ui/exclusive_access/flash_fullscreen_interactive_browsertest.cc index 7102b0e..ef37aa5 100644 --- a/chrome/browser/ui/exclusive_access/flash_fullscreen_interactive_browsertest.cc +++ b/chrome/browser/ui/exclusive_access/flash_fullscreen_interactive_browsertest.cc @@ -147,8 +147,10 @@ class FlashFullscreenInteractiveBrowserTest : public OutOfProcessPPAPITest { return false; } EXPECT_EQ(GetActiveWebContents()->GetCapturerCount() > 0, - !browser()->fullscreen_controller()-> - IsWindowFullscreenForTabOrPending()); + !browser() + ->exclusive_access_manager() + ->fullscreen_controller() + ->IsWindowFullscreenForTabOrPending()); } return true; @@ -187,8 +189,11 @@ class FlashFullscreenInteractiveBrowserTest : public OutOfProcessPPAPITest { private: bool IsObservingTabInFullscreen(content::WebContents* contents, bool expected_in_fullscreen) const { - return expected_in_fullscreen == browser()->fullscreen_controller()-> - IsFullscreenForTabOrPending(contents); + return expected_in_fullscreen == + browser() + ->exclusive_access_manager() + ->fullscreen_controller() + ->IsFullscreenForTabOrPending(contents); } bool IsObservingFlashHasFocus(content::WebContents* contents, diff --git a/chrome/browser/ui/exclusive_access/fullscreen_controller.cc b/chrome/browser/ui/exclusive_access/fullscreen_controller.cc index 39cdac29..b37d04c 100644 --- a/chrome/browser/ui/exclusive_access/fullscreen_controller.cc +++ b/chrome/browser/ui/exclusive_access/fullscreen_controller.cc @@ -37,28 +37,22 @@ using base::UserMetricsAction; using content::RenderViewHost; using content::WebContents; -FullscreenController::FullscreenController(Browser* browser) - : browser_(browser), - window_(browser->window()), - profile_(browser->profile()), - fullscreened_tab_(NULL), +FullscreenController::FullscreenController(ExclusiveAccessManager* manager, + Browser* browser) + : ExclusiveAccessControllerBase(manager, browser), state_prior_to_tab_fullscreen_(STATE_INVALID), tab_fullscreen_accepted_(false), toggled_into_fullscreen_(false), - mouse_lock_tab_(NULL), - mouse_lock_state_(MOUSELOCK_NOT_REQUESTED), reentrant_window_state_change_call_check_(false), is_privileged_fullscreen_for_testing_(false), ptr_factory_(this) { - DCHECK(window_); - DCHECK(profile_); } FullscreenController::~FullscreenController() { } bool FullscreenController::IsFullscreenForBrowser() const { - return window_->IsFullscreen() && !IsFullscreenCausedByTab(); + return browser()->window()->IsFullscreen() && !IsFullscreenCausedByTab(); } void FullscreenController::ToggleBrowserFullscreenMode() { @@ -79,13 +73,26 @@ void FullscreenController::ToggleBrowserFullscreenModeWithExtension( } bool FullscreenController::IsWindowFullscreenForTabOrPending() const { - return fullscreened_tab_ != NULL; + return exclusive_access_tab() != nullptr; +} + +bool FullscreenController::IsExtensionFullscreenOrPending() const { + return !extension_caused_fullscreen_.is_empty(); +} + +bool FullscreenController::IsControllerInitiatedFullscreen() const { + return toggled_into_fullscreen_; +} + +bool FullscreenController::IsUserAcceptedFullscreen() const { + return tab_fullscreen_accepted_; } bool FullscreenController::IsFullscreenForTabOrPending( const WebContents* web_contents) const { - if (web_contents == fullscreened_tab_) { - DCHECK(web_contents == browser_->tab_strip_model()->GetActiveWebContents()); + if (web_contents == exclusive_access_tab()) { + DCHECK(web_contents == + browser()->tab_strip_model()->GetActiveWebContents()); DCHECK(web_contents->GetCapturerCount() == 0); return true; } @@ -106,7 +113,7 @@ void FullscreenController::EnterFullscreenModeForTab(WebContents* web_contents, return; } - if (web_contents != browser_->tab_strip_model()->GetActiveWebContents() || + if (web_contents != browser()->tab_strip_model()->GetActiveWebContents() || IsWindowFullscreenForTabOrPending()) { return; } @@ -120,18 +127,21 @@ void FullscreenController::EnterFullscreenModeForTab(WebContents* web_contents, return; #endif - SetFullscreenedTab(web_contents, origin); + SetTabWithExclusiveAccess(web_contents); + fullscreened_origin_ = origin; + + BrowserWindow* window = browser()->window(); - if (!window_->IsFullscreen()) { + if (!window->IsFullscreen()) { // Normal -> Tab Fullscreen. state_prior_to_tab_fullscreen_ = STATE_NORMAL; ToggleFullscreenModeInternal(TAB); return; } - if (window_->IsFullscreenWithToolbar()) { + if (window->IsFullscreenWithToolbar()) { // Browser Fullscreen with Toolbar -> Tab Fullscreen (no toolbar). - window_->UpdateFullscreenWithToolbar(false); + window->UpdateFullscreenWithToolbar(false); state_prior_to_tab_fullscreen_ = STATE_BROWSER_FULLSCREEN_WITH_TOOLBAR; } else { // Browser Fullscreen without Toolbar -> Tab Fullscreen. @@ -143,7 +153,7 @@ void FullscreenController::EnterFullscreenModeForTab(WebContents* web_contents, if (!tab_fullscreen_accepted_) { tab_fullscreen_accepted_ = GetFullscreenSetting() == CONTENT_SETTING_ALLOW; } - UpdateFullscreenExitBubbleContent(); + exclusive_access_manager()->UpdateExclusiveAccessExitBubbleContent(); // This is only a change between Browser and Tab fullscreen. We generate // a fullscreen notification now because there is no window change. @@ -158,7 +168,7 @@ void FullscreenController::ExitFullscreenModeForTab(WebContents* web_contents) { } if (!IsWindowFullscreenForTabOrPending() || - web_contents != fullscreened_tab_) { + web_contents != exclusive_access_tab()) { return; } @@ -171,7 +181,8 @@ void FullscreenController::ExitFullscreenModeForTab(WebContents* web_contents) { return; #endif - if (!window_->IsFullscreen()) + BrowserWindow* window = browser()->window(); + if (!window->IsFullscreen()) return; if (IsFullscreenCausedByTab()) { @@ -183,12 +194,12 @@ void FullscreenController::ExitFullscreenModeForTab(WebContents* web_contents) { // Tab Fullscreen -> Browser Fullscreen (with or without toolbar). if (state_prior_to_tab_fullscreen_ == STATE_BROWSER_FULLSCREEN_WITH_TOOLBAR) { // Tab Fullscreen (no toolbar) -> Browser Fullscreen with Toolbar. - window_->UpdateFullscreenWithToolbar(true); + window->UpdateFullscreenWithToolbar(true); } #if defined(OS_MACOSX) // Clear the bubble URL, which forces the Mac UI to redraw. - UpdateFullscreenExitBubbleContent(); + exclusive_access_manager()->UpdateExclusiveAccessExitBubbleContent(); #endif // defined(OS_MACOSX) // If currently there is a tab in "tab fullscreen" mode and fullscreen @@ -196,7 +207,7 @@ void FullscreenController::ExitFullscreenModeForTab(WebContents* web_contents) { // mode), we need to switch back to "browser fullscreen" mode. In this // case, all we have to do is notifying the tab that it has exited "tab // fullscreen" mode. - NotifyTabOfExitIfNecessary(); + NotifyTabExclusiveAccessLost(); // This is only a change between Browser and Tab fullscreen. We generate // a fullscreen notification now because there is no window change. @@ -205,7 +216,7 @@ void FullscreenController::ExitFullscreenModeForTab(WebContents* web_contents) { bool FullscreenController::IsInMetroSnapMode() { #if defined(OS_WIN) - return window_->IsInMetroSnapMode(); + return browser()->window()->IsInMetroSnapMode(); #else return false; #endif @@ -216,7 +227,7 @@ void FullscreenController::SetMetroSnapMode(bool enable) { reentrant_window_state_change_call_check_ = false; toggled_into_fullscreen_ = false; - window_->SetMetroSnapMode(enable); + browser()->window()->SetMetroSnapMode(enable); // FullscreenController unit tests for metro snap assume that on Windows calls // to WindowFullscreenStateChanged are reentrant. If that assumption is @@ -225,73 +236,6 @@ void FullscreenController::SetMetroSnapMode(bool enable) { } #endif // defined(OS_WIN) -bool FullscreenController::IsMouseLockRequested() const { - return mouse_lock_state_ == MOUSELOCK_REQUESTED; -} - -bool FullscreenController::IsMouseLocked() const { - return mouse_lock_state_ == MOUSELOCK_ACCEPTED || - mouse_lock_state_ == MOUSELOCK_ACCEPTED_SILENTLY; -} - -void FullscreenController::RequestToLockMouse(WebContents* web_contents, - bool user_gesture, - bool last_unlocked_by_target) { - DCHECK(!IsMouseLocked()); - NotifyMouseLockChange(); - - // Must have a user gesture to prevent misbehaving sites from constantly - // re-locking the mouse. Exceptions are when the page has unlocked - // (i.e. not the user), or if we're in tab fullscreen (user gesture required - // for that) - if (!last_unlocked_by_target && !user_gesture && - !IsFullscreenForTabOrPending(web_contents)) { - web_contents->GotResponseToLockMouseRequest(false); - return; - } - SetMouseLockTab(web_contents); - ExclusiveAccessBubbleType bubble_type = GetExclusiveAccessBubbleType(); - - switch (GetMouseLockSetting(web_contents->GetURL())) { - case CONTENT_SETTING_ALLOW: - // If bubble already displaying buttons we must not lock the mouse yet, - // or it would prevent pressing those buttons. Instead, merge the request. - if (!IsPrivilegedFullscreenForTab() && - exclusive_access_bubble::ShowButtonsForType(bubble_type)) { - mouse_lock_state_ = MOUSELOCK_REQUESTED; - } else { - // Lock mouse. - if (web_contents->GotResponseToLockMouseRequest(true)) { - if (last_unlocked_by_target) { - mouse_lock_state_ = MOUSELOCK_ACCEPTED_SILENTLY; - } else { - mouse_lock_state_ = MOUSELOCK_ACCEPTED; - } - } else { - SetMouseLockTab(NULL); - mouse_lock_state_ = MOUSELOCK_NOT_REQUESTED; - } - } - break; - case CONTENT_SETTING_BLOCK: - web_contents->GotResponseToLockMouseRequest(false); - SetMouseLockTab(NULL); - mouse_lock_state_ = MOUSELOCK_NOT_REQUESTED; - break; - case CONTENT_SETTING_ASK: - mouse_lock_state_ = MOUSELOCK_REQUESTED; - break; - default: - NOTREACHED(); - } - UpdateFullscreenExitBubbleContent(); -} - -void FullscreenController::OnTabDeactivated(WebContents* web_contents) { - if (web_contents == fullscreened_tab_ || web_contents == mouse_lock_tab_) - ExitTabFullscreenOrMouseLockIfNecessary(); -} - void FullscreenController::OnTabDetachedFromView(WebContents* old_contents) { if (!IsFullscreenForCapturedTab(old_contents)) return; @@ -327,97 +271,63 @@ void FullscreenController::OnTabDetachedFromView(WebContents* old_contents) { void FullscreenController::OnTabClosing(WebContents* web_contents) { if (IsFullscreenForCapturedTab(web_contents)) { web_contents->ExitFullscreen(); - } else if (web_contents == fullscreened_tab_ || - web_contents == mouse_lock_tab_) { - ExitTabFullscreenOrMouseLockIfNecessary(); - // The call to exit fullscreen may result in asynchronous notification of - // fullscreen state change (e.g., on Linux). We don't want to rely on it - // to call NotifyTabOfExitIfNecessary(), because at that point - // |fullscreened_tab_| may not be valid. Instead, we call it here to clean - // up tab fullscreen related state. - NotifyTabOfExitIfNecessary(); + } else { + ExclusiveAccessControllerBase::OnTabClosing(web_contents); } } void FullscreenController::WindowFullscreenStateChanged() { reentrant_window_state_change_call_check_ = true; - bool exiting_fullscreen = !window_->IsFullscreen(); + BrowserWindow* const window = browser()->window(); + bool exiting_fullscreen = !window->IsFullscreen(); PostFullscreenChangeNotification(!exiting_fullscreen); if (exiting_fullscreen) { toggled_into_fullscreen_ = false; extension_caused_fullscreen_ = GURL(); - NotifyTabOfExitIfNecessary(); + NotifyTabExclusiveAccessLost(); } if (exiting_fullscreen) { - window_->GetDownloadShelf()->Unhide(); + window->GetDownloadShelf()->Unhide(); } else { - window_->GetDownloadShelf()->Hide(); - if (window_->GetStatusBubble()) - window_->GetStatusBubble()->Hide(); + window->GetDownloadShelf()->Hide(); + if (window->GetStatusBubble()) + window->GetStatusBubble()->Hide(); } } bool FullscreenController::HandleUserPressedEscape() { WebContents* const active_web_contents = - browser_->tab_strip_model()->GetActiveWebContents(); + browser()->tab_strip_model()->GetActiveWebContents(); if (IsFullscreenForCapturedTab(active_web_contents)) { active_web_contents->ExitFullscreen(); return true; - } else if (IsWindowFullscreenForTabOrPending() || - IsMouseLocked() || IsMouseLockRequested()) { - ExitTabFullscreenOrMouseLockIfNecessary(); + } else if (IsWindowFullscreenForTabOrPending()) { + ExitExclusiveAccessIfNecessary(); return true; } return false; } -void FullscreenController::ExitTabOrBrowserFullscreenToPreviousState() { +void FullscreenController::ExitExclusiveAccessToPreviousState() { if (IsWindowFullscreenForTabOrPending()) - ExitTabFullscreenOrMouseLockIfNecessary(); + ExitFullscreenModeForTab(exclusive_access_tab()); else if (IsFullscreenForBrowser()) ExitFullscreenModeInternal(); } -void FullscreenController::OnAcceptFullscreenPermission() { - ExclusiveAccessBubbleType bubble_type = GetExclusiveAccessBubbleType(); - bool mouse_lock = false; +bool FullscreenController::OnAcceptExclusiveAccessPermission() { + ExclusiveAccessBubbleType bubble_type = + exclusive_access_manager()->GetExclusiveAccessExitBubbleType(); bool fullscreen = false; exclusive_access_bubble::PermissionRequestedByType(bubble_type, &fullscreen, - &mouse_lock); + nullptr); DCHECK(!(fullscreen && tab_fullscreen_accepted_)); - DCHECK(!(mouse_lock && IsMouseLocked())); - - HostContentSettingsMap* settings_map = profile_->GetHostContentSettingsMap(); - - if (mouse_lock && !IsMouseLocked()) { - DCHECK(IsMouseLockRequested()); - - GURL url = GetFullscreenExitBubbleURL(); - ContentSettingsPattern pattern = ContentSettingsPattern::FromURL(url); - - // TODO(markusheintz): We should allow patterns for all possible URLs here. - if (pattern.IsValid()) { - settings_map->SetContentSetting( - pattern, ContentSettingsPattern::Wildcard(), - CONTENT_SETTINGS_TYPE_MOUSELOCK, std::string(), - CONTENT_SETTING_ALLOW); - } - - if (mouse_lock_tab_ && - mouse_lock_tab_->GotResponseToLockMouseRequest(true)) { - mouse_lock_state_ = MOUSELOCK_ACCEPTED; - } else { - mouse_lock_state_ = MOUSELOCK_NOT_REQUESTED; - SetMouseLockTab(NULL); - } - NotifyMouseLockChange(); - } if (fullscreen && !tab_fullscreen_accepted_) { - DCHECK(fullscreened_tab_); + DCHECK(exclusive_access_tab()); // Origins can enter fullscreen even when embedded in other origins. // Permission is tracked based on the combinations of requester and // embedder. Thus, even if a requesting origin has been previously approved @@ -438,112 +348,39 @@ void FullscreenController::OnAcceptFullscreenPermission() { // ContentSettings requires valid patterns and the patterns might be invalid // in some edge cases like if the current frame is about:blank. if (primary_pattern.IsValid() && secondary_pattern.IsValid()) { + HostContentSettingsMap* settings_map = + profile()->GetHostContentSettingsMap(); settings_map->SetContentSetting( primary_pattern, secondary_pattern, CONTENT_SETTINGS_TYPE_FULLSCREEN, std::string(), CONTENT_SETTING_ALLOW); } tab_fullscreen_accepted_ = true; - } - UpdateFullscreenExitBubbleContent(); -} - -void FullscreenController::OnDenyFullscreenPermission() { - if (!fullscreened_tab_ && !mouse_lock_tab_) - return; - - if (IsMouseLockRequested()) { - mouse_lock_state_ = MOUSELOCK_NOT_REQUESTED; - if (mouse_lock_tab_) - mouse_lock_tab_->GotResponseToLockMouseRequest(false); - SetMouseLockTab(NULL); - NotifyMouseLockChange(); - - // UpdateFullscreenExitBubbleContent() must be called, but to avoid - // duplicate calls we do so only if not adjusting the fullscreen state - // below, which also calls UpdateFullscreenExitBubbleContent(). - if (!IsWindowFullscreenForTabOrPending()) - UpdateFullscreenExitBubbleContent(); + return true; } - if (IsWindowFullscreenForTabOrPending()) - ExitTabFullscreenOrMouseLockIfNecessary(); + return false; } -void FullscreenController::LostMouseLock() { - mouse_lock_state_ = MOUSELOCK_NOT_REQUESTED; - SetMouseLockTab(NULL); - NotifyMouseLockChange(); - UpdateFullscreenExitBubbleContent(); -} +bool FullscreenController::OnDenyExclusiveAccessPermission() { + if (IsWindowFullscreenForTabOrPending()) { + ExitExclusiveAccessIfNecessary(); + return true; + } -void FullscreenController::Observe(int type, - const content::NotificationSource& source, - const content::NotificationDetails& details) { - DCHECK_EQ(content::NOTIFICATION_NAV_ENTRY_COMMITTED, type); - if (content::Details<content::LoadCommittedDetails>(details)-> - is_navigation_to_different_page()) - ExitTabFullscreenOrMouseLockIfNecessary(); + return false; } -GURL FullscreenController::GetFullscreenExitBubbleURL() const { - if (fullscreened_tab_) +GURL FullscreenController::GetURLForExclusiveAccessBubble() const { + if (exclusive_access_tab()) return GetRequestingOrigin(); - if (mouse_lock_tab_) - return mouse_lock_tab_->GetURL(); return extension_caused_fullscreen_; } -ExclusiveAccessBubbleType FullscreenController::GetExclusiveAccessBubbleType() - const { - // In kiosk and exclusive app mode we always want to be fullscreen and do not - // want to show exit instructions for browser mode fullscreen. - bool app_mode = false; -#if !defined(OS_MACOSX) // App mode (kiosk) is not available on Mac yet. - app_mode = chrome::IsRunningInAppMode(); -#endif - - if (mouse_lock_state_ == MOUSELOCK_ACCEPTED_SILENTLY) - return EXCLUSIVE_ACCESS_BUBBLE_TYPE_NONE; - - if (!fullscreened_tab_) { - if (IsMouseLocked()) - return EXCLUSIVE_ACCESS_BUBBLE_TYPE_MOUSELOCK_EXIT_INSTRUCTION; - if (IsMouseLockRequested()) - return EXCLUSIVE_ACCESS_BUBBLE_TYPE_MOUSELOCK_BUTTONS; - if (!extension_caused_fullscreen_.is_empty()) - return EXCLUSIVE_ACCESS_BUBBLE_TYPE_EXTENSION_FULLSCREEN_EXIT_INSTRUCTION; - if (toggled_into_fullscreen_ && !app_mode) - return EXCLUSIVE_ACCESS_BUBBLE_TYPE_BROWSER_FULLSCREEN_EXIT_INSTRUCTION; - return EXCLUSIVE_ACCESS_BUBBLE_TYPE_NONE; - } - - if (tab_fullscreen_accepted_) { - if (IsPrivilegedFullscreenForTab()) - return EXCLUSIVE_ACCESS_BUBBLE_TYPE_NONE; - if (IsMouseLocked()) - return EXCLUSIVE_ACCESS_BUBBLE_TYPE_FULLSCREEN_MOUSELOCK_EXIT_INSTRUCTION; - if (IsMouseLockRequested()) - return EXCLUSIVE_ACCESS_BUBBLE_TYPE_MOUSELOCK_BUTTONS; - return EXCLUSIVE_ACCESS_BUBBLE_TYPE_FULLSCREEN_EXIT_INSTRUCTION; - } - - if (IsMouseLockRequested()) - return EXCLUSIVE_ACCESS_BUBBLE_TYPE_FULLSCREEN_MOUSELOCK_BUTTONS; - return EXCLUSIVE_ACCESS_BUBBLE_TYPE_FULLSCREEN_BUTTONS; -} - -void FullscreenController::UpdateNotificationRegistrations() { - if (fullscreened_tab_ && mouse_lock_tab_) - DCHECK(fullscreened_tab_ == mouse_lock_tab_); - - WebContents* tab = fullscreened_tab_ ? fullscreened_tab_ : mouse_lock_tab_; - - if (tab && registrar_.IsEmpty()) { - registrar_.Add(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, - content::Source<content::NavigationController>(&tab->GetController())); - } else if (!tab && !registrar_.IsEmpty()) { - registrar_.RemoveAll(); - } +void FullscreenController::ExitExclusiveAccessIfNecessary() { + if (IsWindowFullscreenForTabOrPending()) + ExitFullscreenModeForTab(exclusive_access_tab()); + else + NotifyTabExclusiveAccessLost(); } void FullscreenController::PostFullscreenChangeNotification( @@ -562,35 +399,16 @@ void FullscreenController::NotifyFullscreenChange(bool is_fullscreen) { content::Details<bool>(&is_fullscreen)); } -void FullscreenController::NotifyTabOfExitIfNecessary() { - if (fullscreened_tab_) { - WebContents* web_contents = fullscreened_tab_; - // This call will set |fullscreened_tab_| to nullptr. - SetFullscreenedTab(nullptr, GURL()); +void FullscreenController::NotifyTabExclusiveAccessLost() { + if (exclusive_access_tab()) { + WebContents* web_contents = exclusive_access_tab(); + SetTabWithExclusiveAccess(nullptr); + fullscreened_origin_ = GURL(); state_prior_to_tab_fullscreen_ = STATE_INVALID; tab_fullscreen_accepted_ = false; web_contents->ExitFullscreen(); + exclusive_access_manager()->UpdateExclusiveAccessExitBubbleContent(); } - - if (mouse_lock_tab_) { - if (IsMouseLockRequested()) { - mouse_lock_tab_->GotResponseToLockMouseRequest(false); - NotifyMouseLockChange(); - } else { - UnlockMouse(); - } - SetMouseLockTab(NULL); - mouse_lock_state_ = MOUSELOCK_NOT_REQUESTED; - } - - UpdateFullscreenExitBubbleContent(); -} - -void FullscreenController::NotifyMouseLockChange() { - content::NotificationService::current()->Notify( - chrome::NOTIFICATION_MOUSE_LOCK_CHANGED, - content::Source<FullscreenController>(this), - content::NotificationService::NoDetails()); } void FullscreenController::ToggleFullscreenModeInternal( @@ -601,24 +419,23 @@ void FullscreenController::ToggleFullscreenModeInternal( return; #endif - bool enter_fullscreen = !window_->IsFullscreen(); + BrowserWindow* const window = browser()->window(); + bool enter_fullscreen = !window->IsFullscreen(); // When a Mac user requests a toggle they may be toggling between // FullscreenWithoutChrome and FullscreenWithToolbar. - if (window_->IsFullscreen() && - !IsWindowFullscreenForTabOrPending() && - window_->SupportsFullscreenWithToolbar()) { + if (window->IsFullscreen() && !IsWindowFullscreenForTabOrPending() && + window->SupportsFullscreenWithToolbar()) { if (option == BROWSER_WITH_TOOLBAR) { - enter_fullscreen = - enter_fullscreen || !window_->IsFullscreenWithToolbar(); + enter_fullscreen = enter_fullscreen || !window->IsFullscreenWithToolbar(); } else { - enter_fullscreen = enter_fullscreen || window_->IsFullscreenWithToolbar(); + enter_fullscreen = enter_fullscreen || window->IsFullscreenWithToolbar(); } } // In kiosk mode, we always want to be fullscreen. When the browser first // starts we're not yet fullscreen, so let the initial toggle go through. - if (chrome::IsRunningInAppMode() && window_->IsFullscreen()) + if (chrome::IsRunningInAppMode() && window->IsFullscreen()) return; #if !defined(OS_MACOSX) @@ -626,7 +443,7 @@ void FullscreenController::ToggleFullscreenModeInternal( // from manually entering fullscreen mode and also disables kiosk mode on // desktop platforms. if (enter_fullscreen && - !profile_->GetPrefs()->GetBoolean(prefs::kFullscreenAllowed)) { + !profile()->GetPrefs()->GetBoolean(prefs::kFullscreenAllowed)) { return; } #endif @@ -654,10 +471,11 @@ void FullscreenController::EnterFullscreenModeInternal( // TODO(scheib): Record metrics for WITH_TOOLBAR, without counting transitions // from tab fullscreen out to browser with toolbar. - window_->EnterFullscreen(url, GetExclusiveAccessBubbleType(), - option == BROWSER_WITH_TOOLBAR); + browser()->window()->EnterFullscreen( + url, exclusive_access_manager()->GetExclusiveAccessExitBubbleType(), + option == BROWSER_WITH_TOOLBAR); - UpdateFullscreenExitBubbleContent(); + exclusive_access_manager()->UpdateExclusiveAccessExitBubbleContent(); // Once the window has become fullscreen it'll call back to // WindowFullscreenStateChanged(). We don't do this immediately as @@ -671,47 +489,16 @@ void FullscreenController::ExitFullscreenModeInternal() { // Mac windows report a state change instantly, and so we must also clear // state_prior_to_tab_fullscreen_ to match them else other logic using // state_prior_to_tab_fullscreen_ will be incorrect. - NotifyTabOfExitIfNecessary(); + NotifyTabExclusiveAccessLost(); #endif - window_->ExitFullscreen(); + browser()->window()->ExitFullscreen(); extension_caused_fullscreen_ = GURL(); - UpdateFullscreenExitBubbleContent(); -} - -void FullscreenController::SetFullscreenedTab(WebContents* tab, - const GURL& origin) { - fullscreened_tab_ = tab; - fullscreened_origin_ = origin; - UpdateNotificationRegistrations(); -} - -void FullscreenController::SetMouseLockTab(WebContents* tab) { - mouse_lock_tab_ = tab; - UpdateNotificationRegistrations(); -} - -void FullscreenController::ExitTabFullscreenOrMouseLockIfNecessary() { - if (IsWindowFullscreenForTabOrPending()) - ExitFullscreenModeForTab(fullscreened_tab_); - else - NotifyTabOfExitIfNecessary(); -} - -void FullscreenController::UpdateFullscreenExitBubbleContent() { - GURL url = GetFullscreenExitBubbleURL(); - ExclusiveAccessBubbleType bubble_type = GetExclusiveAccessBubbleType(); - - // If bubble displays buttons, unlock mouse to allow pressing them. - if (exclusive_access_bubble::ShowButtonsForType(bubble_type) && - IsMouseLocked()) - UnlockMouse(); - - window_->UpdateFullscreenExitBubbleContent(url, bubble_type); + exclusive_access_manager()->UpdateExclusiveAccessExitBubbleContent(); } ContentSetting FullscreenController::GetFullscreenSetting() const { - DCHECK(fullscreened_tab_); + DCHECK(exclusive_access_tab()); GURL url = GetRequestingOrigin(); @@ -720,7 +507,7 @@ ContentSetting FullscreenController::GetFullscreenSetting() const { // If the permission was granted to the website with no embedder, it should // always be allowed, even if embedded. - if (profile_->GetHostContentSettingsMap()->GetContentSetting( + if (profile()->GetHostContentSettingsMap()->GetContentSetting( url, url, CONTENT_SETTINGS_TYPE_FULLSCREEN, std::string()) == CONTENT_SETTING_ALLOW) { return CONTENT_SETTING_ALLOW; @@ -728,25 +515,15 @@ ContentSetting FullscreenController::GetFullscreenSetting() const { // See the comment above the call to |SetContentSetting()| for how the // requesting and embedding origins interact with each other wrt permissions. - return profile_->GetHostContentSettingsMap()->GetContentSetting( + return profile()->GetHostContentSettingsMap()->GetContentSetting( url, GetEmbeddingOrigin(), CONTENT_SETTINGS_TYPE_FULLSCREEN, std::string()); } -ContentSetting -FullscreenController::GetMouseLockSetting(const GURL& url) const { - if (IsPrivilegedFullscreenForTab() || url.SchemeIsFile()) - return CONTENT_SETTING_ALLOW; - - HostContentSettingsMap* settings_map = profile_->GetHostContentSettingsMap(); - return settings_map->GetContentSetting(url, url, - CONTENT_SETTINGS_TYPE_MOUSELOCK, std::string()); -} - bool FullscreenController::IsPrivilegedFullscreenForTab() const { const bool embedded_widget_present = - fullscreened_tab_ && - fullscreened_tab_->GetFullscreenRenderWidgetHostView(); + exclusive_access_tab() && + exclusive_access_tab()->GetFullscreenRenderWidgetHostView(); return embedded_widget_present || is_privileged_fullscreen_for_testing_; } @@ -776,43 +553,30 @@ bool FullscreenController::MaybeToggleFullscreenForCapturedTab( bool FullscreenController::IsFullscreenForCapturedTab( const WebContents* web_contents) const { - // Note: On Mac, some of the OnTabXXX() methods get called with a NULL value + // Note: On Mac, some of the OnTabXXX() methods get called with a nullptr + // value // for web_contents. Check for that here. - const FullscreenWithinTabHelper* const helper = web_contents ? - FullscreenWithinTabHelper::FromWebContents(web_contents) : NULL; + const FullscreenWithinTabHelper* const helper = + web_contents ? FullscreenWithinTabHelper::FromWebContents(web_contents) + : nullptr; if (helper && helper->is_fullscreen_for_captured_tab()) { - DCHECK_NE(fullscreened_tab_, web_contents); + DCHECK_NE(exclusive_access_tab(), web_contents); return true; } return false; } -void FullscreenController::UnlockMouse() { - if (!mouse_lock_tab_) - return; - content::RenderWidgetHostView* mouse_lock_view = - (fullscreened_tab_ == mouse_lock_tab_ && IsPrivilegedFullscreenForTab()) ? - mouse_lock_tab_->GetFullscreenRenderWidgetHostView() : NULL; - if (!mouse_lock_view) { - RenderViewHost* const rvh = mouse_lock_tab_->GetRenderViewHost(); - if (rvh) - mouse_lock_view = rvh->GetView(); - } - if (mouse_lock_view) - mouse_lock_view->UnlockMouse(); -} - GURL FullscreenController::GetRequestingOrigin() const { - DCHECK(fullscreened_tab_); + DCHECK(exclusive_access_tab()); if (!fullscreened_origin_.is_empty()) return fullscreened_origin_; - return fullscreened_tab_->GetLastCommittedURL(); + return exclusive_access_tab()->GetLastCommittedURL(); } GURL FullscreenController::GetEmbeddingOrigin() const { - DCHECK(fullscreened_tab_); + DCHECK(exclusive_access_tab()); - return fullscreened_tab_->GetLastCommittedURL(); + return exclusive_access_tab()->GetLastCommittedURL(); } diff --git a/chrome/browser/ui/exclusive_access/fullscreen_controller.h b/chrome/browser/ui/exclusive_access/fullscreen_controller.h index d276678..763591f 100644 --- a/chrome/browser/ui/exclusive_access/fullscreen_controller.h +++ b/chrome/browser/ui/exclusive_access/fullscreen_controller.h @@ -9,15 +9,12 @@ #include "base/basictypes.h" #include "base/memory/weak_ptr.h" -#include "chrome/browser/ui/exclusive_access/exclusive_access_bubble_type.h" +#include "chrome/browser/ui/exclusive_access/exclusive_access_controller_base.h" #include "components/content_settings/core/common/content_settings.h" #include "content/public/browser/notification_observer.h" #include "content/public/browser/notification_registrar.h" -class Browser; -class BrowserWindow; class GURL; -class Profile; namespace content { class WebContents; @@ -34,8 +31,7 @@ class WebContents; // tab so it can stop rendering in its fullscreen mode. // // For Flash, FullscreenController will auto-accept all permission requests for -// fullscreen and/or mouse lock, since the assumption is that the plugin handles -// this for us. +// fullscreen, since the assumption is that the plugin handles this for us. // // FullscreenWithinTab Note: // All fullscreen widgets are displayed within the tab contents area, and @@ -50,10 +46,10 @@ class WebContents; // quality improvement since scaling and letterboxing steps can be skipped in // the capture pipeline. -// This class implements fullscreen and mouselock behaviour. -class FullscreenController : public content::NotificationObserver { +// This class implements fullscreen behaviour. +class FullscreenController : public ExclusiveAccessControllerBase { public: - explicit FullscreenController(Browser* browser); + FullscreenController(ExclusiveAccessManager* manager, Browser* browser); ~FullscreenController() override; // Browser/User Fullscreen /////////////////////////////////////////////////// @@ -63,6 +59,9 @@ class FullscreenController : public content::NotificationObserver { // transition. bool IsFullscreenForBrowser() const; + // Returns true if Flash is providing the "exit from fullscreen" message. + bool IsPrivilegedFullscreenForTab() const; + void ToggleBrowserFullscreenMode(); // Fullscreen mode with tab strip and toolbar shown. @@ -81,6 +80,16 @@ class FullscreenController : public content::NotificationObserver { // BrowserWindow::IsFullscreen() may still return false. bool IsWindowFullscreenForTabOrPending() const; + // Returns true if the browser window is fullscreen because of extension + // initiated fullscreen. + bool IsExtensionFullscreenOrPending() const; + + // Returns true if controller has entered fullscreen mode. + bool IsControllerInitiatedFullscreen() const; + + // Returns true if the user has accepted fullscreen. + bool IsUserAcceptedFullscreen() const; + // Returns true if the tab is/will be in fullscreen mode. Note: This does NOT // indicate whether the browser window is/will be fullscreened as well. See // 'FullscreenWithinTab Note'. @@ -116,95 +125,46 @@ class FullscreenController : public content::NotificationObserver { void SetMetroSnapMode(bool enable); #endif - // Mouse Lock //////////////////////////////////////////////////////////////// - - bool IsMouseLockRequested() const; - bool IsMouseLocked() const; - - void RequestToLockMouse(content::WebContents* web_contents, - bool user_gesture, - bool last_unlocked_by_target); + // Overrde from ExclusiveAccessControllerBase. + void OnTabDetachedFromView(content::WebContents* web_contents) override; + void OnTabClosing(content::WebContents* web_contents) override; + bool HandleUserPressedEscape() override; + void ExitExclusiveAccessToPreviousState() override; + bool OnAcceptExclusiveAccessPermission() override; + bool OnDenyExclusiveAccessPermission() override; + GURL GetURLForExclusiveAccessBubble() const override; + void ExitExclusiveAccessIfNecessary() override; // Callbacks ///////////////////////////////////////////////////////////////// - // Called by Browser::TabDeactivated. - void OnTabDeactivated(content::WebContents* web_contents); - - // Called by Browser::ActiveTabChanged. - void OnTabDetachedFromView(content::WebContents* web_contents); - - // Called by Browser::TabClosingAt. - void OnTabClosing(content::WebContents* web_contents); - // Called by Browser::WindowFullscreenStateChanged. void WindowFullscreenStateChanged(); - // Called by Browser::PreHandleKeyboardEvent. - bool HandleUserPressedEscape(); - - // Called by platform FullscreenExitBubble. - void ExitTabOrBrowserFullscreenToPreviousState(); - void OnAcceptFullscreenPermission(); - void OnDenyFullscreenPermission(); - - // Called by Browser::LostMouseLock. - void LostMouseLock(); - - // content::NotificationObserver: - void Observe(int type, - const content::NotificationSource& source, - const content::NotificationDetails& details) override; - - // Bubble Content //////////////////////////////////////////////////////////// - - GURL GetFullscreenExitBubbleURL() const; - ExclusiveAccessBubbleType GetExclusiveAccessBubbleType() const; - private: friend class FullscreenControllerTest; - enum MouseLockState { - MOUSELOCK_NOT_REQUESTED, - // The page requests to lock the mouse and the user hasn't responded to the - // request. - MOUSELOCK_REQUESTED, - // Mouse lock has been allowed by the user. - MOUSELOCK_ACCEPTED, - // Mouse lock has been silently accepted, no notification to user. - MOUSELOCK_ACCEPTED_SILENTLY - }; - enum FullscreenInternalOption { BROWSER, BROWSER_WITH_TOOLBAR, TAB }; - void UpdateNotificationRegistrations(); - // Posts a task to call NotifyFullscreenChange. void PostFullscreenChangeNotification(bool is_fullscreen); // Sends a NOTIFICATION_FULLSCREEN_CHANGED notification. void NotifyFullscreenChange(bool is_fullscreen); - // Notifies the tab that it has been forced out of fullscreen and mouse lock - // mode if necessary. - void NotifyTabOfExitIfNecessary(); - void NotifyMouseLockChange(); + + // Notifies the tab that it has been forced out of fullscreen mode if + // necessary. + void NotifyTabExclusiveAccessLost() override; void ToggleFullscreenModeInternal(FullscreenInternalOption option); void EnterFullscreenModeInternal(FullscreenInternalOption option); void ExitFullscreenModeInternal(); void SetFullscreenedTab(content::WebContents* tab, const GURL& origin); - void SetMouseLockTab(content::WebContents* tab); - - // Make the current tab exit fullscreen mode or mouse lock if it is in it. - void ExitTabFullscreenOrMouseLockIfNecessary(); - void UpdateFullscreenExitBubbleContent(); ContentSetting GetFullscreenSetting() const; - ContentSetting GetMouseLockSetting(const GURL& url) const; - bool IsPrivilegedFullscreenForTab() const; void SetPrivilegedFullscreenForTesting(bool is_privileged); // Returns true if |web_contents| was toggled into/out of fullscreen mode as a // screen-captured tab. See 'FullscreenWithinTab Note'. @@ -214,21 +174,11 @@ class FullscreenController : public content::NotificationObserver { // tab. See 'FullscreenWithinTab Note'. bool IsFullscreenForCapturedTab(const content::WebContents* web_contents) const; - void UnlockMouse(); // Helper methods that should be used in a TAB context. GURL GetRequestingOrigin() const; GURL GetEmbeddingOrigin() const; - Browser* const browser_; - BrowserWindow* const window_; - Profile* const profile_; - - // If there is currently a tab in fullscreen mode (entered via - // webkitRequestFullScreen), this is its WebContents. - // Assign using SetFullscreenedTab(). - content::WebContents* fullscreened_tab_; - // If a tab is fullscreen, the |fullscreen_origin_| should be used as the // origin with regards to fullscreen. The |fullscreened_tab_| url should be // used as the embedder url. @@ -253,14 +203,6 @@ class FullscreenController : public content::NotificationObserver { // True if this controller has toggled into tab OR browser fullscreen. bool toggled_into_fullscreen_; - // WebContents for current tab requesting or currently in mouse lock. - // Assign using SetMouseLockTab(). - content::WebContents* mouse_lock_tab_; - - MouseLockState mouse_lock_state_; - - content::NotificationRegistrar registrar_; - // Used to verify that calls we expect to reenter by calling // WindowFullscreenStateChanged do so. bool reentrant_window_state_change_call_check_; diff --git a/chrome/browser/ui/exclusive_access/fullscreen_controller_state_test.cc b/chrome/browser/ui/exclusive_access/fullscreen_controller_state_test.cc index 189b654..0a6fbc5 100644 --- a/chrome/browser/ui/exclusive_access/fullscreen_controller_state_test.cc +++ b/chrome/browser/ui/exclusive_access/fullscreen_controller_state_test.cc @@ -415,15 +415,19 @@ bool FullscreenControllerStateTest::InvokeEvent(Event event) { break; case BUBBLE_EXIT_LINK: - GetFullscreenController()->ExitTabOrBrowserFullscreenToPreviousState(); + GetFullscreenController()->ExitExclusiveAccessToPreviousState(); break; case BUBBLE_ALLOW: - GetFullscreenController()->OnAcceptFullscreenPermission(); + GetBrowser() + ->exclusive_access_manager() + ->OnAcceptExclusiveAccessPermission(); break; case BUBBLE_DENY: - GetFullscreenController()->OnDenyFullscreenPermission(); + GetBrowser() + ->exclusive_access_manager() + ->OnDenyExclusiveAccessPermission(); break; case WINDOW_CHANGE: @@ -756,7 +760,7 @@ void FullscreenControllerStateTest::VerifyWindowStateExpectations( } FullscreenController* FullscreenControllerStateTest::GetFullscreenController() { - return GetBrowser()->fullscreen_controller(); + return GetBrowser()->exclusive_access_manager()->fullscreen_controller(); } std::string FullscreenControllerStateTest::GetTransitionTableAsString() const { diff --git a/chrome/browser/ui/exclusive_access/fullscreen_controller_state_unittest.cc b/chrome/browser/ui/exclusive_access/fullscreen_controller_state_unittest.cc index 541a8b5..31ef252 100644 --- a/chrome/browser/ui/exclusive_access/fullscreen_controller_state_unittest.cc +++ b/chrome/browser/ui/exclusive_access/fullscreen_controller_state_unittest.cc @@ -428,7 +428,9 @@ TEST_F(FullscreenControllerStateUnitTest, ExitFullscreenViaBrowserWindow) { browser()->window()->ExitFullscreen(); ChangeWindowFullscreenState(); EXPECT_EQ(EXCLUSIVE_ACCESS_BUBBLE_TYPE_NONE, - browser()->fullscreen_controller()->GetExclusiveAccessBubbleType()); + browser() + ->exclusive_access_manager() + ->GetExclusiveAccessExitBubbleType()); } // Test that switching tabs takes the browser out of tab fullscreen. @@ -763,8 +765,9 @@ TEST_F(FullscreenControllerStateUnitTest, EXPECT_TRUE(wc_delegate->IsFullscreenForTabOrPending(tab)); EXPECT_TRUE(second_wc_delegate->IsFullscreenForTabOrPending(tab)); EXPECT_FALSE(GetFullscreenController()->IsWindowFullscreenForTabOrPending()); - EXPECT_FALSE(second_browser->fullscreen_controller()-> - IsWindowFullscreenForTabOrPending()); + EXPECT_FALSE(second_browser->exclusive_access_manager() + ->fullscreen_controller() + ->IsWindowFullscreenForTabOrPending()); // Now, detach and reattach it back to the first browser window. Again, the // tab should remain in fullscreen mode and neither browser window should have @@ -777,8 +780,9 @@ TEST_F(FullscreenControllerStateUnitTest, EXPECT_TRUE(wc_delegate->IsFullscreenForTabOrPending(tab)); EXPECT_TRUE(second_wc_delegate->IsFullscreenForTabOrPending(tab)); EXPECT_FALSE(GetFullscreenController()->IsWindowFullscreenForTabOrPending()); - EXPECT_FALSE(second_browser->fullscreen_controller()-> - IsWindowFullscreenForTabOrPending()); + EXPECT_FALSE(second_browser->exclusive_access_manager() + ->fullscreen_controller() + ->IsWindowFullscreenForTabOrPending()); // Exit fullscreen. ASSERT_TRUE(InvokeEvent(TAB_FULLSCREEN_FALSE)); @@ -786,8 +790,9 @@ TEST_F(FullscreenControllerStateUnitTest, EXPECT_FALSE(wc_delegate->IsFullscreenForTabOrPending(tab)); EXPECT_FALSE(second_wc_delegate->IsFullscreenForTabOrPending(tab)); EXPECT_FALSE(GetFullscreenController()->IsWindowFullscreenForTabOrPending()); - EXPECT_FALSE(second_browser->fullscreen_controller()-> - IsWindowFullscreenForTabOrPending()); + EXPECT_FALSE(second_browser->exclusive_access_manager() + ->fullscreen_controller() + ->IsWindowFullscreenForTabOrPending()); // Required tear-down specific to this test. second_browser->tab_strip_model()->CloseAllTabs(); diff --git a/chrome/browser/ui/exclusive_access/fullscreen_controller_test.cc b/chrome/browser/ui/exclusive_access/fullscreen_controller_test.cc index bf1925f..335892b 100644 --- a/chrome/browser/ui/exclusive_access/fullscreen_controller_test.cc +++ b/chrome/browser/ui/exclusive_access/fullscreen_controller_test.cc @@ -27,34 +27,39 @@ void FullscreenControllerTest::RequestToLockMouse( last_unlocked_by_target); } +FullscreenController* FullscreenControllerTest::GetFullscreenController() { + return GetExclusiveAccessManager()->fullscreen_controller(); +} + +ExclusiveAccessManager* FullscreenControllerTest::GetExclusiveAccessManager() { + return browser()->exclusive_access_manager(); +} + void FullscreenControllerTest::LostMouseLock() { browser()->LostMouseLock(); } bool FullscreenControllerTest::SendEscapeToFullscreenController() { - return browser()->fullscreen_controller()->HandleUserPressedEscape(); + return GetExclusiveAccessManager()->HandleUserPressedEscape(); } bool FullscreenControllerTest::IsFullscreenForBrowser() { - return browser()->fullscreen_controller()->IsFullscreenForBrowser(); + return GetFullscreenController()->IsFullscreenForBrowser(); } bool FullscreenControllerTest::IsWindowFullscreenForTabOrPending() { - return browser()->fullscreen_controller()-> - IsWindowFullscreenForTabOrPending(); + return GetFullscreenController()->IsWindowFullscreenForTabOrPending(); } bool FullscreenControllerTest::IsMouseLockPermissionRequested() { - ExclusiveAccessBubbleType type = - browser()->fullscreen_controller()->GetExclusiveAccessBubbleType(); + ExclusiveAccessBubbleType type = GetExclusiveAccessBubbleType(); bool mouse_lock = false; exclusive_access_bubble::PermissionRequestedByType(type, NULL, &mouse_lock); return mouse_lock; } bool FullscreenControllerTest::IsFullscreenPermissionRequested() { - ExclusiveAccessBubbleType type = - browser()->fullscreen_controller()->GetExclusiveAccessBubbleType(); + ExclusiveAccessBubbleType type = GetExclusiveAccessBubbleType(); bool fullscreen = false; exclusive_access_bubble::PermissionRequestedByType(type, &fullscreen, NULL); return fullscreen; @@ -62,27 +67,24 @@ bool FullscreenControllerTest::IsFullscreenPermissionRequested() { ExclusiveAccessBubbleType FullscreenControllerTest::GetExclusiveAccessBubbleType() { - return browser()->fullscreen_controller()->GetExclusiveAccessBubbleType(); + return GetExclusiveAccessManager()->GetExclusiveAccessExitBubbleType(); } bool FullscreenControllerTest::IsFullscreenBubbleDisplayed() { - ExclusiveAccessBubbleType type = - browser()->fullscreen_controller()->GetExclusiveAccessBubbleType(); - return type != EXCLUSIVE_ACCESS_BUBBLE_TYPE_NONE; + return GetExclusiveAccessBubbleType() != EXCLUSIVE_ACCESS_BUBBLE_TYPE_NONE; } bool FullscreenControllerTest::IsFullscreenBubbleDisplayingButtons() { - ExclusiveAccessBubbleType type = - browser()->fullscreen_controller()->GetExclusiveAccessBubbleType(); - return exclusive_access_bubble::ShowButtonsForType(type); + return exclusive_access_bubble::ShowButtonsForType( + GetExclusiveAccessBubbleType()); } void FullscreenControllerTest::AcceptCurrentFullscreenOrMouseLockRequest() { - browser()->fullscreen_controller()->OnAcceptFullscreenPermission(); + GetExclusiveAccessManager()->OnAcceptExclusiveAccessPermission(); } void FullscreenControllerTest::DenyCurrentFullscreenOrMouseLockRequest() { - browser()->fullscreen_controller()->OnDenyFullscreenPermission(); + GetExclusiveAccessManager()->OnDenyExclusiveAccessPermission(); } void FullscreenControllerTest::GoBack() { @@ -100,6 +102,5 @@ void FullscreenControllerTest::Reload() { } void FullscreenControllerTest::SetPrivilegedFullscreen(bool is_privileged) { - browser()->fullscreen_controller()-> - SetPrivilegedFullscreenForTesting(is_privileged); + GetFullscreenController()->SetPrivilegedFullscreenForTesting(is_privileged); } diff --git a/chrome/browser/ui/exclusive_access/fullscreen_controller_test.h b/chrome/browser/ui/exclusive_access/fullscreen_controller_test.h index 59928b2..039a016 100644 --- a/chrome/browser/ui/exclusive_access/fullscreen_controller_test.h +++ b/chrome/browser/ui/exclusive_access/fullscreen_controller_test.h @@ -7,6 +7,7 @@ #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/ui/exclusive_access/exclusive_access_bubble_type.h" +#include "chrome/browser/ui/exclusive_access/fullscreen_controller.h" #include "chrome/test/base/in_process_browser_test.h" #include "content/public/browser/notification_service.h" #include "content/public/test/test_utils.h" @@ -55,6 +56,9 @@ class FullscreenControllerTest : public InProcessBrowserTest { void Reload(); void SetPrivilegedFullscreen(bool is_privileged); static const char kFullscreenMouseLockHTML[]; + FullscreenController* GetFullscreenController(); + ExclusiveAccessManager* GetExclusiveAccessManager(); + private: void ToggleTabFullscreen_Internal(bool enter_fullscreen, bool retry_until_success); diff --git a/chrome/browser/ui/exclusive_access/mouse_lock_controller.cc b/chrome/browser/ui/exclusive_access/mouse_lock_controller.cc new file mode 100644 index 0000000..a053b85 --- /dev/null +++ b/chrome/browser/ui/exclusive_access/mouse_lock_controller.cc @@ -0,0 +1,234 @@ +// Copyright (c) 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/exclusive_access/mouse_lock_controller.h" + +#include "chrome/browser/chrome_notification_types.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/exclusive_access/fullscreen_controller.h" +#include "components/content_settings/core/browser/host_content_settings_map.h" +#include "content/public/browser/notification_service.h" +#include "content/public/browser/render_view_host.h" +#include "content/public/browser/render_widget_host_view.h" +#include "content/public/browser/web_contents.h" + +using content::RenderViewHost; +using content::WebContents; + +MouseLockController::MouseLockController(ExclusiveAccessManager* manager, + Browser* browser) + : ExclusiveAccessControllerBase(manager, browser), + mouse_lock_state_(MOUSELOCK_NOT_REQUESTED) { +} + +MouseLockController::~MouseLockController() { +} + +bool MouseLockController::IsMouseLocked() const { + return mouse_lock_state_ == MOUSELOCK_ACCEPTED || + mouse_lock_state_ == MOUSELOCK_ACCEPTED_SILENTLY; +} + +bool MouseLockController::IsMouseLockSilentlyAccepted() const { + return mouse_lock_state_ == MOUSELOCK_ACCEPTED_SILENTLY; +} + +void MouseLockController::RequestToLockMouse(WebContents* web_contents, + bool user_gesture, + bool last_unlocked_by_target) { + DCHECK(!IsMouseLocked()); + NotifyMouseLockChange(); + + // Must have a user gesture to prevent misbehaving sites from constantly + // re-locking the mouse. Exceptions are when the page has unlocked + // (i.e. not the user), or if we're in tab fullscreen (user gesture required + // for that) + if (!last_unlocked_by_target && !user_gesture && + !exclusive_access_manager() + ->fullscreen_controller() + ->IsFullscreenForTabOrPending(web_contents)) { + web_contents->GotResponseToLockMouseRequest(false); + return; + } + SetTabWithExclusiveAccess(web_contents); + ExclusiveAccessBubbleType bubble_type = + exclusive_access_manager()->GetExclusiveAccessExitBubbleType(); + + switch (GetMouseLockSetting(web_contents->GetURL())) { + case CONTENT_SETTING_ALLOW: + // If bubble already displaying buttons we must not lock the mouse yet, + // or it would prevent pressing those buttons. Instead, merge the request. + if (!exclusive_access_manager() + ->fullscreen_controller() + ->IsPrivilegedFullscreenForTab() && + exclusive_access_bubble::ShowButtonsForType(bubble_type)) { + mouse_lock_state_ = MOUSELOCK_REQUESTED; + } else { + // Lock mouse. + if (web_contents->GotResponseToLockMouseRequest(true)) { + if (last_unlocked_by_target) { + mouse_lock_state_ = MOUSELOCK_ACCEPTED_SILENTLY; + } else { + mouse_lock_state_ = MOUSELOCK_ACCEPTED; + } + } else { + SetTabWithExclusiveAccess(nullptr); + mouse_lock_state_ = MOUSELOCK_NOT_REQUESTED; + } + } + break; + case CONTENT_SETTING_BLOCK: + web_contents->GotResponseToLockMouseRequest(false); + SetTabWithExclusiveAccess(nullptr); + mouse_lock_state_ = MOUSELOCK_NOT_REQUESTED; + break; + case CONTENT_SETTING_ASK: + mouse_lock_state_ = MOUSELOCK_REQUESTED; + break; + default: + NOTREACHED(); + } + exclusive_access_manager()->UpdateExclusiveAccessExitBubbleContent(); +} + +void MouseLockController::ExitExclusiveAccessIfNecessary() { + NotifyTabExclusiveAccessLost(); +} + +void MouseLockController::NotifyTabExclusiveAccessLost() { + WebContents* tab = exclusive_access_tab(); + if (tab) { + if (IsMouseLockRequested()) { + tab->GotResponseToLockMouseRequest(false); + NotifyMouseLockChange(); + } else { + UnlockMouse(); + } + SetTabWithExclusiveAccess(nullptr); + mouse_lock_state_ = MOUSELOCK_NOT_REQUESTED; + exclusive_access_manager()->UpdateExclusiveAccessExitBubbleContent(); + } +} + +bool MouseLockController::HandleUserPressedEscape() { + if (IsMouseLocked() || IsMouseLockRequested()) { + ExitExclusiveAccessIfNecessary(); + return true; + } + + return false; +} + +void MouseLockController::ExitExclusiveAccessToPreviousState() { + // Nothing to do for mouse lock. +} + +bool MouseLockController::OnAcceptExclusiveAccessPermission() { + ExclusiveAccessBubbleType bubble_type = + exclusive_access_manager()->GetExclusiveAccessExitBubbleType(); + bool mouse_lock = false; + exclusive_access_bubble::PermissionRequestedByType(bubble_type, nullptr, + &mouse_lock); + DCHECK(!(mouse_lock && IsMouseLocked())); + + if (mouse_lock && !IsMouseLocked()) { + DCHECK(IsMouseLockRequested()); + + HostContentSettingsMap* settings_map = + profile()->GetHostContentSettingsMap(); + + GURL url = GetExclusiveAccessBubbleURL(); + ContentSettingsPattern pattern = ContentSettingsPattern::FromURL(url); + + // TODO(markusheintz): We should allow patterns for all possible URLs here. + if (pattern.IsValid()) { + settings_map->SetContentSetting(pattern, + ContentSettingsPattern::Wildcard(), + CONTENT_SETTINGS_TYPE_MOUSELOCK, + std::string(), CONTENT_SETTING_ALLOW); + } + + WebContents* tab = exclusive_access_tab(); + if (tab && tab->GotResponseToLockMouseRequest(true)) { + mouse_lock_state_ = MOUSELOCK_ACCEPTED; + } else { + mouse_lock_state_ = MOUSELOCK_NOT_REQUESTED; + SetTabWithExclusiveAccess(nullptr); + } + NotifyMouseLockChange(); + return true; + } + + return false; +} + +bool MouseLockController::OnDenyExclusiveAccessPermission() { + WebContents* tab = exclusive_access_tab(); + + if (tab && IsMouseLockRequested()) { + mouse_lock_state_ = MOUSELOCK_NOT_REQUESTED; + tab->GotResponseToLockMouseRequest(false); + SetTabWithExclusiveAccess(nullptr); + NotifyMouseLockChange(); + return true; + } + + return false; +} + +void MouseLockController::LostMouseLock() { + mouse_lock_state_ = MOUSELOCK_NOT_REQUESTED; + SetTabWithExclusiveAccess(nullptr); + NotifyMouseLockChange(); + exclusive_access_manager()->UpdateExclusiveAccessExitBubbleContent(); +} + +bool MouseLockController::IsMouseLockRequested() const { + return mouse_lock_state_ == MOUSELOCK_REQUESTED; +} + +void MouseLockController::NotifyMouseLockChange() { + content::NotificationService::current()->Notify( + chrome::NOTIFICATION_MOUSE_LOCK_CHANGED, + content::Source<MouseLockController>(this), + content::NotificationService::NoDetails()); +} + +void MouseLockController::UnlockMouse() { + WebContents* tab = exclusive_access_tab(); + + if (!tab) + return; + + content::RenderWidgetHostView* mouse_lock_view = nullptr; + FullscreenController* fullscreen_controller = + exclusive_access_manager()->fullscreen_controller(); + if ((fullscreen_controller->exclusive_access_tab() == tab) && + fullscreen_controller->IsPrivilegedFullscreenForTab()) { + mouse_lock_view = + exclusive_access_tab()->GetFullscreenRenderWidgetHostView(); + } + + if (!mouse_lock_view) { + RenderViewHost* const rvh = exclusive_access_tab()->GetRenderViewHost(); + if (rvh) + mouse_lock_view = rvh->GetView(); + } + + if (mouse_lock_view) + mouse_lock_view->UnlockMouse(); +} + +ContentSetting MouseLockController::GetMouseLockSetting(const GURL& url) const { + if (exclusive_access_manager() + ->fullscreen_controller() + ->IsPrivilegedFullscreenForTab() || + url.SchemeIsFile()) + return CONTENT_SETTING_ALLOW; + + HostContentSettingsMap* settings_map = profile()->GetHostContentSettingsMap(); + return settings_map->GetContentSetting( + url, url, CONTENT_SETTINGS_TYPE_MOUSELOCK, std::string()); +} diff --git a/chrome/browser/ui/exclusive_access/mouse_lock_controller.h b/chrome/browser/ui/exclusive_access/mouse_lock_controller.h new file mode 100644 index 0000000..27cede2 --- /dev/null +++ b/chrome/browser/ui/exclusive_access/mouse_lock_controller.h @@ -0,0 +1,61 @@ +// Copyright (c) 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_EXCLUSIVE_ACCESS_MOUSE_LOCK_CONTROLLER_H_ +#define CHROME_BROWSER_UI_EXCLUSIVE_ACCESS_MOUSE_LOCK_CONTROLLER_H_ + +#include "chrome/browser/ui/exclusive_access/exclusive_access_controller_base.h" +#include "components/content_settings/core/common/content_settings.h" + +// This class implements mouselock behavior. +class MouseLockController : public ExclusiveAccessControllerBase { + public: + MouseLockController(ExclusiveAccessManager* manager, Browser* browser); + ~MouseLockController() override; + + bool IsMouseLocked() const; + bool IsMouseLockSilentlyAccepted() const; + bool IsMouseLockRequested() const; + + void RequestToLockMouse(content::WebContents* web_contents, + bool user_gesture, + bool last_unlocked_by_target); + + // Override from ExclusiveAccessControllerBase + bool HandleUserPressedEscape() override; + + void ExitExclusiveAccessToPreviousState() override; + bool OnAcceptExclusiveAccessPermission() override; + bool OnDenyExclusiveAccessPermission() override; + + // Called by Browser::LostMouseLock. + void LostMouseLock(); + + void UnlockMouse(); + + private: + enum MouseLockState { + MOUSELOCK_NOT_REQUESTED, + // The page requests to lock the mouse and the user hasn't responded to the + // request. + MOUSELOCK_REQUESTED, + // Mouse lock has been allowed by the user. + MOUSELOCK_ACCEPTED, + // Mouse lock has been silently accepted, no notification to user. + MOUSELOCK_ACCEPTED_SILENTLY + }; + + void NotifyMouseLockChange(); + + void ExitExclusiveAccessIfNecessary() override; + void NotifyTabExclusiveAccessLost() override; + + ContentSetting GetMouseLockSetting(const GURL& url) const; + + MouseLockState mouse_lock_state_; + + DISALLOW_COPY_AND_ASSIGN(MouseLockController); +}; + +#endif // CHROME_BROWSER_UI_EXCLUSIVE_ACCESS_MOUSE_LOCK_CONTROLLER_H_ diff --git a/chrome/browser/ui/views/exclusive_access_bubble_views.cc b/chrome/browser/ui/views/exclusive_access_bubble_views.cc index 94fa862..902bdc2 100644 --- a/chrome/browser/ui/views/exclusive_access_bubble_views.cc +++ b/chrome/browser/ui/views/exclusive_access_bubble_views.cc @@ -8,6 +8,7 @@ #include "base/strings/utf_string_conversions.h" #include "chrome/app/chrome_command_ids.h" #include "chrome/browser/chrome_notification_types.h" +#include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h" #include "chrome/browser/ui/exclusive_access/fullscreen_controller.h" #include "chrome/browser/ui/views/frame/browser_view.h" #include "chrome/browser/ui/views/frame/immersive_mode_controller.h" @@ -295,9 +296,11 @@ ExclusiveAccessBubbleViews::ExclusiveAccessBubbleViews( popup_->AddObserver(this); - registrar_.Add(this, chrome::NOTIFICATION_FULLSCREEN_CHANGED, - content::Source<FullscreenController>( - browser_view_->browser()->fullscreen_controller())); + registrar_.Add( + this, chrome::NOTIFICATION_FULLSCREEN_CHANGED, + content::Source<FullscreenController>(browser_view_->browser() + ->exclusive_access_manager() + ->fullscreen_controller())); UpdateForImmersiveState(); } diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc index 958dce5..ec64e54 100644 --- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc +++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc @@ -80,8 +80,10 @@ IN_PROC_BROWSER_TEST_F(BrowserNonClientFrameViewAshTest, // NOTIFICATION_FULLSCREEN_CHANGED is sent asynchronously. scoped_ptr<FullscreenNotificationObserver> waiter( new FullscreenNotificationObserver()); - browser()->fullscreen_controller()->EnterFullscreenModeForTab( - web_contents, GURL()); + browser() + ->exclusive_access_manager() + ->fullscreen_controller() + ->EnterFullscreenModeForTab(web_contents, GURL()); waiter->Wait(); } EXPECT_FALSE(browser_view->immersive_mode_controller()->IsEnabled()); @@ -138,8 +140,10 @@ IN_PROC_BROWSER_TEST_F(BrowserNonClientFrameViewAshTest, ImmersiveFullscreen) { { scoped_ptr<FullscreenNotificationObserver> waiter( new FullscreenNotificationObserver()); - browser()->fullscreen_controller()->EnterFullscreenModeForTab( - web_contents, GURL()); + browser() + ->exclusive_access_manager() + ->fullscreen_controller() + ->EnterFullscreenModeForTab(web_contents, GURL()); waiter->Wait(); } EXPECT_TRUE(immersive_mode_controller->IsEnabled()); @@ -165,7 +169,10 @@ IN_PROC_BROWSER_TEST_F(BrowserNonClientFrameViewAshTest, ImmersiveFullscreen) { { scoped_ptr<FullscreenNotificationObserver> waiter( new FullscreenNotificationObserver()); - browser()->fullscreen_controller()->ExitFullscreenModeForTab(web_contents); + browser() + ->exclusive_access_manager() + ->fullscreen_controller() + ->ExitFullscreenModeForTab(web_contents); waiter->Wait(); } diff --git a/chrome/browser/ui/views/frame/immersive_mode_controller_ash.cc b/chrome/browser/ui/views/frame/immersive_mode_controller_ash.cc index 664a4d2..31fda80 100644 --- a/chrome/browser/ui/views/frame/immersive_mode_controller_ash.cc +++ b/chrome/browser/ui/views/frame/immersive_mode_controller_ash.cc @@ -8,6 +8,7 @@ #include "ash/wm/immersive_revealed_lock.h" #include "ash/wm/window_state.h" #include "chrome/browser/chrome_notification_types.h" +#include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h" #include "chrome/browser/ui/exclusive_access/fullscreen_controller.h" #include "chrome/browser/ui/views/frame/browser_view.h" #include "chrome/browser/ui/views/frame/top_container_view.h" @@ -138,8 +139,9 @@ void ImmersiveModeControllerAsh::EnableWindowObservers(bool enable) { return; observers_enabled_ = enable; - content::Source<FullscreenController> source( - browser_view_->browser()->fullscreen_controller()); + content::Source<FullscreenController> source(browser_view_->browser() + ->exclusive_access_manager() + ->fullscreen_controller()); if (enable) { ash::wm::GetWindowState(native_window_)->AddObserver(this); registrar_.Add(this, chrome::NOTIFICATION_FULLSCREEN_CHANGED, source); @@ -163,8 +165,10 @@ bool ImmersiveModeControllerAsh::UpdateTabIndicators() { if (!IsEnabled() || !has_tabstrip) { use_tab_indicators_ = false; } else { - bool in_tab_fullscreen = browser_view_->browser()->fullscreen_controller()-> - IsWindowFullscreenForTabOrPending(); + bool in_tab_fullscreen = browser_view_->browser() + ->exclusive_access_manager() + ->fullscreen_controller() + ->IsWindowFullscreenForTabOrPending(); use_tab_indicators_ = !in_tab_fullscreen; } diff --git a/chrome/browser/ui/views/frame/immersive_mode_controller_ash_unittest.cc b/chrome/browser/ui/views/frame/immersive_mode_controller_ash_unittest.cc index 85d8a0d..2a27679 100644 --- a/chrome/browser/ui/views/frame/immersive_mode_controller_ash_unittest.cc +++ b/chrome/browser/ui/views/frame/immersive_mode_controller_ash_unittest.cc @@ -74,13 +74,16 @@ class ImmersiveModeControllerAshTest : public TestWithBrowserView { scoped_ptr<FullscreenNotificationObserver> waiter( new FullscreenNotificationObserver()); if (tab_fullscreen) { - browser()->fullscreen_controller()->EnterFullscreenModeForTab( - web_contents, GURL()); + browser() + ->exclusive_access_manager() + ->fullscreen_controller() + ->EnterFullscreenModeForTab(web_contents, GURL()); } else { - browser()->fullscreen_controller()->ExitFullscreenModeForTab( - web_contents); + browser() + ->exclusive_access_manager() + ->fullscreen_controller() + ->ExitFullscreenModeForTab(web_contents); } - waiter->Wait(); } diff --git a/chrome/browser/ui/views/location_bar/zoom_bubble_view.cc b/chrome/browser/ui/views/location_bar/zoom_bubble_view.cc index 416de50..eff898a 100644 --- a/chrome/browser/ui/views/location_bar/zoom_bubble_view.cc +++ b/chrome/browser/ui/views/location_bar/zoom_bubble_view.cc @@ -39,7 +39,8 @@ ZoomBubbleView* ZoomBubbleView::zoom_bubble_ = NULL; void ZoomBubbleView::ShowBubble(content::WebContents* web_contents, bool auto_close) { Browser* browser = chrome::FindBrowserWithWebContents(web_contents); - DCHECK(browser && browser->window() && browser->fullscreen_controller()); + DCHECK(browser && browser->window() && + browser->exclusive_access_manager()->fullscreen_controller()); BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser); bool is_fullscreen = browser_view->IsFullscreen(); @@ -66,11 +67,8 @@ void ZoomBubbleView::ShowBubble(content::WebContents* web_contents, // bubble must be closed and a new one created. CloseBubble(); - zoom_bubble_ = new ZoomBubbleView(anchor_view, - web_contents, - auto_close, - browser_view->immersive_mode_controller(), - browser->fullscreen_controller()); + zoom_bubble_ = new ZoomBubbleView(anchor_view, web_contents, auto_close, + browser_view->immersive_mode_controller()); // If the zoom change was initiated by an extension, capture the relevent // information from it. @@ -118,8 +116,7 @@ ZoomBubbleView::ZoomBubbleView( views::View* anchor_view, content::WebContents* web_contents, bool auto_close, - ImmersiveModeController* immersive_mode_controller, - FullscreenController* fullscreen_controller) + ImmersiveModeController* immersive_mode_controller) : ManagedFullScreenBubbleDelegateView(anchor_view, web_contents), image_button_(NULL), label_(NULL), diff --git a/chrome/browser/ui/views/location_bar/zoom_bubble_view.h b/chrome/browser/ui/views/location_bar/zoom_bubble_view.h index 13afb64..b8039e6 100644 --- a/chrome/browser/ui/views/location_bar/zoom_bubble_view.h +++ b/chrome/browser/ui/views/location_bar/zoom_bubble_view.h @@ -75,8 +75,7 @@ class ZoomBubbleView : public ManagedFullScreenBubbleDelegateView, ZoomBubbleView(views::View* anchor_view, content::WebContents* web_contents, bool auto_close, - ImmersiveModeController* immersive_mode_controller, - FullscreenController* fullscreen_controller); + ImmersiveModeController* immersive_mode_controller); ~ZoomBubbleView() override; // ManagedFullScreenBubbleDelegateView: diff --git a/chrome/browser/ui/views/location_bar/zoom_bubble_view_browsertest.cc b/chrome/browser/ui/views/location_bar/zoom_bubble_view_browsertest.cc index eaa6571..207c029 100644 --- a/chrome/browser/ui/views/location_bar/zoom_bubble_view_browsertest.cc +++ b/chrome/browser/ui/views/location_bar/zoom_bubble_view_browsertest.cc @@ -38,8 +38,10 @@ IN_PROC_BROWSER_TEST_F(ZoomBubbleBrowserTest, MAYBE_NonImmersiveFullscreen) { // notification before testing the zoom bubble visibility. scoped_ptr<FullscreenNotificationObserver> waiter( new FullscreenNotificationObserver()); - browser()->fullscreen_controller()->EnterFullscreenModeForTab( - web_contents, GURL()); + browser() + ->exclusive_access_manager() + ->fullscreen_controller() + ->EnterFullscreenModeForTab(web_contents, GURL()); waiter->Wait(); } ASSERT_FALSE(browser_view->immersive_mode_controller()->IsEnabled()); diff --git a/chrome/browser/ui/views/managed_full_screen_bubble_delegate_view.cc b/chrome/browser/ui/views/managed_full_screen_bubble_delegate_view.cc index 4642cb3..9a867d2 100644 --- a/chrome/browser/ui/views/managed_full_screen_bubble_delegate_view.cc +++ b/chrome/browser/ui/views/managed_full_screen_bubble_delegate_view.cc @@ -21,9 +21,10 @@ ManagedFullScreenBubbleDelegateView::ManagedFullScreenBubbleDelegateView( // Add observer to close the bubble if the fullscreen state changes. if (web_contents) { Browser* browser = chrome::FindBrowserWithWebContents(web_contents); - registrar_.Add(this, chrome::NOTIFICATION_FULLSCREEN_CHANGED, - content::Source<FullscreenController>( - browser->fullscreen_controller())); + registrar_.Add( + this, chrome::NOTIFICATION_FULLSCREEN_CHANGED, + content::Source<FullscreenController>( + browser->exclusive_access_manager()->fullscreen_controller())); } } diff --git a/chrome/browser/ui/views/passwords/manage_passwords_bubble_view.cc b/chrome/browser/ui/views/passwords/manage_passwords_bubble_view.cc index e269bf5..a158ec2 100644 --- a/chrome/browser/ui/views/passwords/manage_passwords_bubble_view.cc +++ b/chrome/browser/ui/views/passwords/manage_passwords_bubble_view.cc @@ -861,7 +861,6 @@ void ManagePasswordsBubbleView::ShowBubble(content::WebContents* web_contents, Browser* browser = chrome::FindBrowserWithWebContents(web_contents); DCHECK(browser); DCHECK(browser->window()); - DCHECK(browser->fullscreen_controller()); if (IsShowing()) return; diff --git a/chrome/chrome_browser_ui.gypi b/chrome/chrome_browser_ui.gypi index 7c16457..00703f1 100644 --- a/chrome/chrome_browser_ui.gypi +++ b/chrome/chrome_browser_ui.gypi @@ -1435,10 +1435,16 @@ 'browser/ui/exclusive_access/exclusive_access_bubble.h', 'browser/ui/exclusive_access/exclusive_access_bubble_type.cc', 'browser/ui/exclusive_access/exclusive_access_bubble_type.h', + 'browser/ui/exclusive_access/exclusive_access_controller_base.cc', + 'browser/ui/exclusive_access/exclusive_access_controller_base.h', + 'browser/ui/exclusive_access/exclusive_access_manager.cc', + 'browser/ui/exclusive_access/exclusive_access_manager.h', 'browser/ui/exclusive_access/fullscreen_controller.cc', 'browser/ui/exclusive_access/fullscreen_controller.h', 'browser/ui/exclusive_access/fullscreen_within_tab_helper.cc', 'browser/ui/exclusive_access/fullscreen_within_tab_helper.h', + 'browser/ui/exclusive_access/mouse_lock_controller.cc', + 'browser/ui/exclusive_access/mouse_lock_controller.h', 'browser/ui/fast_unload_controller.cc', 'browser/ui/fast_unload_controller.h', 'browser/ui/find_bar/find_bar_controller.cc', |