| Index: chrome/browser/renderer_host/chrome_extension_message_filter.cc
|
| diff --git a/chrome/browser/renderer_host/chrome_extension_message_filter.cc b/chrome/browser/renderer_host/chrome_extension_message_filter.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..6a358eef20b06cd04c035e1c07a774aeecfa65fd
|
| --- /dev/null
|
| +++ b/chrome/browser/renderer_host/chrome_extension_message_filter.cc
|
| @@ -0,0 +1,300 @@
|
| +// Copyright 2014 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/renderer_host/chrome_extension_message_filter.h"
|
| +
|
| +#include "base/bind.h"
|
| +#include "base/bind_helpers.h"
|
| +#include "base/files/file_path.h"
|
| +#include "base/strings/utf_string_conversions.h"
|
| +#include "chrome/browser/browser_process.h"
|
| +#include "chrome/browser/extensions/activity_log/activity_action_constants.h"
|
| +#include "chrome/browser/extensions/activity_log/activity_actions.h"
|
| +#include "chrome/browser/extensions/activity_log/activity_log.h"
|
| +#include "chrome/browser/extensions/api/activity_log_private/activity_log_private_api.h"
|
| +#include "chrome/browser/extensions/api/messaging/message_service.h"
|
| +#include "chrome/browser/profiles/profile.h"
|
| +#include "chrome/browser/profiles/profile_manager.h"
|
| +#include "chrome/common/extensions/api/i18n/default_locale_handler.h"
|
| +#include "chrome/common/render_messages.h"
|
| +#include "content/public/browser/render_process_host.h"
|
| +#include "extensions/browser/extension_system.h"
|
| +#include "extensions/common/constants.h"
|
| +#include "extensions/common/extension_messages.h"
|
| +#include "extensions/common/file_util.h"
|
| +#include "extensions/common/message_bundle.h"
|
| +
|
| +using content::BrowserThread;
|
| +using extensions::APIPermission;
|
| +
|
| +namespace {
|
| +
|
| +const uint32 kFilteredMessageClasses[] = {
|
| + ChromeMsgStart,
|
| + ExtensionMsgStart,
|
| +};
|
| +
|
| +// Logs an action to the extension activity log for the specified profile. Can
|
| +// be called from any thread.
|
| +void AddActionToExtensionActivityLog(
|
| + Profile* profile,
|
| + scoped_refptr<extensions::Action> action) {
|
| + // The ActivityLog can only be accessed from the main (UI) thread. If we're
|
| + // running on the wrong thread, re-dispatch from the main thread.
|
| + if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
|
| + BrowserThread::PostTask(
|
| + BrowserThread::UI, FROM_HERE,
|
| + base::Bind(&AddActionToExtensionActivityLog, profile, action));
|
| + } else {
|
| + if (!g_browser_process->profile_manager()->IsValidProfile(profile))
|
| + return;
|
| + // If the action included a URL, check whether it is for an incognito
|
| + // profile. The check is performed here so that it can safely be done from
|
| + // the UI thread.
|
| + if (action->page_url().is_valid() || !action->page_title().empty())
|
| + action->set_page_incognito(profile->IsOffTheRecord());
|
| + extensions::ActivityLog* activity_log =
|
| + extensions::ActivityLog::GetInstance(profile);
|
| + activity_log->LogAction(action);
|
| + }
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +ChromeExtensionMessageFilter::ChromeExtensionMessageFilter(
|
| + int render_process_id,
|
| + Profile* profile)
|
| + : BrowserMessageFilter(kFilteredMessageClasses,
|
| + arraysize(kFilteredMessageClasses)),
|
| + render_process_id_(render_process_id),
|
| + profile_(profile),
|
| + extension_info_map_(
|
| + extensions::ExtensionSystem::Get(profile)->info_map()) {
|
| +}
|
| +
|
| +ChromeExtensionMessageFilter::~ChromeExtensionMessageFilter() {
|
| +}
|
| +
|
| +bool ChromeExtensionMessageFilter::OnMessageReceived(
|
| + const IPC::Message& message) {
|
| + bool handled = true;
|
| + IPC_BEGIN_MESSAGE_MAP(ChromeExtensionMessageFilter, message)
|
| + IPC_MESSAGE_HANDLER(ChromeViewHostMsg_CanTriggerClipboardRead,
|
| + OnCanTriggerClipboardRead)
|
| + IPC_MESSAGE_HANDLER(ChromeViewHostMsg_CanTriggerClipboardWrite,
|
| + OnCanTriggerClipboardWrite)
|
| + IPC_MESSAGE_HANDLER(ExtensionHostMsg_OpenChannelToExtension,
|
| + OnOpenChannelToExtension)
|
| + IPC_MESSAGE_HANDLER(ExtensionHostMsg_OpenChannelToTab, OnOpenChannelToTab)
|
| + IPC_MESSAGE_HANDLER(ExtensionHostMsg_OpenChannelToNativeApp,
|
| + OnOpenChannelToNativeApp)
|
| + IPC_MESSAGE_HANDLER_DELAY_REPLY(ExtensionHostMsg_GetMessageBundle,
|
| + OnGetExtMessageBundle)
|
| + IPC_MESSAGE_HANDLER(ExtensionHostMsg_CloseChannel, OnExtensionCloseChannel)
|
| + IPC_MESSAGE_HANDLER(ExtensionHostMsg_AddAPIActionToActivityLog,
|
| + OnAddAPIActionToExtensionActivityLog);
|
| + IPC_MESSAGE_HANDLER(ExtensionHostMsg_AddDOMActionToActivityLog,
|
| + OnAddDOMActionToExtensionActivityLog);
|
| + IPC_MESSAGE_HANDLER(ExtensionHostMsg_AddEventToActivityLog,
|
| + OnAddEventToExtensionActivityLog);
|
| + IPC_MESSAGE_UNHANDLED(handled = false)
|
| + IPC_END_MESSAGE_MAP()
|
| +
|
| + return handled;
|
| +}
|
| +
|
| +void ChromeExtensionMessageFilter::OverrideThreadForMessage(
|
| + const IPC::Message& message, BrowserThread::ID* thread) {
|
| + switch (message.type()) {
|
| + case ExtensionHostMsg_CloseChannel::ID:
|
| + *thread = BrowserThread::UI;
|
| + break;
|
| + default:
|
| + break;
|
| + }
|
| +}
|
| +
|
| +void ChromeExtensionMessageFilter::OnCanTriggerClipboardRead(
|
| + const GURL& origin, bool* allowed) {
|
| + *allowed = extension_info_map_->SecurityOriginHasAPIPermission(
|
| + origin, render_process_id_, APIPermission::kClipboardRead);
|
| +}
|
| +
|
| +void ChromeExtensionMessageFilter::OnCanTriggerClipboardWrite(
|
| + const GURL& origin, bool* allowed) {
|
| + // Since all extensions could historically write to the clipboard, preserve it
|
| + // for compatibility.
|
| + *allowed = (origin.SchemeIs(extensions::kExtensionScheme) ||
|
| + extension_info_map_->SecurityOriginHasAPIPermission(
|
| + origin, render_process_id_, APIPermission::kClipboardWrite));
|
| +}
|
| +
|
| +void ChromeExtensionMessageFilter::OnOpenChannelToExtension(
|
| + int routing_id,
|
| + const ExtensionMsg_ExternalConnectionInfo& info,
|
| + const std::string& channel_name,
|
| + bool include_tls_channel_id,
|
| + int* port_id) {
|
| + int port2_id;
|
| + extensions::MessageService::AllocatePortIdPair(port_id, &port2_id);
|
| +
|
| + BrowserThread::PostTask(
|
| + BrowserThread::UI, FROM_HERE,
|
| + base::Bind(
|
| + &ChromeExtensionMessageFilter::OpenChannelToExtensionOnUIThread,
|
| + this, render_process_id_, routing_id, port2_id, info,
|
| + channel_name, include_tls_channel_id));
|
| +}
|
| +
|
| +void ChromeExtensionMessageFilter::OpenChannelToExtensionOnUIThread(
|
| + int source_process_id, int source_routing_id,
|
| + int receiver_port_id,
|
| + const ExtensionMsg_ExternalConnectionInfo& info,
|
| + const std::string& channel_name,
|
| + bool include_tls_channel_id) {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| + extensions::MessageService::Get(profile_)->OpenChannelToExtension(
|
| + source_process_id, source_routing_id, receiver_port_id,
|
| + info.source_id, info.target_id, info.source_url, channel_name,
|
| + include_tls_channel_id);
|
| +}
|
| +
|
| +void ChromeExtensionMessageFilter::OnOpenChannelToNativeApp(
|
| + int routing_id,
|
| + const std::string& source_extension_id,
|
| + const std::string& native_app_name,
|
| + int* port_id) {
|
| + int port2_id;
|
| + extensions::MessageService::AllocatePortIdPair(port_id, &port2_id);
|
| +
|
| + BrowserThread::PostTask(
|
| + BrowserThread::UI, FROM_HERE,
|
| + base::Bind(
|
| + &ChromeExtensionMessageFilter::OpenChannelToNativeAppOnUIThread,
|
| + this, routing_id, port2_id, source_extension_id, native_app_name));
|
| +}
|
| +
|
| +void ChromeExtensionMessageFilter::OpenChannelToNativeAppOnUIThread(
|
| + int source_routing_id,
|
| + int receiver_port_id,
|
| + const std::string& source_extension_id,
|
| + const std::string& native_app_name) {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| + extensions::MessageService::Get(profile_)->OpenChannelToNativeApp(
|
| + render_process_id_, source_routing_id, receiver_port_id,
|
| + source_extension_id, native_app_name);
|
| +}
|
| +
|
| +void ChromeExtensionMessageFilter::OnOpenChannelToTab(
|
| + int routing_id, int tab_id, const std::string& extension_id,
|
| + const std::string& channel_name, int* port_id) {
|
| + int port2_id;
|
| + extensions::MessageService::AllocatePortIdPair(port_id, &port2_id);
|
| +
|
| + BrowserThread::PostTask(
|
| + BrowserThread::UI, FROM_HERE,
|
| + base::Bind(&ChromeExtensionMessageFilter::OpenChannelToTabOnUIThread,
|
| + this, render_process_id_, routing_id, port2_id, tab_id,
|
| + extension_id, channel_name));
|
| +}
|
| +
|
| +void ChromeExtensionMessageFilter::OpenChannelToTabOnUIThread(
|
| + int source_process_id, int source_routing_id,
|
| + int receiver_port_id,
|
| + int tab_id,
|
| + const std::string& extension_id,
|
| + const std::string& channel_name) {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| + extensions::MessageService::Get(profile_)->OpenChannelToTab(
|
| + source_process_id, source_routing_id, receiver_port_id,
|
| + tab_id, extension_id, channel_name);
|
| +}
|
| +
|
| +void ChromeExtensionMessageFilter::OnGetExtMessageBundle(
|
| + const std::string& extension_id, IPC::Message* reply_msg) {
|
| + const extensions::Extension* extension =
|
| + extension_info_map_->extensions().GetByID(extension_id);
|
| + base::FilePath extension_path;
|
| + std::string default_locale;
|
| + if (extension) {
|
| + extension_path = extension->path();
|
| + default_locale = extensions::LocaleInfo::GetDefaultLocale(extension);
|
| + }
|
| +
|
| + BrowserThread::PostBlockingPoolTask(
|
| + FROM_HERE,
|
| + base::Bind(
|
| + &ChromeExtensionMessageFilter::OnGetExtMessageBundleOnBlockingPool,
|
| + this, extension_path, extension_id, default_locale, reply_msg));
|
| +}
|
| +
|
| +void ChromeExtensionMessageFilter::OnGetExtMessageBundleOnBlockingPool(
|
| + const base::FilePath& extension_path,
|
| + const std::string& extension_id,
|
| + const std::string& default_locale,
|
| + IPC::Message* reply_msg) {
|
| + DCHECK(BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread());
|
| +
|
| + scoped_ptr<extensions::MessageBundle::SubstitutionMap> dictionary_map(
|
| + extensions::file_util::LoadMessageBundleSubstitutionMap(
|
| + extension_path, extension_id, default_locale));
|
| +
|
| + ExtensionHostMsg_GetMessageBundle::WriteReplyParams(reply_msg,
|
| + *dictionary_map);
|
| + Send(reply_msg);
|
| +}
|
| +
|
| +void ChromeExtensionMessageFilter::OnExtensionCloseChannel(
|
| + int port_id,
|
| + const std::string& error_message) {
|
| + if (!content::RenderProcessHost::FromID(render_process_id_))
|
| + return; // To guard against crash in browser_tests shutdown.
|
| +
|
| + extensions::MessageService* message_service =
|
| + extensions::MessageService::Get(profile_);
|
| + if (message_service)
|
| + message_service->CloseChannel(port_id, error_message);
|
| +}
|
| +
|
| +void ChromeExtensionMessageFilter::OnAddAPIActionToExtensionActivityLog(
|
| + const std::string& extension_id,
|
| + const ExtensionHostMsg_APIActionOrEvent_Params& params) {
|
| + scoped_refptr<extensions::Action> action = new extensions::Action(
|
| + extension_id, base::Time::Now(), extensions::Action::ACTION_API_CALL,
|
| + params.api_call);
|
| + action->set_args(make_scoped_ptr(params.arguments.DeepCopy()));
|
| + if (!params.extra.empty()) {
|
| + action->mutable_other()->SetString(
|
| + activity_log_constants::kActionExtra, params.extra);
|
| + }
|
| + AddActionToExtensionActivityLog(profile_, action);
|
| +}
|
| +
|
| +void ChromeExtensionMessageFilter::OnAddDOMActionToExtensionActivityLog(
|
| + const std::string& extension_id,
|
| + const ExtensionHostMsg_DOMAction_Params& params) {
|
| + scoped_refptr<extensions::Action> action = new extensions::Action(
|
| + extension_id, base::Time::Now(), extensions::Action::ACTION_DOM_ACCESS,
|
| + params.api_call);
|
| + action->set_args(make_scoped_ptr(params.arguments.DeepCopy()));
|
| + action->set_page_url(params.url);
|
| + action->set_page_title(base::UTF16ToUTF8(params.url_title));
|
| + action->mutable_other()->SetInteger(activity_log_constants::kActionDomVerb,
|
| + params.call_type);
|
| + AddActionToExtensionActivityLog(profile_, action);
|
| +}
|
| +
|
| +void ChromeExtensionMessageFilter::OnAddEventToExtensionActivityLog(
|
| + const std::string& extension_id,
|
| + const ExtensionHostMsg_APIActionOrEvent_Params& params) {
|
| + scoped_refptr<extensions::Action> action = new extensions::Action(
|
| + extension_id, base::Time::Now(), extensions::Action::ACTION_API_EVENT,
|
| + params.api_call);
|
| + action->set_args(make_scoped_ptr(params.arguments.DeepCopy()));
|
| + if (!params.extra.empty()) {
|
| + action->mutable_other()->SetString(activity_log_constants::kActionExtra,
|
| + params.extra);
|
| + }
|
| + AddActionToExtensionActivityLog(profile_, action);
|
| +}
|
|
|