OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 "chrome/browser/extensions/extension_view_host.h" | 5 #include "chrome/browser/extensions/extension_view_host.h" |
6 | 6 |
7 #include "base/strings/string_piece.h" | 7 #include "base/strings/string_piece.h" |
| 8 #include "chrome/browser/chrome_notification_types.h" |
| 9 #include "chrome/browser/extensions/extension_service.h" |
| 10 #include "chrome/browser/extensions/extension_system.h" |
8 #include "chrome/browser/extensions/window_controller.h" | 11 #include "chrome/browser/extensions/window_controller.h" |
| 12 #include "chrome/browser/platform_util.h" |
9 #include "chrome/browser/ui/browser.h" | 13 #include "chrome/browser/ui/browser.h" |
10 #include "chrome/common/extensions/extension_messages.h" | 14 #include "chrome/common/extensions/extension_messages.h" |
| 15 #include "components/web_modal/web_contents_modal_dialog_manager.h" |
| 16 #include "content/public/browser/notification_source.h" |
11 #include "content/public/browser/render_view_host.h" | 17 #include "content/public/browser/render_view_host.h" |
| 18 #include "content/public/browser/web_contents.h" |
| 19 #include "content/public/browser/web_contents_view.h" |
12 #include "grit/browser_resources.h" | 20 #include "grit/browser_resources.h" |
13 #include "ui/base/resource/resource_bundle.h" | 21 #include "ui/base/resource/resource_bundle.h" |
14 #include "ui/events/keycodes/keyboard_codes.h" | 22 #include "ui/events/keycodes/keyboard_codes.h" |
15 | 23 |
16 using content::NativeWebKeyboardEvent; | 24 using content::NativeWebKeyboardEvent; |
17 using content::OpenURLParams; | 25 using content::OpenURLParams; |
18 using content::RenderViewHost; | 26 using content::RenderViewHost; |
19 using content::WebContents; | 27 using content::WebContents; |
20 using content::WebContentsObserver; | 28 using content::WebContentsObserver; |
| 29 using web_modal::WebContentsModalDialogManager; |
21 | 30 |
22 namespace extensions { | 31 namespace extensions { |
23 | 32 |
24 // Notifies an ExtensionViewHost when a WebContents is destroyed. | 33 // Notifies an ExtensionViewHost when a WebContents is destroyed. |
25 class ExtensionViewHost::AssociatedWebContentsObserver | 34 class ExtensionViewHost::AssociatedWebContentsObserver |
26 : public WebContentsObserver { | 35 : public WebContentsObserver { |
27 public: | 36 public: |
28 AssociatedWebContentsObserver(ExtensionViewHost* host, | 37 AssociatedWebContentsObserver(ExtensionViewHost* host, |
29 WebContents* web_contents) | 38 WebContents* web_contents) |
30 : WebContentsObserver(web_contents), host_(host) {} | 39 : WebContentsObserver(web_contents), host_(host) {} |
(...skipping 17 matching lines...) Expand all Loading... |
48 const GURL& url, | 57 const GURL& url, |
49 ViewType host_type) | 58 ViewType host_type) |
50 : ExtensionHost(extension, site_instance, url, host_type), | 59 : ExtensionHost(extension, site_instance, url, host_type), |
51 associated_web_contents_(NULL) { | 60 associated_web_contents_(NULL) { |
52 // Not used for panels, see PanelHost. | 61 // Not used for panels, see PanelHost. |
53 DCHECK(host_type == VIEW_TYPE_EXTENSION_DIALOG || | 62 DCHECK(host_type == VIEW_TYPE_EXTENSION_DIALOG || |
54 host_type == VIEW_TYPE_EXTENSION_INFOBAR || | 63 host_type == VIEW_TYPE_EXTENSION_INFOBAR || |
55 host_type == VIEW_TYPE_EXTENSION_POPUP); | 64 host_type == VIEW_TYPE_EXTENSION_POPUP); |
56 } | 65 } |
57 | 66 |
58 ExtensionViewHost::~ExtensionViewHost() {} | 67 ExtensionViewHost::~ExtensionViewHost() { |
| 68 // The hosting WebContents will be deleted in the base class, so unregister |
| 69 // this object before it deletes the attached WebContentsModalDialogManager. |
| 70 WebContentsModalDialogManager* manager = |
| 71 WebContentsModalDialogManager::FromWebContents(host_contents()); |
| 72 if (manager) |
| 73 manager->SetDelegate(NULL); |
| 74 } |
59 | 75 |
60 void ExtensionViewHost::CreateView(Browser* browser) { | 76 void ExtensionViewHost::CreateView(Browser* browser) { |
61 #if defined(TOOLKIT_VIEWS) | 77 #if defined(TOOLKIT_VIEWS) |
62 view_.reset(new ExtensionViewViews(this, browser)); | 78 view_.reset(new ExtensionViewViews(this, browser)); |
63 // We own |view_|, so don't auto delete when it's removed from the view | 79 // We own |view_|, so don't auto delete when it's removed from the view |
64 // hierarchy. | 80 // hierarchy. |
65 view_->set_owned_by_client(); | 81 view_->set_owned_by_client(); |
66 #elif defined(OS_MACOSX) | 82 #elif defined(OS_MACOSX) |
67 view_.reset(new ExtensionViewMac(this, browser)); | 83 view_.reset(new ExtensionViewMac(this, browser)); |
68 view_->Init(); | 84 view_->Init(); |
(...skipping 10 matching lines...) Expand all Loading... |
79 associated_web_contents_ = web_contents; | 95 associated_web_contents_ = web_contents; |
80 if (associated_web_contents_) { | 96 if (associated_web_contents_) { |
81 // Observe the new WebContents for deletion. | 97 // Observe the new WebContents for deletion. |
82 associated_web_contents_observer_.reset( | 98 associated_web_contents_observer_.reset( |
83 new AssociatedWebContentsObserver(this, associated_web_contents_)); | 99 new AssociatedWebContentsObserver(this, associated_web_contents_)); |
84 } else { | 100 } else { |
85 associated_web_contents_observer_.reset(); | 101 associated_web_contents_observer_.reset(); |
86 } | 102 } |
87 } | 103 } |
88 | 104 |
89 // ExtensionHost overrides: | |
90 | |
91 void ExtensionViewHost::UnhandledKeyboardEvent( | 105 void ExtensionViewHost::UnhandledKeyboardEvent( |
92 WebContents* source, | 106 WebContents* source, |
93 const content::NativeWebKeyboardEvent& event) { | 107 const content::NativeWebKeyboardEvent& event) { |
94 Browser* browser = view_->browser(); | 108 Browser* browser = view_->browser(); |
95 if (browser) { | 109 if (browser) { |
96 // Handle lower priority browser shortcuts such as Ctrl-f. | 110 // Handle lower priority browser shortcuts such as Ctrl-f. |
97 return browser->HandleKeyboardEvent(source, event); | 111 return browser->HandleKeyboardEvent(source, event); |
98 } else { | 112 } else { |
99 #if defined(TOOLKIT_VIEWS) | 113 #if defined(TOOLKIT_VIEWS) |
100 // In case there's no Browser (e.g. for dialogs), pass it to | 114 // In case there's no Browser (e.g. for dialogs), pass it to |
101 // ExtensionViewViews to handle accelerators. The view's FocusManager does | 115 // ExtensionViewViews to handle accelerators. The view's FocusManager does |
102 // not know anything about Browser accelerators, but might know others such | 116 // not know anything about Browser accelerators, but might know others such |
103 // as Ash's. | 117 // as Ash's. |
104 view_->HandleKeyboardEvent(event); | 118 view_->HandleKeyboardEvent(event); |
105 #endif | 119 #endif |
106 } | 120 } |
107 } | 121 } |
108 | 122 |
| 123 // ExtensionHost overrides: |
| 124 |
109 void ExtensionViewHost::OnDidStopLoading() { | 125 void ExtensionViewHost::OnDidStopLoading() { |
110 DCHECK(did_stop_loading()); | 126 DCHECK(did_stop_loading()); |
111 #if defined(TOOLKIT_VIEWS) || defined(OS_MACOSX) | 127 #if defined(TOOLKIT_VIEWS) || defined(OS_MACOSX) |
112 view_->DidStopLoading(); | 128 view_->DidStopLoading(); |
113 #endif | 129 #endif |
114 } | 130 } |
115 | 131 |
116 void ExtensionViewHost::OnDocumentAvailable() { | 132 void ExtensionViewHost::OnDocumentAvailable() { |
117 if (extension_host_type() == VIEW_TYPE_EXTENSION_INFOBAR) { | 133 if (extension_host_type() == VIEW_TYPE_EXTENSION_INFOBAR) { |
118 // No style sheet for other types, at the moment. | 134 // No style sheet for other types, at the moment. |
119 InsertInfobarCSS(); | 135 InsertInfobarCSS(); |
120 } | 136 } |
121 } | 137 } |
122 | 138 |
| 139 void ExtensionViewHost::LoadInitialURL() { |
| 140 if (!ExtensionSystem::GetForBrowserContext(browser_context())-> |
| 141 extension_service()->IsBackgroundPageReady(extension())) { |
| 142 // Make sure the background page loads before any others. |
| 143 registrar()->Add(this, |
| 144 chrome::NOTIFICATION_EXTENSION_BACKGROUND_PAGE_READY, |
| 145 content::Source<Extension>(extension())); |
| 146 return; |
| 147 } |
| 148 |
| 149 // Popups may spawn modal dialogs, which need positioning information. |
| 150 if (extension_host_type() == VIEW_TYPE_EXTENSION_POPUP) { |
| 151 WebContentsModalDialogManager::CreateForWebContents(host_contents()); |
| 152 WebContentsModalDialogManager::FromWebContents( |
| 153 host_contents())->SetDelegate(this); |
| 154 } |
| 155 |
| 156 ExtensionHost::LoadInitialURL(); |
| 157 } |
| 158 |
123 bool ExtensionViewHost::IsBackgroundPage() const { | 159 bool ExtensionViewHost::IsBackgroundPage() const { |
124 DCHECK(view_); | 160 DCHECK(view_); |
125 return false; | 161 return false; |
126 } | 162 } |
127 | 163 |
128 WebContents* ExtensionViewHost::OpenURLFromTab( | 164 WebContents* ExtensionViewHost::OpenURLFromTab( |
129 WebContents* source, | 165 WebContents* source, |
130 const OpenURLParams& params) { | 166 const OpenURLParams& params) { |
131 // Whitelist the dispositions we will allow to be opened. | 167 // Whitelist the dispositions we will allow to be opened. |
132 switch (params.disposition) { | 168 switch (params.disposition) { |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
195 | 231 |
196 // If the host is bound to a window, then extract its id. Extensions hosted | 232 // If the host is bound to a window, then extract its id. Extensions hosted |
197 // in ExternalTabContainer objects may not have an associated window. | 233 // in ExternalTabContainer objects may not have an associated window. |
198 WindowController* window = GetExtensionWindowController(); | 234 WindowController* window = GetExtensionWindowController(); |
199 if (window) { | 235 if (window) { |
200 render_view_host->Send(new ExtensionMsg_UpdateBrowserWindowId( | 236 render_view_host->Send(new ExtensionMsg_UpdateBrowserWindowId( |
201 render_view_host->GetRoutingID(), window->GetWindowId())); | 237 render_view_host->GetRoutingID(), window->GetWindowId())); |
202 } | 238 } |
203 } | 239 } |
204 | 240 |
205 #if !defined(OS_ANDROID) | 241 web_modal::WebContentsModalDialogHost* |
| 242 ExtensionViewHost::GetWebContentsModalDialogHost() { |
| 243 return this; |
| 244 } |
| 245 |
| 246 bool ExtensionViewHost::IsWebContentsVisible(WebContents* web_contents) { |
| 247 return platform_util::IsVisible(web_contents->GetView()->GetNativeView()); |
| 248 } |
| 249 |
206 gfx::NativeView ExtensionViewHost::GetHostView() const { | 250 gfx::NativeView ExtensionViewHost::GetHostView() const { |
207 return view_->native_view(); | 251 return view_->native_view(); |
208 } | 252 } |
209 #endif // !defined(OS_ANDROID) | 253 |
| 254 gfx::Point ExtensionViewHost::GetDialogPosition(const gfx::Size& size) { |
| 255 if (!GetVisibleWebContents()) |
| 256 return gfx::Point(); |
| 257 gfx::Rect bounds = GetVisibleWebContents()->GetView()->GetViewBounds(); |
| 258 return gfx::Point( |
| 259 std::max(0, (bounds.width() - size.width()) / 2), |
| 260 std::max(0, (bounds.height() - size.height()) / 2)); |
| 261 } |
| 262 |
| 263 gfx::Size ExtensionViewHost::GetMaximumDialogSize() { |
| 264 if (!GetVisibleWebContents()) |
| 265 return gfx::Size(); |
| 266 return GetVisibleWebContents()->GetView()->GetViewBounds().size(); |
| 267 } |
| 268 |
| 269 void ExtensionViewHost::AddObserver( |
| 270 web_modal::ModalDialogHostObserver* observer) { |
| 271 } |
| 272 |
| 273 void ExtensionViewHost::RemoveObserver( |
| 274 web_modal::ModalDialogHostObserver* observer) { |
| 275 } |
210 | 276 |
211 WindowController* ExtensionViewHost::GetExtensionWindowController() const { | 277 WindowController* ExtensionViewHost::GetExtensionWindowController() const { |
212 return view_->browser() ? view_->browser()->extension_window_controller() | 278 return view_->browser() ? view_->browser()->extension_window_controller() |
213 : NULL; | 279 : NULL; |
214 } | 280 } |
215 | 281 |
216 WebContents* ExtensionViewHost::GetAssociatedWebContents() const { | 282 WebContents* ExtensionViewHost::GetAssociatedWebContents() const { |
217 return associated_web_contents_; | 283 return associated_web_contents_; |
218 } | 284 } |
219 | 285 |
220 WebContents* ExtensionViewHost::GetVisibleWebContents() const { | 286 WebContents* ExtensionViewHost::GetVisibleWebContents() const { |
221 if (associated_web_contents_) | 287 if (associated_web_contents_) |
222 return associated_web_contents_; | 288 return associated_web_contents_; |
223 if (extension_host_type() == VIEW_TYPE_EXTENSION_POPUP) | 289 if (extension_host_type() == VIEW_TYPE_EXTENSION_POPUP) |
224 return host_contents(); | 290 return host_contents(); |
225 return NULL; | 291 return NULL; |
226 } | 292 } |
227 | 293 |
| 294 void ExtensionViewHost::Observe(int type, |
| 295 const content::NotificationSource& source, |
| 296 const content::NotificationDetails& details) { |
| 297 if (type == chrome::NOTIFICATION_EXTENSION_BACKGROUND_PAGE_READY) { |
| 298 DCHECK(ExtensionSystem::GetForBrowserContext(browser_context())-> |
| 299 extension_service()->IsBackgroundPageReady(extension())); |
| 300 LoadInitialURL(); |
| 301 return; |
| 302 } |
| 303 ExtensionHost::Observe(type, source, details); |
| 304 } |
| 305 |
228 void ExtensionViewHost::InsertInfobarCSS() { | 306 void ExtensionViewHost::InsertInfobarCSS() { |
229 static const base::StringPiece css( | 307 static const base::StringPiece css( |
230 ResourceBundle::GetSharedInstance().GetRawDataResource( | 308 ResourceBundle::GetSharedInstance().GetRawDataResource( |
231 IDR_EXTENSIONS_INFOBAR_CSS)); | 309 IDR_EXTENSIONS_INFOBAR_CSS)); |
232 | 310 |
233 render_view_host()->InsertCSS(string16(), css.as_string()); | 311 render_view_host()->InsertCSS(string16(), css.as_string()); |
234 } | 312 } |
235 | 313 |
236 } // namespace extensions | 314 } // namespace extensions |
OLD | NEW |