// Copyright (c) 2012 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/permissions_updater.h"

#include <set>
#include <utility>

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/feature_list.h"
#include "base/memory/ref_counted.h"
#include "base/no_destructor.h"
#include "base/values.h"
#include "chrome/browser/extensions/api/permissions/permissions_api_helpers.h"
#include "chrome/browser/extensions/extension_management.h"
#include "chrome/browser/extensions/extension_system_factory.h"
#include "chrome/browser/extensions/scripting_permissions_modifier.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/extensions/api/permissions.h"
#include "chrome/common/webui_url_constants.h"
#include "components/keyed_service/content/browser_context_keyed_service_shutdown_notifier_factory.h"
#include "components/keyed_service/core/keyed_service_shutdown_notifier.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/common/url_constants.h"
#include "extensions/browser/event_router.h"
#include "extensions/browser/event_router_factory.h"
#include "extensions/browser/extension_prefs.h"
#include "extensions/browser/notification_types.h"
#include "extensions/common/cors_util.h"
#include "extensions/common/extension.h"
#include "extensions/common/extension_features.h"
#include "extensions/common/extension_messages.h"
#include "extensions/common/manifest_handlers/permissions_parser.h"
#include "extensions/common/permissions/permission_set.h"
#include "extensions/common/permissions/permissions_data.h"
#include "services/network/public/cpp/features.h"

using content::RenderProcessHost;
using extensions::permissions_api_helpers::PackPermissionSet;

namespace extensions {

namespace permissions = api::permissions;

namespace {

// Returns a PermissionSet that has the active permissions of the extension,
// bounded to its current manifest.
std::unique_ptr<const PermissionSet> GetBoundedActivePermissions(
    const Extension* extension,
    const PermissionSet* active_permissions) {
  // If the extension has used the optional permissions API, it will have a
  // custom set of active permissions defined in the extension prefs. Here,
  // we update the extension's active permissions based on the prefs.
  if (!active_permissions)
    return extension->permissions_data()->active_permissions().Clone();

  const PermissionSet& required_permissions =
      PermissionsParser::GetRequiredPermissions(extension);

  // We restrict the active permissions to be within the bounds defined in the
  // extension's manifest.
  //  a) active permissions must be a subset of optional + default permissions
  //  b) active permissions must contains all default permissions
  std::unique_ptr<const PermissionSet> total_permissions =
      PermissionSet::CreateUnion(
          required_permissions,
          PermissionsParser::GetOptionalPermissions(extension));

  // Make sure the active permissions contain no more than optional + default.
  std::unique_ptr<const PermissionSet> adjusted_active =
      PermissionSet::CreateIntersection(*total_permissions,
                                        *active_permissions);

  // Make sure the active permissions contain the default permissions.
  adjusted_active =
      PermissionSet::CreateUnion(required_permissions, *adjusted_active);

  return adjusted_active;
}

std::unique_ptr<PermissionsUpdater::Delegate>& GetDelegateWrapper() {
  static base::NoDestructor<std::unique_ptr<PermissionsUpdater::Delegate>>
      delegate_wrapper;
  return *delegate_wrapper;
}

PermissionsUpdater::Delegate* GetDelegate() {
  return GetDelegateWrapper().get();
}

// A helper class to watch profile lifetime.
class PermissionsUpdaterShutdownNotifierFactory
    : public BrowserContextKeyedServiceShutdownNotifierFactory {
 public:
  static PermissionsUpdaterShutdownNotifierFactory* GetInstance() {
    static base::NoDestructor<PermissionsUpdaterShutdownNotifierFactory>
        factory;
    return factory.get();
  }

 private:
  friend class base::NoDestructor<PermissionsUpdaterShutdownNotifierFactory>;

  PermissionsUpdaterShutdownNotifierFactory()
      : BrowserContextKeyedServiceShutdownNotifierFactory(
            "PermissionsUpdaterShutdownFactory") {
    DependsOn(EventRouterFactory::GetInstance());
    DependsOn(ExtensionSystemFactory::GetInstance());
  }
  ~PermissionsUpdaterShutdownNotifierFactory() override {}

  DISALLOW_COPY_AND_ASSIGN(PermissionsUpdaterShutdownNotifierFactory);
};

}  // namespace

// A helper class to asynchronously dispatch the permissions updated
// notification once origin access has been updated. This will fire the
// event if and only if the BrowserContext is still valid.
// This class manages its own lifetime and deletes itself when either the
// permissions updated event is fired, or the BrowserContext is shut down
// (whichever happens first).
class PermissionsUpdater::NetworkPermissionsUpdateHelper {
 public:
  static void UpdateNetworkServicePermissions(
      content::BrowserContext* browser_context,
      EventType event_type,
      scoped_refptr<const Extension> extension,
      const PermissionSet& changed,
      base::OnceClosure completion_callback);

 private:
  // This class manages its own lifetime.
  NetworkPermissionsUpdateHelper(content::BrowserContext* browser_context,
                                 base::OnceClosure dispatch_event);
  ~NetworkPermissionsUpdateHelper();

  void OnShutdown();
  void OnOriginAccessUpdated();

  base::OnceClosure dispatch_event_;
  std::unique_ptr<KeyedServiceShutdownNotifier::Subscription>
      shutdown_subscription_;
  base::WeakPtrFactory<NetworkPermissionsUpdateHelper> weak_factory_;

  DISALLOW_COPY_AND_ASSIGN(NetworkPermissionsUpdateHelper);
};

// static
void PermissionsUpdater::NetworkPermissionsUpdateHelper::
    UpdateNetworkServicePermissions(content::BrowserContext* browser_context,
                                    EventType event_type,
                                    scoped_refptr<const Extension> extension,
                                    const PermissionSet& changed,
                                    base::OnceClosure completion_callback) {
  if (changed.effective_hosts().is_empty()) {
    // If there is no difference in allowlist/blocklist for the extension, we
    // can synchronously finish it without updating the CORS access list.
    PermissionsUpdater::NotifyPermissionsUpdated(
        browser_context, event_type, std::move(extension), changed.Clone(),
        std::move(completion_callback));
    return;
  }

  std::vector<network::mojom::CorsOriginPatternPtr> allow_list =
      CreateCorsOriginAccessAllowList(*extension);
  if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) {
    ExtensionsClient::Get()->AddOriginAccessPermissions(*extension, true,
                                                        &allow_list);
  }

  NetworkPermissionsUpdateHelper* helper = new NetworkPermissionsUpdateHelper(
      browser_context,
      base::BindOnce(&PermissionsUpdater::NotifyPermissionsUpdated,
                     browser_context, event_type, extension,
                     changed.Clone(), std::move(completion_callback)));

  // After an asynchronous call below, the helper will call
  // NotifyPermissionsUpdated if the profile is still valid.
  browser_context->SetCorsOriginAccessListForOrigin(
      url::Origin::Create(extension->url()), std::move(allow_list),
      CreateCorsOriginAccessBlockList(*extension),
      base::BindOnce(&NetworkPermissionsUpdateHelper::OnOriginAccessUpdated,
                     helper->weak_factory_.GetWeakPtr()));
}

PermissionsUpdater::NetworkPermissionsUpdateHelper::
    NetworkPermissionsUpdateHelper(content::BrowserContext* browser_context,
                                   base::OnceClosure dispatch_event)
    : dispatch_event_(std::move(dispatch_event)),
      shutdown_subscription_(
          PermissionsUpdaterShutdownNotifierFactory::GetInstance()
              ->Get(browser_context)
              ->Subscribe(
                  base::Bind(&NetworkPermissionsUpdateHelper::OnShutdown,
                             base::Unretained(this)))),
      weak_factory_(this) {}

PermissionsUpdater::NetworkPermissionsUpdateHelper::
    ~NetworkPermissionsUpdateHelper() {}

void PermissionsUpdater::NetworkPermissionsUpdateHelper::OnShutdown() {
  // The profile is shutting down. Don't dispatch the permissions updated
  // event, and clean up the dangling references.
  delete this;
}

void PermissionsUpdater::NetworkPermissionsUpdateHelper::
    OnOriginAccessUpdated() {
  // The origin access list was successfully updated; dispatch the event
  // and clean up dangling references.
  std::move(dispatch_event_).Run();
  delete this;
}

PermissionsUpdater::PermissionsUpdater(content::BrowserContext* browser_context)
    : PermissionsUpdater(browser_context, INIT_FLAG_NONE) {}

PermissionsUpdater::PermissionsUpdater(content::BrowserContext* browser_context,
                                       InitFlag init_flag)
    : browser_context_(browser_context), init_flag_(init_flag) {}

PermissionsUpdater::~PermissionsUpdater() {}

// static
void PermissionsUpdater::SetPlatformDelegate(
    std::unique_ptr<Delegate> delegate) {
  GetDelegateWrapper() = std::move(delegate);
}

void PermissionsUpdater::GrantOptionalPermissions(
    const Extension& extension,
    const PermissionSet& permissions,
    base::OnceClosure completion_callback) {
  CHECK(PermissionsParser::GetOptionalPermissions(&extension)
            .Contains(permissions))
      << "Cannot add optional permissions that are not "
      << "specified in the manifest.";

  // Granted optional permissions are stored in both the granted permissions (so
  // we don't later disable the extension when we check the active permissions
  // against the granted set to determine if there's a permissions increase) and
  // the granted runtime permissions (so they don't get withheld with runtime
  // host permissions enabled). They're also added to the active set, which is
  // the permission set stored in preferences representing the extension's
  // currently-desired permission state.
  constexpr int permissions_store_mask =
      kActivePermissions | kGrantedPermissions | kRuntimeGrantedPermissions;
  AddPermissionsImpl(extension, permissions, permissions_store_mask,
                     permissions, std::move(completion_callback));
}

void PermissionsUpdater::GrantRuntimePermissions(
    const Extension& extension,
    const PermissionSet& permissions,
    base::OnceClosure completion_callback) {
  DCHECK(base::FeatureList::IsEnabled(
      extensions_features::kRuntimeHostPermissions));

  // We don't want to grant the extension object/process more privilege than it
  // requested, even if the user grants additional permission. For instance, if
  // the extension requests https://maps.google.com and the user grants
  // https://*.google.com, we only want to grant the extension itself
  // https://maps.google.com. Since we updated the prefs with the exact
  // granted permissions (*.google.com), if the extension later requests
  // increased permissions that are already covered, they will be auto-granted.

  // Determine which permissions to add to the extension.
  const PermissionSet& withheld =
      extension.permissions_data()->withheld_permissions();

  // We add the intersection of any permissions that were withheld and the
  // permissions that were granted. Since these might not be directly
  // overlapping, we need to use a detailed intersection behavior here.
  std::unique_ptr<const PermissionSet> active_permissions_to_add =
      PermissionSet::CreateIntersection(
          withheld, permissions,
          URLPatternSet::IntersectionBehavior::kDetailed);
  CHECK(extension.permissions_data()->withheld_permissions().Contains(
      *active_permissions_to_add))
      << "Cannot add runtime granted permissions that were not withheld.";

  // Adding runtime granted permissions does not add permissions to the
  // granted or active permissions store, so that behavior taken with the
  // runtime host permissions feature is confined to when the experiment is
  // enabled.
  constexpr int permissions_store_mask = kRuntimeGrantedPermissions;
  AddPermissionsImpl(extension, *active_permissions_to_add,
                     permissions_store_mask, permissions,
                     std::move(completion_callback));
}

void PermissionsUpdater::RevokeOptionalPermissions(
    const Extension& extension,
    const PermissionSet& permissions,
    RemoveType remove_type,
    base::OnceClosure completion_callback) {
  // TODO(devlin): Ideally, we'd have this CHECK in place, but unit tests are
  // currently violating it.
  CHECK(PermissionsParser::GetOptionalPermissions(&extension)
            .Contains(permissions))
      << "Cannot remove optional permissions that are not "
      << "specified in the manifest.";

  // Revoked optional permissions are removed from granted and runtime-granted
  // permissions only if the user, and not the extension, removed them. This
  // allows the extension to add them again without prompting the user. They are
  // always removed from the active set, which is the set of permissions the
  // the extension currently requests.
  int permissions_store_mask = kActivePermissions;
  if (remove_type == REMOVE_HARD)
    permissions_store_mask |= kGrantedPermissions | kRuntimeGrantedPermissions;

  RemovePermissionsImpl(extension, permissions, permissions_store_mask,
                        permissions, std::move(completion_callback));
}

void PermissionsUpdater::RevokeRuntimePermissions(
    const Extension& extension,
    const PermissionSet& permissions,
    base::OnceClosure completion_callback) {
  DCHECK(base::FeatureList::IsEnabled(
      extensions_features::kRuntimeHostPermissions));
  // Similar to the process in adding permissions, we might be revoking more
  // permissions than the extension currently has explicit access to. For
  // instance, we might be revoking https://*.google.com/* even if the extension
  // only has https://maps.google.com/*.
  const PermissionSet& active =
      extension.permissions_data()->active_permissions();
  // Unlike adding permissions, we should know that any permissions we remove
  // are a superset of the permissions the extension has active (because we only
  // allow removal origins and the extension can't have a broader origin than
  // what it has granted).
  std::unique_ptr<const PermissionSet> active_permissions_to_remove =
      PermissionSet::CreateIntersection(
          active, permissions,
          URLPatternSet::IntersectionBehavior::kPatternsContainedByBoth);
  // One exception: If we're revoking a permission like "<all_urls>", we need
  // to make sure it doesn't revoke the included chrome://favicon permission.
  std::set<URLPattern> removable_explicit_hosts;
  bool needs_adjustment = false;
  for (const auto& pattern : active_permissions_to_remove->explicit_hosts()) {
    bool is_chrome_favicon = pattern.scheme() == content::kChromeUIScheme &&
                             pattern.host() == chrome::kChromeUIFaviconHost;
    if (is_chrome_favicon)
      needs_adjustment = true;
    else
      removable_explicit_hosts.insert(pattern);
  }
  if (needs_adjustment) {
    // Tedious, because PermissionSets are const. :(
    active_permissions_to_remove = std::make_unique<PermissionSet>(
        active_permissions_to_remove->apis().Clone(),
        active_permissions_to_remove->manifest_permissions().Clone(),
        URLPatternSet(removable_explicit_hosts),
        active_permissions_to_remove->scriptable_hosts().Clone());
  }

  CHECK(extension.permissions_data()->active_permissions().Contains(
      *active_permissions_to_remove))
      << "Cannot remove permissions that are not active.";
  CHECK(GetRevokablePermissions(&extension)->Contains(permissions))
      << "Cannot remove non-revokable permissions.";

  // Removing runtime-granted permissions does not remove permissions from
  // the granted permissions store. This is done to ensure behavior taken with
  // the runtime host permissions feature is confined to when the experiment is
  // enabled. Similarly, since the runtime-granted permissions were never added
  // to the active permissions stored in prefs, they are also not removed.
  constexpr int permissions_store_mask = kRuntimeGrantedPermissions;
  RemovePermissionsImpl(extension, *active_permissions_to_remove,
                        permissions_store_mask, permissions,
                        std::move(completion_callback));
}

void PermissionsUpdater::SetPolicyHostRestrictions(
    const Extension* extension,
    const URLPatternSet& runtime_blocked_hosts,
    const URLPatternSet& runtime_allowed_hosts) {
  extension->permissions_data()->SetPolicyHostRestrictions(
      runtime_blocked_hosts, runtime_allowed_hosts);

  // Update the BrowserContext origin lists, and send notification to the
  // currently running renderers of the runtime block hosts settings.
  NetworkPermissionsUpdateHelper::UpdateNetworkServicePermissions(
      browser_context_, POLICY, extension, PermissionSet(),
      base::DoNothing::Once());
}

void PermissionsUpdater::SetUsesDefaultHostRestrictions(
    const Extension* extension) {
  extension->permissions_data()->SetUsesDefaultHostRestrictions();
  NetworkPermissionsUpdateHelper::UpdateNetworkServicePermissions(
      browser_context_, POLICY, extension, PermissionSet(),
      base::DoNothing::Once());
}

void PermissionsUpdater::SetDefaultPolicyHostRestrictions(
    const URLPatternSet& default_runtime_blocked_hosts,
    const URLPatternSet& default_runtime_allowed_hosts) {
  PermissionsData::SetDefaultPolicyHostRestrictions(
      default_runtime_blocked_hosts, default_runtime_allowed_hosts);

  // Send notification to the currently running renderers of the runtime block
  // hosts settings.
  NotifyDefaultPolicyHostRestrictionsUpdated(default_runtime_blocked_hosts,
                                             default_runtime_allowed_hosts);
}

void PermissionsUpdater::RemovePermissionsUnsafe(
    const Extension* extension,
    const PermissionSet& to_remove) {
  const PermissionSet& active =
      extension->permissions_data()->active_permissions();
  std::unique_ptr<const PermissionSet> total =
      PermissionSet::CreateDifference(active, to_remove);
  // |successfully_removed| might not equal |to_remove| if |to_remove| contains
  // permissions the extension didn't have.
  std::unique_ptr<const PermissionSet> successfully_removed =
      PermissionSet::CreateDifference(active, *total);

  // TODO(devlin): This seems wrong. Since these permissions are being removed
  // by enterprise policy, we should not update the active permissions set in
  // preferences. That way, if the enterprise policy is changed, the removed
  // permissions would be re-added.
  constexpr bool update_active_prefs = true;
  SetPermissions(extension, std::move(total), update_active_prefs);
  NetworkPermissionsUpdateHelper::UpdateNetworkServicePermissions(
      browser_context_, REMOVED, extension, *successfully_removed,
      base::DoNothing::Once());
}

std::unique_ptr<const PermissionSet>
PermissionsUpdater::GetRevokablePermissions(const Extension* extension) const {
  // Any permissions not required by the extension are revokable.
  const PermissionSet& required =
      PermissionsParser::GetRequiredPermissions(extension);
  std::unique_ptr<const PermissionSet> revokable_permissions =
      PermissionSet::CreateDifference(
          extension->permissions_data()->active_permissions(), required);

  // Additionally, some required permissions may be revokable if they can be
  // withheld by the ScriptingPermissionsModifier.
  std::unique_ptr<const PermissionSet> revokable_scripting_permissions =
      ScriptingPermissionsModifier(browser_context_,
                                   base::WrapRefCounted(extension))
          .GetRevokablePermissions();

  if (revokable_scripting_permissions) {
    revokable_permissions = PermissionSet::CreateUnion(
        *revokable_permissions, *revokable_scripting_permissions);
  }
  return revokable_permissions;
}

void PermissionsUpdater::GrantActivePermissions(const Extension* extension) {
  CHECK(extension);

  ExtensionPrefs::Get(browser_context_)
      ->AddGrantedPermissions(
          extension->id(), extension->permissions_data()->active_permissions());
}

void PermissionsUpdater::InitializePermissions(const Extension* extension) {
  std::unique_ptr<const PermissionSet> bounded_wrapper;
  const PermissionSet* bounded_active = nullptr;
  ExtensionPrefs* prefs = ExtensionPrefs::Get(browser_context_);
  // If |extension| is a transient dummy extension, we do not want to look for
  // it in preferences.
  if (init_flag_ & INIT_FLAG_TRANSIENT) {
    bounded_active = &extension->permissions_data()->active_permissions();
  } else {
    std::unique_ptr<const PermissionSet> active_permissions =
        prefs->GetActivePermissions(extension->id());
    bounded_wrapper =
        GetBoundedActivePermissions(extension, active_permissions.get());
    bounded_active = bounded_wrapper.get();
  }

  std::unique_ptr<const PermissionSet> granted_permissions;
  ScriptingPermissionsModifier::WithholdPermissionsIfNecessary(
      *extension, *prefs, *bounded_active, &granted_permissions);

  if (GetDelegate())
    GetDelegate()->InitializePermissions(extension, &granted_permissions);

  bool update_active_permissions = false;
  if ((init_flag_ & INIT_FLAG_TRANSIENT) == 0) {
    update_active_permissions = true;
    // Apply per-extension policy if set.
    ExtensionManagement* management =
        ExtensionManagementFactory::GetForBrowserContext(browser_context_);
    if (!management->UsesDefaultPolicyHostRestrictions(extension)) {
      SetPolicyHostRestrictions(extension,
                                management->GetPolicyBlockedHosts(extension),
                                management->GetPolicyAllowedHosts(extension));
    }
  }

  SetPermissions(extension, std::move(granted_permissions),
                 update_active_permissions);
}

void PermissionsUpdater::AddPermissionsForTesting(
    const Extension& extension,
    const PermissionSet& permissions) {
  AddPermissionsImpl(extension, permissions, kNone, permissions,
                     base::DoNothing::Once());
}

void PermissionsUpdater::SetPermissions(
    const Extension* extension,
    std::unique_ptr<const PermissionSet> new_active,
    bool update_prefs) {
  // Calculate the withheld permissions as any permissions that were required,
  // but are not in the active set.
  const PermissionSet& required =
      PermissionsParser::GetRequiredPermissions(extension);
  // TODO(https://crbug.com/869403): Currently, withheld permissions should only
  // contain permissions withheld by the runtime host permissions feature.
  // However, there could possibly be API permissions that were removed from the
  // active set by enterprise policy. These shouldn't go in the withheld
  // permission set, since withheld permissions are generally supposed to be
  // grantable. Currently, we can deal with this because all permissions
  // withheld by runtime host permissions are explicit or scriptable hosts, and
  // all permissions blocked by enterprise are API permissions. So to get the
  // set of runtime-hosts-withheld permissions, we just look at the delta in the
  // URLPatternSets. However, this is very fragile, and should be dealt with
  // more robustly.
  std::unique_ptr<const PermissionSet> new_withheld =
      PermissionSet::CreateDifference(
          PermissionSet(APIPermissionSet(), ManifestPermissionSet(),
                        required.explicit_hosts().Clone(),
                        required.scriptable_hosts().Clone()),
          *new_active);

  extension->permissions_data()->SetPermissions(std::move(new_active),
                                                std::move(new_withheld));

  if (update_prefs) {
    ExtensionPrefs::Get(browser_context_)
        ->SetActivePermissions(
            extension->id(),
            extension->permissions_data()->active_permissions());
  }
}

// static
void PermissionsUpdater::NotifyPermissionsUpdated(
    content::BrowserContext* browser_context,
    EventType event_type,
    scoped_refptr<const Extension> extension,
    std::unique_ptr<const PermissionSet> changed,
    base::OnceClosure completion_callback) {
  if (changed->IsEmpty() && event_type != POLICY) {
    std::move(completion_callback).Run();
    return;
  }

  UpdatedExtensionPermissionsInfo::Reason reason;
  events::HistogramValue histogram_value = events::UNKNOWN;
  const char* event_name = NULL;
  Profile* profile = Profile::FromBrowserContext(browser_context);

  if (event_type == REMOVED) {
    reason = UpdatedExtensionPermissionsInfo::REMOVED;
    histogram_value = events::PERMISSIONS_ON_REMOVED;
    event_name = permissions::OnRemoved::kEventName;
  } else if (event_type == ADDED) {
    reason = UpdatedExtensionPermissionsInfo::ADDED;
    histogram_value = events::PERMISSIONS_ON_ADDED;
    event_name = permissions::OnAdded::kEventName;
  } else {
    DCHECK_EQ(POLICY, event_type);
    reason = UpdatedExtensionPermissionsInfo::POLICY;
  }

  // Notify other APIs or interested parties.
  UpdatedExtensionPermissionsInfo info =
      UpdatedExtensionPermissionsInfo(extension.get(), *changed, reason);
  content::NotificationService::current()->Notify(
      extensions::NOTIFICATION_EXTENSION_PERMISSIONS_UPDATED,
      content::Source<Profile>(profile),
      content::Details<UpdatedExtensionPermissionsInfo>(&info));

  ExtensionMsg_UpdatePermissions_Params params;
  params.extension_id = extension->id();
  params.active_permissions = ExtensionMsg_PermissionSetStruct(
      extension->permissions_data()->active_permissions());
  params.withheld_permissions = ExtensionMsg_PermissionSetStruct(
      extension->permissions_data()->withheld_permissions());
  params.uses_default_policy_host_restrictions =
      extension->permissions_data()->UsesDefaultPolicyHostRestrictions();
  if (!params.uses_default_policy_host_restrictions) {
    params.policy_blocked_hosts =
        extension->permissions_data()->policy_blocked_hosts().Clone();
    params.policy_allowed_hosts =
        extension->permissions_data()->policy_allowed_hosts().Clone();
  }

  // Send the new permissions to the renderers.
  for (RenderProcessHost::iterator i(RenderProcessHost::AllHostsIterator());
       !i.IsAtEnd(); i.Advance()) {
    RenderProcessHost* host = i.GetCurrentValue();
    if (profile->IsSameProfile(
            Profile::FromBrowserContext(host->GetBrowserContext()))) {
      host->Send(new ExtensionMsg_UpdatePermissions(params));
    }
  }

  // Trigger the onAdded and onRemoved events in the extension. We explicitly
  // don't do this for policy-related events.
  EventRouter* event_router =
      event_name ? EventRouter::Get(browser_context) : nullptr;
  if (event_router) {
    std::unique_ptr<base::ListValue> value(new base::ListValue());
    std::unique_ptr<api::permissions::Permissions> permissions =
        PackPermissionSet(*changed);
    value->Append(permissions->ToValue());
    auto event = std::make_unique<Event>(histogram_value, event_name,
                                         std::move(value), browser_context);
    event_router->DispatchEventToExtension(extension->id(), std::move(event));
  }

  std::move(completion_callback).Run();
}

// Notify the renderers that extension policy (policy_blocked_hosts) is updated
// and provide new set of hosts.
void PermissionsUpdater::NotifyDefaultPolicyHostRestrictionsUpdated(
    const URLPatternSet& default_runtime_blocked_hosts,
    const URLPatternSet& default_runtime_allowed_hosts) {
  DCHECK_EQ(0, init_flag_ & INIT_FLAG_TRANSIENT);

  Profile* profile = Profile::FromBrowserContext(browser_context_);

  ExtensionMsg_UpdateDefaultPolicyHostRestrictions_Params params;
  params.default_policy_blocked_hosts = default_runtime_blocked_hosts.Clone();
  params.default_policy_allowed_hosts = default_runtime_allowed_hosts.Clone();

  // Send the new policy to the renderers.
  for (RenderProcessHost::iterator host_iterator(
           RenderProcessHost::AllHostsIterator());
       !host_iterator.IsAtEnd(); host_iterator.Advance()) {
    RenderProcessHost* host = host_iterator.GetCurrentValue();
    if (profile->IsSameProfile(
            Profile::FromBrowserContext(host->GetBrowserContext()))) {
      host->Send(new ExtensionMsg_UpdateDefaultPolicyHostRestrictions(params));
    }
  }
}

void PermissionsUpdater::AddPermissionsImpl(
    const Extension& extension,
    const PermissionSet& active_permissions_to_add,
    int permissions_store_mask,
    const PermissionSet& prefs_permissions_to_add,
    base::OnceClosure completion_callback) {
  std::unique_ptr<const PermissionSet> new_active = PermissionSet::CreateUnion(
      active_permissions_to_add,
      extension.permissions_data()->active_permissions());

  bool update_active_prefs = (permissions_store_mask & kActivePermissions) != 0;
  SetPermissions(&extension, std::move(new_active), update_active_prefs);

  if ((permissions_store_mask & kGrantedPermissions) != 0) {
    // TODO(devlin): Could we only grant |permissions|, rather than all those
    // in the active permissions? In theory, all other active permissions have
    // already been granted.
    GrantActivePermissions(&extension);
  }

  if ((permissions_store_mask & kRuntimeGrantedPermissions) != 0) {
    ExtensionPrefs::Get(browser_context_)
        ->AddRuntimeGrantedPermissions(extension.id(),
                                       prefs_permissions_to_add);
  }

  NetworkPermissionsUpdateHelper::UpdateNetworkServicePermissions(
      browser_context_, ADDED, &extension, active_permissions_to_add,
      std::move(completion_callback));
}

void PermissionsUpdater::RemovePermissionsImpl(
    const Extension& extension,
    const PermissionSet& active_permissions_to_remove,
    int permissions_store_mask,
    const PermissionSet& prefs_permissions_to_remove,
    base::OnceClosure completion_callback) {
  std::unique_ptr<const PermissionSet> new_active =
      PermissionSet::CreateDifference(
          extension.permissions_data()->active_permissions(),
          active_permissions_to_remove);

  bool update_active_prefs = (permissions_store_mask & kActivePermissions) != 0;
  SetPermissions(&extension, std::move(new_active), update_active_prefs);

  ExtensionPrefs* prefs = ExtensionPrefs::Get(browser_context_);
  // NOTE: Currently, this code path is only reached in unit tests. See comment
  // above REMOVE_HARD in the header file.
  if ((permissions_store_mask & kGrantedPermissions) != 0) {
    prefs->RemoveGrantedPermissions(extension.id(),
                                    prefs_permissions_to_remove);
  }

  if ((permissions_store_mask & kRuntimeGrantedPermissions) != 0) {
    prefs->RemoveRuntimeGrantedPermissions(extension.id(),
                                           prefs_permissions_to_remove);
  }

  NetworkPermissionsUpdateHelper::UpdateNetworkServicePermissions(
      browser_context_, REMOVED, &extension, active_permissions_to_remove,
      std::move(completion_callback));
}

}  // namespace extensions
