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); |
+} |