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

Unified Diff: extensions/renderer/script_context_set.cc

Issue 995283004: Move Extension ScriptContext creation into ScriptContextSet. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fix memory for real Created 5 years, 9 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
« no previous file with comments | « extensions/renderer/script_context_set.h ('k') | extensions/renderer/script_context_set_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: extensions/renderer/script_context_set.cc
diff --git a/extensions/renderer/script_context_set.cc b/extensions/renderer/script_context_set.cc
index 5f7be6c156f84c6b031580b5ee4fcc486ae6171d..1e9e9e8ee3f2f852877909ebcff7a40ccad1fd0c 100644
--- a/extensions/renderer/script_context_set.cc
+++ b/extensions/renderer/script_context_set.cc
@@ -5,34 +5,50 @@
#include "extensions/renderer/script_context_set.h"
#include "base/message_loop/message_loop.h"
+#include "content/public/common/url_constants.h"
#include "content/public/renderer/render_view.h"
#include "extensions/common/extension.h"
+#include "extensions/renderer/extension_groups.h"
#include "extensions/renderer/script_context.h"
+#include "extensions/renderer/script_injection.h"
+#include "third_party/WebKit/public/web/WebDocument.h"
+#include "third_party/WebKit/public/web/WebLocalFrame.h"
#include "v8/include/v8.h"
namespace extensions {
-ScriptContextSet::ScriptContextSet() {
-}
-ScriptContextSet::~ScriptContextSet() {
+ScriptContextSet::ScriptContextSet(ExtensionSet* extensions,
+ ExtensionIdSet* active_extension_ids)
+ : extensions_(extensions), active_extension_ids_(active_extension_ids) {
}
-int ScriptContextSet::size() const {
- return static_cast<int>(contexts_.size());
+ScriptContextSet::~ScriptContextSet() {
}
-void ScriptContextSet::Add(ScriptContext* context) {
-#if DCHECK_IS_ON()
- // It's OK to insert the same context twice, but we should only ever have
- // one ScriptContext per v8::Context.
- for (ContextSet::iterator iter = contexts_.begin(); iter != contexts_.end();
- ++iter) {
- ScriptContext* candidate = *iter;
- if (candidate != context)
- DCHECK(candidate->v8_context() != context->v8_context());
- }
-#endif
- contexts_.insert(context);
+ScriptContext* ScriptContextSet::Register(
+ blink::WebLocalFrame* frame,
+ const v8::Handle<v8::Context>& v8_context,
+ int extension_group,
+ int world_id) {
+ const Extension* extension =
+ GetExtensionFromFrameAndWorld(frame, world_id, false);
+ const Extension* effective_extension =
+ GetExtensionFromFrameAndWorld(frame, world_id, true);
+
+ GURL frame_url = ScriptContext::GetDataSourceURLForFrame(frame);
+ Feature::Context context_type =
+ ClassifyJavaScriptContext(extension, extension_group, frame_url,
+ frame->document().securityOrigin());
+ Feature::Context effective_context_type = ClassifyJavaScriptContext(
+ effective_extension, extension_group,
+ ScriptContext::GetEffectiveDocumentURL(frame, frame_url, true),
+ frame->document().securityOrigin());
+
+ ScriptContext* context =
+ new ScriptContext(v8_context, frame, extension, context_type,
+ effective_extension, effective_context_type);
+ contexts_.insert(context); // takes ownership
+ return context;
}
void ScriptContextSet::Remove(ScriptContext* context) {
@@ -42,32 +58,25 @@ void ScriptContextSet::Remove(ScriptContext* context) {
}
}
-ScriptContextSet::ContextSet ScriptContextSet::GetAll() const {
- return contexts_;
-}
-
ScriptContext* ScriptContextSet::GetCurrent() const {
v8::Isolate* isolate = v8::Isolate::GetCurrent();
return isolate->InContext() ? GetByV8Context(isolate->GetCurrentContext())
- : NULL;
+ : nullptr;
}
ScriptContext* ScriptContextSet::GetCalling() const {
v8::Isolate* isolate = v8::Isolate::GetCurrent();
v8::Local<v8::Context> calling = isolate->GetCallingContext();
- return calling.IsEmpty() ? NULL : GetByV8Context(calling);
+ return calling.IsEmpty() ? nullptr : GetByV8Context(calling);
}
ScriptContext* ScriptContextSet::GetByV8Context(
- v8::Handle<v8::Context> v8_context) const {
- for (ContextSet::const_iterator iter = contexts_.begin();
- iter != contexts_.end();
- ++iter) {
- if ((*iter)->v8_context() == v8_context)
- return *iter;
+ const v8::Handle<v8::Context>& v8_context) const {
+ for (ScriptContext* script_context : contexts_) {
+ if (script_context->v8_context() == v8_context)
+ return script_context;
}
-
- return NULL;
+ return nullptr;
}
void ScriptContextSet::ForEach(
@@ -76,11 +85,9 @@ void ScriptContextSet::ForEach(
const base::Callback<void(ScriptContext*)>& callback) const {
// We copy the context list, because calling into javascript may modify it
// out from under us.
- ContextSet contexts = GetAll();
-
- for (ContextSet::iterator it = contexts.begin(); it != contexts.end(); ++it) {
- ScriptContext* context = *it;
+ std::set<ScriptContext*> contexts_copy = contexts_;
+ for (ScriptContext* context : contexts_copy) {
// For the same reason as above, contexts may become invalid while we run.
if (!context->is_valid())
continue;
@@ -102,23 +109,103 @@ void ScriptContextSet::ForEach(
}
}
-ScriptContextSet::ContextSet ScriptContextSet::OnExtensionUnloaded(
+std::set<ScriptContext*> ScriptContextSet::OnExtensionUnloaded(
const std::string& extension_id) {
- ContextSet contexts = GetAll();
- ContextSet removed;
-
- // Clean up contexts belonging to the unloaded extension. This is done so
- // that content scripts (which remain injected into the page) don't continue
- // receiving events and sending messages.
- for (ContextSet::iterator it = contexts.begin(); it != contexts.end(); ++it) {
- if ((*it)->extension() && (*it)->extension()->id() == extension_id) {
- (*it)->DispatchOnUnloadEvent();
- removed.insert(*it);
- Remove(*it);
- }
+ std::set<ScriptContext*> removed;
+ ForEach(extension_id,
+ base::Bind(&ScriptContextSet::DispatchOnUnloadEventAndRemove,
+ base::Unretained(this), &removed));
+ return removed;
+}
+
+const Extension* ScriptContextSet::GetExtensionFromFrameAndWorld(
+ const blink::WebLocalFrame* frame,
+ int world_id,
+ bool use_effective_url) {
+ std::string extension_id;
+ if (world_id != 0) {
+ // Isolated worlds (content script).
+ extension_id = ScriptInjection::GetHostIdForIsolatedWorld(world_id);
+ } else if (!frame->document().securityOrigin().isUnique()) {
+ // TODO(kalman): Delete the above check.
+ // Extension pages (chrome-extension:// URLs).
+ GURL frame_url = ScriptContext::GetDataSourceURLForFrame(frame);
+ frame_url = ScriptContext::GetEffectiveDocumentURL(frame, frame_url,
+ use_effective_url);
+ extension_id = extensions_->GetExtensionOrAppIDByURL(frame_url);
}
- return removed;
+ // There are conditions where despite a context being associated with an
+ // extension, no extension actually gets found. Ignore "invalid" because CSP
+ // blocks extension page loading by switching the extension ID to "invalid".
+ const Extension* extension = extensions_->GetByID(extension_id);
+ if (!extension && !extension_id.empty() && extension_id != "invalid") {
+ // TODO(kalman): Do something here?
+ }
+ return extension;
+}
+
+Feature::Context ScriptContextSet::ClassifyJavaScriptContext(
+ const Extension* extension,
+ int extension_group,
+ const GURL& url,
+ const blink::WebSecurityOrigin& origin) {
+ // WARNING: This logic must match ProcessMap::GetContextType, as much as
+ // possible.
+
+ DCHECK_GE(extension_group, 0);
+ if (extension_group == EXTENSION_GROUP_CONTENT_SCRIPTS) {
+ return extension ? // TODO(kalman): when does this happen?
+ Feature::CONTENT_SCRIPT_CONTEXT
+ : Feature::UNSPECIFIED_CONTEXT;
+ }
+
+ // We have an explicit check for sandboxed pages before checking whether the
+ // extension is active in this process because:
+ // 1. Sandboxed pages run in the same process as regular extension pages, so
+ // the extension is considered active.
+ // 2. ScriptContext creation (which triggers bindings injection) happens
+ // before the SecurityContext is updated with the sandbox flags (after
+ // reading the CSP header), so the caller can't check if the context's
+ // security origin is unique yet.
+ if (ScriptContext::IsSandboxedPage(*extensions_, url))
+ return Feature::WEB_PAGE_CONTEXT;
+
+ if (extension && active_extension_ids_->count(extension->id()) > 0) {
+ // |extension| is active in this process, but it could be either a true
+ // extension process or within the extent of a hosted app. In the latter
+ // case this would usually be considered a (blessed) web page context,
+ // unless the extension in question is a component extension, in which case
+ // we cheat and call it blessed.
+ return (extension->is_hosted_app() &&
+ extension->location() != Manifest::COMPONENT)
+ ? Feature::BLESSED_WEB_PAGE_CONTEXT
+ : Feature::BLESSED_EXTENSION_CONTEXT;
+ }
+
+ // TODO(kalman): This isUnique() check is wrong, it should be performed as
+ // part of ScriptContext::IsSandboxedPage().
+ if (!origin.isUnique() && extensions_->ExtensionBindingsAllowed(url)) {
+ if (!extension) // TODO(kalman): when does this happen?
+ return Feature::UNSPECIFIED_CONTEXT;
+ return extension->is_hosted_app() ? Feature::BLESSED_WEB_PAGE_CONTEXT
+ : Feature::UNBLESSED_EXTENSION_CONTEXT;
+ }
+
+ if (!url.is_valid())
+ return Feature::UNSPECIFIED_CONTEXT;
+
+ if (url.SchemeIs(content::kChromeUIScheme))
+ return Feature::WEBUI_CONTEXT;
+
+ return Feature::WEB_PAGE_CONTEXT;
+}
+
+void ScriptContextSet::DispatchOnUnloadEventAndRemove(
+ std::set<ScriptContext*>* out,
+ ScriptContext* context) {
+ Remove(context); // deleted asynchronously
+ out->insert(context);
}
} // namespace extensions
« no previous file with comments | « extensions/renderer/script_context_set.h ('k') | extensions/renderer/script_context_set_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698