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

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

Issue 15091002: Lazily load API schemas from resource files and convert all APIs to features (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix chromeos tests 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 606 matching lines...) Expand 10 before | Expand all | Expand 10 after
617 617
618 v8::Handle<v8::Object> new_object = v8::Object::New(); 618 v8::Handle<v8::Object> new_object = v8::Object::New();
619 object->Set(key, new_object); 619 object->Set(key, new_object);
620 return new_object; 620 return new_object;
621 } 621 }
622 622
623 void Dispatcher::AddOrRemoveBindings(ChromeV8Context* context) { 623 void Dispatcher::AddOrRemoveBindings(ChromeV8Context* context) {
624 v8::HandleScope handle_scope; 624 v8::HandleScope handle_scope;
625 v8::Context::Scope context_scope(context->v8_context()); 625 v8::Context::Scope context_scope(context->v8_context());
626 626
627 std::set<std::string> apis = 627 FeatureProvider* feature_provider = BaseFeatureProvider::GetByName("api");
628 ExtensionAPI::GetSharedInstance()->GetAllAPINames(); 628 const std::vector<std::string>& apis = feature_provider->GetAllFeatureNames();
629 for (std::set<std::string>::iterator it = apis.begin(); 629 for (std::vector<std::string>::const_iterator it = apis.begin();
630 it != apis.end(); ++it) { 630 it != apis.end(); ++it) {
631 const std::string& api_name = *it; 631 const std::string& api_name = *it;
632 Feature* feature = feature_provider->GetFeature(api_name);
633 DCHECK(feature);
634 if (feature->IsInternal())
635 continue;
636
637 // If this API name has parent features, then this must be a function or
638 // event, so we should not register.
639 bool parent_feature_available = false;
640 for (Feature* parent_feature = feature_provider->GetParent(feature);
641 parent_feature;
642 parent_feature = feature_provider->GetParent(parent_feature)) {
643 if (context->IsAnyFeatureAvailableToContext(parent_feature->name())) {
644 parent_feature_available = true;
645 break;
646 }
647 }
648 if (parent_feature_available)
649 continue;
650
632 if (!context->IsAnyFeatureAvailableToContext(api_name)) { 651 if (!context->IsAnyFeatureAvailableToContext(api_name)) {
633 DeregisterBinding(api_name, context); 652 DeregisterBinding(api_name, context);
634 continue; 653 continue;
635 } 654 }
636 655
637 Feature* feature =
638 BaseFeatureProvider::GetByName("api")->GetFeature(api_name);
639 if (feature && feature->IsInternal())
640 continue;
641
642 RegisterBinding(api_name, context); 656 RegisterBinding(api_name, context);
643 } 657 }
644 } 658 }
645 659
646 void Dispatcher::DeregisterBinding(const std::string& api_name, 660 void Dispatcher::DeregisterBinding(const std::string& api_name,
647 ChromeV8Context* context) { 661 ChromeV8Context* context) {
648 std::string bind_name; 662 std::string bind_name;
649 v8::Handle<v8::Object> bind_object = 663 v8::Handle<v8::Object> bind_object =
650 GetOrCreateBindObjectIfAvailable(api_name, &bind_name, context); 664 GetOrCreateBindObjectIfAvailable(api_name, &bind_name, context);
651 v8::Handle<v8::String> v8_bind_name = v8::String::New(bind_name.c_str()); 665 v8::Handle<v8::String> v8_bind_name = v8::String::New(bind_name.c_str());
(...skipping 13 matching lines...) Expand all
665 // Check if this API has an ancestor. If the API's ancestor is available and 679 // Check if this API has an ancestor. If the API's ancestor is available and
666 // the API is not available, don't install the bindings for this API. If 680 // the API is not available, don't install the bindings for this API. If
667 // the API is available and its ancestor is not, delete the ancestor and 681 // the API is available and its ancestor is not, delete the ancestor and
668 // install the bindings for the API. This is to prevent loading the ancestor 682 // install the bindings for the API. This is to prevent loading the ancestor
669 // API schema if it will not be needed. 683 // API schema if it will not be needed.
670 // 684 //
671 // For example: 685 // For example:
672 // If app is available and app.window is not, just install app. 686 // If app is available and app.window is not, just install app.
673 // If app.window is available and app is not, delete app and install 687 // If app.window is available and app is not, delete app and install
674 // app.window on a new object so app does not have to be loaded. 688 // app.window on a new object so app does not have to be loaded.
689 FeatureProvider* feature_provider = BaseFeatureProvider::GetByName("api");
675 std::string ancestor_name; 690 std::string ancestor_name;
676 bool only_ancestor_available = false; 691 bool only_ancestor_available = false;
677 692
678 for (size_t i = 0; i < split.size() - 1; ++i) { 693 for (size_t i = 0; i < split.size() - 1; ++i) {
679 ancestor_name += (i ? ".": "") + split[i]; 694 ancestor_name += (i ? ".": "") + split[i];
680 if (!ancestor_name.empty() && 695 if (feature_provider->GetFeature(ancestor_name) &&
681 context->GetAvailability(ancestor_name).is_available() && 696 context->GetAvailability(ancestor_name).is_available() &&
682 !context->GetAvailability(api_name).is_available()) { 697 !context->GetAvailability(api_name).is_available()) {
683 only_ancestor_available = true; 698 only_ancestor_available = true;
684 break; 699 break;
685 } 700 }
686 701
687 if (bind_object.IsEmpty()) { 702 if (bind_object.IsEmpty()) {
688 bind_object = AsObjectOrEmpty(GetOrCreateChrome(context)); 703 bind_object = AsObjectOrEmpty(GetOrCreateChrome(context));
689 if (bind_object.IsEmpty()) 704 if (bind_object.IsEmpty())
690 return v8::Handle<v8::Object>(); 705 return v8::Handle<v8::Object>();
(...skipping 665 matching lines...) Expand 10 before | Expand all | Expand 10 after
1356 DLOG(ERROR) << "Not in a v8::Context"; 1371 DLOG(ERROR) << "Not in a v8::Context";
1357 return false; 1372 return false;
1358 } 1373 }
1359 1374
1360 if (!context->extension()) { 1375 if (!context->extension()) {
1361 v8::ThrowException( 1376 v8::ThrowException(
1362 v8::Exception::Error(v8::String::New("Not in an extension."))); 1377 v8::Exception::Error(v8::String::New("Not in an extension.")));
1363 return false; 1378 return false;
1364 } 1379 }
1365 1380
1366 if (!context->extension()->HasAPIPermission(function_name)) {
1367 static const char kMessage[] =
1368 "You do not have permission to use '%s'. Be sure to declare"
1369 " in your manifest what permissions you need.";
1370 std::string error_msg = base::StringPrintf(kMessage, function_name.c_str());
1371 APIActivityLogger::LogBlockedCall(context->extension()->id(),
1372 function_name);
1373 v8::ThrowException(
1374 v8::Exception::Error(v8::String::New(error_msg.c_str())));
1375 return false;
1376 }
1377
1378 if (ExtensionAPI::GetSharedInstance()->IsPrivileged(function_name) &&
1379 context->context_type() != Feature::BLESSED_EXTENSION_CONTEXT) {
1380 static const char kMessage[] =
1381 "%s can only be used in an extension process.";
1382 std::string error_msg = base::StringPrintf(kMessage, function_name.c_str());
1383 v8::ThrowException(
1384 v8::Exception::Error(v8::String::New(error_msg.c_str())));
1385 return false;
1386 }
1387
1388 // Theoretically we could end up with bindings being injected into sandboxed 1381 // Theoretically we could end up with bindings being injected into sandboxed
1389 // frames, for example content scripts. Don't let them execute API functions. 1382 // frames, for example content scripts. Don't let them execute API functions.
1390 WebKit::WebFrame* frame = context->web_frame(); 1383 WebKit::WebFrame* frame = context->web_frame();
1391 ExtensionURLInfo url_info(frame->document().securityOrigin(), 1384 ExtensionURLInfo url_info(frame->document().securityOrigin(),
1392 UserScriptSlave::GetDataSourceURLForFrame(frame)); 1385 UserScriptSlave::GetDataSourceURLForFrame(frame));
1393 if (extensions_.IsSandboxedPage(url_info)) { 1386 if (extensions_.IsSandboxedPage(url_info)) {
1394 static const char kMessage[] = 1387 static const char kMessage[] =
1395 "%s cannot be used within a sandboxed frame."; 1388 "%s cannot be used within a sandboxed frame.";
1396 std::string error_msg = base::StringPrintf(kMessage, function_name.c_str()); 1389 std::string error_msg = base::StringPrintf(kMessage, function_name.c_str());
1397 v8::ThrowException( 1390 v8::ThrowException(
1398 v8::Exception::Error(v8::String::New(error_msg.c_str()))); 1391 v8::Exception::Error(v8::String::New(error_msg.c_str())));
1399 return false; 1392 return false;
1400 } 1393 }
1401 1394
1402 return true; 1395 Feature::Availability availability = context->GetAvailability(function_name);
1396 if (!availability.is_available()) {
1397 v8::ThrowException(v8::Exception::Error(
1398 v8::String::New(availability.message().c_str())));
1399 }
1400
1401 return availability.is_available();
1403 } 1402 }
1404 1403
1405 void Dispatcher::DispatchEvent(const std::string& extension_id, 1404 void Dispatcher::DispatchEvent(const std::string& extension_id,
1406 const std::string& event_name) const { 1405 const std::string& event_name) const {
1407 base::ListValue args; 1406 base::ListValue args;
1408 args.Set(0, new base::StringValue(event_name)); 1407 args.Set(0, new base::StringValue(event_name));
1409 args.Set(1, new base::ListValue()); 1408 args.Set(1, new base::ListValue());
1410 v8_context_set_.ForEach( 1409 v8_context_set_.ForEach(
1411 extension_id, 1410 extension_id,
1412 NULL, // all render views 1411 NULL, // all render views
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
1448 RenderView* background_view = 1447 RenderView* background_view =
1449 ExtensionHelper::GetBackgroundPage(extension_id); 1448 ExtensionHelper::GetBackgroundPage(extension_id);
1450 if (background_view) { 1449 if (background_view) {
1451 background_view->Send(new ExtensionHostMsg_EventAck( 1450 background_view->Send(new ExtensionHostMsg_EventAck(
1452 background_view->GetRoutingID())); 1451 background_view->GetRoutingID()));
1453 } 1452 }
1454 } 1453 }
1455 } 1454 }
1456 1455
1457 } // namespace extensions 1456 } // namespace extensions
OLDNEW
« no previous file with comments | « chrome/renderer/extensions/chrome_v8_context.cc ('k') | chrome/renderer/extensions/event_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698