OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 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 | 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_host.h" | 5 #include "chrome/browser/extensions/extension_host.h" |
6 | 6 |
7 #include <list> | 7 #include <list> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/memory/singleton.h" | 10 #include "base/memory/singleton.h" |
11 #include "base/memory/weak_ptr.h" | 11 #include "base/memory/weak_ptr.h" |
12 #include "base/message_loop.h" | 12 #include "base/message_loop.h" |
13 #include "base/metrics/histogram.h" | 13 #include "base/metrics/histogram.h" |
14 #include "base/string_util.h" | 14 #include "base/string_util.h" |
15 #include "base/utf_string_conversions.h" | 15 #include "base/utf_string_conversions.h" |
16 #include "chrome/browser/browser_shutdown.h" | 16 #include "chrome/browser/browser_shutdown.h" |
17 #include "chrome/browser/extensions/extension_service.h" | 17 #include "chrome/browser/extensions/extension_service.h" |
18 #include "chrome/browser/extensions/extension_tab_util.h" | 18 #include "chrome/browser/extensions/extension_tab_util.h" |
| 19 #include "chrome/browser/file_select_helper.h" |
| 20 #include "chrome/browser/platform_util.h" |
19 #include "chrome/browser/profiles/profile.h" | 21 #include "chrome/browser/profiles/profile.h" |
| 22 #include "chrome/browser/renderer_preferences_util.h" |
| 23 #include "chrome/browser/tabs/tab_strip_model.h" |
20 #include "chrome/browser/ui/app_modal_dialogs/message_box_handler.h" | 24 #include "chrome/browser/ui/app_modal_dialogs/message_box_handler.h" |
21 #include "chrome/browser/ui/browser.h" | 25 #include "chrome/browser/ui/browser.h" |
22 #include "chrome/browser/ui/browser_list.h" | 26 #include "chrome/browser/ui/browser_list.h" |
23 #include "chrome/browser/ui/browser_window.h" | 27 #include "chrome/browser/ui/browser_window.h" |
24 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" | 28 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" |
| 29 #include "chrome/browser/ui/webui/chrome_web_ui_factory.h" |
25 #include "chrome/common/chrome_constants.h" | 30 #include "chrome/common/chrome_constants.h" |
26 #include "chrome/common/chrome_notification_types.h" | 31 #include "chrome/common/chrome_notification_types.h" |
27 #include "chrome/common/extensions/extension.h" | 32 #include "chrome/common/extensions/extension.h" |
28 #include "chrome/common/extensions/extension_constants.h" | 33 #include "chrome/common/extensions/extension_constants.h" |
29 #include "chrome/common/extensions/extension_messages.h" | 34 #include "chrome/common/extensions/extension_messages.h" |
30 #include "chrome/common/render_messages.h" | 35 #include "chrome/common/render_messages.h" |
31 #include "chrome/common/url_constants.h" | 36 #include "chrome/common/url_constants.h" |
32 #include "chrome/common/chrome_view_types.h" | 37 #include "chrome/common/chrome_view_types.h" |
33 #include "content/browser/browsing_instance.h" | 38 #include "content/browser/browsing_instance.h" |
34 #include "content/browser/renderer_host/browser_render_process_host.h" | 39 #include "content/browser/renderer_host/browser_render_process_host.h" |
35 #include "content/browser/renderer_host/render_process_host.h" | 40 #include "content/browser/renderer_host/render_process_host.h" |
36 #include "content/browser/renderer_host/render_view_host.h" | 41 #include "content/browser/renderer_host/render_view_host.h" |
| 42 #include "content/browser/renderer_host/render_widget_host.h" |
| 43 #include "content/browser/renderer_host/render_widget_host_view.h" |
| 44 #include "content/browser/site_instance.h" |
| 45 #include "content/browser/tab_contents/popup_menu_helper_mac.h" |
37 #include "content/browser/tab_contents/tab_contents.h" | 46 #include "content/browser/tab_contents/tab_contents.h" |
38 #include "content/browser/tab_contents/tab_contents_view.h" | 47 #include "content/browser/tab_contents/tab_contents_view.h" |
39 #include "content/public/browser/notification_service.h" | 48 #include "content/public/browser/notification_service.h" |
40 #include "content/common/view_messages.h" | 49 #include "content/common/view_messages.h" |
41 #include "content/public/browser/content_browser_client.h" | 50 #include "content/public/browser/content_browser_client.h" |
42 #include "content/public/browser/native_web_keyboard_event.h" | 51 #include "content/public/browser/native_web_keyboard_event.h" |
| 52 #include "content/public/common/bindings_policy.h" |
43 #include "grit/browser_resources.h" | 53 #include "grit/browser_resources.h" |
44 #include "grit/chromium_strings.h" | 54 #include "grit/chromium_strings.h" |
45 #include "grit/generated_resources.h" | 55 #include "grit/generated_resources.h" |
46 #include "ui/base/keycodes/keyboard_codes.h" | 56 #include "ui/base/keycodes/keyboard_codes.h" |
47 #include "ui/base/l10n/l10n_util.h" | 57 #include "ui/base/l10n/l10n_util.h" |
48 #include "ui/base/resource/resource_bundle.h" | 58 #include "ui/base/resource/resource_bundle.h" |
| 59 #include "webkit/glue/context_menu.h" |
49 | 60 |
50 #if defined(TOOLKIT_VIEWS) | 61 #if defined(TOOLKIT_VIEWS) |
51 #include "views/widget/widget.h" | 62 #include "views/widget/widget.h" |
52 #endif | 63 #endif |
53 | 64 |
54 using WebKit::WebDragOperation; | 65 using WebKit::WebDragOperation; |
55 using WebKit::WebDragOperationsMask; | 66 using WebKit::WebDragOperationsMask; |
56 | 67 |
| 68 // static |
| 69 bool ExtensionHost::enable_dom_automation_ = false; |
| 70 |
57 // Helper class that rate-limits the creation of renderer processes for | 71 // Helper class that rate-limits the creation of renderer processes for |
58 // ExtensionHosts, to avoid blocking the UI. | 72 // ExtensionHosts, to avoid blocking the UI. |
59 class ExtensionHost::ProcessCreationQueue { | 73 class ExtensionHost::ProcessCreationQueue { |
60 public: | 74 public: |
61 static ProcessCreationQueue* GetInstance() { | 75 static ProcessCreationQueue* GetInstance() { |
62 return Singleton<ProcessCreationQueue>::get(); | 76 return Singleton<ProcessCreationQueue>::get(); |
63 } | 77 } |
64 | 78 |
65 // Add a host to the queue for RenderView creation. | 79 // Add a host to the queue for RenderView creation. |
66 void CreateSoon(ExtensionHost* host) { | 80 void CreateSoon(ExtensionHost* host) { |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
117 ExtensionHost::ExtensionHost(const Extension* extension, | 131 ExtensionHost::ExtensionHost(const Extension* extension, |
118 SiteInstance* site_instance, | 132 SiteInstance* site_instance, |
119 const GURL& url, | 133 const GURL& url, |
120 content::ViewType host_type) | 134 content::ViewType host_type) |
121 : extension_(extension), | 135 : extension_(extension), |
122 extension_id_(extension->id()), | 136 extension_id_(extension->id()), |
123 profile_(Profile::FromBrowserContext( | 137 profile_(Profile::FromBrowserContext( |
124 site_instance->browsing_instance()->browser_context())), | 138 site_instance->browsing_instance()->browser_context())), |
125 did_stop_loading_(false), | 139 did_stop_loading_(false), |
126 document_element_available_(false), | 140 document_element_available_(false), |
127 initial_url_(url), | 141 url_(url), |
128 ALLOW_THIS_IN_INITIALIZER_LIST( | 142 ALLOW_THIS_IN_INITIALIZER_LIST( |
129 extension_function_dispatcher_(profile_, this)), | 143 extension_function_dispatcher_(profile_, this)), |
130 extension_host_type_(host_type), | 144 extension_host_type_(host_type), |
131 associated_tab_contents_(NULL) { | 145 associated_tab_contents_(NULL) { |
132 host_contents_.reset(new TabContents( | 146 render_view_host_ = new RenderViewHost(site_instance, this, MSG_ROUTING_NONE, |
133 profile_, site_instance, MSG_ROUTING_NONE, NULL, NULL)); | 147 NULL); |
134 TabContentsObserver::Observe(host_contents_.get()); | 148 if (enable_dom_automation_) |
135 host_contents_->set_delegate(this); | 149 render_view_host_->AllowBindings(content::BINDINGS_POLICY_DOM_AUTOMATION); |
136 host_contents_->set_view_type(host_type); | |
137 | 150 |
138 // Listen for when an extension is unloaded from the same profile, as it may | 151 // Listen for when an extension is unloaded from the same profile, as it may |
139 // be the same extension that this points to. | 152 // be the same extension that this points to. |
140 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED, | 153 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED, |
141 content::Source<Profile>(profile_)); | 154 content::Source<Profile>(profile_)); |
142 } | 155 } |
143 | 156 |
144 // This "mock" constructor should only be used by unit tests. | 157 // This "mock" constructor should only be used by unit tests. |
145 ExtensionHost::ExtensionHost(const Extension* extension, | 158 ExtensionHost::ExtensionHost(const Extension* extension, |
146 content::ViewType host_type) | 159 content::ViewType host_type) |
147 : extension_(extension), | 160 : extension_(extension), |
148 extension_id_(extension->id()), | 161 extension_id_(extension->id()), |
149 profile_(NULL), | 162 profile_(NULL), |
| 163 render_view_host_(NULL), |
150 did_stop_loading_(false), | 164 did_stop_loading_(false), |
151 document_element_available_(false), | 165 document_element_available_(false), |
152 initial_url_(GURL()), | 166 url_(GURL()), |
153 ALLOW_THIS_IN_INITIALIZER_LIST( | 167 ALLOW_THIS_IN_INITIALIZER_LIST( |
154 extension_function_dispatcher_(profile_, this)), | 168 extension_function_dispatcher_(profile_, this)), |
155 extension_host_type_(host_type), | 169 extension_host_type_(host_type), |
156 associated_tab_contents_(NULL) { | 170 associated_tab_contents_(NULL) { |
157 } | 171 } |
158 | 172 |
159 ExtensionHost::~ExtensionHost() { | 173 ExtensionHost::~ExtensionHost() { |
160 content::NotificationService::current()->Notify( | 174 content::NotificationService::current()->Notify( |
161 chrome::NOTIFICATION_EXTENSION_HOST_DESTROYED, | 175 chrome::NOTIFICATION_EXTENSION_HOST_DESTROYED, |
162 content::Source<Profile>(profile_), | 176 content::Source<Profile>(profile_), |
163 content::Details<ExtensionHost>(this)); | 177 content::Details<ExtensionHost>(this)); |
164 ProcessCreationQueue::GetInstance()->Remove(this); | 178 ProcessCreationQueue::GetInstance()->Remove(this); |
| 179 GetJavaScriptDialogCreatorInstance()->ResetJavaScriptState(this); |
| 180 // render_view_host_ may be NULL in unit tests. |
| 181 if (render_view_host_) |
| 182 render_view_host_->Shutdown(); // deletes render_view_host |
165 } | 183 } |
166 | 184 |
167 void ExtensionHost::CreateView(Browser* browser) { | 185 void ExtensionHost::CreateView(Browser* browser) { |
168 #if defined(TOOLKIT_VIEWS) | 186 #if defined(TOOLKIT_VIEWS) |
169 view_.reset(new ExtensionView(this, browser)); | 187 view_.reset(new ExtensionView(this, browser)); |
170 // We own |view_|, so don't auto delete when it's removed from the view | 188 // We own |view_|, so don't auto delete when it's removed from the view |
171 // hierarchy. | 189 // hierarchy. |
172 view_->set_parent_owned(false); | 190 view_->set_parent_owned(false); |
173 #elif defined(OS_MACOSX) | 191 #elif defined(OS_MACOSX) |
174 view_.reset(new ExtensionViewMac(this, browser)); | 192 view_.reset(new ExtensionViewMac(this, browser)); |
175 view_->Init(); | 193 view_->Init(); |
176 #elif defined(TOOLKIT_USES_GTK) | 194 #elif defined(TOOLKIT_USES_GTK) |
177 view_.reset(new ExtensionViewGtk(this, browser)); | 195 view_.reset(new ExtensionViewGtk(this, browser)); |
178 view_->Init(); | 196 view_->Init(); |
179 #else | 197 #else |
180 // TODO(port) | 198 // TODO(port) |
181 NOTREACHED(); | 199 NOTREACHED(); |
182 #endif | 200 #endif |
183 } | 201 } |
184 | 202 |
185 TabContents* ExtensionHost::GetAssociatedTabContents() const { | 203 TabContents* ExtensionHost::GetAssociatedTabContents() const { |
186 return associated_tab_contents_; | 204 return associated_tab_contents_; |
187 } | 205 } |
188 | 206 |
189 RenderProcessHost* ExtensionHost::render_process_host() const { | 207 RenderProcessHost* ExtensionHost::render_process_host() const { |
190 return host_contents()->GetRenderProcessHost(); | 208 return render_view_host_->process(); |
191 } | 209 } |
192 | 210 |
193 RenderViewHost* ExtensionHost::render_view_host() const { | 211 SiteInstance* ExtensionHost::site_instance() const { |
194 // TODO(mpcomplete): This can be NULL. How do we handle that? | 212 return render_view_host_->site_instance(); |
195 return host_contents()->render_view_host(); | |
196 } | 213 } |
197 | 214 |
198 bool ExtensionHost::IsRenderViewLive() const { | 215 bool ExtensionHost::IsRenderViewLive() const { |
199 return render_view_host()->IsRenderViewLive(); | 216 return render_view_host_->IsRenderViewLive(); |
200 } | 217 } |
201 | 218 |
202 void ExtensionHost::CreateRenderViewSoon() { | 219 void ExtensionHost::CreateRenderViewSoon(RenderWidgetHostView* host_view) { |
203 if (render_process_host()->HasConnection()) { | 220 render_view_host_->SetView(host_view); |
| 221 if (render_view_host_->process()->HasConnection()) { |
204 // If the process is already started, go ahead and initialize the RenderView | 222 // If the process is already started, go ahead and initialize the RenderView |
205 // synchronously. The process creation is the real meaty part that we want | 223 // synchronously. The process creation is the real meaty part that we want |
206 // to defer. | 224 // to defer. |
207 CreateRenderViewNow(); | 225 CreateRenderViewNow(); |
208 } else { | 226 } else { |
209 ProcessCreationQueue::GetInstance()->CreateSoon(this); | 227 ProcessCreationQueue::GetInstance()->CreateSoon(this); |
210 } | 228 } |
211 } | 229 } |
212 | 230 |
213 void ExtensionHost::CreateRenderViewNow() { | 231 void ExtensionHost::CreateRenderViewNow() { |
214 LoadInitialURL(); | 232 render_view_host_->CreateRenderView(string16()); |
215 if (is_background_page()) { | 233 if (extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_POPUP || |
216 DCHECK(IsRenderViewLive()); | 234 extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_DIALOG || |
217 profile_->GetExtensionService()->DidCreateRenderViewForBackgroundPage(this); | 235 extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_INFOBAR) { |
| 236 // If the host is bound to a browser, then extract its window id. |
| 237 // Extensions hosted in ExternalTabContainer objects may not have |
| 238 // an associated browser. |
| 239 const Browser* browser = GetBrowser(); |
| 240 if (browser && render_view_host_) { |
| 241 render_view_host_->Send(new ExtensionMsg_UpdateBrowserWindowId( |
| 242 render_view_host_->routing_id(), |
| 243 ExtensionTabUtil::GetWindowId(browser))); |
| 244 } |
218 } | 245 } |
| 246 NavigateToURL(url_); |
| 247 DCHECK(IsRenderViewLive()); |
| 248 if (is_background_page()) |
| 249 profile_->GetExtensionService()->DidCreateRenderViewForBackgroundPage( |
| 250 this); |
219 } | 251 } |
220 | 252 |
221 const Browser* ExtensionHost::GetBrowser() const { | 253 const Browser* ExtensionHost::GetBrowser() const { |
222 return view() ? view()->browser() : NULL; | 254 return view() ? view()->browser() : NULL; |
223 } | 255 } |
224 | 256 |
225 Browser* ExtensionHost::GetBrowser() { | 257 Browser* ExtensionHost::GetBrowser() { |
226 return view() ? view()->browser() : NULL; | 258 return view() ? view()->browser() : NULL; |
227 } | 259 } |
228 | 260 |
229 gfx::NativeView ExtensionHost::GetNativeViewOfHost() { | 261 gfx::NativeView ExtensionHost::GetNativeViewOfHost() { |
230 return view() ? view()->native_view() : NULL; | 262 return view() ? view()->native_view() : NULL; |
231 } | 263 } |
232 | 264 |
233 const GURL& ExtensionHost::GetURL() const { | 265 void ExtensionHost::NavigateToURL(const GURL& url) { |
234 return host_contents()->GetURL(); | 266 // Prevent explicit navigation to another extension id's pages. |
235 } | 267 // This method is only called by some APIs, so we still need to protect |
| 268 // DidNavigate below (location = ""). |
| 269 if (url.SchemeIs(chrome::kExtensionScheme) && url.host() != extension_id()) { |
| 270 // TODO(erikkay) communicate this back to the caller? |
| 271 return; |
| 272 } |
236 | 273 |
237 void ExtensionHost::LoadInitialURL() { | 274 url_ = url; |
| 275 |
238 if (!is_background_page() && | 276 if (!is_background_page() && |
239 !profile_->GetExtensionService()->IsBackgroundPageReady(extension_)) { | 277 !profile_->GetExtensionService()->IsBackgroundPageReady(extension_)) { |
240 // Make sure the background page loads before any others. | 278 // Make sure the background page loads before any others. |
241 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_BACKGROUND_PAGE_READY, | 279 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_BACKGROUND_PAGE_READY, |
242 content::Source<Extension>(extension_)); | 280 content::Source<Extension>(extension_)); |
243 return; | 281 return; |
244 } | 282 } |
245 | 283 |
246 host_contents_->controller().LoadURL( | 284 render_view_host_->NavigateToURL(url_); |
247 initial_url_, GURL(), content::PAGE_TRANSITION_LINK, std::string()); | |
248 } | 285 } |
249 | 286 |
250 void ExtensionHost::Observe(int type, | 287 void ExtensionHost::Observe(int type, |
251 const content::NotificationSource& source, | 288 const content::NotificationSource& source, |
252 const content::NotificationDetails& details) { | 289 const content::NotificationDetails& details) { |
253 switch (type) { | 290 switch (type) { |
254 case chrome::NOTIFICATION_EXTENSION_BACKGROUND_PAGE_READY: | 291 case chrome::NOTIFICATION_EXTENSION_BACKGROUND_PAGE_READY: |
255 DCHECK(profile_->GetExtensionService()-> | 292 DCHECK(profile_->GetExtensionService()-> |
256 IsBackgroundPageReady(extension_)); | 293 IsBackgroundPageReady(extension_)); |
257 LoadInitialURL(); | 294 NavigateToURL(url_); |
258 break; | 295 break; |
259 case chrome::NOTIFICATION_EXTENSION_UNLOADED: | 296 case chrome::NOTIFICATION_EXTENSION_UNLOADED: |
260 // The extension object will be deleted after this notification has been | 297 // The extension object will be deleted after this notification has been |
261 // sent. NULL it out so that dirty pointer issues don't arise in cases | 298 // sent. NULL it out so that dirty pointer issues don't arise in cases |
262 // when multiple ExtensionHost objects pointing to the same Extension are | 299 // when multiple ExtensionHost objects pointing to the same Extension are |
263 // present. | 300 // present. |
264 if (extension_ == | 301 if (extension_ == |
265 content::Details<UnloadedExtensionInfo>(details)->extension) { | 302 content::Details<UnloadedExtensionInfo>(details)->extension) { |
266 extension_ = NULL; | 303 extension_ = NULL; |
267 } | 304 } |
268 break; | 305 break; |
269 default: | 306 default: |
270 NOTREACHED() << "Unexpected notification sent."; | 307 NOTREACHED() << "Unexpected notification sent."; |
271 break; | 308 break; |
272 } | 309 } |
273 } | 310 } |
274 | 311 |
275 void ExtensionHost::UpdatePreferredSize(TabContents* source, | 312 void ExtensionHost::UpdatePreferredSize(const gfx::Size& new_size) { |
276 const gfx::Size& pref_size) { | |
277 if (view_.get()) | 313 if (view_.get()) |
278 view_->UpdatePreferredSize(pref_size); | 314 view_->UpdatePreferredSize(new_size); |
279 } | 315 } |
280 | 316 |
281 void ExtensionHost::RenderViewGone(base::TerminationStatus status) { | 317 void ExtensionHost::RenderViewGone(RenderViewHost* render_view_host, |
| 318 base::TerminationStatus status, |
| 319 int error_code) { |
282 // During browser shutdown, we may use sudden termination on an extension | 320 // During browser shutdown, we may use sudden termination on an extension |
283 // process, so it is expected to lose our connection to the render view. | 321 // process, so it is expected to lose our connection to the render view. |
284 // Do nothing. | 322 // Do nothing. |
285 if (browser_shutdown::GetShutdownType() != browser_shutdown::NOT_VALID) | 323 if (browser_shutdown::GetShutdownType() != browser_shutdown::NOT_VALID) |
286 return; | 324 return; |
287 | 325 |
288 // In certain cases, multiple ExtensionHost objects may have pointed to | 326 // In certain cases, multiple ExtensionHost objects may have pointed to |
289 // the same Extension at some point (one with a background page and a | 327 // the same Extension at some point (one with a background page and a |
290 // popup, for example). When the first ExtensionHost goes away, the extension | 328 // popup, for example). When the first ExtensionHost goes away, the extension |
291 // is unloaded, and any other host that pointed to that extension will have | 329 // is unloaded, and any other host that pointed to that extension will have |
292 // its pointer to it NULLed out so that any attempt to unload a dirty pointer | 330 // its pointer to it NULLed out so that any attempt to unload a dirty pointer |
293 // will be averted. | 331 // will be averted. |
294 if (!extension_) | 332 if (!extension_) |
295 return; | 333 return; |
296 | 334 |
297 // TODO(aa): This is suspicious. There can be multiple views in an extension, | 335 // TODO(aa): This is suspicious. There can be multiple views in an extension, |
298 // and they aren't all going to use ExtensionHost. This should be in someplace | 336 // and they aren't all going to use ExtensionHost. This should be in someplace |
299 // more central, like EPM maybe. | 337 // more central, like EPM maybe. |
| 338 DCHECK_EQ(render_view_host_, render_view_host); |
300 content::NotificationService::current()->Notify( | 339 content::NotificationService::current()->Notify( |
301 chrome::NOTIFICATION_EXTENSION_PROCESS_TERMINATED, | 340 chrome::NOTIFICATION_EXTENSION_PROCESS_TERMINATED, |
302 content::Source<Profile>(profile_), | 341 content::Source<Profile>(profile_), |
303 content::Details<ExtensionHost>(this)); | 342 content::Details<ExtensionHost>(this)); |
304 } | 343 } |
305 | 344 |
| 345 void ExtensionHost::DidNavigate(RenderViewHost* render_view_host, |
| 346 const ViewHostMsg_FrameNavigate_Params& params) { |
| 347 // We only care when the outer frame changes. |
| 348 if (!content::PageTransitionIsMainFrame(params.transition)) |
| 349 return; |
| 350 |
| 351 url_ = params.url; |
| 352 } |
| 353 |
306 void ExtensionHost::InsertInfobarCSS() { | 354 void ExtensionHost::InsertInfobarCSS() { |
307 DCHECK(!is_background_page()); | 355 DCHECK(!is_background_page()); |
308 | 356 |
309 static const base::StringPiece css( | 357 static const base::StringPiece css( |
310 ResourceBundle::GetSharedInstance().GetRawDataResource( | 358 ResourceBundle::GetSharedInstance().GetRawDataResource( |
311 IDR_EXTENSIONS_INFOBAR_CSS)); | 359 IDR_EXTENSIONS_INFOBAR_CSS)); |
312 | 360 |
313 render_view_host()->InsertCSS(string16(), css.as_string()); | 361 render_view_host()->InsertCSS(string16(), css.as_string()); |
314 } | 362 } |
315 | 363 |
316 void ExtensionHost::DisableScrollbarsForSmallWindows( | 364 void ExtensionHost::DisableScrollbarsForSmallWindows( |
317 const gfx::Size& size_limit) { | 365 const gfx::Size& size_limit) { |
318 render_view_host()->DisableScrollbarsForThreshold(size_limit); | 366 render_view_host()->DisableScrollbarsForThreshold(size_limit); |
319 } | 367 } |
320 | 368 |
321 void ExtensionHost::DidStopLoading() { | 369 void ExtensionHost::DidStopLoading() { |
322 bool notify = !did_stop_loading_; | 370 bool notify = !did_stop_loading_; |
323 did_stop_loading_ = true; | 371 did_stop_loading_ = true; |
324 if (extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_POPUP || | 372 if (extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_POPUP || |
325 extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_DIALOG || | 373 extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_DIALOG || |
326 extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_INFOBAR) { | 374 extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_INFOBAR) { |
327 #if defined(TOOLKIT_VIEWS) || defined(OS_MACOSX) | 375 #if defined(TOOLKIT_VIEWS) |
328 if (view_.get()) | 376 if (view_.get()) |
329 view_->DidStopLoading(); | 377 view_->DidStopLoading(); |
330 #endif | 378 #endif |
331 } | 379 } |
332 if (notify) { | 380 if (notify) { |
333 content::NotificationService::current()->Notify( | 381 content::NotificationService::current()->Notify( |
334 chrome::NOTIFICATION_EXTENSION_HOST_DID_STOP_LOADING, | 382 chrome::NOTIFICATION_EXTENSION_HOST_DID_STOP_LOADING, |
335 content::Source<Profile>(profile_), | 383 content::Source<Profile>(profile_), |
336 content::Details<ExtensionHost>(this)); | 384 content::Details<ExtensionHost>(this)); |
337 if (extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_BACKGROUND_PAGE) { | 385 if (extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_BACKGROUND_PAGE) { |
338 UMA_HISTOGRAM_TIMES("Extensions.BackgroundPageLoadTime", | 386 UMA_HISTOGRAM_TIMES("Extensions.BackgroundPageLoadTime", |
339 since_created_.Elapsed()); | 387 since_created_.Elapsed()); |
340 } else if (extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_DIALOG) { | 388 } else if (extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_DIALOG) { |
341 UMA_HISTOGRAM_TIMES("Extensions.DialogLoadTime", | 389 UMA_HISTOGRAM_TIMES("Extensions.DialogLoadTime", |
342 since_created_.Elapsed()); | 390 since_created_.Elapsed()); |
343 } else if (extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_POPUP) { | 391 } else if (extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_POPUP) { |
344 UMA_HISTOGRAM_TIMES("Extensions.PopupLoadTime", | 392 UMA_HISTOGRAM_TIMES("Extensions.PopupLoadTime", |
345 since_created_.Elapsed()); | 393 since_created_.Elapsed()); |
346 } else if (extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_INFOBAR) { | 394 } else if (extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_INFOBAR) { |
347 UMA_HISTOGRAM_TIMES("Extensions.InfobarLoadTime", | 395 UMA_HISTOGRAM_TIMES("Extensions.InfobarLoadTime", |
348 since_created_.Elapsed()); | 396 since_created_.Elapsed()); |
349 } | 397 } |
350 } | 398 } |
351 } | 399 } |
352 | 400 |
353 void ExtensionHost::DocumentAvailableInMainFrame() { | 401 void ExtensionHost::DocumentAvailableInMainFrame(RenderViewHost* rvh) { |
354 // If the document has already been marked as available for this host, then | 402 // If the document has already been marked as available for this host, then |
355 // bail. No need for the redundant setup. http://crbug.com/31170 | 403 // bail. No need for the redundant setup. http://crbug.com/31170 |
356 if (document_element_available_) | 404 if (document_element_available_) |
357 return; | 405 return; |
358 | 406 |
359 document_element_available_ = true; | 407 document_element_available_ = true; |
360 if (is_background_page()) { | 408 if (is_background_page()) { |
361 profile_->GetExtensionService()->SetBackgroundPageReady(extension_); | 409 profile_->GetExtensionService()->SetBackgroundPageReady(extension_); |
362 } else { | 410 } else { |
363 switch (extension_host_type_) { | 411 switch (extension_host_type_) { |
364 case chrome::VIEW_TYPE_EXTENSION_INFOBAR: | 412 case chrome::VIEW_TYPE_EXTENSION_INFOBAR: |
365 InsertInfobarCSS(); | 413 InsertInfobarCSS(); |
366 break; | 414 break; |
367 default: | 415 default: |
368 break; // No style sheet for other types, at the moment. | 416 break; // No style sheet for other types, at the moment. |
369 } | 417 } |
370 } | 418 } |
371 } | 419 } |
372 | 420 |
373 void ExtensionHost::CloseContents(TabContents* contents) { | 421 void ExtensionHost::DocumentOnLoadCompletedInMainFrame(RenderViewHost* rvh, |
| 422 int32 page_id) { |
| 423 if (chrome::VIEW_TYPE_EXTENSION_POPUP == GetRenderViewType()) { |
| 424 content::NotificationService::current()->Notify( |
| 425 chrome::NOTIFICATION_EXTENSION_POPUP_VIEW_READY, |
| 426 content::Source<Profile>(profile_), |
| 427 content::Details<ExtensionHost>(this)); |
| 428 } |
| 429 } |
| 430 |
| 431 void ExtensionHost::RunJavaScriptMessage(const RenderViewHost* rvh, |
| 432 const string16& message, |
| 433 const string16& default_prompt, |
| 434 const GURL& frame_url, |
| 435 const int flags, |
| 436 IPC::Message* reply_msg, |
| 437 bool* did_suppress_message) { |
| 438 bool suppress_this_message = false; |
| 439 |
| 440 string16 title; |
| 441 if (extension_->location() == Extension::COMPONENT) |
| 442 title = l10n_util::GetStringUTF16(IDS_PRODUCT_NAME); |
| 443 else |
| 444 title = UTF8ToUTF16(extension_->name()); |
| 445 |
| 446 GetJavaScriptDialogCreatorInstance()->RunJavaScriptDialog( |
| 447 this, |
| 448 content::JavaScriptDialogCreator::DIALOG_TITLE_PLAIN_STRING, |
| 449 title, |
| 450 flags, |
| 451 message, |
| 452 default_prompt, |
| 453 reply_msg, |
| 454 &suppress_this_message); |
| 455 |
| 456 if (suppress_this_message) { |
| 457 // If we are suppressing messages, just reply as if the user immediately |
| 458 // pressed "Cancel". |
| 459 OnDialogClosed(reply_msg, false, string16()); |
| 460 } |
| 461 |
| 462 *did_suppress_message = suppress_this_message; |
| 463 } |
| 464 |
| 465 gfx::NativeWindow ExtensionHost::GetDialogRootWindow() { |
| 466 // If we have a view, use that. |
| 467 gfx::NativeView native_view = GetNativeViewOfHost(); |
| 468 if (native_view) |
| 469 return platform_util::GetTopLevel(native_view); |
| 470 |
| 471 // Otherwise, try the active tab's view. |
| 472 Browser* browser = extension_function_dispatcher_.GetCurrentBrowser( |
| 473 render_view_host_, true); |
| 474 if (browser) { |
| 475 TabContents* active_tab = browser->GetSelectedTabContents(); |
| 476 if (active_tab) |
| 477 return active_tab->view()->GetTopLevelNativeWindow(); |
| 478 } |
| 479 |
| 480 return NULL; |
| 481 } |
| 482 |
| 483 void ExtensionHost::OnDialogClosed(IPC::Message* reply_msg, |
| 484 bool success, |
| 485 const string16& user_input) { |
| 486 render_view_host()->JavaScriptDialogClosed(reply_msg, |
| 487 success, |
| 488 user_input); |
| 489 } |
| 490 |
| 491 void ExtensionHost::Close(RenderViewHost* render_view_host) { |
374 if (extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_POPUP || | 492 if (extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_POPUP || |
375 extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_DIALOG || | 493 extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_DIALOG || |
376 extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_BACKGROUND_PAGE || | 494 extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_BACKGROUND_PAGE || |
377 extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_INFOBAR) { | 495 extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_INFOBAR) { |
378 content::NotificationService::current()->Notify( | 496 content::NotificationService::current()->Notify( |
379 chrome::NOTIFICATION_EXTENSION_HOST_VIEW_SHOULD_CLOSE, | 497 chrome::NOTIFICATION_EXTENSION_HOST_VIEW_SHOULD_CLOSE, |
380 content::Source<Profile>(profile_), | 498 content::Source<Profile>(profile_), |
381 content::Details<ExtensionHost>(this)); | 499 content::Details<ExtensionHost>(this)); |
382 } | 500 } |
383 } | 501 } |
384 | 502 |
| 503 content::RendererPreferences ExtensionHost::GetRendererPrefs( |
| 504 content::BrowserContext* browser_context) const { |
| 505 Profile* profile = Profile::FromBrowserContext(browser_context); |
| 506 content::RendererPreferences preferences; |
| 507 |
| 508 TabContents* associated_contents = GetAssociatedTabContents(); |
| 509 if (associated_contents) |
| 510 preferences = |
| 511 static_cast<RenderViewHostDelegate*>(associated_contents)-> |
| 512 GetRendererPrefs(profile); |
| 513 |
| 514 renderer_preferences_util::UpdateFromSystemSettings(&preferences, profile); |
| 515 return preferences; |
| 516 } |
| 517 |
| 518 WebPreferences ExtensionHost::GetWebkitPrefs() { |
| 519 WebPreferences webkit_prefs = |
| 520 RenderViewHostDelegateHelper::GetWebkitPrefs(render_view_host()); |
| 521 |
| 522 // Disable anything that requires the GPU process for background pages. |
| 523 // See http://crbug.com/64512 and http://crbug.com/64841. |
| 524 if (extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_BACKGROUND_PAGE) { |
| 525 webkit_prefs.experimental_webgl_enabled = false; |
| 526 webkit_prefs.accelerated_compositing_enabled = false; |
| 527 webkit_prefs.accelerated_2d_canvas_enabled = false; |
| 528 } |
| 529 |
| 530 return webkit_prefs; |
| 531 } |
| 532 |
| 533 RenderViewHostDelegate::View* ExtensionHost::GetViewDelegate() { |
| 534 return this; |
| 535 } |
| 536 |
385 bool ExtensionHost::PreHandleKeyboardEvent(const NativeWebKeyboardEvent& event, | 537 bool ExtensionHost::PreHandleKeyboardEvent(const NativeWebKeyboardEvent& event, |
386 bool* is_keyboard_shortcut) { | 538 bool* is_keyboard_shortcut) { |
387 if (extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_POPUP && | 539 if (extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_POPUP && |
388 event.type == NativeWebKeyboardEvent::RawKeyDown && | 540 event.type == NativeWebKeyboardEvent::RawKeyDown && |
389 event.windowsKeyCode == ui::VKEY_ESCAPE) { | 541 event.windowsKeyCode == ui::VKEY_ESCAPE) { |
390 DCHECK(is_keyboard_shortcut != NULL); | 542 DCHECK(is_keyboard_shortcut != NULL); |
391 *is_keyboard_shortcut = true; | 543 *is_keyboard_shortcut = true; |
392 } | 544 } |
393 return false; | 545 return false; |
394 } | 546 } |
395 | 547 |
396 void ExtensionHost::HandleKeyboardEvent(const NativeWebKeyboardEvent& event) { | 548 void ExtensionHost::HandleKeyboardEvent(const NativeWebKeyboardEvent& event) { |
397 if (extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_POPUP) { | 549 if (extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_POPUP) { |
398 if (event.type == NativeWebKeyboardEvent::RawKeyDown && | 550 if (event.type == NativeWebKeyboardEvent::RawKeyDown && |
399 event.windowsKeyCode == ui::VKEY_ESCAPE) { | 551 event.windowsKeyCode == ui::VKEY_ESCAPE) { |
400 content::NotificationService::current()->Notify( | 552 content::NotificationService::current()->Notify( |
401 chrome::NOTIFICATION_EXTENSION_HOST_VIEW_SHOULD_CLOSE, | 553 chrome::NOTIFICATION_EXTENSION_HOST_VIEW_SHOULD_CLOSE, |
402 content::Source<Profile>(profile_), | 554 content::Source<Profile>(profile_), |
403 content::Details<ExtensionHost>(this)); | 555 content::Details<ExtensionHost>(this)); |
404 return; | 556 return; |
405 } | 557 } |
406 } | 558 } |
407 UnhandledKeyboardEvent(event); | 559 UnhandledKeyboardEvent(event); |
408 } | 560 } |
409 | 561 |
410 bool ExtensionHost::OnMessageReceived(const IPC::Message& message) { | 562 void ExtensionHost::HandleMouseMove() { |
411 bool handled = true; | 563 #if defined(OS_WIN) |
412 IPC_BEGIN_MESSAGE_MAP(ExtensionHost, message) | 564 if (view_.get()) |
413 IPC_MESSAGE_HANDLER(ExtensionHostMsg_Request, OnRequest) | 565 view_->HandleMouseMove(); |
414 IPC_MESSAGE_UNHANDLED(handled = false) | 566 #endif |
415 IPC_END_MESSAGE_MAP() | |
416 return handled; | |
417 } | 567 } |
418 | 568 |
419 void ExtensionHost::OnRequest(const ExtensionHostMsg_Request_Params& params) { | 569 void ExtensionHost::HandleMouseDown() { |
420 extension_function_dispatcher_.Dispatch(params, render_view_host()); | |
421 } | 570 } |
422 | 571 |
423 void ExtensionHost::RenderViewCreated(RenderViewHost* render_view_host) { | 572 void ExtensionHost::HandleMouseLeave() { |
| 573 #if defined(OS_WIN) |
424 if (view_.get()) | 574 if (view_.get()) |
425 view_->RenderViewCreated(); | 575 view_->HandleMouseLeave(); |
426 | 576 #endif |
427 if (extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_POPUP || | |
428 extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_INFOBAR) { | |
429 render_view_host->EnablePreferredSizeMode( | |
430 kPreferredSizeWidth | kPreferredSizeHeightThisIsSlow); | |
431 } | |
432 | |
433 // If the host is bound to a browser, then extract its window id. | |
434 // Extensions hosted in ExternalTabContainer objects may not have | |
435 // an associated browser. | |
436 const Browser* browser = GetBrowser(); | |
437 if (browser) { | |
438 render_view_host->Send(new ExtensionMsg_UpdateBrowserWindowId( | |
439 render_view_host->routing_id(), | |
440 ExtensionTabUtil::GetWindowId(browser))); | |
441 } | |
442 } | 577 } |
443 | 578 |
444 content::JavaScriptDialogCreator* ExtensionHost::GetJavaScriptDialogCreator() { | 579 void ExtensionHost::HandleMouseUp() { |
445 return GetJavaScriptDialogCreatorInstance(); | |
446 } | 580 } |
447 | 581 |
448 void ExtensionHost::AddNewContents(TabContents* source, | 582 void ExtensionHost::HandleMouseActivate() { |
449 TabContents* new_contents, | 583 } |
450 WindowOpenDisposition disposition, | 584 |
451 const gfx::Rect& initial_pos, | 585 void ExtensionHost::RunFileChooser( |
452 bool user_gesture) { | 586 RenderViewHost* render_view_host, |
453 // TODO(mpcomplete): is all this necessary? Maybe we can just call the | 587 const ViewHostMsg_RunFileChooser_Params& params) { |
454 // brower's delegate, and fall back to browser::Navigate if browser is NULL. | 588 // FileSelectHelper adds a reference to itself and only releases it after |
455 TabContents* contents = new_contents; | 589 // sending the result message. It won't be destroyed when this reference |
| 590 // goes out of scope. |
| 591 scoped_refptr<FileSelectHelper> file_select_helper( |
| 592 new FileSelectHelper(profile())); |
| 593 file_select_helper->RunFileChooser(render_view_host, |
| 594 GetAssociatedTabContents(), |
| 595 params); |
| 596 } |
| 597 |
| 598 void ExtensionHost::CreateNewWindow( |
| 599 int route_id, |
| 600 const ViewHostMsg_CreateWindow_Params& params) { |
| 601 // TODO(aa): Use the browser's profile if the extension is split mode |
| 602 // incognito. |
| 603 Profile* profile = Profile::FromBrowserContext( |
| 604 render_view_host()->process()->browser_context()); |
| 605 TabContents* new_contents = delegate_view_helper_.CreateNewWindow( |
| 606 route_id, |
| 607 profile, |
| 608 site_instance(), |
| 609 ChromeWebUIFactory::GetInstance()->GetWebUIType( |
| 610 render_view_host()->process()->browser_context(), url_), |
| 611 this, |
| 612 params.window_container_type, |
| 613 params.frame_name); |
| 614 |
| 615 TabContents* associated_contents = GetAssociatedTabContents(); |
| 616 if (associated_contents && associated_contents->delegate()) |
| 617 associated_contents->delegate()->TabContentsCreated(new_contents); |
| 618 } |
| 619 |
| 620 void ExtensionHost::CreateNewWidget(int route_id, |
| 621 WebKit::WebPopupType popup_type) { |
| 622 CreateNewWidgetInternal(route_id, popup_type); |
| 623 } |
| 624 |
| 625 void ExtensionHost::CreateNewFullscreenWidget(int route_id) { |
| 626 NOTREACHED() |
| 627 << "ExtensionHost does not support showing full screen popups yet."; |
| 628 } |
| 629 |
| 630 RenderWidgetHostView* ExtensionHost::CreateNewWidgetInternal( |
| 631 int route_id, WebKit::WebPopupType popup_type) { |
| 632 return delegate_view_helper_.CreateNewWidget(route_id, popup_type, |
| 633 site_instance()->GetProcess()); |
| 634 } |
| 635 |
| 636 void ExtensionHost::ShowCreatedWindow(int route_id, |
| 637 WindowOpenDisposition disposition, |
| 638 const gfx::Rect& initial_pos, |
| 639 bool user_gesture) { |
| 640 TabContents* contents = delegate_view_helper_.GetCreatedWindow(route_id); |
456 if (!contents) | 641 if (!contents) |
457 return; | 642 return; |
458 Profile* profile = Profile::FromBrowserContext(contents->browser_context()); | 643 Profile* profile = Profile::FromBrowserContext(contents->browser_context()); |
459 | 644 |
460 if (disposition == NEW_POPUP) { | 645 if (disposition == NEW_POPUP) { |
461 // Find a browser with a matching profile for creating a popup. | 646 // Find a browser with a matching profile for creating a popup. |
462 // (If none is found, NULL argument to NavigateParams is valid.) | 647 // (If none is found, NULL argument to NavigateParams is valid.) |
463 Browser* browser = BrowserList::FindTabbedBrowser( | 648 Browser* browser = BrowserList::FindTabbedBrowser( |
464 profile, false); // Match incognito exactly. | 649 profile, false); // Match incognito exactly. |
465 TabContentsWrapper* wrapper = new TabContentsWrapper(contents); | 650 TabContentsWrapper* wrapper = new TabContentsWrapper(contents); |
466 browser::NavigateParams params(browser, wrapper); | 651 browser::NavigateParams params(browser, wrapper); |
467 if (!browser) | 652 if (!browser) |
468 params.profile = profile; | 653 params.profile = profile; |
469 // The extension_app_id parameter ends up as app_name in the Browser | 654 // The extension_app_id parameter ends up as app_name in the Browser |
470 // which causes the Browser to return true for is_app(). This affects | 655 // which causes the Browser to return true for is_app(). This affects |
471 // among other things, whether the location bar gets displayed. | 656 // among other things, whether the location bar gets displayed. |
472 params.extension_app_id = extension_id_; | 657 params.extension_app_id = extension_id_; |
473 params.disposition = NEW_POPUP; | 658 params.disposition = NEW_POPUP; |
474 params.window_bounds = initial_pos; | 659 params.window_bounds = initial_pos; |
475 params.window_action = browser::NavigateParams::SHOW_WINDOW; | 660 params.window_action = browser::NavigateParams::SHOW_WINDOW; |
476 params.user_gesture = user_gesture; | 661 params.user_gesture = user_gesture; |
477 browser::Navigate(¶ms); | 662 browser::Navigate(¶ms); |
478 return; | 663 return; |
479 } | 664 } |
480 | 665 |
| 666 // If the tab contents isn't a popup, it's a normal tab. We need to find a |
| 667 // home for it. This is typically a Browser, but it can also be some other |
| 668 // TabContentsDelegate in the case of ChromeFrame. |
| 669 |
481 // First, if the creating extension view was associated with a tab contents, | 670 // First, if the creating extension view was associated with a tab contents, |
482 // use that tab content's delegate. We must be careful here that the | 671 // use that tab content's delegate. We must be careful here that the |
483 // associated tab contents has the same profile as the new tab contents. In | 672 // associated tab contents has the same profile as the new tab contents. In |
484 // the case of extensions in 'spanning' incognito mode, they can mismatch. | 673 // the case of extensions in 'spanning' incognito mode, they can mismatch. |
485 // We don't want to end up putting a normal tab into an incognito window, or | 674 // We don't want to end up putting a normal tab into an incognito window, or |
486 // vice versa. | 675 // vice versa. |
487 TabContents* associated_contents = GetAssociatedTabContents(); | 676 TabContents* associated_contents = GetAssociatedTabContents(); |
488 if (associated_contents && | 677 if (associated_contents && |
489 associated_contents->browser_context() == contents->browser_context()) { | 678 associated_contents->browser_context() == contents->browser_context()) { |
490 associated_contents->AddNewContents( | 679 associated_contents->AddNewContents( |
491 contents, disposition, initial_pos, user_gesture); | 680 contents, disposition, initial_pos, user_gesture); |
492 return; | 681 return; |
493 } | 682 } |
494 | 683 |
495 // If there's no associated tab contents, or it doesn't have a matching | 684 // If there's no associated tab contents, or it doesn't have a matching |
496 // profile, try finding an open window. Again, we must make sure to find a | 685 // profile, try finding an open window. Again, we must make sure to find a |
497 // window with the correct profile. | 686 // window with the correct profile. |
498 Browser* browser = BrowserList::FindTabbedBrowser( | 687 Browser* browser = BrowserList::FindTabbedBrowser( |
499 profile, false); // Match incognito exactly. | 688 profile, false); // Match incognito exactly. |
500 | 689 |
501 // If there's no Browser open with the right profile, create a new one. | 690 // If there's no Browser open with the right profile, create a new one. |
502 if (!browser) { | 691 if (!browser) { |
503 browser = Browser::Create(profile); | 692 browser = Browser::Create(profile); |
504 browser->window()->Show(); | 693 browser->window()->Show(); |
505 } | 694 } |
506 browser->AddTabContents(contents, disposition, initial_pos, user_gesture); | 695 browser->AddTabContents(contents, disposition, initial_pos, user_gesture); |
507 } | 696 } |
508 | 697 |
| 698 void ExtensionHost::ShowCreatedWidget(int route_id, |
| 699 const gfx::Rect& initial_pos) { |
| 700 ShowCreatedWidgetInternal(delegate_view_helper_.GetCreatedWidget(route_id), |
| 701 initial_pos); |
| 702 } |
509 | 703 |
510 void ExtensionHost::RenderViewReady() { | 704 void ExtensionHost::ShowCreatedFullscreenWidget(int route_id) { |
| 705 NOTREACHED() |
| 706 << "ExtensionHost does not support showing full screen popups yet."; |
| 707 } |
| 708 |
| 709 void ExtensionHost::ShowCreatedWidgetInternal( |
| 710 RenderWidgetHostView* widget_host_view, |
| 711 const gfx::Rect& initial_pos) { |
| 712 Browser *browser = GetBrowser(); |
| 713 DCHECK(browser); |
| 714 if (!browser) |
| 715 return; |
| 716 browser->BrowserRenderWidgetShowing(); |
| 717 // TODO(erikkay): These two lines could be refactored with TabContentsView. |
| 718 widget_host_view->InitAsPopup(render_view_host()->view(), initial_pos); |
| 719 widget_host_view->GetRenderWidgetHost()->Init(); |
| 720 } |
| 721 |
| 722 void ExtensionHost::ShowContextMenu(const ContextMenuParams& params) { |
| 723 // TODO(erikkay) Show a default context menu. |
| 724 } |
| 725 |
| 726 void ExtensionHost::ShowPopupMenu(const gfx::Rect& bounds, |
| 727 int item_height, |
| 728 double item_font_size, |
| 729 int selected_item, |
| 730 const std::vector<WebMenuItem>& items, |
| 731 bool right_aligned) { |
| 732 #if defined(OS_MACOSX) |
| 733 PopupMenuHelper popup_menu_helper(render_view_host()); |
| 734 popup_menu_helper.ShowPopupMenu(bounds, item_height, item_font_size, |
| 735 selected_item, items, right_aligned); |
| 736 #else |
| 737 // Only on Mac are select popup menus external. |
| 738 NOTREACHED(); |
| 739 #endif |
| 740 } |
| 741 |
| 742 void ExtensionHost::StartDragging(const WebDropData& drop_data, |
| 743 WebDragOperationsMask operation_mask, |
| 744 const SkBitmap& image, |
| 745 const gfx::Point& image_offset) { |
| 746 // We're not going to do any drag & drop, but we have to tell the renderer the |
| 747 // drag & drop ended, othewise the renderer thinks the drag operation is |
| 748 // underway and mouse events won't work. See bug 34061. |
| 749 // TODO(twiz) Implement drag & drop support for ExtensionHost instances. |
| 750 // See feature issue 36288. |
| 751 render_view_host()->DragSourceSystemDragEnded(); |
| 752 } |
| 753 |
| 754 void ExtensionHost::UpdateDragCursor(WebDragOperation operation) { |
| 755 } |
| 756 |
| 757 void ExtensionHost::GotFocus() { |
| 758 #if defined(TOOLKIT_VIEWS) && !defined(TOUCH_UI) |
| 759 // Request focus so that the FocusManager has a focused view and can perform |
| 760 // normally its key event processing (so that it lets tab key events go to the |
| 761 // renderer). |
| 762 view()->RequestFocus(); |
| 763 #else |
| 764 // TODO(port) |
| 765 #endif |
| 766 } |
| 767 |
| 768 void ExtensionHost::TakeFocus(bool reverse) { |
| 769 } |
| 770 |
| 771 content::ViewType ExtensionHost::GetRenderViewType() const { |
| 772 return extension_host_type_; |
| 773 } |
| 774 |
| 775 bool ExtensionHost::OnMessageReceived(const IPC::Message& message) { |
| 776 bool handled = true; |
| 777 IPC_BEGIN_MESSAGE_MAP(ExtensionHost, message) |
| 778 IPC_MESSAGE_HANDLER(ExtensionHostMsg_Request, OnRequest) |
| 779 IPC_MESSAGE_UNHANDLED(handled = false) |
| 780 IPC_END_MESSAGE_MAP() |
| 781 return handled; |
| 782 } |
| 783 |
| 784 void ExtensionHost::OnRequest(const ExtensionHostMsg_Request_Params& params) { |
| 785 extension_function_dispatcher_.Dispatch(params, render_view_host_); |
| 786 } |
| 787 |
| 788 const GURL& ExtensionHost::GetURL() const { |
| 789 return url_; |
| 790 } |
| 791 |
| 792 void ExtensionHost::RenderViewCreated(RenderViewHost* render_view_host) { |
| 793 if (view_.get()) |
| 794 view_->RenderViewCreated(); |
| 795 |
| 796 if (extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_POPUP || |
| 797 extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_INFOBAR) { |
| 798 render_view_host->EnablePreferredSizeMode( |
| 799 kPreferredSizeWidth | kPreferredSizeHeightThisIsSlow); |
| 800 } |
| 801 } |
| 802 |
| 803 void ExtensionHost::RenderViewReady(RenderViewHost* render_view_host) { |
511 content::NotificationService::current()->Notify( | 804 content::NotificationService::current()->Notify( |
512 chrome::NOTIFICATION_EXTENSION_HOST_CREATED, | 805 chrome::NOTIFICATION_EXTENSION_HOST_CREATED, |
513 content::Source<Profile>(profile_), | 806 content::Source<Profile>(profile_), |
514 content::Details<ExtensionHost>(this)); | 807 content::Details<ExtensionHost>(this)); |
515 } | 808 } |
OLD | NEW |