| Index: extensions/renderer/script_context_set.cc
|
| diff --git a/extensions/renderer/script_context_set.cc b/extensions/renderer/script_context_set.cc
|
| index 1e9e9e8ee3f2f852877909ebcff7a40ccad1fd0c..5f7be6c156f84c6b031580b5ee4fcc486ae6171d 100644
|
| --- a/extensions/renderer/script_context_set.cc
|
| +++ b/extensions/renderer/script_context_set.cc
|
| @@ -5,50 +5,34 @@
|
| #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(ExtensionSet* extensions,
|
| - ExtensionIdSet* active_extension_ids)
|
| - : extensions_(extensions), active_extension_ids_(active_extension_ids) {
|
| +ScriptContextSet::ScriptContextSet() {
|
| }
|
| -
|
| ScriptContextSet::~ScriptContextSet() {
|
| }
|
|
|
| -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);
|
| +int ScriptContextSet::size() const {
|
| + return static_cast<int>(contexts_.size());
|
| +}
|
|
|
| - 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::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);
|
| }
|
|
|
| void ScriptContextSet::Remove(ScriptContext* context) {
|
| @@ -58,25 +42,32 @@
|
| }
|
| }
|
|
|
| +ScriptContextSet::ContextSet ScriptContextSet::GetAll() const {
|
| + return contexts_;
|
| +}
|
| +
|
| ScriptContext* ScriptContextSet::GetCurrent() const {
|
| v8::Isolate* isolate = v8::Isolate::GetCurrent();
|
| return isolate->InContext() ? GetByV8Context(isolate->GetCurrentContext())
|
| - : nullptr;
|
| + : NULL;
|
| }
|
|
|
| ScriptContext* ScriptContextSet::GetCalling() const {
|
| v8::Isolate* isolate = v8::Isolate::GetCurrent();
|
| v8::Local<v8::Context> calling = isolate->GetCallingContext();
|
| - return calling.IsEmpty() ? nullptr : GetByV8Context(calling);
|
| + return calling.IsEmpty() ? NULL : GetByV8Context(calling);
|
| }
|
|
|
| ScriptContext* ScriptContextSet::GetByV8Context(
|
| - const v8::Handle<v8::Context>& v8_context) const {
|
| - for (ScriptContext* script_context : contexts_) {
|
| - if (script_context->v8_context() == v8_context)
|
| - return script_context;
|
| + 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;
|
| }
|
| - return nullptr;
|
| +
|
| + return NULL;
|
| }
|
|
|
| void ScriptContextSet::ForEach(
|
| @@ -85,9 +76,11 @@
|
| const base::Callback<void(ScriptContext*)>& callback) const {
|
| // We copy the context list, because calling into javascript may modify it
|
| // out from under us.
|
| - std::set<ScriptContext*> contexts_copy = contexts_;
|
| + ContextSet contexts = GetAll();
|
|
|
| - for (ScriptContext* context : contexts_copy) {
|
| + for (ContextSet::iterator it = contexts.begin(); it != contexts.end(); ++it) {
|
| + ScriptContext* context = *it;
|
| +
|
| // For the same reason as above, contexts may become invalid while we run.
|
| if (!context->is_valid())
|
| continue;
|
| @@ -109,103 +102,23 @@
|
| }
|
| }
|
|
|
| -std::set<ScriptContext*> ScriptContextSet::OnExtensionUnloaded(
|
| +ScriptContextSet::ContextSet ScriptContextSet::OnExtensionUnloaded(
|
| const std::string& extension_id) {
|
| - std::set<ScriptContext*> removed;
|
| - ForEach(extension_id,
|
| - base::Bind(&ScriptContextSet::DispatchOnUnloadEventAndRemove,
|
| - base::Unretained(this), &removed));
|
| + 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);
|
| + }
|
| + }
|
| +
|
| 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);
|
| - }
|
| -
|
| - // 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
|
|
|