Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(15)

Side by Side Diff: chrome/renderer/extensions/dispatcher.cc

Issue 13604005: Prevent chrome.app JSON schema from loading on every page (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: register bindings only for APIs available to the context Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698