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

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

Issue 5968009: Change extension unload notification to indicate updates.... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 10 years 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) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 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 8
9 #include "base/basictypes.h" 9 #include "base/basictypes.h"
10 #include "base/command_line.h" 10 #include "base/command_line.h"
(...skipping 875 matching lines...) Expand 10 before | Expand all | Expand 10 after
886 886
887 // Also copy the extension identifier since the reference might have been 887 // Also copy the extension identifier since the reference might have been
888 // obtained via Extension::id(). 888 // obtained via Extension::id().
889 std::string extension_id_copy(extension_id); 889 std::string extension_id_copy(extension_id);
890 890
891 if (profile_->GetTemplateURLModel()) 891 if (profile_->GetTemplateURLModel())
892 profile_->GetTemplateURLModel()->UnregisterExtensionKeyword(extension); 892 profile_->GetTemplateURLModel()->UnregisterExtensionKeyword(extension);
893 893
894 // Unload before doing more cleanup to ensure that nothing is hanging on to 894 // Unload before doing more cleanup to ensure that nothing is hanging on to
895 // any of these resources. 895 // any of these resources.
896 UnloadExtension(extension_id); 896 UnloadExtension(extension_id, UnloadedExtensionInfo::UNINSTALL);
897 897
898 extension_prefs_->OnExtensionUninstalled(extension_id_copy, location, 898 extension_prefs_->OnExtensionUninstalled(extension_id_copy, location,
899 external_uninstall); 899 external_uninstall);
900 900
901 // Tell the backend to start deleting installed extensions on the file thread. 901 // Tell the backend to start deleting installed extensions on the file thread.
902 if (Extension::LOAD != location) { 902 if (Extension::LOAD != location) {
903 BrowserThread::PostTask( 903 BrowserThread::PostTask(
904 BrowserThread::FILE, FROM_HERE, 904 BrowserThread::FILE, FROM_HERE,
905 NewRunnableFunction( 905 NewRunnableFunction(
906 &extension_file_util::UninstallExtension, 906 &extension_file_util::UninstallExtension,
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
964 // Move it over to the disabled list. 964 // Move it over to the disabled list.
965 disabled_extensions_.push_back(make_scoped_refptr(extension)); 965 disabled_extensions_.push_back(make_scoped_refptr(extension));
966 ExtensionList::iterator iter = std::find(extensions_.begin(), 966 ExtensionList::iterator iter = std::find(extensions_.begin(),
967 extensions_.end(), 967 extensions_.end(),
968 extension); 968 extension);
969 extensions_.erase(iter); 969 extensions_.erase(iter);
970 970
971 ExtensionDOMUI::UnregisterChromeURLOverrides(profile_, 971 ExtensionDOMUI::UnregisterChromeURLOverrides(profile_,
972 extension->GetChromeURLOverrides()); 972 extension->GetChromeURLOverrides());
973 973
974 NotifyExtensionUnloaded(extension); 974 NotifyExtensionUnloaded(extension, UnloadedExtensionInfo::DISABLE);
975 UpdateActiveExtensionsInCrashReporter(); 975 UpdateActiveExtensionsInCrashReporter();
976 } 976 }
977 977
978 void ExtensionService::GrantPermissions(const Extension* extension) { 978 void ExtensionService::GrantPermissions(const Extension* extension) {
979 CHECK(extension); 979 CHECK(extension);
980 980
981 // We only maintain the granted permissions prefs for INTERNAL extensions. 981 // We only maintain the granted permissions prefs for INTERNAL extensions.
982 CHECK(extension->location() == Extension::INTERNAL); 982 CHECK(extension->location() == Extension::INTERNAL);
983 983
984 ExtensionExtent effective_hosts = extension->GetEffectiveHostPermissions(); 984 ExtensionExtent effective_hosts = extension->GetEffectiveHostPermissions();
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after
1231 if (extension->is_app()) 1231 if (extension->is_app())
1232 GrantProtectedStorage(extension); 1232 GrantProtectedStorage(extension);
1233 } 1233 }
1234 1234
1235 NotificationService::current()->Notify( 1235 NotificationService::current()->Notify(
1236 NotificationType::EXTENSION_LOADED, 1236 NotificationType::EXTENSION_LOADED,
1237 Source<Profile>(profile_), 1237 Source<Profile>(profile_),
1238 Details<const Extension>(extension)); 1238 Details<const Extension>(extension));
1239 } 1239 }
1240 1240
1241 void ExtensionService::NotifyExtensionUnloaded(const Extension* extension) { 1241 void ExtensionService::NotifyExtensionUnloaded(
1242 const Extension* extension, UnloadedExtensionInfo::Reason reason) {
1243 UnloadedExtensionInfo details(extension, reason);
1242 NotificationService::current()->Notify( 1244 NotificationService::current()->Notify(
1243 NotificationType::EXTENSION_UNLOADED, 1245 NotificationType::EXTENSION_UNLOADED,
1244 Source<Profile>(profile_), 1246 Source<Profile>(profile_),
1245 Details<const Extension>(extension)); 1247 Details<UnloadedExtensionInfo>(&details));
1246 1248
1247 if (profile_) { 1249 if (profile_) {
1248 profile_->UnregisterExtensionWithRequestContexts(extension); 1250 profile_->UnregisterExtensionWithRequestContexts(extension);
1249 1251
1250 // Check if this permission required unlimited storage quota, reset its 1252 // Check if this permission required unlimited storage quota, reset its
1251 // in-memory quota. 1253 // in-memory quota.
1252 if (extension->HasApiPermission(Extension::kUnlimitedStoragePermission)) 1254 if (extension->HasApiPermission(Extension::kUnlimitedStoragePermission))
1253 RevokeUnlimitedStorage(extension); 1255 RevokeUnlimitedStorage(extension);
1254 1256
1255 // If this is an app, then stop protecting its storage so it can be deleted. 1257 // If this is an app, then stop protecting its storage so it can be deleted.
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
1365 iter != extensions_.end(); ++iter) { 1367 iter != extensions_.end(); ++iter) {
1366 const Extension* extension = (*iter); 1368 const Extension* extension = (*iter);
1367 if (blacklist_set.find(extension->id()) != blacklist_set.end()) { 1369 if (blacklist_set.find(extension->id()) != blacklist_set.end()) {
1368 to_be_removed.push_back(extension->id()); 1370 to_be_removed.push_back(extension->id());
1369 } 1371 }
1370 } 1372 }
1371 1373
1372 // UnloadExtension will change the extensions_ list. So, we should 1374 // UnloadExtension will change the extensions_ list. So, we should
1373 // call it outside the iterator loop. 1375 // call it outside the iterator loop.
1374 for (unsigned int i = 0; i < to_be_removed.size(); ++i) { 1376 for (unsigned int i = 0; i < to_be_removed.size(); ++i) {
1375 UnloadExtension(to_be_removed[i]); 1377 UnloadExtension(to_be_removed[i], UnloadedExtensionInfo::DISABLE);
1376 } 1378 }
1377 } 1379 }
1378 1380
1379 void ExtensionService::DestroyingProfile() { 1381 void ExtensionService::DestroyingProfile() {
1380 pref_change_registrar_.RemoveAll(); 1382 pref_change_registrar_.RemoveAll();
1381 profile_ = NULL; 1383 profile_ = NULL;
1382 toolbar_model_.DestroyingProfile(); 1384 toolbar_model_.DestroyingProfile();
1383 } 1385 }
1384 1386
1385 ExtensionPrefs* ExtensionService::extension_prefs() { 1387 ExtensionPrefs* ExtensionService::extension_prefs() {
1386 return extension_prefs_; 1388 return extension_prefs_;
1387 } 1389 }
1388 1390
1389 void ExtensionService::CheckAdminBlacklist() { 1391 void ExtensionService::CheckAdminBlacklist() {
1390 std::vector<std::string> to_be_removed; 1392 std::vector<std::string> to_be_removed;
1391 // Loop through extensions list, unload installed extensions. 1393 // Loop through extensions list, unload installed extensions.
1392 for (ExtensionList::const_iterator iter = extensions_.begin(); 1394 for (ExtensionList::const_iterator iter = extensions_.begin();
1393 iter != extensions_.end(); ++iter) { 1395 iter != extensions_.end(); ++iter) {
1394 const Extension* extension = (*iter); 1396 const Extension* extension = (*iter);
1395 if (!extension_prefs_->IsExtensionAllowedByPolicy(extension->id())) 1397 if (!extension_prefs_->IsExtensionAllowedByPolicy(extension->id()))
1396 to_be_removed.push_back(extension->id()); 1398 to_be_removed.push_back(extension->id());
1397 } 1399 }
1398 1400
1399 // UnloadExtension will change the extensions_ list. So, we should 1401 // UnloadExtension will change the extensions_ list. So, we should
1400 // call it outside the iterator loop. 1402 // call it outside the iterator loop.
1401 for (unsigned int i = 0; i < to_be_removed.size(); ++i) 1403 for (unsigned int i = 0; i < to_be_removed.size(); ++i)
1402 UnloadExtension(to_be_removed[i]); 1404 UnloadExtension(to_be_removed[i], UnloadedExtensionInfo::DISABLE);
1403 } 1405 }
1404 1406
1405 bool ExtensionService::IsIncognitoEnabled(const Extension* extension) { 1407 bool ExtensionService::IsIncognitoEnabled(const Extension* extension) {
1406 // If this is a component extension we always allow it to work in incognito 1408 // If this is a component extension we always allow it to work in incognito
1407 // mode. 1409 // mode.
1408 if (extension->location() == Extension::COMPONENT) 1410 if (extension->location() == Extension::COMPONENT)
1409 return true; 1411 return true;
1410 1412
1411 // Check the prefs. 1413 // Check the prefs.
1412 return extension_prefs_->IsIncognitoEnabled(extension->id()); 1414 return extension_prefs_->IsIncognitoEnabled(extension->id());
1413 } 1415 }
1414 1416
1415 void ExtensionService::SetIsIncognitoEnabled(const Extension* extension, 1417 void ExtensionService::SetIsIncognitoEnabled(const Extension* extension,
1416 bool enabled) { 1418 bool enabled) {
1417 extension_prefs_->SetIsIncognitoEnabled(extension->id(), enabled); 1419 extension_prefs_->SetIsIncognitoEnabled(extension->id(), enabled);
1418 1420
1419 // Broadcast unloaded and loaded events to update browser state. Only bother 1421 // Broadcast unloaded and loaded events to update browser state. Only bother
1420 // if the extension is actually enabled, since there is no UI otherwise. 1422 // if the extension is actually enabled, since there is no UI otherwise.
1421 bool is_enabled = std::find(extensions_.begin(), extensions_.end(), 1423 bool is_enabled = std::find(extensions_.begin(), extensions_.end(),
1422 extension) != extensions_.end(); 1424 extension) != extensions_.end();
1423 if (is_enabled) { 1425 if (is_enabled) {
1424 NotifyExtensionUnloaded(extension); 1426 NotifyExtensionUnloaded(extension, UnloadedExtensionInfo::DISABLE);
1425 NotifyExtensionLoaded(extension); 1427 NotifyExtensionLoaded(extension);
1426 } 1428 }
1427 } 1429 }
1428 1430
1429 bool ExtensionService::CanCrossIncognito(const Extension* extension) { 1431 bool ExtensionService::CanCrossIncognito(const Extension* extension) {
1430 // We allow the extension to see events and data from another profile iff it 1432 // We allow the extension to see events and data from another profile iff it
1431 // uses "spanning" behavior and it has incognito access. "split" mode 1433 // uses "spanning" behavior and it has incognito access. "split" mode
1432 // extensions only see events for a matching profile. 1434 // extensions only see events for a matching profile.
1433 return IsIncognitoEnabled(extension) && !extension->incognito_split_mode(); 1435 return IsIncognitoEnabled(extension) && !extension->incognito_split_mode();
1434 } 1436 }
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
1473 list_copy = static_cast<ListValue*>(list_pref->DeepCopy()); 1475 list_copy = static_cast<ListValue*>(list_pref->DeepCopy());
1474 BrowserThread::PostTask( 1476 BrowserThread::PostTask(
1475 BrowserThread::FILE, FROM_HERE, 1477 BrowserThread::FILE, FROM_HERE,
1476 NewRunnableMethod( 1478 NewRunnableMethod(
1477 backend_.get(), 1479 backend_.get(),
1478 &ExtensionServiceBackend::UpdateExternalPolicyExtensionProvider, 1480 &ExtensionServiceBackend::UpdateExternalPolicyExtensionProvider,
1479 scoped_refptr<RefCountedList>( 1481 scoped_refptr<RefCountedList>(
1480 new RefCountedList(list_copy)))); 1482 new RefCountedList(list_copy))));
1481 } 1483 }
1482 1484
1483 void ExtensionService::UnloadExtension(const std::string& extension_id) { 1485 void ExtensionService::UnloadExtension(
1486 const std::string& extension_id,
1487 UnloadedExtensionInfo::Reason reason) {
1484 // Make sure the extension gets deleted after we return from this function. 1488 // Make sure the extension gets deleted after we return from this function.
1485 scoped_refptr<const Extension> extension( 1489 scoped_refptr<const Extension> extension(
1486 GetExtensionByIdInternal(extension_id, true, true)); 1490 GetExtensionByIdInternal(extension_id, true, true));
1487 1491
1488 // This method can be called via PostTask, so the extension may have been 1492 // This method can be called via PostTask, so the extension may have been
1489 // unloaded by the time this runs. 1493 // unloaded by the time this runs.
1490 if (!extension) 1494 if (!extension)
1491 return; 1495 return;
1492 1496
1493 // Keep information about the extension so that we can reload it later 1497 // Keep information about the extension so that we can reload it later
1494 // even if it's not permanently installed. 1498 // even if it's not permanently installed.
1495 unloaded_extension_paths_[extension->id()] = extension->path(); 1499 unloaded_extension_paths_[extension->id()] = extension->path();
1496 1500
1497 // Clean up if the extension is meant to be enabled after a reload. 1501 // Clean up if the extension is meant to be enabled after a reload.
1498 disabled_extension_paths_.erase(extension->id()); 1502 disabled_extension_paths_.erase(extension->id());
1499 1503
1500 // Clean up runtime data. 1504 // Clean up runtime data.
1501 extension_runtime_data_.erase(extension_id); 1505 extension_runtime_data_.erase(extension_id);
1502 1506
1503 ExtensionDOMUI::UnregisterChromeURLOverrides(profile_, 1507 ExtensionDOMUI::UnregisterChromeURLOverrides(profile_,
1504 extension->GetChromeURLOverrides()); 1508 extension->GetChromeURLOverrides());
1505 1509
1506 ExtensionList::iterator iter = std::find(disabled_extensions_.begin(), 1510 ExtensionList::iterator iter = std::find(disabled_extensions_.begin(),
1507 disabled_extensions_.end(), 1511 disabled_extensions_.end(),
1508 extension.get()); 1512 extension.get());
1509 if (iter != disabled_extensions_.end()) { 1513 if (iter != disabled_extensions_.end()) {
1514 UnloadedExtensionInfo details(extension, reason);
1515 details.already_disabled = true;
1510 disabled_extensions_.erase(iter); 1516 disabled_extensions_.erase(iter);
1511 NotificationService::current()->Notify( 1517 NotificationService::current()->Notify(
1512 NotificationType::EXTENSION_UNLOADED_DISABLED, 1518 NotificationType::EXTENSION_UNLOADED,
1513 Source<Profile>(profile_), 1519 Source<Profile>(profile_),
1514 Details<const Extension>(extension.get())); 1520 Details<UnloadedExtensionInfo>(&details));
1515 return; 1521 return;
1516 } 1522 }
1517 1523
1518 iter = std::find(extensions_.begin(), extensions_.end(), extension.get()); 1524 iter = std::find(extensions_.begin(), extensions_.end(), extension.get());
1519 1525
1520 // Remove the extension from our list. 1526 // Remove the extension from our list.
1521 extensions_.erase(iter); 1527 extensions_.erase(iter);
1522 1528
1523 NotifyExtensionUnloaded(extension.get()); 1529 NotifyExtensionUnloaded(extension.get(), reason);
1524 UpdateActiveExtensionsInCrashReporter(); 1530 UpdateActiveExtensionsInCrashReporter();
1525 } 1531 }
1526 1532
1527 void ExtensionService::UnloadAllExtensions() { 1533 void ExtensionService::UnloadAllExtensions() {
1528 extensions_.clear(); 1534 extensions_.clear();
1529 disabled_extensions_.clear(); 1535 disabled_extensions_.clear();
1530 extension_runtime_data_.clear(); 1536 extension_runtime_data_.clear();
1531 1537
1532 // TODO(erikkay) should there be a notification for this? We can't use 1538 // TODO(erikkay) should there be a notification for this? We can't use
1533 // EXTENSION_UNLOADED since that implies that the extension has been disabled 1539 // EXTENSION_UNLOADED since that implies that the extension has been disabled
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after
1699 1705
1700 // Extensions get upgraded if the privileges are allowed to increase or 1706 // Extensions get upgraded if the privileges are allowed to increase or
1701 // the privileges haven't increased. 1707 // the privileges haven't increased.
1702 if (!is_privilege_increase) { 1708 if (!is_privilege_increase) {
1703 SetBeingUpgraded(old, true); 1709 SetBeingUpgraded(old, true);
1704 SetBeingUpgraded(extension, true); 1710 SetBeingUpgraded(extension, true);
1705 } 1711 }
1706 1712
1707 // To upgrade an extension in place, unload the old one and 1713 // To upgrade an extension in place, unload the old one and
1708 // then load the new one. 1714 // then load the new one.
1709 UnloadExtension(old->id()); 1715 UnloadExtension(old->id(), UnloadedExtensionInfo::UPDATE);
1710 old = NULL; 1716 old = NULL;
1711 } 1717 }
1712 1718
1713 // Extension has changed permissions significantly. Disable it. A 1719 // Extension has changed permissions significantly. Disable it. A
1714 // notification should be sent by the caller. 1720 // notification should be sent by the caller.
1715 if (is_privilege_increase) { 1721 if (is_privilege_increase) {
1716 extension_prefs_->SetExtensionState(extension, Extension::DISABLED); 1722 extension_prefs_->SetExtensionState(extension, Extension::DISABLED);
1717 extension_prefs_->SetDidExtensionEscalatePermissions(extension, true); 1723 extension_prefs_->SetDidExtensionEscalatePermissions(extension, true);
1718 } 1724 }
1719 } 1725 }
(...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after
1989 if (profile_ != Source<Profile>(source).ptr()->GetOriginalProfile()) 1995 if (profile_ != Source<Profile>(source).ptr()->GetOriginalProfile())
1990 break; 1996 break;
1991 1997
1992 ExtensionHost* host = Details<ExtensionHost>(details).ptr(); 1998 ExtensionHost* host = Details<ExtensionHost>(details).ptr();
1993 1999
1994 // Unload the entire extension. We want it to be in a consistent state: 2000 // Unload the entire extension. We want it to be in a consistent state:
1995 // either fully working or not loaded at all, but never half-crashed. 2001 // either fully working or not loaded at all, but never half-crashed.
1996 // We do it in a PostTask so that other handlers of this notification will 2002 // We do it in a PostTask so that other handlers of this notification will
1997 // still have access to the Extension and ExtensionHost. 2003 // still have access to the Extension and ExtensionHost.
1998 MessageLoop::current()->PostTask(FROM_HERE, 2004 MessageLoop::current()->PostTask(FROM_HERE,
1999 NewRunnableMethod(this, &ExtensionService::UnloadExtension, 2005 NewRunnableMethod(this,
2000 host->extension()->id())); 2006 &ExtensionService::UnloadExtension,
2007 host->extension()->id(),
2008 UnloadedExtensionInfo::DISABLE));
2001 break; 2009 break;
2002 } 2010 }
2003 2011
2004 case NotificationType::PREF_CHANGED: { 2012 case NotificationType::PREF_CHANGED: {
2005 std::string* pref_name = Details<std::string>(details).ptr(); 2013 std::string* pref_name = Details<std::string>(details).ptr();
2006 if (*pref_name == prefs::kExtensionInstallAllowList || 2014 if (*pref_name == prefs::kExtensionInstallAllowList ||
2007 *pref_name == prefs::kExtensionInstallDenyList) { 2015 *pref_name == prefs::kExtensionInstallDenyList) {
2008 CheckAdminBlacklist(); 2016 CheckAdminBlacklist();
2009 } else if (*pref_name == prefs::kExtensionInstallForceList) { 2017 } else if (*pref_name == prefs::kExtensionInstallForceList) {
2010 UpdateExternalPolicyExtensionProvider(); 2018 UpdateExternalPolicyExtensionProvider();
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
2057 } 2065 }
2058 2066
2059 void ExtensionService::SetBeingUpgraded(const Extension* extension, 2067 void ExtensionService::SetBeingUpgraded(const Extension* extension,
2060 bool value) { 2068 bool value) {
2061 extension_runtime_data_[extension->id()].being_upgraded = value; 2069 extension_runtime_data_[extension->id()].being_upgraded = value;
2062 } 2070 }
2063 2071
2064 PropertyBag* ExtensionService::GetPropertyBag(const Extension* extension) { 2072 PropertyBag* ExtensionService::GetPropertyBag(const Extension* extension) {
2065 return &extension_runtime_data_[extension->id()].property_bag; 2073 return &extension_runtime_data_[extension->id()].property_bag;
2066 } 2074 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698