| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "extensions/browser/extension_host.h" | 5 #include "extensions/browser/extension_host.h" |
| 6 | 6 |
| 7 #include "base/logging.h" | 7 #include "base/logging.h" |
| 8 #include "base/metrics/field_trial.h" | 8 #include "base/metrics/field_trial.h" |
| 9 #include "base/metrics/histogram_macros.h" | 9 #include "base/metrics/histogram_macros.h" |
| 10 #include "base/profiler/scoped_tracker.h" | 10 #include "base/profiler/scoped_tracker.h" |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 51 | 51 |
| 52 ExtensionHost::ExtensionHost(const Extension* extension, | 52 ExtensionHost::ExtensionHost(const Extension* extension, |
| 53 SiteInstance* site_instance, | 53 SiteInstance* site_instance, |
| 54 const GURL& url, | 54 const GURL& url, |
| 55 ViewType host_type) | 55 ViewType host_type) |
| 56 : delegate_(ExtensionsBrowserClient::Get()->CreateExtensionHostDelegate()), | 56 : delegate_(ExtensionsBrowserClient::Get()->CreateExtensionHostDelegate()), |
| 57 extension_(extension), | 57 extension_(extension), |
| 58 extension_id_(extension->id()), | 58 extension_id_(extension->id()), |
| 59 browser_context_(site_instance->GetBrowserContext()), | 59 browser_context_(site_instance->GetBrowserContext()), |
| 60 render_view_host_(nullptr), | 60 render_view_host_(nullptr), |
| 61 did_stop_loading_(false), | 61 has_loaded_once_(false), |
| 62 document_element_available_(false), | 62 document_element_available_(false), |
| 63 initial_url_(url), | 63 initial_url_(url), |
| 64 extension_function_dispatcher_(browser_context_, this), | 64 extension_function_dispatcher_(browser_context_, this), |
| 65 extension_host_type_(host_type) { | 65 extension_host_type_(host_type) { |
| 66 // Not used for panels, see PanelHost. | 66 // Not used for panels, see PanelHost. |
| 67 DCHECK(host_type == VIEW_TYPE_EXTENSION_BACKGROUND_PAGE || | 67 DCHECK(host_type == VIEW_TYPE_EXTENSION_BACKGROUND_PAGE || |
| 68 host_type == VIEW_TYPE_EXTENSION_DIALOG || | 68 host_type == VIEW_TYPE_EXTENSION_DIALOG || |
| 69 host_type == VIEW_TYPE_EXTENSION_POPUP); | 69 host_type == VIEW_TYPE_EXTENSION_POPUP); |
| 70 host_contents_.reset(WebContents::Create( | 70 host_contents_.reset(WebContents::Create( |
| 71 WebContents::CreateParams(browser_context_, site_instance))), | 71 WebContents::CreateParams(browser_context_, site_instance))), |
| (...skipping 13 matching lines...) Expand all Loading... |
| 85 | 85 |
| 86 ExtensionHost::~ExtensionHost() { | 86 ExtensionHost::~ExtensionHost() { |
| 87 ExtensionRegistry::Get(browser_context_)->RemoveObserver(this); | 87 ExtensionRegistry::Get(browser_context_)->RemoveObserver(this); |
| 88 | 88 |
| 89 if (extension_host_type_ == VIEW_TYPE_EXTENSION_BACKGROUND_PAGE && | 89 if (extension_host_type_ == VIEW_TYPE_EXTENSION_BACKGROUND_PAGE && |
| 90 extension_ && BackgroundInfo::HasLazyBackgroundPage(extension_) && | 90 extension_ && BackgroundInfo::HasLazyBackgroundPage(extension_) && |
| 91 load_start_.get()) { | 91 load_start_.get()) { |
| 92 UMA_HISTOGRAM_LONG_TIMES("Extensions.EventPageActiveTime2", | 92 UMA_HISTOGRAM_LONG_TIMES("Extensions.EventPageActiveTime2", |
| 93 load_start_->Elapsed()); | 93 load_start_->Elapsed()); |
| 94 } | 94 } |
| 95 |
| 95 content::NotificationService::current()->Notify( | 96 content::NotificationService::current()->Notify( |
| 96 extensions::NOTIFICATION_EXTENSION_HOST_DESTROYED, | 97 extensions::NOTIFICATION_EXTENSION_HOST_DESTROYED, |
| 97 content::Source<BrowserContext>(browser_context_), | 98 content::Source<BrowserContext>(browser_context_), |
| 98 content::Details<ExtensionHost>(this)); | 99 content::Details<ExtensionHost>(this)); |
| 99 FOR_EACH_OBSERVER(ExtensionHostObserver, observer_list_, | 100 FOR_EACH_OBSERVER(ExtensionHostObserver, observer_list_, |
| 100 OnExtensionHostDestroyed(this)); | 101 OnExtensionHostDestroyed(this)); |
| 101 FOR_EACH_OBSERVER(DeferredStartRenderHostObserver, | 102 FOR_EACH_OBSERVER(DeferredStartRenderHostObserver, |
| 102 deferred_start_render_host_observer_list_, | 103 deferred_start_render_host_observer_list_, |
| 103 OnDeferredStartRenderHostDestroyed(this)); | 104 OnDeferredStartRenderHostDestroyed(this)); |
| 105 |
| 106 // Remove ourselves from the queue as late as possible (before effectively |
| 107 // destroying self, but after everything else) so that queues that are |
| 108 // monitoring lifetime get a chance to see stop-loading events. |
| 104 delegate_->GetExtensionHostQueue()->Remove(this); | 109 delegate_->GetExtensionHostQueue()->Remove(this); |
| 105 // Immediately stop observing |host_contents_| because its destruction events | 110 |
| 106 // (like DidStopLoading, it turns out) can call back into ExtensionHost | 111 // Deliberately stop observing |host_contents_| because its destruction |
| 107 // re-entrantly, when anything declared after |host_contents_| has already | 112 // events (like DidStopLoading, it turns out) can call back into |
| 108 // been destroyed. | 113 // ExtensionHost re-entrantly, when anything declared after |host_contents_| |
| 114 // has already been destroyed. |
| 109 content::WebContentsObserver::Observe(nullptr); | 115 content::WebContentsObserver::Observe(nullptr); |
| 110 } | 116 } |
| 111 | 117 |
| 112 content::RenderProcessHost* ExtensionHost::render_process_host() const { | 118 content::RenderProcessHost* ExtensionHost::render_process_host() const { |
| 113 return render_view_host()->GetProcess(); | 119 return render_view_host()->GetProcess(); |
| 114 } | 120 } |
| 115 | 121 |
| 116 RenderViewHost* ExtensionHost::render_view_host() const { | 122 RenderViewHost* ExtensionHost::render_view_host() const { |
| 117 // TODO(mpcomplete): This can be null. How do we handle that? | 123 // TODO(mpcomplete): This can be null. How do we handle that? |
| 118 return render_view_host_; | 124 return render_view_host_; |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 212 } | 218 } |
| 213 | 219 |
| 214 void ExtensionHost::LoadInitialURL() { | 220 void ExtensionHost::LoadInitialURL() { |
| 215 load_start_.reset(new base::ElapsedTimer()); | 221 load_start_.reset(new base::ElapsedTimer()); |
| 216 host_contents_->GetController().LoadURL( | 222 host_contents_->GetController().LoadURL( |
| 217 initial_url_, content::Referrer(), ui::PAGE_TRANSITION_LINK, | 223 initial_url_, content::Referrer(), ui::PAGE_TRANSITION_LINK, |
| 218 std::string()); | 224 std::string()); |
| 219 } | 225 } |
| 220 | 226 |
| 221 bool ExtensionHost::IsBackgroundPage() const { | 227 bool ExtensionHost::IsBackgroundPage() const { |
| 222 DCHECK(extension_host_type_ == VIEW_TYPE_EXTENSION_BACKGROUND_PAGE); | 228 DCHECK_EQ(extension_host_type_, VIEW_TYPE_EXTENSION_BACKGROUND_PAGE); |
| 223 return true; | 229 return true; |
| 224 } | 230 } |
| 225 | 231 |
| 226 void ExtensionHost::OnExtensionUnloaded( | 232 void ExtensionHost::OnExtensionUnloaded( |
| 227 content::BrowserContext* browser_context, | 233 content::BrowserContext* browser_context, |
| 228 const Extension* extension, | 234 const Extension* extension, |
| 229 UnloadedExtensionInfo::Reason reason) { | 235 UnloadedExtensionInfo::Reason reason) { |
| 230 // The extension object will be deleted after this notification has been sent. | 236 // The extension object will be deleted after this notification has been sent. |
| 231 // Null it out so that dirty pointer issues don't arise in cases when multiple | 237 // Null it out so that dirty pointer issues don't arise in cases when multiple |
| 232 // ExtensionHost objects pointing to the same Extension are present. | 238 // ExtensionHost objects pointing to the same Extension are present. |
| (...skipping 22 matching lines...) Expand all Loading... |
| 255 // TODO(aa): This is suspicious. There can be multiple views in an extension, | 261 // TODO(aa): This is suspicious. There can be multiple views in an extension, |
| 256 // and they aren't all going to use ExtensionHost. This should be in someplace | 262 // and they aren't all going to use ExtensionHost. This should be in someplace |
| 257 // more central, like EPM maybe. | 263 // more central, like EPM maybe. |
| 258 content::NotificationService::current()->Notify( | 264 content::NotificationService::current()->Notify( |
| 259 extensions::NOTIFICATION_EXTENSION_PROCESS_TERMINATED, | 265 extensions::NOTIFICATION_EXTENSION_PROCESS_TERMINATED, |
| 260 content::Source<BrowserContext>(browser_context_), | 266 content::Source<BrowserContext>(browser_context_), |
| 261 content::Details<ExtensionHost>(this)); | 267 content::Details<ExtensionHost>(this)); |
| 262 } | 268 } |
| 263 | 269 |
| 264 void ExtensionHost::DidStartLoading(content::RenderViewHost* render_view_host) { | 270 void ExtensionHost::DidStartLoading(content::RenderViewHost* render_view_host) { |
| 265 FOR_EACH_OBSERVER(DeferredStartRenderHostObserver, | 271 if (!has_loaded_once_) { |
| 266 deferred_start_render_host_observer_list_, | 272 FOR_EACH_OBSERVER(DeferredStartRenderHostObserver, |
| 267 OnDeferredStartRenderHostDidStartLoading(this)); | 273 deferred_start_render_host_observer_list_, |
| 274 OnDeferredStartRenderHostDidStartFirstLoad(this)); |
| 275 } |
| 268 } | 276 } |
| 269 | 277 |
| 270 void ExtensionHost::DidStopLoading(content::RenderViewHost* render_view_host) { | 278 void ExtensionHost::DidStopLoading(content::RenderViewHost* render_view_host) { |
| 271 bool notify = !did_stop_loading_; | 279 // Only record UMA for the first load. Subsequent loads will likely behave |
| 272 did_stop_loading_ = true; | 280 // quite different, and it's first load we're most interested in. |
| 273 OnDidStopLoading(); | 281 bool first_load = !has_loaded_once_; |
| 274 if (notify) { | 282 has_loaded_once_ = true; |
| 275 CHECK(load_start_.get()); | 283 if (first_load) { |
| 276 if (extension_host_type_ == VIEW_TYPE_EXTENSION_BACKGROUND_PAGE) { | 284 RecordStopLoadingUMA(); |
| 277 if (extension_ && BackgroundInfo::HasLazyBackgroundPage(extension_)) { | 285 OnDidStopFirstLoad(); |
| 278 UMA_HISTOGRAM_MEDIUM_TIMES("Extensions.EventPageLoadTime2", | |
| 279 load_start_->Elapsed()); | |
| 280 } else { | |
| 281 UMA_HISTOGRAM_MEDIUM_TIMES("Extensions.BackgroundPageLoadTime2", | |
| 282 load_start_->Elapsed()); | |
| 283 } | |
| 284 } else if (extension_host_type_ == VIEW_TYPE_EXTENSION_POPUP) { | |
| 285 UMA_HISTOGRAM_MEDIUM_TIMES("Extensions.PopupLoadTime2", | |
| 286 load_start_->Elapsed()); | |
| 287 } | |
| 288 content::NotificationService::current()->Notify( | 286 content::NotificationService::current()->Notify( |
| 289 extensions::NOTIFICATION_EXTENSION_HOST_DID_STOP_LOADING, | 287 extensions::NOTIFICATION_EXTENSION_HOST_DID_STOP_FIRST_LOAD, |
| 290 content::Source<BrowserContext>(browser_context_), | 288 content::Source<BrowserContext>(browser_context_), |
| 291 content::Details<ExtensionHost>(this)); | 289 content::Details<ExtensionHost>(this)); |
| 292 FOR_EACH_OBSERVER(DeferredStartRenderHostObserver, | 290 FOR_EACH_OBSERVER(DeferredStartRenderHostObserver, |
| 293 deferred_start_render_host_observer_list_, | 291 deferred_start_render_host_observer_list_, |
| 294 OnDeferredStartRenderHostDidStopLoading(this)); | 292 OnDeferredStartRenderHostDidStopFirstLoad(this)); |
| 295 } | 293 } |
| 296 } | 294 } |
| 297 | 295 |
| 298 void ExtensionHost::OnDidStopLoading() { | 296 void ExtensionHost::OnDidStopFirstLoad() { |
| 299 DCHECK(extension_host_type_ == VIEW_TYPE_EXTENSION_BACKGROUND_PAGE); | 297 DCHECK_EQ(extension_host_type_, VIEW_TYPE_EXTENSION_BACKGROUND_PAGE); |
| 300 // Nothing to do for background pages. | 298 // Nothing to do for background pages. |
| 301 } | 299 } |
| 302 | 300 |
| 303 void ExtensionHost::DocumentAvailableInMainFrame() { | 301 void ExtensionHost::DocumentAvailableInMainFrame() { |
| 304 // If the document has already been marked as available for this host, then | 302 // If the document has already been marked as available for this host, then |
| 305 // bail. No need for the redundant setup. http://crbug.com/31170 | 303 // bail. No need for the redundant setup. http://crbug.com/31170 |
| 306 if (document_element_available_) | 304 if (document_element_available_) |
| 307 return; | 305 return; |
| 308 document_element_available_ = true; | 306 document_element_available_ = true; |
| 309 | 307 |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 454 content::MediaStreamType type) { | 452 content::MediaStreamType type) { |
| 455 return delegate_->CheckMediaAccessPermission( | 453 return delegate_->CheckMediaAccessPermission( |
| 456 web_contents, security_origin, type, extension()); | 454 web_contents, security_origin, type, extension()); |
| 457 } | 455 } |
| 458 | 456 |
| 459 bool ExtensionHost::IsNeverVisible(content::WebContents* web_contents) { | 457 bool ExtensionHost::IsNeverVisible(content::WebContents* web_contents) { |
| 460 ViewType view_type = extensions::GetViewType(web_contents); | 458 ViewType view_type = extensions::GetViewType(web_contents); |
| 461 return view_type == extensions::VIEW_TYPE_EXTENSION_BACKGROUND_PAGE; | 459 return view_type == extensions::VIEW_TYPE_EXTENSION_BACKGROUND_PAGE; |
| 462 } | 460 } |
| 463 | 461 |
| 462 void ExtensionHost::RecordStopLoadingUMA() { |
| 463 CHECK(load_start_.get()); |
| 464 if (extension_host_type_ == VIEW_TYPE_EXTENSION_BACKGROUND_PAGE) { |
| 465 if (extension_ && BackgroundInfo::HasLazyBackgroundPage(extension_)) { |
| 466 UMA_HISTOGRAM_MEDIUM_TIMES("Extensions.EventPageLoadTime2", |
| 467 load_start_->Elapsed()); |
| 468 } else { |
| 469 UMA_HISTOGRAM_MEDIUM_TIMES("Extensions.BackgroundPageLoadTime2", |
| 470 load_start_->Elapsed()); |
| 471 } |
| 472 } else if (extension_host_type_ == VIEW_TYPE_EXTENSION_POPUP) { |
| 473 UMA_HISTOGRAM_MEDIUM_TIMES("Extensions.PopupLoadTime2", |
| 474 load_start_->Elapsed()); |
| 475 } |
| 476 } |
| 477 |
| 464 } // namespace extensions | 478 } // namespace extensions |
| OLD | NEW |