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/dispatcher.h" | 5 #include "chrome/renderer/extensions/dispatcher.h" |
6 | 6 |
7 #include "base/callback.h" | 7 #include "base/callback.h" |
8 #include "base/command_line.h" | 8 #include "base/command_line.h" |
9 #include "base/memory/scoped_ptr.h" | 9 #include "base/memory/scoped_ptr.h" |
10 #include "base/strings/string_piece.h" | 10 #include "base/strings/string_piece.h" |
(...skipping 636 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
647 int world_id) { | 647 int world_id) { |
648 g_hack_extension_group = extension_group; | 648 g_hack_extension_group = extension_group; |
649 return true; | 649 return true; |
650 } | 650 } |
651 | 651 |
652 v8::Handle<v8::Object> Dispatcher::GetOrCreateObject( | 652 v8::Handle<v8::Object> Dispatcher::GetOrCreateObject( |
653 v8::Handle<v8::Object> object, | 653 v8::Handle<v8::Object> object, |
654 const std::string& field) { | 654 const std::string& field) { |
655 v8::HandleScope handle_scope; | 655 v8::HandleScope handle_scope; |
656 v8::Handle<v8::String> key = v8::String::New(field.c_str()); | 656 v8::Handle<v8::String> key = v8::String::New(field.c_str()); |
657 // This little dance is for APIs that may be unavailable but have available | 657 // If the object has a callback property, it is assumed it is an unavailable |
658 // children. For example, chrome.app can be unavailable, while | 658 // API, so it is safe to delete. This is checked before GetOrCreateObject is |
659 // chrome.app.runtime is available. The lazy getter for chrome.app must be | 659 // called. |
660 // deleted, so that there isn't an error when accessing chrome.app.runtime. | 660 if (object->HasRealNamedCallbackProperty(key)) { |
661 if (object->Has(key)) { | 661 object->Delete(key); |
662 } else if (object->HasRealNamedProperty(key)) { | |
662 v8::Handle<v8::Value> value = object->Get(key); | 663 v8::Handle<v8::Value> value = object->Get(key); |
663 if (value->IsObject()) | 664 CHECK(value->IsObject()); |
664 return handle_scope.Close(v8::Handle<v8::Object>::Cast(value)); | 665 return handle_scope.Close(v8::Handle<v8::Object>::Cast(value)); |
665 else | |
666 object->Delete(key); | |
667 } | 666 } |
668 | 667 |
669 v8::Handle<v8::Object> new_object = v8::Object::New(); | 668 v8::Handle<v8::Object> new_object = v8::Object::New(); |
670 object->Set(key, new_object); | 669 object->Set(key, new_object); |
671 return handle_scope.Close(new_object); | 670 return handle_scope.Close(new_object); |
672 } | 671 } |
673 | 672 |
674 void Dispatcher::RegisterSchemaGeneratedBindings( | 673 void Dispatcher::RegisterSchemaGeneratedBindings( |
675 ModuleSystem* module_system, | 674 ModuleSystem* module_system, |
676 ChromeV8Context* context, | 675 ChromeV8Context* context) { |
677 v8::Handle<v8::Context> v8_context) { | |
678 std::set<std::string> apis = | 676 std::set<std::string> apis = |
679 ExtensionAPI::GetSharedInstance()->GetAllAPINames(); | 677 ExtensionAPI::GetSharedInstance()->GetAllAPINames(); |
680 for (std::set<std::string>::iterator it = apis.begin(); | 678 for (std::set<std::string>::iterator it = apis.begin(); |
681 it != apis.end(); ++it) { | 679 it != apis.end(); ++it) { |
682 const std::string& api_name = *it; | 680 const std::string& api_name = *it; |
681 if (!context->GetAvailabilityForContext(api_name).is_available()) | |
682 continue; | |
683 | 683 |
684 Feature* feature = | 684 Feature* feature = |
685 BaseFeatureProvider::GetByName("api")->GetFeature(api_name); | 685 BaseFeatureProvider::GetByName("api")->GetFeature(api_name); |
686 if (feature && feature->IsInternal()) | 686 if (feature && feature->IsInternal()) |
687 continue; | 687 continue; |
688 | 688 |
689 std::vector<std::string> split; | 689 std::vector<std::string> split; |
690 base::SplitString(api_name, '.', &split); | 690 base::SplitString(api_name, '.', &split); |
691 | 691 |
692 v8::Handle<v8::Object> bind_object = GetOrCreateChrome(v8_context); | 692 v8::Handle<v8::Object> bind_object = |
693 for (size_t i = 0; i < split.size() - 1; ++i) | 693 GetOrCreateChrome(context->v8_context()); |
694 | |
695 // Check if this API has an ancestor. If the API's ancestor is available and | |
696 // the API is not available, don't install the bindings for this API. If | |
697 // the API is available and its ancestor is not, delete the ancestor and | |
698 // install the bindings for the API. This is to prevent loading the ancestor | |
699 // API schema if it will not be needed. | |
700 // | |
701 // For example: | |
702 // If app is available and app.window is not, just install app. | |
703 // If app.window is available and app is not, delete app and install | |
704 // app.window on a new object so app does not have to be loaded. | |
705 std::string ancestor_name; | |
706 bool only_ancestor_available = false; | |
707 for (size_t i = 0; i < split.size() - 1; ++i) { | |
708 ancestor_name += (i ? ".": "") + split[i]; | |
709 if (!ancestor_name.empty() && | |
710 context->GetAvailability(ancestor_name).is_available() && | |
711 !context->GetAvailability(api_name).is_available()) { | |
712 only_ancestor_available = true; | |
713 break; | |
714 } | |
694 bind_object = GetOrCreateObject(bind_object, split[i]); | 715 bind_object = GetOrCreateObject(bind_object, split[i]); |
716 } | |
717 if (only_ancestor_available) | |
718 continue; | |
695 | 719 |
696 if (lazy_bindings_map_.find(api_name) != lazy_bindings_map_.end()) { | 720 if (lazy_bindings_map_.find(api_name) != lazy_bindings_map_.end()) { |
697 InstallBindings(module_system, v8_context, api_name); | 721 InstallBindings(module_system, context->v8_context(), api_name); |
698 } else if (!source_map_.Contains(api_name)) { | 722 } else if (!source_map_.Contains(api_name)) { |
699 module_system->RegisterNativeHandler( | 723 module_system->RegisterNativeHandler( |
700 api_name, | 724 api_name, |
701 scoped_ptr<NativeHandler>(new BindingGeneratingNativeHandler( | 725 scoped_ptr<NativeHandler>(new BindingGeneratingNativeHandler( |
702 module_system, | 726 module_system, |
703 api_name, | 727 api_name, |
704 "binding"))); | 728 "binding"))); |
705 module_system->SetNativeLazyField(bind_object, | 729 module_system->SetNativeLazyField(bind_object, |
706 split.back(), | 730 split.back(), |
707 api_name, | 731 api_name, |
(...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
976 BackgroundInfo::HasLazyBackgroundPage(extension)); | 1000 BackgroundInfo::HasLazyBackgroundPage(extension)); |
977 module_system->RegisterNativeHandler("process", | 1001 module_system->RegisterNativeHandler("process", |
978 scoped_ptr<NativeHandler>(new ProcessInfoNativeHandler( | 1002 scoped_ptr<NativeHandler>(new ProcessInfoNativeHandler( |
979 this, v8_context, context->GetExtensionID(), | 1003 this, v8_context, context->GetExtensionID(), |
980 context->GetContextTypeDescription(), | 1004 context->GetContextTypeDescription(), |
981 ChromeRenderProcessObserver::is_incognito_process(), | 1005 ChromeRenderProcessObserver::is_incognito_process(), |
982 manifest_version, send_request_disabled))); | 1006 manifest_version, send_request_disabled))); |
983 | 1007 |
984 GetOrCreateChrome(v8_context); | 1008 GetOrCreateChrome(v8_context); |
985 | 1009 |
986 // Loading JavaScript is expensive, so only run the full API bindings | 1010 // TODO(kalman): see comment below about ExtensionAPI. |
987 // generation mechanisms in extension pages (NOT all web pages). | 1011 InstallBindings(module_system.get(), v8_context, "app"); |
988 switch (context_type) { | 1012 InstallBindings(module_system.get(), v8_context, "webstore"); |
not at google - send to devlin
2013/04/19 14:34:36
We should be able to remove these two lines since
cduvall
2013/04/24 01:34:01
Done.
| |
989 case Feature::UNSPECIFIED_CONTEXT: | 1013 if (extension && !extension->is_platform_app()) |
990 case Feature::WEB_PAGE_CONTEXT: | 1014 module_system->Require("miscellaneous_bindings"); |
991 // TODO(kalman): see comment below about ExtensionAPI. | 1015 module_system->Require("json"); // see paranoid comment in json.js |
not at google - send to devlin
2013/04/19 14:34:36
I'd be interested in seeing whether moving this Re
cduvall
2013/04/24 01:34:01
Deleting this Require ended up not failing any tes
not at google - send to devlin
2013/04/24 04:09:10
No tests? I would actually expect it to break one
cduvall
2013/04/25 00:12:10
Done.
| |
992 InstallBindings(module_system.get(), v8_context, "app"); | |
993 InstallBindings(module_system.get(), v8_context, "webstore"); | |
994 break; | |
995 case Feature::BLESSED_EXTENSION_CONTEXT: | |
996 case Feature::UNBLESSED_EXTENSION_CONTEXT: | |
997 case Feature::CONTENT_SCRIPT_CONTEXT: | |
998 if (extension && !extension->is_platform_app()) | |
999 module_system->Require("miscellaneous_bindings"); | |
1000 module_system->Require("json"); // see paranoid comment in json.js | |
1001 | 1016 |
1002 // TODO(kalman): move this code back out of the switch and execute it | 1017 RegisterSchemaGeneratedBindings(module_system.get(), context); |
1003 // regardless of |context_type|. ExtensionAPI knows how to return the | |
1004 // correct APIs, however, until it doesn't have a 2MB overhead we can't | |
1005 // load it in every process. | |
1006 RegisterSchemaGeneratedBindings(module_system.get(), | |
1007 context, | |
1008 v8_context); | |
1009 break; | |
1010 } | |
1011 | 1018 |
1012 bool is_within_platform_app = IsWithinPlatformApp(frame); | 1019 bool is_within_platform_app = IsWithinPlatformApp(frame); |
1013 // Inject custom JS into the platform app context. | 1020 // Inject custom JS into the platform app context. |
1014 if (is_within_platform_app) | 1021 if (is_within_platform_app) |
1015 module_system->Require("platformApp"); | 1022 module_system->Require("platformApp"); |
1016 | 1023 |
1017 // Only platform apps support the <webview> tag, because the "webView" and | 1024 // Only platform apps support the <webview> tag, because the "webView" and |
1018 // "denyWebView" modules will affect the performance of DOM modifications | 1025 // "denyWebView" modules will affect the performance of DOM modifications |
1019 // (http://crbug.com/196453). | 1026 // (http://crbug.com/196453). |
1020 if (context_type == Feature::BLESSED_EXTENSION_CONTEXT && | 1027 if (context_type == Feature::BLESSED_EXTENSION_CONTEXT && |
(...skipping 353 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1374 std::string error_msg = base::StringPrintf(kMessage, function_name.c_str()); | 1381 std::string error_msg = base::StringPrintf(kMessage, function_name.c_str()); |
1375 v8::ThrowException( | 1382 v8::ThrowException( |
1376 v8::Exception::Error(v8::String::New(error_msg.c_str()))); | 1383 v8::Exception::Error(v8::String::New(error_msg.c_str()))); |
1377 return false; | 1384 return false; |
1378 } | 1385 } |
1379 | 1386 |
1380 return true; | 1387 return true; |
1381 } | 1388 } |
1382 | 1389 |
1383 } // namespace extensions | 1390 } // namespace extensions |
OLD | NEW |