// 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/active_tab_permission_granter.h"

#include <set>
#include <utility>
#include <vector>

#include "base/no_destructor.h"
#include "chrome/browser/extensions/extension_action_runner.h"
#include "chrome/browser/extensions/extension_util.h"
#include "chrome/browser/profiles/profile.h"
#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/web_contents.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/process_manager.h"
#include "extensions/common/extension_messages.h"
#include "extensions/common/permissions/permission_set.h"
#include "extensions/common/permissions/permissions_data.h"
#include "extensions/common/user_script.h"
#include "url/gurl.h"

namespace extensions {

namespace {

using CreateMessageFunction = base::Callback<IPC::Message*(bool)>;

// Creates a new IPC message for updating tab-specific permissions.
IPC::Message* CreateUpdateMessage(const GURL& visible_url,
                                  const std::string& extension_id,
                                  const URLPatternSet& new_hosts,
                                  int tab_id,
                                  bool update_whitelist) {
  return new ExtensionMsg_UpdateTabSpecificPermissions(
      visible_url, extension_id, new_hosts, update_whitelist, tab_id);
}

// Creates a new IPC message for clearing tab-specific permissions.
IPC::Message* CreateClearMessage(const std::vector<std::string>& ids,
                                 int tab_id,
                                 bool update_whitelist) {
  return new ExtensionMsg_ClearTabSpecificPermissions(
      ids, update_whitelist, tab_id);
}

// Sends a message exactly once to each render process host owning one of the
// given |frame_hosts| and |tab_process|. If |tab_process| doesn't own any of
// the |frame_hosts|, it will not be signaled to update its origin whitelist.
void SendMessageToProcesses(
    const std::set<content::RenderFrameHost*>& frame_hosts,
    content::RenderProcessHost* tab_process,
    const CreateMessageFunction& create_message) {
  std::set<content::RenderProcessHost*> sent_to_hosts;
  for (content::RenderFrameHost* frame_host : frame_hosts) {
    content::RenderProcessHost* process_host = frame_host->GetProcess();
    if (sent_to_hosts.count(process_host) == 0) {
      // Extension processes have to update the origin whitelists.
      process_host->Send(create_message.Run(true));
      sent_to_hosts.insert(frame_host->GetProcess());
    }
  }
  // If the tab wasn't one of those processes already updated (it likely
  // wasn't), update it. Tabs don't need to update the origin whitelist.
  if (sent_to_hosts.count(tab_process) == 0)
    tab_process->Send(create_message.Run(false));
}

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

ActiveTabPermissionGranter::Delegate* GetActiveTabPermissionGranterDelegate() {
  return GetActiveTabPermissionGranterDelegateWrapper().get();
}

// Returns true if activeTab is allowed to be granted to the extension. This can
// return false for platform-specific implementations.
bool ShouldGrantActiveTabOrPrompt(const Extension* extension,
                                  content::WebContents* web_contents) {
  return !GetActiveTabPermissionGranterDelegate() ||
         GetActiveTabPermissionGranterDelegate()->ShouldGrantActiveTabOrPrompt(
             extension, web_contents);
}

}  // namespace

ActiveTabPermissionGranter::ActiveTabPermissionGranter(
    content::WebContents* web_contents,
    int tab_id,
    Profile* profile)
    : content::WebContentsObserver(web_contents),
      tab_id_(tab_id),
      extension_registry_observer_(this) {
  extension_registry_observer_.Add(ExtensionRegistry::Get(profile));
}

ActiveTabPermissionGranter::~ActiveTabPermissionGranter() {}

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

void ActiveTabPermissionGranter::GrantIfRequested(const Extension* extension) {
  if (granted_extensions_.Contains(extension->id()))
    return;

  APIPermissionSet new_apis;
  URLPatternSet new_hosts;

  const PermissionsData* permissions_data = extension->permissions_data();

  // TODO(devlin): This should be GetLastCommittedURL().
  GURL url = web_contents()->GetVisibleURL();

  // If the extension requested the host permission to |url| but had it
  // withheld, we grant it active tab-style permissions, even if it doesn't have
  // the activeTab permission in the manifest. This is necessary for the
  // runtime host permissions feature to work.
  // Note: It's important that we check if the extension has activeTab before
  // checking ShouldGrantActiveTabOrPrompt() in order to prevent
  // ShouldGrantActiveTabOrPrompt() from prompting for extensions that don't
  // request the activeTab permission.
  if ((permissions_data->HasAPIPermission(APIPermission::kActiveTab) ||
       permissions_data->withheld_permissions().effective_hosts().MatchesURL(
           url)) &&
      ShouldGrantActiveTabOrPrompt(extension, web_contents())) {
    // Gate activeTab for file urls on extensions having explicit access to file
    // urls.
    int valid_schemes = UserScript::ValidUserScriptSchemes();
    if (!util::AllowFileAccess(extension->id(),
                               web_contents()->GetBrowserContext())) {
      valid_schemes &= ~URLPattern::SCHEME_FILE;
    }
    new_hosts.AddOrigin(valid_schemes, url.GetOrigin());
    new_apis.insert(APIPermission::kTab);
  }

  if (permissions_data->HasAPIPermission(APIPermission::kTabCapture))
    new_apis.insert(APIPermission::kTabCaptureForTab);

  if (!new_apis.empty() || !new_hosts.is_empty()) {
    granted_extensions_.Insert(extension);
    PermissionSet new_permissions(std::move(new_apis), ManifestPermissionSet(),
                                  new_hosts, new_hosts);
    permissions_data->UpdateTabSpecificPermissions(tab_id_, new_permissions);
    const content::NavigationEntry* navigation_entry =
        web_contents()->GetController().GetVisibleEntry();
    if (navigation_entry) {
      // We update all extension render views with the new tab permissions, and
      // also the tab itself.
      CreateMessageFunction update_message =
          base::Bind(&CreateUpdateMessage, navigation_entry->GetURL(),
                     extension->id(), new_hosts.Clone(), tab_id_);
      SendMessageToProcesses(
          ProcessManager::Get(web_contents()->GetBrowserContext())
              ->GetRenderFrameHostsForExtension(extension->id()),
          web_contents()->GetMainFrame()->GetProcess(), update_message);

      // If more things ever need to know about this, we should consider making
      // an observer class.
      // It's important that this comes after the IPC is sent to the renderer,
      // so that any tasks executing in the renderer occur after it has the
      // updated permissions.
      ExtensionActionRunner::GetForWebContents(web_contents())
          ->OnActiveTabPermissionGranted(extension);
    }
  }
}

void ActiveTabPermissionGranter::RevokeForTesting() {
  ClearActiveExtensionsAndNotify();
}

void ActiveTabPermissionGranter::DidFinishNavigation(
    content::NavigationHandle* navigation_handle) {
  // Important: sub-frames don't get granted!
  if (!navigation_handle->IsInMainFrame() ||
      !navigation_handle->HasCommitted() ||
      navigation_handle->IsSameDocument()) {
    return;
  }

  // Only clear the granted permissions for cross-origin navigations.
  // TODO(devlin): We likely shouldn't be using the visible entry. Instead,
  // we should use WebContents::GetLastCommittedURL().
  const content::NavigationEntry* navigation_entry =
      web_contents()->GetController().GetVisibleEntry();
  if (navigation_entry && navigation_entry->GetURL().GetOrigin() ==
                              navigation_handle->GetPreviousURL().GetOrigin()) {
    return;
  }

  ClearActiveExtensionsAndNotify();
}

void ActiveTabPermissionGranter::WebContentsDestroyed() {
  ClearActiveExtensionsAndNotify();
}

void ActiveTabPermissionGranter::OnExtensionUnloaded(
    content::BrowserContext* browser_context,
    const Extension* extension,
    UnloadedExtensionReason reason) {
  // Note: don't need to clear the permissions (nor tell the renderer about it)
  // because it's being unloaded anyway.
  granted_extensions_.Remove(extension->id());
}

void ActiveTabPermissionGranter::ClearActiveExtensionsAndNotify() {
  if (granted_extensions_.is_empty())
    return;

  std::set<content::RenderFrameHost*> frame_hosts;
  std::vector<std::string> extension_ids;
  ProcessManager* process_manager =
      ProcessManager::Get(web_contents()->GetBrowserContext());
  for (const scoped_refptr<const Extension>& extension : granted_extensions_) {
    extension->permissions_data()->ClearTabSpecificPermissions(tab_id_);
    extension_ids.push_back(extension->id());
    std::set<content::RenderFrameHost*> extension_frame_hosts =
        process_manager->GetRenderFrameHostsForExtension(extension->id());
    frame_hosts.insert(extension_frame_hosts.begin(),
                       extension_frame_hosts.end());
  }

  CreateMessageFunction clear_message =
      base::Bind(&CreateClearMessage, extension_ids, tab_id_);
  SendMessageToProcesses(
      frame_hosts, web_contents()->GetMainFrame()->GetProcess(), clear_message);

  granted_extensions_.Clear();
}

}  // namespace extensions
