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

Side by Side Diff: chrome/browser/extensions/extension_service.cc

Issue 7432006: Add an experimental permissions API for extensions. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix clang Created 9 years, 5 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) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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/browser/extensions/extension_service.h" 5 #include "chrome/browser/extensions/extension_service.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <set> 8 #include <set>
9 9
10 #include "base/basictypes.h" 10 #include "base/basictypes.h"
(...skipping 534 matching lines...) Expand 10 before | Expand all | Expand 10 after
545 : weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)), 545 : weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)),
546 method_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)), 546 method_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)),
547 profile_(profile), 547 profile_(profile),
548 extension_prefs_(extension_prefs), 548 extension_prefs_(extension_prefs),
549 pending_extension_manager_(*ALLOW_THIS_IN_INITIALIZER_LIST(this)), 549 pending_extension_manager_(*ALLOW_THIS_IN_INITIALIZER_LIST(this)),
550 install_directory_(install_directory), 550 install_directory_(install_directory),
551 extensions_enabled_(extensions_enabled), 551 extensions_enabled_(extensions_enabled),
552 show_extensions_prompts_(true), 552 show_extensions_prompts_(true),
553 ready_(false), 553 ready_(false),
554 toolbar_model_(ALLOW_THIS_IN_INITIALIZER_LIST(this)), 554 toolbar_model_(ALLOW_THIS_IN_INITIALIZER_LIST(this)),
555 permissions_manager_(ALLOW_THIS_IN_INITIALIZER_LIST(this)),
555 apps_promo_(profile->GetPrefs()), 556 apps_promo_(profile->GetPrefs()),
556 event_routers_initialized_(false) { 557 event_routers_initialized_(false) {
557 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 558 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
558 559
559 // Figure out if extension installation should be enabled. 560 // Figure out if extension installation should be enabled.
560 if (command_line->HasSwitch(switches::kDisableExtensions)) { 561 if (command_line->HasSwitch(switches::kDisableExtensions)) {
561 extensions_enabled_ = false; 562 extensions_enabled_ = false;
562 } else if (profile->GetPrefs()->GetBoolean(prefs::kDisableExtensions)) { 563 } else if (profile->GetPrefs()->GetBoolean(prefs::kDisableExtensions)) {
563 extensions_enabled_ = false; 564 extensions_enabled_ = false;
564 } 565 }
(...skipping 402 matching lines...) Expand 10 before | Expand all | Expand 10 after
967 extension); 968 extension);
968 terminated_extensions_.erase(iter); 969 terminated_extensions_.erase(iter);
969 } 970 }
970 971
971 NotifyExtensionUnloaded(extension, UnloadedExtensionInfo::DISABLE); 972 NotifyExtensionUnloaded(extension, UnloadedExtensionInfo::DISABLE);
972 } 973 }
973 974
974 void ExtensionService::GrantPermissions(const Extension* extension) { 975 void ExtensionService::GrantPermissions(const Extension* extension) {
975 CHECK(extension); 976 CHECK(extension);
976 977
977 // We only maintain the granted permissions prefs for INTERNAL extensions. 978 // We only maintain the granted permissions prefs for extensions that can't
978 CHECK_EQ(Extension::INTERNAL, extension->location()); 979 // silently increase their permissions.
980 if (extension->CanSilentlyIncreasePermissions())
981 return;
979 982
980 extension_prefs_->AddGrantedPermissions(extension->id(), 983 extension_prefs_->AddGrantedPermissions(extension->id(),
981 extension->permission_set()); 984 extension->GetActivePermissions());
982 } 985 }
983 986
984 void ExtensionService::GrantPermissionsAndEnableExtension( 987 void ExtensionService::GrantPermissionsAndEnableExtension(
985 const Extension* extension) { 988 const Extension* extension) {
986 CHECK(extension); 989 CHECK(extension);
987 RecordPermissionMessagesHistogram( 990 RecordPermissionMessagesHistogram(
988 extension, "Extensions.Permissions_ReEnable"); 991 extension, "Extensions.Permissions_ReEnable");
989 GrantPermissions(extension); 992 GrantPermissions(extension);
990 extension_prefs_->SetDidExtensionEscalatePermissions(extension, false); 993 extension_prefs_->SetDidExtensionEscalatePermissions(extension, false);
991 EnableExtension(extension->id()); 994 EnableExtension(extension->id());
992 } 995 }
993 996
997 void ExtensionService::UpdateActivePermissions(
998 const Extension* extension,
999 const ExtensionPermissionSet* permissions) {
1000 extension_prefs()->SetActivePermissions(extension->id(), permissions);
1001 extension->SetActivePermissions(permissions);
1002 }
1003
994 void ExtensionService::LoadExtension(const FilePath& extension_path) { 1004 void ExtensionService::LoadExtension(const FilePath& extension_path) {
995 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, 1005 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
996 NewRunnableMethod(backend_.get(), 1006 NewRunnableMethod(backend_.get(),
997 &ExtensionServiceBackend::LoadSingleExtension, 1007 &ExtensionServiceBackend::LoadSingleExtension,
998 extension_path, true)); 1008 extension_path, true));
999 } 1009 }
1000 1010
1001 void ExtensionService::LoadExtensionFromCommandLine( 1011 void ExtensionService::LoadExtensionFromCommandLine(
1002 const FilePath& path_in) { 1012 const FilePath& path_in) {
1003 1013
(...skipping 345 matching lines...) Expand 10 before | Expand all | Expand 10 after
1349 Source<Profile>(profile_), 1359 Source<Profile>(profile_),
1350 Details<const Extension>(extension)); 1360 Details<const Extension>(extension));
1351 1361
1352 // Tell renderers about the new extension. 1362 // Tell renderers about the new extension.
1353 for (RenderProcessHost::iterator i(RenderProcessHost::AllHostsIterator()); 1363 for (RenderProcessHost::iterator i(RenderProcessHost::AllHostsIterator());
1354 !i.IsAtEnd(); i.Advance()) { 1364 !i.IsAtEnd(); i.Advance()) {
1355 RenderProcessHost* host = i.GetCurrentValue(); 1365 RenderProcessHost* host = i.GetCurrentValue();
1356 if (host->profile()->GetOriginalProfile() == 1366 if (host->profile()->GetOriginalProfile() ==
1357 profile_->GetOriginalProfile()) { 1367 profile_->GetOriginalProfile()) {
1358 host->Send( 1368 host->Send(
1359 new ExtensionMsg_Loaded(ExtensionMsg_Loaded_Params(extension))); 1369 new ExtensionMsg_Loaded(ExtensionMsg_Loaded_Params(
1370 extension, extension->GetActivePermissions())));
1360 } 1371 }
1361 } 1372 }
1362 1373
1363 // Tell a random-ass collection of other subsystems about the new extension. 1374 // Tell a random-ass collection of other subsystems about the new extension.
1364 // TODO(aa): What should we do with all this goop? Can it move into the 1375 // TODO(aa): What should we do with all this goop? Can it move into the
1365 // relevant objects via EXTENSION_LOADED? 1376 // relevant objects via EXTENSION_LOADED?
1366 1377
1367 profile_->GetExtensionSpecialStoragePolicy()-> 1378 profile_->GetExtensionSpecialStoragePolicy()->
1368 GrantRightsForExtension(extension); 1379 GrantRightsForExtension(extension);
1369 1380
(...skipping 587 matching lines...) Expand 10 before | Expand all | Expand 10 after
1957 1968
1958 // If a terminated extension is loaded, remove it from the terminated list. 1969 // If a terminated extension is loaded, remove it from the terminated list.
1959 UntrackTerminatedExtension(extension->id()); 1970 UntrackTerminatedExtension(extension->id());
1960 1971
1961 // If the extension was disabled for a reload, then enable it. 1972 // If the extension was disabled for a reload, then enable it.
1962 if (disabled_extension_paths_.erase(extension->id()) > 0) 1973 if (disabled_extension_paths_.erase(extension->id()) > 0)
1963 EnableExtension(extension->id()); 1974 EnableExtension(extension->id());
1964 1975
1965 // Check if the extension's privileges have changed and disable the 1976 // Check if the extension's privileges have changed and disable the
1966 // extension if necessary. 1977 // extension if necessary.
1967 DisableIfPrivilegeIncrease(extension); 1978 InitializePermissions(extension);
1968 1979
1969 bool disabled = Extension::UserMayDisable(extension->location()) && 1980 bool disabled = Extension::UserMayDisable(extension->location()) &&
1970 extension_prefs_->GetExtensionState(extension->id()) == 1981 extension_prefs_->GetExtensionState(extension->id()) ==
1971 Extension::DISABLED; 1982 Extension::DISABLED;
1972 if (disabled) { 1983 if (disabled) {
1973 disabled_extensions_.push_back(scoped_extension); 1984 disabled_extensions_.push_back(scoped_extension);
1974 // TODO(aa): This seems dodgy. It seems that AddExtension() could get called 1985 // TODO(aa): This seems dodgy. It seems that AddExtension() could get called
1975 // with a disabled extension for other reasons other than that an update was 1986 // with a disabled extension for other reasons other than that an update was
1976 // disabled. 1987 // disabled.
1977 NotificationService::current()->Notify( 1988 NotificationService::current()->Notify(
1978 chrome::NOTIFICATION_EXTENSION_UPDATE_DISABLED, 1989 chrome::NOTIFICATION_EXTENSION_UPDATE_DISABLED,
1979 Source<Profile>(profile_), 1990 Source<Profile>(profile_),
1980 Details<const Extension>(extension)); 1991 Details<const Extension>(extension));
1981 return; 1992 return;
1982 } 1993 }
1983 1994
1984 extensions_.push_back(scoped_extension); 1995 extensions_.push_back(scoped_extension);
1985 NotifyExtensionLoaded(extension); 1996 NotifyExtensionLoaded(extension);
1986 } 1997 }
1987 1998
1988 void ExtensionService::DisableIfPrivilegeIncrease(const Extension* extension) { 1999 void ExtensionService::InitializePermissions(const Extension* extension) {
2000 // If the extension has used the optional permissions API, it will have a
2001 // custom set of active permissions defined in the extension prefs. Here,
2002 // we update the extension's active permissions based on the prefs.
2003 scoped_refptr<ExtensionPermissionSet> active_permissions =
2004 extension_prefs()->GetActivePermissions(extension->id());
2005
2006 if (active_permissions.get()) {
2007 // We restrict the active permissions to be within the bounds defined in the
2008 // extension's manifest.
2009 // a) active permissions must be a subset of optional + default permissions
2010 // b) active permissions must contains all default permissions
2011 scoped_refptr<ExtensionPermissionSet> total_permissions =
2012 ExtensionPermissionSet::CreateUnion(
2013 extension->required_permission_set(),
2014 extension->optional_permission_set());
2015
2016 // Make sure the active permissions contain no more than optional + default.
2017 scoped_refptr<ExtensionPermissionSet> adjusted_active =
2018 ExtensionPermissionSet::CreateIntersection(
2019 total_permissions.get(), active_permissions.get());
2020
2021 // Make sure the active permissions contain the default permissions.
2022 adjusted_active = ExtensionPermissionSet::CreateUnion(
2023 extension->required_permission_set(), adjusted_active.get());
2024
2025 UpdateActivePermissions(extension, adjusted_active);
2026 }
2027
1989 // We keep track of all permissions the user has granted each extension. 2028 // We keep track of all permissions the user has granted each extension.
1990 // This allows extensions to gracefully support backwards compatibility 2029 // This allows extensions to gracefully support backwards compatibility
1991 // by including unknown permissions in their manifests. When the user 2030 // by including unknown permissions in their manifests. When the user
1992 // installs the extension, only the recognized permissions are recorded. 2031 // installs the extension, only the recognized permissions are recorded.
1993 // When the unknown permissions become recognized (e.g., through browser 2032 // When the unknown permissions become recognized (e.g., through browser
1994 // upgrade), we can prompt the user to accept these new permissions. 2033 // upgrade), we can prompt the user to accept these new permissions.
1995 // Extensions can also silently upgrade to less permissions, and then 2034 // Extensions can also silently upgrade to less permissions, and then
1996 // silently upgrade to a version that adds these permissions back. 2035 // silently upgrade to a version that adds these permissions back.
1997 // 2036 //
1998 // For example, pretend that Chrome 10 includes a permission "omnibox" 2037 // For example, pretend that Chrome 10 includes a permission "omnibox"
1999 // for an API that adds suggestions to the omnibox. An extension can 2038 // for an API that adds suggestions to the omnibox. An extension can
2000 // maintain backwards compatibility while still having "omnibox" in the 2039 // maintain backwards compatibility while still having "omnibox" in the
2001 // manifest. If a user installs the extension on Chrome 9, the browser 2040 // manifest. If a user installs the extension on Chrome 9, the browser
2002 // will record the permissions it recognized, not including "omnibox." 2041 // will record the permissions it recognized, not including "omnibox."
2003 // When upgrading to Chrome 10, "omnibox" will be recognized and Chrome 2042 // When upgrading to Chrome 10, "omnibox" will be recognized and Chrome
2004 // will disable the extension and prompt the user to approve the increase 2043 // will disable the extension and prompt the user to approve the increase
2005 // in privileges. The extension could then release a new version that 2044 // in privileges. The extension could then release a new version that
2006 // removes the "omnibox" permission. When the user upgrades, Chrome will 2045 // removes the "omnibox" permission. When the user upgrades, Chrome will
2007 // still remember that "omnibox" had been granted, so that if the 2046 // still remember that "omnibox" had been granted, so that if the
2008 // extension once again includes "omnibox" in an upgrade, the extension 2047 // extension once again includes "omnibox" in an upgrade, the extension
2009 // can upgrade without requiring this user's approval. 2048 // can upgrade without requiring this user's approval.
2010 const Extension* old = GetExtensionByIdInternal(extension->id(), 2049 const Extension* old = GetExtensionByIdInternal(extension->id(),
2011 true, true, false); 2050 true, true, false);
2012 bool is_extension_upgrade = old != NULL; 2051 bool is_extension_upgrade = old != NULL;
2013 bool is_privilege_increase = false; 2052 bool is_privilege_increase = false;
2014 2053
2015 // We only record the granted permissions for INTERNAL extensions, since 2054 // We only need to compare the granted permissions to the current permissions
2016 // they can't silently increase privileges. 2055 // if the extension is not allowed to silently increase its permissions.
2017 if (extension->location() == Extension::INTERNAL) { 2056 if (!extension->CanSilentlyIncreasePermissions()) {
2018 // Add all the recognized permissions if the granted permissions list 2057 // Add all the recognized permissions if the granted permissions list
2019 // hasn't been initialized yet. 2058 // hasn't been initialized yet.
2020 scoped_ptr<ExtensionPermissionSet> granted_permissions( 2059 scoped_refptr<ExtensionPermissionSet> granted_permissions =
2021 extension_prefs_->GetGrantedPermissions(extension->id())); 2060 extension_prefs_->GetGrantedPermissions(extension->id());
2022 CHECK(granted_permissions.get()); 2061 CHECK(granted_permissions.get());
2023 2062
2024 // Here, we check if an extension's privileges have increased in a manner 2063 // Here, we check if an extension's privileges have increased in a manner
2025 // that requires the user's approval. This could occur because the browser 2064 // that requires the user's approval. This could occur because the browser
2026 // upgraded and recognized additional privileges, or an extension upgrades 2065 // upgraded and recognized additional privileges, or an extension upgrades
2027 // to a version that requires additional privileges. 2066 // to a version that requires additional privileges.
2028 is_privilege_increase = 2067 is_privilege_increase =
2029 granted_permissions->HasLessPrivilegesThan(extension->permission_set()); 2068 granted_permissions->HasLessPrivilegesThan(
2069 extension->GetActivePermissions());
2030 } 2070 }
2031 2071
2032 if (is_extension_upgrade) { 2072 if (is_extension_upgrade) {
2033 // Other than for unpacked extensions, CrxInstaller should have guaranteed 2073 // Other than for unpacked extensions, CrxInstaller should have guaranteed
2034 // that we aren't downgrading. 2074 // that we aren't downgrading.
2035 if (extension->location() != Extension::LOAD) 2075 if (extension->location() != Extension::LOAD)
2036 CHECK(extension->version()->CompareTo(*(old->version())) >= 0); 2076 CHECK(extension->version()->CompareTo(*(old->version())) >= 0);
2037 2077
2038 // Extensions get upgraded if the privileges are allowed to increase or 2078 // Extensions get upgraded if the privileges are allowed to increase or
2039 // the privileges haven't increased. 2079 // the privileges haven't increased.
(...skipping 331 matching lines...) Expand 10 before | Expand all | Expand 10 after
2371 process->Send(new ExtensionMsg_SetFunctionNames(function_names)); 2411 process->Send(new ExtensionMsg_SetFunctionNames(function_names));
2372 2412
2373 // Scripting whitelist. This is modified by tests and must be communicated 2413 // Scripting whitelist. This is modified by tests and must be communicated
2374 // to renderers. 2414 // to renderers.
2375 process->Send(new ExtensionMsg_SetScriptingWhitelist( 2415 process->Send(new ExtensionMsg_SetScriptingWhitelist(
2376 *Extension::GetScriptingWhitelist())); 2416 *Extension::GetScriptingWhitelist()));
2377 2417
2378 // Loaded extensions. 2418 // Loaded extensions.
2379 for (size_t i = 0; i < extensions_.size(); ++i) { 2419 for (size_t i = 0; i < extensions_.size(); ++i) {
2380 process->Send(new ExtensionMsg_Loaded( 2420 process->Send(new ExtensionMsg_Loaded(
2381 ExtensionMsg_Loaded_Params(extensions_[i]))); 2421 ExtensionMsg_Loaded_Params(
2422 extensions_[i], extensions_[i]->GetActivePermissions())));
2382 } 2423 }
2383 break; 2424 break;
2384 } 2425 }
2385 case content::NOTIFICATION_RENDERER_PROCESS_TERMINATED: { 2426 case content::NOTIFICATION_RENDERER_PROCESS_TERMINATED: {
2386 RenderProcessHost* process = Source<RenderProcessHost>(source).ptr(); 2427 RenderProcessHost* process = Source<RenderProcessHost>(source).ptr();
2387 installed_app_hosts_.erase(process->id()); 2428 installed_app_hosts_.erase(process->id());
2388 break; 2429 break;
2389 } 2430 }
2390 case chrome::NOTIFICATION_PREF_CHANGED: { 2431 case chrome::NOTIFICATION_PREF_CHANGED: {
2391 std::string* pref_name = Details<std::string>(details).ptr(); 2432 std::string* pref_name = Details<std::string>(details).ptr();
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
2519 2560
2520 ExtensionService::NaClModuleInfoList::iterator 2561 ExtensionService::NaClModuleInfoList::iterator
2521 ExtensionService::FindNaClModule(const GURL& url) { 2562 ExtensionService::FindNaClModule(const GURL& url) {
2522 for (NaClModuleInfoList::iterator iter = nacl_module_list_.begin(); 2563 for (NaClModuleInfoList::iterator iter = nacl_module_list_.begin();
2523 iter != nacl_module_list_.end(); ++iter) { 2564 iter != nacl_module_list_.end(); ++iter) {
2524 if (iter->url == url) 2565 if (iter->url == url)
2525 return iter; 2566 return iter;
2526 } 2567 }
2527 return nacl_module_list_.end(); 2568 return nacl_module_list_.end();
2528 } 2569 }
OLDNEW
« no previous file with comments | « chrome/browser/extensions/extension_service.h ('k') | chrome/browser/extensions/extension_service_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698