// 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.MatchesEffectiveTld())
      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.MatchesEffectiveTld())
        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
