Chromium Code Reviews| 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..47b6a74449530c5d5e9943fda9e670785ec7c739 |
| --- /dev/null |
| +++ b/chrome/browser/renderer_host/chrome_extension_message_filter.cc |
| @@ -0,0 +1,277 @@ |
| +// 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_manager.h" |
|
James Cook
2014/06/03 16:07:15
nit: Also #include "chrome/browser/profiles/profil
Lei Zhang
2014/06/03 19:46:30
Done.
|
| +#include "chrome/common/extensions/api/i18n/default_locale_handler.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; |
| + |
| +namespace { |
| + |
| +const uint32 kFilteredMessageClasses[] = { |
| + 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(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::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); |
| +} |