1 // Copyright 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "chrome/browser/extensions/extension_util.h" 6 7 #include "base/command_line.h" 8 #include "chrome/browser/extensions/extension_prefs.h" 9 #include "chrome/browser/extensions/extension_service.h" 10 #include "chrome/browser/extensions/extension_sync_service.h" 11 #include "chrome/common/chrome_switches.h" 12 #include "chrome/common/extensions/sync_helper.h" 13 #include "extensions/common/extension.h" 14 #include "extensions/common/manifest.h" 15 #include "extensions/common/manifest_handlers/incognito_info.h" 16 17 using extensions::Extension; 18 using extensions::ExtensionPrefs; 19 20 namespace extension_util { 21 22 bool IsIncognitoEnabled(const std::string& extension_id, 23 const ExtensionService* service) { 24 if (!service) 25 return false; 26 27 const Extension* extension = service->GetInstalledExtension(extension_id); 28 if (extension && !extension->can_be_incognito_enabled()) 29 return false; 30 // If this is an existing component extension we always allow it to 31 // work in incognito mode. 32 if (extension && extension->location() == extensions::Manifest::COMPONENT) 33 return true; 34 if (extension && extension->force_incognito_enabled()) 35 return true; 36 37 // Check the prefs. 38 return service->extension_prefs()->IsIncognitoEnabled(extension_id); 39 } 40 41 void SetIsIncognitoEnabled(const std::string& extension_id, 42 ExtensionService* service, 43 bool enabled) { 44 const Extension* extension = service->GetInstalledExtension(extension_id); 45 if (extension && !extension->can_be_incognito_enabled()) 46 return; 47 if (extension && extension->location() == extensions::Manifest::COMPONENT) { 48 // This shouldn't be called for component extensions unless it is called 49 // by sync, for syncable component extensions. 50 // See http://crbug.com/112290 and associated CLs for the sordid history. 51 DCHECK(extensions::sync_helper::IsSyncable(extension)); 52 53 // If we are here, make sure the we aren't trying to change the value. 54 DCHECK_EQ(enabled, IsIncognitoEnabled(extension_id, service)); 55 return; 56 } 57 58 ExtensionPrefs* extension_prefs = service->extension_prefs(); 59 // Broadcast unloaded and loaded events to update browser state. Only bother 60 // if the value changed and the extension is actually enabled, since there is 61 // no UI otherwise. 62 bool old_enabled = extension_prefs->IsIncognitoEnabled(extension_id); 63 if (enabled == old_enabled) 64 return; 65 66 extension_prefs->SetIsIncognitoEnabled(extension_id, enabled); 67 68 bool extension_is_enabled = service->extensions()->Contains(extension_id); 69 70 // When we reload the extension the ID may be invalidated if we've passed it 71 // by const ref everywhere. Make a copy to be safe. 72 std::string id = extension_id; 73 if (extension_is_enabled) 74 service->ReloadExtension(id); 75 76 // Reloading the extension invalidates the |extension| pointer. 77 extension = service->GetInstalledExtension(id); 78 if (extension) { 79 ExtensionSyncService::Get(service->profile())-> 80 SyncExtensionChangeIfNeeded(*extension); 81 } 82 } 83 84 bool CanCrossIncognito(const Extension* extension, 85 const ExtensionService* service) { 86 // We allow the extension to see events and data from another profile iff it 87 // uses "spanning" behavior and it has incognito access. "split" mode 88 // extensions only see events for a matching profile. 89 CHECK(extension); 90 return extension_util::IsIncognitoEnabled(extension->id(), service) && 91 !extensions::IncognitoInfo::IsSplitMode(extension); 92 } 93 94 bool CanLoadInIncognito(const Extension* extension, 95 const ExtensionService* service) { 96 if (extension->is_hosted_app()) 97 return true; 98 // Packaged apps and regular extensions need to be enabled specifically for 99 // incognito (and split mode should be set). 100 return extensions::IncognitoInfo::IsSplitMode(extension) && 101 extension_util::IsIncognitoEnabled(extension->id(), service); 102 } 103 104 bool AllowFileAccess(const Extension* extension, 105 const ExtensionService* service) { 106 return (CommandLine::ForCurrentProcess()->HasSwitch( 107 switches::kDisableExtensionsFileAccessCheck) || 108 service->extension_prefs()->AllowFileAccess(extension->id())); 109 } 110 111 void SetAllowFileAccess(const Extension* extension, 112 ExtensionService* service, 113 bool allow) { 114 // Reload to update browser state. Only bother if the value changed and the 115 // extension is actually enabled, since there is no UI otherwise. 116 bool old_allow = AllowFileAccess(extension, service); 117 if (allow == old_allow) 118 return; 119 120 service->extension_prefs()->SetAllowFileAccess(extension->id(), allow); 121 122 bool extension_is_enabled = service->extensions()->Contains(extension->id()); 123 if (extension_is_enabled) 124 service->ReloadExtension(extension->id()); 125 } 126 127 bool IsAppLaunchable(const std::string& extension_id, 128 const ExtensionService* service) { 129 return !(service->extension_prefs()->GetDisableReasons(extension_id) & 130 Extension::DISABLE_UNSUPPORTED_REQUIREMENT); 131 } 132 133 bool IsAppLaunchableWithoutEnabling(const std::string& extension_id, 134 const ExtensionService* service) { 135 const Extension* launchable_extension = service->GetExtensionById( 136 extension_id, ExtensionService::INCLUDE_ENABLED); 137 return launchable_extension != NULL; 138 } 139 140 } // namespace extension_util 141