OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 } |
OLD | NEW |