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

Unified Diff: extensions/renderer/dispatcher.cc

Issue 1318643002: Pass the v8::Context through the willDestroyServiceWorkerContextOnWorkerThread event. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: rebase against blink change Created 5 years, 4 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/dispatcher.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: extensions/renderer/dispatcher.cc
diff --git a/extensions/renderer/dispatcher.cc b/extensions/renderer/dispatcher.cc
index 34324e2be1bf10a27c375337e720fd03c5a85029..1203e6f30964ce7a3fa2503579186a2b53a04710 100644
--- a/extensions/renderer/dispatcher.cc
+++ b/extensions/renderer/dispatcher.cc
@@ -197,21 +197,41 @@ class ServiceWorkerScriptContextSet {
ServiceWorkerScriptContextSet() {}
~ServiceWorkerScriptContextSet() {}
- void Insert(const GURL& url, scoped_ptr<ScriptContext> context) {
+ void Insert(scoped_ptr<ScriptContext> context) {
base::AutoLock lock(lock_);
- CHECK(script_contexts_.find(url) == script_contexts_.end());
- script_contexts_.set(url, context.Pass());
+ CHECK(FindScriptContext(context->v8_context()) == contexts_.end());
+ contexts_.push_back(context.Pass());
}
- void Remove(const GURL& url) {
+ void Remove(v8::Local<v8::Context> v8_context) {
base::AutoLock lock(lock_);
- scoped_ptr<ScriptContext> context = script_contexts_.take_and_erase(url);
- CHECK(context);
- context->Invalidate();
+ ScriptContextList::iterator context_it = FindScriptContext(v8_context);
+ // TODO(kalman): It would be good to CHECK(context_it != contexts_.end())
+ // here, but service workers can be started before the extension has been
+ // installed. See the length comment explaining why this happens, and
+ // how to solve it, in DidInitializeServiceWorkerContextOnWorkerThread.
+ // This does need to be fixed eventually, but for now, at least don't crash.
+ if (context_it == contexts_.end())
+ return;
+ (*context_it)->Invalidate();
+ contexts_.erase(context_it);
}
private:
- base::ScopedPtrMap<GURL, scoped_ptr<ScriptContext>> script_contexts_;
+ using ScriptContextList = ScopedVector<ScriptContext>;
+
+ // Returns an iterator to the ScriptContext associated with |v8_context|, or
+ // contexts_.end() if not found.
+ ScriptContextList::iterator FindScriptContext(
+ v8::Local<v8::Context> v8_context) {
+ for (auto it = contexts_.begin(); it != contexts_.end(); ++it) {
+ if ((*it)->v8_context() == v8_context)
+ return it;
+ }
+ return contexts_.end();
+ }
+
+ ScriptContextList contexts_;
mutable base::Lock lock_;
@@ -383,15 +403,35 @@ void Dispatcher::DidInitializeServiceWorkerContextOnWorkerThread(
const Extension* extension =
RendererExtensionRegistry::Get()->GetExtensionOrAppByURL(url);
- if (!extension)
+ if (!extension) {
+ // TODO(kalman): This is no good. Instead we need to either:
+ //
+ // - Hold onto the v8::Context and create the ScriptContext and install
+ // our bindings when this extension is loaded.
+ // - Deal with there being an extension ID (url.host()) but no
+ // extension associated with it, then document that getBackgroundClient
+ // may fail if the extension hasn't loaded yet.
+ //
+ // The former is safer, but is unfriendly to caching (e.g. session restore).
+ // It seems to contradict the service worker idiom.
+ //
+ // The latter is friendly to caching, but running extension code without an
+ // installed extension makes me nervous, and means that we won't be able to
+ // expose arbitrary (i.e. capability-checked) extension APIs to service
+ // workers. We will probably need to relax some assertions - we just need
+ // to find them.
+ //
+ // Perhaps this could be solved with our own event on the service worker
+ // saying that an extension is ready, and documenting that extension APIs
+ // won't work before that event has fired?
return;
+ }
ScriptContext* context = new ScriptContext(
v8_context, nullptr, extension, Feature::SERVICE_WORKER_CONTEXT,
extension, Feature::SERVICE_WORKER_CONTEXT);
- g_service_worker_script_context_set.Get().Insert(url,
- make_scoped_ptr(context));
+ g_service_worker_script_context_set.Get().Insert(make_scoped_ptr(context));
v8::Isolate* isolate = context->isolate();
@@ -438,9 +478,10 @@ void Dispatcher::WillReleaseScriptContext(
// static
void Dispatcher::WillDestroyServiceWorkerContextOnWorkerThread(
+ v8::Local<v8::Context> v8_context,
const GURL& url) {
- if (RendererExtensionRegistry::Get()->GetExtensionOrAppByURL(url))
- g_service_worker_script_context_set.Get().Remove(url);
+ if (url.SchemeIs(kExtensionScheme))
+ g_service_worker_script_context_set.Get().Remove(v8_context);
}
void Dispatcher::DidCreateDocumentElement(blink::WebLocalFrame* frame) {
« no previous file with comments | « extensions/renderer/dispatcher.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698