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" | |
21 #include "chrome/browser/profiles/profile.h" | 19 #include "chrome/browser/profiles/profile.h" |
22 #include "chrome/browser/renderer_preferences_util.h" | |
23 #include "chrome/browser/tabs/tab_strip_model.h" | |
24 #include "chrome/browser/ui/app_modal_dialogs/message_box_handler.h" | 20 #include "chrome/browser/ui/app_modal_dialogs/message_box_handler.h" |
25 #include "chrome/browser/ui/browser.h" | 21 #include "chrome/browser/ui/browser.h" |
26 #include "chrome/browser/ui/browser_list.h" | 22 #include "chrome/browser/ui/browser_list.h" |
27 #include "chrome/browser/ui/browser_window.h" | 23 #include "chrome/browser/ui/browser_window.h" |
28 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" | 24 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" |
29 #include "chrome/browser/ui/webui/chrome_web_ui_factory.h" | |
30 #include "chrome/common/chrome_constants.h" | 25 #include "chrome/common/chrome_constants.h" |
31 #include "chrome/common/chrome_notification_types.h" | 26 #include "chrome/common/chrome_notification_types.h" |
32 #include "chrome/common/extensions/extension.h" | 27 #include "chrome/common/extensions/extension.h" |
33 #include "chrome/common/extensions/extension_constants.h" | 28 #include "chrome/common/extensions/extension_constants.h" |
34 #include "chrome/common/extensions/extension_messages.h" | 29 #include "chrome/common/extensions/extension_messages.h" |
35 #include "chrome/common/render_messages.h" | 30 #include "chrome/common/render_messages.h" |
36 #include "chrome/common/url_constants.h" | 31 #include "chrome/common/url_constants.h" |
37 #include "chrome/common/chrome_view_types.h" | 32 #include "chrome/common/chrome_view_types.h" |
38 #include "content/browser/browsing_instance.h" | 33 #include "content/browser/browsing_instance.h" |
39 #include "content/browser/renderer_host/browser_render_process_host.h" | 34 #include "content/browser/renderer_host/browser_render_process_host.h" |
40 #include "content/browser/renderer_host/render_process_host.h" | 35 #include "content/browser/renderer_host/render_process_host.h" |
41 #include "content/browser/renderer_host/render_view_host.h" | 36 #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" | |
46 #include "content/browser/tab_contents/tab_contents.h" | 37 #include "content/browser/tab_contents/tab_contents.h" |
47 #include "content/browser/tab_contents/tab_contents_view.h" | 38 #include "content/browser/tab_contents/tab_contents_view.h" |
48 #include "content/public/browser/notification_service.h" | 39 #include "content/public/browser/notification_service.h" |
49 #include "content/common/view_messages.h" | 40 #include "content/common/view_messages.h" |
50 #include "content/public/browser/content_browser_client.h" | 41 #include "content/public/browser/content_browser_client.h" |
51 #include "content/public/browser/native_web_keyboard_event.h" | 42 #include "content/public/browser/native_web_keyboard_event.h" |
52 #include "content/public/common/bindings_policy.h" | |
53 #include "grit/browser_resources.h" | 43 #include "grit/browser_resources.h" |
54 #include "grit/chromium_strings.h" | 44 #include "grit/chromium_strings.h" |
55 #include "grit/generated_resources.h" | 45 #include "grit/generated_resources.h" |
56 #include "ui/base/keycodes/keyboard_codes.h" | 46 #include "ui/base/keycodes/keyboard_codes.h" |
57 #include "ui/base/l10n/l10n_util.h" | 47 #include "ui/base/l10n/l10n_util.h" |
58 #include "ui/base/resource/resource_bundle.h" | 48 #include "ui/base/resource/resource_bundle.h" |
59 #include "webkit/glue/context_menu.h" | |
60 | 49 |
61 #if defined(TOOLKIT_VIEWS) | 50 #if defined(TOOLKIT_VIEWS) |
62 #include "views/widget/widget.h" | 51 #include "views/widget/widget.h" |
63 #endif | 52 #endif |
64 | 53 |
65 using WebKit::WebDragOperation; | 54 using WebKit::WebDragOperation; |
66 using WebKit::WebDragOperationsMask; | 55 using WebKit::WebDragOperationsMask; |
67 | 56 |
68 // static | |
69 bool ExtensionHost::enable_dom_automation_ = false; | |
70 | |
71 // Helper class that rate-limits the creation of renderer processes for | 57 // Helper class that rate-limits the creation of renderer processes for |
72 // ExtensionHosts, to avoid blocking the UI. | 58 // ExtensionHosts, to avoid blocking the UI. |
73 class ExtensionHost::ProcessCreationQueue { | 59 class ExtensionHost::ProcessCreationQueue { |
74 public: | 60 public: |
75 static ProcessCreationQueue* GetInstance() { | 61 static ProcessCreationQueue* GetInstance() { |
76 return Singleton<ProcessCreationQueue>::get(); | 62 return Singleton<ProcessCreationQueue>::get(); |
77 } | 63 } |
78 | 64 |
79 // Add a host to the queue for RenderView creation. | 65 // Add a host to the queue for RenderView creation. |
80 void CreateSoon(ExtensionHost* host) { | 66 void CreateSoon(ExtensionHost* host) { |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
131 ExtensionHost::ExtensionHost(const Extension* extension, | 117 ExtensionHost::ExtensionHost(const Extension* extension, |
132 SiteInstance* site_instance, | 118 SiteInstance* site_instance, |
133 const GURL& url, | 119 const GURL& url, |
134 content::ViewType host_type) | 120 content::ViewType host_type) |
135 : extension_(extension), | 121 : extension_(extension), |
136 extension_id_(extension->id()), | 122 extension_id_(extension->id()), |
137 profile_(Profile::FromBrowserContext( | 123 profile_(Profile::FromBrowserContext( |
138 site_instance->browsing_instance()->browser_context())), | 124 site_instance->browsing_instance()->browser_context())), |
139 did_stop_loading_(false), | 125 did_stop_loading_(false), |
140 document_element_available_(false), | 126 document_element_available_(false), |
141 url_(url), | 127 initial_url_(url), |
142 ALLOW_THIS_IN_INITIALIZER_LIST( | 128 ALLOW_THIS_IN_INITIALIZER_LIST( |
143 extension_function_dispatcher_(profile_, this)), | 129 extension_function_dispatcher_(profile_, this)), |
144 extension_host_type_(host_type), | 130 extension_host_type_(host_type), |
145 associated_tab_contents_(NULL) { | 131 associated_tab_contents_(NULL) { |
146 render_view_host_ = new RenderViewHost(site_instance, this, MSG_ROUTING_NONE, | 132 host_contents_.reset(new TabContents( |
147 NULL); | 133 profile_, site_instance, MSG_ROUTING_NONE, NULL, NULL)); |
148 if (enable_dom_automation_) | 134 TabContentsObserver::Observe(host_contents_.get()); |
149 render_view_host_->AllowBindings(content::BINDINGS_POLICY_DOM_AUTOMATION); | 135 host_contents_->set_delegate(this); |
| 136 host_contents_->set_view_type(host_type); |
150 | 137 |
151 // Listen for when an extension is unloaded from the same profile, as it may | 138 // Listen for when an extension is unloaded from the same profile, as it may |
152 // be the same extension that this points to. | 139 // be the same extension that this points to. |
153 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED, | 140 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED, |
154 content::Source<Profile>(profile_)); | 141 content::Source<Profile>(profile_)); |
155 } | 142 } |
156 | 143 |
157 // This "mock" constructor should only be used by unit tests. | 144 // This "mock" constructor should only be used by unit tests. |
158 ExtensionHost::ExtensionHost(const Extension* extension, | 145 ExtensionHost::ExtensionHost(const Extension* extension, |
159 content::ViewType host_type) | 146 content::ViewType host_type) |
160 : extension_(extension), | 147 : extension_(extension), |
161 extension_id_(extension->id()), | 148 extension_id_(extension->id()), |
162 profile_(NULL), | 149 profile_(NULL), |
163 render_view_host_(NULL), | |
164 did_stop_loading_(false), | 150 did_stop_loading_(false), |
165 document_element_available_(false), | 151 document_element_available_(false), |
166 url_(GURL()), | 152 initial_url_(GURL()), |
167 ALLOW_THIS_IN_INITIALIZER_LIST( | 153 ALLOW_THIS_IN_INITIALIZER_LIST( |
168 extension_function_dispatcher_(profile_, this)), | 154 extension_function_dispatcher_(profile_, this)), |
169 extension_host_type_(host_type), | 155 extension_host_type_(host_type), |
170 associated_tab_contents_(NULL) { | 156 associated_tab_contents_(NULL) { |
171 } | 157 } |
172 | 158 |
173 ExtensionHost::~ExtensionHost() { | 159 ExtensionHost::~ExtensionHost() { |
174 content::NotificationService::current()->Notify( | 160 content::NotificationService::current()->Notify( |
175 chrome::NOTIFICATION_EXTENSION_HOST_DESTROYED, | 161 chrome::NOTIFICATION_EXTENSION_HOST_DESTROYED, |
176 content::Source<Profile>(profile_), | 162 content::Source<Profile>(profile_), |
177 content::Details<ExtensionHost>(this)); | 163 content::Details<ExtensionHost>(this)); |
178 ProcessCreationQueue::GetInstance()->Remove(this); | 164 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 | |
183 } | 165 } |
184 | 166 |
185 void ExtensionHost::CreateView(Browser* browser) { | 167 void ExtensionHost::CreateView(Browser* browser) { |
186 #if defined(TOOLKIT_VIEWS) | 168 #if defined(TOOLKIT_VIEWS) |
187 view_.reset(new ExtensionView(this, browser)); | 169 view_.reset(new ExtensionView(this, browser)); |
188 // We own |view_|, so don't auto delete when it's removed from the view | 170 // We own |view_|, so don't auto delete when it's removed from the view |
189 // hierarchy. | 171 // hierarchy. |
190 view_->set_parent_owned(false); | 172 view_->set_parent_owned(false); |
191 #elif defined(OS_MACOSX) | 173 #elif defined(OS_MACOSX) |
192 view_.reset(new ExtensionViewMac(this, browser)); | 174 view_.reset(new ExtensionViewMac(this, browser)); |
193 view_->Init(); | 175 view_->Init(); |
194 #elif defined(TOOLKIT_USES_GTK) | 176 #elif defined(TOOLKIT_USES_GTK) |
195 view_.reset(new ExtensionViewGtk(this, browser)); | 177 view_.reset(new ExtensionViewGtk(this, browser)); |
196 view_->Init(); | 178 view_->Init(); |
197 #else | 179 #else |
198 // TODO(port) | 180 // TODO(port) |
199 NOTREACHED(); | 181 NOTREACHED(); |
200 #endif | 182 #endif |
201 } | 183 } |
202 | 184 |
203 TabContents* ExtensionHost::GetAssociatedTabContents() const { | 185 TabContents* ExtensionHost::GetAssociatedTabContents() const { |
204 return associated_tab_contents_; | 186 return associated_tab_contents_; |
205 } | 187 } |
206 | 188 |
207 RenderProcessHost* ExtensionHost::render_process_host() const { | 189 RenderProcessHost* ExtensionHost::render_process_host() const { |
208 return render_view_host_->process(); | 190 return host_contents()->GetRenderProcessHost(); |
209 } | 191 } |
210 | 192 |
211 SiteInstance* ExtensionHost::site_instance() const { | 193 RenderViewHost* ExtensionHost::render_view_host() const { |
212 return render_view_host_->site_instance(); | 194 // TODO(mpcomplete): This can be NULL. How do we handle that? |
| 195 return host_contents()->render_view_host(); |
213 } | 196 } |
214 | 197 |
215 bool ExtensionHost::IsRenderViewLive() const { | 198 bool ExtensionHost::IsRenderViewLive() const { |
216 return render_view_host_->IsRenderViewLive(); | 199 return render_view_host()->IsRenderViewLive(); |
217 } | 200 } |
218 | 201 |
219 void ExtensionHost::CreateRenderViewSoon(RenderWidgetHostView* host_view) { | 202 void ExtensionHost::CreateRenderViewSoon() { |
220 render_view_host_->SetView(host_view); | 203 if (render_process_host()->HasConnection()) { |
221 if (render_view_host_->process()->HasConnection()) { | |
222 // If the process is already started, go ahead and initialize the RenderView | 204 // If the process is already started, go ahead and initialize the RenderView |
223 // synchronously. The process creation is the real meaty part that we want | 205 // synchronously. The process creation is the real meaty part that we want |
224 // to defer. | 206 // to defer. |
225 CreateRenderViewNow(); | 207 CreateRenderViewNow(); |
226 } else { | 208 } else { |
227 ProcessCreationQueue::GetInstance()->CreateSoon(this); | 209 ProcessCreationQueue::GetInstance()->CreateSoon(this); |
228 } | 210 } |
229 } | 211 } |
230 | 212 |
231 void ExtensionHost::CreateRenderViewNow() { | 213 void ExtensionHost::CreateRenderViewNow() { |
232 render_view_host_->CreateRenderView(string16()); | 214 LoadInitialURL(); |
233 if (extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_POPUP || | 215 if (is_background_page()) { |
234 extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_DIALOG || | 216 DCHECK(IsRenderViewLive()); |
235 extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_INFOBAR) { | 217 profile_->GetExtensionService()->DidCreateRenderViewForBackgroundPage(this); |
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 } | |
245 } | 218 } |
246 NavigateToURL(url_); | |
247 DCHECK(IsRenderViewLive()); | |
248 if (is_background_page()) | |
249 profile_->GetExtensionService()->DidCreateRenderViewForBackgroundPage( | |
250 this); | |
251 } | 219 } |
252 | 220 |
253 const Browser* ExtensionHost::GetBrowser() const { | 221 const Browser* ExtensionHost::GetBrowser() const { |
254 return view() ? view()->browser() : NULL; | 222 return view() ? view()->browser() : NULL; |
255 } | 223 } |
256 | 224 |
257 Browser* ExtensionHost::GetBrowser() { | 225 Browser* ExtensionHost::GetBrowser() { |
258 return view() ? view()->browser() : NULL; | 226 return view() ? view()->browser() : NULL; |
259 } | 227 } |
260 | 228 |
261 gfx::NativeView ExtensionHost::GetNativeViewOfHost() { | 229 gfx::NativeView ExtensionHost::GetNativeViewOfHost() { |
262 return view() ? view()->native_view() : NULL; | 230 return view() ? view()->native_view() : NULL; |
263 } | 231 } |
264 | 232 |
265 void ExtensionHost::NavigateToURL(const GURL& url) { | 233 const GURL& ExtensionHost::GetURL() const { |
266 // Prevent explicit navigation to another extension id's pages. | 234 return host_contents()->GetURL(); |
267 // This method is only called by some APIs, so we still need to protect | 235 } |
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 } | |
273 | 236 |
274 url_ = url; | 237 void ExtensionHost::LoadInitialURL() { |
275 | |
276 if (!is_background_page() && | 238 if (!is_background_page() && |
277 !profile_->GetExtensionService()->IsBackgroundPageReady(extension_)) { | 239 !profile_->GetExtensionService()->IsBackgroundPageReady(extension_)) { |
278 // Make sure the background page loads before any others. | 240 // Make sure the background page loads before any others. |
279 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_BACKGROUND_PAGE_READY, | 241 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_BACKGROUND_PAGE_READY, |
280 content::Source<Extension>(extension_)); | 242 content::Source<Extension>(extension_)); |
281 return; | 243 return; |
282 } | 244 } |
283 | 245 |
284 render_view_host_->NavigateToURL(url_); | 246 host_contents_->controller().LoadURL( |
| 247 initial_url_, GURL(), content::PAGE_TRANSITION_LINK, std::string()); |
285 } | 248 } |
286 | 249 |
287 void ExtensionHost::Observe(int type, | 250 void ExtensionHost::Observe(int type, |
288 const content::NotificationSource& source, | 251 const content::NotificationSource& source, |
289 const content::NotificationDetails& details) { | 252 const content::NotificationDetails& details) { |
290 switch (type) { | 253 switch (type) { |
291 case chrome::NOTIFICATION_EXTENSION_BACKGROUND_PAGE_READY: | 254 case chrome::NOTIFICATION_EXTENSION_BACKGROUND_PAGE_READY: |
292 DCHECK(profile_->GetExtensionService()-> | 255 DCHECK(profile_->GetExtensionService()-> |
293 IsBackgroundPageReady(extension_)); | 256 IsBackgroundPageReady(extension_)); |
294 NavigateToURL(url_); | 257 LoadInitialURL(); |
295 break; | 258 break; |
296 case chrome::NOTIFICATION_EXTENSION_UNLOADED: | 259 case chrome::NOTIFICATION_EXTENSION_UNLOADED: |
297 // The extension object will be deleted after this notification has been | 260 // The extension object will be deleted after this notification has been |
298 // sent. NULL it out so that dirty pointer issues don't arise in cases | 261 // sent. NULL it out so that dirty pointer issues don't arise in cases |
299 // when multiple ExtensionHost objects pointing to the same Extension are | 262 // when multiple ExtensionHost objects pointing to the same Extension are |
300 // present. | 263 // present. |
301 if (extension_ == | 264 if (extension_ == |
302 content::Details<UnloadedExtensionInfo>(details)->extension) { | 265 content::Details<UnloadedExtensionInfo>(details)->extension) { |
303 extension_ = NULL; | 266 extension_ = NULL; |
304 } | 267 } |
305 break; | 268 break; |
306 default: | 269 default: |
307 NOTREACHED() << "Unexpected notification sent."; | 270 NOTREACHED() << "Unexpected notification sent."; |
308 break; | 271 break; |
309 } | 272 } |
310 } | 273 } |
311 | 274 |
312 void ExtensionHost::UpdatePreferredSize(const gfx::Size& new_size) { | 275 void ExtensionHost::UpdatePreferredSize(TabContents* source, |
| 276 const gfx::Size& pref_size) { |
313 if (view_.get()) | 277 if (view_.get()) |
314 view_->UpdatePreferredSize(new_size); | 278 view_->UpdatePreferredSize(pref_size); |
315 } | 279 } |
316 | 280 |
317 void ExtensionHost::RenderViewGone(RenderViewHost* render_view_host, | 281 void ExtensionHost::RenderViewGone(base::TerminationStatus status) { |
318 base::TerminationStatus status, | |
319 int error_code) { | |
320 // During browser shutdown, we may use sudden termination on an extension | 282 // During browser shutdown, we may use sudden termination on an extension |
321 // process, so it is expected to lose our connection to the render view. | 283 // process, so it is expected to lose our connection to the render view. |
322 // Do nothing. | 284 // Do nothing. |
323 if (browser_shutdown::GetShutdownType() != browser_shutdown::NOT_VALID) | 285 if (browser_shutdown::GetShutdownType() != browser_shutdown::NOT_VALID) |
324 return; | 286 return; |
325 | 287 |
326 // In certain cases, multiple ExtensionHost objects may have pointed to | 288 // In certain cases, multiple ExtensionHost objects may have pointed to |
327 // the same Extension at some point (one with a background page and a | 289 // the same Extension at some point (one with a background page and a |
328 // popup, for example). When the first ExtensionHost goes away, the extension | 290 // popup, for example). When the first ExtensionHost goes away, the extension |
329 // is unloaded, and any other host that pointed to that extension will have | 291 // is unloaded, and any other host that pointed to that extension will have |
330 // its pointer to it NULLed out so that any attempt to unload a dirty pointer | 292 // its pointer to it NULLed out so that any attempt to unload a dirty pointer |
331 // will be averted. | 293 // will be averted. |
332 if (!extension_) | 294 if (!extension_) |
333 return; | 295 return; |
334 | 296 |
335 // TODO(aa): This is suspicious. There can be multiple views in an extension, | 297 // TODO(aa): This is suspicious. There can be multiple views in an extension, |
336 // and they aren't all going to use ExtensionHost. This should be in someplace | 298 // and they aren't all going to use ExtensionHost. This should be in someplace |
337 // more central, like EPM maybe. | 299 // more central, like EPM maybe. |
338 DCHECK_EQ(render_view_host_, render_view_host); | |
339 content::NotificationService::current()->Notify( | 300 content::NotificationService::current()->Notify( |
340 chrome::NOTIFICATION_EXTENSION_PROCESS_TERMINATED, | 301 chrome::NOTIFICATION_EXTENSION_PROCESS_TERMINATED, |
341 content::Source<Profile>(profile_), | 302 content::Source<Profile>(profile_), |
342 content::Details<ExtensionHost>(this)); | 303 content::Details<ExtensionHost>(this)); |
343 } | 304 } |
344 | 305 |
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 | |
354 void ExtensionHost::InsertInfobarCSS() { | 306 void ExtensionHost::InsertInfobarCSS() { |
355 DCHECK(!is_background_page()); | 307 DCHECK(!is_background_page()); |
356 | 308 |
357 static const base::StringPiece css( | 309 static const base::StringPiece css( |
358 ResourceBundle::GetSharedInstance().GetRawDataResource( | 310 ResourceBundle::GetSharedInstance().GetRawDataResource( |
359 IDR_EXTENSIONS_INFOBAR_CSS)); | 311 IDR_EXTENSIONS_INFOBAR_CSS)); |
360 | 312 |
361 render_view_host()->InsertCSS(string16(), css.as_string()); | 313 render_view_host()->InsertCSS(string16(), css.as_string()); |
362 } | 314 } |
363 | 315 |
364 void ExtensionHost::DisableScrollbarsForSmallWindows( | 316 void ExtensionHost::DisableScrollbarsForSmallWindows( |
365 const gfx::Size& size_limit) { | 317 const gfx::Size& size_limit) { |
366 render_view_host()->DisableScrollbarsForThreshold(size_limit); | 318 render_view_host()->DisableScrollbarsForThreshold(size_limit); |
367 } | 319 } |
368 | 320 |
369 void ExtensionHost::DidStopLoading() { | 321 void ExtensionHost::DidStopLoading() { |
370 bool notify = !did_stop_loading_; | 322 bool notify = !did_stop_loading_; |
371 did_stop_loading_ = true; | 323 did_stop_loading_ = true; |
372 if (extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_POPUP || | 324 if (extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_POPUP || |
373 extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_DIALOG || | 325 extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_DIALOG || |
374 extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_INFOBAR) { | 326 extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_INFOBAR) { |
375 #if defined(TOOLKIT_VIEWS) | 327 #if defined(TOOLKIT_VIEWS) || defined(OS_MACOSX) |
376 if (view_.get()) | 328 if (view_.get()) |
377 view_->DidStopLoading(); | 329 view_->DidStopLoading(); |
378 #endif | 330 #endif |
379 } | 331 } |
380 if (notify) { | 332 if (notify) { |
381 content::NotificationService::current()->Notify( | 333 content::NotificationService::current()->Notify( |
382 chrome::NOTIFICATION_EXTENSION_HOST_DID_STOP_LOADING, | 334 chrome::NOTIFICATION_EXTENSION_HOST_DID_STOP_LOADING, |
383 content::Source<Profile>(profile_), | 335 content::Source<Profile>(profile_), |
384 content::Details<ExtensionHost>(this)); | 336 content::Details<ExtensionHost>(this)); |
385 if (extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_BACKGROUND_PAGE) { | 337 if (extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_BACKGROUND_PAGE) { |
386 UMA_HISTOGRAM_TIMES("Extensions.BackgroundPageLoadTime", | 338 UMA_HISTOGRAM_TIMES("Extensions.BackgroundPageLoadTime", |
387 since_created_.Elapsed()); | 339 since_created_.Elapsed()); |
388 } else if (extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_DIALOG) { | 340 } else if (extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_DIALOG) { |
389 UMA_HISTOGRAM_TIMES("Extensions.DialogLoadTime", | 341 UMA_HISTOGRAM_TIMES("Extensions.DialogLoadTime", |
390 since_created_.Elapsed()); | 342 since_created_.Elapsed()); |
391 } else if (extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_POPUP) { | 343 } else if (extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_POPUP) { |
392 UMA_HISTOGRAM_TIMES("Extensions.PopupLoadTime", | 344 UMA_HISTOGRAM_TIMES("Extensions.PopupLoadTime", |
393 since_created_.Elapsed()); | 345 since_created_.Elapsed()); |
394 } else if (extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_INFOBAR) { | 346 } else if (extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_INFOBAR) { |
395 UMA_HISTOGRAM_TIMES("Extensions.InfobarLoadTime", | 347 UMA_HISTOGRAM_TIMES("Extensions.InfobarLoadTime", |
396 since_created_.Elapsed()); | 348 since_created_.Elapsed()); |
397 } | 349 } |
398 } | 350 } |
399 } | 351 } |
400 | 352 |
401 void ExtensionHost::DocumentAvailableInMainFrame(RenderViewHost* rvh) { | 353 void ExtensionHost::DocumentAvailableInMainFrame() { |
402 // If the document has already been marked as available for this host, then | 354 // If the document has already been marked as available for this host, then |
403 // bail. No need for the redundant setup. http://crbug.com/31170 | 355 // bail. No need for the redundant setup. http://crbug.com/31170 |
404 if (document_element_available_) | 356 if (document_element_available_) |
405 return; | 357 return; |
406 | 358 |
407 document_element_available_ = true; | 359 document_element_available_ = true; |
408 if (is_background_page()) { | 360 if (is_background_page()) { |
409 profile_->GetExtensionService()->SetBackgroundPageReady(extension_); | 361 profile_->GetExtensionService()->SetBackgroundPageReady(extension_); |
410 } else { | 362 } else { |
411 switch (extension_host_type_) { | 363 switch (extension_host_type_) { |
412 case chrome::VIEW_TYPE_EXTENSION_INFOBAR: | 364 case chrome::VIEW_TYPE_EXTENSION_INFOBAR: |
413 InsertInfobarCSS(); | 365 InsertInfobarCSS(); |
414 break; | 366 break; |
415 default: | 367 default: |
416 break; // No style sheet for other types, at the moment. | 368 break; // No style sheet for other types, at the moment. |
417 } | 369 } |
418 } | 370 } |
419 } | 371 } |
420 | 372 |
421 void ExtensionHost::DocumentOnLoadCompletedInMainFrame(RenderViewHost* rvh, | 373 void ExtensionHost::CloseContents(TabContents* contents) { |
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) { | |
492 if (extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_POPUP || | 374 if (extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_POPUP || |
493 extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_DIALOG || | 375 extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_DIALOG || |
494 extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_BACKGROUND_PAGE || | 376 extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_BACKGROUND_PAGE || |
495 extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_INFOBAR) { | 377 extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_INFOBAR) { |
496 content::NotificationService::current()->Notify( | 378 content::NotificationService::current()->Notify( |
497 chrome::NOTIFICATION_EXTENSION_HOST_VIEW_SHOULD_CLOSE, | 379 chrome::NOTIFICATION_EXTENSION_HOST_VIEW_SHOULD_CLOSE, |
498 content::Source<Profile>(profile_), | 380 content::Source<Profile>(profile_), |
499 content::Details<ExtensionHost>(this)); | 381 content::Details<ExtensionHost>(this)); |
500 } | 382 } |
501 } | 383 } |
502 | 384 |
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 | |
537 bool ExtensionHost::PreHandleKeyboardEvent(const NativeWebKeyboardEvent& event, | 385 bool ExtensionHost::PreHandleKeyboardEvent(const NativeWebKeyboardEvent& event, |
538 bool* is_keyboard_shortcut) { | 386 bool* is_keyboard_shortcut) { |
539 if (extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_POPUP && | 387 if (extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_POPUP && |
540 event.type == NativeWebKeyboardEvent::RawKeyDown && | 388 event.type == NativeWebKeyboardEvent::RawKeyDown && |
541 event.windowsKeyCode == ui::VKEY_ESCAPE) { | 389 event.windowsKeyCode == ui::VKEY_ESCAPE) { |
542 DCHECK(is_keyboard_shortcut != NULL); | 390 DCHECK(is_keyboard_shortcut != NULL); |
543 *is_keyboard_shortcut = true; | 391 *is_keyboard_shortcut = true; |
544 } | 392 } |
545 return false; | 393 return false; |
546 } | 394 } |
547 | 395 |
548 void ExtensionHost::HandleKeyboardEvent(const NativeWebKeyboardEvent& event) { | 396 void ExtensionHost::HandleKeyboardEvent(const NativeWebKeyboardEvent& event) { |
549 if (extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_POPUP) { | 397 if (extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_POPUP) { |
550 if (event.type == NativeWebKeyboardEvent::RawKeyDown && | 398 if (event.type == NativeWebKeyboardEvent::RawKeyDown && |
551 event.windowsKeyCode == ui::VKEY_ESCAPE) { | 399 event.windowsKeyCode == ui::VKEY_ESCAPE) { |
552 content::NotificationService::current()->Notify( | 400 content::NotificationService::current()->Notify( |
553 chrome::NOTIFICATION_EXTENSION_HOST_VIEW_SHOULD_CLOSE, | 401 chrome::NOTIFICATION_EXTENSION_HOST_VIEW_SHOULD_CLOSE, |
554 content::Source<Profile>(profile_), | 402 content::Source<Profile>(profile_), |
555 content::Details<ExtensionHost>(this)); | 403 content::Details<ExtensionHost>(this)); |
556 return; | 404 return; |
557 } | 405 } |
558 } | 406 } |
559 UnhandledKeyboardEvent(event); | 407 UnhandledKeyboardEvent(event); |
560 } | 408 } |
561 | 409 |
562 void ExtensionHost::HandleMouseMove() { | 410 bool ExtensionHost::OnMessageReceived(const IPC::Message& message) { |
563 #if defined(OS_WIN) | 411 bool handled = true; |
564 if (view_.get()) | 412 IPC_BEGIN_MESSAGE_MAP(ExtensionHost, message) |
565 view_->HandleMouseMove(); | 413 IPC_MESSAGE_HANDLER(ExtensionHostMsg_Request, OnRequest) |
566 #endif | 414 IPC_MESSAGE_UNHANDLED(handled = false) |
| 415 IPC_END_MESSAGE_MAP() |
| 416 return handled; |
567 } | 417 } |
568 | 418 |
569 void ExtensionHost::HandleMouseDown() { | 419 void ExtensionHost::OnRequest(const ExtensionHostMsg_Request_Params& params) { |
| 420 extension_function_dispatcher_.Dispatch(params, render_view_host()); |
570 } | 421 } |
571 | 422 |
572 void ExtensionHost::HandleMouseLeave() { | 423 void ExtensionHost::RenderViewCreated(RenderViewHost* render_view_host) { |
573 #if defined(OS_WIN) | |
574 if (view_.get()) | 424 if (view_.get()) |
575 view_->HandleMouseLeave(); | 425 view_->RenderViewCreated(); |
576 #endif | 426 |
| 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 } |
577 } | 442 } |
578 | 443 |
579 void ExtensionHost::HandleMouseUp() { | 444 content::JavaScriptDialogCreator* ExtensionHost::GetJavaScriptDialogCreator() { |
| 445 return GetJavaScriptDialogCreatorInstance(); |
580 } | 446 } |
581 | 447 |
582 void ExtensionHost::HandleMouseActivate() { | 448 void ExtensionHost::AddNewContents(TabContents* source, |
583 } | 449 TabContents* new_contents, |
584 | 450 WindowOpenDisposition disposition, |
585 void ExtensionHost::RunFileChooser( | 451 const gfx::Rect& initial_pos, |
586 RenderViewHost* render_view_host, | 452 bool user_gesture) { |
587 const ViewHostMsg_RunFileChooser_Params& params) { | 453 // TODO(mpcomplete): is all this necessary? Maybe we can just call the |
588 // FileSelectHelper adds a reference to itself and only releases it after | 454 // brower's delegate, and fall back to browser::Navigate if browser is NULL. |
589 // sending the result message. It won't be destroyed when this reference | 455 TabContents* contents = new_contents; |
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); | |
641 if (!contents) | 456 if (!contents) |
642 return; | 457 return; |
643 Profile* profile = Profile::FromBrowserContext(contents->browser_context()); | 458 Profile* profile = Profile::FromBrowserContext(contents->browser_context()); |
644 | 459 |
645 if (disposition == NEW_POPUP) { | 460 if (disposition == NEW_POPUP) { |
646 // Find a browser with a matching profile for creating a popup. | 461 // Find a browser with a matching profile for creating a popup. |
647 // (If none is found, NULL argument to NavigateParams is valid.) | 462 // (If none is found, NULL argument to NavigateParams is valid.) |
648 Browser* browser = BrowserList::FindTabbedBrowser( | 463 Browser* browser = BrowserList::FindTabbedBrowser( |
649 profile, false); // Match incognito exactly. | 464 profile, false); // Match incognito exactly. |
650 TabContentsWrapper* wrapper = new TabContentsWrapper(contents); | 465 TabContentsWrapper* wrapper = new TabContentsWrapper(contents); |
651 browser::NavigateParams params(browser, wrapper); | 466 browser::NavigateParams params(browser, wrapper); |
652 if (!browser) | 467 if (!browser) |
653 params.profile = profile; | 468 params.profile = profile; |
654 // The extension_app_id parameter ends up as app_name in the Browser | 469 // The extension_app_id parameter ends up as app_name in the Browser |
655 // which causes the Browser to return true for is_app(). This affects | 470 // which causes the Browser to return true for is_app(). This affects |
656 // among other things, whether the location bar gets displayed. | 471 // among other things, whether the location bar gets displayed. |
657 params.extension_app_id = extension_id_; | 472 params.extension_app_id = extension_id_; |
658 params.disposition = NEW_POPUP; | 473 params.disposition = NEW_POPUP; |
659 params.window_bounds = initial_pos; | 474 params.window_bounds = initial_pos; |
660 params.window_action = browser::NavigateParams::SHOW_WINDOW; | 475 params.window_action = browser::NavigateParams::SHOW_WINDOW; |
661 params.user_gesture = user_gesture; | 476 params.user_gesture = user_gesture; |
662 browser::Navigate(¶ms); | 477 browser::Navigate(¶ms); |
663 return; | 478 return; |
664 } | 479 } |
665 | 480 |
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 | |
670 // First, if the creating extension view was associated with a tab contents, | 481 // First, if the creating extension view was associated with a tab contents, |
671 // use that tab content's delegate. We must be careful here that the | 482 // use that tab content's delegate. We must be careful here that the |
672 // associated tab contents has the same profile as the new tab contents. In | 483 // associated tab contents has the same profile as the new tab contents. In |
673 // the case of extensions in 'spanning' incognito mode, they can mismatch. | 484 // the case of extensions in 'spanning' incognito mode, they can mismatch. |
674 // We don't want to end up putting a normal tab into an incognito window, or | 485 // We don't want to end up putting a normal tab into an incognito window, or |
675 // vice versa. | 486 // vice versa. |
676 TabContents* associated_contents = GetAssociatedTabContents(); | 487 TabContents* associated_contents = GetAssociatedTabContents(); |
677 if (associated_contents && | 488 if (associated_contents && |
678 associated_contents->browser_context() == contents->browser_context()) { | 489 associated_contents->browser_context() == contents->browser_context()) { |
679 associated_contents->AddNewContents( | 490 associated_contents->AddNewContents( |
680 contents, disposition, initial_pos, user_gesture); | 491 contents, disposition, initial_pos, user_gesture); |
681 return; | 492 return; |
682 } | 493 } |
683 | 494 |
684 // If there's no associated tab contents, or it doesn't have a matching | 495 // If there's no associated tab contents, or it doesn't have a matching |
685 // profile, try finding an open window. Again, we must make sure to find a | 496 // profile, try finding an open window. Again, we must make sure to find a |
686 // window with the correct profile. | 497 // window with the correct profile. |
687 Browser* browser = BrowserList::FindTabbedBrowser( | 498 Browser* browser = BrowserList::FindTabbedBrowser( |
688 profile, false); // Match incognito exactly. | 499 profile, false); // Match incognito exactly. |
689 | 500 |
690 // If there's no Browser open with the right profile, create a new one. | 501 // If there's no Browser open with the right profile, create a new one. |
691 if (!browser) { | 502 if (!browser) { |
692 browser = Browser::Create(profile); | 503 browser = Browser::Create(profile); |
693 browser->window()->Show(); | 504 browser->window()->Show(); |
694 } | 505 } |
695 browser->AddTabContents(contents, disposition, initial_pos, user_gesture); | 506 browser->AddTabContents(contents, disposition, initial_pos, user_gesture); |
696 } | 507 } |
697 | 508 |
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 } | |
703 | 509 |
704 void ExtensionHost::ShowCreatedFullscreenWidget(int route_id) { | 510 void ExtensionHost::RenderViewReady() { |
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) { | |
804 content::NotificationService::current()->Notify( | 511 content::NotificationService::current()->Notify( |
805 chrome::NOTIFICATION_EXTENSION_HOST_CREATED, | 512 chrome::NOTIFICATION_EXTENSION_HOST_CREATED, |
806 content::Source<Profile>(profile_), | 513 content::Source<Profile>(profile_), |
807 content::Details<ExtensionHost>(this)); | 514 content::Details<ExtensionHost>(this)); |
808 } | 515 } |
OLD | NEW |