Merge CrosDisksClientStubImpl into FakeCrosDisksClient
[chromium-blink-merge.git] / extensions / renderer / script_context_set.cc
blob5ee9db4d2f1a0c69dfcb5c3c17416655facd2df5
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "extensions/renderer/script_context_set.h"
7 #include "base/message_loop/message_loop.h"
8 #include "content/public/renderer/render_view.h"
9 #include "extensions/common/extension.h"
10 #include "extensions/renderer/script_context.h"
11 #include "v8/include/v8.h"
13 namespace extensions {
15 ScriptContextSet::ScriptContextSet() {
17 ScriptContextSet::~ScriptContextSet() {
20 int ScriptContextSet::size() const {
21 return static_cast<int>(contexts_.size());
24 void ScriptContextSet::Add(ScriptContext* context) {
25 #if DCHECK_IS_ON
26 // It's OK to insert the same context twice, but we should only ever have
27 // one ScriptContext per v8::Context.
28 for (ContextSet::iterator iter = contexts_.begin(); iter != contexts_.end();
29 ++iter) {
30 ScriptContext* candidate = *iter;
31 if (candidate != context)
32 DCHECK(candidate->v8_context() != context->v8_context());
34 #endif
35 contexts_.insert(context);
38 void ScriptContextSet::Remove(ScriptContext* context) {
39 if (contexts_.erase(context)) {
40 context->Invalidate();
41 base::MessageLoop::current()->DeleteSoon(FROM_HERE, context);
45 ScriptContextSet::ContextSet ScriptContextSet::GetAll() const {
46 return contexts_;
49 ScriptContext* ScriptContextSet::GetCurrent() const {
50 v8::Isolate* isolate = v8::Isolate::GetCurrent();
51 return isolate->InContext() ? GetByV8Context(isolate->GetCurrentContext())
52 : NULL;
55 ScriptContext* ScriptContextSet::GetCalling() const {
56 v8::Isolate* isolate = v8::Isolate::GetCurrent();
57 v8::Local<v8::Context> calling = isolate->GetCallingContext();
58 return calling.IsEmpty() ? NULL : GetByV8Context(calling);
61 ScriptContext* ScriptContextSet::GetByV8Context(
62 v8::Handle<v8::Context> v8_context) const {
63 for (ContextSet::const_iterator iter = contexts_.begin();
64 iter != contexts_.end();
65 ++iter) {
66 if ((*iter)->v8_context() == v8_context)
67 return *iter;
70 return NULL;
73 void ScriptContextSet::ForEach(
74 const std::string& extension_id,
75 content::RenderView* render_view,
76 const base::Callback<void(ScriptContext*)>& callback) const {
77 // We copy the context list, because calling into javascript may modify it
78 // out from under us.
79 ContextSet contexts = GetAll();
81 for (ContextSet::iterator it = contexts.begin(); it != contexts.end(); ++it) {
82 ScriptContext* context = *it;
84 // For the same reason as above, contexts may become invalid while we run.
85 if (!context->is_valid())
86 continue;
88 if (!extension_id.empty()) {
89 const Extension* extension = context->extension();
90 if (!extension || (extension_id != extension->id()))
91 continue;
94 content::RenderView* context_render_view = context->GetRenderView();
95 if (!context_render_view)
96 continue;
98 if (render_view && render_view != context_render_view)
99 continue;
101 callback.Run(context);
105 ScriptContextSet::ContextSet ScriptContextSet::OnExtensionUnloaded(
106 const std::string& extension_id) {
107 ContextSet contexts = GetAll();
108 ContextSet removed;
110 // Clean up contexts belonging to the unloaded extension. This is done so
111 // that content scripts (which remain injected into the page) don't continue
112 // receiving events and sending messages.
113 for (ContextSet::iterator it = contexts.begin(); it != contexts.end(); ++it) {
114 if ((*it)->extension() && (*it)->extension()->id() == extension_id) {
115 (*it)->DispatchOnUnloadEvent();
116 removed.insert(*it);
117 Remove(*it);
121 return removed;
124 } // namespace extensions