OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 2011 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. | |
4 | |
5 #include "chrome/browser/ui/fullscreen_controller.h" | |
6 | |
7 #include "base/bind.h" | |
8 #include "base/command_line.h" | |
9 #include "chrome/browser/content_settings/host_content_settings_map.h" | |
10 #include "chrome/browser/profiles/profile.h" | |
11 #include "chrome/browser/ui/browser.h" | |
12 #include "chrome/browser/ui/browser_window.h" | |
13 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" | |
14 #include "chrome/common/chrome_notification_types.h" | |
15 #include "chrome/common/chrome_switches.h" | |
16 #include "content/browser/user_metrics.h" | |
17 #include "content/public/browser/notification_service.h" | |
18 | |
19 FullscreenController::FullscreenController(BrowserWindow* window, | |
20 Profile* profile, | |
21 Browser* browser) | |
22 : window_(window), | |
23 profile_(profile), | |
24 browser_(browser), | |
25 fullscreened_tab_(NULL), | |
26 tab_caused_fullscreen_(false), | |
27 tab_fullscreen_accepted_(false), | |
28 mouse_lock_state_(MOUSELOCK_NOT_REQUESTED) { | |
29 } | |
30 | |
31 FullscreenController::~FullscreenController() {} | |
32 | |
33 bool FullscreenController::IsFullscreenForTab() const { | |
34 return fullscreened_tab_ != NULL; | |
35 } | |
36 | |
37 bool FullscreenController::IsFullscreenForTab(const TabContents* tab) const { | |
38 const TabContentsWrapper* wrapper = | |
39 TabContentsWrapper::GetCurrentWrapperForContents(tab); | |
40 if (!wrapper || (wrapper != fullscreened_tab_)) | |
41 return false; | |
42 DCHECK(tab == browser_->GetSelectedTabContents()); | |
43 DCHECK(window_->IsFullscreen()); | |
44 return true; | |
45 } | |
46 | |
47 void FullscreenController::RequestToLockMouse(TabContents* tab) { | |
48 // Mouse Lock is only permitted when browser is in tab fullscreen. | |
49 if (!IsFullscreenForTab(tab)) { | |
50 tab->GotResponseToLockMouseRequest(false); | |
51 return; | |
52 } | |
53 | |
54 if (mouse_lock_state_ == MOUSELOCK_ACCEPTED) { | |
55 tab->GotResponseToLockMouseRequest(true); | |
56 return; | |
57 } | |
58 | |
59 switch (GetMouseLockSetting(tab->GetURL())) { | |
60 case CONTENT_SETTING_ALLOW: | |
61 mouse_lock_state_ = MOUSELOCK_ACCEPTED; | |
62 tab->GotResponseToLockMouseRequest(true); | |
63 break; | |
64 case CONTENT_SETTING_BLOCK: | |
65 mouse_lock_state_ = MOUSELOCK_NOT_REQUESTED; | |
66 tab->GotResponseToLockMouseRequest(false); | |
67 break; | |
68 case CONTENT_SETTING_ASK: | |
69 mouse_lock_state_ = MOUSELOCK_REQUESTED; | |
70 break; | |
71 default: | |
72 NOTREACHED(); | |
73 } | |
74 UpdateFullscreenExitBubbleContent(); | |
75 } | |
76 | |
77 void FullscreenController::ToggleFullscreenModeForTab(TabContents* tab, | |
78 bool enter_fullscreen) { | |
79 if (tab != browser_->GetSelectedTabContents()) | |
80 return; | |
81 | |
82 bool in_browser_or_tab_fullscreen_mode; | |
83 #if defined(OS_MACOSX) | |
84 in_browser_or_tab_fullscreen_mode = window_->InPresentationMode(); | |
85 #else | |
86 in_browser_or_tab_fullscreen_mode = window_->IsFullscreen(); | |
87 #endif | |
88 | |
89 if (enter_fullscreen) { | |
90 fullscreened_tab_ = TabContentsWrapper::GetCurrentWrapperForContents(tab); | |
91 if (!in_browser_or_tab_fullscreen_mode) { | |
92 tab_caused_fullscreen_ = true; | |
93 #if defined(OS_MACOSX) | |
94 TogglePresentationMode(true); | |
95 #else | |
96 ToggleFullscreenMode(true); | |
97 #endif | |
98 } else { | |
99 // We need to update the fullscreen exit bubble, e.g., going from browser | |
100 // fullscreen to tab fullscreen will need to show different content. | |
101 const GURL& url = tab->GetURL(); | |
102 if (!tab_fullscreen_accepted_) { | |
103 tab_fullscreen_accepted_ = | |
104 GetFullscreenSetting(url) == CONTENT_SETTING_ALLOW; | |
105 } | |
106 UpdateFullscreenExitBubbleContent(); | |
107 } | |
108 } else { | |
109 if (in_browser_or_tab_fullscreen_mode) { | |
110 if (tab_caused_fullscreen_) { | |
111 #if defined(OS_MACOSX) | |
112 TogglePresentationMode(true); | |
113 #else | |
114 ToggleFullscreenMode(true); | |
115 #endif | |
116 } else { | |
117 // If currently there is a tab in "tab fullscreen" mode and fullscreen | |
118 // was not caused by it (i.e., previously it was in "browser fullscreen" | |
119 // mode), we need to switch back to "browser fullscreen" mode. In this | |
120 // case, all we have to do is notifying the tab that it has exited "tab | |
121 // fullscreen" mode. | |
122 NotifyTabOfFullscreenExitIfNecessary(); | |
123 } | |
124 } | |
125 } | |
126 } | |
127 | |
128 #if defined(OS_MACOSX) | |
129 void FullscreenController::TogglePresentationMode(bool for_tab) { | |
130 bool entering_fullscreen = !window_->InPresentationMode(); | |
131 GURL url; | |
132 if (for_tab) { | |
133 url = browser_->GetSelectedTabContents()->GetURL(); | |
134 tab_fullscreen_accepted_ = entering_fullscreen && | |
135 GetFullscreenSetting(url) == CONTENT_SETTING_ALLOW; | |
136 } | |
137 if (entering_fullscreen) | |
138 window_->EnterPresentationMode(url, GetFullscreenExitBubbleType()); | |
139 else | |
140 window_->ExitPresentationMode(); | |
141 WindowFullscreenStateChanged(); | |
142 } | |
143 #endif | |
144 | |
145 // TODO(koz): Change |for_tab| to an enum. | |
146 void FullscreenController::ToggleFullscreenMode(bool for_tab) { | |
147 bool entering_fullscreen = !window_->IsFullscreen(); | |
148 | |
149 #if !defined(OS_MACOSX) | |
150 // In kiosk mode, we always want to be fullscreen. When the browser first | |
151 // starts we're not yet fullscreen, so let the initial toggle go through. | |
152 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kKioskMode) && | |
153 window_->IsFullscreen()) | |
154 return; | |
155 #endif | |
156 | |
157 GURL url; | |
158 if (for_tab) { | |
159 url = browser_->GetSelectedTabContents()->GetURL(); | |
160 tab_fullscreen_accepted_ = entering_fullscreen && | |
161 GetFullscreenSetting(url) == CONTENT_SETTING_ALLOW; | |
162 } else { | |
163 UserMetrics::RecordAction(UserMetricsAction("ToggleFullscreen")); | |
164 } | |
165 if (entering_fullscreen) | |
166 window_->EnterFullscreen(url, GetFullscreenExitBubbleType()); | |
167 else | |
168 window_->ExitFullscreen(); | |
169 | |
170 // Once the window has become fullscreen it'll call back to | |
171 // WindowFullscreenStateChanged(). We don't do this immediately as | |
172 // BrowserWindow::EnterFullscreen() asks for bookmark_bar_state_, so we let | |
173 // the BrowserWindow invoke WindowFullscreenStateChanged when appropriate. | |
174 | |
175 // TODO: convert mac to invoke WindowFullscreenStateChanged once it updates | |
176 // the necessary state of the frame. | |
177 #if defined(OS_MACOSX) | |
178 WindowFullscreenStateChanged(); | |
179 #endif | |
180 } | |
181 | |
182 void FullscreenController::LostMouseLock() { | |
183 mouse_lock_state_ = MOUSELOCK_NOT_REQUESTED; | |
184 UpdateFullscreenExitBubbleContent(); | |
185 } | |
186 | |
187 void FullscreenController::OnTabClosing(TabContents* tab_contents) { | |
188 if (IsFullscreenForTab(tab_contents)) { | |
189 ExitTabbedFullscreenModeIfNecessary(); | |
190 // The call to exit fullscreen may result in asynchronous notification of | |
191 // fullscreen state change (e.g., on Linux). We don't want to rely on it | |
192 // to call NotifyTabOfFullscreenExitIfNecessary(), because at that point | |
193 // |fullscreen_tab_| may not be valid. Instead, we call it here to clean up | |
194 // tab fullscreen related state. | |
195 NotifyTabOfFullscreenExitIfNecessary(); | |
196 } | |
197 } | |
198 | |
199 void FullscreenController::OnTabDeactivated(TabContentsWrapper* contents) { | |
200 if (contents == fullscreened_tab_) | |
201 ExitTabbedFullscreenModeIfNecessary(); | |
202 } | |
203 | |
204 void FullscreenController::OnAcceptFullscreenPermission( | |
205 const GURL& url, | |
206 FullscreenExitBubbleType bubble_type) { | |
207 bool mouse_lock = false; | |
208 bool fullscreen = false; | |
209 fullscreen_bubble::PermissionRequestedByType(bubble_type, &fullscreen, | |
210 &mouse_lock); | |
211 DCHECK(fullscreened_tab_); | |
212 DCHECK_NE(tab_fullscreen_accepted_, fullscreen); | |
213 | |
214 HostContentSettingsMap* settings_map = profile_->GetHostContentSettingsMap(); | |
215 if (mouse_lock) { | |
216 DCHECK_EQ(mouse_lock_state_, MOUSELOCK_REQUESTED); | |
217 settings_map->SetContentSetting(ContentSettingsPattern::FromURL(url), | |
218 ContentSettingsPattern::Wildcard(), CONTENT_SETTINGS_TYPE_MOUSELOCK, | |
219 std::string(), CONTENT_SETTING_ALLOW); | |
220 mouse_lock_state_ = | |
221 fullscreened_tab_->tab_contents()->GotResponseToLockMouseRequest(true) ? | |
222 MOUSELOCK_ACCEPTED : MOUSELOCK_NOT_REQUESTED; | |
223 } | |
224 if (!tab_fullscreen_accepted_) { | |
225 settings_map->SetContentSetting(ContentSettingsPattern::FromURL(url), | |
226 ContentSettingsPattern::Wildcard(), CONTENT_SETTINGS_TYPE_FULLSCREEN, | |
227 std::string(), CONTENT_SETTING_ALLOW); | |
228 tab_fullscreen_accepted_ = true; | |
229 } | |
230 UpdateFullscreenExitBubbleContent(); | |
231 } | |
232 | |
233 void FullscreenController::OnDenyFullscreenPermission( | |
234 FullscreenExitBubbleType bubble_type) { | |
235 bool mouse_lock = false; | |
236 bool fullscreen = false; | |
237 fullscreen_bubble::PermissionRequestedByType(bubble_type, &fullscreen, | |
238 &mouse_lock); | |
239 DCHECK(fullscreened_tab_); | |
240 DCHECK_NE(tab_fullscreen_accepted_, fullscreen); | |
241 | |
242 if (mouse_lock) { | |
243 DCHECK_EQ(mouse_lock_state_, MOUSELOCK_REQUESTED); | |
244 mouse_lock_state_ = MOUSELOCK_NOT_REQUESTED; | |
245 fullscreened_tab_->tab_contents()->GotResponseToLockMouseRequest(false); | |
246 if (!fullscreen) | |
247 UpdateFullscreenExitBubbleContent(); | |
248 } | |
249 | |
250 if (fullscreen) | |
251 ExitTabbedFullscreenModeIfNecessary(); | |
252 } | |
253 | |
254 void FullscreenController::WindowFullscreenStateChanged() { | |
255 MessageLoop::current()->PostTask(FROM_HERE, | |
256 base::Bind(&FullscreenController::NotifyFullscreenChange, this)); | |
sky
2011/12/08 23:34:13
I just came across this in tracking down a regress
koz (OOO until 15th September)
2011/12/08 23:45:39
This notification has always been async (see the d
| |
257 bool notify_tab_of_exit; | |
258 #if defined(OS_MACOSX) | |
259 notify_tab_of_exit = !window_->InPresentationMode(); | |
260 #else | |
261 notify_tab_of_exit = !window_->IsFullscreen(); | |
262 #endif | |
263 if (notify_tab_of_exit) | |
264 NotifyTabOfFullscreenExitIfNecessary(); | |
265 } | |
266 | |
267 bool FullscreenController::HandleUserPressedEscape() { | |
268 if (!IsFullscreenForTab()) | |
269 return false; | |
270 ExitTabbedFullscreenModeIfNecessary(); | |
271 return true; | |
272 } | |
273 | |
274 void FullscreenController::NotifyTabOfFullscreenExitIfNecessary() { | |
275 if (fullscreened_tab_) | |
276 fullscreened_tab_->ExitFullscreenMode(); | |
277 else | |
278 DCHECK_EQ(mouse_lock_state_, MOUSELOCK_NOT_REQUESTED); | |
279 | |
280 fullscreened_tab_ = NULL; | |
281 tab_caused_fullscreen_ = false; | |
282 tab_fullscreen_accepted_ = false; | |
283 mouse_lock_state_ = MOUSELOCK_NOT_REQUESTED; | |
284 | |
285 UpdateFullscreenExitBubbleContent(); | |
286 } | |
287 | |
288 void FullscreenController::ExitTabbedFullscreenModeIfNecessary() { | |
289 if (tab_caused_fullscreen_) | |
290 ToggleFullscreenMode(false); | |
291 else | |
292 NotifyTabOfFullscreenExitIfNecessary(); | |
293 } | |
294 | |
295 void FullscreenController::UpdateFullscreenExitBubbleContent() { | |
296 GURL url; | |
297 if (fullscreened_tab_) | |
298 url = fullscreened_tab_->tab_contents()->GetURL(); | |
299 | |
300 window_->UpdateFullscreenExitBubbleContent(url, | |
301 GetFullscreenExitBubbleType()); | |
302 } | |
303 | |
304 void FullscreenController::NotifyFullscreenChange() { | |
305 content::NotificationService::current()->Notify( | |
306 chrome::NOTIFICATION_FULLSCREEN_CHANGED, | |
307 content::Source<FullscreenController>(this), | |
308 content::NotificationService::NoDetails()); | |
309 } | |
310 | |
311 FullscreenExitBubbleType | |
312 FullscreenController::GetFullscreenExitBubbleType() const { | |
313 if (!fullscreened_tab_) { | |
314 DCHECK_EQ(MOUSELOCK_NOT_REQUESTED, mouse_lock_state_); | |
315 return FEB_TYPE_BROWSER_FULLSCREEN_EXIT_INSTRUCTION; | |
316 } | |
317 if (fullscreened_tab_ && !tab_fullscreen_accepted_) { | |
318 DCHECK_NE(MOUSELOCK_ACCEPTED, mouse_lock_state_); | |
319 return mouse_lock_state_ == MOUSELOCK_REQUESTED ? | |
320 FEB_TYPE_FULLSCREEN_MOUSELOCK_BUTTONS : FEB_TYPE_FULLSCREEN_BUTTONS; | |
321 } | |
322 if (mouse_lock_state_ == MOUSELOCK_REQUESTED) | |
323 return FEB_TYPE_MOUSELOCK_BUTTONS; | |
324 return mouse_lock_state_ == MOUSELOCK_ACCEPTED ? | |
325 FEB_TYPE_FULLSCREEN_MOUSELOCK_EXIT_INSTRUCTION : | |
326 FEB_TYPE_FULLSCREEN_EXIT_INSTRUCTION; | |
327 } | |
328 | |
329 ContentSetting | |
Peter Kasting
2011/11/21 19:17:46
Nit: Prefer to wrap these next two functions like:
| |
330 FullscreenController::GetFullscreenSetting(const GURL& url) const { | |
331 if (url.SchemeIsFile()) | |
332 return CONTENT_SETTING_ALLOW; | |
333 | |
334 return profile_->GetHostContentSettingsMap()->GetContentSetting(url, url, | |
335 CONTENT_SETTINGS_TYPE_FULLSCREEN, std::string()); | |
336 | |
Peter Kasting
2011/11/21 19:17:46
Nit: Extra blank line
| |
337 } | |
338 | |
339 ContentSetting | |
340 FullscreenController::GetMouseLockSetting(const GURL& url) const { | |
341 if (url.SchemeIsFile()) | |
342 return CONTENT_SETTING_ALLOW; | |
343 | |
344 HostContentSettingsMap* settings_map = profile_->GetHostContentSettingsMap(); | |
345 return settings_map->GetContentSetting(url, url, | |
346 CONTENT_SETTINGS_TYPE_MOUSELOCK, std::string()); | |
347 } | |
OLD | NEW |