OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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 "chrome/renderer/extensions/chrome_v8_context.h" | 5 #include "chrome/renderer/extensions/chrome_v8_context.h" |
6 | 6 |
7 #include "base/logging.h" | |
8 #include "base/memory/scoped_ptr.h" | 7 #include "base/memory/scoped_ptr.h" |
9 #include "base/strings/string_split.h" | 8 #include "base/strings/string_split.h" |
10 #include "base/values.h" | 9 #include "base/values.h" |
11 #include "chrome/renderer/extensions/chrome_v8_extension.h" | |
12 #include "chrome/renderer/extensions/module_system.h" | |
13 #include "chrome/renderer/extensions/user_script_slave.h" | 10 #include "chrome/renderer/extensions/user_script_slave.h" |
14 #include "content/public/renderer/render_view.h" | |
15 #include "content/public/renderer/v8_value_converter.h" | 11 #include "content/public/renderer/v8_value_converter.h" |
16 #include "extensions/common/extension.h" | |
17 #include "extensions/common/extension_api.h" | 12 #include "extensions/common/extension_api.h" |
18 #include "extensions/common/extension_urls.h" | 13 #include "extensions/common/extension_urls.h" |
19 #include "extensions/common/features/base_feature_provider.h" | 14 #include "extensions/common/features/base_feature_provider.h" |
| 15 #include "extensions/renderer/module_system.h" |
20 #include "third_party/WebKit/public/web/WebFrame.h" | 16 #include "third_party/WebKit/public/web/WebFrame.h" |
21 #include "third_party/WebKit/public/web/WebScopedMicrotaskSuppression.h" | |
22 #include "third_party/WebKit/public/web/WebView.h" | |
23 #include "v8/include/v8.h" | 17 #include "v8/include/v8.h" |
24 | 18 |
25 using content::V8ValueConverter; | 19 using content::V8ValueConverter; |
26 | 20 |
27 namespace extensions { | 21 namespace extensions { |
28 | 22 |
29 ChromeV8Context::ChromeV8Context(v8::Handle<v8::Context> v8_context, | 23 ChromeV8Context::ChromeV8Context(v8::Handle<v8::Context> v8_context, |
30 blink::WebFrame* web_frame, | 24 blink::WebFrame* web_frame, |
31 const Extension* extension, | 25 const Extension* extension, |
32 Feature::Context context_type) | 26 Feature::Context context_type) |
33 : v8_context_(v8_context), | 27 : ScriptContext(v8_context, web_frame, extension, context_type), |
34 web_frame_(web_frame), | 28 pepper_request_proxy_(this) {} |
35 extension_(extension), | |
36 context_type_(context_type), | |
37 safe_builtins_(this), | |
38 pepper_request_proxy_(this), | |
39 isolate_(v8_context->GetIsolate()) { | |
40 VLOG(1) << "Created context:\n" | |
41 << " extension id: " << GetExtensionID() << "\n" | |
42 << " frame: " << web_frame_ << "\n" | |
43 << " context type: " << GetContextTypeDescription(); | |
44 } | |
45 | |
46 ChromeV8Context::~ChromeV8Context() { | |
47 VLOG(1) << "Destroyed context for extension\n" | |
48 << " extension id: " << GetExtensionID(); | |
49 Invalidate(); | |
50 } | |
51 | |
52 void ChromeV8Context::Invalidate() { | |
53 if (!is_valid()) | |
54 return; | |
55 if (module_system_) | |
56 module_system_->Invalidate(); | |
57 web_frame_ = NULL; | |
58 v8_context_.reset(); | |
59 } | |
60 | |
61 std::string ChromeV8Context::GetExtensionID() const { | |
62 return extension_.get() ? extension_->id() : std::string(); | |
63 } | |
64 | |
65 content::RenderView* ChromeV8Context::GetRenderView() const { | |
66 if (web_frame_ && web_frame_->view()) | |
67 return content::RenderView::FromWebView(web_frame_->view()); | |
68 else | |
69 return NULL; | |
70 } | |
71 | 29 |
72 GURL ChromeV8Context::GetURL() const { | 30 GURL ChromeV8Context::GetURL() const { |
73 return web_frame_ ? | 31 return web_frame() ? UserScriptSlave::GetDataSourceURLForFrame(web_frame()) |
74 UserScriptSlave::GetDataSourceURLForFrame(web_frame_) : GURL(); | 32 : GURL(); |
75 } | |
76 | |
77 v8::Local<v8::Value> ChromeV8Context::CallFunction( | |
78 v8::Handle<v8::Function> function, | |
79 int argc, | |
80 v8::Handle<v8::Value> argv[]) const { | |
81 v8::EscapableHandleScope handle_scope(isolate()); | |
82 v8::Context::Scope scope(v8_context()); | |
83 | |
84 blink::WebScopedMicrotaskSuppression suppression; | |
85 if (!is_valid()) { | |
86 return handle_scope.Escape( | |
87 v8::Local<v8::Primitive>(v8::Undefined(isolate()))); | |
88 } | |
89 | |
90 v8::Handle<v8::Object> global = v8_context()->Global(); | |
91 if (!web_frame_) | |
92 return handle_scope.Escape(function->Call(global, argc, argv)); | |
93 return handle_scope.Escape( | |
94 v8::Local<v8::Value>(web_frame_->callFunctionEvenIfScriptDisabled( | |
95 function, global, argc, argv))); | |
96 } | 33 } |
97 | 34 |
98 bool ChromeV8Context::IsAnyFeatureAvailableToContext(const Feature& api) { | 35 bool ChromeV8Context::IsAnyFeatureAvailableToContext(const Feature& api) { |
99 return ExtensionAPI::GetSharedInstance()->IsAnyFeatureAvailableToContext( | 36 return ExtensionAPI::GetSharedInstance()->IsAnyFeatureAvailableToContext( |
100 api, | 37 api, |
101 extension_.get(), | 38 extension(), |
102 context_type_, | 39 context_type(), |
103 UserScriptSlave::GetDataSourceURLForFrame(web_frame_)); | 40 UserScriptSlave::GetDataSourceURLForFrame(web_frame())); |
104 } | |
105 | |
106 Feature::Availability ChromeV8Context::GetAvailability( | |
107 const std::string& api_name) { | |
108 // Hack: Hosted apps should have the availability of messaging APIs based on | |
109 // the URL of the page (which might have access depending on some extension | |
110 // with externally_connectable), not whether the app has access to messaging | |
111 // (which it won't). | |
112 const Extension* extension = extension_.get(); | |
113 if (extension && extension->is_hosted_app() && | |
114 (api_name == "runtime.connect" || api_name == "runtime.sendMessage")) { | |
115 extension = NULL; | |
116 } | |
117 return ExtensionAPI::GetSharedInstance()->IsAvailable(api_name, | |
118 extension, | |
119 context_type_, | |
120 GetURL()); | |
121 } | |
122 | |
123 void ChromeV8Context::DispatchEvent(const char* event_name, | |
124 v8::Handle<v8::Array> args) const { | |
125 v8::HandleScope handle_scope(isolate()); | |
126 v8::Context::Scope context_scope(v8_context()); | |
127 | |
128 v8::Handle<v8::Value> argv[] = { | |
129 v8::String::NewFromUtf8(isolate(), event_name), args}; | |
130 module_system_->CallModuleMethod( | |
131 kEventBindings, "dispatchEvent", arraysize(argv), argv); | |
132 } | |
133 | |
134 void ChromeV8Context::DispatchOnUnloadEvent() { | |
135 module_system_->CallModuleMethod("unload_event", "dispatch"); | |
136 } | |
137 | |
138 std::string ChromeV8Context::GetContextTypeDescription() { | |
139 switch (context_type_) { | |
140 case Feature::UNSPECIFIED_CONTEXT: return "UNSPECIFIED"; | |
141 case Feature::BLESSED_EXTENSION_CONTEXT: return "BLESSED_EXTENSION"; | |
142 case Feature::UNBLESSED_EXTENSION_CONTEXT: return "UNBLESSED_EXTENSION"; | |
143 case Feature::CONTENT_SCRIPT_CONTEXT: return "CONTENT_SCRIPT"; | |
144 case Feature::WEB_PAGE_CONTEXT: return "WEB_PAGE"; | |
145 case Feature::BLESSED_WEB_PAGE_CONTEXT: return "BLESSED_WEB_PAGE"; | |
146 } | |
147 NOTREACHED(); | |
148 return std::string(); | |
149 } | |
150 | |
151 ChromeV8Context* ChromeV8Context::GetContext() { | |
152 return this; | |
153 } | 41 } |
154 | 42 |
155 void ChromeV8Context::OnResponseReceived(const std::string& name, | 43 void ChromeV8Context::OnResponseReceived(const std::string& name, |
156 int request_id, | 44 int request_id, |
157 bool success, | 45 bool success, |
158 const base::ListValue& response, | 46 const base::ListValue& response, |
159 const std::string& error) { | 47 const std::string& error) { |
160 v8::HandleScope handle_scope(isolate()); | 48 v8::HandleScope handle_scope(isolate()); |
161 | 49 |
162 scoped_ptr<V8ValueConverter> converter(V8ValueConverter::create()); | 50 scoped_ptr<V8ValueConverter> converter(V8ValueConverter::create()); |
163 v8::Handle<v8::Value> argv[] = { | 51 v8::Handle<v8::Value> argv[] = { |
164 v8::Integer::New(isolate(), request_id), | 52 v8::Integer::New(isolate(), request_id), |
165 v8::String::NewFromUtf8(isolate(), name.c_str()), | 53 v8::String::NewFromUtf8(isolate(), name.c_str()), |
166 v8::Boolean::New(isolate(), success), | 54 v8::Boolean::New(isolate(), success), |
167 converter->ToV8Value(&response, v8_context_.NewHandle(isolate())), | 55 converter->ToV8Value(&response, v8_context_.NewHandle(isolate())), |
168 v8::String::NewFromUtf8(isolate(), error.c_str()) | 56 v8::String::NewFromUtf8(isolate(), error.c_str()) |
169 }; | 57 }; |
170 | 58 |
171 v8::Handle<v8::Value> retval = module_system_->CallModuleMethod( | 59 v8::Handle<v8::Value> retval = module_system()->CallModuleMethod( |
172 "sendRequest", "handleResponse", arraysize(argv), argv); | 60 "sendRequest", "handleResponse", arraysize(argv), argv); |
173 | 61 |
174 // In debug, the js will validate the callback parameters and return a | 62 // In debug, the js will validate the callback parameters and return a |
175 // string if a validation error has occured. | 63 // string if a validation error has occured. |
176 DCHECK(retval.IsEmpty() || retval->IsUndefined()) | 64 DCHECK(retval.IsEmpty() || retval->IsUndefined()) |
177 << *v8::String::Utf8Value(retval); | 65 << *v8::String::Utf8Value(retval); |
178 } | 66 } |
179 | 67 |
180 } // namespace extensions | 68 } // namespace extensions |
OLD | NEW |