OLD | NEW |
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/dispatcher.h" | 5 #include "extensions/renderer/dispatcher.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/callback.h" | 8 #include "base/callback.h" |
9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
10 #include "base/debug/alias.h" | 10 #include "base/debug/alias.h" |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
117 static const int64 kMaxExtensionIdleHandlerDelayMs = 5 * 60 * 1000; | 117 static const int64 kMaxExtensionIdleHandlerDelayMs = 5 * 60 * 1000; |
118 static const char kEventDispatchFunction[] = "dispatchEvent"; | 118 static const char kEventDispatchFunction[] = "dispatchEvent"; |
119 static const char kOnSuspendEvent[] = "runtime.onSuspend"; | 119 static const char kOnSuspendEvent[] = "runtime.onSuspend"; |
120 static const char kOnSuspendCanceledEvent[] = "runtime.onSuspendCanceled"; | 120 static const char kOnSuspendCanceledEvent[] = "runtime.onSuspendCanceled"; |
121 | 121 |
122 // Returns the global value for "chrome" from |context|. If one doesn't exist | 122 // Returns the global value for "chrome" from |context|. If one doesn't exist |
123 // creates a new object for it. | 123 // creates a new object for it. |
124 // | 124 // |
125 // Note that this isn't necessarily an object, since webpages can write, for | 125 // Note that this isn't necessarily an object, since webpages can write, for |
126 // example, "window.chrome = true". | 126 // example, "window.chrome = true". |
127 v8::Handle<v8::Value> GetOrCreateChrome(ScriptContext* context) { | 127 v8::Local<v8::Value> GetOrCreateChrome(ScriptContext* context) { |
128 v8::Handle<v8::String> chrome_string( | 128 v8::Local<v8::String> chrome_string( |
129 v8::String::NewFromUtf8(context->isolate(), "chrome")); | 129 v8::String::NewFromUtf8(context->isolate(), "chrome")); |
130 v8::Handle<v8::Object> global(context->v8_context()->Global()); | 130 v8::Local<v8::Object> global(context->v8_context()->Global()); |
131 v8::Handle<v8::Value> chrome(global->Get(chrome_string)); | 131 v8::Local<v8::Value> chrome(global->Get(chrome_string)); |
132 if (chrome->IsUndefined()) { | 132 if (chrome->IsUndefined()) { |
133 chrome = v8::Object::New(context->isolate()); | 133 chrome = v8::Object::New(context->isolate()); |
134 global->Set(chrome_string, chrome); | 134 global->Set(chrome_string, chrome); |
135 } | 135 } |
136 return chrome; | 136 return chrome; |
137 } | 137 } |
138 | 138 |
139 // Returns |value| cast to an object if possible, else an empty handle. | 139 // Returns |value| cast to an object if possible, else an empty handle. |
140 v8::Handle<v8::Object> AsObjectOrEmpty(v8::Handle<v8::Value> value) { | 140 v8::Local<v8::Object> AsObjectOrEmpty(v8::Local<v8::Value> value) { |
141 return value->IsObject() ? value.As<v8::Object>() : v8::Handle<v8::Object>(); | 141 return value->IsObject() ? value.As<v8::Object>() : v8::Local<v8::Object>(); |
142 } | 142 } |
143 | 143 |
144 // Calls a method |method_name| in a module |module_name| belonging to the | 144 // Calls a method |method_name| in a module |module_name| belonging to the |
145 // module system from |context|. Intended as a callback target from | 145 // module system from |context|. Intended as a callback target from |
146 // ScriptContextSet::ForEach. | 146 // ScriptContextSet::ForEach. |
147 void CallModuleMethod(const std::string& module_name, | 147 void CallModuleMethod(const std::string& module_name, |
148 const std::string& method_name, | 148 const std::string& method_name, |
149 const base::ListValue* args, | 149 const base::ListValue* args, |
150 ScriptContext* context) { | 150 ScriptContext* context) { |
151 v8::HandleScope handle_scope(context->isolate()); | 151 v8::HandleScope handle_scope(context->isolate()); |
152 v8::Context::Scope context_scope(context->v8_context()); | 152 v8::Context::Scope context_scope(context->v8_context()); |
153 | 153 |
154 scoped_ptr<content::V8ValueConverter> converter( | 154 scoped_ptr<content::V8ValueConverter> converter( |
155 content::V8ValueConverter::create()); | 155 content::V8ValueConverter::create()); |
156 | 156 |
157 std::vector<v8::Handle<v8::Value> > arguments; | 157 std::vector<v8::Local<v8::Value>> arguments; |
158 for (base::ListValue::const_iterator it = args->begin(); it != args->end(); | 158 for (base::ListValue::const_iterator it = args->begin(); it != args->end(); |
159 ++it) { | 159 ++it) { |
160 arguments.push_back(converter->ToV8Value(*it, context->v8_context())); | 160 arguments.push_back(converter->ToV8Value(*it, context->v8_context())); |
161 } | 161 } |
162 | 162 |
163 context->module_system()->CallModuleMethod( | 163 context->module_system()->CallModuleMethod( |
164 module_name, method_name, &arguments); | 164 module_name, method_name, &arguments); |
165 } | 165 } |
166 | 166 |
167 // This handles the "chrome." root API object in script contexts. | 167 // This handles the "chrome." root API object in script contexts. |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
222 bool Dispatcher::IsExtensionActive(const std::string& extension_id) const { | 222 bool Dispatcher::IsExtensionActive(const std::string& extension_id) const { |
223 bool is_active = | 223 bool is_active = |
224 active_extension_ids_.find(extension_id) != active_extension_ids_.end(); | 224 active_extension_ids_.find(extension_id) != active_extension_ids_.end(); |
225 if (is_active) | 225 if (is_active) |
226 CHECK(extensions_.Contains(extension_id)); | 226 CHECK(extensions_.Contains(extension_id)); |
227 return is_active; | 227 return is_active; |
228 } | 228 } |
229 | 229 |
230 void Dispatcher::DidCreateScriptContext( | 230 void Dispatcher::DidCreateScriptContext( |
231 blink::WebLocalFrame* frame, | 231 blink::WebLocalFrame* frame, |
232 const v8::Handle<v8::Context>& v8_context, | 232 const v8::Local<v8::Context>& v8_context, |
233 int extension_group, | 233 int extension_group, |
234 int world_id) { | 234 int world_id) { |
235 const base::TimeTicks start_time = base::TimeTicks::Now(); | 235 const base::TimeTicks start_time = base::TimeTicks::Now(); |
236 | 236 |
237 ScriptContext* context = script_context_set_->Register( | 237 ScriptContext* context = script_context_set_->Register( |
238 frame, v8_context, extension_group, world_id); | 238 frame, v8_context, extension_group, world_id); |
239 | 239 |
240 // Initialize origin permissions for content scripts, which can't be | 240 // Initialize origin permissions for content scripts, which can't be |
241 // initialized in |OnActivateExtension|. | 241 // initialized in |OnActivateExtension|. |
242 if (context->context_type() == Feature::CONTENT_SCRIPT_CONTEXT) | 242 if (context->context_type() == Feature::CONTENT_SCRIPT_CONTEXT) |
243 InitOriginPermissions(context->extension()); | 243 InitOriginPermissions(context->extension()); |
244 | 244 |
245 { | 245 { |
246 scoped_ptr<ModuleSystem> module_system( | 246 scoped_ptr<ModuleSystem> module_system( |
247 new ModuleSystem(context, &source_map_)); | 247 new ModuleSystem(context, &source_map_)); |
248 context->set_module_system(module_system.Pass()); | 248 context->set_module_system(module_system.Pass()); |
249 } | 249 } |
250 ModuleSystem* module_system = context->module_system(); | 250 ModuleSystem* module_system = context->module_system(); |
251 | 251 |
252 // Enable natives in startup. | 252 // Enable natives in startup. |
253 ModuleSystem::NativesEnabledScope natives_enabled_scope(module_system); | 253 ModuleSystem::NativesEnabledScope natives_enabled_scope(module_system); |
254 | 254 |
255 RegisterNativeHandlers(module_system, context); | 255 RegisterNativeHandlers(module_system, context); |
256 | 256 |
257 // chrome.Event is part of the public API (although undocumented). Make it | 257 // chrome.Event is part of the public API (although undocumented). Make it |
258 // lazily evalulate to Event from event_bindings.js. For extensions only | 258 // lazily evalulate to Event from event_bindings.js. For extensions only |
259 // though, not all webpages! | 259 // though, not all webpages! |
260 if (context->extension()) { | 260 if (context->extension()) { |
261 v8::Handle<v8::Object> chrome = AsObjectOrEmpty(GetOrCreateChrome(context)); | 261 v8::Local<v8::Object> chrome = AsObjectOrEmpty(GetOrCreateChrome(context)); |
262 if (!chrome.IsEmpty()) | 262 if (!chrome.IsEmpty()) |
263 module_system->SetLazyField(chrome, "Event", kEventBindings, "Event"); | 263 module_system->SetLazyField(chrome, "Event", kEventBindings, "Event"); |
264 } | 264 } |
265 | 265 |
266 UpdateBindingsForContext(context); | 266 UpdateBindingsForContext(context); |
267 | 267 |
268 bool is_within_platform_app = IsWithinPlatformApp(); | 268 bool is_within_platform_app = IsWithinPlatformApp(); |
269 // Inject custom JS into the platform app context. | 269 // Inject custom JS into the platform app context. |
270 if (is_within_platform_app) { | 270 if (is_within_platform_app) { |
271 module_system->Require("platformApp"); | 271 module_system->Require("platformApp"); |
(...skipping 29 matching lines...) Expand all Loading... |
301 case Feature::WEBUI_CONTEXT: | 301 case Feature::WEBUI_CONTEXT: |
302 UMA_HISTOGRAM_TIMES("Extensions.DidCreateScriptContext_WebUI", elapsed); | 302 UMA_HISTOGRAM_TIMES("Extensions.DidCreateScriptContext_WebUI", elapsed); |
303 break; | 303 break; |
304 } | 304 } |
305 | 305 |
306 VLOG(1) << "Num tracked contexts: " << script_context_set_->size(); | 306 VLOG(1) << "Num tracked contexts: " << script_context_set_->size(); |
307 } | 307 } |
308 | 308 |
309 void Dispatcher::WillReleaseScriptContext( | 309 void Dispatcher::WillReleaseScriptContext( |
310 blink::WebLocalFrame* frame, | 310 blink::WebLocalFrame* frame, |
311 const v8::Handle<v8::Context>& v8_context, | 311 const v8::Local<v8::Context>& v8_context, |
312 int world_id) { | 312 int world_id) { |
313 ScriptContext* context = script_context_set_->GetByV8Context(v8_context); | 313 ScriptContext* context = script_context_set_->GetByV8Context(v8_context); |
314 if (!context) | 314 if (!context) |
315 return; | 315 return; |
316 | 316 |
317 context->DispatchOnUnloadEvent(); | 317 context->DispatchOnUnloadEvent(); |
318 // TODO(kalman): Make |request_sender| use |context->AddInvalidationObserver|. | 318 // TODO(kalman): Make |request_sender| use |context->AddInvalidationObserver|. |
319 // In fact |request_sender_| should really be owned by ScriptContext. | 319 // In fact |request_sender_| should really be owned by ScriptContext. |
320 request_sender_->InvalidateSource(context); | 320 request_sender_->InvalidateSource(context); |
321 | 321 |
(...skipping 854 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1176 RegisterBinding(api_name, context); | 1176 RegisterBinding(api_name, context); |
1177 } | 1177 } |
1178 break; | 1178 break; |
1179 } | 1179 } |
1180 } | 1180 } |
1181 } | 1181 } |
1182 | 1182 |
1183 void Dispatcher::RegisterBinding(const std::string& api_name, | 1183 void Dispatcher::RegisterBinding(const std::string& api_name, |
1184 ScriptContext* context) { | 1184 ScriptContext* context) { |
1185 std::string bind_name; | 1185 std::string bind_name; |
1186 v8::Handle<v8::Object> bind_object = | 1186 v8::Local<v8::Object> bind_object = |
1187 GetOrCreateBindObjectIfAvailable(api_name, &bind_name, context); | 1187 GetOrCreateBindObjectIfAvailable(api_name, &bind_name, context); |
1188 | 1188 |
1189 // Empty if the bind object failed to be created, probably because the | 1189 // Empty if the bind object failed to be created, probably because the |
1190 // extension overrode chrome with a non-object, e.g. window.chrome = true. | 1190 // extension overrode chrome with a non-object, e.g. window.chrome = true. |
1191 if (bind_object.IsEmpty()) | 1191 if (bind_object.IsEmpty()) |
1192 return; | 1192 return; |
1193 | 1193 |
1194 v8::Local<v8::String> v8_bind_name = | 1194 v8::Local<v8::String> v8_bind_name = |
1195 v8::String::NewFromUtf8(context->isolate(), bind_name.c_str()); | 1195 v8::String::NewFromUtf8(context->isolate(), bind_name.c_str()); |
1196 if (bind_object->HasRealNamedProperty(v8_bind_name)) { | 1196 if (bind_object->HasRealNamedProperty(v8_bind_name)) { |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1294 for (std::set<std::string>::iterator iter = active_extension_ids_.begin(); | 1294 for (std::set<std::string>::iterator iter = active_extension_ids_.begin(); |
1295 iter != active_extension_ids_.end(); | 1295 iter != active_extension_ids_.end(); |
1296 ++iter) { | 1296 ++iter) { |
1297 const Extension* extension = extensions_.GetByID(*iter); | 1297 const Extension* extension = extensions_.GetByID(*iter); |
1298 if (extension && extension->is_platform_app()) | 1298 if (extension && extension->is_platform_app()) |
1299 return true; | 1299 return true; |
1300 } | 1300 } |
1301 return false; | 1301 return false; |
1302 } | 1302 } |
1303 | 1303 |
1304 v8::Handle<v8::Object> Dispatcher::GetOrCreateObject( | 1304 v8::Local<v8::Object> Dispatcher::GetOrCreateObject( |
1305 const v8::Handle<v8::Object>& object, | 1305 const v8::Local<v8::Object>& object, |
1306 const std::string& field, | 1306 const std::string& field, |
1307 v8::Isolate* isolate) { | 1307 v8::Isolate* isolate) { |
1308 v8::Handle<v8::String> key = v8::String::NewFromUtf8(isolate, field.c_str()); | 1308 v8::Local<v8::String> key = v8::String::NewFromUtf8(isolate, field.c_str()); |
1309 // If the object has a callback property, it is assumed it is an unavailable | 1309 // If the object has a callback property, it is assumed it is an unavailable |
1310 // API, so it is safe to delete. This is checked before GetOrCreateObject is | 1310 // API, so it is safe to delete. This is checked before GetOrCreateObject is |
1311 // called. | 1311 // called. |
1312 if (object->HasRealNamedCallbackProperty(key)) { | 1312 if (object->HasRealNamedCallbackProperty(key)) { |
1313 object->Delete(key); | 1313 object->Delete(key); |
1314 } else if (object->HasRealNamedProperty(key)) { | 1314 } else if (object->HasRealNamedProperty(key)) { |
1315 v8::Handle<v8::Value> value = object->Get(key); | 1315 v8::Local<v8::Value> value = object->Get(key); |
1316 CHECK(value->IsObject()); | 1316 CHECK(value->IsObject()); |
1317 return v8::Handle<v8::Object>::Cast(value); | 1317 return v8::Local<v8::Object>::Cast(value); |
1318 } | 1318 } |
1319 | 1319 |
1320 v8::Handle<v8::Object> new_object = v8::Object::New(isolate); | 1320 v8::Local<v8::Object> new_object = v8::Object::New(isolate); |
1321 object->Set(key, new_object); | 1321 object->Set(key, new_object); |
1322 return new_object; | 1322 return new_object; |
1323 } | 1323 } |
1324 | 1324 |
1325 v8::Handle<v8::Object> Dispatcher::GetOrCreateBindObjectIfAvailable( | 1325 v8::Local<v8::Object> Dispatcher::GetOrCreateBindObjectIfAvailable( |
1326 const std::string& api_name, | 1326 const std::string& api_name, |
1327 std::string* bind_name, | 1327 std::string* bind_name, |
1328 ScriptContext* context) { | 1328 ScriptContext* context) { |
1329 std::vector<std::string> split; | 1329 std::vector<std::string> split; |
1330 base::SplitString(api_name, '.', &split); | 1330 base::SplitString(api_name, '.', &split); |
1331 | 1331 |
1332 v8::Handle<v8::Object> bind_object; | 1332 v8::Local<v8::Object> bind_object; |
1333 | 1333 |
1334 // Check if this API has an ancestor. If the API's ancestor is available and | 1334 // Check if this API has an ancestor. If the API's ancestor is available and |
1335 // the API is not available, don't install the bindings for this API. If | 1335 // the API is not available, don't install the bindings for this API. If |
1336 // the API is available and its ancestor is not, delete the ancestor and | 1336 // the API is available and its ancestor is not, delete the ancestor and |
1337 // install the bindings for the API. This is to prevent loading the ancestor | 1337 // install the bindings for the API. This is to prevent loading the ancestor |
1338 // API schema if it will not be needed. | 1338 // API schema if it will not be needed. |
1339 // | 1339 // |
1340 // For example: | 1340 // For example: |
1341 // If app is available and app.window is not, just install app. | 1341 // If app is available and app.window is not, just install app. |
1342 // If app.window is available and app is not, delete app and install | 1342 // If app.window is available and app is not, delete app and install |
1343 // app.window on a new object so app does not have to be loaded. | 1343 // app.window on a new object so app does not have to be loaded. |
1344 const FeatureProvider* api_feature_provider = | 1344 const FeatureProvider* api_feature_provider = |
1345 FeatureProvider::GetAPIFeatures(); | 1345 FeatureProvider::GetAPIFeatures(); |
1346 std::string ancestor_name; | 1346 std::string ancestor_name; |
1347 bool only_ancestor_available = false; | 1347 bool only_ancestor_available = false; |
1348 | 1348 |
1349 for (size_t i = 0; i < split.size() - 1; ++i) { | 1349 for (size_t i = 0; i < split.size() - 1; ++i) { |
1350 ancestor_name += (i ? "." : "") + split[i]; | 1350 ancestor_name += (i ? "." : "") + split[i]; |
1351 if (api_feature_provider->GetFeature(ancestor_name) && | 1351 if (api_feature_provider->GetFeature(ancestor_name) && |
1352 context->GetAvailability(ancestor_name).is_available() && | 1352 context->GetAvailability(ancestor_name).is_available() && |
1353 !context->GetAvailability(api_name).is_available()) { | 1353 !context->GetAvailability(api_name).is_available()) { |
1354 only_ancestor_available = true; | 1354 only_ancestor_available = true; |
1355 break; | 1355 break; |
1356 } | 1356 } |
1357 | 1357 |
1358 if (bind_object.IsEmpty()) { | 1358 if (bind_object.IsEmpty()) { |
1359 bind_object = AsObjectOrEmpty(GetOrCreateChrome(context)); | 1359 bind_object = AsObjectOrEmpty(GetOrCreateChrome(context)); |
1360 if (bind_object.IsEmpty()) | 1360 if (bind_object.IsEmpty()) |
1361 return v8::Handle<v8::Object>(); | 1361 return v8::Local<v8::Object>(); |
1362 } | 1362 } |
1363 bind_object = GetOrCreateObject(bind_object, split[i], context->isolate()); | 1363 bind_object = GetOrCreateObject(bind_object, split[i], context->isolate()); |
1364 } | 1364 } |
1365 | 1365 |
1366 if (only_ancestor_available) | 1366 if (only_ancestor_available) |
1367 return v8::Handle<v8::Object>(); | 1367 return v8::Local<v8::Object>(); |
1368 | 1368 |
1369 if (bind_name) | 1369 if (bind_name) |
1370 *bind_name = split.back(); | 1370 *bind_name = split.back(); |
1371 | 1371 |
1372 return bind_object.IsEmpty() ? AsObjectOrEmpty(GetOrCreateChrome(context)) | 1372 return bind_object.IsEmpty() ? AsObjectOrEmpty(GetOrCreateChrome(context)) |
1373 : bind_object; | 1373 : bind_object; |
1374 } | 1374 } |
1375 | 1375 |
1376 void Dispatcher::RequireGuestViewModules(ScriptContext* context) { | 1376 void Dispatcher::RequireGuestViewModules(ScriptContext* context) { |
1377 Feature::Context context_type = context->context_type(); | 1377 Feature::Context context_type = context->context_type(); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1411 // The "guestViewDeny" module must always be loaded last. It registers | 1411 // The "guestViewDeny" module must always be loaded last. It registers |
1412 // error-providing custom elements for the GuestView types that are not | 1412 // error-providing custom elements for the GuestView types that are not |
1413 // available, and thus all of those types must have been checked and loaded | 1413 // available, and thus all of those types must have been checked and loaded |
1414 // (or not loaded) beforehand. | 1414 // (or not loaded) beforehand. |
1415 if (context_type == Feature::BLESSED_EXTENSION_CONTEXT) { | 1415 if (context_type == Feature::BLESSED_EXTENSION_CONTEXT) { |
1416 module_system->Require("guestViewDeny"); | 1416 module_system->Require("guestViewDeny"); |
1417 } | 1417 } |
1418 } | 1418 } |
1419 | 1419 |
1420 } // namespace extensions | 1420 } // namespace extensions |
OLD | NEW |