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

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

Issue 1010473002: Revert of Move Extension ScriptContext creation into ScriptContextSet. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: 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"
9 #include "content/public/renderer/render_view.h" 8 #include "content/public/renderer/render_view.h"
10 #include "extensions/common/extension.h" 9 #include "extensions/common/extension.h"
11 #include "extensions/renderer/extension_groups.h"
12 #include "extensions/renderer/script_context.h" 10 #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"
16 #include "v8/include/v8.h" 11 #include "v8/include/v8.h"
17 12
18 namespace extensions { 13 namespace extensions {
19 14
20 ScriptContextSet::ScriptContextSet(ExtensionSet* extensions, 15 ScriptContextSet::ScriptContextSet() {
21 ExtensionIdSet* active_extension_ids)
22 : extensions_(extensions), active_extension_ids_(active_extension_ids) {
23 } 16 }
24
25 ScriptContextSet::~ScriptContextSet() { 17 ScriptContextSet::~ScriptContextSet() {
26 } 18 }
27 19
28 ScriptContext* ScriptContextSet::Register( 20 int ScriptContextSet::size() const {
29 blink::WebLocalFrame* frame, 21 return static_cast<int>(contexts_.size());
30 const v8::Handle<v8::Context>& v8_context, 22 }
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);
37 23
38 GURL frame_url = ScriptContext::GetDataSourceURLForFrame(frame); 24 void ScriptContextSet::Add(ScriptContext* context) {
39 Feature::Context context_type = 25 #if DCHECK_IS_ON()
40 ClassifyJavaScriptContext(extension, extension_group, frame_url, 26 // It's OK to insert the same context twice, but we should only ever have
41 frame->document().securityOrigin()); 27 // one ScriptContext per v8::Context.
42 Feature::Context effective_context_type = ClassifyJavaScriptContext( 28 for (ContextSet::iterator iter = contexts_.begin(); iter != contexts_.end();
43 effective_extension, extension_group, 29 ++iter) {
44 ScriptContext::GetEffectiveDocumentURL(frame, frame_url, true), 30 ScriptContext* candidate = *iter;
45 frame->document().securityOrigin()); 31 if (candidate != context)
46 32 DCHECK(candidate->v8_context() != context->v8_context());
47 ScriptContext* context = 33 }
48 new ScriptContext(v8_context, frame, extension, context_type, 34 #endif
49 effective_extension, effective_context_type); 35 contexts_.insert(context);
50 contexts_.insert(context); // takes ownership
51 return context;
52 } 36 }
53 37
54 void ScriptContextSet::Remove(ScriptContext* context) { 38 void ScriptContextSet::Remove(ScriptContext* context) {
55 if (contexts_.erase(context)) { 39 if (contexts_.erase(context)) {
56 context->Invalidate(); 40 context->Invalidate();
57 base::MessageLoop::current()->DeleteSoon(FROM_HERE, context); 41 base::MessageLoop::current()->DeleteSoon(FROM_HERE, context);
58 } 42 }
59 } 43 }
60 44
45 ScriptContextSet::ContextSet ScriptContextSet::GetAll() const {
46 return contexts_;
47 }
48
61 ScriptContext* ScriptContextSet::GetCurrent() const { 49 ScriptContext* ScriptContextSet::GetCurrent() const {
62 v8::Isolate* isolate = v8::Isolate::GetCurrent(); 50 v8::Isolate* isolate = v8::Isolate::GetCurrent();
63 return isolate->InContext() ? GetByV8Context(isolate->GetCurrentContext()) 51 return isolate->InContext() ? GetByV8Context(isolate->GetCurrentContext())
64 : nullptr; 52 : NULL;
65 } 53 }
66 54
67 ScriptContext* ScriptContextSet::GetCalling() const { 55 ScriptContext* ScriptContextSet::GetCalling() const {
68 v8::Isolate* isolate = v8::Isolate::GetCurrent(); 56 v8::Isolate* isolate = v8::Isolate::GetCurrent();
69 v8::Local<v8::Context> calling = isolate->GetCallingContext(); 57 v8::Local<v8::Context> calling = isolate->GetCallingContext();
70 return calling.IsEmpty() ? nullptr : GetByV8Context(calling); 58 return calling.IsEmpty() ? NULL : GetByV8Context(calling);
71 } 59 }
72 60
73 ScriptContext* ScriptContextSet::GetByV8Context( 61 ScriptContext* ScriptContextSet::GetByV8Context(
74 const v8::Handle<v8::Context>& v8_context) const { 62 v8::Handle<v8::Context> v8_context) const {
75 for (ScriptContext* script_context : contexts_) { 63 for (ContextSet::const_iterator iter = contexts_.begin();
76 if (script_context->v8_context() == v8_context) 64 iter != contexts_.end();
77 return script_context; 65 ++iter) {
66 if ((*iter)->v8_context() == v8_context)
67 return *iter;
78 } 68 }
79 return nullptr; 69
70 return NULL;
80 } 71 }
81 72
82 void ScriptContextSet::ForEach( 73 void ScriptContextSet::ForEach(
83 const std::string& extension_id, 74 const std::string& extension_id,
84 content::RenderView* render_view, 75 content::RenderView* render_view,
85 const base::Callback<void(ScriptContext*)>& callback) const { 76 const base::Callback<void(ScriptContext*)>& callback) const {
86 // We copy the context list, because calling into javascript may modify it 77 // We copy the context list, because calling into javascript may modify it
87 // out from under us. 78 // out from under us.
88 std::set<ScriptContext*> contexts_copy = contexts_; 79 ContextSet contexts = GetAll();
89 80
90 for (ScriptContext* context : contexts_copy) { 81 for (ContextSet::iterator it = contexts.begin(); it != contexts.end(); ++it) {
82 ScriptContext* context = *it;
83
91 // For the same reason as above, contexts may become invalid while we run. 84 // For the same reason as above, contexts may become invalid while we run.
92 if (!context->is_valid()) 85 if (!context->is_valid())
93 continue; 86 continue;
94 87
95 if (!extension_id.empty()) { 88 if (!extension_id.empty()) {
96 const Extension* extension = context->extension(); 89 const Extension* extension = context->extension();
97 if (!extension || (extension_id != extension->id())) 90 if (!extension || (extension_id != extension->id()))
98 continue; 91 continue;
99 } 92 }
100 93
101 content::RenderView* context_render_view = context->GetRenderView(); 94 content::RenderView* context_render_view = context->GetRenderView();
102 if (!context_render_view) 95 if (!context_render_view)
103 continue; 96 continue;
104 97
105 if (render_view && render_view != context_render_view) 98 if (render_view && render_view != context_render_view)
106 continue; 99 continue;
107 100
108 callback.Run(context); 101 callback.Run(context);
109 } 102 }
110 } 103 }
111 104
112 std::set<ScriptContext*> ScriptContextSet::OnExtensionUnloaded( 105 ScriptContextSet::ContextSet ScriptContextSet::OnExtensionUnloaded(
113 const std::string& extension_id) { 106 const std::string& extension_id) {
114 std::set<ScriptContext*> removed; 107 ContextSet contexts = GetAll();
115 ForEach(extension_id, 108 ContextSet removed;
116 base::Bind(&ScriptContextSet::DispatchOnUnloadEventAndRemove, 109
117 base::Unretained(this), &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);
118 }
119 }
120
118 return removed; 121 return removed;
119 } 122 }
120 123
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
211 } // namespace extensions 124 } // 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