| 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 <list> | 7 #include <list> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 114 // ExtensionHost | 114 // ExtensionHost |
| 115 | 115 |
| 116 ExtensionHost::ExtensionHost(const Extension* extension, | 116 ExtensionHost::ExtensionHost(const Extension* extension, |
| 117 SiteInstance* site_instance, | 117 SiteInstance* site_instance, |
| 118 const GURL& url, | 118 const GURL& url, |
| 119 ViewType host_type) | 119 ViewType host_type) |
| 120 : delegate_(ExtensionsBrowserClient::Get()->CreateExtensionHostDelegate()), | 120 : delegate_(ExtensionsBrowserClient::Get()->CreateExtensionHostDelegate()), |
| 121 extension_(extension), | 121 extension_(extension), |
| 122 extension_id_(extension->id()), | 122 extension_id_(extension->id()), |
| 123 browser_context_(site_instance->GetBrowserContext()), | 123 browser_context_(site_instance->GetBrowserContext()), |
| 124 render_view_host_(NULL), | 124 render_view_host_(nullptr), |
| 125 did_stop_loading_(false), | 125 did_stop_loading_(false), |
| 126 document_element_available_(false), | 126 document_element_available_(false), |
| 127 initial_url_(url), | 127 initial_url_(url), |
| 128 extension_function_dispatcher_(browser_context_, this), | 128 extension_function_dispatcher_(browser_context_, this), |
| 129 extension_host_type_(host_type) { | 129 extension_host_type_(host_type) { |
| 130 // Not used for panels, see PanelHost. | 130 // Not used for panels, see PanelHost. |
| 131 DCHECK(host_type == VIEW_TYPE_EXTENSION_BACKGROUND_PAGE || | 131 DCHECK(host_type == VIEW_TYPE_EXTENSION_BACKGROUND_PAGE || |
| 132 host_type == VIEW_TYPE_EXTENSION_DIALOG || | 132 host_type == VIEW_TYPE_EXTENSION_DIALOG || |
| 133 host_type == VIEW_TYPE_EXTENSION_POPUP); | 133 host_type == VIEW_TYPE_EXTENSION_POPUP); |
| 134 host_contents_.reset(WebContents::Create( | 134 host_contents_.reset(WebContents::Create( |
| (...skipping 21 matching lines...) Expand all Loading... |
| 156 UMA_HISTOGRAM_LONG_TIMES("Extensions.EventPageActiveTime2", | 156 UMA_HISTOGRAM_LONG_TIMES("Extensions.EventPageActiveTime2", |
| 157 load_start_->Elapsed()); | 157 load_start_->Elapsed()); |
| 158 } | 158 } |
| 159 content::NotificationService::current()->Notify( | 159 content::NotificationService::current()->Notify( |
| 160 extensions::NOTIFICATION_EXTENSION_HOST_DESTROYED, | 160 extensions::NOTIFICATION_EXTENSION_HOST_DESTROYED, |
| 161 content::Source<BrowserContext>(browser_context_), | 161 content::Source<BrowserContext>(browser_context_), |
| 162 content::Details<ExtensionHost>(this)); | 162 content::Details<ExtensionHost>(this)); |
| 163 FOR_EACH_OBSERVER(ExtensionHostObserver, observer_list_, | 163 FOR_EACH_OBSERVER(ExtensionHostObserver, observer_list_, |
| 164 OnExtensionHostDestroyed(this)); | 164 OnExtensionHostDestroyed(this)); |
| 165 ProcessCreationQueue::GetInstance()->Remove(this); | 165 ProcessCreationQueue::GetInstance()->Remove(this); |
| 166 // Immediately stop observing |host_contents_| because its destruction events |
| 167 // (like DidStopLoading, it turns out) can call back into ExtensionHost |
| 168 // re-entrantly, when anything declared after |host_contents_| has already |
| 169 // been destroyed. |
| 170 content::WebContentsObserver::Observe(nullptr); |
| 166 } | 171 } |
| 167 | 172 |
| 168 content::RenderProcessHost* ExtensionHost::render_process_host() const { | 173 content::RenderProcessHost* ExtensionHost::render_process_host() const { |
| 169 return render_view_host()->GetProcess(); | 174 return render_view_host()->GetProcess(); |
| 170 } | 175 } |
| 171 | 176 |
| 172 RenderViewHost* ExtensionHost::render_view_host() const { | 177 RenderViewHost* ExtensionHost::render_view_host() const { |
| 173 // TODO(mpcomplete): This can be NULL. How do we handle that? | 178 // TODO(mpcomplete): This can be null. How do we handle that? |
| 174 return render_view_host_; | 179 return render_view_host_; |
| 175 } | 180 } |
| 176 | 181 |
| 177 bool ExtensionHost::IsRenderViewLive() const { | 182 bool ExtensionHost::IsRenderViewLive() const { |
| 178 return render_view_host()->IsRenderViewLive(); | 183 return render_view_host()->IsRenderViewLive(); |
| 179 } | 184 } |
| 180 | 185 |
| 181 void ExtensionHost::CreateRenderViewSoon() { | 186 void ExtensionHost::CreateRenderViewSoon() { |
| 182 if (render_process_host() && render_process_host()->HasConnection()) { | 187 if (render_process_host() && render_process_host()->HasConnection()) { |
| 183 // If the process is already started, go ahead and initialize the RenderView | 188 // If the process is already started, go ahead and initialize the RenderView |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 255 DCHECK(extension_host_type_ == VIEW_TYPE_EXTENSION_BACKGROUND_PAGE); | 260 DCHECK(extension_host_type_ == VIEW_TYPE_EXTENSION_BACKGROUND_PAGE); |
| 256 return true; | 261 return true; |
| 257 } | 262 } |
| 258 | 263 |
| 259 void ExtensionHost::Observe(int type, | 264 void ExtensionHost::Observe(int type, |
| 260 const content::NotificationSource& source, | 265 const content::NotificationSource& source, |
| 261 const content::NotificationDetails& details) { | 266 const content::NotificationDetails& details) { |
| 262 switch (type) { | 267 switch (type) { |
| 263 case extensions::NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED: | 268 case extensions::NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED: |
| 264 // The extension object will be deleted after this notification has been | 269 // The extension object will be deleted after this notification has been |
| 265 // sent. NULL it out so that dirty pointer issues don't arise in cases | 270 // sent. Null it out so that dirty pointer issues don't arise in cases |
| 266 // when multiple ExtensionHost objects pointing to the same Extension are | 271 // when multiple ExtensionHost objects pointing to the same Extension are |
| 267 // present. | 272 // present. |
| 268 if (extension_ == content::Details<UnloadedExtensionInfo>(details)-> | 273 if (extension_ == content::Details<UnloadedExtensionInfo>(details)-> |
| 269 extension) { | 274 extension) { |
| 270 extension_ = NULL; | 275 extension_ = nullptr; |
| 271 } | 276 } |
| 272 break; | 277 break; |
| 273 default: | 278 default: |
| 274 NOTREACHED() << "Unexpected notification sent."; | 279 NOTREACHED() << "Unexpected notification sent."; |
| 275 break; | 280 break; |
| 276 } | 281 } |
| 277 } | 282 } |
| 278 | 283 |
| 279 void ExtensionHost::RenderProcessGone(base::TerminationStatus status) { | 284 void ExtensionHost::RenderProcessGone(base::TerminationStatus status) { |
| 280 // During browser shutdown, we may use sudden termination on an extension | 285 // During browser shutdown, we may use sudden termination on an extension |
| 281 // process, so it is expected to lose our connection to the render view. | 286 // process, so it is expected to lose our connection to the render view. |
| 282 // Do nothing. | 287 // Do nothing. |
| 283 RenderProcessHost* process_host = host_contents_->GetRenderProcessHost(); | 288 RenderProcessHost* process_host = host_contents_->GetRenderProcessHost(); |
| 284 if (process_host && process_host->FastShutdownStarted()) | 289 if (process_host && process_host->FastShutdownStarted()) |
| 285 return; | 290 return; |
| 286 | 291 |
| 287 // In certain cases, multiple ExtensionHost objects may have pointed to | 292 // In certain cases, multiple ExtensionHost objects may have pointed to |
| 288 // the same Extension at some point (one with a background page and a | 293 // the same Extension at some point (one with a background page and a |
| 289 // popup, for example). When the first ExtensionHost goes away, the extension | 294 // popup, for example). When the first ExtensionHost goes away, the extension |
| 290 // is unloaded, and any other host that pointed to that extension will have | 295 // is unloaded, and any other host that pointed to that extension will have |
| 291 // its pointer to it NULLed out so that any attempt to unload a dirty pointer | 296 // its pointer to it null'd out so that any attempt to unload a dirty pointer |
| 292 // will be averted. | 297 // will be averted. |
| 293 if (!extension_) | 298 if (!extension_) |
| 294 return; | 299 return; |
| 295 | 300 |
| 296 // TODO(aa): This is suspicious. There can be multiple views in an extension, | 301 // TODO(aa): This is suspicious. There can be multiple views in an extension, |
| 297 // and they aren't all going to use ExtensionHost. This should be in someplace | 302 // and they aren't all going to use ExtensionHost. This should be in someplace |
| 298 // more central, like EPM maybe. | 303 // more central, like EPM maybe. |
| 299 content::NotificationService::current()->Notify( | 304 content::NotificationService::current()->Notify( |
| 300 extensions::NOTIFICATION_EXTENSION_PROCESS_TERMINATED, | 305 extensions::NOTIFICATION_EXTENSION_PROCESS_TERMINATED, |
| 301 content::Source<BrowserContext>(browser_context_), | 306 content::Source<BrowserContext>(browser_context_), |
| 302 content::Details<ExtensionHost>(this)); | 307 content::Details<ExtensionHost>(this)); |
| 303 } | 308 } |
| 304 | 309 |
| 305 void ExtensionHost::DidStopLoading(content::RenderViewHost* render_view_host) { | 310 void ExtensionHost::DidStopLoading(content::RenderViewHost* render_view_host) { |
| 306 bool notify = !did_stop_loading_; | 311 bool notify = !did_stop_loading_; |
| 307 did_stop_loading_ = true; | 312 did_stop_loading_ = true; |
| 308 OnDidStopLoading(); | 313 OnDidStopLoading(); |
| 309 if (notify) { | 314 if (notify) { |
| 310 // Log metrics. It's tempting to CHECK(load_start_) here, but it's possible | 315 CHECK(load_start_.get()); |
| 311 // to get a DidStopLoading even if we never started loading, in convoluted | 316 if (extension_host_type_ == VIEW_TYPE_EXTENSION_BACKGROUND_PAGE) { |
| 312 // notification and observer chains. | 317 if (extension_ && BackgroundInfo::HasLazyBackgroundPage(extension_)) { |
| 313 if (load_start_.get()) { | 318 UMA_HISTOGRAM_MEDIUM_TIMES("Extensions.EventPageLoadTime2", |
| 314 if (extension_host_type_ == VIEW_TYPE_EXTENSION_BACKGROUND_PAGE) { | 319 load_start_->Elapsed()); |
| 315 if (extension_ && BackgroundInfo::HasLazyBackgroundPage(extension_)) { | 320 } else { |
| 316 UMA_HISTOGRAM_MEDIUM_TIMES("Extensions.EventPageLoadTime2", | 321 UMA_HISTOGRAM_MEDIUM_TIMES("Extensions.BackgroundPageLoadTime2", |
| 317 load_start_->Elapsed()); | |
| 318 } else { | |
| 319 UMA_HISTOGRAM_MEDIUM_TIMES("Extensions.BackgroundPageLoadTime2", | |
| 320 load_start_->Elapsed()); | |
| 321 } | |
| 322 } else if (extension_host_type_ == VIEW_TYPE_EXTENSION_POPUP) { | |
| 323 UMA_HISTOGRAM_MEDIUM_TIMES("Extensions.PopupLoadTime2", | |
| 324 load_start_->Elapsed()); | 322 load_start_->Elapsed()); |
| 325 } | 323 } |
| 324 } else if (extension_host_type_ == VIEW_TYPE_EXTENSION_POPUP) { |
| 325 UMA_HISTOGRAM_MEDIUM_TIMES("Extensions.PopupLoadTime2", |
| 326 load_start_->Elapsed()); |
| 326 } | 327 } |
| 327 | |
| 328 // Send the notification last, because it might result in this being | 328 // Send the notification last, because it might result in this being |
| 329 // deleted. | 329 // deleted. |
| 330 content::NotificationService::current()->Notify( | 330 content::NotificationService::current()->Notify( |
| 331 extensions::NOTIFICATION_EXTENSION_HOST_DID_STOP_LOADING, | 331 extensions::NOTIFICATION_EXTENSION_HOST_DID_STOP_LOADING, |
| 332 content::Source<BrowserContext>(browser_context_), | 332 content::Source<BrowserContext>(browser_context_), |
| 333 content::Details<ExtensionHost>(this)); | 333 content::Details<ExtensionHost>(this)); |
| 334 } | 334 } |
| 335 } | 335 } |
| 336 | 336 |
| 337 void ExtensionHost::OnDidStopLoading() { | 337 void ExtensionHost::OnDidStopLoading() { |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 484 return delegate_->CheckMediaAccessPermission( | 484 return delegate_->CheckMediaAccessPermission( |
| 485 web_contents, security_origin, type, extension()); | 485 web_contents, security_origin, type, extension()); |
| 486 } | 486 } |
| 487 | 487 |
| 488 bool ExtensionHost::IsNeverVisible(content::WebContents* web_contents) { | 488 bool ExtensionHost::IsNeverVisible(content::WebContents* web_contents) { |
| 489 ViewType view_type = extensions::GetViewType(web_contents); | 489 ViewType view_type = extensions::GetViewType(web_contents); |
| 490 return view_type == extensions::VIEW_TYPE_EXTENSION_BACKGROUND_PAGE; | 490 return view_type == extensions::VIEW_TYPE_EXTENSION_BACKGROUND_PAGE; |
| 491 } | 491 } |
| 492 | 492 |
| 493 } // namespace extensions | 493 } // namespace extensions |
| OLD | NEW |