Commit 77b04119 authored by kalman's avatar kalman Committed by Commit bot

Revert of Move Extension ScriptContext creation into ScriptContextSet....

Revert of Move Extension ScriptContext creation into ScriptContextSet. (patchset #4 id:60001 of https://codereview.chromium.org/995283004/)

Reason for revert:
Memory failure in ScriptContextTest.GinRunnerLifetime.

Original issue's description:
> Move Extension ScriptContext creation into ScriptContextSet.
>
> Previously extensions::Dispatcher was responsible for creating ScriptContexts
> then Adding them to its ScriptContextSet. Now, ScriptContextSet creates them
> itself. This prepares the Extension system for later changing to lazily or
> asynchronously creating ScriptContexts.
>
> BUG=466373
> R=rockot@chromium.org
>
> Committed: https://crrev.com/75605c7fca774b95984ba67f70ba86bb5750c0f6
> Cr-Commit-Position: refs/heads/master@{#320602}
>
> Committed: https://crrev.com/52f4caf6d01302ebf42136b42fa77d1c67d93ae9
> Cr-Commit-Position: refs/heads/master@{#320770}

TBR=rockot@chromium.org
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true
BUG=466373

Review URL: https://codereview.chromium.org/1013823003

Cr-Commit-Position: refs/heads/master@{#320794}
parent c02ec7c4
...@@ -14,7 +14,6 @@ ...@@ -14,7 +14,6 @@
#include "extensions/renderer/script_context.h" #include "extensions/renderer/script_context.h"
#include "third_party/WebKit/public/web/WebDocument.h" #include "third_party/WebKit/public/web/WebDocument.h"
#include "third_party/WebKit/public/web/WebElement.h" #include "third_party/WebKit/public/web/WebElement.h"
#include "third_party/WebKit/public/web/WebLocalFrame.h"
#include "third_party/WebKit/public/web/WebNode.h" #include "third_party/WebKit/public/web/WebNode.h"
#include "third_party/WebKit/public/web/WebNodeList.h" #include "third_party/WebKit/public/web/WebNodeList.h"
#include "third_party/WebKit/public/web/WebUserGestureIndicator.h" #include "third_party/WebKit/public/web/WebUserGestureIndicator.h"
...@@ -23,6 +22,7 @@ ...@@ -23,6 +22,7 @@
using blink::WebDocument; using blink::WebDocument;
using blink::WebElement; using blink::WebElement;
using blink::WebFrame;
using blink::WebNode; using blink::WebNode;
using blink::WebNodeList; using blink::WebNodeList;
using blink::WebUserGestureIndicator; using blink::WebUserGestureIndicator;
...@@ -79,7 +79,7 @@ void WebstoreBindings::Install( ...@@ -79,7 +79,7 @@ void WebstoreBindings::Install(
std::string webstore_item_id; std::string webstore_item_id;
std::string error; std::string error;
blink::WebLocalFrame* frame = context()->web_frame(); WebFrame* frame = context()->web_frame();
if (!GetWebstoreItemIdFromFrame( if (!GetWebstoreItemIdFromFrame(
frame, preferred_store_link_url, &webstore_item_id, &error)) { frame, preferred_store_link_url, &webstore_item_id, &error)) {
...@@ -102,10 +102,8 @@ void WebstoreBindings::Install( ...@@ -102,10 +102,8 @@ void WebstoreBindings::Install(
// static // static
bool WebstoreBindings::GetWebstoreItemIdFromFrame( bool WebstoreBindings::GetWebstoreItemIdFromFrame(
blink::WebLocalFrame* frame, WebFrame* frame, const std::string& preferred_store_link_url,
const std::string& preferred_store_link_url, std::string* webstore_item_id, std::string* error) {
std::string* webstore_item_id,
std::string* error) {
if (frame != frame->top()) { if (frame != frame->top()) {
*error = kNotInTopFrameError; *error = kNotInTopFrameError;
return false; return false;
......
...@@ -9,10 +9,7 @@ ...@@ -9,10 +9,7 @@
#include "chrome/common/extensions/webstore_install_result.h" #include "chrome/common/extensions/webstore_install_result.h"
#include "chrome/renderer/extensions/chrome_v8_extension_handler.h" #include "chrome/renderer/extensions/chrome_v8_extension_handler.h"
#include "extensions/renderer/object_backed_native_handler.h" #include "extensions/renderer/object_backed_native_handler.h"
#include "third_party/WebKit/public/web/WebFrame.h"
namespace blink {
class WebLocalFrame;
}
namespace extensions { namespace extensions {
...@@ -45,10 +42,8 @@ class WebstoreBindings : public ObjectBackedNativeHandler, ...@@ -45,10 +42,8 @@ class WebstoreBindings : public ObjectBackedNativeHandler,
// parameter will be populated with the ID. On failure, false will be returned // parameter will be populated with the ID. On failure, false will be returned
// and |error| will be populated with the error. // and |error| will be populated with the error.
static bool GetWebstoreItemIdFromFrame( static bool GetWebstoreItemIdFromFrame(
blink::WebLocalFrame* frame, blink::WebFrame* frame, const std::string& preferred_store_link_url,
const std::string& preferred_store_link_url, std::string* webstore_item_id, std::string* error);
std::string* webstore_item_id,
std::string* error);
DISALLOW_COPY_AND_ASSIGN(WebstoreBindings); DISALLOW_COPY_AND_ASSIGN(WebstoreBindings);
}; };
......
This diff is collapsed.
...@@ -11,12 +11,10 @@ ...@@ -11,12 +11,10 @@
#include <utility> #include <utility>
#include <vector> #include <vector>
#include "base/memory/scoped_ptr.h"
#include "base/scoped_observer.h" #include "base/scoped_observer.h"
#include "base/timer/timer.h" #include "base/timer/timer.h"
#include "content/public/renderer/render_process_observer.h" #include "content/public/renderer/render_process_observer.h"
#include "extensions/common/event_filter.h" #include "extensions/common/event_filter.h"
#include "extensions/common/extension.h"
#include "extensions/common/extension_set.h" #include "extensions/common/extension_set.h"
#include "extensions/common/extensions_client.h" #include "extensions/common/extensions_client.h"
#include "extensions/common/features/feature.h" #include "extensions/common/features/feature.h"
...@@ -55,6 +53,7 @@ class RenderThread; ...@@ -55,6 +53,7 @@ class RenderThread;
namespace extensions { namespace extensions {
class ContentWatcher; class ContentWatcher;
class DispatcherDelegate; class DispatcherDelegate;
class Extension;
class FilteredEventRouter; class FilteredEventRouter;
class ManifestPermissionSet; class ManifestPermissionSet;
class RequestSender; class RequestSender;
...@@ -77,7 +76,7 @@ class Dispatcher : public content::RenderProcessObserver, ...@@ -77,7 +76,7 @@ class Dispatcher : public content::RenderProcessObserver,
const ExtensionSet* extensions() const { return &extensions_; } const ExtensionSet* extensions() const { return &extensions_; }
const ScriptContextSet& script_context_set() const { const ScriptContextSet& script_context_set() const {
return *script_context_set_; return script_context_set_;
} }
V8SchemaRegistry* v8_schema_registry() { return v8_schema_registry_.get(); } V8SchemaRegistry* v8_schema_registry() { return v8_schema_registry_.get(); }
...@@ -90,6 +89,14 @@ class Dispatcher : public content::RenderProcessObserver, ...@@ -90,6 +89,14 @@ class Dispatcher : public content::RenderProcessObserver,
bool IsExtensionActive(const std::string& extension_id) const; bool IsExtensionActive(const std::string& extension_id) const;
// Finds the extension for the JavaScript context associated with the
// specified |frame| and isolated world. If |world_id| is zero, finds the
// extension ID associated with the main world's JavaScript context. If the
// JavaScript context isn't from an extension, returns empty string.
const Extension* GetExtensionFromFrameAndWorld(const blink::WebFrame* frame,
int world_id,
bool use_effective_url);
void DidCreateScriptContext(blink::WebLocalFrame* frame, void DidCreateScriptContext(blink::WebLocalFrame* frame,
const v8::Handle<v8::Context>& context, const v8::Handle<v8::Context>& context,
int extension_group, int extension_group,
...@@ -235,6 +242,15 @@ class Dispatcher : public content::RenderProcessObserver, ...@@ -235,6 +242,15 @@ class Dispatcher : public content::RenderProcessObserver,
// Returns whether the current renderer hosts a platform app. // Returns whether the current renderer hosts a platform app.
bool IsWithinPlatformApp(); bool IsWithinPlatformApp();
bool IsSandboxedPage(const GURL& url) const;
// Returns the Feature::Context type of context for a JavaScript context.
Feature::Context ClassifyJavaScriptContext(
const Extension* extension,
int extension_group,
const GURL& url,
const blink::WebSecurityOrigin& origin);
// Gets |field| from |object| or creates it as an empty object if it doesn't // Gets |field| from |object| or creates it as an empty object if it doesn't
// exist. // exist.
v8::Handle<v8::Object> GetOrCreateObject(const v8::Handle<v8::Object>& object, v8::Handle<v8::Object> GetOrCreateObject(const v8::Handle<v8::Object>& object,
...@@ -268,7 +284,7 @@ class Dispatcher : public content::RenderProcessObserver, ...@@ -268,7 +284,7 @@ class Dispatcher : public content::RenderProcessObserver,
// All the bindings contexts that are currently loaded for this renderer. // All the bindings contexts that are currently loaded for this renderer.
// There is zero or one for each v8 context. // There is zero or one for each v8 context.
scoped_ptr<ScriptContextSet> script_context_set_; ScriptContextSet script_context_set_;
scoped_ptr<ContentWatcher> content_watcher_; scoped_ptr<ContentWatcher> content_watcher_;
...@@ -284,7 +300,7 @@ class Dispatcher : public content::RenderProcessObserver, ...@@ -284,7 +300,7 @@ class Dispatcher : public content::RenderProcessObserver,
std::set<std::string> function_names_; std::set<std::string> function_names_;
// The extensions and apps that are active in this process. // The extensions and apps that are active in this process.
ExtensionIdSet active_extension_ids_; std::set<std::string> active_extension_ids_;
ResourceBundleSourceMap source_map_; ResourceBundleSourceMap source_map_;
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
#include "base/bind.h" #include "base/bind.h"
#include "extensions/renderer/script_context.h" #include "extensions/renderer/script_context.h"
#include "third_party/WebKit/public/web/WebDocument.h" #include "third_party/WebKit/public/web/WebDocument.h"
#include "third_party/WebKit/public/web/WebLocalFrame.h" #include "third_party/WebKit/public/web/WebFrame.h"
#include "v8/include/v8.h" #include "v8/include/v8.h"
namespace extensions { namespace extensions {
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
#include "extensions/renderer/dispatcher.h" #include "extensions/renderer/dispatcher.h"
#include "extensions/renderer/script_context.h" #include "extensions/renderer/script_context.h"
#include "third_party/WebKit/public/web/WebDocument.h" #include "third_party/WebKit/public/web/WebDocument.h"
#include "third_party/WebKit/public/web/WebLocalFrame.h" #include "third_party/WebKit/public/web/WebFrame.h"
#include "third_party/WebKit/public/web/WebScopedUserGesture.h" #include "third_party/WebKit/public/web/WebScopedUserGesture.h"
#include "third_party/WebKit/public/web/WebUserGestureIndicator.h" #include "third_party/WebKit/public/web/WebUserGestureIndicator.h"
#include "third_party/WebKit/public/web/WebUserGestureToken.h" #include "third_party/WebKit/public/web/WebUserGestureToken.h"
...@@ -97,7 +97,7 @@ void RequestSender::StartRequest(Source* source, ...@@ -97,7 +97,7 @@ void RequestSender::StartRequest(Source* source,
return; return;
GURL source_url; GURL source_url;
if (blink::WebLocalFrame* webframe = context->web_frame()) if (blink::WebFrame* webframe = context->web_frame())
source_url = webframe->document().url(); source_url = webframe->document().url();
InsertRequest(request_id, new PendingRequest(name, source, InsertRequest(request_id, new PendingRequest(name, source,
......
...@@ -13,19 +13,15 @@ ...@@ -13,19 +13,15 @@
#include "content/public/common/url_constants.h" #include "content/public/common/url_constants.h"
#include "content/public/renderer/render_frame.h" #include "content/public/renderer/render_frame.h"
#include "content/public/renderer/render_view.h" #include "content/public/renderer/render_view.h"
#include "extensions/common/constants.h"
#include "extensions/common/extension.h" #include "extensions/common/extension.h"
#include "extensions/common/extension_api.h" #include "extensions/common/extension_api.h"
#include "extensions/common/extension_set.h"
#include "extensions/common/extension_urls.h" #include "extensions/common/extension_urls.h"
#include "extensions/common/features/base_feature_provider.h" #include "extensions/common/features/base_feature_provider.h"
#include "extensions/common/manifest_handlers/sandboxed_page_info.h"
#include "extensions/common/permissions/permissions_data.h" #include "extensions/common/permissions/permissions_data.h"
#include "gin/per_context_data.h" #include "gin/per_context_data.h"
#include "third_party/WebKit/public/web/WebDataSource.h" #include "third_party/WebKit/public/web/WebDataSource.h"
#include "third_party/WebKit/public/web/WebDocument.h" #include "third_party/WebKit/public/web/WebDocument.h"
#include "third_party/WebKit/public/web/WebFrame.h" #include "third_party/WebKit/public/web/WebFrame.h"
#include "third_party/WebKit/public/web/WebLocalFrame.h"
#include "third_party/WebKit/public/web/WebScopedMicrotaskSuppression.h" #include "third_party/WebKit/public/web/WebScopedMicrotaskSuppression.h"
#include "third_party/WebKit/public/web/WebSecurityOrigin.h" #include "third_party/WebKit/public/web/WebSecurityOrigin.h"
#include "third_party/WebKit/public/web/WebView.h" #include "third_party/WebKit/public/web/WebView.h"
...@@ -79,7 +75,7 @@ class ScriptContext::Runner : public gin::Runner { ...@@ -79,7 +75,7 @@ class ScriptContext::Runner : public gin::Runner {
}; };
ScriptContext::ScriptContext(const v8::Handle<v8::Context>& v8_context, ScriptContext::ScriptContext(const v8::Handle<v8::Context>& v8_context,
blink::WebLocalFrame* web_frame, blink::WebFrame* web_frame,
const Extension* extension, const Extension* extension,
Feature::Context context_type, Feature::Context context_type,
const Extension* effective_extension, const Extension* effective_extension,
...@@ -114,21 +110,6 @@ ScriptContext::~ScriptContext() { ...@@ -114,21 +110,6 @@ ScriptContext::~ScriptContext() {
Invalidate(); Invalidate();
} }
// static
bool ScriptContext::IsSandboxedPage(const ExtensionSet& extensions,
const GURL& url) {
// TODO(kalman): This is checking for the wrong thing, it should be checking
// if the frame's security origin is unique. The extension sandbox directive
// is checked for in extensions/common/manifest_handlers/csp_info.cc.
if (url.SchemeIs(kExtensionScheme)) {
const Extension* extension = extensions.GetByID(url.host());
if (extension) {
return SandboxedPageInfo::IsSandboxedPage(extension, url.path());
}
}
return false;
}
void ScriptContext::Invalidate() { void ScriptContext::Invalidate() {
if (!is_valid()) if (!is_valid())
return; return;
......
...@@ -20,7 +20,6 @@ ...@@ -20,7 +20,6 @@
namespace blink { namespace blink {
class WebFrame; class WebFrame;
class WebLocalFrame;
} }
namespace content { namespace content {
...@@ -30,27 +29,18 @@ class RenderView; ...@@ -30,27 +29,18 @@ class RenderView;
namespace extensions { namespace extensions {
class Extension; class Extension;
class ExtensionSet;
// Extensions wrapper for a v8 context. // Extensions wrapper for a v8 context.
class ScriptContext : public RequestSender::Source { class ScriptContext : public RequestSender::Source {
public: public:
ScriptContext(const v8::Handle<v8::Context>& context, ScriptContext(const v8::Handle<v8::Context>& context,
blink::WebLocalFrame* frame, blink::WebFrame* frame,
const Extension* extension, const Extension* extension,
Feature::Context context_type, Feature::Context context_type,
const Extension* effective_extension, const Extension* effective_extension,
Feature::Context effective_context_type); Feature::Context effective_context_type);
~ScriptContext() override; ~ScriptContext() override;
// Returns whether |url| is sandboxed (as declared in any Extension in
// |extension_set| as sandboxed).
//
// Declared in ScriptContext for lack of a better place, but this should
// become unnecessary at some point as crbug.com/466373 is worked on.
static bool IsSandboxedPage(const ExtensionSet& extension_set,
const GURL& url);
// Clears the WebFrame for this contexts and invalidates the associated // Clears the WebFrame for this contexts and invalidates the associated
// ModuleSystem. // ModuleSystem.
void Invalidate(); void Invalidate();
...@@ -69,7 +59,7 @@ class ScriptContext : public RequestSender::Source { ...@@ -69,7 +59,7 @@ class ScriptContext : public RequestSender::Source {
return effective_extension_.get(); return effective_extension_.get();
} }
blink::WebLocalFrame* web_frame() const { return web_frame_; } blink::WebFrame* web_frame() const { return web_frame_; }
Feature::Context context_type() const { return context_type_; } Feature::Context context_type() const { return context_type_; }
...@@ -124,14 +114,6 @@ class ScriptContext : public RequestSender::Source { ...@@ -124,14 +114,6 @@ class ScriptContext : public RequestSender::Source {
v8::Isolate* isolate() const { return isolate_; } v8::Isolate* isolate() const { return isolate_; }
// Get the URL of this context's web frame. // Get the URL of this context's web frame.
//
// TODO(kalman): Remove this and replace with a GetOrigin() call which reads
// of WebDocument::securityOrigin():
// - The URL can change (e.g. pushState) but the origin cannot. Luckily it
// appears as though callers don't make security decisions based on the
// result of GetURL() so it's not a problem... yet.
// - Origin is the correct check to be making.
// - It might let us remove the about:blank resolving?
GURL GetURL() const; GURL GetURL() const;
// Returns whether the API |api| or any part of the API could be // Returns whether the API |api| or any part of the API could be
...@@ -175,9 +157,9 @@ class ScriptContext : public RequestSender::Source { ...@@ -175,9 +157,9 @@ class ScriptContext : public RequestSender::Source {
private: private:
class Runner; class Runner;
// The WebLocalFrame associated with this context. This can be NULL because // The WebFrame associated with this context. This can be NULL because this
// this object can outlive is destroyed asynchronously. // object can outlive is destroyed asynchronously.
blink::WebLocalFrame* web_frame_; blink::WebFrame* web_frame_;
// The extension associated with this context, or NULL if there is none. This // The extension associated with this context, or NULL if there is none. This
// might be a hosted app in the case that this context is hosting a web URL. // might be a hosted app in the case that this context is hosting a web URL.
......
...@@ -5,50 +5,34 @@ ...@@ -5,50 +5,34 @@
#include "extensions/renderer/script_context_set.h" #include "extensions/renderer/script_context_set.h"
#include "base/message_loop/message_loop.h" #include "base/message_loop/message_loop.h"
#include "content/public/common/url_constants.h"
#include "content/public/renderer/render_view.h" #include "content/public/renderer/render_view.h"
#include "extensions/common/extension.h" #include "extensions/common/extension.h"
#include "extensions/renderer/extension_groups.h"
#include "extensions/renderer/script_context.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" #include "v8/include/v8.h"
namespace extensions { namespace extensions {
ScriptContextSet::ScriptContextSet(ExtensionSet* extensions, ScriptContextSet::ScriptContextSet() {
ExtensionIdSet* active_extension_ids)
: extensions_(extensions), active_extension_ids_(active_extension_ids) {
} }
ScriptContextSet::~ScriptContextSet() { ScriptContextSet::~ScriptContextSet() {
} }
ScriptContext* ScriptContextSet::Register( int ScriptContextSet::size() const {
blink::WebLocalFrame* frame, return static_cast<int>(contexts_.size());
const v8::Handle<v8::Context>& v8_context, }
int extension_group,
int world_id) { void ScriptContextSet::Add(ScriptContext* context) {
const Extension* extension = #if DCHECK_IS_ON()
GetExtensionFromFrameAndWorld(frame, world_id, false); // It's OK to insert the same context twice, but we should only ever have
const Extension* effective_extension = // one ScriptContext per v8::Context.
GetExtensionFromFrameAndWorld(frame, world_id, true); for (ContextSet::iterator iter = contexts_.begin(); iter != contexts_.end();
++iter) {
GURL frame_url = ScriptContext::GetDataSourceURLForFrame(frame); ScriptContext* candidate = *iter;
Feature::Context context_type = if (candidate != context)
ClassifyJavaScriptContext(extension, extension_group, frame_url, DCHECK(candidate->v8_context() != context->v8_context());
frame->document().securityOrigin()); }
Feature::Context effective_context_type = ClassifyJavaScriptContext( #endif
effective_extension, extension_group, contexts_.insert(context);
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) { void ScriptContextSet::Remove(ScriptContext* context) {
...@@ -58,25 +42,32 @@ void ScriptContextSet::Remove(ScriptContext* context) { ...@@ -58,25 +42,32 @@ void ScriptContextSet::Remove(ScriptContext* context) {
} }
} }
ScriptContextSet::ContextSet ScriptContextSet::GetAll() const {
return contexts_;
}
ScriptContext* ScriptContextSet::GetCurrent() const { ScriptContext* ScriptContextSet::GetCurrent() const {
v8::Isolate* isolate = v8::Isolate::GetCurrent(); v8::Isolate* isolate = v8::Isolate::GetCurrent();
return isolate->InContext() ? GetByV8Context(isolate->GetCurrentContext()) return isolate->InContext() ? GetByV8Context(isolate->GetCurrentContext())
: nullptr; : NULL;
} }
ScriptContext* ScriptContextSet::GetCalling() const { ScriptContext* ScriptContextSet::GetCalling() const {
v8::Isolate* isolate = v8::Isolate::GetCurrent(); v8::Isolate* isolate = v8::Isolate::GetCurrent();
v8::Local<v8::Context> calling = isolate->GetCallingContext(); v8::Local<v8::Context> calling = isolate->GetCallingContext();
return calling.IsEmpty() ? nullptr : GetByV8Context(calling); return calling.IsEmpty() ? NULL : GetByV8Context(calling);
} }
ScriptContext* ScriptContextSet::GetByV8Context( ScriptContext* ScriptContextSet::GetByV8Context(
const v8::Handle<v8::Context>& v8_context) const { v8::Handle<v8::Context> v8_context) const {
for (ScriptContext* script_context : contexts_) { for (ContextSet::const_iterator iter = contexts_.begin();
if (script_context->v8_context() == v8_context) iter != contexts_.end();
return script_context; ++iter) {
if ((*iter)->v8_context() == v8_context)
return *iter;
} }
return nullptr;
return NULL;
} }
void ScriptContextSet::ForEach( void ScriptContextSet::ForEach(
...@@ -85,9 +76,11 @@ void ScriptContextSet::ForEach( ...@@ -85,9 +76,11 @@ void ScriptContextSet::ForEach(
const base::Callback<void(ScriptContext*)>& callback) const { const base::Callback<void(ScriptContext*)>& callback) const {
// We copy the context list, because calling into javascript may modify it // We copy the context list, because calling into javascript may modify it
// out from under us. // out from under us.
std::set<ScriptContext*> contexts_copy = contexts_; ContextSet contexts = GetAll();
for (ContextSet::iterator it = contexts.begin(); it != contexts.end(); ++it) {
ScriptContext* context = *it;
for (ScriptContext* context : contexts_copy) {
// For the same reason as above, contexts may become invalid while we run. // For the same reason as above, contexts may become invalid while we run.
if (!context->is_valid()) if (!context->is_valid())
continue; continue;
...@@ -109,103 +102,23 @@ void ScriptContextSet::ForEach( ...@@ -109,103 +102,23 @@ void ScriptContextSet::ForEach(
} }
} }
std::set<ScriptContext*> ScriptContextSet::OnExtensionUnloaded( ScriptContextSet::ContextSet ScriptContextSet::OnExtensionUnloaded(
const std::string& extension_id) { const std::string& extension_id) {
std::set<ScriptContext*> removed; ContextSet contexts = GetAll();
ForEach(extension_id, ContextSet removed;
base::Bind(&ScriptContextSet::DispatchOnUnloadEventAndRemove,
base::Unretained(this), &removed)); // Clean up contexts belonging to the unloaded extension. This is done so
return removed; // 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) {
const Extension* ScriptContextSet::GetExtensionFromFrameAndWorld( if ((*it)->extension() && (*it)->extension()->id() == extension_id) {
const blink::WebLocalFrame* frame, (*it)->DispatchOnUnloadEvent();
int world_id, removed.insert(*it);
bool use_effective_url) { Remove(*it);
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 removed;
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 } // namespace extensions
...@@ -8,12 +8,8 @@ ...@@ -8,12 +8,8 @@
#include <set> #include <set>
#include <string> #include <string>
#include "base/macros.h" #include "base/basictypes.h"
#include "base/memory/weak_ptr.h" #include "base/bind.h"
#include "extensions/common/extension.h"
#include "extensions/common/extension_set.h"
#include "extensions/common/features/feature.h"
#include "url/gurl.h"
#include "v8/include/v8.h" #include "v8/include/v8.h"
class GURL; class GURL;
...@@ -22,50 +18,39 @@ namespace base { ...@@ -22,50 +18,39 @@ namespace base {
class ListValue; class ListValue;
} }
namespace blink {
class WebLocalFrame;
class WebSecurityOrigin;
}
namespace content { namespace content {
class RenderView; class RenderView;
} }
namespace v8 {
class Context;
}
namespace extensions { namespace extensions {
class ScriptContext; class ScriptContext;
// A container of ScriptContexts, responsible for both creating and managing // A container of ExtensionBindingsContext. Since calling JavaScript within a
// them. // context can cause any number of contexts to be created or destroyed, this
// // has additional smarts to help with the set changing underneath callers.
// Since calling JavaScript within a context can cause any number of contexts
// to be created or destroyed, this has additional smarts to help with the set
// changing underneath callers.
class ScriptContextSet { class ScriptContextSet {
public: public:
ScriptContextSet( ScriptContextSet();
ExtensionSet* extensions,
// Set of the IDs of extensions that are active in this process.
// Must outlive this. TODO(kalman): Combine this and |extensions|.
ExtensionIdSet* active_extension_ids);
~ScriptContextSet(); ~ScriptContextSet();
// Returns the number of contexts being tracked by this set. int size() const;
// This may also include invalid contexts. TODO(kalman): Useful?
size_t size() const { return contexts_.size(); }
// Creates and starts managing a new ScriptContext. Ownership is held. // Takes ownership of |context|.
// Returns a weak reference to the new ScriptContext. void Add(ScriptContext* context);
ScriptContext* Register(blink::WebLocalFrame* frame,
const v8::Handle<v8::Context>& v8_context,
int extension_group,
int world_id);
// If the specified context is contained in this set, remove it, then delete // If the specified context is contained in this set, remove it, then delete
// it asynchronously. After this call returns the context object will still // it asynchronously. After this call returns the context object will still
// be valid, but its frame() pointer will be cleared. // be valid, but its frame() pointer will be cleared.
void Remove(ScriptContext* context); void Remove(ScriptContext* context);
// Returns a copy to protect against changes.
typedef std::set<ScriptContext*> ContextSet;
ContextSet GetAll() const;
// Gets the ScriptContext corresponding to v8::Context::GetCurrent(), or // Gets the ScriptContext corresponding to v8::Context::GetCurrent(), or
// NULL if no such context exists. // NULL if no such context exists.
ScriptContext* GetCurrent() const; ScriptContext* GetCurrent() const;
...@@ -76,7 +61,7 @@ class ScriptContextSet { ...@@ -76,7 +61,7 @@ class ScriptContextSet {
// Gets the ScriptContext corresponding to the specified // Gets the ScriptContext corresponding to the specified
// v8::Context or NULL if no such context exists. // v8::Context or NULL if no such context exists.
ScriptContext* GetByV8Context(const v8::Handle<v8::Context>& context) const; ScriptContext* GetByV8Context(v8::Handle<v8::Context> context) const;
// Synchronously runs |callback| with each ScriptContext that belongs to // Synchronously runs |callback| with each ScriptContext that belongs to
// |extension_id| in |render_view|. // |extension_id| in |render_view|.
...@@ -103,39 +88,10 @@ class ScriptContextSet { ...@@ -103,39 +88,10 @@ class ScriptContextSet {
// Returns the set of ScriptContexts that were removed as a result. These // Returns the set of ScriptContexts that were removed as a result. These
// are safe to interact with until the end of the current event loop, since // are safe to interact with until the end of the current event loop, since
// they're deleted asynchronously. // they're deleted asynchronously.
std::set<ScriptContext*> OnExtensionUnloaded(const std::string& extension_id); ContextSet OnExtensionUnloaded(const std::string& extension_id);
private: private:
// Finds the extension for the JavaScript context associated with the ContextSet contexts_;
// specified |frame| and isolated world. If |world_id| is zero, finds the
// extension ID associated with the main world's JavaScript context. If the
// JavaScript context isn't from an extension, returns empty string.
const Extension* GetExtensionFromFrameAndWorld(
const blink::WebLocalFrame* frame,
int world_id,
bool use_effective_url);
// Returns the Feature::Context type of context for a JavaScript context.
Feature::Context ClassifyJavaScriptContext(
const Extension* extension,
int extension_group,
const GURL& url,
const blink::WebSecurityOrigin& origin);
// Calls Remove on |context| then appends |context| to |out|.
// This is a helper designed to be used by OnExtensionUnloaded with ForEach.
void DispatchOnUnloadEventAndRemove(std::set<ScriptContext*>* out,
ScriptContext* context);
// Weak reference to all installed Extensions.
ExtensionSet* extensions_;
// Weak reference to all installed Extensions that are also active in this
// process.
ExtensionIdSet* active_extension_ids_;
// The set of all ScriptContexts we own.
std::set<ScriptContext*> contexts_;
DISALLOW_COPY_AND_ASSIGN(ScriptContextSet); DISALLOW_COPY_AND_ASSIGN(ScriptContextSet);
}; };
......
...@@ -2,59 +2,61 @@ ...@@ -2,59 +2,61 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#include <vector>
#include "base/message_loop/message_loop.h" #include "base/message_loop/message_loop.h"
#include "extensions/common/extension.h" #include "extensions/common/extension.h"
#include "extensions/common/extension_set.h"
#include "extensions/common/features/feature.h" #include "extensions/common/features/feature.h"
#include "extensions/renderer/script_context.h" #include "extensions/renderer/script_context.h"
#include "extensions/renderer/script_context_set.h" #include "extensions/renderer/script_context_set.h"
#include "gin/public/context_holder.h" #include "gin/public/context_holder.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
#include "third_party/WebKit/public/web/WebFrame.h"
#include "third_party/WebKit/public/web/WebLocalFrame.h" #include "third_party/WebKit/public/web/WebLocalFrame.h"
#include "third_party/WebKit/public/web/WebView.h" #include "third_party/WebKit/public/web/WebView.h"
#include "v8/include/v8.h" #include "v8/include/v8.h"
namespace extensions { namespace extensions {
TEST(ScriptContextSetTest, Lifecycle) { TEST(ScriptContextSet, Lifecycle) {
base::MessageLoop loop; base::MessageLoop loop;
ExtensionSet extensions; ScriptContextSet context_set;
ExtensionIdSet active_extensions;
ScriptContextSet context_set(&extensions, &active_extensions);
blink::WebView* webview = blink::WebView::create(nullptr);
blink::WebLocalFrame* frame = blink::WebLocalFrame::create(nullptr);
webview->setMainFrame(frame);
v8::Isolate* isolate = v8::Isolate::GetCurrent(); v8::Isolate* isolate = v8::Isolate::GetCurrent();
v8::HandleScope handle_scope(isolate); v8::HandleScope handle_scope(isolate);
// Note: ScriptContext has gin stuff in it, and without a ContextHolder tests
// will leak memory.
gin::ContextHolder context_holder(isolate); gin::ContextHolder context_holder(isolate);
v8::Handle<v8::Context> v8_context = v8::Context::New(isolate); context_holder.SetContext(v8::Context::New(isolate));
v8::Context::Scope context_scope(v8_context);
ScriptContext* context = context_set.Register( blink::WebView* webview = blink::WebView::create(nullptr);
frame, v8_context, 0, 0); // no extension group or world ID blink::WebFrame* frame = blink::WebLocalFrame::create(nullptr);
webview->setMainFrame(frame);
const Extension* extension = NULL;
ScriptContext* context =
new ScriptContext(context_holder.context(),
frame,
extension,
Feature::BLESSED_EXTENSION_CONTEXT,
extension,
Feature::BLESSED_EXTENSION_CONTEXT);
context_set.Add(context);
EXPECT_EQ(1u, context_set.GetAll().count(context));
EXPECT_EQ(context, context_set.GetByV8Context(context->v8_context()));
// Context is valid and resembles correctness. // Adding the same item multiple times should be OK and deduped.
EXPECT_TRUE(context->is_valid()); context_set.Add(context);
EXPECT_EQ(frame, context->web_frame()); EXPECT_EQ(1u, context_set.GetAll().count(context));
EXPECT_EQ(v8_context, context->v8_context());
// Context has been correctly added. // GetAll() returns a copy so removing from one should not remove from others.
EXPECT_EQ(1u, context_set.size()); ScriptContextSet::ContextSet set_copy = context_set.GetAll();
EXPECT_EQ(context, context_set.GetByV8Context(v8_context)); EXPECT_EQ(1u, set_copy.count(context));
// Test context is correctly removed.
context_set.Remove(context); context_set.Remove(context);
EXPECT_EQ(0u, context_set.size()); EXPECT_EQ(0, context_set.size());
EXPECT_EQ(nullptr, context_set.GetByV8Context(v8_context)); EXPECT_FALSE(context_set.GetByV8Context(context->v8_context()));
EXPECT_EQ(1u, set_copy.size());
// After removal, the context should be invalid. // After removal, the context should be marked for destruction.
EXPECT_FALSE(context->is_valid()); EXPECT_FALSE(context->web_frame());
EXPECT_EQ(nullptr, context->web_frame());
// Run loop to do the actual deletion. // Run loop to do the actual deletion.
loop.RunUntilIdle(); loop.RunUntilIdle();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment