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