| Index: chrome/browser/ui/fullscreen_controller.cc
|
| diff --git a/chrome/browser/ui/fullscreen_controller.cc b/chrome/browser/ui/fullscreen_controller.cc
|
| index 8f50aff764afd76f8efd6731cc20320e0eec1fd7..088437af5c2b640cc7af585f6a10605b65b4889e 100644
|
| --- a/chrome/browser/ui/fullscreen_controller.cc
|
| +++ b/chrome/browser/ui/fullscreen_controller.cc
|
| @@ -18,6 +18,7 @@
|
| #include "chrome/common/extensions/extension.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/user_metrics.h"
|
| #include "content/public/browser/web_contents.h"
|
|
|
| @@ -34,6 +35,8 @@ FullscreenController::FullscreenController(BrowserWindow* window,
|
| fullscreened_tab_(NULL),
|
| tab_caused_fullscreen_(false),
|
| tab_fullscreen_accepted_(false),
|
| + toggled_into_fullscreen_(false),
|
| + mouse_lock_tab_(NULL),
|
| mouse_lock_state_(MOUSELOCK_NOT_REQUESTED) {
|
| }
|
|
|
| @@ -64,29 +67,39 @@ bool FullscreenController::IsMouseLocked() const {
|
| }
|
|
|
| void FullscreenController::RequestToLockMouse(WebContents* tab,
|
| - bool /* user_gesture */) {
|
| - // TODO(scheib) user_gesture required for Mouse Lock in Windowed Mode.
|
| - // See http://crbug.com/107013, which will land in multiple patches.
|
| -
|
| + bool user_gesture) {
|
| DCHECK(!IsMouseLocked());
|
| + NotifyMouseLockChange();
|
|
|
| - // Mouse Lock is only permitted when browser is in tab fullscreen.
|
| - if (!IsFullscreenForTabOrPending(tab)) {
|
| + // Must have a user gesture, or we must already be in tab fullscreen.
|
| + if (!user_gesture && !IsFullscreenForTabOrPending(tab)) {
|
| tab->GotResponseToLockMouseRequest(false);
|
| return;
|
| }
|
|
|
| + mouse_lock_tab_ = TabContentsWrapper::GetCurrentWrapperForContents(tab);
|
| + FullscreenExitBubbleType bubble_type = GetFullscreenExitBubbleType();
|
| +
|
| switch (GetMouseLockSetting(tab->GetURL())) {
|
| case CONTENT_SETTING_ALLOW:
|
| - if (tab_fullscreen_accepted_) {
|
| - if (tab->GotResponseToLockMouseRequest(true))
|
| - mouse_lock_state_ = MOUSELOCK_ACCEPTED;
|
| - } else {
|
| + // If bubble already displaying buttons we must not lock the mouse yet,
|
| + // or it would prevent pressing those buttons. Instead, merge the request.
|
| + if (fullscreen_bubble::ShowButtonsForType(bubble_type)) {
|
| mouse_lock_state_ = MOUSELOCK_REQUESTED;
|
| + } else {
|
| + // Lock mouse.
|
| + if (tab->GotResponseToLockMouseRequest(true)) {
|
| + mouse_lock_state_ = MOUSELOCK_ACCEPTED;
|
| + } else {
|
| + mouse_lock_tab_ = NULL;
|
| + mouse_lock_state_ = MOUSELOCK_NOT_REQUESTED;
|
| + }
|
| }
|
| break;
|
| case CONTENT_SETTING_BLOCK:
|
| tab->GotResponseToLockMouseRequest(false);
|
| + mouse_lock_tab_ = NULL;
|
| + mouse_lock_state_ = MOUSELOCK_NOT_REQUESTED;
|
| break;
|
| case CONTENT_SETTING_ASK:
|
| mouse_lock_state_ = MOUSELOCK_REQUESTED;
|
| @@ -142,7 +155,7 @@ void FullscreenController::ToggleFullscreenModeForTab(WebContents* tab,
|
| // 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.
|
| - NotifyTabOfFullscreenExitIfNecessary();
|
| + NotifyTabOfExitIfNecessary();
|
| }
|
| }
|
| }
|
| @@ -169,24 +182,26 @@ void FullscreenController::ToggleFullscreenModeWithExtension(
|
|
|
| void FullscreenController::LostMouseLock() {
|
| mouse_lock_state_ = MOUSELOCK_NOT_REQUESTED;
|
| + mouse_lock_tab_ = NULL;
|
| + NotifyMouseLockChange();
|
| UpdateFullscreenExitBubbleContent();
|
| }
|
|
|
| void FullscreenController::OnTabClosing(WebContents* web_contents) {
|
| if (IsFullscreenForTabOrPending(web_contents)) {
|
| - ExitTabbedFullscreenModeIfNecessary();
|
| + 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 NotifyTabOfFullscreenExitIfNecessary(), because at that point
|
| - // |fullscreen_tab_| may not be valid. Instead, we call it here to clean up
|
| - // tab fullscreen related state.
|
| - NotifyTabOfFullscreenExitIfNecessary();
|
| + // 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();
|
| }
|
| }
|
|
|
| void FullscreenController::OnTabDeactivated(TabContentsWrapper* contents) {
|
| if (contents == fullscreened_tab_)
|
| - ExitTabbedFullscreenModeIfNecessary();
|
| + ExitTabFullscreenOrMouseLockIfNecessary();
|
| }
|
|
|
| void FullscreenController::OnAcceptFullscreenPermission(
|
| @@ -196,12 +211,13 @@ void FullscreenController::OnAcceptFullscreenPermission(
|
| bool fullscreen = false;
|
| fullscreen_bubble::PermissionRequestedByType(bubble_type, &fullscreen,
|
| &mouse_lock);
|
| - DCHECK(fullscreened_tab_);
|
| - DCHECK_NE(tab_fullscreen_accepted_, fullscreen);
|
| + DCHECK(!(fullscreen && tab_fullscreen_accepted_));
|
| + DCHECK(!(mouse_lock && IsMouseLocked()));
|
|
|
| HostContentSettingsMap* settings_map = profile_->GetHostContentSettingsMap();
|
| ContentSettingsPattern pattern = ContentSettingsPattern::FromURL(url);
|
| - if (mouse_lock) {
|
| +
|
| + if (mouse_lock && !IsMouseLocked()) {
|
| DCHECK(IsMouseLockRequested());
|
| // TODO(markusheintz): We should allow patterns for all possible URLs here.
|
| if (pattern.IsValid()) {
|
| @@ -210,11 +226,20 @@ void FullscreenController::OnAcceptFullscreenPermission(
|
| CONTENT_SETTINGS_TYPE_MOUSELOCK, std::string(),
|
| CONTENT_SETTING_ALLOW);
|
| }
|
| - mouse_lock_state_ =
|
| - fullscreened_tab_->web_contents()->GotResponseToLockMouseRequest(true) ?
|
| - MOUSELOCK_ACCEPTED : MOUSELOCK_NOT_REQUESTED;
|
| +
|
| + if (mouse_lock_tab_ &&
|
| + mouse_lock_tab_->web_contents() &&
|
| + mouse_lock_tab_->web_contents()->GotResponseToLockMouseRequest(true)) {
|
| + mouse_lock_state_ = MOUSELOCK_ACCEPTED;
|
| + } else {
|
| + mouse_lock_state_ = MOUSELOCK_NOT_REQUESTED;
|
| + mouse_lock_tab_ = NULL;
|
| + }
|
| + NotifyMouseLockChange();
|
| }
|
| - if (!tab_fullscreen_accepted_) {
|
| +
|
| + if (fullscreen && !tab_fullscreen_accepted_) {
|
| + DCHECK(fullscreened_tab_);
|
| if (pattern.IsValid()) {
|
| settings_map->SetContentSetting(
|
| pattern, ContentSettingsPattern::Wildcard(),
|
| @@ -232,19 +257,27 @@ void FullscreenController::OnDenyFullscreenPermission(
|
| bool fullscreen = false;
|
| fullscreen_bubble::PermissionRequestedByType(bubble_type, &fullscreen,
|
| &mouse_lock);
|
| - DCHECK(fullscreened_tab_);
|
| - DCHECK_NE(tab_fullscreen_accepted_, fullscreen);
|
| + DCHECK(fullscreened_tab_ || mouse_lock_tab_);
|
| + DCHECK(!(fullscreen && tab_fullscreen_accepted_));
|
| + DCHECK(!(mouse_lock && IsMouseLocked()));
|
|
|
| if (mouse_lock) {
|
| DCHECK(IsMouseLockRequested());
|
| mouse_lock_state_ = MOUSELOCK_NOT_REQUESTED;
|
| - fullscreened_tab_->web_contents()->GotResponseToLockMouseRequest(false);
|
| + if (mouse_lock_tab_ && mouse_lock_tab_->web_contents())
|
| + mouse_lock_tab_->web_contents()->GotResponseToLockMouseRequest(false);
|
| + mouse_lock_tab_ = 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 (!fullscreen)
|
| UpdateFullscreenExitBubbleContent();
|
| }
|
|
|
| if (fullscreen)
|
| - ExitTabbedFullscreenModeIfNecessary();
|
| + ExitTabFullscreenOrMouseLockIfNecessary();
|
| }
|
|
|
| void FullscreenController::WindowFullscreenStateChanged() {
|
| @@ -257,7 +290,7 @@ void FullscreenController::WindowFullscreenStateChanged() {
|
| exiting_fullscreen = !window_->IsFullscreen();
|
| #endif
|
| if (exiting_fullscreen)
|
| - NotifyTabOfFullscreenExitIfNecessary();
|
| + NotifyTabOfExitIfNecessary();
|
| if (exiting_fullscreen)
|
| window_->GetDownloadShelf()->Unhide();
|
| else
|
| @@ -265,47 +298,72 @@ void FullscreenController::WindowFullscreenStateChanged() {
|
| }
|
|
|
| bool FullscreenController::HandleUserPressedEscape() {
|
| - if (!IsFullscreenForTabOrPending())
|
| - return false;
|
| - ExitTabbedFullscreenModeIfNecessary();
|
| - return true;
|
| + if (IsFullscreenForTabOrPending() ||
|
| + IsMouseLocked() || IsMouseLockRequested()) {
|
| + ExitTabFullscreenOrMouseLockIfNecessary();
|
| + return true;
|
| + }
|
| +
|
| + return false;
|
| }
|
|
|
| FullscreenController::~FullscreenController() {}
|
|
|
| -void FullscreenController::NotifyTabOfFullscreenExitIfNecessary() {
|
| +void FullscreenController::NotifyTabOfExitIfNecessary() {
|
| if (fullscreened_tab_) {
|
| RenderViewHost* rvh =
|
| fullscreened_tab_->web_contents()->GetRenderViewHost();
|
| fullscreened_tab_ = NULL;
|
| tab_caused_fullscreen_ = false;
|
| tab_fullscreen_accepted_ = false;
|
| - mouse_lock_state_ = MOUSELOCK_NOT_REQUESTED;
|
| if (rvh)
|
| rvh->ExitFullscreen();
|
| - } else {
|
| - DCHECK_EQ(mouse_lock_state_, MOUSELOCK_NOT_REQUESTED);
|
| + }
|
| +
|
| + if (mouse_lock_tab_) {
|
| + WebContents* web_contents = mouse_lock_tab_->web_contents();
|
| + if (IsMouseLockRequested()) {
|
| + web_contents->GotResponseToLockMouseRequest(false);
|
| + } else if (web_contents->GetRenderViewHost() &&
|
| + web_contents->GetRenderViewHost()->GetView()) {
|
| + web_contents->GetRenderViewHost()->GetView()->UnlockMouse();
|
| + }
|
| + mouse_lock_tab_ = NULL;
|
| + mouse_lock_state_ = MOUSELOCK_NOT_REQUESTED;
|
| }
|
|
|
| UpdateFullscreenExitBubbleContent();
|
| }
|
|
|
| -void FullscreenController::ExitTabbedFullscreenModeIfNecessary() {
|
| +void FullscreenController::ExitTabFullscreenOrMouseLockIfNecessary() {
|
| if (tab_caused_fullscreen_)
|
| ToggleFullscreenMode();
|
| else
|
| - NotifyTabOfFullscreenExitIfNecessary();
|
| + NotifyTabOfExitIfNecessary();
|
| }
|
|
|
| void FullscreenController::UpdateFullscreenExitBubbleContent() {
|
| GURL url;
|
| if (fullscreened_tab_)
|
| url = fullscreened_tab_->web_contents()->GetURL();
|
| + else if (mouse_lock_tab_)
|
| + url = mouse_lock_tab_->web_contents()->GetURL();
|
| else if (!extension_caused_fullscreen_.is_empty())
|
| url = extension_caused_fullscreen_;
|
|
|
| - window_->UpdateFullscreenExitBubbleContent(url,
|
| - GetFullscreenExitBubbleType());
|
| + FullscreenExitBubbleType bubble_type = GetFullscreenExitBubbleType();
|
| +
|
| + // If bubble displays buttons, unlock mouse to allow pressing them.
|
| + if (fullscreen_bubble::ShowButtonsForType(bubble_type) &&
|
| + IsMouseLocked() &&
|
| + mouse_lock_tab_->web_contents()) {
|
| + WebContents* web_contents = mouse_lock_tab_->web_contents();
|
| + if (web_contents && web_contents->GetRenderViewHost() &&
|
| + web_contents->GetRenderViewHost()->GetView())
|
| + web_contents->GetRenderViewHost()->GetView()->UnlockMouse();
|
| + }
|
| +
|
| + window_->UpdateFullscreenExitBubbleContent(url, bubble_type);
|
| }
|
|
|
| void FullscreenController::NotifyFullscreenChange() {
|
| @@ -315,24 +373,55 @@ void FullscreenController::NotifyFullscreenChange() {
|
| content::NotificationService::NoDetails());
|
| }
|
|
|
| +void FullscreenController::NotifyMouseLockChange() {
|
| + content::NotificationService::current()->Notify(
|
| + chrome::NOTIFICATION_MOUSE_LOCK_CHANGED,
|
| + content::Source<FullscreenController>(this),
|
| + content::NotificationService::NoDetails());
|
| +}
|
| +
|
| FullscreenExitBubbleType FullscreenController::GetFullscreenExitBubbleType()
|
| const {
|
| - if (!fullscreened_tab_) {
|
| - DCHECK_EQ(MOUSELOCK_NOT_REQUESTED, mouse_lock_state_);
|
| - return !extension_caused_fullscreen_.is_empty() ?
|
| - FEB_TYPE_BROWSER_EXTENSION_FULLSCREEN_EXIT_INSTRUCTION :
|
| - FEB_TYPE_BROWSER_FULLSCREEN_EXIT_INSTRUCTION;
|
| - }
|
| - if (fullscreened_tab_ && !tab_fullscreen_accepted_) {
|
| - DCHECK_NE(MOUSELOCK_ACCEPTED, mouse_lock_state_);
|
| - return mouse_lock_state_ == MOUSELOCK_REQUESTED ?
|
| - FEB_TYPE_FULLSCREEN_MOUSELOCK_BUTTONS : FEB_TYPE_FULLSCREEN_BUTTONS;
|
| + // In kiosk mode we always want to be fullscreen and do not want to show
|
| + // exit instructions for browser mode fullscreen.
|
| + bool kiosk = false;
|
| +#if !defined(OS_MACOSX) // Kiosk mode not available on Mac.
|
| + kiosk = CommandLine::ForCurrentProcess()->HasSwitch(switches::kKioskMode);
|
| +#endif
|
| +
|
| + if (fullscreened_tab_) {
|
| + if (tab_fullscreen_accepted_) {
|
| + if (IsMouseLocked()) {
|
| + return FEB_TYPE_FULLSCREEN_MOUSELOCK_EXIT_INSTRUCTION;
|
| + } else if (IsMouseLockRequested()) {
|
| + return FEB_TYPE_MOUSELOCK_BUTTONS;
|
| + } else {
|
| + return FEB_TYPE_FULLSCREEN_EXIT_INSTRUCTION;
|
| + }
|
| + } else { // Full screen not yet accepted.
|
| + if (IsMouseLockRequested()) {
|
| + return FEB_TYPE_FULLSCREEN_MOUSELOCK_BUTTONS;
|
| + } else {
|
| + return FEB_TYPE_FULLSCREEN_BUTTONS;
|
| + }
|
| + }
|
| + } else { // Not tab full screen.
|
| + if (IsMouseLocked()) {
|
| + return FEB_TYPE_MOUSELOCK_EXIT_INSTRUCTION;
|
| + } else if (IsMouseLockRequested()) {
|
| + return FEB_TYPE_MOUSELOCK_BUTTONS;
|
| + } else {
|
| + if (!extension_caused_fullscreen_.is_empty()) {
|
| + return FEB_TYPE_BROWSER_EXTENSION_FULLSCREEN_EXIT_INSTRUCTION;
|
| + } else if (toggled_into_fullscreen_ && !kiosk) {
|
| + return FEB_TYPE_BROWSER_FULLSCREEN_EXIT_INSTRUCTION;
|
| + } else {
|
| + return FEB_TYPE_NONE;
|
| + }
|
| + }
|
| }
|
| - if (mouse_lock_state_ == MOUSELOCK_REQUESTED)
|
| - return FEB_TYPE_MOUSELOCK_BUTTONS;
|
| - return mouse_lock_state_ == MOUSELOCK_ACCEPTED ?
|
| - FEB_TYPE_FULLSCREEN_MOUSELOCK_EXIT_INSTRUCTION :
|
| - FEB_TYPE_FULLSCREEN_EXIT_INSTRUCTION;
|
| + NOTREACHED();
|
| + return FEB_TYPE_NONE;
|
| }
|
|
|
| ContentSetting
|
| @@ -357,17 +446,18 @@ ContentSetting
|
|
|
| #if defined(OS_MACOSX)
|
| void FullscreenController::TogglePresentationModeInternal(bool for_tab) {
|
| - bool entering_fullscreen = !window_->InPresentationMode();
|
| + toggled_into_fullscreen_ = !window_->InPresentationMode();
|
| GURL url;
|
| if (for_tab) {
|
| url = browser_->GetSelectedWebContents()->GetURL();
|
| - tab_fullscreen_accepted_ = entering_fullscreen &&
|
| + tab_fullscreen_accepted_ = toggled_into_fullscreen_ &&
|
| GetFullscreenSetting(url) == CONTENT_SETTING_ALLOW;
|
| }
|
| - if (entering_fullscreen)
|
| + if (toggled_into_fullscreen_)
|
| window_->EnterPresentationMode(url, GetFullscreenExitBubbleType());
|
| else
|
| window_->ExitPresentationMode();
|
| + UpdateFullscreenExitBubbleContent();
|
|
|
| // WindowFullscreenStateChanged will be called by BrowserWindowController
|
| // when the transition completes.
|
| @@ -376,11 +466,11 @@ void FullscreenController::TogglePresentationModeInternal(bool for_tab) {
|
|
|
| // TODO(koz): Change |for_tab| to an enum.
|
| void FullscreenController::ToggleFullscreenModeInternal(bool for_tab) {
|
| - bool entering_fullscreen = !window_->IsFullscreen();
|
| + toggled_into_fullscreen_ = !window_->IsFullscreen();
|
|
|
| -#if !defined(OS_MACOSX)
|
| - // 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.
|
| + // 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 !defined(OS_MACOSX) // Kiosk mode not available on Mac.
|
| if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kKioskMode) &&
|
| window_->IsFullscreen())
|
| return;
|
| @@ -389,19 +479,20 @@ void FullscreenController::ToggleFullscreenModeInternal(bool for_tab) {
|
| GURL url;
|
| if (for_tab) {
|
| url = browser_->GetSelectedWebContents()->GetURL();
|
| - tab_fullscreen_accepted_ = entering_fullscreen &&
|
| + tab_fullscreen_accepted_ = toggled_into_fullscreen_ &&
|
| GetFullscreenSetting(url) == CONTENT_SETTING_ALLOW;
|
| } else {
|
| if (!extension_caused_fullscreen_.is_empty())
|
| url = extension_caused_fullscreen_;
|
| content::RecordAction(UserMetricsAction("ToggleFullscreen"));
|
| }
|
| - if (entering_fullscreen) {
|
| + if (toggled_into_fullscreen_) {
|
| window_->EnterFullscreen(url, GetFullscreenExitBubbleType());
|
| } else {
|
| window_->ExitFullscreen();
|
| extension_caused_fullscreen_ = GURL();
|
| }
|
| + UpdateFullscreenExitBubbleContent();
|
|
|
| // Once the window has become fullscreen it'll call back to
|
| // WindowFullscreenStateChanged(). We don't do this immediately as
|
|
|