Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / browser / ui / fullscreen / fullscreen_controller.cc
blob3754c80dfb6bebe366c7a228c5228c410e55fe26
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"
7 #include "base/bind.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/status_bubble.h"
19 #include "chrome/browser/ui/tabs/tab_strip_model.h"
20 #include "chrome/common/chrome_switches.h"
21 #include "content/public/browser/navigation_details.h"
22 #include "content/public/browser/navigation_entry.h"
23 #include "content/public/browser/notification_service.h"
24 #include "content/public/browser/render_view_host.h"
25 #include "content/public/browser/render_widget_host_view.h"
26 #include "content/public/browser/user_metrics.h"
27 #include "content/public/browser/web_contents.h"
28 #include "extensions/common/extension.h"
30 #if defined(OS_MACOSX)
31 #include "base/mac/mac_util.h"
32 #else
33 #include "base/prefs/pref_service.h"
34 #include "chrome/common/pref_names.h"
35 #endif
37 using base::UserMetricsAction;
38 using content::RenderViewHost;
39 using content::WebContents;
41 FullscreenController::FullscreenController(Browser* browser)
42 : browser_(browser),
43 window_(browser->window()),
44 profile_(browser->profile()),
45 fullscreened_tab_(NULL),
46 state_prior_to_tab_fullscreen_(STATE_INVALID),
47 tab_fullscreen_accepted_(false),
48 toggled_into_fullscreen_(false),
49 mouse_lock_tab_(NULL),
50 mouse_lock_state_(MOUSELOCK_NOT_REQUESTED),
51 reentrant_window_state_change_call_check_(false),
52 is_privileged_fullscreen_for_testing_(false),
53 ptr_factory_(this) {
54 DCHECK(window_);
55 DCHECK(profile_);
58 FullscreenController::~FullscreenController() {
61 bool FullscreenController::IsFullscreenForBrowser() const {
62 return window_->IsFullscreen() && !IsFullscreenCausedByTab();
65 void FullscreenController::ToggleFullscreenMode() {
66 extension_caused_fullscreen_ = GURL();
67 ToggleFullscreenModeInternal(BROWSER);
70 bool FullscreenController::IsFullscreenForTabOrPending() const {
71 return fullscreened_tab_ != NULL;
74 bool FullscreenController::IsFullscreenForTabOrPending(
75 const WebContents* web_contents) const {
76 if (web_contents != fullscreened_tab_)
77 return false;
78 DCHECK(web_contents == browser_->tab_strip_model()->GetActiveWebContents());
79 return true;
82 bool FullscreenController::IsFullscreenCausedByTab() const {
83 return state_prior_to_tab_fullscreen_ == STATE_NORMAL;
86 void FullscreenController::ToggleFullscreenModeForTab(WebContents* web_contents,
87 bool enter_fullscreen) {
88 if (fullscreened_tab_) {
89 if (web_contents != fullscreened_tab_)
90 return;
91 } else if (
92 web_contents != browser_->tab_strip_model()->GetActiveWebContents()) {
93 return;
95 if (IsFullscreenForTabOrPending() == enter_fullscreen)
96 return;
98 #if defined(OS_WIN)
99 // For now, avoid breaking when initiating full screen tab mode while in
100 // a metro snap.
101 // TODO(robertshield): Find a way to reconcile tab-initiated fullscreen
102 // modes with metro snap.
103 if (IsInMetroSnapMode())
104 return;
105 #endif
107 bool in_browser_or_tab_fullscreen_mode = window_->IsFullscreen();
108 bool window_is_fullscreen_with_chrome = false;
109 #if defined(OS_MACOSX)
110 window_is_fullscreen_with_chrome = window_->IsFullscreenWithChrome();
111 #endif
113 if (enter_fullscreen) {
114 SetFullscreenedTab(web_contents);
115 if (!in_browser_or_tab_fullscreen_mode) {
116 state_prior_to_tab_fullscreen_ = STATE_NORMAL;
117 ToggleFullscreenModeInternal(TAB);
118 } else if (window_is_fullscreen_with_chrome) {
119 #if defined(OS_MACOSX)
120 state_prior_to_tab_fullscreen_ = STATE_BROWSER_FULLSCREEN_WITH_CHROME;
121 EnterFullscreenModeInternal(TAB);
122 #else
123 NOTREACHED();
124 #endif
125 } else {
126 state_prior_to_tab_fullscreen_ = STATE_BROWSER_FULLSCREEN_NO_CHROME;
128 // We need to update the fullscreen exit bubble, e.g., going from browser
129 // fullscreen to tab fullscreen will need to show different content.
130 const GURL& url = web_contents->GetURL();
131 if (!tab_fullscreen_accepted_) {
132 tab_fullscreen_accepted_ =
133 GetFullscreenSetting(url) == CONTENT_SETTING_ALLOW;
135 UpdateFullscreenExitBubbleContent();
137 // This is only a change between Browser and Tab fullscreen. We generate
138 // a fullscreen notification now because there is no window change.
139 PostFullscreenChangeNotification(true);
141 } else {
142 if (in_browser_or_tab_fullscreen_mode) {
143 if (IsFullscreenCausedByTab()) {
144 ToggleFullscreenModeInternal(TAB);
145 } else {
146 #if defined(OS_MACOSX)
147 if (state_prior_to_tab_fullscreen_ ==
148 STATE_BROWSER_FULLSCREEN_WITH_CHROME) {
149 EnterFullscreenModeInternal(BROWSER_WITH_CHROME);
150 } else {
151 // Clear the bubble URL, which forces the Mac UI to redraw.
152 UpdateFullscreenExitBubbleContent();
154 #endif
155 // If currently there is a tab in "tab fullscreen" mode and fullscreen
156 // was not caused by it (i.e., previously it was in "browser fullscreen"
157 // mode), we need to switch back to "browser fullscreen" mode. In this
158 // case, all we have to do is notifying the tab that it has exited "tab
159 // fullscreen" mode.
160 NotifyTabOfExitIfNecessary();
162 // This is only a change between Browser and Tab fullscreen. We generate
163 // a fullscreen notification now because there is no window change.
164 PostFullscreenChangeNotification(true);
170 void FullscreenController::ToggleFullscreenModeWithExtension(
171 const GURL& extension_url) {
172 // |extension_caused_fullscreen_| will be reset if this causes fullscreen to
173 // exit.
174 extension_caused_fullscreen_ = extension_url;
175 ToggleFullscreenModeInternal(BROWSER);
178 bool FullscreenController::IsInMetroSnapMode() {
179 #if defined(OS_WIN)
180 return window_->IsInMetroSnapMode();
181 #else
182 return false;
183 #endif
186 #if defined(OS_WIN)
187 void FullscreenController::SetMetroSnapMode(bool enable) {
188 reentrant_window_state_change_call_check_ = false;
190 toggled_into_fullscreen_ = false;
191 window_->SetMetroSnapMode(enable);
193 // FullscreenController unit tests for metro snap assume that on Windows calls
194 // to WindowFullscreenStateChanged are reentrant. If that assumption is
195 // invalidated, the tests must be updated to maintain coverage.
196 CHECK(reentrant_window_state_change_call_check_);
198 #endif // defined(OS_WIN)
200 #if defined(OS_MACOSX)
201 void FullscreenController::ToggleFullscreenWithChrome() {
202 // This method cannot be called if simplified fullscreen is enabled.
203 const CommandLine* command_line = CommandLine::ForCurrentProcess();
204 DCHECK(!command_line->HasSwitch(switches::kEnableSimplifiedFullscreen));
205 ToggleFullscreenModeInternal(BROWSER_WITH_CHROME);
207 #endif
209 bool FullscreenController::IsMouseLockRequested() const {
210 return mouse_lock_state_ == MOUSELOCK_REQUESTED;
213 bool FullscreenController::IsMouseLocked() const {
214 return mouse_lock_state_ == MOUSELOCK_ACCEPTED ||
215 mouse_lock_state_ == MOUSELOCK_ACCEPTED_SILENTLY;
218 void FullscreenController::RequestToLockMouse(WebContents* web_contents,
219 bool user_gesture,
220 bool last_unlocked_by_target) {
221 DCHECK(!IsMouseLocked());
222 NotifyMouseLockChange();
224 // Must have a user gesture to prevent misbehaving sites from constantly
225 // re-locking the mouse. Exceptions are when the page has unlocked
226 // (i.e. not the user), or if we're in tab fullscreen (user gesture required
227 // for that)
228 if (!last_unlocked_by_target && !user_gesture &&
229 !IsFullscreenForTabOrPending(web_contents)) {
230 web_contents->GotResponseToLockMouseRequest(false);
231 return;
233 SetMouseLockTab(web_contents);
234 FullscreenExitBubbleType bubble_type = GetFullscreenExitBubbleType();
236 switch (GetMouseLockSetting(web_contents->GetURL())) {
237 case CONTENT_SETTING_ALLOW:
238 // If bubble already displaying buttons we must not lock the mouse yet,
239 // or it would prevent pressing those buttons. Instead, merge the request.
240 if (!IsPrivilegedFullscreenForTab() &&
241 fullscreen_bubble::ShowButtonsForType(bubble_type)) {
242 mouse_lock_state_ = MOUSELOCK_REQUESTED;
243 } else {
244 // Lock mouse.
245 if (web_contents->GotResponseToLockMouseRequest(true)) {
246 if (last_unlocked_by_target) {
247 mouse_lock_state_ = MOUSELOCK_ACCEPTED_SILENTLY;
248 } else {
249 mouse_lock_state_ = MOUSELOCK_ACCEPTED;
251 } else {
252 SetMouseLockTab(NULL);
253 mouse_lock_state_ = MOUSELOCK_NOT_REQUESTED;
256 break;
257 case CONTENT_SETTING_BLOCK:
258 web_contents->GotResponseToLockMouseRequest(false);
259 SetMouseLockTab(NULL);
260 mouse_lock_state_ = MOUSELOCK_NOT_REQUESTED;
261 break;
262 case CONTENT_SETTING_ASK:
263 mouse_lock_state_ = MOUSELOCK_REQUESTED;
264 break;
265 default:
266 NOTREACHED();
268 UpdateFullscreenExitBubbleContent();
271 void FullscreenController::OnTabDeactivated(WebContents* web_contents) {
272 if (web_contents == fullscreened_tab_ || web_contents == mouse_lock_tab_)
273 ExitTabFullscreenOrMouseLockIfNecessary();
276 void FullscreenController::OnTabClosing(WebContents* web_contents) {
277 if (web_contents == fullscreened_tab_ || web_contents == mouse_lock_tab_) {
278 ExitTabFullscreenOrMouseLockIfNecessary();
279 // The call to exit fullscreen may result in asynchronous notification of
280 // fullscreen state change (e.g., on Linux). We don't want to rely on it
281 // to call NotifyTabOfExitIfNecessary(), because at that point
282 // |fullscreened_tab_| may not be valid. Instead, we call it here to clean
283 // up tab fullscreen related state.
284 NotifyTabOfExitIfNecessary();
288 void FullscreenController::WindowFullscreenStateChanged() {
289 reentrant_window_state_change_call_check_ = true;
291 bool exiting_fullscreen = !window_->IsFullscreen();
293 PostFullscreenChangeNotification(!exiting_fullscreen);
294 if (exiting_fullscreen) {
295 toggled_into_fullscreen_ = false;
296 extension_caused_fullscreen_ = GURL();
297 NotifyTabOfExitIfNecessary();
299 if (exiting_fullscreen) {
300 window_->GetDownloadShelf()->Unhide();
301 } else {
302 window_->GetDownloadShelf()->Hide();
303 if (window_->GetStatusBubble())
304 window_->GetStatusBubble()->Hide();
308 bool FullscreenController::HandleUserPressedEscape() {
309 if (IsFullscreenForTabOrPending() ||
310 IsMouseLocked() || IsMouseLockRequested()) {
311 ExitTabFullscreenOrMouseLockIfNecessary();
312 return true;
315 return false;
318 void FullscreenController::ExitTabOrBrowserFullscreenToPreviousState() {
319 if (IsFullscreenForTabOrPending())
320 ExitTabFullscreenOrMouseLockIfNecessary();
321 else if (IsFullscreenForBrowser())
322 ExitFullscreenModeInternal();
325 void FullscreenController::OnAcceptFullscreenPermission() {
326 FullscreenExitBubbleType bubble_type = GetFullscreenExitBubbleType();
327 bool mouse_lock = false;
328 bool fullscreen = false;
329 fullscreen_bubble::PermissionRequestedByType(bubble_type, &fullscreen,
330 &mouse_lock);
331 DCHECK(!(fullscreen && tab_fullscreen_accepted_));
332 DCHECK(!(mouse_lock && IsMouseLocked()));
334 HostContentSettingsMap* settings_map = profile_->GetHostContentSettingsMap();
336 GURL url = GetFullscreenExitBubbleURL();
337 ContentSettingsPattern pattern = ContentSettingsPattern::FromURL(url);
339 if (mouse_lock && !IsMouseLocked()) {
340 DCHECK(IsMouseLockRequested());
341 // TODO(markusheintz): We should allow patterns for all possible URLs here.
342 if (pattern.IsValid()) {
343 settings_map->SetContentSetting(
344 pattern, ContentSettingsPattern::Wildcard(),
345 CONTENT_SETTINGS_TYPE_MOUSELOCK, std::string(),
346 CONTENT_SETTING_ALLOW);
349 if (mouse_lock_tab_ &&
350 mouse_lock_tab_->GotResponseToLockMouseRequest(true)) {
351 mouse_lock_state_ = MOUSELOCK_ACCEPTED;
352 } else {
353 mouse_lock_state_ = MOUSELOCK_NOT_REQUESTED;
354 SetMouseLockTab(NULL);
356 NotifyMouseLockChange();
359 if (fullscreen && !tab_fullscreen_accepted_) {
360 DCHECK(fullscreened_tab_);
361 if (pattern.IsValid()) {
362 settings_map->SetContentSetting(
363 pattern, ContentSettingsPattern::Wildcard(),
364 CONTENT_SETTINGS_TYPE_FULLSCREEN, std::string(),
365 CONTENT_SETTING_ALLOW);
367 tab_fullscreen_accepted_ = true;
369 UpdateFullscreenExitBubbleContent();
372 void FullscreenController::OnDenyFullscreenPermission() {
373 if (!fullscreened_tab_ && !mouse_lock_tab_)
374 return;
376 if (IsMouseLockRequested()) {
377 mouse_lock_state_ = MOUSELOCK_NOT_REQUESTED;
378 if (mouse_lock_tab_)
379 mouse_lock_tab_->GotResponseToLockMouseRequest(false);
380 SetMouseLockTab(NULL);
381 NotifyMouseLockChange();
383 // UpdateFullscreenExitBubbleContent() must be called, but to avoid
384 // duplicate calls we do so only if not adjusting the fullscreen state
385 // below, which also calls UpdateFullscreenExitBubbleContent().
386 if (!IsFullscreenForTabOrPending())
387 UpdateFullscreenExitBubbleContent();
390 if (IsFullscreenForTabOrPending())
391 ExitTabFullscreenOrMouseLockIfNecessary();
394 void FullscreenController::LostMouseLock() {
395 mouse_lock_state_ = MOUSELOCK_NOT_REQUESTED;
396 SetMouseLockTab(NULL);
397 NotifyMouseLockChange();
398 UpdateFullscreenExitBubbleContent();
401 void FullscreenController::Observe(int type,
402 const content::NotificationSource& source,
403 const content::NotificationDetails& details) {
404 switch (type) {
405 case content::NOTIFICATION_NAV_ENTRY_COMMITTED:
406 if (content::Details<content::LoadCommittedDetails>(details)->
407 is_navigation_to_different_page()) {
408 ExitTabFullscreenOrMouseLockIfNecessary();
410 break;
412 default:
413 NOTREACHED() << "Got a notification we didn't register for.";
417 GURL FullscreenController::GetFullscreenExitBubbleURL() const {
418 if (fullscreened_tab_)
419 return fullscreened_tab_->GetURL();
420 else if (mouse_lock_tab_)
421 return mouse_lock_tab_->GetURL();
422 else if (!extension_caused_fullscreen_.is_empty())
423 return extension_caused_fullscreen_;
424 else
425 return GURL();
428 FullscreenExitBubbleType FullscreenController::GetFullscreenExitBubbleType()
429 const {
430 // In kiosk and exclusive app mode we always want to be fullscreen and do not
431 // want to show exit instructions for browser mode fullscreen.
432 bool app_mode = false;
433 #if !defined(OS_MACOSX) // App mode (kiosk) is not available on Mac yet.
434 app_mode = chrome::IsRunningInAppMode();
435 #endif
437 if (mouse_lock_state_ == MOUSELOCK_ACCEPTED_SILENTLY) {
438 return FEB_TYPE_NONE;
441 if (fullscreened_tab_) {
442 if (tab_fullscreen_accepted_) {
443 if (IsPrivilegedFullscreenForTab()) {
444 return FEB_TYPE_NONE;
445 } else if (IsMouseLocked()) {
446 return FEB_TYPE_FULLSCREEN_MOUSELOCK_EXIT_INSTRUCTION;
447 } else if (IsMouseLockRequested()) {
448 return FEB_TYPE_MOUSELOCK_BUTTONS;
449 } else {
450 return FEB_TYPE_FULLSCREEN_EXIT_INSTRUCTION;
452 } else { // Full screen not yet accepted.
453 if (IsMouseLockRequested()) {
454 return FEB_TYPE_FULLSCREEN_MOUSELOCK_BUTTONS;
455 } else {
456 return FEB_TYPE_FULLSCREEN_BUTTONS;
459 } else { // Not tab full screen.
460 if (IsMouseLocked()) {
461 return FEB_TYPE_MOUSELOCK_EXIT_INSTRUCTION;
462 } else if (IsMouseLockRequested()) {
463 return FEB_TYPE_MOUSELOCK_BUTTONS;
464 } else {
465 if (!extension_caused_fullscreen_.is_empty()) {
466 return FEB_TYPE_BROWSER_EXTENSION_FULLSCREEN_EXIT_INSTRUCTION;
467 } else if (toggled_into_fullscreen_ && !app_mode) {
468 return FEB_TYPE_BROWSER_FULLSCREEN_EXIT_INSTRUCTION;
469 } else {
470 return FEB_TYPE_NONE;
474 NOTREACHED();
475 return FEB_TYPE_NONE;
478 void FullscreenController::UpdateNotificationRegistrations() {
479 if (fullscreened_tab_ && mouse_lock_tab_)
480 DCHECK(fullscreened_tab_ == mouse_lock_tab_);
482 WebContents* tab = fullscreened_tab_ ? fullscreened_tab_ : mouse_lock_tab_;
484 if (tab && registrar_.IsEmpty()) {
485 registrar_.Add(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED,
486 content::Source<content::NavigationController>(&tab->GetController()));
487 } else if (!tab && !registrar_.IsEmpty()) {
488 registrar_.RemoveAll();
492 void FullscreenController::PostFullscreenChangeNotification(
493 bool is_fullscreen) {
494 base::MessageLoop::current()->PostTask(
495 FROM_HERE,
496 base::Bind(&FullscreenController::NotifyFullscreenChange,
497 ptr_factory_.GetWeakPtr(),
498 is_fullscreen));
501 void FullscreenController::NotifyFullscreenChange(bool is_fullscreen) {
502 content::NotificationService::current()->Notify(
503 chrome::NOTIFICATION_FULLSCREEN_CHANGED,
504 content::Source<FullscreenController>(this),
505 content::Details<bool>(&is_fullscreen));
508 void FullscreenController::NotifyTabOfExitIfNecessary() {
509 if (fullscreened_tab_) {
510 RenderViewHost* rvh = fullscreened_tab_->GetRenderViewHost();
511 SetFullscreenedTab(NULL);
512 state_prior_to_tab_fullscreen_ = STATE_INVALID;
513 tab_fullscreen_accepted_ = false;
514 if (rvh)
515 rvh->ExitFullscreen();
518 if (mouse_lock_tab_) {
519 if (IsMouseLockRequested()) {
520 mouse_lock_tab_->GotResponseToLockMouseRequest(false);
521 NotifyMouseLockChange();
522 } else {
523 UnlockMouse();
525 SetMouseLockTab(NULL);
526 mouse_lock_state_ = MOUSELOCK_NOT_REQUESTED;
529 UpdateFullscreenExitBubbleContent();
532 void FullscreenController::NotifyMouseLockChange() {
533 content::NotificationService::current()->Notify(
534 chrome::NOTIFICATION_MOUSE_LOCK_CHANGED,
535 content::Source<FullscreenController>(this),
536 content::NotificationService::NoDetails());
539 void FullscreenController::ToggleFullscreenModeInternal(
540 FullscreenInternalOption option) {
541 #if defined(OS_WIN)
542 // When in Metro snap mode, toggling in and out of fullscreen is prevented.
543 if (IsInMetroSnapMode())
544 return;
545 #endif
547 bool enter_fullscreen = !window_->IsFullscreen();
548 #if defined(OS_MACOSX)
549 // When a Mac user requests a toggle they may be toggling between
550 // FullscreenWithoutChrome and FullscreenWithChrome.
551 if (!IsFullscreenForTabOrPending()) {
552 if (option == BROWSER_WITH_CHROME)
553 enter_fullscreen |= window_->IsFullscreenWithoutChrome();
554 else
555 enter_fullscreen |= window_->IsFullscreenWithChrome();
557 #endif
559 // In kiosk mode, we always want to be fullscreen. When the browser first
560 // starts we're not yet fullscreen, so let the initial toggle go through.
561 if (chrome::IsRunningInAppMode() && window_->IsFullscreen())
562 return;
564 #if !defined(OS_MACOSX)
565 // Do not enter fullscreen mode if disallowed by pref. This prevents the user
566 // from manually entering fullscreen mode and also disables kiosk mode on
567 // desktop platforms.
568 if (enter_fullscreen &&
569 !profile_->GetPrefs()->GetBoolean(prefs::kFullscreenAllowed)) {
570 return;
572 #endif
574 if (enter_fullscreen)
575 EnterFullscreenModeInternal(option);
576 else
577 ExitFullscreenModeInternal();
580 void FullscreenController::EnterFullscreenModeInternal(
581 FullscreenInternalOption option) {
582 toggled_into_fullscreen_ = true;
583 GURL url;
584 if (option == TAB) {
585 url = browser_->tab_strip_model()->GetActiveWebContents()->GetURL();
586 tab_fullscreen_accepted_ =
587 GetFullscreenSetting(url) == CONTENT_SETTING_ALLOW;
588 } else {
589 if (!extension_caused_fullscreen_.is_empty())
590 url = extension_caused_fullscreen_;
593 if (option == BROWSER)
594 content::RecordAction(UserMetricsAction("ToggleFullscreen"));
595 // TODO(scheib): Record metrics for WITH_CHROME, without counting transitions
596 // from tab fullscreen out to browser with chrome.
598 #if defined(OS_MACOSX)
599 if (option == BROWSER_WITH_CHROME) {
600 CHECK(chrome::mac::SupportsSystemFullscreen());
601 window_->EnterFullscreenWithChrome();
602 } else {
603 #else
605 #endif
606 window_->EnterFullscreen(url, GetFullscreenExitBubbleType());
609 UpdateFullscreenExitBubbleContent();
611 // Once the window has become fullscreen it'll call back to
612 // WindowFullscreenStateChanged(). We don't do this immediately as
613 // BrowserWindow::EnterFullscreen() asks for bookmark_bar_state_, so we let
614 // the BrowserWindow invoke WindowFullscreenStateChanged when appropriate.
617 void FullscreenController::ExitFullscreenModeInternal() {
618 toggled_into_fullscreen_ = false;
619 #if defined(OS_MACOSX)
620 // Mac windows report a state change instantly, and so we must also clear
621 // state_prior_to_tab_fullscreen_ to match them else other logic using
622 // state_prior_to_tab_fullscreen_ will be incorrect.
623 NotifyTabOfExitIfNecessary();
624 #endif
625 window_->ExitFullscreen();
626 extension_caused_fullscreen_ = GURL();
628 UpdateFullscreenExitBubbleContent();
631 void FullscreenController::SetFullscreenedTab(WebContents* tab) {
632 fullscreened_tab_ = tab;
633 UpdateNotificationRegistrations();
636 void FullscreenController::SetMouseLockTab(WebContents* tab) {
637 mouse_lock_tab_ = tab;
638 UpdateNotificationRegistrations();
641 void FullscreenController::ExitTabFullscreenOrMouseLockIfNecessary() {
642 if (IsFullscreenForTabOrPending())
643 ToggleFullscreenModeForTab(fullscreened_tab_, false);
644 else
645 NotifyTabOfExitIfNecessary();
648 void FullscreenController::UpdateFullscreenExitBubbleContent() {
649 GURL url = GetFullscreenExitBubbleURL();
650 FullscreenExitBubbleType bubble_type = GetFullscreenExitBubbleType();
652 // If bubble displays buttons, unlock mouse to allow pressing them.
653 if (fullscreen_bubble::ShowButtonsForType(bubble_type) && IsMouseLocked())
654 UnlockMouse();
656 window_->UpdateFullscreenExitBubbleContent(url, bubble_type);
659 ContentSetting
660 FullscreenController::GetFullscreenSetting(const GURL& url) const {
661 if (IsPrivilegedFullscreenForTab() || url.SchemeIsFile())
662 return CONTENT_SETTING_ALLOW;
664 return profile_->GetHostContentSettingsMap()->GetContentSetting(url, url,
665 CONTENT_SETTINGS_TYPE_FULLSCREEN, std::string());
668 ContentSetting
669 FullscreenController::GetMouseLockSetting(const GURL& url) const {
670 if (IsPrivilegedFullscreenForTab() || url.SchemeIsFile())
671 return CONTENT_SETTING_ALLOW;
673 HostContentSettingsMap* settings_map = profile_->GetHostContentSettingsMap();
674 return settings_map->GetContentSetting(url, url,
675 CONTENT_SETTINGS_TYPE_MOUSELOCK, std::string());
678 bool FullscreenController::IsPrivilegedFullscreenForTab() const {
679 const bool embedded_widget_present =
680 fullscreened_tab_ &&
681 fullscreened_tab_->GetFullscreenRenderWidgetHostView() &&
682 implicit_cast<const content::WebContentsDelegate*>(browser_)->
683 EmbedsFullscreenWidget();
684 return embedded_widget_present || is_privileged_fullscreen_for_testing_;
687 void FullscreenController::SetPrivilegedFullscreenForTesting(
688 bool is_privileged) {
689 is_privileged_fullscreen_for_testing_ = is_privileged;
692 void FullscreenController::UnlockMouse() {
693 if (!mouse_lock_tab_)
694 return;
695 content::RenderWidgetHostView* mouse_lock_view =
696 (fullscreened_tab_ == mouse_lock_tab_ && IsPrivilegedFullscreenForTab()) ?
697 mouse_lock_tab_->GetFullscreenRenderWidgetHostView() : NULL;
698 if (!mouse_lock_view) {
699 RenderViewHost* const rvh = mouse_lock_tab_->GetRenderViewHost();
700 if (rvh)
701 mouse_lock_view = rvh->GetView();
703 if (mouse_lock_view)
704 mouse_lock_view->UnlockMouse();