OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ui/views/controls/webview/webview.h" | 5 #include "ui/views/controls/webview/webview.h" |
6 | 6 |
7 #include "content/public/browser/browser_accessibility_state.h" | 7 #include "content/public/browser/browser_accessibility_state.h" |
8 #include "content/public/browser/browser_context.h" | 8 #include "content/public/browser/browser_context.h" |
9 #include "content/public/browser/navigation_controller.h" | 9 #include "content/public/browser/navigation_controller.h" |
10 #include "content/public/browser/notification_details.h" | 10 #include "content/public/browser/notification_details.h" |
11 #include "content/public/browser/notification_registrar.h" | 11 #include "content/public/browser/notification_registrar.h" |
12 #include "content/public/browser/notification_source.h" | 12 #include "content/public/browser/notification_source.h" |
13 #include "content/public/browser/notification_types.h" | 13 #include "content/public/browser/notification_types.h" |
14 #include "content/public/browser/render_view_host.h" | 14 #include "content/public/browser/render_view_host.h" |
15 #include "content/public/browser/render_widget_host_view.h" | 15 #include "content/public/browser/render_widget_host_view.h" |
16 #include "content/public/browser/web_contents.h" | 16 #include "content/public/browser/web_contents.h" |
17 #include "content/public/browser/web_contents_observer.h" | |
17 #include "content/public/browser/web_contents_view.h" | 18 #include "content/public/browser/web_contents_view.h" |
18 #include "ipc/ipc_message.h" | 19 #include "ipc/ipc_message.h" |
19 #include "ui/base/accessibility/accessibility_types.h" | 20 #include "ui/base/accessibility/accessibility_types.h" |
20 #include "ui/base/accessibility/accessible_view_state.h" | 21 #include "ui/base/accessibility/accessible_view_state.h" |
21 #include "ui/base/events/event.h" | 22 #include "ui/base/events/event.h" |
22 #include "ui/views/accessibility/native_view_accessibility.h" | 23 #include "ui/views/accessibility/native_view_accessibility.h" |
23 #include "ui/views/controls/native/native_view_host.h" | 24 #include "ui/views/controls/native/native_view_host.h" |
24 #include "ui/views/focus/focus_manager.h" | 25 #include "ui/views/focus/focus_manager.h" |
25 #include "ui/views/views_delegate.h" | 26 #include "ui/views/views_delegate.h" |
26 | 27 |
27 namespace views { | 28 namespace views { |
28 | 29 |
29 // static | 30 // static |
30 const char WebView::kViewClassName[] = "WebView"; | 31 const char WebView::kViewClassName[] = "WebView"; |
31 | 32 |
33 class WebView::FullscreenObserver : public content::WebContentsObserver { | |
sky
2013/09/10 19:38:58
Add a description.
Is there a particular reason y
miu
2013/09/11 03:57:03
Done, and also for its "cousin" in the Mac cocoa U
| |
34 public: | |
35 explicit FullscreenObserver(WebView* view) : view_(view) {} | |
36 | |
37 void Observe(content::WebContents* new_web_contents) { | |
38 WebContentsObserver::Observe(new_web_contents); | |
39 } | |
40 | |
41 virtual void DidShowFullscreenWidget(int routing_id) OVERRIDE { | |
42 view_->ReattachForFullscreenChange(true); | |
43 } | |
44 | |
45 virtual void DidDestroyFullscreenWidget(int routing_id) OVERRIDE { | |
46 view_->ReattachForFullscreenChange(false); | |
47 } | |
48 | |
49 private: | |
50 WebView* const view_; | |
sky
2013/09/10 19:38:58
members at the end of a section.
miu
2013/09/11 03:57:03
Done.
| |
51 | |
52 // Workaround for MSVC++ linker bug/feature that requires | |
53 // instantiation of the inline IPC::Listener methods in all translation units. | |
54 virtual void OnChannelConnected(int32 peer_id) OVERRIDE {} | |
55 virtual void OnChannelError() OVERRIDE {} | |
56 }; | |
sky
2013/09/10 19:38:58
DISALLOW...
miu
2013/09/11 03:57:03
Done.
| |
57 | |
32 //////////////////////////////////////////////////////////////////////////////// | 58 //////////////////////////////////////////////////////////////////////////////// |
33 // WebView, public: | 59 // WebView, public: |
34 | 60 |
35 WebView::WebView(content::BrowserContext* browser_context) | 61 WebView::WebView(content::BrowserContext* browser_context) |
36 : wcv_holder_(new NativeViewHost), | 62 : wcv_holder_(new NativeViewHost), |
37 web_contents_(NULL), | 63 web_contents_(NULL), |
64 is_embedding_fullscreen_widget_(false), | |
38 browser_context_(browser_context), | 65 browser_context_(browser_context), |
39 allow_accelerators_(false) { | 66 allow_accelerators_(false) { |
40 AddChildView(wcv_holder_); | 67 AddChildView(wcv_holder_); |
41 NativeViewAccessibility::RegisterWebView(this); | 68 NativeViewAccessibility::RegisterWebView(this); |
42 } | 69 } |
43 | 70 |
44 WebView::~WebView() { | 71 WebView::~WebView() { |
45 NativeViewAccessibility::UnregisterWebView(this); | 72 NativeViewAccessibility::UnregisterWebView(this); |
46 } | 73 } |
47 | 74 |
48 content::WebContents* WebView::GetWebContents() { | 75 content::WebContents* WebView::GetWebContents() { |
49 CreateWebContentsWithSiteInstance(NULL); | 76 CreateWebContentsWithSiteInstance(NULL); |
50 return web_contents_; | 77 return web_contents_; |
51 } | 78 } |
52 | 79 |
53 void WebView::CreateWebContentsWithSiteInstance( | 80 void WebView::CreateWebContentsWithSiteInstance( |
54 content::SiteInstance* site_instance) { | 81 content::SiteInstance* site_instance) { |
55 if (!web_contents_) { | 82 if (!web_contents_) { |
56 wc_owner_.reset(CreateWebContents(browser_context_, site_instance)); | 83 wc_owner_.reset(CreateWebContents(browser_context_, site_instance)); |
57 web_contents_ = wc_owner_.get(); | 84 web_contents_ = wc_owner_.get(); |
58 web_contents_->SetDelegate(this); | 85 web_contents_->SetDelegate(this); |
59 AttachWebContents(); | 86 AttachWebContents(); |
60 } | 87 } |
61 } | 88 } |
62 | 89 |
63 void WebView::SetWebContents(content::WebContents* web_contents) { | 90 void WebView::SetWebContents(content::WebContents* web_contents) { |
64 if (web_contents == web_contents_) | 91 if (web_contents == web_contents_) |
65 return; | 92 return; |
66 DetachWebContents(); | 93 DetachWebContents(); |
67 wc_owner_.reset(); | 94 if (wc_owner_ != web_contents) |
95 wc_owner_.reset(); | |
68 web_contents_ = web_contents; | 96 web_contents_ = web_contents; |
97 if (fullscreen_observer_) { | |
98 fullscreen_observer_->Observe(web_contents_); | |
99 is_embedding_fullscreen_widget_ = | |
100 web_contents_ && web_contents_->GetFullscreenRenderWidgetHostView(); | |
101 } else { | |
102 is_embedding_fullscreen_widget_ = false; | |
103 } | |
69 AttachWebContents(); | 104 AttachWebContents(); |
70 } | 105 } |
71 | 106 |
107 void WebView::SetEmbedFullscreenWidgetMode(bool enable) { | |
108 bool should_be_embedded = enable; | |
109 if (!fullscreen_observer_ && enable) { | |
110 DCHECK(!is_embedding_fullscreen_widget_); | |
111 fullscreen_observer_.reset(new FullscreenObserver(this)); | |
112 fullscreen_observer_->Observe(web_contents_); | |
113 should_be_embedded = | |
114 web_contents_ && web_contents_->GetFullscreenRenderWidgetHostView(); | |
115 } else if (fullscreen_observer_ && !enable) { | |
116 fullscreen_observer_.reset(); | |
117 } | |
118 if (should_be_embedded != is_embedding_fullscreen_widget_) | |
119 ReattachForFullscreenChange(should_be_embedded); | |
120 } | |
121 | |
72 void WebView::LoadInitialURL(const GURL& url) { | 122 void WebView::LoadInitialURL(const GURL& url) { |
73 GetWebContents()->GetController().LoadURL( | 123 GetWebContents()->GetController().LoadURL( |
74 url, content::Referrer(), content::PAGE_TRANSITION_AUTO_TOPLEVEL, | 124 url, content::Referrer(), content::PAGE_TRANSITION_AUTO_TOPLEVEL, |
75 std::string()); | 125 std::string()); |
76 } | 126 } |
77 | 127 |
78 void WebView::SetFastResize(bool fast_resize) { | 128 void WebView::SetFastResize(bool fast_resize) { |
79 wcv_holder_->set_fast_resize(fast_resize); | 129 wcv_holder_->set_fast_resize(fast_resize); |
80 } | 130 } |
81 | 131 |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
119 return web_contents_ && !web_contents_->IsCrashed(); | 169 return web_contents_ && !web_contents_->IsCrashed(); |
120 } | 170 } |
121 | 171 |
122 bool WebView::IsFocusable() const { | 172 bool WebView::IsFocusable() const { |
123 // We need to be focusable when our contents is not a view hierarchy, as | 173 // We need to be focusable when our contents is not a view hierarchy, as |
124 // clicking on the contents needs to focus us. | 174 // clicking on the contents needs to focus us. |
125 return !!web_contents_; | 175 return !!web_contents_; |
126 } | 176 } |
127 | 177 |
128 void WebView::OnFocus() { | 178 void WebView::OnFocus() { |
129 if (web_contents_) | 179 if (!web_contents_) |
180 return; | |
181 if (is_embedding_fullscreen_widget_) { | |
182 content::RenderWidgetHostView* const current_fs_view = | |
183 web_contents_->GetFullscreenRenderWidgetHostView(); | |
184 if (current_fs_view) | |
185 current_fs_view->GetRenderWidgetHost()->Focus(); | |
186 } else { | |
130 web_contents_->GetView()->Focus(); | 187 web_contents_->GetView()->Focus(); |
188 } | |
131 } | 189 } |
132 | 190 |
133 void WebView::AboutToRequestFocusFromTabTraversal(bool reverse) { | 191 void WebView::AboutToRequestFocusFromTabTraversal(bool reverse) { |
134 if (web_contents_) | 192 if (web_contents_) |
135 web_contents_->FocusThroughTabTraversal(reverse); | 193 web_contents_->FocusThroughTabTraversal(reverse); |
136 } | 194 } |
137 | 195 |
138 void WebView::GetAccessibleState(ui::AccessibleViewState* state) { | 196 void WebView::GetAccessibleState(ui::AccessibleViewState* state) { |
139 state->role = ui::AccessibilityTypes::ROLE_GROUPING; | 197 state->role = ui::AccessibilityTypes::ROLE_GROUPING; |
140 } | 198 } |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
179 | 237 |
180 //////////////////////////////////////////////////////////////////////////////// | 238 //////////////////////////////////////////////////////////////////////////////// |
181 // WebView, content::WebContentsDelegate implementation: | 239 // WebView, content::WebContentsDelegate implementation: |
182 | 240 |
183 void WebView::WebContentsFocused(content::WebContents* web_contents) { | 241 void WebView::WebContentsFocused(content::WebContents* web_contents) { |
184 DCHECK(wc_owner_.get()); | 242 DCHECK(wc_owner_.get()); |
185 // The WebView is only the delegate of WebContentses it creates itself. | 243 // The WebView is only the delegate of WebContentses it creates itself. |
186 OnWebContentsFocused(web_contents_); | 244 OnWebContentsFocused(web_contents_); |
187 } | 245 } |
188 | 246 |
247 bool WebView::EmbedsFullscreenWidget() const { | |
248 DCHECK(wc_owner_.get()); | |
249 return !!fullscreen_observer_; | |
250 } | |
251 | |
189 //////////////////////////////////////////////////////////////////////////////// | 252 //////////////////////////////////////////////////////////////////////////////// |
190 // WebView, private: | 253 // WebView, private: |
191 | 254 |
192 void WebView::AttachWebContents() { | 255 void WebView::AttachWebContents() { |
193 // Prevents attachment if the WebView isn't already in a Widget, or it's | 256 // Prevents attachment if the WebView isn't already in a Widget, or it's |
194 // already attached. | 257 // already attached. |
195 if (!GetWidget() || !web_contents_ || | 258 if (!GetWidget() || !web_contents_) |
196 wcv_holder_->native_view() == web_contents_->GetView()->GetNativeView()) { | |
197 return; | 259 return; |
260 | |
261 const gfx::NativeView view_to_attach = is_embedding_fullscreen_widget_ ? | |
262 web_contents_->GetFullscreenRenderWidgetHostView()->GetNativeView() : | |
263 web_contents_->GetView()->GetNativeView(); | |
264 if (wcv_holder_->native_view() == view_to_attach) | |
265 return; | |
266 wcv_holder_->Attach(view_to_attach); | |
267 | |
268 // The view will not be focused automatically when it is attached, so we need | |
269 // to pass on focus to it if the FocusManager thinks the view is focused. Note | |
270 // that not every Widget has a focus manager. | |
271 FocusManager* focus_manager = GetFocusManager(); | |
272 if (focus_manager && focus_manager->GetFocusedView() == this) { | |
273 if (is_embedding_fullscreen_widget_) | |
274 web_contents_->GetFullscreenRenderWidgetHostView()->Focus(); | |
275 else | |
276 web_contents_->GetView()->Focus(); | |
198 } | 277 } |
199 | 278 |
200 if (web_contents_) { | 279 registrar_.Add( |
201 wcv_holder_->Attach(web_contents_->GetView()->GetNativeView()); | 280 this, |
202 | 281 content::NOTIFICATION_RENDER_VIEW_HOST_CHANGED, |
203 // The WebContentsView will not be focused automatically when it is | 282 content::Source<content::NavigationController>( |
204 // attached, so we need to pass on focus to it if the FocusManager thinks | 283 &web_contents_->GetController())); |
205 // the WebView is focused. Note that not every Widget has a focus manager. | 284 registrar_.Add( |
206 FocusManager* focus_manager = GetFocusManager(); | 285 this, |
207 if (focus_manager && focus_manager->GetFocusedView() == this) | 286 content::NOTIFICATION_WEB_CONTENTS_DESTROYED, |
208 web_contents_->GetView()->Focus(); | 287 content::Source<content::WebContents>(web_contents_)); |
209 | |
210 registrar_.Add( | |
211 this, | |
212 content::NOTIFICATION_RENDER_VIEW_HOST_CHANGED, | |
213 content::Source<content::NavigationController>( | |
214 &web_contents_->GetController())); | |
215 registrar_.Add( | |
216 this, | |
217 content::NOTIFICATION_WEB_CONTENTS_DESTROYED, | |
218 content::Source<content::WebContents>(web_contents_)); | |
219 } | |
220 | 288 |
221 #if defined(OS_WIN) && defined(USE_AURA) | 289 #if defined(OS_WIN) && defined(USE_AURA) |
222 web_contents_->SetParentNativeViewAccessible( | 290 if (!is_embedding_fullscreen_widget_) { |
223 parent()->GetNativeViewAccessible()); | 291 web_contents_->SetParentNativeViewAccessible( |
292 parent()->GetNativeViewAccessible()); | |
293 } | |
224 #endif | 294 #endif |
225 } | 295 } |
226 | 296 |
227 void WebView::DetachWebContents() { | 297 void WebView::DetachWebContents() { |
228 if (web_contents_) { | 298 if (web_contents_) { |
229 wcv_holder_->Detach(); | 299 wcv_holder_->Detach(); |
230 #if defined(OS_WIN) && !defined(USE_AURA) | 300 #if defined(OS_WIN) |
231 // TODO(beng): This should either not be necessary, or be done implicitly by | 301 if (!is_embedding_fullscreen_widget_) { |
232 // NativeViewHostWin on Detach(). As it stands, this is needed so that the | 302 #if !defined(USE_AURA) |
233 // view of the detached contents knows to tell the renderer it's been | 303 // TODO(beng): This should either not be necessary, or be done implicitly |
234 // hidden. | 304 // by NativeViewHostWin on Detach(). As it stands, this is needed so that |
235 // | 305 // the of the detached contents knows to tell the renderer it's been |
236 // Moving this out of here would also mean we wouldn't be potentially | 306 // hidden. |
237 // calling member functions on a half-destroyed WebContents. | 307 // |
238 ShowWindow(web_contents_->GetView()->GetNativeView(), SW_HIDE); | 308 // Moving this out of here would also mean we wouldn't be potentially |
239 #elif defined(OS_WIN) && defined(USE_AURA) | 309 // calling member functions on a half-destroyed WebContents. |
240 web_contents_->SetParentNativeViewAccessible(NULL); | 310 ShowWindow(web_contents_->GetView()->GetNativeView(), SW_HIDE); |
311 #else | |
312 web_contents_->SetParentNativeViewAccessible(NULL); | |
313 #endif | |
314 } | |
241 #endif | 315 #endif |
242 } | 316 } |
243 registrar_.RemoveAll(); | 317 registrar_.RemoveAll(); |
244 } | 318 } |
245 | 319 |
320 void WebView::ReattachForFullscreenChange(bool enter_fullscreen) { | |
321 DetachWebContents(); | |
322 is_embedding_fullscreen_widget_ = enter_fullscreen && | |
323 web_contents_ && web_contents_->GetFullscreenRenderWidgetHostView(); | |
324 AttachWebContents(); | |
325 } | |
326 | |
246 void WebView::RenderViewHostChanged(content::RenderViewHost* old_host, | 327 void WebView::RenderViewHostChanged(content::RenderViewHost* old_host, |
247 content::RenderViewHost* new_host) { | 328 content::RenderViewHost* new_host) { |
248 if (GetFocusManager()->GetFocusedView() == this) | 329 if (GetFocusManager()->GetFocusedView() == this) |
249 web_contents_->GetView()->Focus(); | 330 web_contents_->GetView()->Focus(); |
250 } | 331 } |
251 | 332 |
252 void WebView::WebContentsDestroyed(content::WebContents* web_contents) { | 333 void WebView::WebContentsDestroyed(content::WebContents* web_contents) { |
253 DCHECK(web_contents == web_contents_); | 334 DCHECK(web_contents == web_contents_); |
254 SetWebContents(NULL); | 335 SetWebContents(NULL); |
255 } | 336 } |
(...skipping 10 matching lines...) Expand all Loading... | |
266 if (!contents) { | 347 if (!contents) { |
267 content::WebContents::CreateParams create_params( | 348 content::WebContents::CreateParams create_params( |
268 browser_context, site_instance); | 349 browser_context, site_instance); |
269 return content::WebContents::Create(create_params); | 350 return content::WebContents::Create(create_params); |
270 } | 351 } |
271 | 352 |
272 return contents; | 353 return contents; |
273 } | 354 } |
274 | 355 |
275 } // namespace views | 356 } // namespace views |
OLD | NEW |