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

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

Issue 15961006: Regenerate Extensions API bindings when optional permissions change (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 6 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/debug/alias.h" 9 #include "base/debug/alias.h"
10 #include "base/json/json_reader.h" 10 #include "base/json/json_reader.h"
(...skipping 701 matching lines...) Expand 10 before | Expand all | Expand 10 after
712 CHECK(value->IsObject()); 712 CHECK(value->IsObject());
713 return handle_scope.Close(v8::Handle<v8::Object>::Cast(value)); 713 return handle_scope.Close(v8::Handle<v8::Object>::Cast(value));
714 } 714 }
715 715
716 v8::Handle<v8::Object> new_object = v8::Object::New(); 716 v8::Handle<v8::Object> new_object = v8::Object::New();
717 object->Set(key, new_object); 717 object->Set(key, new_object);
718 return handle_scope.Close(new_object); 718 return handle_scope.Close(new_object);
719 } 719 }
720 720
721 void Dispatcher::RegisterSchemaGeneratedBindings( 721 void Dispatcher::RegisterSchemaGeneratedBindings(
722 ModuleSystem* module_system, 722 ModuleSystem* module_system,
not at google - send to devlin 2013/05/31 16:35:00 actually module_system on here isn't necessary bec
cduvall 2013/06/05 03:05:56 Done.
723 ChromeV8Context* context) { 723 ChromeV8Context* context) {
724 std::set<std::string> apis = 724 std::set<std::string> apis =
725 ExtensionAPI::GetSharedInstance()->GetAllAPINames(); 725 ExtensionAPI::GetSharedInstance()->GetAllAPINames();
726 for (std::set<std::string>::iterator it = apis.begin(); 726 for (std::set<std::string>::iterator it = apis.begin();
727 it != apis.end(); ++it) { 727 it != apis.end(); ++it) {
728 const std::string& api_name = *it; 728 const std::string& api_name = *it;
729 if (!context->IsAnyFeatureAvailableToContext(api_name)) 729 if (!context->IsAnyFeatureAvailableToContext(api_name)) {
730 RemoveAPIBindingIfPresent(api_name, context);
730 continue; 731 continue;
732 }
731 733
732 Feature* feature = 734 Feature* feature =
733 BaseFeatureProvider::GetByName("api")->GetFeature(api_name); 735 BaseFeatureProvider::GetByName("api")->GetFeature(api_name);
734 if (feature && feature->IsInternal()) 736 if (feature && feature->IsInternal())
735 continue; 737 continue;
736 738
737 std::vector<std::string> split; 739 RegisterBinding(api_name, module_system, context);
738 base::SplitString(api_name, '.', &split);
739
740 v8::Handle<v8::Object> bind_object =
741 GetOrCreateChrome(context->v8_context());
742
743 // Check if this API has an ancestor. If the API's ancestor is available and
744 // the API is not available, don't install the bindings for this API. If
745 // the API is available and its ancestor is not, delete the ancestor and
746 // install the bindings for the API. This is to prevent loading the ancestor
747 // API schema if it will not be needed.
748 //
749 // For example:
750 // If app is available and app.window is not, just install app.
751 // If app.window is available and app is not, delete app and install
752 // app.window on a new object so app does not have to be loaded.
753 std::string ancestor_name;
754 bool only_ancestor_available = false;
755 for (size_t i = 0; i < split.size() - 1; ++i) {
756 ancestor_name += (i ? ".": "") + split[i];
757 if (!ancestor_name.empty() &&
758 context->GetAvailability(ancestor_name).is_available() &&
759 !context->GetAvailability(api_name).is_available()) {
760 only_ancestor_available = true;
761 break;
762 }
763 bind_object = GetOrCreateObject(bind_object, split[i]);
764 }
765 if (only_ancestor_available)
766 continue;
767
768 if (lazy_bindings_map_.find(api_name) != lazy_bindings_map_.end()) {
769 InstallBindings(module_system, context->v8_context(), api_name);
770 } else if (!source_map_.Contains(api_name)) {
771 module_system->RegisterNativeHandler(
772 api_name,
773 scoped_ptr<NativeHandler>(new BindingGeneratingNativeHandler(
774 module_system,
775 api_name,
776 "binding")));
777 module_system->SetNativeLazyField(bind_object,
778 split.back(),
779 api_name,
780 "binding");
781 } else {
782 module_system->SetLazyField(bind_object,
783 split.back(),
784 api_name,
785 "binding");
786 }
787 } 740 }
788 } 741 }
789 742
743 void Dispatcher::RemoveAPIBindingIfPresent(const std::string& api_name,
not at google - send to devlin 2013/05/31 16:35:00 Maybe DeregisterBinding as a parallel to RegisterB
cduvall 2013/06/05 03:05:56 Done.
744 ChromeV8Context* context) {
745 std::string bind_name;
746 v8::Handle<v8::Object> bind_object =
747 GetBindObject(api_name, &bind_name, context);
748 if (bind_object->HasRealNamedProperty(v8::String::New(bind_name.c_str()))) {
749 bind_object->Delete(v8::String::New(bind_name.c_str()));
not at google - send to devlin 2013/05/31 16:35:00 save a reference to the v8::String::New here.
cduvall 2013/06/05 03:05:56 Done.
750 }
not at google - send to devlin 2013/05/31 16:35:00 no {}
cduvall 2013/06/05 03:05:56 Done.
751 }
752
753 v8::Handle<v8::Object> Dispatcher::GetBindObject(const std::string& api_name,
754 std::string* bind_name,
not at google - send to devlin 2013/05/31 16:35:00 this is really GetOrCreateBindObject, though maybe
cduvall 2013/06/05 03:05:56 Done.
755 ChromeV8Context* context) {
756 v8::HandleScope handle_scope;
757 std::vector<std::string> split;
758 base::SplitString(api_name, '.', &split);
759
760 v8::Handle<v8::Object> bind_object = GetOrCreateChrome(context->v8_context());
not at google - send to devlin 2013/05/31 16:35:00 I think you'll need to move this to after the avai
cduvall 2013/06/05 03:05:56 Done.
761
762 // Check if this API has an ancestor. If the API's ancestor is available and
763 // the API is not available, don't install the bindings for this API. If
764 // the API is available and its ancestor is not, delete the ancestor and
765 // install the bindings for the API. This is to prevent loading the ancestor
766 // API schema if it will not be needed.
767 //
768 // For example:
769 // If app is available and app.window is not, just install app.
770 // If app.window is available and app is not, delete app and install
771 // app.window on a new object so app does not have to be loaded.
772 std::string ancestor_name;
773 bool only_ancestor_available = false;
774 for (size_t i = 0; i < split.size() - 1; ++i) {
775 ancestor_name += (i ? ".": "") + split[i];
776 if (!ancestor_name.empty() &&
777 context->GetAvailability(ancestor_name).is_available() &&
778 !context->GetAvailability(api_name).is_available()) {
779 only_ancestor_available = true;
780 break;
781 }
782 bind_object = GetOrCreateObject(bind_object, split[i]);
783 }
784 if (only_ancestor_available)
785 return handle_scope.Close(v8::Handle<v8::Object>());
786 if (bind_name)
787 *bind_name = split.back();
788 return handle_scope.Close(bind_object);
789 }
790
791 void Dispatcher::RegisterBinding(const std::string& api_name,
792 ModuleSystem* module_system,
793 ChromeV8Context* context) {
794 std::string bind_name;
795 v8::Handle<v8::Object> bind_object =
796 GetBindObject(api_name, &bind_name, context);
797 if (bind_object.IsEmpty())
798 return;
799
800 if (lazy_bindings_map_.find(api_name) != lazy_bindings_map_.end()) {
801 InstallBindings(module_system, context->v8_context(), api_name);
802 } else if (!source_map_.Contains(api_name)) {
803 module_system->RegisterNativeHandler(
804 api_name,
805 scoped_ptr<NativeHandler>(new BindingGeneratingNativeHandler(
806 module_system,
807 api_name,
808 "binding")));
809 module_system->SetNativeLazyField(bind_object,
810 bind_name,
811 api_name,
812 "binding");
813 } else {
814 module_system->SetLazyField(bind_object,
815 bind_name,
816 api_name,
817 "binding");
818 }
819 }
820
790 void Dispatcher::RegisterNativeHandlers(ModuleSystem* module_system, 821 void Dispatcher::RegisterNativeHandlers(ModuleSystem* module_system,
791 ChromeV8Context* context) { 822 ChromeV8Context* context) {
792 v8::Handle<v8::Context> v8_context = context->v8_context(); 823 v8::Handle<v8::Context> v8_context = context->v8_context();
793 824
794 module_system->RegisterNativeHandler("event_bindings", 825 module_system->RegisterNativeHandler("event_bindings",
795 scoped_ptr<NativeHandler>(EventBindings::Create(this, v8_context))); 826 scoped_ptr<NativeHandler>(EventBindings::Create(this, v8_context)));
796 module_system->RegisterNativeHandler("miscellaneous_bindings", 827 module_system->RegisterNativeHandler("miscellaneous_bindings",
797 scoped_ptr<NativeHandler>(MiscellaneousBindings::Get(this, v8_context))); 828 scoped_ptr<NativeHandler>(MiscellaneousBindings::Get(this, v8_context)));
798 module_system->RegisterNativeHandler("apiDefinitions", 829 module_system->RegisterNativeHandler("apiDefinitions",
799 scoped_ptr<NativeHandler>(new ApiDefinitionsNatives(this, context))); 830 scoped_ptr<NativeHandler>(new ApiDefinitionsNatives(this, context)));
(...skipping 446 matching lines...) Expand 10 before | Expand all | Expand 10 after
1246 WebSecurityPolicy::addOriginAccessWhitelistEntry)( 1277 WebSecurityPolicy::addOriginAccessWhitelistEntry)(
1247 extension->url(), 1278 extension->url(),
1248 WebString::fromUTF8(schemes[j]), 1279 WebString::fromUTF8(schemes[j]),
1249 WebString::fromUTF8(i->host()), 1280 WebString::fromUTF8(i->host()),
1250 i->match_subdomains()); 1281 i->match_subdomains());
1251 } 1282 }
1252 } 1283 }
1253 } 1284 }
1254 } 1285 }
1255 1286
1287 void Dispatcher::RefreshSchemaGeneratedBindings() {
1288 v8::HandleScope handle_scope;
1289 CHECK(v8_context_set().size());
1290 // TODO(cduvall): This is wrong. Not sure what to do.
cduvall 2013/05/31 03:06:34 I'm not sure how to get the right context to regis
not at google - send to devlin 2013/05/31 16:35:00 Ah right, yeah. So what you want is this: https:/
cduvall 2013/06/05 03:05:56 So I added in the v8_context_set_.ForEach(), but I
not at google - send to devlin 2013/06/05 19:03:44 It may be the lack of an is_valid check in ChromeV
cduvall 2013/06/05 23:27:59 Looks like the is_valid() check didn't fix the pro
1291 ChromeV8Context* context = *v8_context_set().GetAll().begin();
1292 context->v8_context()->Enter();
1293 RegisterSchemaGeneratedBindings(context->module_system(), context);
1294 context->v8_context()->Exit();
not at google - send to devlin 2013/05/31 16:35:00 use v8::Context::Scope here, and move into Registe
cduvall 2013/06/05 03:05:56 Done.
1295 }
1296
1256 void Dispatcher::OnUpdatePermissions(int reason_id, 1297 void Dispatcher::OnUpdatePermissions(int reason_id,
1257 const std::string& extension_id, 1298 const std::string& extension_id,
1258 const APIPermissionSet& apis, 1299 const APIPermissionSet& apis,
1259 const URLPatternSet& explicit_hosts, 1300 const URLPatternSet& explicit_hosts,
1260 const URLPatternSet& scriptable_hosts) { 1301 const URLPatternSet& scriptable_hosts) {
1261 const Extension* extension = extensions_.GetByID(extension_id); 1302 const Extension* extension = extensions_.GetByID(extension_id);
1262 if (!extension) 1303 if (!extension)
1263 return; 1304 return;
1264 1305
1265 scoped_refptr<const PermissionSet> delta = 1306 scoped_refptr<const PermissionSet> delta =
1266 new PermissionSet(apis, explicit_hosts, scriptable_hosts); 1307 new PermissionSet(apis, explicit_hosts, scriptable_hosts);
1267 scoped_refptr<const PermissionSet> old_active = 1308 scoped_refptr<const PermissionSet> old_active =
1268 extension->GetActivePermissions(); 1309 extension->GetActivePermissions();
1269 UpdatedExtensionPermissionsInfo::Reason reason = 1310 UpdatedExtensionPermissionsInfo::Reason reason =
1270 static_cast<UpdatedExtensionPermissionsInfo::Reason>(reason_id); 1311 static_cast<UpdatedExtensionPermissionsInfo::Reason>(reason_id);
1271 1312
1272 const PermissionSet* new_active = NULL; 1313 const PermissionSet* new_active = NULL;
1273 switch (reason) { 1314 switch (reason) {
1274 case UpdatedExtensionPermissionsInfo::ADDED: 1315 case UpdatedExtensionPermissionsInfo::ADDED:
1275 new_active = PermissionSet::CreateUnion(old_active, delta); 1316 new_active = PermissionSet::CreateUnion(old_active, delta);
1276 break; 1317 break;
1277 case UpdatedExtensionPermissionsInfo::REMOVED: 1318 case UpdatedExtensionPermissionsInfo::REMOVED:
1278 new_active = PermissionSet::CreateDifference(old_active, delta); 1319 new_active = PermissionSet::CreateDifference(old_active, delta);
1279 break; 1320 break;
1280 } 1321 }
1281 1322
1282 PermissionsData::SetActivePermissions(extension, new_active); 1323 PermissionsData::SetActivePermissions(extension, new_active);
1283 AddOrRemoveOriginPermissions(reason, extension, explicit_hosts); 1324 AddOrRemoveOriginPermissions(reason, extension, explicit_hosts);
1325 RefreshSchemaGeneratedBindings();
1284 } 1326 }
1285 1327
1286 void Dispatcher::OnUpdateTabSpecificPermissions( 1328 void Dispatcher::OnUpdateTabSpecificPermissions(
1287 int page_id, 1329 int page_id,
1288 int tab_id, 1330 int tab_id,
1289 const std::string& extension_id, 1331 const std::string& extension_id,
1290 const URLPatternSet& origin_set) { 1332 const URLPatternSet& origin_set) {
1291 RenderView* view = TabFinder::Find(tab_id); 1333 RenderView* view = TabFinder::Find(tab_id);
1292 1334
1293 // For now, the message should only be sent to the render view that contains 1335 // For now, the message should only be sent to the render view that contains
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after
1458 std::string error_msg = base::StringPrintf(kMessage, function_name.c_str()); 1500 std::string error_msg = base::StringPrintf(kMessage, function_name.c_str());
1459 v8::ThrowException( 1501 v8::ThrowException(
1460 v8::Exception::Error(v8::String::New(error_msg.c_str()))); 1502 v8::Exception::Error(v8::String::New(error_msg.c_str())));
1461 return false; 1503 return false;
1462 } 1504 }
1463 1505
1464 return true; 1506 return true;
1465 } 1507 }
1466 1508
1467 } // namespace extensions 1509 } // namespace extensions
OLDNEW
« no previous file with comments | « chrome/renderer/extensions/dispatcher.h ('k') | chrome/test/data/extensions/api_test/permissions/optional/background.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698