1 // Copyright (c) 2012 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 "chrome/renderer/extensions/chrome_v8_context_set.h"
7 #include "base/logging.h"
8 #include "base/message_loop/message_loop.h"
9 #include "base/tracked_objects.h"
10 #include "base/values.h"
11 #include "chrome/common/url_constants.h"
12 #include "chrome/renderer/extensions/chrome_v8_context.h"
13 #include "content/public/renderer/render_thread.h"
14 #include "content/public/renderer/render_view.h"
15 #include "extensions/common/constants.h"
16 #include "extensions/common/extension.h"
17 #include "third_party/WebKit/public/platform/WebURL.h"
18 #include "third_party/WebKit/public/platform/WebURLRequest.h"
19 #include "third_party/WebKit/public/web/WebDocument.h"
20 #include "third_party/WebKit/public/web/WebFrame.h"
21 #include "third_party/WebKit/public/web/WebView.h"
22 #include "v8/include/v8.h"
24 using content::RenderThread
;
26 namespace extensions
{
28 ChromeV8ContextSet::ChromeV8ContextSet() {
30 ChromeV8ContextSet::~ChromeV8ContextSet() {
33 int ChromeV8ContextSet::size() const {
34 return static_cast<int>(contexts_
.size());
37 void ChromeV8ContextSet::Add(ChromeV8Context
* context
) {
39 // It's OK to insert the same context twice, but we should only ever have
40 // one ChromeV8Context per v8::Context.
41 for (ContextSet::iterator iter
= contexts_
.begin(); iter
!= contexts_
.end();
43 ChromeV8Context
* candidate
= *iter
;
44 if (candidate
!= context
)
45 DCHECK(candidate
->v8_context() != context
->v8_context());
48 contexts_
.insert(context
);
51 void ChromeV8ContextSet::Remove(ChromeV8Context
* context
) {
52 if (contexts_
.erase(context
)) {
53 context
->Invalidate();
54 base::MessageLoop::current()->DeleteSoon(FROM_HERE
, context
);
58 ChromeV8ContextSet::ContextSet
ChromeV8ContextSet::GetAll() const {
62 ChromeV8Context
* ChromeV8ContextSet::GetCurrent() const {
63 v8::Isolate
* isolate
= v8::Isolate::GetCurrent();
64 return isolate
->InContext() ? GetByV8Context(isolate
->GetCurrentContext())
68 ChromeV8Context
* ChromeV8ContextSet::GetCalling() const {
69 v8::Isolate
* isolate
= v8::Isolate::GetCurrent();
70 v8::Local
<v8::Context
> calling
= isolate
->GetCallingContext();
71 return calling
.IsEmpty() ? NULL
: GetByV8Context(calling
);
74 ChromeV8Context
* ChromeV8ContextSet::GetByV8Context(
75 v8::Handle
<v8::Context
> v8_context
) const {
76 for (ContextSet::const_iterator iter
= contexts_
.begin();
77 iter
!= contexts_
.end(); ++iter
) {
78 if ((*iter
)->v8_context() == v8_context
)
85 void ChromeV8ContextSet::ForEach(
86 const std::string
& extension_id
,
87 content::RenderView
* render_view
,
88 const base::Callback
<void(ChromeV8Context
*)>& callback
) const {
89 // We copy the context list, because calling into javascript may modify it
91 ContextSet contexts
= GetAll();
93 for (ContextSet::iterator it
= contexts
.begin(); it
!= contexts
.end();
95 ChromeV8Context
* context
= *it
;
97 // For the same reason as above, contexts may become invalid while we run.
98 if (!context
->is_valid())
101 if (!extension_id
.empty()) {
102 const Extension
* extension
= context
->extension();
103 if (!extension
|| (extension_id
!= extension
->id()))
107 content::RenderView
* context_render_view
= context
->GetRenderView();
108 if (!context_render_view
)
111 if (render_view
&& render_view
!= context_render_view
)
114 callback
.Run(context
);
118 ChromeV8ContextSet::ContextSet
ChromeV8ContextSet::OnExtensionUnloaded(
119 const std::string
& extension_id
) {
120 ContextSet contexts
= GetAll();
123 // Clean up contexts belonging to the unloaded extension. This is done so
124 // that content scripts (which remain injected into the page) don't continue
125 // receiving events and sending messages.
126 for (ContextSet::iterator it
= contexts
.begin(); it
!= contexts
.end();
128 if ((*it
)->extension() && (*it
)->extension()->id() == extension_id
) {
129 (*it
)->DispatchOnUnloadEvent();
138 } // namespace extensions