blob: e6d98085e64d95043f001ddc51ebc2e2e72a6868 [file] [log] [blame]
[email protected]f55c90ee62014-04-12 00:50:031// 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.
4
5#ifndef EXTENSIONS_RENDERER_SCRIPT_CONTEXT_H_
6#define EXTENSIONS_RENDERER_SCRIPT_CONTEXT_H_
7
asargent79b64c32016-08-04 17:17:148#include <memory>
[email protected]f55c90ee62014-04-12 00:50:039#include <string>
dchenge59eca1602015-12-18 17:48:0010#include <utility>
kalmanb0c1c502015-04-15 00:25:0611#include <vector>
[email protected]f55c90ee62014-04-12 00:50:0312
kalmanb0c1c502015-04-15 00:25:0613#include "base/callback.h"
[email protected]f55c90ee62014-04-12 00:50:0314#include "base/compiler_specific.h"
avi2d124c02015-12-23 06:36:4215#include "base/macros.h"
kalman04755302015-09-14 18:52:1116#include "base/threading/thread_checker.h"
Devlin Croninfe480ed2017-09-15 20:51:1117#include "base/unguessable_token.h"
[email protected]f55c90ee62014-04-12 00:50:0318#include "extensions/common/features/feature.h"
rockote261b162014-12-12 01:59:4719#include "extensions/common/permissions/api_permission_set.h"
[email protected]f55c90ee62014-04-12 00:50:0320#include "extensions/renderer/module_system.h"
kalman33076cb2015-08-11 19:12:0721#include "extensions/renderer/safe_builtins.h"
rdevlin.cronin0d94256f2016-12-09 15:34:2322#include "extensions/renderer/script_injection_callback.h"
Sadrul Habib Chowdhury0d7ef9f2014-12-03 20:07:3023#include "url/gurl.h"
[email protected]f55c90ee62014-04-12 00:50:0324#include "v8/include/v8.h"
25
26namespace blink {
Dmitry Gozman3eac1792019-05-08 23:53:3127class WebDocumentLoader;
kalmanf91cb892015-04-15 19:20:4828class WebLocalFrame;
[email protected]f55c90ee62014-04-12 00:50:0329}
30
31namespace content {
[email protected]2101c4c2014-08-22 00:16:1632class RenderFrame;
[email protected]f55c90ee62014-04-12 00:50:0333}
34
35namespace extensions {
tbarzicfeb4b052016-11-29 18:23:0936enum class CheckAliasStatus;
[email protected]f55c90ee62014-04-12 00:50:0337class Extension;
38
kalman04755302015-09-14 18:52:1139// Extensions wrapper for a v8::Context.
40//
41// v8::Contexts can be constructed on any thread, and must only be accessed or
42// destroyed that thread.
43//
44// Note that ScriptContexts bound to worker threads will not have the full
45// functionality as those bound to the main RenderThread.
Devlin Cronin86dcc702019-03-19 15:42:5446class ScriptContext {
[email protected]f55c90ee62014-04-12 00:50:0347 public:
annekao533482222015-08-21 23:23:5348 using RunScriptExceptionHandler = base::Callback<void(const v8::TryCatch&)>;
49
tfarinaf85316f2015-04-29 17:03:4050 ScriptContext(const v8::Local<v8::Context>& context,
kalmanf91cb892015-04-15 19:20:4851 blink::WebLocalFrame* frame,
[email protected]f55c90ee62014-04-12 00:50:0352 const Extension* extension,
mek7e1d7452014-09-08 23:55:5753 Feature::Context context_type,
54 const Extension* effective_extension,
55 Feature::Context effective_context_type);
Devlin Cronin86dcc702019-03-19 15:42:5456 ~ScriptContext();
[email protected]f55c90ee62014-04-12 00:50:0357
kalmanc81508d2015-04-23 17:14:0258 // Returns whether |url| from any Extension in |extension_set| is sandboxed,
59 // as declared in each Extension's manifest.
60 // TODO(kalman): Delete this when crbug.com/466373 is fixed.
61 // See comment in HasAccessOrThrowError.
annekao6572d5c2015-08-19 16:13:3662 static bool IsSandboxedPage(const GURL& url);
kalmanf91cb892015-04-15 19:20:4863
Devlin Cronind9ea8342018-01-27 06:00:0464 // Initializes |module_system| and associates it with this context.
65 void SetModuleSystem(std::unique_ptr<ModuleSystem> module_system);
66
Daniel Cheng971cd4522017-05-31 21:58:2267 // Clears the WebLocalFrame for this contexts and invalidates the associated
[email protected]f55c90ee62014-04-12 00:50:0368 // ModuleSystem.
69 void Invalidate();
70
kalmanb0c1c502015-04-15 00:25:0671 // Registers |observer| to be run when this context is invalidated. Closures
72 // are run immediately when Invalidate() is called, not in a message loop.
Istiaque Ahmedcf9175a2018-09-25 21:52:3373 void AddInvalidationObserver(base::OnceClosure observer);
kalmanb0c1c502015-04-15 00:25:0674
[email protected]f55c90ee62014-04-12 00:50:0375 // Returns true if this context is still valid, false if it isn't.
76 // A context becomes invalid via Invalidate().
kalmanb0c1c502015-04-15 00:25:0677 bool is_valid() const { return is_valid_; }
[email protected]f55c90ee62014-04-12 00:50:0378
tfarinaf85316f2015-04-29 17:03:4079 v8::Local<v8::Context> v8_context() const {
kalman078a2192015-03-09 18:19:3980 return v8::Local<v8::Context>::New(isolate_, v8_context_);
[email protected]f55c90ee62014-04-12 00:50:0381 }
82
83 const Extension* extension() const { return extension_.get(); }
84
mek7e1d7452014-09-08 23:55:5785 const Extension* effective_extension() const {
86 return effective_extension_.get();
87 }
88
kalmanf91cb892015-04-15 19:20:4889 blink::WebLocalFrame* web_frame() const { return web_frame_; }
[email protected]f55c90ee62014-04-12 00:50:0390
91 Feature::Context context_type() const { return context_type_; }
92
mek7e1d7452014-09-08 23:55:5793 Feature::Context effective_context_type() const {
94 return effective_context_type_;
95 }
96
Devlin Croninfe480ed2017-09-15 20:51:1197 const base::UnguessableToken& context_id() const { return context_id_; }
98
[email protected]f55c90ee62014-04-12 00:50:0399 ModuleSystem* module_system() { return module_system_.get(); }
100
kalman33076cb2015-08-11 19:12:07101 SafeBuiltins* safe_builtins() { return &safe_builtins_; }
[email protected]f55c90ee62014-04-12 00:50:03102
kalman33076cb2015-08-11 19:12:07103 const SafeBuiltins* safe_builtins() const { return &safe_builtins_; }
[email protected]f55c90ee62014-04-12 00:50:03104
105 // Returns the ID of the extension associated with this context, or empty
106 // string if there is no such extension.
[email protected]800f9872014-06-12 04:12:51107 const std::string& GetExtensionID() const;
[email protected]f55c90ee62014-04-12 00:50:03108
[email protected]2101c4c2014-08-22 00:16:16109 // Returns the RenderFrame associated with this context. Can return NULL if
110 // the context is in the process of being destroyed.
111 content::RenderFrame* GetRenderFrame() const;
112
rdevlin.cronina9bc8cc2016-10-06 15:51:17113 // Safely calls the v8::Function, respecting the page load deferrer and
114 // possibly executing asynchronously.
rdevlin.cronin12a457eb2016-10-25 20:39:58115 // Doesn't catch exceptions; callers must do that if they want.
rdevlin.cronin0d94256f2016-12-09 15:34:23116 // USE THESE METHODS RATHER THAN v8::Function::Call WHEREVER POSSIBLE.
rdevlin.cronina9bc8cc2016-10-06 15:51:17117 void SafeCallFunction(const v8::Local<v8::Function>& function,
118 int argc,
119 v8::Local<v8::Value> argv[]);
rdevlin.cronin0d94256f2016-12-09 15:34:23120 void SafeCallFunction(
121 const v8::Local<v8::Function>& function,
122 int argc,
123 v8::Local<v8::Value> argv[],
124 const ScriptInjectionCallback::CompleteCallback& callback);
rdevlin.cronina9bc8cc2016-10-06 15:51:17125
[email protected]f55c90ee62014-04-12 00:50:03126 // Returns the availability of the API |api_name|.
127 Feature::Availability GetAvailability(const std::string& api_name);
tbarzicfeb4b052016-11-29 18:23:09128 // Returns the availability of the API |api_name|.
129 // |check_alias| Whether API that has an alias that is available should be
130 // considered available (even if the API itself is not available).
131 Feature::Availability GetAvailability(const std::string& api_name,
132 CheckAliasStatus check_alias);
[email protected]f55c90ee62014-04-12 00:50:03133
134 // Returns a string description of the type of context this is.
kalman8bcbc7592015-06-03 23:12:27135 std::string GetContextTypeDescription() const;
[email protected]f55c90ee62014-04-12 00:50:03136
mek7e1d7452014-09-08 23:55:57137 // Returns a string description of the effective type of context this is.
kalman8bcbc7592015-06-03 23:12:27138 std::string GetEffectiveContextTypeDescription() const;
mek7e1d7452014-09-08 23:55:57139
[email protected]f55c90ee62014-04-12 00:50:03140 v8::Isolate* isolate() const { return isolate_; }
141
142 // Get the URL of this context's web frame.
kalmanf91cb892015-04-15 19:20:48143 //
144 // TODO(kalman): Remove this and replace with a GetOrigin() call which reads
Dana Jansens71331252016-03-09 20:57:22145 // of WebDocument::getSecurityOrigin():
kalmanf91cb892015-04-15 19:20:48146 // - The URL can change (e.g. pushState) but the origin cannot. Luckily it
147 // appears as though callers don't make security decisions based on the
kalman04755302015-09-14 18:52:11148 // result of url() so it's not a problem... yet.
kalmanf91cb892015-04-15 19:20:48149 // - Origin is the correct check to be making.
150 // - It might let us remove the about:blank resolving?
kalman04755302015-09-14 18:52:11151 const GURL& url() const { return url_; }
152
lazyboy63b994a2017-06-30 21:20:23153 const GURL& service_worker_scope() const;
154
Istiaque Ahmeda14ec482018-08-25 01:02:18155 int64_t service_worker_version_id() const {
156 return service_worker_version_id_;
157 }
158
kalman04755302015-09-14 18:52:11159 // Sets the URL of this ScriptContext. Usually this will automatically be set
160 // on construction, unless this isn't constructed with enough information to
161 // determine the URL (e.g. frame was null).
162 // TODO(kalman): Make this a constructor parameter (as an origin).
163 void set_url(const GURL& url) { url_ = url; }
lazyboy63b994a2017-06-30 21:20:23164 void set_service_worker_scope(const GURL& scope) {
165 service_worker_scope_ = scope;
166 }
Istiaque Ahmeda14ec482018-08-25 01:02:18167 void set_service_worker_version_id(int64_t service_worker_version_id) {
168 service_worker_version_id_ = service_worker_version_id;
169 }
[email protected]f55c90ee62014-04-12 00:50:03170
tbarzicfeb4b052016-11-29 18:23:09171 // Returns whether the API |api| or any part of the API could be available in
172 // this context without taking into account the context's extension.
173 // |check_alias| Whether the API should be considered available if it has an
174 // alias that is available.
175 bool IsAnyFeatureAvailableToContext(const extensions::Feature& api,
176 CheckAliasStatus check_alias);
[email protected]f55c90ee62014-04-12 00:50:03177
Dmitry Gozman3eac1792019-05-08 23:53:31178 // Scope which maps a frame to a document loader. This is used by various
179 // static methods below, which need to account for "just about to load"
180 // document when retrieving URL.
181 class ScopedFrameDocumentLoader {
182 public:
183 ScopedFrameDocumentLoader(blink::WebLocalFrame* frame,
184 blink::WebDocumentLoader* document_loader);
185 ~ScopedFrameDocumentLoader();
186
187 private:
188 blink::WebLocalFrame* frame_;
189 blink::WebDocumentLoader* document_loader_;
190 DISALLOW_COPY_AND_ASSIGN(ScopedFrameDocumentLoader);
191 };
192
[email protected]f55c90ee62014-04-12 00:50:03193 // Utility to get the URL we will match against for a frame. If the frame has
194 // committed, this is the commited URL. Otherwise it is the provisional URL.
[email protected]c1abb3232014-07-30 18:28:39195 // The returned URL may be invalid.
Takeshi Yoshino41b671a2017-08-01 12:17:51196 static GURL GetDocumentLoaderURLForFrame(const blink::WebLocalFrame* frame);
[email protected]f55c90ee62014-04-12 00:50:03197
Takeshi Yoshino41b671a2017-08-01 12:17:51198 // Similar to GetDocumentLoaderURLForFrame, but only returns the data source
199 // URL if the frame's document url is empty and the frame has a security
200 // origin that allows access to the data source url.
asargent79b64c32016-08-04 17:17:14201 // TODO(asargent/devlin) - there may be places that should switch to using
Takeshi Yoshino41b671a2017-08-01 12:17:51202 // this instead of GetDocumentLoaderURLForFrame.
Daniel Cheng971cd4522017-05-31 21:58:22203 static GURL GetAccessCheckedFrameURL(const blink::WebLocalFrame* frame);
asargent79b64c32016-08-04 17:17:14204
[email protected]ae26b282014-05-15 16:40:16205 // Returns the first non-about:-URL in the document hierarchy above and
206 // including |frame|. The document hierarchy is only traversed if
207 // |document_url| is an about:-URL and if |match_about_blank| is true.
lukaszabedb4b22017-06-23 00:00:13208 static GURL GetEffectiveDocumentURL(blink::WebLocalFrame* frame,
[email protected]ae26b282014-05-15 16:40:16209 const GURL& document_url,
210 bool match_about_blank);
211
rockote261b162014-12-12 01:59:47212 // Grants a set of content capabilities to this context.
Devlin Cronin32708b02018-12-05 17:58:04213 void set_content_capabilities(APIPermissionSet capabilities) {
214 content_capabilities_ = std::move(capabilities);
kalman04755302015-09-14 18:52:11215 }
rockote261b162014-12-12 01:59:47216
217 // Indicates if this context has an effective API permission either by being
218 // a context for an extension which has that permission, or by being a web
219 // context which has been granted the corresponding capability by an
220 // extension.
221 bool HasAPIPermission(APIPermission::ID permission) const;
222
kalmanc81508d2015-04-23 17:14:02223 // Throws an Error in this context's JavaScript context, if this context does
224 // not have access to |name|. Returns true if this context has access (i.e.
225 // no exception thrown), false if it does not (i.e. an exception was thrown).
226 bool HasAccessOrThrowError(const std::string& name);
227
kalman8bcbc7592015-06-03 23:12:27228 // Returns a string representation of this ScriptContext, for debugging.
229 std::string GetDebugString() const;
230
dmazzonid6848287c2015-07-27 23:41:31231 // Gets the current stack trace as a multi-line string to be logged.
232 std::string GetStackTraceAsString() const;
233
annekao533482222015-08-21 23:23:53234 // Runs |code|, labelling the script that gets created as |name| (the name is
235 // used in the devtools and stack traces). |exception_handler| will be called
236 // re-entrantly if an exception is thrown during the script's execution.
237 v8::Local<v8::Value> RunScript(
238 v8::Local<v8::String> name,
239 v8::Local<v8::String> code,
Leszek Swirskid148e132017-11-15 16:50:35240 const RunScriptExceptionHandler& exception_handler,
241 v8::ScriptCompiler::NoCacheReason no_cache_reason =
242 v8::ScriptCompiler::NoCacheReason::kNoCacheNoReason);
annekao533482222015-08-21 23:23:53243
mlamouri60a2857d2015-04-14 15:22:36244 private:
rdevlin.cronincf5482bd2017-06-14 13:18:18245 // DEPRECATED.
246 v8::Local<v8::Value> CallFunction(const v8::Local<v8::Function>& function,
247 int argc,
248 v8::Local<v8::Value> argv[]) const;
249
kalmanb0c1c502015-04-15 00:25:06250 // Whether this context is valid.
251 bool is_valid_;
252
253 // The v8 context the bindings are accessible to.
254 v8::Global<v8::Context> v8_context_;
255
kalmanf91cb892015-04-15 19:20:48256 // The WebLocalFrame associated with this context. This can be NULL because
257 // this object can outlive is destroyed asynchronously.
258 blink::WebLocalFrame* web_frame_;
[email protected]f55c90ee62014-04-12 00:50:03259
260 // The extension associated with this context, or NULL if there is none. This
261 // might be a hosted app in the case that this context is hosting a web URL.
262 scoped_refptr<const Extension> extension_;
263
264 // The type of context.
265 Feature::Context context_type_;
266
mek7e1d7452014-09-08 23:55:57267 // The effective extension associated with this context, or NULL if there is
268 // none. This is different from the above extension if this context is in an
269 // about:blank iframe for example.
270 scoped_refptr<const Extension> effective_extension_;
271
272 // The type of context.
273 Feature::Context effective_context_type_;
274
Devlin Croninfe480ed2017-09-15 20:51:11275 // A globally-unique ID for the script context.
276 base::UnguessableToken context_id_;
277
[email protected]f55c90ee62014-04-12 00:50:03278 // Owns and structures the JS that is injected to set up extension bindings.
dchengf6f80662016-04-20 20:26:04279 std::unique_ptr<ModuleSystem> module_system_;
[email protected]f55c90ee62014-04-12 00:50:03280
281 // Contains safe copies of builtin objects like Function.prototype.
kalman33076cb2015-08-11 19:12:07282 SafeBuiltins safe_builtins_;
[email protected]f55c90ee62014-04-12 00:50:03283
rockote261b162014-12-12 01:59:47284 // The set of capabilities granted to this context by extensions.
285 APIPermissionSet content_capabilities_;
286
Istiaque Ahmedcf9175a2018-09-25 21:52:33287 // A list of base::OnceClosure instances as an observer interface for
kalmanb0c1c502015-04-15 00:25:06288 // invalidation.
Istiaque Ahmedcf9175a2018-09-25 21:52:33289 std::vector<base::OnceClosure> invalidate_observers_;
kalmanb0c1c502015-04-15 00:25:06290
[email protected]f55c90ee62014-04-12 00:50:03291 v8::Isolate* isolate_;
292
Sadrul Habib Chowdhury0d7ef9f2014-12-03 20:07:30293 GURL url_;
294
lazyboy63b994a2017-06-30 21:20:23295 GURL service_worker_scope_;
296
Istiaque Ahmeda14ec482018-08-25 01:02:18297 int64_t service_worker_version_id_;
298
kalman04755302015-09-14 18:52:11299 base::ThreadChecker thread_checker_;
300
[email protected]f55c90ee62014-04-12 00:50:03301 DISALLOW_COPY_AND_ASSIGN(ScriptContext);
302};
303
304} // namespace extensions
305
306#endif // EXTENSIONS_RENDERER_SCRIPT_CONTEXT_H_