1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/ui/fullscreen/fullscreen_controller.h"
8 #include "base/command_line.h"
9 #include "base/message_loop/message_loop.h"
10 #include "chrome/browser/app_mode/app_mode_utils.h"
11 #include "chrome/browser/chrome_notification_types.h"
12 #include "chrome/browser/content_settings/host_content_settings_map.h"
13 #include "chrome/browser/download/download_shelf.h"
14 #include "chrome/browser/fullscreen.h"
15 #include "chrome/browser/profiles/profile.h"
16 #include "chrome/browser/ui/browser.h"
17 #include "chrome/browser/ui/browser_window.h"
18 #include "chrome/browser/ui/fullscreen/fullscreen_within_tab_helper.h"
19 #include "chrome/browser/ui/status_bubble.h"
20 #include "chrome/browser/ui/tabs/tab_strip_model.h"
21 #include "chrome/common/chrome_switches.h"
22 #include "content/public/browser/navigation_details.h"
23 #include "content/public/browser/navigation_entry.h"
24 #include "content/public/browser/notification_service.h"
25 #include "content/public/browser/render_view_host.h"
26 #include "content/public/browser/render_widget_host_view.h"
27 #include "content/public/browser/user_metrics.h"
28 #include "content/public/browser/web_contents.h"
29 #include "content/public/browser/web_contents_view.h"
30 #include "extensions/common/extension.h"
32 #if defined(OS_MACOSX)
33 #include "base/mac/mac_util.h"
35 #include "base/prefs/pref_service.h"
36 #include "chrome/common/pref_names.h"
39 using base::UserMetricsAction;
40 using content::RenderViewHost;
41 using content::WebContents;
43 FullscreenController::FullscreenController(Browser* browser)
45 window_(browser->window()),
46 profile_(browser->profile()),
47 fullscreened_tab_(NULL),
48 state_prior_to_tab_fullscreen_(STATE_INVALID),
49 tab_fullscreen_accepted_(false),
50 toggled_into_fullscreen_(false),
51 mouse_lock_tab_(NULL),
52 mouse_lock_state_(MOUSELOCK_NOT_REQUESTED),
53 reentrant_window_state_change_call_check_(false),
54 is_privileged_fullscreen_for_testing_(false),
60 FullscreenController::~FullscreenController() {
63 bool FullscreenController::IsFullscreenForBrowser() const {
64 return window_->IsFullscreen() && !IsFullscreenCausedByTab();
67 void FullscreenController::ToggleBrowserFullscreenMode() {
68 extension_caused_fullscreen_ = GURL();
69 ToggleFullscreenModeInternal(BROWSER);
72 void FullscreenController::ToggleBrowserFullscreenModeWithExtension(
73 const GURL& extension_url) {
74 // |extension_caused_fullscreen_| will be reset if this causes fullscreen to
76 extension_caused_fullscreen_ = extension_url;
77 ToggleFullscreenModeInternal(BROWSER);
80 bool FullscreenController::IsWindowFullscreenForTabOrPending() const {
81 return fullscreened_tab_ != NULL;
84 bool FullscreenController::IsFullscreenForTabOrPending(
85 const WebContents* web_contents) const {
86 if (web_contents == fullscreened_tab_) {
87 DCHECK(web_contents == browser_->tab_strip_model()->GetActiveWebContents());
88 DCHECK(!IsFullscreenWithinTabPossible() ||
89 web_contents->GetCapturerCount() == 0);
92 return IsFullscreenForCapturedTab(web_contents);
95 bool FullscreenController::IsFullscreenCausedByTab() const {
96 return state_prior_to_tab_fullscreen_ == STATE_NORMAL;
99 void FullscreenController::ToggleFullscreenModeForTab(WebContents* web_contents,
100 bool enter_fullscreen) {
101 if (MaybeToggleFullscreenForCapturedTab(web_contents, enter_fullscreen)) {
102 // During tab capture of fullscreen-within-tab views, the browser window
103 // fullscreen state is unchanged, so return now.
106 if (fullscreened_tab_) {
107 if (web_contents != fullscreened_tab_)
110 web_contents != browser_->tab_strip_model()->GetActiveWebContents()) {
113 if (IsWindowFullscreenForTabOrPending() == enter_fullscreen)
117 // For now, avoid breaking when initiating full screen tab mode while in
119 // TODO(robertshield): Find a way to reconcile tab-initiated fullscreen
120 // modes with metro snap.
121 if (IsInMetroSnapMode())
125 bool in_browser_or_tab_fullscreen_mode = window_->IsFullscreen();
126 bool window_is_fullscreen_with_chrome = false;
127 #if defined(OS_MACOSX)
128 window_is_fullscreen_with_chrome = window_->IsFullscreenWithChrome();
131 if (enter_fullscreen) {
132 SetFullscreenedTab(web_contents);
133 if (!in_browser_or_tab_fullscreen_mode) {
134 state_prior_to_tab_fullscreen_ = STATE_NORMAL;
135 ToggleFullscreenModeInternal(TAB);
136 } else if (window_is_fullscreen_with_chrome) {
137 #if defined(OS_MACOSX)
138 state_prior_to_tab_fullscreen_ = STATE_BROWSER_FULLSCREEN_WITH_CHROME;
139 EnterFullscreenModeInternal(TAB);
144 state_prior_to_tab_fullscreen_ = STATE_BROWSER_FULLSCREEN_NO_CHROME;
146 // We need to update the fullscreen exit bubble, e.g., going from browser
147 // fullscreen to tab fullscreen will need to show different content.
148 const GURL& url = web_contents->GetURL();
149 if (!tab_fullscreen_accepted_) {
150 tab_fullscreen_accepted_ =
151 GetFullscreenSetting(url) == CONTENT_SETTING_ALLOW;
153 UpdateFullscreenExitBubbleContent();
155 // This is only a change between Browser and Tab fullscreen. We generate
156 // a fullscreen notification now because there is no window change.
157 PostFullscreenChangeNotification(true);
160 if (in_browser_or_tab_fullscreen_mode) {
161 if (IsFullscreenCausedByTab()) {
162 ToggleFullscreenModeInternal(TAB);
164 #if defined(OS_MACOSX)
165 if (state_prior_to_tab_fullscreen_ ==
166 STATE_BROWSER_FULLSCREEN_WITH_CHROME) {
167 EnterFullscreenModeInternal(BROWSER_WITH_CHROME);
169 // Clear the bubble URL, which forces the Mac UI to redraw.
170 UpdateFullscreenExitBubbleContent();
173 // If currently there is a tab in "tab fullscreen" mode and fullscreen
174 // was not caused by it (i.e., previously it was in "browser fullscreen"
175 // mode), we need to switch back to "browser fullscreen" mode. In this
176 // case, all we have to do is notifying the tab that it has exited "tab
178 NotifyTabOfExitIfNecessary();
180 // This is only a change between Browser and Tab fullscreen. We generate
181 // a fullscreen notification now because there is no window change.
182 PostFullscreenChangeNotification(true);
188 bool FullscreenController::IsInMetroSnapMode() {
190 return window_->IsInMetroSnapMode();
197 void FullscreenController::SetMetroSnapMode(bool enable) {
198 reentrant_window_state_change_call_check_ = false;
200 toggled_into_fullscreen_ = false;
201 window_->SetMetroSnapMode(enable);
203 // FullscreenController unit tests for metro snap assume that on Windows calls
204 // to WindowFullscreenStateChanged are reentrant. If that assumption is
205 // invalidated, the tests must be updated to maintain coverage.
206 CHECK(reentrant_window_state_change_call_check_);
208 #endif // defined(OS_WIN)
210 #if defined(OS_MACOSX)
211 void FullscreenController::ToggleBrowserFullscreenWithChrome() {
212 // This method cannot be called if simplified fullscreen is enabled.
213 const CommandLine* command_line = CommandLine::ForCurrentProcess();
214 DCHECK(!command_line->HasSwitch(switches::kEnableSimplifiedFullscreen));
215 ToggleFullscreenModeInternal(BROWSER_WITH_CHROME);
219 bool FullscreenController::IsMouseLockRequested() const {
220 return mouse_lock_state_ == MOUSELOCK_REQUESTED;
223 bool FullscreenController::IsMouseLocked() const {
224 return mouse_lock_state_ == MOUSELOCK_ACCEPTED ||
225 mouse_lock_state_ == MOUSELOCK_ACCEPTED_SILENTLY;
228 void FullscreenController::RequestToLockMouse(WebContents* web_contents,
230 bool last_unlocked_by_target) {
231 DCHECK(!IsMouseLocked());
232 NotifyMouseLockChange();
234 // Must have a user gesture to prevent misbehaving sites from constantly
235 // re-locking the mouse. Exceptions are when the page has unlocked
236 // (i.e. not the user), or if we're in tab fullscreen (user gesture required
238 if (!last_unlocked_by_target && !user_gesture &&
239 !IsFullscreenForTabOrPending(web_contents)) {
240 web_contents->GotResponseToLockMouseRequest(false);
243 SetMouseLockTab(web_contents);
244 FullscreenExitBubbleType bubble_type = GetFullscreenExitBubbleType();
246 switch (GetMouseLockSetting(web_contents->GetURL())) {
247 case CONTENT_SETTING_ALLOW:
248 // If bubble already displaying buttons we must not lock the mouse yet,
249 // or it would prevent pressing those buttons. Instead, merge the request.
250 if (!IsPrivilegedFullscreenForTab() &&
251 fullscreen_bubble::ShowButtonsForType(bubble_type)) {
252 mouse_lock_state_ = MOUSELOCK_REQUESTED;
255 if (web_contents->GotResponseToLockMouseRequest(true)) {
256 if (last_unlocked_by_target) {
257 mouse_lock_state_ = MOUSELOCK_ACCEPTED_SILENTLY;
259 mouse_lock_state_ = MOUSELOCK_ACCEPTED;
262 SetMouseLockTab(NULL);
263 mouse_lock_state_ = MOUSELOCK_NOT_REQUESTED;
267 case CONTENT_SETTING_BLOCK:
268 web_contents->GotResponseToLockMouseRequest(false);
269 SetMouseLockTab(NULL);
270 mouse_lock_state_ = MOUSELOCK_NOT_REQUESTED;
272 case CONTENT_SETTING_ASK:
273 mouse_lock_state_ = MOUSELOCK_REQUESTED;
278 UpdateFullscreenExitBubbleContent();
281 void FullscreenController::OnTabDeactivated(WebContents* web_contents) {
282 if (web_contents == fullscreened_tab_ || web_contents == mouse_lock_tab_)
283 ExitTabFullscreenOrMouseLockIfNecessary();
286 void FullscreenController::OnTabDetachedFromView(WebContents* old_contents) {
287 if (!IsFullscreenForCapturedTab(old_contents))
290 // A fullscreen-within-tab view undergoing screen capture has been detached
291 // and is no longer visible to the user. Set it to exactly the WebContents'
292 // preferred size. See 'FullscreenWithinTab Note'.
294 // When the user later selects the tab to show |old_contents| again, UI code
295 // elsewhere (e.g., views::WebView) will resize the view to fit within the
296 // browser window once again.
298 // If the view has been detached from the browser window (e.g., to drag a tab
299 // off into a new browser window), return immediately to avoid an unnecessary
301 if (!old_contents->GetDelegate())
304 // Do nothing if tab capture ended after toggling fullscreen, or a preferred
305 // size was never specified by the capturer.
306 if (old_contents->GetCapturerCount() == 0 ||
307 old_contents->GetPreferredSize().IsEmpty()) {
311 content::RenderWidgetHostView* const current_fs_view =
312 old_contents->GetFullscreenRenderWidgetHostView();
314 current_fs_view->SetSize(old_contents->GetPreferredSize());
315 old_contents->GetView()->SizeContents(old_contents->GetPreferredSize());
318 void FullscreenController::OnTabClosing(WebContents* web_contents) {
319 if (IsFullscreenForCapturedTab(web_contents)) {
320 RenderViewHost* const rvh = web_contents->GetRenderViewHost();
322 rvh->ExitFullscreen();
323 } else if (web_contents == fullscreened_tab_ ||
324 web_contents == mouse_lock_tab_) {
325 ExitTabFullscreenOrMouseLockIfNecessary();
326 // The call to exit fullscreen may result in asynchronous notification of
327 // fullscreen state change (e.g., on Linux). We don't want to rely on it
328 // to call NotifyTabOfExitIfNecessary(), because at that point
329 // |fullscreened_tab_| may not be valid. Instead, we call it here to clean
330 // up tab fullscreen related state.
331 NotifyTabOfExitIfNecessary();
335 void FullscreenController::WindowFullscreenStateChanged() {
336 reentrant_window_state_change_call_check_ = true;
338 bool exiting_fullscreen = !window_->IsFullscreen();
340 PostFullscreenChangeNotification(!exiting_fullscreen);
341 if (exiting_fullscreen) {
342 toggled_into_fullscreen_ = false;
343 extension_caused_fullscreen_ = GURL();
344 NotifyTabOfExitIfNecessary();
346 if (exiting_fullscreen) {
347 window_->GetDownloadShelf()->Unhide();
349 window_->GetDownloadShelf()->Hide();
350 if (window_->GetStatusBubble())
351 window_->GetStatusBubble()->Hide();
355 bool FullscreenController::HandleUserPressedEscape() {
356 WebContents* const active_web_contents =
357 browser_->tab_strip_model()->GetActiveWebContents();
358 if (IsFullscreenForCapturedTab(active_web_contents)) {
359 RenderViewHost* const rvh = active_web_contents->GetRenderViewHost();
361 rvh->ExitFullscreen();
363 } else if (IsWindowFullscreenForTabOrPending() ||
364 IsMouseLocked() || IsMouseLockRequested()) {
365 ExitTabFullscreenOrMouseLockIfNecessary();
372 void FullscreenController::ExitTabOrBrowserFullscreenToPreviousState() {
373 if (IsWindowFullscreenForTabOrPending())
374 ExitTabFullscreenOrMouseLockIfNecessary();
375 else if (IsFullscreenForBrowser())
376 ExitFullscreenModeInternal();
379 void FullscreenController::OnAcceptFullscreenPermission() {
380 FullscreenExitBubbleType bubble_type = GetFullscreenExitBubbleType();
381 bool mouse_lock = false;
382 bool fullscreen = false;
383 fullscreen_bubble::PermissionRequestedByType(bubble_type, &fullscreen,
385 DCHECK(!(fullscreen && tab_fullscreen_accepted_));
386 DCHECK(!(mouse_lock && IsMouseLocked()));
388 HostContentSettingsMap* settings_map = profile_->GetHostContentSettingsMap();
390 GURL url = GetFullscreenExitBubbleURL();
391 ContentSettingsPattern pattern = ContentSettingsPattern::FromURL(url);
393 if (mouse_lock && !IsMouseLocked()) {
394 DCHECK(IsMouseLockRequested());
395 // TODO(markusheintz): We should allow patterns for all possible URLs here.
396 if (pattern.IsValid()) {
397 settings_map->SetContentSetting(
398 pattern, ContentSettingsPattern::Wildcard(),
399 CONTENT_SETTINGS_TYPE_MOUSELOCK, std::string(),
400 CONTENT_SETTING_ALLOW);
403 if (mouse_lock_tab_ &&
404 mouse_lock_tab_->GotResponseToLockMouseRequest(true)) {
405 mouse_lock_state_ = MOUSELOCK_ACCEPTED;
407 mouse_lock_state_ = MOUSELOCK_NOT_REQUESTED;
408 SetMouseLockTab(NULL);
410 NotifyMouseLockChange();
413 if (fullscreen && !tab_fullscreen_accepted_) {
414 DCHECK(fullscreened_tab_);
415 if (pattern.IsValid()) {
416 settings_map->SetContentSetting(
417 pattern, ContentSettingsPattern::Wildcard(),
418 CONTENT_SETTINGS_TYPE_FULLSCREEN, std::string(),
419 CONTENT_SETTING_ALLOW);
421 tab_fullscreen_accepted_ = true;
423 UpdateFullscreenExitBubbleContent();
426 void FullscreenController::OnDenyFullscreenPermission() {
427 if (!fullscreened_tab_ && !mouse_lock_tab_)
430 if (IsMouseLockRequested()) {
431 mouse_lock_state_ = MOUSELOCK_NOT_REQUESTED;
433 mouse_lock_tab_->GotResponseToLockMouseRequest(false);
434 SetMouseLockTab(NULL);
435 NotifyMouseLockChange();
437 // UpdateFullscreenExitBubbleContent() must be called, but to avoid
438 // duplicate calls we do so only if not adjusting the fullscreen state
439 // below, which also calls UpdateFullscreenExitBubbleContent().
440 if (!IsWindowFullscreenForTabOrPending())
441 UpdateFullscreenExitBubbleContent();
444 if (IsWindowFullscreenForTabOrPending())
445 ExitTabFullscreenOrMouseLockIfNecessary();
448 void FullscreenController::LostMouseLock() {
449 mouse_lock_state_ = MOUSELOCK_NOT_REQUESTED;
450 SetMouseLockTab(NULL);
451 NotifyMouseLockChange();
452 UpdateFullscreenExitBubbleContent();
455 void FullscreenController::Observe(int type,
456 const content::NotificationSource& source,
457 const content::NotificationDetails& details) {
458 DCHECK_EQ(content::NOTIFICATION_NAV_ENTRY_COMMITTED, type);
459 if (content::Details<content::LoadCommittedDetails>(details)->
460 is_navigation_to_different_page())
461 ExitTabFullscreenOrMouseLockIfNecessary();
464 GURL FullscreenController::GetFullscreenExitBubbleURL() const {
465 if (fullscreened_tab_)
466 return fullscreened_tab_->GetURL();
468 return mouse_lock_tab_->GetURL();
469 return extension_caused_fullscreen_;
472 FullscreenExitBubbleType FullscreenController::GetFullscreenExitBubbleType()
474 // In kiosk and exclusive app mode we always want to be fullscreen and do not
475 // want to show exit instructions for browser mode fullscreen.
476 bool app_mode = false;
477 #if !defined(OS_MACOSX) // App mode (kiosk) is not available on Mac yet.
478 app_mode = chrome::IsRunningInAppMode();
481 if (mouse_lock_state_ == MOUSELOCK_ACCEPTED_SILENTLY)
482 return FEB_TYPE_NONE;
484 if (!fullscreened_tab_) {
486 return FEB_TYPE_MOUSELOCK_EXIT_INSTRUCTION;
487 if (IsMouseLockRequested())
488 return FEB_TYPE_MOUSELOCK_BUTTONS;
489 if (!extension_caused_fullscreen_.is_empty())
490 return FEB_TYPE_BROWSER_EXTENSION_FULLSCREEN_EXIT_INSTRUCTION;
491 if (toggled_into_fullscreen_ && !app_mode)
492 return FEB_TYPE_BROWSER_FULLSCREEN_EXIT_INSTRUCTION;
493 return FEB_TYPE_NONE;
496 if (tab_fullscreen_accepted_) {
497 if (IsPrivilegedFullscreenForTab())
498 return FEB_TYPE_NONE;
500 return FEB_TYPE_FULLSCREEN_MOUSELOCK_EXIT_INSTRUCTION;
501 if (IsMouseLockRequested())
502 return FEB_TYPE_MOUSELOCK_BUTTONS;
503 return FEB_TYPE_FULLSCREEN_EXIT_INSTRUCTION;
506 if (IsMouseLockRequested())
507 return FEB_TYPE_FULLSCREEN_MOUSELOCK_BUTTONS;
508 return FEB_TYPE_FULLSCREEN_BUTTONS;
511 void FullscreenController::UpdateNotificationRegistrations() {
512 if (fullscreened_tab_ && mouse_lock_tab_)
513 DCHECK(fullscreened_tab_ == mouse_lock_tab_);
515 WebContents* tab = fullscreened_tab_ ? fullscreened_tab_ : mouse_lock_tab_;
517 if (tab && registrar_.IsEmpty()) {
518 registrar_.Add(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED,
519 content::Source<content::NavigationController>(&tab->GetController()));
520 } else if (!tab && !registrar_.IsEmpty()) {
521 registrar_.RemoveAll();
525 void FullscreenController::PostFullscreenChangeNotification(
526 bool is_fullscreen) {
527 base::MessageLoop::current()->PostTask(
529 base::Bind(&FullscreenController::NotifyFullscreenChange,
530 ptr_factory_.GetWeakPtr(),
534 void FullscreenController::NotifyFullscreenChange(bool is_fullscreen) {
535 content::NotificationService::current()->Notify(
536 chrome::NOTIFICATION_FULLSCREEN_CHANGED,
537 content::Source<FullscreenController>(this),
538 content::Details<bool>(&is_fullscreen));
541 void FullscreenController::NotifyTabOfExitIfNecessary() {
542 if (fullscreened_tab_) {
543 RenderViewHost* rvh = fullscreened_tab_->GetRenderViewHost();
544 SetFullscreenedTab(NULL);
545 state_prior_to_tab_fullscreen_ = STATE_INVALID;
546 tab_fullscreen_accepted_ = false;
548 rvh->ExitFullscreen();
551 if (mouse_lock_tab_) {
552 if (IsMouseLockRequested()) {
553 mouse_lock_tab_->GotResponseToLockMouseRequest(false);
554 NotifyMouseLockChange();
558 SetMouseLockTab(NULL);
559 mouse_lock_state_ = MOUSELOCK_NOT_REQUESTED;
562 UpdateFullscreenExitBubbleContent();
565 void FullscreenController::NotifyMouseLockChange() {
566 content::NotificationService::current()->Notify(
567 chrome::NOTIFICATION_MOUSE_LOCK_CHANGED,
568 content::Source<FullscreenController>(this),
569 content::NotificationService::NoDetails());
572 void FullscreenController::ToggleFullscreenModeInternal(
573 FullscreenInternalOption option) {
575 // When in Metro snap mode, toggling in and out of fullscreen is prevented.
576 if (IsInMetroSnapMode())
580 bool enter_fullscreen = !window_->IsFullscreen();
581 #if defined(OS_MACOSX)
582 // When a Mac user requests a toggle they may be toggling between
583 // FullscreenWithoutChrome and FullscreenWithChrome.
584 if (!IsWindowFullscreenForTabOrPending()) {
585 if (option == BROWSER_WITH_CHROME)
586 enter_fullscreen |= window_->IsFullscreenWithoutChrome();
588 enter_fullscreen |= window_->IsFullscreenWithChrome();
592 // In kiosk mode, we always want to be fullscreen. When the browser first
593 // starts we're not yet fullscreen, so let the initial toggle go through.
594 if (chrome::IsRunningInAppMode() && window_->IsFullscreen())
597 #if !defined(OS_MACOSX)
598 // Do not enter fullscreen mode if disallowed by pref. This prevents the user
599 // from manually entering fullscreen mode and also disables kiosk mode on
600 // desktop platforms.
601 if (enter_fullscreen &&
602 !profile_->GetPrefs()->GetBoolean(prefs::kFullscreenAllowed)) {
607 if (enter_fullscreen)
608 EnterFullscreenModeInternal(option);
610 ExitFullscreenModeInternal();
613 void FullscreenController::EnterFullscreenModeInternal(
614 FullscreenInternalOption option) {
615 toggled_into_fullscreen_ = true;
618 url = browser_->tab_strip_model()->GetActiveWebContents()->GetURL();
619 tab_fullscreen_accepted_ =
620 GetFullscreenSetting(url) == CONTENT_SETTING_ALLOW;
622 if (!extension_caused_fullscreen_.is_empty())
623 url = extension_caused_fullscreen_;
626 if (option == BROWSER)
627 content::RecordAction(UserMetricsAction("ToggleFullscreen"));
628 // TODO(scheib): Record metrics for WITH_CHROME, without counting transitions
629 // from tab fullscreen out to browser with chrome.
631 #if defined(OS_MACOSX)
632 if (option == BROWSER_WITH_CHROME) {
633 CHECK(chrome::mac::SupportsSystemFullscreen());
634 window_->EnterFullscreenWithChrome();
639 window_->EnterFullscreen(url, GetFullscreenExitBubbleType());
642 UpdateFullscreenExitBubbleContent();
644 // Once the window has become fullscreen it'll call back to
645 // WindowFullscreenStateChanged(). We don't do this immediately as
646 // BrowserWindow::EnterFullscreen() asks for bookmark_bar_state_, so we let
647 // the BrowserWindow invoke WindowFullscreenStateChanged when appropriate.
650 void FullscreenController::ExitFullscreenModeInternal() {
651 toggled_into_fullscreen_ = false;
652 #if defined(OS_MACOSX)
653 // Mac windows report a state change instantly, and so we must also clear
654 // state_prior_to_tab_fullscreen_ to match them else other logic using
655 // state_prior_to_tab_fullscreen_ will be incorrect.
656 NotifyTabOfExitIfNecessary();
658 window_->ExitFullscreen();
659 extension_caused_fullscreen_ = GURL();
661 UpdateFullscreenExitBubbleContent();
664 void FullscreenController::SetFullscreenedTab(WebContents* tab) {
665 fullscreened_tab_ = tab;
666 UpdateNotificationRegistrations();
669 void FullscreenController::SetMouseLockTab(WebContents* tab) {
670 mouse_lock_tab_ = tab;
671 UpdateNotificationRegistrations();
674 void FullscreenController::ExitTabFullscreenOrMouseLockIfNecessary() {
675 if (IsWindowFullscreenForTabOrPending())
676 ToggleFullscreenModeForTab(fullscreened_tab_, false);
678 NotifyTabOfExitIfNecessary();
681 void FullscreenController::UpdateFullscreenExitBubbleContent() {
682 GURL url = GetFullscreenExitBubbleURL();
683 FullscreenExitBubbleType bubble_type = GetFullscreenExitBubbleType();
685 // If bubble displays buttons, unlock mouse to allow pressing them.
686 if (fullscreen_bubble::ShowButtonsForType(bubble_type) && IsMouseLocked())
689 window_->UpdateFullscreenExitBubbleContent(url, bubble_type);
693 FullscreenController::GetFullscreenSetting(const GURL& url) const {
694 if (IsPrivilegedFullscreenForTab() || url.SchemeIsFile())
695 return CONTENT_SETTING_ALLOW;
697 return profile_->GetHostContentSettingsMap()->GetContentSetting(url, url,
698 CONTENT_SETTINGS_TYPE_FULLSCREEN, std::string());
702 FullscreenController::GetMouseLockSetting(const GURL& url) const {
703 if (IsPrivilegedFullscreenForTab() || url.SchemeIsFile())
704 return CONTENT_SETTING_ALLOW;
706 HostContentSettingsMap* settings_map = profile_->GetHostContentSettingsMap();
707 return settings_map->GetContentSetting(url, url,
708 CONTENT_SETTINGS_TYPE_MOUSELOCK, std::string());
711 bool FullscreenController::IsPrivilegedFullscreenForTab() const {
712 const bool embedded_widget_present =
714 fullscreened_tab_->GetFullscreenRenderWidgetHostView() &&
715 IsFullscreenWithinTabPossible();
716 return embedded_widget_present || is_privileged_fullscreen_for_testing_;
719 void FullscreenController::SetPrivilegedFullscreenForTesting(
720 bool is_privileged) {
721 is_privileged_fullscreen_for_testing_ = is_privileged;
724 bool FullscreenController::IsFullscreenWithinTabPossible() const {
725 return implicit_cast<const content::WebContentsDelegate*>(browser_)->
726 EmbedsFullscreenWidget();
729 bool FullscreenController::MaybeToggleFullscreenForCapturedTab(
730 WebContents* web_contents, bool enter_fullscreen) {
731 if (!IsFullscreenWithinTabPossible())
734 if (enter_fullscreen) {
735 if (web_contents->GetCapturerCount() > 0) {
736 FullscreenWithinTabHelper::CreateForWebContents(web_contents);
737 FullscreenWithinTabHelper::FromWebContents(web_contents)->
738 SetIsFullscreenForCapturedTab(true);
742 if (IsFullscreenForCapturedTab(web_contents)) {
743 FullscreenWithinTabHelper::RemoveForWebContents(web_contents);
751 bool FullscreenController::IsFullscreenForCapturedTab(
752 const WebContents* web_contents) const {
753 // Note: On Mac, some of the OnTabXXX() methods get called with a NULL value
754 // for web_contents. Check for that here.
755 const FullscreenWithinTabHelper* const helper = web_contents ?
756 FullscreenWithinTabHelper::FromWebContents(web_contents) : NULL;
757 if (helper && helper->is_fullscreen_for_captured_tab()) {
758 DCHECK(IsFullscreenWithinTabPossible());
759 DCHECK_NE(fullscreened_tab_, web_contents);
765 void FullscreenController::UnlockMouse() {
766 if (!mouse_lock_tab_)
768 content::RenderWidgetHostView* mouse_lock_view =
769 (fullscreened_tab_ == mouse_lock_tab_ && IsPrivilegedFullscreenForTab()) ?
770 mouse_lock_tab_->GetFullscreenRenderWidgetHostView() : NULL;
771 if (!mouse_lock_view) {
772 RenderViewHost* const rvh = mouse_lock_tab_->GetRenderViewHost();
774 mouse_lock_view = rvh->GetView();
777 mouse_lock_view->UnlockMouse();