// Copyright 2015 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/scripting_permissions_modifier.h"

#include "chrome/browser/extensions/extension_sync_service.h"
#include "chrome/browser/extensions/permissions_updater.h"
#include "extensions/browser/extension_prefs.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/common/extension.h"
#include "extensions/common/feature_switch.h"
#include "extensions/common/manifest_handlers/permissions_parser.h"
#include "extensions/common/permissions/permission_set.h"
#include "extensions/common/permissions/permissions_data.h"
#include "extensions/common/user_script.h"

namespace extensions {

namespace {

// The entry into the ExtensionPrefs for allowing an extension to script on
// all urls without explicit permission.
const char kExtensionAllowedOnAllUrlsPrefName[] =
    "extension_can_script_all_urls";

// The entry into the prefs for when a user has explicitly set the "extension
// allowed on all urls" pref.
const char kHasSetScriptOnAllUrlsPrefName[] = "has_set_script_all_urls";

URLPatternSet FilterImpliedAllHostsPatterns(const URLPatternSet& patterns) {
  URLPatternSet result;
  for (const URLPattern& pattern : patterns) {
    if (pattern.ImpliesAllHosts())
      result.AddPattern(pattern);
  }
  return result;
}

// Returns true if the extension must be allowed to execute scripts on all urls.
bool ExtensionMustBeAllowedOnAllUrls(const Extension& extension) {
  // Some extensions must retain privilege to execute on all urls. Specifically,
  // extensions that don't show up in chrome:extensions (where withheld
  // permissions couldn't be granted), extensions that are part of chrome or
  // corporate policy, and extensions that are whitelisted to script everywhere
  // must always have permission to run on a page.
  return !extension.ShouldDisplayInExtensionSettings() ||
         Manifest::IsPolicyLocation(extension.location()) ||
         Manifest::IsComponentLocation(extension.location()) ||
         PermissionsData::CanExecuteScriptEverywhere(&extension);
}

// Sets the preference for whether the extension with |id| is allowed to execute
// on all urls, and, if |by_user| is true, also updates preferences to indicate
// that the user has explicitly set a value (rather than using the default).
void SetAllowedOnAllUrlsPref(bool by_user,
                             bool allowed,
                             const std::string& id,
                             ExtensionPrefs* prefs) {
  prefs->UpdateExtensionPref(id, kExtensionAllowedOnAllUrlsPrefName,
                             std::make_unique<base::Value>(allowed));
  if (by_user) {
    prefs->UpdateExtensionPref(id, kHasSetScriptOnAllUrlsPrefName,
                               std::make_unique<base::Value>(true));
  }
}

}  // namespace

ScriptingPermissionsModifier::ScriptingPermissionsModifier(
    content::BrowserContext* browser_context,
    const scoped_refptr<const Extension>& extension)
    : browser_context_(browser_context),
      extension_(extension),
      extension_prefs_(ExtensionPrefs::Get(browser_context_)) {
  DCHECK(extension_);
}

ScriptingPermissionsModifier::~ScriptingPermissionsModifier() {}

// static
void ScriptingPermissionsModifier::SetAllowedOnAllUrlsForSync(
    bool allowed,
    content::BrowserContext* context,
    const std::string& id) {
  const Extension* extension =
      ExtensionRegistry::Get(context)->GetExtensionById(
          id, ExtensionRegistry::EVERYTHING);
  if (extension) {
    // If the extension exists, we should go through the normal flow.
    ScriptingPermissionsModifier(context, extension)
        .SetAllowedOnAllUrls(allowed);
    return;
  }
  // Otherwise, we only update the preference, and the extension will be
  // properly initialized once it's added.
  SetAllowedOnAllUrlsPref(true, allowed, id, ExtensionPrefs::Get(context));
}

// static
bool ScriptingPermissionsModifier::DefaultAllowedOnAllUrls() {
  return !FeatureSwitch::scripts_require_action()->IsEnabled();
}

void ScriptingPermissionsModifier::SetAllowedOnAllUrls(bool allowed) {
  if (ExtensionMustBeAllowedOnAllUrls(*extension_)) {
    CleanUpPrefsIfNecessary();
    return;
  }
  if (IsAllowedOnAllUrls() == allowed)
    return;

  SetAllowedOnAllUrlsPref(true, allowed, extension_->id(), extension_prefs_);
  if (allowed)
    GrantWithheldImpliedAllHosts();
  else
    WithholdImpliedAllHosts();

  // If this was an update to permissions, we also need to sync the change.
  ExtensionSyncService* sync_service =
      ExtensionSyncService::Get(browser_context_);
  if (sync_service)  // |sync_service| can be null in unittests.
    sync_service->SyncExtensionChangeIfNeeded(*extension_);
}

bool ScriptingPermissionsModifier::IsAllowedOnAllUrls() {
  if (ExtensionMustBeAllowedOnAllUrls(*extension_)) {
    CleanUpPrefsIfNecessary();
    return true;
  }
  bool allowed = false;
  if (!extension_prefs_->ReadPrefAsBoolean(
          extension_->id(), kExtensionAllowedOnAllUrlsPrefName, &allowed)) {
    // If there is no value present, we make one, defaulting it to the value of
    // the 'scripts require action' flag. If the flag is on, then the extension
    // does not have permission to script on all urls by default.
    allowed = DefaultAllowedOnAllUrls();
    SetAllowedOnAllUrlsPref(false, allowed, extension_->id(), extension_prefs_);
  }
  return allowed;
}

bool ScriptingPermissionsModifier::HasSetAllowedOnAllUrls() const {
  bool set = false;
  return extension_prefs_->ReadPrefAsBoolean(
             extension_->id(), kHasSetScriptOnAllUrlsPrefName, &set) &&
         set;
}

bool ScriptingPermissionsModifier::CanAffectExtension(
    const PermissionSet& permissions) const {
  // We can withhold permissions if the extension isn't required to maintain
  // permission and if it requests access to all hosts.
  return !ExtensionMustBeAllowedOnAllUrls(*extension_) &&
         permissions.ShouldWarnAllHosts();
}

bool ScriptingPermissionsModifier::HasAffectedExtension() const {
  return extension_->permissions_data()->HasWithheldImpliedAllHosts() ||
         HasSetAllowedOnAllUrls();
}

void ScriptingPermissionsModifier::GrantHostPermission(const GURL& url) {
  GURL origin = url.GetOrigin();
  URLPatternSet new_explicit_hosts;
  URLPatternSet new_scriptable_hosts;

  const PermissionSet& withheld_permissions =
      extension_->permissions_data()->withheld_permissions();
  if (withheld_permissions.explicit_hosts().MatchesURL(url)) {
    new_explicit_hosts.AddOrigin(UserScript::ValidUserScriptSchemes(), origin);
  }
  if (withheld_permissions.scriptable_hosts().MatchesURL(url)) {
    new_scriptable_hosts.AddOrigin(UserScript::ValidUserScriptSchemes(),
                                   origin);
  }

  PermissionsUpdater(browser_context_)
      .AddPermissions(extension_.get(),
                      PermissionSet(APIPermissionSet(), ManifestPermissionSet(),
                                    new_explicit_hosts, new_scriptable_hosts));
}

bool ScriptingPermissionsModifier::HasGrantedHostPermission(const GURL& url) {
  GURL origin = url.GetOrigin();
  const PermissionSet& required_permissions =
      PermissionsParser::GetRequiredPermissions(extension_.get());
  if (!extension_->permissions_data()
           ->active_permissions()
           .effective_hosts()
           .MatchesURL(origin))
    return false;
  std::unique_ptr<const PermissionSet> granted_permissions;
  std::unique_ptr<const PermissionSet> withheld_permissions;
  WithholdPermissions(required_permissions, &granted_permissions,
                      &withheld_permissions, true);
  if (!granted_permissions->effective_hosts().MatchesURL(origin) &&
      withheld_permissions->effective_hosts().MatchesURL(origin))
    return true;

  return false;
}

void ScriptingPermissionsModifier::RemoveGrantedHostPermission(
    const GURL& url) {
  DCHECK(HasGrantedHostPermission(url));

  GURL origin = url.GetOrigin();
  URLPatternSet explicit_hosts;
  URLPatternSet scriptable_hosts;
  const PermissionSet& active_permissions =
      extension_->permissions_data()->active_permissions();
  if (active_permissions.explicit_hosts().MatchesURL(url))
    explicit_hosts.AddOrigin(UserScript::ValidUserScriptSchemes(), origin);
  if (active_permissions.scriptable_hosts().MatchesURL(url))
    scriptable_hosts.AddOrigin(UserScript::ValidUserScriptSchemes(), origin);

  PermissionsUpdater(browser_context_)
      .RemovePermissions(
          extension_.get(),
          PermissionSet(APIPermissionSet(), ManifestPermissionSet(),
                        explicit_hosts, scriptable_hosts),
          PermissionsUpdater::REMOVE_HARD);
}

void ScriptingPermissionsModifier::WithholdPermissions(
    const PermissionSet& permissions,
    std::unique_ptr<const PermissionSet>* granted_permissions_out,
    std::unique_ptr<const PermissionSet>* withheld_permissions_out,
    bool use_initial_state) {
  bool should_withhold = false;
  if (CanAffectExtension(permissions)) {
    if (use_initial_state) {
      // If the user ever set the extension's "all-urls" preference, then the
      // initial state was withheld. This is important, since the all-urls
      // permission should be shown as revokable. Otherwise, default to whatever
      // the system setting is.
      should_withhold = HasSetAllowedOnAllUrls() || !DefaultAllowedOnAllUrls();
    } else {
      should_withhold = !IsAllowedOnAllUrls();
    }
  }

  if (!should_withhold) {
    *granted_permissions_out = permissions.Clone();
    withheld_permissions_out->reset(new PermissionSet());
    return;
  }

  auto segregate_url_permissions = [](const URLPatternSet& patterns,
                                      URLPatternSet* granted,
                                      URLPatternSet* withheld) {
    for (const URLPattern& pattern : patterns) {
      if (pattern.ImpliesAllHosts())
        withheld->AddPattern(pattern);
      else
        granted->AddPattern(pattern);
    }
  };

  URLPatternSet granted_explicit_hosts;
  URLPatternSet withheld_explicit_hosts;
  URLPatternSet granted_scriptable_hosts;
  URLPatternSet withheld_scriptable_hosts;
  segregate_url_permissions(permissions.explicit_hosts(),
                            &granted_explicit_hosts, &withheld_explicit_hosts);
  segregate_url_permissions(permissions.scriptable_hosts(),
                            &granted_scriptable_hosts,
                            &withheld_scriptable_hosts);

  granted_permissions_out->reset(
      new PermissionSet(permissions.apis(), permissions.manifest_permissions(),
                        granted_explicit_hosts, granted_scriptable_hosts));
  withheld_permissions_out->reset(
      new PermissionSet(APIPermissionSet(), ManifestPermissionSet(),
                        withheld_explicit_hosts, withheld_scriptable_hosts));
}

void ScriptingPermissionsModifier::GrantWithheldImpliedAllHosts() {
  const PermissionSet& withheld =
      extension_->permissions_data()->withheld_permissions();

  PermissionSet permissions(
      APIPermissionSet(), ManifestPermissionSet(),
      FilterImpliedAllHostsPatterns(withheld.explicit_hosts()),
      FilterImpliedAllHostsPatterns(withheld.scriptable_hosts()));
  PermissionsUpdater(browser_context_)
      .AddPermissions(extension_.get(), permissions);
}

void ScriptingPermissionsModifier::WithholdImpliedAllHosts() {
  const PermissionSet& active =
      extension_->permissions_data()->active_permissions();
  PermissionSet permissions(
      APIPermissionSet(), ManifestPermissionSet(),
      FilterImpliedAllHostsPatterns(active.explicit_hosts()),
      FilterImpliedAllHostsPatterns(active.scriptable_hosts()));
  PermissionsUpdater(browser_context_)
      .RemovePermissions(extension_.get(), permissions,
                         PermissionsUpdater::REMOVE_HARD);
}

void ScriptingPermissionsModifier::CleanUpPrefsIfNecessary() {
  // From a bug, some extensions such as policy extensions could have the
  // preference set even if it should have been impossible. Reset the prefs to
  // a sane state.
  // See crbug.com/629927
  // TODO(devlin): Remove this in M56.
  DCHECK(ExtensionMustBeAllowedOnAllUrls(*extension_));
  extension_prefs_->UpdateExtensionPref(extension_->id(),
                                        kExtensionAllowedOnAllUrlsPrefName,
                                        std::make_unique<base::Value>(true));
  extension_prefs_->UpdateExtensionPref(
      extension_->id(), kHasSetScriptOnAllUrlsPrefName, nullptr);
}

}  // namespace extensions
