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

Unified Diff: extensions/browser/renderer_startup_helper.cc

Issue 2766063003: Extensions: Keep track of loaded extensions in RendererStartupHelper. (Closed)
Patch Set: Address review Created 3 years, 8 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 side-by-side diff with in-line comments
Download patch
Index: extensions/browser/renderer_startup_helper.cc
diff --git a/extensions/browser/renderer_startup_helper.cc b/extensions/browser/renderer_startup_helper.cc
index c200c27a2dd843ec4e6fa83d24ef74f875f9c21a..4a309faa66b52703b07cf139612d261f59dc6701 100644
--- a/extensions/browser/renderer_startup_helper.cc
+++ b/extensions/browser/renderer_startup_helper.cc
@@ -4,6 +4,9 @@
#include "extensions/browser/renderer_startup_helper.h"
+#include "base/debug/dump_without_crashing.h"
+#include "base/stl_util.h"
+#include "base/strings/string_util.h"
#include "base/values.h"
#include "components/keyed_service/content/browser_context_dependency_manager.h"
#include "content/public/browser/notification_service.h"
@@ -31,6 +34,8 @@ RendererStartupHelper::RendererStartupHelper(BrowserContext* browser_context)
content::NotificationService::AllBrowserContextsAndSources());
registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_TERMINATED,
content::NotificationService::AllBrowserContextsAndSources());
+ registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED,
+ content::NotificationService::AllBrowserContextsAndSources());
}
RendererStartupHelper::~RendererStartupHelper() {}
@@ -45,6 +50,10 @@ void RendererStartupHelper::Observe(
content::Source<content::RenderProcessHost>(source).ptr());
break;
case content::NOTIFICATION_RENDERER_PROCESS_TERMINATED:
+ // Fall through.
+ case content::NOTIFICATION_RENDERER_PROCESS_CLOSED:
+ // This is needed to take care of the case when a RenderProcessHost is
+ // reused for a different renderer process.
UntrackProcess(content::Source<content::RenderProcessHost>(source).ptr());
break;
default:
@@ -96,6 +105,10 @@ void RendererStartupHelper::InitializeProcess(
const ExtensionSet& extensions =
ExtensionRegistry::Get(browser_context_)->enabled_extensions();
for (const auto& ext : extensions) {
+ // OnLoadedExtension should have already been called for the extension.
+ DCHECK(base::ContainsKey(extension_process_map_, ext->id()));
+ DCHECK(!base::ContainsKey(extension_process_map_[ext->id()], process));
+
// Renderers don't need to know about themes.
if (!ext->is_theme()) {
// TODO(kalman): Only include tab specific permissions for extension
@@ -105,18 +118,23 @@ void RendererStartupHelper::InitializeProcess(
bool include_tab_permissions = true;
loaded_extensions.push_back(
ExtensionMsg_Loaded_Params(ext.get(), include_tab_permissions));
+ extension_process_map_[ext->id()].insert(process);
}
}
process->Send(new ExtensionMsg_Loaded(loaded_extensions));
auto iter = pending_active_extensions_.find(process);
if (iter != pending_active_extensions_.end()) {
for (const ExtensionId& id : iter->second) {
+ // The extension should be loaded in the process.
DCHECK(extensions.Contains(id));
+ DCHECK(base::ContainsKey(extension_process_map_, id));
+ DCHECK(base::ContainsKey(extension_process_map_[id], process));
process->Send(new ExtensionMsg_ActivateExtension(id));
}
}
initialized_processes_.insert(process);
+ pending_active_extensions_.erase(process);
}
void RendererStartupHelper::UntrackProcess(
@@ -128,24 +146,50 @@ void RendererStartupHelper::UntrackProcess(
initialized_processes_.erase(process);
pending_active_extensions_.erase(process);
+ for (auto& extension_process_pair : extension_process_map_)
+ extension_process_pair.second.erase(process);
}
void RendererStartupHelper::ActivateExtensionInProcess(
const Extension& extension,
content::RenderProcessHost* process) {
+ // The extension should have been loaded already. Dump without crashing to
+ // debug crbug.com/528026.
+ if (!base::ContainsKey(extension_process_map_, extension.id())) {
+#if DCHECK_IS_ON()
+ NOTREACHED() << "Extension " << extension.id()
+ << "activated before loading";
+#else
+ base::debug::DumpWithoutCrashing();
+ return;
+#endif
+ }
+
// Renderers don't need to know about themes. We also don't normally
// "activate" themes, but this could happen if someone tries to open a tab
// to the e.g. theme's manifest.
if (extension.is_theme())
return;
- if (initialized_processes_.count(process))
+ if (base::ContainsKey(initialized_processes_, process)) {
+ DCHECK(base::ContainsKey(extension_process_map_[extension.id()], process));
process->Send(new ExtensionMsg_ActivateExtension(extension.id()));
- else
+ } else {
pending_active_extensions_[process].insert(extension.id());
+ }
}
void RendererStartupHelper::OnExtensionLoaded(const Extension& extension) {
+ // Extension was already loaded.
+ // TODO(crbug.com/708230): Ensure that clients don't call this for an
+ // already loaded extension and change this to a DCHECK.
+ if (base::ContainsKey(extension_process_map_, extension.id()))
+ return;
+
+ // Mark the extension as loaded.
+ std::set<content::RenderProcessHost*>& loaded_process_set =
+ extension_process_map_[extension.id()];
+
// Renderers don't need to know about themes.
if (extension.is_theme())
return;
@@ -157,19 +201,31 @@ void RendererStartupHelper::OnExtensionLoaded(const Extension& extension) {
std::vector<ExtensionMsg_Loaded_Params> params(
1,
ExtensionMsg_Loaded_Params(&extension, false /* no tab permissions */));
- for (content::RenderProcessHost* process : initialized_processes_)
+ for (content::RenderProcessHost* process : initialized_processes_) {
process->Send(new ExtensionMsg_Loaded(params));
+ loaded_process_set.insert(process);
+ }
}
void RendererStartupHelper::OnExtensionUnloaded(const Extension& extension) {
- // Renderers don't need to know about themes.
- if (extension.is_theme())
+ // Extension is not loaded.
+ // TODO(crbug.com/708230): Ensure that clients call this for a loaded
+ // extension only and change this to a DCHECK.
+ if (!base::ContainsKey(extension_process_map_, extension.id()))
return;
- for (content::RenderProcessHost* process : initialized_processes_)
+ const std::set<content::RenderProcessHost*>& loaded_process_set =
+ extension_process_map_[extension.id()];
+ for (content::RenderProcessHost* process : loaded_process_set) {
+ DCHECK(base::ContainsKey(initialized_processes_, process));
process->Send(new ExtensionMsg_Unloaded(extension.id()));
+ }
+
for (auto& process_extensions_pair : pending_active_extensions_)
process_extensions_pair.second.erase(extension.id());
+
+ // Mark the extension as unloaded.
+ extension_process_map_.erase(extension.id());
}
//////////////////////////////////////////////////////////////////////////////
« no previous file with comments | « extensions/browser/renderer_startup_helper.h ('k') | extensions/browser/renderer_startup_helper_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698