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