Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(656)

Side by Side Diff: chrome/browser/extensions/extension_host.cc

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

Powered by Google App Engine
This is Rietveld 408576698