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 |