// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/extensions/extension_util.h"
#include "base/command_line.h"
#include "chrome/browser/extensions/extension_prefs.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_sync_service.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/extensions/sync_helper.h"
#include "extensions/common/extension.h"
#include "extensions/common/manifest.h"
#include "extensions/common/manifest_handlers/incognito_info.h"
using extensions::Extension;
using extensions::ExtensionPrefs;
namespace extension_util {
bool IsIncognitoEnabled(const std::string& extension_id,
const ExtensionService* service) {
if (!service)
return false;
const Extension* extension = service->GetInstalledExtension(extension_id);
if (extension && !extension->can_be_incognito_enabled())
return false;
// If this is an existing component extension we always allow it to
// work in incognito mode.
if (extension && extension->location() == extensions::Manifest::COMPONENT)
return true;
if (extension && extension->force_incognito_enabled())
return true;
// Check the prefs.
return service->extension_prefs()->IsIncognitoEnabled(extension_id);
}
void SetIsIncognitoEnabled(const std::string& extension_id,
ExtensionService* service,
bool enabled) {
const Extension* extension = service->GetInstalledExtension(extension_id);
if (extension && !extension->can_be_incognito_enabled())
return;
if (extension && extension->location() == extensions::Manifest::COMPONENT) {
// This shouldn't be called for component extensions unless it is called
// by sync, for syncable component extensions.
// See http://crbug.com/112290 and associated CLs for the sordid history.
DCHECK(extensions::sync_helper::IsSyncable(extension));
// If we are here, make sure the we aren't trying to change the value.
DCHECK_EQ(enabled, IsIncognitoEnabled(extension_id, service));
return;
}
ExtensionPrefs* extension_prefs = service->extension_prefs();
// Broadcast unloaded and loaded events to update browser state. Only bother
// if the value changed and the extension is actually enabled, since there is
// no UI otherwise.
bool old_enabled = extension_prefs->IsIncognitoEnabled(extension_id);
if (enabled == old_enabled)
return;
extension_prefs->SetIsIncognitoEnabled(extension_id, enabled);
bool extension_is_enabled = service->extensions()->Contains(extension_id);
// When we reload the extension the ID may be invalidated if we've passed it
// by const ref everywhere. Make a copy to be safe.
std::string id = extension_id;
if (extension_is_enabled)
service->ReloadExtension(id);
// Reloading the extension invalidates the |extension| pointer.
extension = service->GetInstalledExtension(id);
if (extension) {
ExtensionSyncService::Get(service->profile())->
SyncExtensionChangeIfNeeded(*extension);
}
}
bool CanCrossIncognito(const Extension* extension,
const ExtensionService* service) {
// We allow the extension to see events and data from another profile iff it
// uses "spanning" behavior and it has incognito access. "split" mode
// extensions only see events for a matching profile.
CHECK(extension);
return extension_util::IsIncognitoEnabled(extension->id(), service) &&
!extensions::IncognitoInfo::IsSplitMode(extension);
}
bool CanLoadInIncognito(const Extension* extension,
const ExtensionService* service) {
if (extension->is_hosted_app())
return true;
// Packaged apps and regular extensions need to be enabled specifically for
// incognito (and split mode should be set).
return extensions::IncognitoInfo::IsSplitMode(extension) &&
extension_util::IsIncognitoEnabled(extension->id(), service);
}
bool AllowFileAccess(const Extension* extension,
const ExtensionService* service) {
return (CommandLine::ForCurrentProcess()->HasSwitch(
switches::kDisableExtensionsFileAccessCheck) ||
service->extension_prefs()->AllowFileAccess(extension->id()));
}
void SetAllowFileAccess(const Extension* extension,
ExtensionService* service,
bool allow) {
// Reload to update browser state. Only bother if the value changed and the
// extension is actually enabled, since there is no UI otherwise.
bool old_allow = AllowFileAccess(extension, service);
if (allow == old_allow)
return;
service->extension_prefs()->SetAllowFileAccess(extension->id(), allow);
bool extension_is_enabled = service->extensions()->Contains(extension->id());
if (extension_is_enabled)
service->ReloadExtension(extension->id());
}
bool IsAppLaunchable(const std::string& extension_id,
const ExtensionService* service) {
return !(service->extension_prefs()->GetDisableReasons(extension_id) &
Extension::DISABLE_UNSUPPORTED_REQUIREMENT);
}
bool IsAppLaunchableWithoutEnabling(const std::string& extension_id,
const ExtensionService* service) {
const Extension* launchable_extension = service->GetExtensionById(
extension_id, ExtensionService::INCLUDE_ENABLED);
return launchable_extension != NULL;
}
} // namespace extension_util