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

Side by Side Diff: extensions/renderer/script_context_set.cc

Issue 995283004: Move Extension ScriptContext creation into ScriptContextSet. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fix memory for real Created 5 years, 9 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 unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "extensions/renderer/script_context_set.h" 5 #include "extensions/renderer/script_context_set.h"
6 6
7 #include "base/message_loop/message_loop.h" 7 #include "base/message_loop/message_loop.h"
8 #include "content/public/common/url_constants.h"
8 #include "content/public/renderer/render_view.h" 9 #include "content/public/renderer/render_view.h"
9 #include "extensions/common/extension.h" 10 #include "extensions/common/extension.h"
11 #include "extensions/renderer/extension_groups.h"
10 #include "extensions/renderer/script_context.h" 12 #include "extensions/renderer/script_context.h"
13 #include "extensions/renderer/script_injection.h"
14 #include "third_party/WebKit/public/web/WebDocument.h"
15 #include "third_party/WebKit/public/web/WebLocalFrame.h"
11 #include "v8/include/v8.h" 16 #include "v8/include/v8.h"
12 17
13 namespace extensions { 18 namespace extensions {
14 19
15 ScriptContextSet::ScriptContextSet() { 20 ScriptContextSet::ScriptContextSet(ExtensionSet* extensions,
21 ExtensionIdSet* active_extension_ids)
22 : extensions_(extensions), active_extension_ids_(active_extension_ids) {
16 } 23 }
24
17 ScriptContextSet::~ScriptContextSet() { 25 ScriptContextSet::~ScriptContextSet() {
18 } 26 }
19 27
20 int ScriptContextSet::size() const { 28 ScriptContext* ScriptContextSet::Register(
21 return static_cast<int>(contexts_.size()); 29 blink::WebLocalFrame* frame,
22 } 30 const v8::Handle<v8::Context>& v8_context,
31 int extension_group,
32 int world_id) {
33 const Extension* extension =
34 GetExtensionFromFrameAndWorld(frame, world_id, false);
35 const Extension* effective_extension =
36 GetExtensionFromFrameAndWorld(frame, world_id, true);
23 37
24 void ScriptContextSet::Add(ScriptContext* context) { 38 GURL frame_url = ScriptContext::GetDataSourceURLForFrame(frame);
25 #if DCHECK_IS_ON() 39 Feature::Context context_type =
26 // It's OK to insert the same context twice, but we should only ever have 40 ClassifyJavaScriptContext(extension, extension_group, frame_url,
27 // one ScriptContext per v8::Context. 41 frame->document().securityOrigin());
28 for (ContextSet::iterator iter = contexts_.begin(); iter != contexts_.end(); 42 Feature::Context effective_context_type = ClassifyJavaScriptContext(
29 ++iter) { 43 effective_extension, extension_group,
30 ScriptContext* candidate = *iter; 44 ScriptContext::GetEffectiveDocumentURL(frame, frame_url, true),
31 if (candidate != context) 45 frame->document().securityOrigin());
32 DCHECK(candidate->v8_context() != context->v8_context()); 46
33 } 47 ScriptContext* context =
34 #endif 48 new ScriptContext(v8_context, frame, extension, context_type,
35 contexts_.insert(context); 49 effective_extension, effective_context_type);
50 contexts_.insert(context); // takes ownership
51 return context;
36 } 52 }
37 53
38 void ScriptContextSet::Remove(ScriptContext* context) { 54 void ScriptContextSet::Remove(ScriptContext* context) {
39 if (contexts_.erase(context)) { 55 if (contexts_.erase(context)) {
40 context->Invalidate(); 56 context->Invalidate();
41 base::MessageLoop::current()->DeleteSoon(FROM_HERE, context); 57 base::MessageLoop::current()->DeleteSoon(FROM_HERE, context);
42 } 58 }
43 } 59 }
44 60
45 ScriptContextSet::ContextSet ScriptContextSet::GetAll() const {
46 return contexts_;
47 }
48
49 ScriptContext* ScriptContextSet::GetCurrent() const { 61 ScriptContext* ScriptContextSet::GetCurrent() const {
50 v8::Isolate* isolate = v8::Isolate::GetCurrent(); 62 v8::Isolate* isolate = v8::Isolate::GetCurrent();
51 return isolate->InContext() ? GetByV8Context(isolate->GetCurrentContext()) 63 return isolate->InContext() ? GetByV8Context(isolate->GetCurrentContext())
52 : NULL; 64 : nullptr;
53 } 65 }
54 66
55 ScriptContext* ScriptContextSet::GetCalling() const { 67 ScriptContext* ScriptContextSet::GetCalling() const {
56 v8::Isolate* isolate = v8::Isolate::GetCurrent(); 68 v8::Isolate* isolate = v8::Isolate::GetCurrent();
57 v8::Local<v8::Context> calling = isolate->GetCallingContext(); 69 v8::Local<v8::Context> calling = isolate->GetCallingContext();
58 return calling.IsEmpty() ? NULL : GetByV8Context(calling); 70 return calling.IsEmpty() ? nullptr : GetByV8Context(calling);
59 } 71 }
60 72
61 ScriptContext* ScriptContextSet::GetByV8Context( 73 ScriptContext* ScriptContextSet::GetByV8Context(
62 v8::Handle<v8::Context> v8_context) const { 74 const v8::Handle<v8::Context>& v8_context) const {
63 for (ContextSet::const_iterator iter = contexts_.begin(); 75 for (ScriptContext* script_context : contexts_) {
64 iter != contexts_.end(); 76 if (script_context->v8_context() == v8_context)
65 ++iter) { 77 return script_context;
66 if ((*iter)->v8_context() == v8_context)
67 return *iter;
68 } 78 }
69 79 return nullptr;
70 return NULL;
71 } 80 }
72 81
73 void ScriptContextSet::ForEach( 82 void ScriptContextSet::ForEach(
74 const std::string& extension_id, 83 const std::string& extension_id,
75 content::RenderView* render_view, 84 content::RenderView* render_view,
76 const base::Callback<void(ScriptContext*)>& callback) const { 85 const base::Callback<void(ScriptContext*)>& callback) const {
77 // We copy the context list, because calling into javascript may modify it 86 // We copy the context list, because calling into javascript may modify it
78 // out from under us. 87 // out from under us.
79 ContextSet contexts = GetAll(); 88 std::set<ScriptContext*> contexts_copy = contexts_;
80 89
81 for (ContextSet::iterator it = contexts.begin(); it != contexts.end(); ++it) { 90 for (ScriptContext* context : contexts_copy) {
82 ScriptContext* context = *it;
83
84 // For the same reason as above, contexts may become invalid while we run. 91 // For the same reason as above, contexts may become invalid while we run.
85 if (!context->is_valid()) 92 if (!context->is_valid())
86 continue; 93 continue;
87 94
88 if (!extension_id.empty()) { 95 if (!extension_id.empty()) {
89 const Extension* extension = context->extension(); 96 const Extension* extension = context->extension();
90 if (!extension || (extension_id != extension->id())) 97 if (!extension || (extension_id != extension->id()))
91 continue; 98 continue;
92 } 99 }
93 100
94 content::RenderView* context_render_view = context->GetRenderView(); 101 content::RenderView* context_render_view = context->GetRenderView();
95 if (!context_render_view) 102 if (!context_render_view)
96 continue; 103 continue;
97 104
98 if (render_view && render_view != context_render_view) 105 if (render_view && render_view != context_render_view)
99 continue; 106 continue;
100 107
101 callback.Run(context); 108 callback.Run(context);
102 } 109 }
103 } 110 }
104 111
105 ScriptContextSet::ContextSet ScriptContextSet::OnExtensionUnloaded( 112 std::set<ScriptContext*> ScriptContextSet::OnExtensionUnloaded(
106 const std::string& extension_id) { 113 const std::string& extension_id) {
107 ContextSet contexts = GetAll(); 114 std::set<ScriptContext*> removed;
108 ContextSet removed; 115 ForEach(extension_id,
109 116 base::Bind(&ScriptContextSet::DispatchOnUnloadEventAndRemove,
110 // Clean up contexts belonging to the unloaded extension. This is done so 117 base::Unretained(this), &removed));
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);
118 }
119 }
120
121 return removed; 118 return removed;
122 } 119 }
123 120
121 const Extension* ScriptContextSet::GetExtensionFromFrameAndWorld(
122 const blink::WebLocalFrame* frame,
123 int world_id,
124 bool use_effective_url) {
125 std::string extension_id;
126 if (world_id != 0) {
127 // Isolated worlds (content script).
128 extension_id = ScriptInjection::GetHostIdForIsolatedWorld(world_id);
129 } else if (!frame->document().securityOrigin().isUnique()) {
130 // TODO(kalman): Delete the above check.
131 // Extension pages (chrome-extension:// URLs).
132 GURL frame_url = ScriptContext::GetDataSourceURLForFrame(frame);
133 frame_url = ScriptContext::GetEffectiveDocumentURL(frame, frame_url,
134 use_effective_url);
135 extension_id = extensions_->GetExtensionOrAppIDByURL(frame_url);
136 }
137
138 // There are conditions where despite a context being associated with an
139 // extension, no extension actually gets found. Ignore "invalid" because CSP
140 // blocks extension page loading by switching the extension ID to "invalid".
141 const Extension* extension = extensions_->GetByID(extension_id);
142 if (!extension && !extension_id.empty() && extension_id != "invalid") {
143 // TODO(kalman): Do something here?
144 }
145 return extension;
146 }
147
148 Feature::Context ScriptContextSet::ClassifyJavaScriptContext(
149 const Extension* extension,
150 int extension_group,
151 const GURL& url,
152 const blink::WebSecurityOrigin& origin) {
153 // WARNING: This logic must match ProcessMap::GetContextType, as much as
154 // possible.
155
156 DCHECK_GE(extension_group, 0);
157 if (extension_group == EXTENSION_GROUP_CONTENT_SCRIPTS) {
158 return extension ? // TODO(kalman): when does this happen?
159 Feature::CONTENT_SCRIPT_CONTEXT
160 : Feature::UNSPECIFIED_CONTEXT;
161 }
162
163 // We have an explicit check for sandboxed pages before checking whether the
164 // extension is active in this process because:
165 // 1. Sandboxed pages run in the same process as regular extension pages, so
166 // the extension is considered active.
167 // 2. ScriptContext creation (which triggers bindings injection) happens
168 // before the SecurityContext is updated with the sandbox flags (after
169 // reading the CSP header), so the caller can't check if the context's
170 // security origin is unique yet.
171 if (ScriptContext::IsSandboxedPage(*extensions_, url))
172 return Feature::WEB_PAGE_CONTEXT;
173
174 if (extension && active_extension_ids_->count(extension->id()) > 0) {
175 // |extension| is active in this process, but it could be either a true
176 // extension process or within the extent of a hosted app. In the latter
177 // case this would usually be considered a (blessed) web page context,
178 // unless the extension in question is a component extension, in which case
179 // we cheat and call it blessed.
180 return (extension->is_hosted_app() &&
181 extension->location() != Manifest::COMPONENT)
182 ? Feature::BLESSED_WEB_PAGE_CONTEXT
183 : Feature::BLESSED_EXTENSION_CONTEXT;
184 }
185
186 // TODO(kalman): This isUnique() check is wrong, it should be performed as
187 // part of ScriptContext::IsSandboxedPage().
188 if (!origin.isUnique() && extensions_->ExtensionBindingsAllowed(url)) {
189 if (!extension) // TODO(kalman): when does this happen?
190 return Feature::UNSPECIFIED_CONTEXT;
191 return extension->is_hosted_app() ? Feature::BLESSED_WEB_PAGE_CONTEXT
192 : Feature::UNBLESSED_EXTENSION_CONTEXT;
193 }
194
195 if (!url.is_valid())
196 return Feature::UNSPECIFIED_CONTEXT;
197
198 if (url.SchemeIs(content::kChromeUIScheme))
199 return Feature::WEBUI_CONTEXT;
200
201 return Feature::WEB_PAGE_CONTEXT;
202 }
203
204 void ScriptContextSet::DispatchOnUnloadEventAndRemove(
205 std::set<ScriptContext*>* out,
206 ScriptContext* context) {
207 Remove(context); // deleted asynchronously
208 out->insert(context);
209 }
210
124 } // namespace extensions 211 } // namespace extensions
OLDNEW
« no previous file with comments | « extensions/renderer/script_context_set.h ('k') | extensions/renderer/script_context_set_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698