[go: nahoru, domu]

Add support for passing an arbitrary parameter to an IPC message handler. The motivation is for WebContentsObserver to pass RenderFrameHost* to message handlers easily.

As an example, an observer would look like this:

bool FooWebContentsObserver::OnMessageReceived(
    const IPC::Message& message,
    RenderFrameHost* render_frame_host) {
IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(FooWebContentsObserver, message, RenderFrameHost, render_frame_host)
  IPC_MESSAGE_HANDLER(FooHostMsg_Bar, OnBar)
.
.
.

void FooWebContentsObserver::OnBar(RenderFrameHost* render_frame_host, ...

You can of course still have dispatchers without the extra parameter as before.


This is generalizing the existing code that allows an IPC message handler to have a "const IPC::Message& message) first parameter to get access to the IPC.

Sync IPCs don't support this yet. It's a lot more work because for them we conveniently reuse tuple's DispatchToMethod. This isn't urgent yet, since sync IPCs aren't dispatched on the UI thread for the most part because of NPAPI and Windows, so punting on this for now.

BUG=304341
R=tsepez@chromium.org

Review URL: https://codereview.chromium.org/283623002

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@270237 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/chrome/browser/extensions/api/alarms/alarms_api_unittest.cc b/chrome/browser/extensions/api/alarms/alarms_api_unittest.cc
index e5c6e6da..77e36a4 100644
--- a/chrome/browser/extensions/api/alarms/alarms_api_unittest.cc
+++ b/chrome/browser/extensions/api/alarms/alarms_api_unittest.cc
@@ -283,9 +283,10 @@
   const IPC::Message* warning = sink.GetUniqueMessageMatching(
       ExtensionMsg_AddMessageToConsole::ID);
   ASSERT_TRUE(warning);
-  content::ConsoleMessageLevel level = content::CONSOLE_MESSAGE_LEVEL_DEBUG;
-  std::string message;
-  ExtensionMsg_AddMessageToConsole::Read(warning, &level, &message);
+  ExtensionMsg_AddMessageToConsole::Param params;
+  ExtensionMsg_AddMessageToConsole::Read(warning, &params);
+  content::ConsoleMessageLevel level = params.a;
+  std::string message = params.b;
   EXPECT_EQ(content::CONSOLE_MESSAGE_LEVEL_WARNING, level);
   EXPECT_THAT(message, testing::HasSubstr("delay is less than minimum of 1"));
 }
diff --git a/chrome/browser/search/instant_service_unittest.cc b/chrome/browser/search/instant_service_unittest.cc
index 760bb58..eca0fe4 100644
--- a/chrome/browser/search/instant_service_unittest.cc
+++ b/chrome/browser/search/instant_service_unittest.cc
@@ -106,9 +106,10 @@
   EXPECT_EQ(1U, rph->sink().message_count());
   const IPC::Message* msg = rph->sink().GetMessageAt(0);
   ASSERT_TRUE(msg);
-  std::vector<GURL> search_urls;
-  GURL new_tab_page_url;
-  ChromeViewMsg_SetSearchURLs::Read(msg, &search_urls, &new_tab_page_url);
+  ChromeViewMsg_SetSearchURLs::Param params;
+  ChromeViewMsg_SetSearchURLs::Read(msg, &params);
+  std::vector<GURL> search_urls = params.a;
+  GURL new_tab_page_url = params.b;
   EXPECT_EQ(2U, search_urls.size());
   EXPECT_EQ("https://www.google.com/alt#quux=", search_urls[0].spec());
   EXPECT_EQ("https://www.google.com/url?bar=", search_urls[1].spec());
diff --git a/chrome/browser/spellchecker/spellcheck_message_filter_mac_browsertest.cc b/chrome/browser/spellchecker/spellcheck_message_filter_mac_browsertest.cc
index 4da3f1d1..2d3efc1 100644
--- a/chrome/browser/spellchecker/spellcheck_message_filter_mac_browsertest.cc
+++ b/chrome/browser/spellchecker/spellcheck_message_filter_mac_browsertest.cc
@@ -52,10 +52,11 @@
   base::MessageLoopForUI::current()->Run();
   EXPECT_EQ(1U, target->sent_messages_.size());
 
-  int sent_identifier;
-  std::vector<SpellCheckResult> sent_results;
+  SpellCheckMsg_RespondTextCheck::Param params;
   bool ok = SpellCheckMsg_RespondTextCheck::Read(
-      target->sent_messages_[0], &sent_identifier, &sent_results);
+      target->sent_messages_[0], &params);
+  std::vector<SpellCheckResult> sent_results = params.b;
+ 
   EXPECT_TRUE(ok);
   EXPECT_EQ(1U, sent_results.size());
   EXPECT_EQ(sent_results[0].location, 0);
diff --git a/chrome/browser/spellchecker/spellcheck_message_filter_unittest.cc b/chrome/browser/spellchecker/spellcheck_message_filter_unittest.cc
index ecde185..696ccb4 100644
--- a/chrome/browser/spellchecker/spellcheck_message_filter_unittest.cc
+++ b/chrome/browser/spellchecker/spellcheck_message_filter_unittest.cc
@@ -101,15 +101,13 @@
       kRouteId, kCallbackId, kMarkers, kSuccess, kText, results);
   EXPECT_EQ(static_cast<size_t>(1), filter->sent_messages.size());
 
-  int sent_identifier = -1;
-  bool sent_success = false;
-  base::string16 sent_text;
-  std::vector<SpellCheckResult> sent_results;
-  bool ok = SpellCheckMsg_RespondSpellingService::Read(filter->sent_messages[0],
-                                                       &sent_identifier,
-                                                       &sent_success,
-                                                       &sent_text,
-                                                       &sent_results);
+  SpellCheckMsg_RespondSpellingService::Param params;
+  bool ok = SpellCheckMsg_RespondSpellingService::Read(
+      filter->sent_messages[0], & params);
+  int sent_identifier = params.a;
+  bool sent_success = params.b;
+  base::string16 sent_text = params.c;
+  std::vector<SpellCheckResult> sent_results = params.d;
   EXPECT_TRUE(ok);
   EXPECT_EQ(kCallbackId, sent_identifier);
   EXPECT_EQ(kSuccess, sent_success);
@@ -134,15 +132,11 @@
       true,  base::ASCIIToUTF16("Helllo walrd"), results);
   EXPECT_EQ(static_cast<size_t>(1), filter->sent_messages.size());
 
-  int sent_identifier = -1;
-  bool sent_success = false;
-  base::string16 sent_text;
-  std::vector<SpellCheckResult> sent_results;
-  bool ok = SpellCheckMsg_RespondSpellingService::Read(filter->sent_messages[0],
-                                                       &sent_identifier,
-                                                       &sent_success,
-                                                       &sent_text,
-                                                       &sent_results);
+  SpellCheckMsg_RespondSpellingService::Param params;
+  bool ok = SpellCheckMsg_RespondSpellingService::Read(
+      filter->sent_messages[0], & params);
+  base::string16 sent_text = params.c;
+  std::vector<SpellCheckResult> sent_results = params.d;
   EXPECT_TRUE(ok);
   EXPECT_EQ(static_cast<size_t>(2), sent_results.size());
 }
diff --git a/chrome/renderer/spellchecker/spellcheck_provider_mac_unittest.cc b/chrome/renderer/spellchecker/spellcheck_provider_mac_unittest.cc
index bab1107d5..5188d39a 100644
--- a/chrome/renderer/spellchecker/spellcheck_provider_mac_unittest.cc
+++ b/chrome/renderer/spellchecker/spellcheck_provider_mac_unittest.cc
@@ -16,36 +16,14 @@
 
 class SpellCheckProviderMacTest : public SpellCheckProviderTest {};
 
-struct MessageParameters {
-  MessageParameters()
-      : router_id(0),
-        request_id(0) {}
-
-  int router_id;
-  int request_id;
-  base::string16 text;
-  std::vector<SpellCheckMarker> markers;
-};
-
-MessageParameters ReadRequestTextCheck(IPC::Message* message) {
-  MessageParameters parameters;
-  bool ok = SpellCheckHostMsg_RequestTextCheck::Read(
-      message,
-      &parameters.router_id,
-      &parameters.request_id,
-      &parameters.text,
-      &parameters.markers);
-  EXPECT_TRUE(ok);
-  return parameters;
-}
-
-void FakeMessageArrival(SpellCheckProvider* provider,
-                        const MessageParameters& parameters) {
+void FakeMessageArrival(
+    SpellCheckProvider* provider,
+    const SpellCheckHostMsg_RequestTextCheck::Param& parameters) {
   std::vector<SpellCheckResult> fake_result;
   bool handled = provider->OnMessageReceived(
       SpellCheckMsg_RespondTextCheck(
           0,
-          parameters.request_id,
+          parameters.b,
           fake_result));
   EXPECT_TRUE(handled);
 }
@@ -60,11 +38,13 @@
   EXPECT_EQ(provider_.messages_.size(), 1U);
   EXPECT_EQ(provider_.pending_text_request_size(), 1U);
 
-  MessageParameters read_parameters =
-      ReadRequestTextCheck(provider_.messages_[0]);
-  EXPECT_EQ(read_parameters.text, base::UTF8ToUTF16("hello "));
+  SpellCheckHostMsg_RequestTextCheck::Param read_parameters1;
+  bool ok = SpellCheckHostMsg_RequestTextCheck::Read(
+      provider_.messages_[0], &read_parameters1);
+  EXPECT_TRUE(ok);
+  EXPECT_EQ(read_parameters1.c, base::UTF8ToUTF16("hello "));
 
-  FakeMessageArrival(&provider_, read_parameters);
+  FakeMessageArrival(&provider_, read_parameters1);
   EXPECT_EQ(completion.completion_count_, 1U);
   EXPECT_EQ(provider_.pending_text_request_size(), 0U);
 }
@@ -84,13 +64,17 @@
   EXPECT_EQ(provider_.messages_.size(), 2U);
   EXPECT_EQ(provider_.pending_text_request_size(), 2U);
 
-  MessageParameters read_parameters1 =
-      ReadRequestTextCheck(provider_.messages_[0]);
-  EXPECT_EQ(read_parameters1.text, base::UTF8ToUTF16("hello "));
+  SpellCheckHostMsg_RequestTextCheck::Param read_parameters1;
+  bool ok = SpellCheckHostMsg_RequestTextCheck::Read(
+      provider_.messages_[0], &read_parameters1);
+  EXPECT_TRUE(ok);
+  EXPECT_EQ(read_parameters1.c, base::UTF8ToUTF16("hello "));
 
-  MessageParameters read_parameters2 =
-      ReadRequestTextCheck(provider_.messages_[1]);
-  EXPECT_EQ(read_parameters2.text, base::UTF8ToUTF16("bye "));
+  SpellCheckHostMsg_RequestTextCheck::Param read_parameters2;
+  ok = SpellCheckHostMsg_RequestTextCheck::Read(
+      provider_.messages_[1], &read_parameters2);
+  EXPECT_TRUE(ok);
+  EXPECT_EQ(read_parameters2.c, base::UTF8ToUTF16("bye "));
 
   FakeMessageArrival(&provider_, read_parameters1);
   EXPECT_EQ(completion1.completion_count_, 1U);
diff --git a/chrome/renderer/spellchecker/spellcheck_provider_test.cc b/chrome/renderer/spellchecker/spellcheck_provider_test.cc
index d0d80fa..d28cd886 100644
--- a/chrome/renderer/spellchecker/spellcheck_provider_test.cc
+++ b/chrome/renderer/spellchecker/spellcheck_provider_test.cc
@@ -40,13 +40,12 @@
 }
 
 bool TestingSpellCheckProvider::Send(IPC::Message* message)  {
+#if !defined(OS_MACOSX)
   // Call our mock message handlers.
   bool handled = true;
   IPC_BEGIN_MESSAGE_MAP(TestingSpellCheckProvider, *message)
-#if !defined(OS_MACOSX)
     IPC_MESSAGE_HANDLER(SpellCheckHostMsg_CallSpellingService,
                         OnCallSpellingService)
-#endif
     IPC_MESSAGE_UNHANDLED(handled = false)
   IPC_END_MESSAGE_MAP()
 
@@ -54,6 +53,7 @@
     delete message;
     return true;
   }
+#endif
 
   messages_.push_back(message);
   return true;
diff --git a/content/browser/browser_plugin/test_browser_plugin_guest.cc b/content/browser/browser_plugin/test_browser_plugin_guest.cc
index 1e6edfd..ed658624 100644
--- a/content/browser/browser_plugin/test_browser_plugin_guest.cc
+++ b/content/browser/browser_plugin/test_browser_plugin_guest.cc
@@ -35,9 +35,9 @@
 void TestBrowserPluginGuest::SendMessageToEmbedder(IPC::Message* msg) {
   if (msg->type() == BrowserPluginMsg_UpdateRect::ID) {
     update_rect_count_++;
-    int instance_id = 0;
-    BrowserPluginMsg_UpdateRect_Params params;
-    BrowserPluginMsg_UpdateRect::Read(msg, &instance_id, &params);
+    BrowserPluginMsg_UpdateRect::Param param;
+    BrowserPluginMsg_UpdateRect::Read(msg, &param);
+    BrowserPluginMsg_UpdateRect_Params params = param.b;
     last_view_size_observed_ = params.view_size;
     if (!expected_auto_view_size_.IsEmpty() &&
         expected_auto_view_size_ == params.view_size) {
diff --git a/content/browser/loader/resource_dispatcher_host_impl.cc b/content/browser/loader/resource_dispatcher_host_impl.cc
index 7448116..917d0e1 100644
--- a/content/browser/loader/resource_dispatcher_host_impl.cc
+++ b/content/browser/loader/resource_dispatcher_host_impl.cc
@@ -859,10 +859,10 @@
 }
 
 void ResourceDispatcherHostImpl::OnRequestResource(
-    const IPC::Message& message,
+    int routing_id,
     int request_id,
     const ResourceHostMsg_Request& request_data) {
-  BeginRequest(request_id, request_data, NULL, message.routing_id());
+  BeginRequest(request_id, request_data, NULL, routing_id);
 }
 
 // Begins a resource request with the given params on behalf of the specified
diff --git a/content/browser/loader/resource_dispatcher_host_impl.h b/content/browser/loader/resource_dispatcher_host_impl.h
index 449bc13..8f839c8 100644
--- a/content/browser/loader/resource_dispatcher_host_impl.h
+++ b/content/browser/loader/resource_dispatcher_host_impl.h
@@ -340,7 +340,7 @@
                                       int route_id,
                                       bool cancel_requests);
 
-  void OnRequestResource(const IPC::Message& msg,
+  void OnRequestResource(int routing_id,
                          int request_id,
                          const ResourceHostMsg_Request& request_data);
   void OnSyncLoad(int request_id,
diff --git a/content/browser/renderer_host/input/touch_input_browsertest.cc b/content/browser/renderer_host/input/touch_input_browsertest.cc
index a92fd26..270f39c 100644
--- a/content/browser/renderer_host/input/touch_input_browsertest.cc
+++ b/content/browser/renderer_host/input/touch_input_browsertest.cc
@@ -111,10 +111,10 @@
   virtual bool OnMessageReceived(const IPC::Message& message,
                                  bool* message_was_ok) OVERRIDE {
     if (message.type() == InputHostMsg_HandleInputEvent_ACK::ID) {
-      ui::LatencyInfo latency;
-      WebInputEvent::Type type = WebInputEvent::Undefined;
-      InputEventAckState ack = INPUT_EVENT_ACK_STATE_UNKNOWN;
-      InputHostMsg_HandleInputEvent_ACK::Read(&message, &type, &ack, &latency);
+      InputHostMsg_HandleInputEvent_ACK::Param params;
+      InputHostMsg_HandleInputEvent_ACK::Read(&message, &params);
+      WebInputEvent::Type type = params.a;
+      InputEventAckState ack = params.b;
       BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
           base::Bind(&InputEventMessageFilter::ReceivedEventAck,
                      this, type, ack));
diff --git a/content/browser/renderer_host/media/audio_renderer_host_unittest.cc b/content/browser/renderer_host/media/audio_renderer_host_unittest.cc
index 38a7f0a..df9797d 100644
--- a/content/browser/renderer_host/media/audio_renderer_host_unittest.cc
+++ b/content/browser/renderer_host/media/audio_renderer_host_unittest.cc
@@ -89,9 +89,9 @@
     bool handled = true;
     IPC_BEGIN_MESSAGE_MAP(MockAudioRendererHost, *message)
       IPC_MESSAGE_HANDLER(AudioMsg_NotifyStreamCreated,
-                          OnStreamCreated)
+                          OnNotifyStreamCreated)
       IPC_MESSAGE_HANDLER(AudioMsg_NotifyStreamStateChanged,
-                          OnStreamStateChanged)
+                          OnNotifyStreamStateChanged)
       IPC_MESSAGE_UNHANDLED(handled = false)
     IPC_END_MESSAGE_MAP()
     EXPECT_TRUE(handled);
@@ -100,15 +100,14 @@
     return true;
   }
 
-  void OnStreamCreated(const IPC::Message& msg,
-                       int stream_id,
-                       base::SharedMemoryHandle handle,
+  void OnNotifyStreamCreated(int stream_id,
+                             base::SharedMemoryHandle handle,
 #if defined(OS_WIN)
-                       base::SyncSocket::Handle socket_handle,
+                             base::SyncSocket::Handle socket_handle,
 #else
-                       base::FileDescriptor socket_descriptor,
+                             base::FileDescriptor socket_descriptor,
 #endif
-                       uint32 length) {
+                             uint32 length) {
     // Maps the shared memory.
     shared_memory_.reset(new base::SharedMemory(handle, false));
     CHECK(shared_memory_->Map(length));
@@ -128,9 +127,8 @@
     OnStreamCreated(stream_id, length);
   }
 
-  void OnStreamStateChanged(const IPC::Message& msg,
-                            int stream_id,
-                            media::AudioOutputIPCDelegate::State state) {
+  void OnNotifyStreamStateChanged(int stream_id,
+                                  media::AudioOutputIPCDelegate::State state) {
     switch (state) {
       case media::AudioOutputIPCDelegate::kPlaying:
         OnStreamPlaying(stream_id);
diff --git a/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc b/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc
index a181899..d3df02e 100644
--- a/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc
+++ b/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc
@@ -51,7 +51,8 @@
       const scoped_refptr<base::MessageLoopProxy>& message_loop,
       MediaStreamManager* manager)
       : MediaStreamDispatcherHost(kProcessId, salt_callback, manager),
-        message_loop_(message_loop) {}
+        message_loop_(message_loop),
+        current_ipc_(NULL) {}
 
   // A list of mock methods.
   MOCK_METHOD4(OnStreamGenerated,
@@ -114,35 +115,36 @@
   // conversation between this object and the renderer.
   virtual bool Send(IPC::Message* message) OVERRIDE {
     CHECK(message);
+    current_ipc_ = message;
 
     // In this method we dispatch the messages to the according handlers as if
     // we are the renderer.
     bool handled = true;
     IPC_BEGIN_MESSAGE_MAP(MockMediaStreamDispatcherHost, *message)
-      IPC_MESSAGE_HANDLER(MediaStreamMsg_StreamGenerated, OnStreamGenerated)
+      IPC_MESSAGE_HANDLER(MediaStreamMsg_StreamGenerated,
+                          OnStreamGeneratedInternal)
       IPC_MESSAGE_HANDLER(MediaStreamMsg_StreamGenerationFailed,
-                          OnStreamGenerationFailed)
-      IPC_MESSAGE_HANDLER(MediaStreamMsg_DeviceStopped, OnDeviceStopped)
-      IPC_MESSAGE_HANDLER(MediaStreamMsg_DeviceOpened, OnDeviceOpened)
-      IPC_MESSAGE_HANDLER(MediaStreamMsg_DevicesEnumerated,
-                          OnDevicesEnumerated)
+                          OnStreamGenerationFailedInternal)
+      IPC_MESSAGE_HANDLER(MediaStreamMsg_DeviceStopped, OnDeviceStoppedInternal)
+      IPC_MESSAGE_HANDLER(MediaStreamMsg_DeviceOpened, OnDeviceOpenedInternal)
+      IPC_MESSAGE_HANDLER(MediaStreamMsg_DevicesEnumerated, OnDevicesEnumerated)
       IPC_MESSAGE_UNHANDLED(handled = false)
     IPC_END_MESSAGE_MAP()
     EXPECT_TRUE(handled);
 
     delete message;
+    current_ipc_ = NULL;
     return true;
   }
 
   // These handler methods do minimal things and delegate to the mock methods.
-  void OnStreamGenerated(
-      const IPC::Message& msg,
+  void OnStreamGeneratedInternal(
       int request_id,
       std::string label,
       StreamDeviceInfoArray audio_device_list,
       StreamDeviceInfoArray video_device_list) {
-    OnStreamGenerated(msg.routing_id(), request_id, audio_device_list.size(),
-        video_device_list.size());
+    OnStreamGenerated(current_ipc_->routing_id(), request_id,
+                      audio_device_list.size(), video_device_list.size());
     // Notify that the event have occurred.
     base::Closure quit_closure = quit_closures_.front();
     quit_closures_.pop();
@@ -153,11 +155,10 @@
     video_devices_ = video_device_list;
   }
 
-  void OnStreamGenerationFailed(
-      const IPC::Message& msg,
+  void OnStreamGenerationFailedInternal(
       int request_id,
       content::MediaStreamRequestResult result) {
-    OnStreamGenerationFailed(msg.routing_id(), request_id, result);
+    OnStreamGenerationFailed(current_ipc_->routing_id(), request_id, result);
     if (!quit_closures_.empty()) {
       base::Closure quit_closure = quit_closures_.front();
       quit_closures_.pop();
@@ -167,21 +168,19 @@
     label_= "";
   }
 
-  void OnDeviceStopped(const IPC::Message& msg,
-                       const std::string& label,
-                       const content::StreamDeviceInfo& device) {
+  void OnDeviceStoppedInternal(const std::string& label,
+                               const content::StreamDeviceInfo& device) {
     if (IsVideoMediaType(device.device.type))
       EXPECT_TRUE(StreamDeviceInfo::IsEqual(device, video_devices_[0]));
     if (IsAudioMediaType(device.device.type))
       EXPECT_TRUE(StreamDeviceInfo::IsEqual(device, audio_devices_[0]));
 
-    OnDeviceStopped(msg.routing_id());
+    OnDeviceStopped(current_ipc_->routing_id());
   }
 
-  void OnDeviceOpened(const IPC::Message& msg,
-                      int request_id,
-                      const std::string& label,
-                      const StreamDeviceInfo& device) {
+  void OnDeviceOpenedInternal(int request_id,
+                              const std::string& label,
+                              const StreamDeviceInfo& device) {
     base::Closure quit_closure = quit_closures_.front();
     quit_closures_.pop();
     message_loop_->PostTask(FROM_HERE, base::ResetAndReturn(&quit_closure));
@@ -189,8 +188,7 @@
     opened_device_ = device;
   }
 
-  void OnDevicesEnumerated(const IPC::Message& msg,
-                           int request_id,
+  void OnDevicesEnumerated(int request_id,
                            const StreamDeviceInfoArray& devices) {
     base::Closure quit_closure = quit_closures_.front();
     quit_closures_.pop();
@@ -199,7 +197,7 @@
   }
 
   scoped_refptr<base::MessageLoopProxy> message_loop_;
-
+  IPC::Message* current_ipc_;
   std::queue<base::Closure> quit_closures_;
 };
 
diff --git a/content/browser/renderer_host/p2p/socket_dispatcher_host.cc b/content/browser/renderer_host/p2p/socket_dispatcher_host.cc
index be63c02..4a09469 100644
--- a/content/browser/renderer_host/p2p/socket_dispatcher_host.cc
+++ b/content/browser/renderer_host/p2p/socket_dispatcher_host.cc
@@ -160,8 +160,7 @@
   return (it == sockets_.end()) ? NULL : it->second;
 }
 
-void P2PSocketDispatcherHost::OnStartNetworkNotifications(
-    const IPC::Message& msg) {
+void P2PSocketDispatcherHost::OnStartNetworkNotifications() {
   if (!monitoring_networks_) {
     net::NetworkChangeNotifier::AddIPAddressObserver(this);
     monitoring_networks_ = true;
@@ -172,8 +171,7 @@
           &P2PSocketDispatcherHost::DoGetNetworkList, this));
 }
 
-void P2PSocketDispatcherHost::OnStopNetworkNotifications(
-    const IPC::Message& msg) {
+void P2PSocketDispatcherHost::OnStopNetworkNotifications() {
   if (monitoring_networks_) {
     net::NetworkChangeNotifier::RemoveIPAddressObserver(this);
     monitoring_networks_ = false;
diff --git a/content/browser/renderer_host/p2p/socket_dispatcher_host.h b/content/browser/renderer_host/p2p/socket_dispatcher_host.h
index 1f45691..84bba57 100644
--- a/content/browser/renderer_host/p2p/socket_dispatcher_host.h
+++ b/content/browser/renderer_host/p2p/socket_dispatcher_host.h
@@ -60,9 +60,8 @@
   P2PSocketHost* LookupSocket(int socket_id);
 
   // Handlers for the messages coming from the renderer.
-  void OnStartNetworkNotifications(const IPC::Message& msg);
-  void OnStopNetworkNotifications(const IPC::Message& msg);
-
+  void OnStartNetworkNotifications();
+  void OnStopNetworkNotifications();
   void OnGetHostAddress(const std::string& host_name,
                         int32 request_id);
 
diff --git a/content/browser/renderer_host/render_message_filter.cc b/content/browser/renderer_host/render_message_filter.cc
index a47d71a..38950814 100644
--- a/content/browser/renderer_host/render_message_filter.cc
+++ b/content/browser/renderer_host/render_message_filter.cc
@@ -881,7 +881,7 @@
 }
 #endif
 
-void RenderMessageFilter::OnDownloadUrl(const IPC::Message& message,
+void RenderMessageFilter::OnDownloadUrl(int render_view_id,
                                         const GURL& url,
                                         const Referrer& referrer,
                                         const base::string16& suggested_name,
@@ -907,7 +907,7 @@
       true,  // is_content_initiated
       resource_context_,
       render_process_id_,
-      message.routing_id(),
+      render_view_id,
       false,
       save_info.Pass(),
       content::DownloadItem::kInvalidId,
diff --git a/content/browser/renderer_host/render_message_filter.h b/content/browser/renderer_host/render_message_filter.h
index 2814a04f..0f355d7 100644
--- a/content/browser/renderer_host/render_message_filter.h
+++ b/content/browser/renderer_host/render_message_filter.h
@@ -193,7 +193,7 @@
   void OnOpenChannelToPpapiBroker(int routing_id,
                                   const base::FilePath& path);
   void OnGenerateRoutingID(int* route_id);
-  void OnDownloadUrl(const IPC::Message& message,
+  void OnDownloadUrl(int render_view_id,
                      const GURL& url,
                      const Referrer& referrer,
                      const base::string16& suggested_name,
diff --git a/content/browser/renderer_host/render_widget_host_unittest.cc b/content/browser/renderer_host/render_widget_host_unittest.cc
index 4cd7a3d3..11241ab 100644
--- a/content/browser/renderer_host/render_widget_host_unittest.cc
+++ b/content/browser/renderer_host/render_widget_host_unittest.cc
@@ -2242,15 +2242,13 @@
 }
 
 std::string GetInputMessageTypes(RenderWidgetHostProcess* process) {
-  const WebInputEvent* event = NULL;
-  ui::LatencyInfo latency_info;
-  bool is_keyboard_shortcut;
   std::string result;
   for (size_t i = 0; i < process->sink().message_count(); ++i) {
     const IPC::Message *message = process->sink().GetMessageAt(i);
     EXPECT_EQ(InputMsg_HandleInputEvent::ID, message->type());
-    EXPECT_TRUE(InputMsg_HandleInputEvent::Read(
-        message, &event, &latency_info, &is_keyboard_shortcut));
+    InputMsg_HandleInputEvent::Param params;
+    EXPECT_TRUE(InputMsg_HandleInputEvent::Read(message, &params));
+    const WebInputEvent* event = params.a;
     if (i != 0)
       result += " ";
     result += WebInputEventTraits::GetName(event->type);
@@ -2573,14 +2571,12 @@
 void CheckLatencyInfoComponentInMessage(RenderWidgetHostProcess* process,
                                         int64 component_id,
                                         WebInputEvent::Type input_type) {
-  const WebInputEvent* event = NULL;
-  ui::LatencyInfo latency_info;
-  bool is_keyboard_shortcut;
   const IPC::Message* message = process->sink().GetUniqueMessageMatching(
       InputMsg_HandleInputEvent::ID);
   ASSERT_TRUE(message);
-  EXPECT_TRUE(InputMsg_HandleInputEvent::Read(
-      message, &event, &latency_info, &is_keyboard_shortcut));
+  InputMsg_HandleInputEvent::Param params;
+  EXPECT_TRUE(InputMsg_HandleInputEvent::Read(message, &params));
+  ui::LatencyInfo latency_info = params.b;
   EXPECT_TRUE(latency_info.FindLatency(
       ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
       component_id,
diff --git a/content/browser/shared_worker/shared_worker_host.cc b/content/browser/shared_worker/shared_worker_host.cc
index 6f6e4207..869291b 100644
--- a/content/browser/shared_worker/shared_worker_host.cc
+++ b/content/browser/shared_worker/shared_worker_host.cc
@@ -237,12 +237,12 @@
     return;
   if (message.type() == WorkerMsg_Connect::ID) {
     // Crack the SharedWorker Connect message to setup routing for the port.
-    int sent_message_port_id;
-    int new_routing_id;
-    if (!WorkerMsg_Connect::Read(
-            &message, &sent_message_port_id, &new_routing_id)) {
+    WorkerMsg_Connect::Param param;
+    if (!WorkerMsg_Connect::Read(&message, &param))
       return;
-    }
+    int sent_message_port_id = param.a;
+    int new_routing_id = param.b;
+
     DCHECK(container_render_filter_);
     new_routing_id = container_render_filter_->GetNextRoutingID();
     MessagePortService::GetInstance()->UpdateMessagePort(
diff --git a/content/browser/shared_worker/shared_worker_service_impl_unittest.cc b/content/browser/shared_worker/shared_worker_service_impl_unittest.cc
index 878d3bc..a56f6af5 100644
--- a/content/browser/shared_worker/shared_worker_service_impl_unittest.cc
+++ b/content/browser/shared_worker/shared_worker_service_impl_unittest.cc
@@ -357,8 +357,10 @@
   scoped_ptr<IPC::Message> msg(renderer_host->PopMessage());
   EXPECT_EQ(WorkerMsg_Connect::ID, msg->type());
   EXPECT_EQ(expected_msg_route_id, msg->routing_id());
-  int port_id;
-  EXPECT_TRUE(WorkerMsg_Connect::Read(msg.get(), &port_id, routing_id));
+  WorkerMsg_Connect::Param params;
+  EXPECT_TRUE(WorkerMsg_Connect::Read(msg.get(), &params));
+  int port_id = params.a;
+  *routing_id = params.b;
   EXPECT_EQ(expected_sent_message_port_id, port_id);
 }
 
@@ -368,11 +370,9 @@
   scoped_ptr<IPC::Message> msg(renderer_host->PopMessage());
   EXPECT_EQ(MessagePortMsg_Message::ID, msg->type());
   EXPECT_EQ(expected_msg_route_id, msg->routing_id());
-  base::string16 data;
-  std::vector<int> sent_message_port_ids;
-  std::vector<int> new_routing_ids;
-  EXPECT_TRUE(MessagePortMsg_Message::Read(
-      msg.get(), &data, &sent_message_port_ids, &new_routing_ids));
+  MessagePortMsg_Message::Param params;
+  EXPECT_TRUE(MessagePortMsg_Message::Read(msg.get(), &params));
+  base::string16 data = params.a;
   EXPECT_EQ(base::ASCIIToUTF16(expected_data), data);
 }
 
diff --git a/content/browser/worker_host/worker_process_host.cc b/content/browser/worker_host/worker_process_host.cc
index ee9548e8..f00080e 100644
--- a/content/browser/worker_host/worker_process_host.cc
+++ b/content/browser/worker_host/worker_process_host.cc
@@ -510,12 +510,12 @@
     WorkerInstance* instance) {
   if (message.type() == WorkerMsg_Connect::ID) {
     // Crack the SharedWorker Connect message to setup routing for the port.
-    int sent_message_port_id;
-    int new_routing_id;
-    if (!WorkerMsg_Connect::Read(
-            &message, &sent_message_port_id, &new_routing_id)) {
+    WorkerMsg_Connect::Param params;
+    if (!WorkerMsg_Connect::Read(&message, &params))
       return;
-    }
+
+    int sent_message_port_id = params.a;
+    int new_routing_id = params.b;
     new_routing_id = worker_message_filter_->GetNextRoutingID();
     MessagePortService::GetInstance()->UpdateMessagePort(
         sent_message_port_id,
diff --git a/content/child/resource_dispatcher_unittest.cc b/content/child/resource_dispatcher_unittest.cc
index b12db6b..9dfb43e1 100644
--- a/content/child/resource_dispatcher_unittest.cc
+++ b/content/child/resource_dispatcher_unittest.cc
@@ -112,10 +112,11 @@
   // returning the hardcoded file contents.
   void ProcessMessages() {
     while (!message_queue_.empty()) {
-      int request_id;
-      ResourceHostMsg_Request request;
+      ResourceHostMsg_RequestResource::Param params;
       ASSERT_TRUE(ResourceHostMsg_RequestResource::Read(
-          &message_queue_[0], &request_id, &request));
+          &message_queue_[0], &params));
+      int request_id = params.b;
+      ResourceHostMsg_Request request = params.c;
 
       // check values
       EXPECT_EQ(test_page_url, request.url.spec());
diff --git a/content/common/resource_messages.h b/content/common/resource_messages.h
index a77864f..7c39d4f 100644
--- a/content/common/resource_messages.h
+++ b/content/common/resource_messages.h
@@ -302,7 +302,8 @@
 // Resource messages sent from the renderer to the browser.
 
 // Makes a resource request via the browser.
-IPC_MESSAGE_ROUTED2(ResourceHostMsg_RequestResource,
+IPC_MESSAGE_CONTROL3(ResourceHostMsg_RequestResource,
+                    int /* routing_id */,
                     int /* request_id */,
                     ResourceHostMsg_Request)
 
diff --git a/content/common/view_messages.h b/content/common/view_messages.h
index 3d7e3c6f..4dadd337 100644
--- a/content/common/view_messages.h
+++ b/content/common/view_messages.h
@@ -1271,11 +1271,12 @@
                     bool /* blocked by policy */)
 
 // Initiates a download based on user actions like 'ALT+click'.
-IPC_MESSAGE_ROUTED4(ViewHostMsg_DownloadUrl,
-                    GURL     /* url */,
-                    content::Referrer /* referrer */,
-                    base::string16 /* suggested_name */,
-                    bool /* use prompt for save location */)
+IPC_MESSAGE_CONTROL5(ViewHostMsg_DownloadUrl,
+                     int /* render_view_id */,
+                     GURL /* url */,
+                     content::Referrer /* referrer */,
+                     base::string16 /* suggested_name */,
+                     bool /* use prompt for save location */)
 
 // Used to go to the session history entry at the given offset (ie, -1 will
 // return the "back" item).
diff --git a/content/renderer/browser_plugin/browser_plugin_browsertest.cc b/content/renderer/browser_plugin/browser_plugin_browsertest.cc
index f277994..b7eb616 100644
--- a/content/renderer/browser_plugin/browser_plugin_browsertest.cc
+++ b/content/renderer/browser_plugin/browser_plugin_browsertest.cc
@@ -269,9 +269,9 @@
             BrowserPluginHostMsg_NavigateGuest::ID);
     ASSERT_TRUE(msg);
 
-    int instance_id = 0;
-    std::string src;
-    BrowserPluginHostMsg_NavigateGuest::Read(msg, &instance_id, &src);
+    BrowserPluginHostMsg_NavigateGuest::Param params;
+    BrowserPluginHostMsg_NavigateGuest::Read(msg, &params);
+    std::string src = params.b;
     EXPECT_EQ("bar", src);
     std::string src_value =
         ExecuteScriptAndReturnString(
@@ -328,8 +328,10 @@
       browser_plugin_manager()->sink().GetUniqueMessageMatching(
           BrowserPluginHostMsg_ResizeGuest::ID);
   ASSERT_TRUE(msg);
-  BrowserPluginHostMsg_ResizeGuest_Params params;
-  BrowserPluginHostMsg_ResizeGuest::Read(msg, &instance_id, &params);
+  BrowserPluginHostMsg_ResizeGuest::Param param;
+  BrowserPluginHostMsg_ResizeGuest::Read(msg, &param);
+  instance_id = param.a;
+  BrowserPluginHostMsg_ResizeGuest_Params params = param.b;
   EXPECT_EQ(641, params.view_rect.width());
   EXPECT_EQ(480, params.view_rect.height());
 
@@ -576,13 +578,10 @@
             BrowserPluginHostMsg_SetAutoSize::ID);
     ASSERT_TRUE(auto_size_msg);
 
-    int instance_id = 0;
-    BrowserPluginHostMsg_AutoSize_Params auto_size_params;
-    BrowserPluginHostMsg_ResizeGuest_Params resize_params;
-    BrowserPluginHostMsg_SetAutoSize::Read(auto_size_msg,
-                                           &instance_id,
-                                           &auto_size_params,
-                                           &resize_params);
+    BrowserPluginHostMsg_SetAutoSize::Param param;
+    BrowserPluginHostMsg_SetAutoSize::Read(auto_size_msg, &param);
+    BrowserPluginHostMsg_AutoSize_Params auto_size_params = param.b;
+    BrowserPluginHostMsg_ResizeGuest_Params resize_params = param.c;
     EXPECT_FALSE(auto_size_params.enable);
     // These value are not populated (as an optimization) if autosize is
     // disabled.
diff --git a/content/renderer/browser_plugin/browser_plugin_manager_impl.cc b/content/renderer/browser_plugin/browser_plugin_manager_impl.cc
index 4f0bed07..5ce7ebb 100644
--- a/content/renderer/browser_plugin/browser_plugin_manager_impl.cc
+++ b/content/renderer/browser_plugin/browser_plugin_manager_impl.cc
@@ -74,7 +74,6 @@
 }
 
 void BrowserPluginManagerImpl::OnAllocateInstanceIDACK(
-    const IPC::Message& message,
     int request_id,
     int guest_instance_id) {
   InstanceIDMap::iterator it =
diff --git a/content/renderer/browser_plugin/browser_plugin_manager_impl.h b/content/renderer/browser_plugin/browser_plugin_manager_impl.h
index 2ed4135..384313be 100644
--- a/content/renderer/browser_plugin/browser_plugin_manager_impl.h
+++ b/content/renderer/browser_plugin/browser_plugin_manager_impl.h
@@ -38,8 +38,7 @@
  private:
   virtual ~BrowserPluginManagerImpl();
 
-  void OnAllocateInstanceIDACK(const IPC::Message& message,
-                               int request_id,
+  void OnAllocateInstanceIDACK(int request_id,
                                int guest_instance_id);
 
   int request_id_counter_;
diff --git a/content/renderer/input/input_event_filter.cc b/content/renderer/input/input_event_filter.cc
index cd5a8cd3..abd30c0 100644
--- a/content/renderer/input/input_event_filter.cc
+++ b/content/renderer/input/input_event_filter.cc
@@ -146,12 +146,12 @@
   }
 
   int routing_id = message.routing_id();
-  ui::LatencyInfo latency_info;
-  const WebInputEvent* event = NULL;
-  bool is_keyboard_shortcut;
-  if (!InputMsg_HandleInputEvent::Read(
-          &message, &event, &latency_info, &is_keyboard_shortcut))
+  InputMsg_HandleInputEvent::Param params;
+  if (!InputMsg_HandleInputEvent::Read(&message, &params))
     return;
+  const WebInputEvent* event = params.a;
+  ui::LatencyInfo latency_info = params.b;
+  bool is_keyboard_shortcut = params.c;
   DCHECK(event);
 
   InputEventAckState ack = handler_.Run(routing_id, event, &latency_info);
diff --git a/content/renderer/input/input_event_filter_unittest.cc b/content/renderer/input/input_event_filter_unittest.cc
index 5da8b79..cfcc937 100644
--- a/content/renderer/input/input_event_filter_unittest.cc
+++ b/content/renderer/input/input_event_filter_unittest.cc
@@ -178,13 +178,11 @@
     EXPECT_EQ(kTestRoutingID, message->routing_id());
     EXPECT_EQ(InputHostMsg_HandleInputEvent_ACK::ID, message->type());
 
-    WebInputEvent::Type event_type = WebInputEvent::Undefined;
-    InputEventAckState ack_result = INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
-    ui::LatencyInfo latency_info;
-    EXPECT_TRUE(InputHostMsg_HandleInputEvent_ACK::Read(message,
-                                                        &event_type,
-                                                        &ack_result,
-                                                        &latency_info));
+    InputHostMsg_HandleInputEvent_ACK::Param params;
+    EXPECT_TRUE(InputHostMsg_HandleInputEvent_ACK::Read(message, &params));
+    WebInputEvent::Type event_type = params.a;
+    InputEventAckState ack_result = params.b;
+
     EXPECT_EQ(kEvents[i].type, event_type);
     EXPECT_EQ(ack_result, INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
 
@@ -206,11 +204,9 @@
     const IPC::Message& message = message_recorder_.message_at(i);
 
     ASSERT_EQ(InputMsg_HandleInputEvent::ID, message.type());
-    const WebInputEvent* event = NULL;
-    ui::LatencyInfo latency_info;
-    bool is_kbd_shortcut;
-    EXPECT_TRUE(InputMsg_HandleInputEvent::Read(
-        &message, &event, &latency_info, &is_kbd_shortcut));
+    InputMsg_HandleInputEvent::Param params;
+    EXPECT_TRUE(InputMsg_HandleInputEvent::Read(&message, &params));
+    const WebInputEvent* event = params.a;
 
     EXPECT_EQ(kEvents[i].size, event->size);
     EXPECT_TRUE(memcmp(&kEvents[i], event, event->size) == 0);
@@ -234,13 +230,10 @@
     EXPECT_EQ(kTestRoutingID, message->routing_id());
     EXPECT_EQ(InputHostMsg_HandleInputEvent_ACK::ID, message->type());
 
-    WebInputEvent::Type event_type = WebInputEvent::Undefined;
-    InputEventAckState ack_result = INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
-    ui::LatencyInfo latency_info;
-    EXPECT_TRUE(InputHostMsg_HandleInputEvent_ACK::Read(message,
-                                                        &event_type,
-                                                        &ack_result,
-                                                        &latency_info));
+    InputHostMsg_HandleInputEvent_ACK::Param params;
+    EXPECT_TRUE(InputHostMsg_HandleInputEvent_ACK::Read(message, &params));
+    WebInputEvent::Type event_type = params.a;
+    InputEventAckState ack_result = params.b;
     EXPECT_EQ(kEvents[i].type, event_type);
     EXPECT_EQ(ack_result, INPUT_EVENT_ACK_STATE_CONSUMED);
   }
diff --git a/content/renderer/render_view_browsertest.cc b/content/renderer/render_view_browsertest.cc
index b06151b9..a231428c 100644
--- a/content/renderer/render_view_browsertest.cc
+++ b/content/renderer/render_view_browsertest.cc
@@ -537,9 +537,10 @@
   const IPC::Message* msg_A = render_thread_->sink().GetUniqueMessageMatching(
       ViewHostMsg_UpdateState::ID);
   ASSERT_TRUE(msg_A);
-  int page_id_A;
-  PageState state_A;
-  ViewHostMsg_UpdateState::Read(msg_A, &page_id_A, &state_A);
+  ViewHostMsg_UpdateState::Param params;
+  ViewHostMsg_UpdateState::Read(msg_A, &params);
+  int page_id_A = params.a;
+  PageState state_A = params.b;
   EXPECT_EQ(1, page_id_A);
   render_thread_->sink().ClearMessages();
 
@@ -609,9 +610,10 @@
   const IPC::Message* msg_A = render_thread_->sink().GetUniqueMessageMatching(
       ViewHostMsg_UpdateState::ID);
   ASSERT_TRUE(msg_A);
-  int page_id_A;
-  PageState state_A;
-  ViewHostMsg_UpdateState::Read(msg_A, &page_id_A, &state_A);
+  ViewHostMsg_UpdateState::Param param;
+  ViewHostMsg_UpdateState::Read(msg_A, &param);
+  int page_id_A = param.a;
+  PageState state_A = param.b;
   EXPECT_EQ(1, page_id_A);
   render_thread_->sink().ClearMessages();
 
@@ -623,9 +625,9 @@
   const IPC::Message* msg_B = render_thread_->sink().GetUniqueMessageMatching(
       ViewHostMsg_UpdateState::ID);
   ASSERT_TRUE(msg_B);
-  int page_id_B;
-  PageState state_B;
-  ViewHostMsg_UpdateState::Read(msg_B, &page_id_B, &state_B);
+  ViewHostMsg_UpdateState::Read(msg_B, &param);
+  int page_id_B = param.a;
+  PageState state_B = param.b;
   EXPECT_EQ(2, page_id_B);
   EXPECT_NE(state_A, state_B);
   render_thread_->sink().ClearMessages();
@@ -638,9 +640,9 @@
   const IPC::Message* msg_C = render_thread_->sink().GetUniqueMessageMatching(
       ViewHostMsg_UpdateState::ID);
   ASSERT_TRUE(msg_C);
-  int page_id_C;
-  PageState state_C;
-  ViewHostMsg_UpdateState::Read(msg_C, &page_id_C, &state_C);
+  ViewHostMsg_UpdateState::Read(msg_C, &param);
+  int page_id_C = param.a;
+  PageState state_C = param.b;
   EXPECT_EQ(3, page_id_C);
   EXPECT_NE(state_B, state_C);
   render_thread_->sink().ClearMessages();
@@ -690,9 +692,9 @@
   const IPC::Message* msg = render_thread_->sink().GetUniqueMessageMatching(
       ViewHostMsg_UpdateState::ID);
   ASSERT_TRUE(msg);
-  int page_id;
-  PageState state;
-  ViewHostMsg_UpdateState::Read(msg, &page_id, &state);
+  ViewHostMsg_UpdateState::Read(msg, &param);
+  int page_id = param.a;
+  PageState state = param.b;
   EXPECT_EQ(page_id_C, page_id);
   EXPECT_NE(state_A, state);
   EXPECT_NE(state_B, state);
@@ -720,9 +722,10 @@
   const IPC::Message* msg_A = render_thread_->sink().GetUniqueMessageMatching(
       ViewHostMsg_UpdateState::ID);
   ASSERT_TRUE(msg_A);
-  int page_id_A;
-  PageState state_A;
-  ViewHostMsg_UpdateState::Read(msg_A, &page_id_A, &state_A);
+  ViewHostMsg_UpdateState::Param param;
+  ViewHostMsg_UpdateState::Read(msg_A, &param);
+  int page_id_A = param.a;
+  PageState state_A = param.b;
   EXPECT_EQ(1, page_id_A);
   render_thread_->sink().ClearMessages();
 
@@ -785,9 +788,10 @@
   const IPC::Message* msg_A = render_thread_->sink().GetUniqueMessageMatching(
       ViewHostMsg_UpdateState::ID);
   ASSERT_TRUE(msg_A);
-  int page_id_A;
-  PageState state_A;
-  ViewHostMsg_UpdateState::Read(msg_A, &page_id_A, &state_A);
+  ViewHostMsg_UpdateState::Param param;
+  ViewHostMsg_UpdateState::Read(msg_A, &param);
+  int page_id_A = param.a;
+  PageState state_A = param.b;
   EXPECT_EQ(1, page_id_A);
   render_thread_->sink().ClearMessages();
 
@@ -802,9 +806,9 @@
   const IPC::Message* msg_B = render_thread_->sink().GetUniqueMessageMatching(
       ViewHostMsg_UpdateState::ID);
   ASSERT_TRUE(msg_B);
-  int page_id_B;
-  PageState state_B;
-  ViewHostMsg_UpdateState::Read(msg_B, &page_id_B, &state_B);
+  ViewHostMsg_UpdateState::Read(msg_B, &param);
+  int page_id_B = param.a;
+  PageState state_B = param.b;
   EXPECT_EQ(2, page_id_B);
   render_thread_->sink().ClearMessages();
 
@@ -895,13 +899,11 @@
     const IPC::Message* msg = render_thread_->sink().GetMessageAt(0);
     EXPECT_TRUE(msg != NULL);
     EXPECT_EQ(ViewHostMsg_TextInputTypeChanged::ID, msg->type());
-    ui::TextInputType type;
-    bool can_compose_inline = false;
-    ui::TextInputMode input_mode = ui::TEXT_INPUT_MODE_DEFAULT;
-    ViewHostMsg_TextInputTypeChanged::Read(msg,
-                                           &type,
-                                           &input_mode,
-                                           &can_compose_inline);
+    ViewHostMsg_TextInputTypeChanged::Param params;
+    ViewHostMsg_TextInputTypeChanged::Read(msg, &params);
+    ui::TextInputType type = params.a;
+    ui::TextInputMode input_mode = params.b;
+    bool can_compose_inline = params.c;
     EXPECT_EQ(ui::TEXT_INPUT_TYPE_TEXT, type);
     EXPECT_EQ(true, can_compose_inline);
 
@@ -917,10 +919,9 @@
     msg = render_thread_->sink().GetMessageAt(0);
     EXPECT_TRUE(msg != NULL);
     EXPECT_EQ(ViewHostMsg_TextInputTypeChanged::ID, msg->type());
-    ViewHostMsg_TextInputTypeChanged::Read(msg,
-                                           &type,
-                                           &input_mode,
-                                           &can_compose_inline);
+    ViewHostMsg_TextInputTypeChanged::Read(msg, & params);
+    type = params.a;
+    input_mode = params.b;
     EXPECT_EQ(ui::TEXT_INPUT_TYPE_PASSWORD, type);
 
     for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kInputModeTestCases); i++) {
@@ -940,10 +941,9 @@
       const IPC::Message* msg = render_thread_->sink().GetMessageAt(0);
       EXPECT_TRUE(msg != NULL);
       EXPECT_EQ(ViewHostMsg_TextInputTypeChanged::ID, msg->type());
-      ViewHostMsg_TextInputTypeChanged::Read(msg,
-                                            &type,
-                                            &input_mode,
-                                            &can_compose_inline);
+      ViewHostMsg_TextInputTypeChanged::Read(msg, & params);
+      type = params.a;
+      input_mode = params.b;
       EXPECT_EQ(test_case->expected_mode, input_mode);
     }
   }
diff --git a/content/renderer/render_widget_unittest.cc b/content/renderer/render_widget_unittest.cc
index 41dd8472..c84c754 100644
--- a/content/renderer/render_widget_unittest.cc
+++ b/content/renderer/render_widget_unittest.cc
@@ -77,10 +77,6 @@
 TEST_F(RenderWidgetUnittest, TouchHitTestSinglePoint) {
   scoped_refptr<TouchableRenderWidget> widget = new TouchableRenderWidget();
 
-  blink::WebInputEvent::Type type;
-  InputEventAckState ack_state;
-  ui::LatencyInfo latency;
-
   SyntheticWebTouchEvent touch;
   touch.PressPoint(10, 10);
 
@@ -91,7 +87,9 @@
   // be 'no consumer exists'.
   const IPC::Message* message = widget->sink()->GetMessageAt(0);
   EXPECT_EQ(InputHostMsg_HandleInputEvent_ACK::ID, message->type());
-  InputHostMsg_HandleInputEvent_ACK::Read(message, &type, &ack_state, &latency);
+  InputHostMsg_HandleInputEvent_ACK::Param params;
+  InputHostMsg_HandleInputEvent_ACK::Read(message, &params);
+  InputEventAckState ack_state = params.b;
   EXPECT_EQ(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS, ack_state);
   widget->sink()->ClearMessages();
 
@@ -104,7 +102,8 @@
   ASSERT_EQ(1u, widget->sink()->message_count());
   message = widget->sink()->GetMessageAt(0);
   EXPECT_EQ(InputHostMsg_HandleInputEvent_ACK::ID, message->type());
-  InputHostMsg_HandleInputEvent_ACK::Read(message, &type, &ack_state, &latency);
+  InputHostMsg_HandleInputEvent_ACK::Read(message, &params);
+  ack_state = params.b;
   EXPECT_EQ(INPUT_EVENT_ACK_STATE_NOT_CONSUMED, ack_state);
   widget->sink()->ClearMessages();
 }
@@ -116,10 +115,6 @@
   rects.push_back(gfx::Rect(25, 0, 10, 10));
   widget->SetTouchRegion(rects);
 
-  blink::WebInputEvent::Type type;
-  InputEventAckState ack_state;
-  ui::LatencyInfo latency;
-
   SyntheticWebTouchEvent touch;
   touch.PressPoint(25, 25);
 
@@ -130,7 +125,9 @@
   // be 'no consumer exists'.
   const IPC::Message* message = widget->sink()->GetMessageAt(0);
   EXPECT_EQ(InputHostMsg_HandleInputEvent_ACK::ID, message->type());
-  InputHostMsg_HandleInputEvent_ACK::Read(message, &type, &ack_state, &latency);
+  InputHostMsg_HandleInputEvent_ACK::Param params;
+  InputHostMsg_HandleInputEvent_ACK::Read(message, &params);
+  InputEventAckState ack_state = params.b;
   EXPECT_EQ(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS, ack_state);
   widget->sink()->ClearMessages();
 
@@ -140,7 +137,8 @@
   ASSERT_EQ(1u, widget->sink()->message_count());
   message = widget->sink()->GetMessageAt(0);
   EXPECT_EQ(InputHostMsg_HandleInputEvent_ACK::ID, message->type());
-  InputHostMsg_HandleInputEvent_ACK::Read(message, &type, &ack_state, &latency);
+  InputHostMsg_HandleInputEvent_ACK::Read(message, &params);
+  ack_state = params.b;
   EXPECT_EQ(INPUT_EVENT_ACK_STATE_NOT_CONSUMED, ack_state);
   widget->sink()->ClearMessages();
 }
diff --git a/ipc/ipc_message.h b/ipc/ipc_message.h
index 1b13d67..ea6cda6 100644
--- a/ipc/ipc_message.h
+++ b/ipc/ipc_message.h
@@ -141,31 +141,17 @@
   // call.
   void SetHeaderValues(int32 routing, uint32 type, uint32 flags);
 
-  template<class T, class S>
-  static bool Dispatch(const Message* msg, T* obj, S* sender,
+  template<class T, class S, class P>
+  static bool Dispatch(const Message* msg, T* obj, S* sender, P* parameter,
                        void (T::*func)()) {
     (obj->*func)();
     return true;
   }
 
-  template<class T, class S>
-  static bool Dispatch(const Message* msg, T* obj, S* sender,
-                       void (T::*func)() const) {
-    (obj->*func)();
-    return true;
-  }
-
-  template<class T, class S>
-  static bool Dispatch(const Message* msg, T* obj, S* sender,
-                       void (T::*func)(const Message&)) {
-    (obj->*func)(*msg);
-    return true;
-  }
-
-  template<class T, class S>
-  static bool Dispatch(const Message* msg, T* obj, S* sender,
-                       void (T::*func)(const Message&) const) {
-    (obj->*func)(*msg);
+  template<class T, class S, class P>
+  static bool Dispatch(const Message* msg, T* obj, S* sender, P* parameter,
+                       void (T::*func)(P*)) {
+    (obj->*func)(parameter);
     return true;
   }
 
diff --git a/ipc/ipc_message_macros.h b/ipc/ipc_message_macros.h
index c4e250cf..f924e7b 100644
--- a/ipc/ipc_message_macros.h
+++ b/ipc/ipc_message_macros.h
@@ -434,9 +434,12 @@
 
 // The following macros define the common set of methods provided by ASYNC
 // message classes.
+// This macro is for all the async IPCs that don't pass an extra parameter using
+// IPC_BEGIN_MESSAGE_MAP_WITH_PARAM.
 #define IPC_ASYNC_MESSAGE_METHODS_GENERIC                                     \
-  template<class T, class S, class Method>                                    \
-  static bool Dispatch(const Message* msg, T* obj, S* sender, Method func) {  \
+  template<class T, class S, class P, class Method>                           \
+  static bool Dispatch(const Message* msg, T* obj, S* sender, P* parameter,   \
+                       Method func) {                                         \
     Schema::Param p;                                                          \
     if (Read(msg, &p)) {                                                      \
       DispatchToMethod(obj, func, p);                                         \
@@ -444,124 +447,86 @@
     }                                                                         \
     return false;                                                             \
   }
+
+// The following macros are for for async IPCs which have a dispatcher with an
+// extra parameter specified using IPC_BEGIN_MESSAGE_MAP_WITH_PARAM.
 #define IPC_ASYNC_MESSAGE_METHODS_1                                           \
   IPC_ASYNC_MESSAGE_METHODS_GENERIC                                           \
-  template<class T, class S, typename TA>                                     \
-  static bool Dispatch(const Message* msg, T* obj, S* sender,                 \
-                       void (T::*func)(const Message&, TA)) {                 \
+  template<class T, class S, class P, typename TA>                            \
+  static bool Dispatch(const Message* msg, T* obj, S* sender, P* parameter,   \
+                       void (T::*func)(P*, TA)) {                             \
     Schema::Param p;                                                          \
     if (Read(msg, &p)) {                                                      \
-      (obj->*func)(*msg, p.a);                                                \
+      (obj->*func)(parameter, p.a);                                           \
       return true;                                                            \
     }                                                                         \
     return false;                                                             \
   }
 #define IPC_ASYNC_MESSAGE_METHODS_2                                           \
   IPC_ASYNC_MESSAGE_METHODS_GENERIC                                           \
-  template<class T, class S, typename TA, typename TB>                        \
-  static bool Dispatch(const Message* msg, T* obj, S* sender,                 \
-                       void (T::*func)(const Message&, TA, TB)) {             \
+  template<class T, class S, class P, typename TA, typename TB>               \
+  static bool Dispatch(const Message* msg, T* obj, S* sender, P* parameter,   \
+                       void (T::*func)(P*, TA, TB)) {                         \
     Schema::Param p;                                                          \
     if (Read(msg, &p)) {                                                      \
-      (obj->*func)(*msg, p.a, p.b);                                           \
+      (obj->*func)(parameter, p.a, p.b);                                      \
       return true;                                                            \
     }                                                                         \
     return false;                                                             \
-  }                                                                           \
-  template<typename TA, typename TB>                                          \
-  static bool Read(const IPC::Message* msg, TA* a, TB* b) {                   \
-    Schema::Param p;                                                          \
-    if (!Read(msg, &p))                                                       \
-      return false;                                                           \
-    *a = p.a;                                                                 \
-    *b = p.b;                                                                 \
-    return true;                                                              \
   }
 #define IPC_ASYNC_MESSAGE_METHODS_3                                           \
   IPC_ASYNC_MESSAGE_METHODS_GENERIC                                           \
-  template<class T, class S, typename TA, typename TB, typename TC>           \
-  static bool Dispatch(const Message* msg, T* obj, S* sender,                 \
-                       void (T::*func)(const Message&, TA, TB, TC)) {         \
+  template<class T, class S, class P, typename TA, typename TB, typename TC>  \
+  static bool Dispatch(const Message* msg, T* obj, S* sender, P* parameter,   \
+                       void (T::*func)(P*, TA, TB, TC)) {                     \
     Schema::Param p;                                                          \
     if (Read(msg, &p)) {                                                      \
-      (obj->*func)(*msg, p.a, p.b, p.c);                                      \
+      (obj->*func)(parameter, p.a, p.b, p.c);                                 \
       return true;                                                            \
     }                                                                         \
     return false;                                                             \
-  }                                                                           \
-  template<typename TA, typename TB, typename TC>                             \
-  static bool Read(const IPC::Message* msg, TA* a, TB* b, TC* c) {            \
-    Schema::Param p;                                                          \
-    if (!Read(msg, &p))                                                       \
-      return false;                                                           \
-    *a = p.a;                                                                 \
-    *b = p.b;                                                                 \
-    *c = p.c;                                                                 \
-    return true;                                                              \
   }
 #define IPC_ASYNC_MESSAGE_METHODS_4                                           \
   IPC_ASYNC_MESSAGE_METHODS_GENERIC                                           \
-  template<class T, class S, typename TA, typename TB, typename TC,           \
+  template<class T, class S, class P, typename TA, typename TB, typename TC,  \
            typename TD>                                                       \
-  static bool Dispatch(const Message* msg, T* obj, S* sender,                 \
-                       void (T::*func)(const Message&, TA, TB, TC, TD)) {     \
+  static bool Dispatch(const Message* msg, T* obj, S* sender, P* parameter,   \
+                       void (T::*func)(P*, TA, TB, TC, TD)) {                 \
     Schema::Param p;                                                          \
     if (Read(msg, &p)) {                                                      \
-      (obj->*func)(*msg, p.a, p.b, p.c, p.d);                                 \
+      (obj->*func)(parameter, p.a, p.b, p.c, p.d);                            \
       return true;                                                            \
     }                                                                         \
     return false;                                                             \
-  }                                                                           \
-  template<typename TA, typename TB, typename TC, typename TD>                \
-  static bool Read(const IPC::Message* msg, TA* a, TB* b, TC* c, TD* d) {     \
-    Schema::Param p;                                                          \
-    if (!Read(msg, &p))                                                       \
-      return false;                                                           \
-    *a = p.a;                                                                 \
-    *b = p.b;                                                                 \
-    *c = p.c;                                                                 \
-    *d = p.d;                                                                 \
-    return true;                                                              \
   }
 #define IPC_ASYNC_MESSAGE_METHODS_5                                           \
   IPC_ASYNC_MESSAGE_METHODS_GENERIC                                           \
-  template<class T, class S, typename TA, typename TB, typename TC,           \
+  template<class T, class S, class P, typename TA, typename TB, typename TC,  \
            typename TD, typename TE>                                          \
-  static bool Dispatch(const Message* msg, T* obj, S* sender,                 \
-                       void (T::*func)(const Message&, TA, TB, TC, TD, TE)) { \
+  static bool Dispatch(const Message* msg, T* obj, S* sender, P* parameter,   \
+                       void (T::*func)(P*, TA, TB, TC, TD, TE)) {             \
     Schema::Param p;                                                          \
     if (Read(msg, &p)) {                                                      \
-      (obj->*func)(*msg, p.a, p.b, p.c, p.d, p.e);                            \
+      (obj->*func)(parameter, p.a, p.b, p.c, p.d, p.e);                       \
       return true;                                                            \
     }                                                                         \
     return false;                                                             \
-  }                                                                           \
-  template<typename TA, typename TB, typename TC, typename TD, typename TE>   \
-  static bool Read(const IPC::Message* msg, TA* a, TB* b, TC* c, TD* d,       \
-                   TE* e) {                                                   \
-    Schema::Param p;                                                          \
-    if (!Read(msg, &p))                                                       \
-      return false;                                                           \
-    *a = p.a;                                                                 \
-    *b = p.b;                                                                 \
-    *c = p.c;                                                                 \
-    *d = p.d;                                                                 \
-    *e = p.e;                                                                 \
-    return true;                                                              \
   }
 
 // The following macros define the common set of methods provided by SYNC
 // message classes.
 #define IPC_SYNC_MESSAGE_METHODS_GENERIC                                      \
-  template<class T, class S, class Method>                                    \
-  static bool Dispatch(const Message* msg, T* obj, S* sender, Method func) {  \
+  template<class T, class S, class P, class Method>                           \
+  static bool Dispatch(const Message* msg, T* obj, S* sender, P* parameter,   \
+                       Method func) {                                         \
     Schema::SendParam send_params;                                            \
     bool ok = ReadSendParam(msg, &send_params);                               \
     return Schema::DispatchWithSendParams(ok, send_params, msg, obj, sender,  \
                                           func);                              \
   }                                                                           \
-  template<class T, class Method>                                             \
-  static bool DispatchDelayReply(const Message* msg, T* obj, Method func) {   \
+  template<class T, class P, class Method>                                    \
+  static bool DispatchDelayReply(const Message* msg, T* obj, P* parameter,    \
+                                 Method func) {                               \
     Schema::SendParam send_params;                                            \
     bool ok = ReadSendParam(msg, &send_params);                               \
     return Schema::DispatchDelayReplyWithSendParams(ok, send_params, msg,     \
@@ -932,24 +897,32 @@
 
 
 #define IPC_BEGIN_MESSAGE_MAP_EX(class_name, msg, msg_is_ok) \
-  { \
-    typedef class_name _IpcMessageHandlerClass; \
-    const IPC::Message& ipc_message__ = msg; \
-    bool& msg_is_ok__ = msg_is_ok; \
-    switch (ipc_message__.type()) { \
+  IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(class_name, msg, msg_is_ok, void, NULL)
 
 #define IPC_BEGIN_MESSAGE_MAP(class_name, msg) \
   { \
     typedef class_name _IpcMessageHandlerClass; \
+    typedef void _ParamClass; \
+    _ParamClass* param__ = NULL; \
     const IPC::Message& ipc_message__ = msg; \
     bool msg_is_ok__ = true; \
     switch (ipc_message__.type()) { \
 
+#define IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(class_name, msg, msg_is_ok,           \
+                                         param_type, param)                    \
+  {                                                                            \
+    typedef class_name _IpcMessageHandlerClass;                                \
+    typedef param_type _ParamClass;                                            \
+    _ParamClass* param__ = param;                                              \
+    const IPC::Message& ipc_message__ = msg;                                   \
+    bool& msg_is_ok__ = msg_is_ok;                                             \
+    switch (ipc_message__.type()) {                                            \
+
 #define IPC_MESSAGE_FORWARD(msg_class, obj, member_func)                       \
     case msg_class::ID: {                                                      \
         TRACK_RUN_IN_IPC_HANDLER(member_func);                                 \
         msg_is_ok__ = msg_class::Dispatch(&ipc_message__, obj, this,           \
-                                      &member_func);                           \
+                                          param__, &member_func);              \
       }                                                                        \
       break;
 
@@ -960,7 +933,7 @@
     case msg_class::ID: {                                                      \
         TRACK_RUN_IN_IPC_HANDLER(member_func);                                 \
         msg_is_ok__ = msg_class::DispatchDelayReply(&ipc_message__, obj,       \
-                                                  &member_func);               \
+                                                  param__, &member_func);      \
       }                                                                        \
       break;
 
diff --git a/ipc/ipc_message_unittest.cc b/ipc/ipc_message_unittest.cc
index 971314a..ceb92df3 100644
--- a/ipc/ipc_message_unittest.cc
+++ b/ipc/ipc_message_unittest.cc
@@ -11,6 +11,19 @@
 #include "ipc/ipc_message_utils.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
+// IPC messages for testing ----------------------------------------------------
+
+#define IPC_MESSAGE_IMPL
+#include "ipc/ipc_message_macros.h"
+
+#define IPC_MESSAGE_START TestMsgStart
+
+IPC_MESSAGE_CONTROL0(TestMsgClassEmpty)
+
+IPC_MESSAGE_CONTROL1(TestMsgClassI, int)
+
+IPC_SYNC_MESSAGE_CONTROL1_1(TestMsgClassIS, int, std::string)
+
 namespace {
 
 TEST(IPCMessageTest, ListValue) {
@@ -70,4 +83,71 @@
   EXPECT_FALSE(IPC::ReadParam(&bad_msg, &iter, &output));
 }
 
+class IPCMessageParameterTest : public testing::Test {
+ public:
+  IPCMessageParameterTest() : extra_param_("extra_param"), called_(false) {}
+
+  bool OnMessageReceived(const IPC::Message& message) {
+    bool msg_is_ok = true;
+    bool handled = true;
+    IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(IPCMessageParameterTest, message,
+                                     msg_is_ok, std::string, &extra_param_) 
+      IPC_MESSAGE_HANDLER(TestMsgClassEmpty, OnEmpty)
+      IPC_MESSAGE_HANDLER(TestMsgClassI, OnInt)
+      //IPC_MESSAGE_HANDLER(TestMsgClassIS, OnSync)
+      IPC_MESSAGE_UNHANDLED(handled = false)
+    IPC_END_MESSAGE_MAP()
+
+    return handled;
+  }
+
+  void OnEmpty(std::string* extra_param) {
+    EXPECT_EQ(extra_param, &extra_param_);
+    called_ = true;
+  }
+
+  void OnInt(std::string* extra_param, int foo) {
+    EXPECT_EQ(extra_param, &extra_param_);
+    EXPECT_EQ(foo, 42);
+    called_ = true;
+  }
+
+  /* TODO: handle sync IPCs
+    void OnSync(std::string* extra_param, int foo, std::string* out) {
+    EXPECT_EQ(extra_param, &extra_param_);
+    EXPECT_EQ(foo, 42);
+    called_ = true;
+    *out = std::string("out");
+  }
+
+  bool Send(IPC::Message* reply) {
+    delete reply;
+    return true;
+  }*/
+
+  std::string extra_param_;
+  bool called_;
+};
+
+TEST_F(IPCMessageParameterTest, EmptyDispatcherWithParam) {
+  TestMsgClassEmpty message;
+  EXPECT_TRUE(OnMessageReceived(message));
+  EXPECT_TRUE(called_);
+}
+
+TEST_F(IPCMessageParameterTest, OneIntegerWithParam) {
+  TestMsgClassI message(42);
+  EXPECT_TRUE(OnMessageReceived(message));
+  EXPECT_TRUE(called_);
+}
+
+/* TODO: handle sync IPCs
+TEST_F(IPCMessageParameterTest, Sync) {
+  std::string output;
+  TestMsgClassIS message(42, &output);
+  EXPECT_TRUE(OnMessageReceived(message));
+  EXPECT_TRUE(called_);
+  EXPECT_EQ(output, std::string("out"));
+}*/
+
 }  // namespace
diff --git a/ppapi/proxy/resource_message_test_sink.cc b/ppapi/proxy/resource_message_test_sink.cc
index a17e1d5..2c237b067 100644
--- a/ppapi/proxy/resource_message_test_sink.cc
+++ b/ppapi/proxy/resource_message_test_sink.cc
@@ -22,9 +22,10 @@
   for (size_t i = 0; i < sink.message_count(); i++) {
     const IPC::Message* msg = sink.GetMessageAt(i);
     if (msg->type() == WrapperMessage::ID) {
-      Params cur_params;
-      IPC::Message cur_msg;
-      WrapperMessage::Read(msg, &cur_params, &cur_msg);
+      typename WrapperMessage::Param params;
+      WrapperMessage::Read(msg, &params);
+      Params cur_params = params.a;
+      IPC::Message cur_msg = params.b;
       if (cur_msg.type() == id) {
         result.push_back(std::make_pair(cur_params, cur_msg));
       }