Suppression for crbug/241044.
[chromium-blink-merge.git] / chrome / renderer / extensions / chrome_v8_context.cc
blob47171c8cecb9e4bb88f996f4023928a5d876c67f
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.h"
7 #include "base/debug/trace_event.h"
8 #include "base/logging.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "base/strings/string_split.h"
11 #include "base/values.h"
12 #include "chrome/common/extensions/api/extension_api.h"
13 #include "chrome/common/extensions/extension.h"
14 #include "chrome/common/extensions/extension_set.h"
15 #include "chrome/common/extensions/features/base_feature_provider.h"
16 #include "chrome/renderer/extensions/chrome_v8_extension.h"
17 #include "chrome/renderer/extensions/module_system.h"
18 #include "chrome/renderer/extensions/user_script_slave.h"
19 #include "content/public/renderer/render_view.h"
20 #include "content/public/renderer/v8_value_converter.h"
21 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
22 #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
23 #include "v8/include/v8.h"
25 using content::V8ValueConverter;
27 namespace extensions {
29 namespace {
31 const char kChromeHidden[] = "chromeHidden";
32 const char kValidateCallbacks[] = "validateCallbacks";
33 const char kValidateAPI[] = "validateAPI";
35 } // namespace
37 ChromeV8Context::ChromeV8Context(v8::Handle<v8::Context> v8_context,
38 WebKit::WebFrame* web_frame,
39 const Extension* extension,
40 Feature::Context context_type)
41 : v8_context_(v8_context),
42 web_frame_(web_frame),
43 extension_(extension),
44 context_type_(context_type) {
45 VLOG(1) << "Created context:\n"
46 << " extension id: " << GetExtensionID() << "\n"
47 << " frame: " << web_frame_ << "\n"
48 << " context type: " << GetContextTypeDescription();
51 ChromeV8Context::~ChromeV8Context() {
52 VLOG(1) << "Destroyed context for extension\n"
53 << " extension id: " << GetExtensionID();
54 Invalidate();
57 void ChromeV8Context::Invalidate() {
58 if (v8_context_.get().IsEmpty())
59 return;
60 if (module_system_)
61 module_system_->Invalidate();
62 web_frame_ = NULL;
63 v8_context_.reset();
66 std::string ChromeV8Context::GetExtensionID() {
67 return extension_ ? extension_->id() : std::string();
70 // static
71 v8::Handle<v8::Value> ChromeV8Context::GetOrCreateChromeHidden(
72 v8::Handle<v8::Context> context) {
73 v8::Local<v8::Object> global = context->Global();
74 v8::Local<v8::Value> hidden = global->GetHiddenValue(
75 v8::String::New(kChromeHidden));
77 if (hidden.IsEmpty() || hidden->IsUndefined()) {
78 hidden = v8::Object::New();
79 global->SetHiddenValue(v8::String::New(kChromeHidden), hidden);
81 if (DCHECK_IS_ON()) {
82 // Tell bindings.js to validate callbacks and events against their schema
83 // definitions.
84 v8::Local<v8::Object>::Cast(hidden)->Set(
85 v8::String::New(kValidateCallbacks), v8::True());
86 // Tell bindings.js to validate API for ambiguity.
87 v8::Local<v8::Object>::Cast(hidden)->Set(
88 v8::String::New(kValidateAPI), v8::True());
92 DCHECK(hidden->IsObject());
93 return v8::Local<v8::Object>::Cast(hidden);
96 v8::Handle<v8::Value> ChromeV8Context::GetChromeHidden() const {
97 v8::Local<v8::Object> global = v8_context_->Global();
98 return global->GetHiddenValue(v8::String::New(kChromeHidden));
101 content::RenderView* ChromeV8Context::GetRenderView() const {
102 if (web_frame_ && web_frame_->view())
103 return content::RenderView::FromWebView(web_frame_->view());
104 else
105 return NULL;
108 bool ChromeV8Context::CallChromeHiddenMethod(
109 const std::string& function_name,
110 int argc,
111 v8::Handle<v8::Value>* argv,
112 v8::Handle<v8::Value>* result) const {
113 // ChromeV8ContextSet calls Invalidate() and then schedules a task to delete
114 // this object. This check prevents a race from attempting to execute script
115 // on a NULL web_frame_.
116 if (!web_frame_)
117 return false;
119 v8::Context::Scope context_scope(v8_context_.get());
121 // Look up the function name, which may be a sub-property like
122 // "Port.dispatchOnMessage" in the hidden global variable.
123 v8::Local<v8::Value> value = v8::Local<v8::Value>::New(GetChromeHidden());
124 if (value.IsEmpty())
125 return false;
127 std::vector<std::string> components;
128 base::SplitStringDontTrim(function_name, '.', &components);
129 for (size_t i = 0; i < components.size(); ++i) {
130 if (!value.IsEmpty() && value->IsObject()) {
131 value = v8::Local<v8::Object>::Cast(value)->Get(
132 v8::String::New(components[i].c_str()));
136 if (value.IsEmpty() || !value->IsFunction()) {
137 VLOG(1) << "Could not execute chrome hidden method: " << function_name;
138 return false;
141 TRACE_EVENT1("v8", "v8.callChromeHiddenMethod",
142 "function_name", function_name);
144 v8::Local<v8::Function> function = v8::Local<v8::Function>::Cast(value);
145 v8::Handle<v8::Value> result_temp =
146 web_frame_->callFunctionEvenIfScriptDisabled(function,
147 v8::Object::New(),
148 argc,
149 argv);
150 if (result)
151 *result = result_temp;
153 return true;
156 bool ChromeV8Context::IsAnyFeatureAvailableToContext(
157 const std::string& api_name) {
158 return ExtensionAPI::GetSharedInstance()->IsAnyFeatureAvailableToContext(
159 api_name,
160 context_type_,
161 UserScriptSlave::GetDataSourceURLForFrame(web_frame_));
164 Feature::Availability ChromeV8Context::GetAvailability(
165 const std::string& api_name) {
166 return ExtensionAPI::GetSharedInstance()->IsAvailable(
167 api_name,
168 extension_,
169 context_type_,
170 UserScriptSlave::GetDataSourceURLForFrame(web_frame_));
173 void ChromeV8Context::DispatchOnUnloadEvent() {
174 v8::HandleScope handle_scope;
175 CallChromeHiddenMethod("dispatchOnUnload", 0, NULL, NULL);
178 std::string ChromeV8Context::GetContextTypeDescription() {
179 switch (context_type_) {
180 case Feature::UNSPECIFIED_CONTEXT: return "UNSPECIFIED";
181 case Feature::BLESSED_EXTENSION_CONTEXT: return "BLESSED_EXTENSION";
182 case Feature::UNBLESSED_EXTENSION_CONTEXT: return "UNBLESSED_EXTENSION";
183 case Feature::CONTENT_SCRIPT_CONTEXT: return "CONTENT_SCRIPT";
184 case Feature::WEB_PAGE_CONTEXT: return "WEB_PAGE";
186 NOTREACHED();
187 return std::string();
190 ChromeV8Context* ChromeV8Context::GetContext() {
191 return this;
194 void ChromeV8Context::OnResponseReceived(const std::string& name,
195 int request_id,
196 bool success,
197 const base::ListValue& response,
198 const std::string& error) {
199 v8::HandleScope handle_scope;
201 scoped_ptr<V8ValueConverter> converter(V8ValueConverter::create());
202 v8::Handle<v8::Value> argv[] = {
203 v8::Integer::New(request_id),
204 v8::String::New(name.c_str()),
205 v8::Boolean::New(success),
206 converter->ToV8Value(&response, v8_context_.get()),
207 v8::String::New(error.c_str())
210 v8::Handle<v8::Value> retval;
211 CHECK(CallChromeHiddenMethod("handleResponse", arraysize(argv), argv,
212 &retval));
213 // In debug, the js will validate the callback parameters and return a
214 // string if a validation error has occured.
215 if (DCHECK_IS_ON()) {
216 if (!retval.IsEmpty() && !retval->IsUndefined()) {
217 std::string error = *v8::String::AsciiValue(retval);
218 DCHECK(false) << error;
223 } // namespace extensions