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" |
(...skipping 17 matching lines...) Expand all Loading... |
28 | 28 |
29 // static | 29 // static |
30 const char WebView::kViewClassName[] = "WebView"; | 30 const char WebView::kViewClassName[] = "WebView"; |
31 | 31 |
32 //////////////////////////////////////////////////////////////////////////////// | 32 //////////////////////////////////////////////////////////////////////////////// |
33 // WebView, public: | 33 // WebView, public: |
34 | 34 |
35 WebView::WebView(content::BrowserContext* browser_context) | 35 WebView::WebView(content::BrowserContext* browser_context) |
36 : wcv_holder_(new NativeViewHost), | 36 : wcv_holder_(new NativeViewHost), |
37 web_contents_(NULL), | 37 web_contents_(NULL), |
| 38 embed_fullscreen_widget_mode_enabled_(false), |
| 39 is_embedding_fullscreen_widget_(false), |
38 browser_context_(browser_context), | 40 browser_context_(browser_context), |
39 allow_accelerators_(false) { | 41 allow_accelerators_(false) { |
40 AddChildView(wcv_holder_); | 42 AddChildView(wcv_holder_); |
41 NativeViewAccessibility::RegisterWebView(this); | 43 NativeViewAccessibility::RegisterWebView(this); |
42 } | 44 } |
43 | 45 |
44 WebView::~WebView() { | 46 WebView::~WebView() { |
45 NativeViewAccessibility::UnregisterWebView(this); | 47 NativeViewAccessibility::UnregisterWebView(this); |
46 } | 48 } |
47 | 49 |
48 content::WebContents* WebView::GetWebContents() { | 50 content::WebContents* WebView::GetWebContents() { |
49 CreateWebContentsWithSiteInstance(NULL); | 51 CreateWebContentsWithSiteInstance(NULL); |
50 return web_contents_; | 52 return web_contents_; |
51 } | 53 } |
52 | 54 |
53 void WebView::CreateWebContentsWithSiteInstance( | 55 void WebView::CreateWebContentsWithSiteInstance( |
54 content::SiteInstance* site_instance) { | 56 content::SiteInstance* site_instance) { |
55 if (!web_contents_) { | 57 if (!web_contents_) { |
56 wc_owner_.reset(CreateWebContents(browser_context_, site_instance)); | 58 wc_owner_.reset(CreateWebContents(browser_context_, site_instance)); |
57 web_contents_ = wc_owner_.get(); | 59 web_contents_ = wc_owner_.get(); |
58 web_contents_->SetDelegate(this); | 60 web_contents_->SetDelegate(this); |
59 AttachWebContents(); | 61 AttachWebContents(); |
60 } | 62 } |
61 } | 63 } |
62 | 64 |
63 void WebView::SetWebContents(content::WebContents* web_contents) { | 65 void WebView::SetWebContents(content::WebContents* web_contents) { |
64 if (web_contents == web_contents_) | 66 if (web_contents == web_contents_) |
65 return; | 67 return; |
66 DetachWebContents(); | 68 DetachWebContents(); |
67 wc_owner_.reset(); | 69 if (wc_owner_ != web_contents) |
| 70 wc_owner_.reset(); |
68 web_contents_ = web_contents; | 71 web_contents_ = web_contents; |
| 72 if (embed_fullscreen_widget_mode_enabled_) { |
| 73 WebContentsObserver::Observe(web_contents_); |
| 74 is_embedding_fullscreen_widget_ = |
| 75 web_contents_ && web_contents_->GetFullscreenRenderWidgetHostView(); |
| 76 } else { |
| 77 is_embedding_fullscreen_widget_ = false; |
| 78 } |
69 AttachWebContents(); | 79 AttachWebContents(); |
70 } | 80 } |
71 | 81 |
| 82 void WebView::SetEmbedFullscreenWidgetMode(bool enable) { |
| 83 bool should_be_embedded = enable; |
| 84 if (!embed_fullscreen_widget_mode_enabled_ && enable) { |
| 85 DCHECK(!is_embedding_fullscreen_widget_); |
| 86 embed_fullscreen_widget_mode_enabled_ = true; |
| 87 WebContentsObserver::Observe(web_contents_); |
| 88 should_be_embedded = |
| 89 web_contents_ && web_contents_->GetFullscreenRenderWidgetHostView(); |
| 90 } else if (embed_fullscreen_widget_mode_enabled_ && !enable) { |
| 91 embed_fullscreen_widget_mode_enabled_ = false; |
| 92 WebContentsObserver::Observe(NULL); |
| 93 } |
| 94 if (should_be_embedded != is_embedding_fullscreen_widget_) |
| 95 ReattachForFullscreenChange(should_be_embedded); |
| 96 } |
| 97 |
72 void WebView::LoadInitialURL(const GURL& url) { | 98 void WebView::LoadInitialURL(const GURL& url) { |
73 GetWebContents()->GetController().LoadURL( | 99 GetWebContents()->GetController().LoadURL( |
74 url, content::Referrer(), content::PAGE_TRANSITION_AUTO_TOPLEVEL, | 100 url, content::Referrer(), content::PAGE_TRANSITION_AUTO_TOPLEVEL, |
75 std::string()); | 101 std::string()); |
76 } | 102 } |
77 | 103 |
78 void WebView::SetFastResize(bool fast_resize) { | 104 void WebView::SetFastResize(bool fast_resize) { |
79 wcv_holder_->set_fast_resize(fast_resize); | 105 wcv_holder_->set_fast_resize(fast_resize); |
80 } | 106 } |
81 | 107 |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
119 return web_contents_ && !web_contents_->IsCrashed(); | 145 return web_contents_ && !web_contents_->IsCrashed(); |
120 } | 146 } |
121 | 147 |
122 bool WebView::IsFocusable() const { | 148 bool WebView::IsFocusable() const { |
123 // We need to be focusable when our contents is not a view hierarchy, as | 149 // We need to be focusable when our contents is not a view hierarchy, as |
124 // clicking on the contents needs to focus us. | 150 // clicking on the contents needs to focus us. |
125 return !!web_contents_; | 151 return !!web_contents_; |
126 } | 152 } |
127 | 153 |
128 void WebView::OnFocus() { | 154 void WebView::OnFocus() { |
129 if (web_contents_) | 155 if (!web_contents_) |
| 156 return; |
| 157 if (is_embedding_fullscreen_widget_) { |
| 158 content::RenderWidgetHostView* const current_fs_view = |
| 159 web_contents_->GetFullscreenRenderWidgetHostView(); |
| 160 if (current_fs_view) |
| 161 current_fs_view->Focus(); |
| 162 } else { |
130 web_contents_->GetView()->Focus(); | 163 web_contents_->GetView()->Focus(); |
| 164 } |
131 } | 165 } |
132 | 166 |
133 void WebView::AboutToRequestFocusFromTabTraversal(bool reverse) { | 167 void WebView::AboutToRequestFocusFromTabTraversal(bool reverse) { |
134 if (web_contents_) | 168 if (web_contents_) |
135 web_contents_->FocusThroughTabTraversal(reverse); | 169 web_contents_->FocusThroughTabTraversal(reverse); |
136 } | 170 } |
137 | 171 |
138 void WebView::GetAccessibleState(ui::AccessibleViewState* state) { | 172 void WebView::GetAccessibleState(ui::AccessibleViewState* state) { |
139 state->role = ui::AccessibilityTypes::ROLE_GROUPING; | 173 state->role = ui::AccessibilityTypes::ROLE_GROUPING; |
140 } | 174 } |
(...skipping 15 matching lines...) Expand all Loading... |
156 return preferred_size_; | 190 return preferred_size_; |
157 } | 191 } |
158 | 192 |
159 //////////////////////////////////////////////////////////////////////////////// | 193 //////////////////////////////////////////////////////////////////////////////// |
160 // WebView, content::NotificationObserver implementation: | 194 // WebView, content::NotificationObserver implementation: |
161 | 195 |
162 void WebView::Observe(int type, | 196 void WebView::Observe(int type, |
163 const content::NotificationSource& source, | 197 const content::NotificationSource& source, |
164 const content::NotificationDetails& details) { | 198 const content::NotificationDetails& details) { |
165 if (type == content::NOTIFICATION_RENDER_VIEW_HOST_CHANGED) { | 199 if (type == content::NOTIFICATION_RENDER_VIEW_HOST_CHANGED) { |
166 std::pair<content::RenderViewHost*, content::RenderViewHost*>* | 200 FocusManager* const focus_manager = GetFocusManager(); |
167 switched_details = | 201 if (focus_manager && focus_manager->GetFocusedView() == this) |
168 content::Details<std::pair<content::RenderViewHost*, | 202 OnFocus(); |
169 content::RenderViewHost*> >( | |
170 details).ptr(); | |
171 RenderViewHostChanged(switched_details->first, | |
172 switched_details->second); | |
173 } else if (type == content::NOTIFICATION_WEB_CONTENTS_DESTROYED) { | 203 } else if (type == content::NOTIFICATION_WEB_CONTENTS_DESTROYED) { |
174 WebContentsDestroyed(content::Source<content::WebContents>(source).ptr()); | 204 DCHECK(content::Source<content::WebContents>(source).ptr() == |
| 205 web_contents_); |
| 206 SetWebContents(NULL); |
175 } else { | 207 } else { |
176 NOTREACHED(); | 208 NOTREACHED(); |
177 } | 209 } |
178 } | 210 } |
179 | 211 |
180 //////////////////////////////////////////////////////////////////////////////// | 212 //////////////////////////////////////////////////////////////////////////////// |
181 // WebView, content::WebContentsDelegate implementation: | 213 // WebView, content::WebContentsDelegate implementation: |
182 | 214 |
183 void WebView::WebContentsFocused(content::WebContents* web_contents) { | 215 void WebView::WebContentsFocused(content::WebContents* web_contents) { |
184 DCHECK(wc_owner_.get()); | 216 DCHECK(wc_owner_.get()); |
185 // The WebView is only the delegate of WebContentses it creates itself. | 217 // The WebView is only the delegate of WebContentses it creates itself. |
186 OnWebContentsFocused(web_contents_); | 218 OnWebContentsFocused(web_contents_); |
187 } | 219 } |
188 | 220 |
| 221 bool WebView::EmbedsFullscreenWidget() const { |
| 222 DCHECK(wc_owner_.get()); |
| 223 return embed_fullscreen_widget_mode_enabled_; |
| 224 } |
| 225 |
| 226 //////////////////////////////////////////////////////////////////////////////// |
| 227 // WebView, content::WebContentsObserver implementation: |
| 228 |
| 229 void WebView::DidShowFullscreenWidget(int routing_id) { |
| 230 DCHECK(embed_fullscreen_widget_mode_enabled_); |
| 231 ReattachForFullscreenChange(true); |
| 232 } |
| 233 |
| 234 void WebView::DidDestroyFullscreenWidget(int routing_id) { |
| 235 DCHECK(embed_fullscreen_widget_mode_enabled_); |
| 236 ReattachForFullscreenChange(false); |
| 237 } |
| 238 |
189 //////////////////////////////////////////////////////////////////////////////// | 239 //////////////////////////////////////////////////////////////////////////////// |
190 // WebView, private: | 240 // WebView, private: |
191 | 241 |
192 void WebView::AttachWebContents() { | 242 void WebView::AttachWebContents() { |
193 // Prevents attachment if the WebView isn't already in a Widget, or it's | 243 // Prevents attachment if the WebView isn't already in a Widget, or it's |
194 // already attached. | 244 // already attached. |
195 if (!GetWidget() || !web_contents_ || | 245 if (!GetWidget() || !web_contents_) |
196 wcv_holder_->native_view() == web_contents_->GetView()->GetNativeView()) { | |
197 return; | 246 return; |
198 } | |
199 | 247 |
200 if (web_contents_) { | 248 const gfx::NativeView view_to_attach = is_embedding_fullscreen_widget_ ? |
201 wcv_holder_->Attach(web_contents_->GetView()->GetNativeView()); | 249 web_contents_->GetFullscreenRenderWidgetHostView()->GetNativeView() : |
| 250 web_contents_->GetView()->GetNativeView(); |
| 251 if (wcv_holder_->native_view() == view_to_attach) |
| 252 return; |
| 253 wcv_holder_->Attach(view_to_attach); |
202 | 254 |
203 // The WebContentsView will not be focused automatically when it is | 255 // The view will not be focused automatically when it is attached, so we need |
204 // attached, so we need to pass on focus to it if the FocusManager thinks | 256 // to pass on focus to it if the FocusManager thinks the view is focused. Note |
205 // the WebView is focused. Note that not every Widget has a focus manager. | 257 // that not every Widget has a focus manager. |
206 FocusManager* focus_manager = GetFocusManager(); | 258 FocusManager* const focus_manager = GetFocusManager(); |
207 if (focus_manager && focus_manager->GetFocusedView() == this) | 259 if (focus_manager && focus_manager->GetFocusedView() == this) |
208 web_contents_->GetView()->Focus(); | 260 OnFocus(); |
209 | 261 |
210 registrar_.Add( | 262 registrar_.Add( |
211 this, | 263 this, |
212 content::NOTIFICATION_RENDER_VIEW_HOST_CHANGED, | 264 content::NOTIFICATION_RENDER_VIEW_HOST_CHANGED, |
213 content::Source<content::NavigationController>( | 265 content::Source<content::NavigationController>( |
214 &web_contents_->GetController())); | 266 &web_contents_->GetController())); |
215 registrar_.Add( | 267 registrar_.Add( |
216 this, | 268 this, |
217 content::NOTIFICATION_WEB_CONTENTS_DESTROYED, | 269 content::NOTIFICATION_WEB_CONTENTS_DESTROYED, |
218 content::Source<content::WebContents>(web_contents_)); | 270 content::Source<content::WebContents>(web_contents_)); |
219 } | |
220 | 271 |
221 #if defined(OS_WIN) && defined(USE_AURA) | 272 #if defined(OS_WIN) && defined(USE_AURA) |
222 web_contents_->SetParentNativeViewAccessible( | 273 if (!is_embedding_fullscreen_widget_) { |
223 parent()->GetNativeViewAccessible()); | 274 web_contents_->SetParentNativeViewAccessible( |
| 275 parent()->GetNativeViewAccessible()); |
| 276 } |
224 #endif | 277 #endif |
225 } | 278 } |
226 | 279 |
227 void WebView::DetachWebContents() { | 280 void WebView::DetachWebContents() { |
228 if (web_contents_) { | 281 if (web_contents_) { |
229 wcv_holder_->Detach(); | 282 wcv_holder_->Detach(); |
230 #if defined(OS_WIN) && !defined(USE_AURA) | 283 #if defined(OS_WIN) |
231 // TODO(beng): This should either not be necessary, or be done implicitly by | 284 if (!is_embedding_fullscreen_widget_) { |
232 // NativeViewHostWin on Detach(). As it stands, this is needed so that the | 285 #if !defined(USE_AURA) |
233 // view of the detached contents knows to tell the renderer it's been | 286 // TODO(beng): This should either not be necessary, or be done implicitly |
234 // hidden. | 287 // by NativeViewHostWin on Detach(). As it stands, this is needed so that |
235 // | 288 // 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 | 289 // hidden. |
237 // calling member functions on a half-destroyed WebContents. | 290 // |
238 ShowWindow(web_contents_->GetView()->GetNativeView(), SW_HIDE); | 291 // Moving this out of here would also mean we wouldn't be potentially |
239 #elif defined(OS_WIN) && defined(USE_AURA) | 292 // calling member functions on a half-destroyed WebContents. |
240 web_contents_->SetParentNativeViewAccessible(NULL); | 293 ShowWindow(web_contents_->GetView()->GetNativeView(), SW_HIDE); |
| 294 #else |
| 295 web_contents_->SetParentNativeViewAccessible(NULL); |
| 296 #endif |
| 297 } |
241 #endif | 298 #endif |
242 } | 299 } |
243 registrar_.RemoveAll(); | 300 registrar_.RemoveAll(); |
244 } | 301 } |
245 | 302 |
246 void WebView::RenderViewHostChanged(content::RenderViewHost* old_host, | 303 void WebView::ReattachForFullscreenChange(bool enter_fullscreen) { |
247 content::RenderViewHost* new_host) { | 304 DetachWebContents(); |
248 if (GetFocusManager()->GetFocusedView() == this) | 305 is_embedding_fullscreen_widget_ = enter_fullscreen && |
249 web_contents_->GetView()->Focus(); | 306 web_contents_ && web_contents_->GetFullscreenRenderWidgetHostView(); |
250 } | 307 AttachWebContents(); |
251 | |
252 void WebView::WebContentsDestroyed(content::WebContents* web_contents) { | |
253 DCHECK(web_contents == web_contents_); | |
254 SetWebContents(NULL); | |
255 } | 308 } |
256 | 309 |
257 content::WebContents* WebView::CreateWebContents( | 310 content::WebContents* WebView::CreateWebContents( |
258 content::BrowserContext* browser_context, | 311 content::BrowserContext* browser_context, |
259 content::SiteInstance* site_instance) { | 312 content::SiteInstance* site_instance) { |
260 content::WebContents* contents = NULL; | 313 content::WebContents* contents = NULL; |
261 if (ViewsDelegate::views_delegate) { | 314 if (ViewsDelegate::views_delegate) { |
262 contents = ViewsDelegate::views_delegate->CreateWebContents( | 315 contents = ViewsDelegate::views_delegate->CreateWebContents( |
263 browser_context, site_instance); | 316 browser_context, site_instance); |
264 } | 317 } |
265 | 318 |
266 if (!contents) { | 319 if (!contents) { |
267 content::WebContents::CreateParams create_params( | 320 content::WebContents::CreateParams create_params( |
268 browser_context, site_instance); | 321 browser_context, site_instance); |
269 return content::WebContents::Create(create_params); | 322 return content::WebContents::Create(create_params); |
270 } | 323 } |
271 | 324 |
272 return contents; | 325 return contents; |
273 } | 326 } |
274 | 327 |
275 } // namespace views | 328 } // namespace views |
OLD | NEW |