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

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

Issue 930413002: Unobserve the host WebContents of an ExtensionHost on destruction, to prevent (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: nullptr Created 5 years, 10 months 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
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698