Chromium Code Reviews| 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/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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |