summaryrefslogtreecommitdiffstats
path: root/chrome_frame
diff options
context:
space:
mode:
authorananta@chromium.org <ananta@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-05-17 21:47:30 +0000
committerananta@chromium.org <ananta@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-05-17 21:47:30 +0000
commitcb291e642a4fe2d36c2354a1bfdb843661de74a0 (patch)
treebb6c13ad7586ad839c0f0d332410842804a3a2da /chrome_frame
parent981b34450805e070b6694c8df292f24ee1f73ff4 (diff)
downloadchromium_src-cb291e642a4fe2d36c2354a1bfdb843661de74a0.zip
chromium_src-cb291e642a4fe2d36c2354a1bfdb843661de74a0.tar.gz
chromium_src-cb291e642a4fe2d36c2354a1bfdb843661de74a0.tar.bz2
Revert 47453 - In ChromeFrame the ChromeFrameAutomationProxy object is created on the background proxy channel thread and is accessed
from the UI thread, the proxy channel thread and the IPC thread. This leads to a race condition when ChromeFrame is being torn down which occurs because the ChromeFrameAutomationProxy pointer is being set to NULL in the UI thread/deleted in the proxy background thread while it could be accessed while processing a callback in the IPC thread thus causing a crash. Fix is to ensure that the IPC thread does not access the ChromeFrameAutomationProxy pointer. To achieve this the callbacks are now individual context objects which when invoked forward the actions to the ChromeFrameAutomationClient object. The CreateExternalTab and ConnectExternalTab callbacks now complete their actions on the UI thread. While at this based on a discussion and lot of help from Stoyan we decided to clean up the sync message dispatching code used by ChromeFrame by having callbacks now derive from a SyncMessageCallContext class to ensure that these get cleaned up correctly in all cases. For e.g. if we don't receive a response for a message, etc and thus enable them to present a consistent interface to be invoked when we receive a response for a IPc message. Fixes bug http://code.google.com/p/chromium/issues/detail?id=44245 Bug=44245 Review URL: http://codereview.chromium.org/2073007 TBR=ananta@chromium.org Review URL: http://codereview.chromium.org/2110006 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@47461 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome_frame')
-rw-r--r--chrome_frame/chrome_frame_automation.cc220
-rw-r--r--chrome_frame/chrome_frame_automation.h15
-rw-r--r--chrome_frame/sync_msg_reply_dispatcher.cc51
-rw-r--r--chrome_frame/sync_msg_reply_dispatcher.h72
-rw-r--r--chrome_frame/test/automation_client_mock.h6
5 files changed, 145 insertions, 219 deletions
diff --git a/chrome_frame/chrome_frame_automation.cc b/chrome_frame/chrome_frame_automation.cc
index bccdcc8..8d89cbd 100644
--- a/chrome_frame/chrome_frame_automation.cc
+++ b/chrome_frame/chrome_frame_automation.cc
@@ -24,6 +24,7 @@
#include "chrome/test/automation/tab_proxy.h"
#include "chrome_frame/chrome_launcher.h"
#include "chrome_frame/utils.h"
+#include "chrome_frame/sync_msg_reply_dispatcher.h"
#ifdef NDEBUG
int64 kAutomationServerReasonableLaunchDelay = 1000; // in milliseconds
@@ -91,135 +92,33 @@ class ChromeFrameAutomationProxyImpl::TabProxyNotificationMessageFilter
std::list<AutomationHandle> tabs_list_;
};
-// Class that maintains context during the async load/install extension
-// operation. When done, InstallExtensionComplete is posted back to the UI
-// thread so that the users of ChromeFrameAutomationClient can be notified.
-class InstallExtensionContext
- : public SyncMessageReplyDispatcher::SyncMessageCallContext {
- public:
- typedef Tuple1<AutomationMsg_ExtensionResponseValues> output_type;
-
- InstallExtensionContext(ChromeFrameAutomationClient* client,
- const FilePath& crx_path, void* user_data) : client_(client),
- crx_path_(crx_path), user_data_(user_data) {
- }
-
- ~InstallExtensionContext() {
- }
-
- void Completed(AutomationMsg_ExtensionResponseValues res) {
- client_->PostTask(FROM_HERE, NewRunnableMethod(client_.get(),
- &ChromeFrameAutomationClient::InstallExtensionComplete, crx_path_,
- user_data_, res));
- }
-
- private:
- scoped_refptr<ChromeFrameAutomationClient> client_;
- FilePath crx_path_;
- void* user_data_;
-};
-
-// Class that maintains context during the async retrieval of fetching the
-// list of enabled extensions. When done, GetEnabledExtensionsComplete is
-// posted back to the UI thread so that the users of
-// ChromeFrameAutomationClient can be notified.
-class GetEnabledExtensionsContext
- : public SyncMessageReplyDispatcher::SyncMessageCallContext {
- public:
- typedef Tuple1<std::vector<FilePath> > output_type;
-
- GetEnabledExtensionsContext(
- ChromeFrameAutomationClient* client, void* user_data) : client_(client),
- user_data_(user_data) {
- extension_directories_ = new std::vector<FilePath>();
- }
-
- ~GetEnabledExtensionsContext() {
- // ChromeFrameAutomationClient::GetEnabledExtensionsComplete takes
- // ownership of extension_directories_.
- }
-
- std::vector<FilePath>* extension_directories() {
- return extension_directories_;
- }
-
- void Completed(
- std::vector<FilePath> result) {
- (*extension_directories_) = result;
- client_->PostTask(FROM_HERE, NewRunnableMethod(client_.get(),
- &ChromeFrameAutomationClient::GetEnabledExtensionsComplete,
- user_data_, extension_directories_));
- }
-
- private:
- scoped_refptr<ChromeFrameAutomationClient> client_;
- std::vector<FilePath>* extension_directories_;
- void* user_data_;
-};
-
-// Class that maintains contextual information for the create and connect
-// external tab operations.
-class CreateExternalTabContext
- : public SyncMessageReplyDispatcher::SyncMessageCallContext {
- public:
- typedef Tuple3<HWND, HWND, int> output_type;
- explicit CreateExternalTabContext(ChromeFrameAutomationClient* client)
- : client_(client) {
- }
-
- void Completed(HWND chrome_window, HWND tab_window, int tab_handle) {
- client_->PostTask(FROM_HERE,
- NewRunnableMethod(client_.get(),
- &ChromeFrameAutomationClient::CreateExternalTabComplete,
- chrome_window, tab_window, tab_handle));
- }
-
- private:
- scoped_refptr<ChromeFrameAutomationClient> client_;
-};
-
-// This class maintains context information for the BeginNavigate operations
-// pertaining to the external tab.
-class BeginNavigateContext
- : public SyncMessageReplyDispatcher::SyncMessageCallContext {
- public:
- explicit BeginNavigateContext(ChromeFrameAutomationClient* client)
- : client_(client) {}
-
- typedef Tuple1<AutomationMsg_NavigationResponseValues> output_type;
-
- void Completed(AutomationMsg_NavigationResponseValues response) {
- client_->BeginNavigateCompleted(response);
- }
-
- private:
- scoped_refptr<ChromeFrameAutomationClient> client_;
-};
-
class ChromeFrameAutomationProxyImpl::CFMsgDispatcher
: public SyncMessageReplyDispatcher {
public:
CFMsgDispatcher() : SyncMessageReplyDispatcher() {}
protected:
virtual bool HandleMessageType(const IPC::Message& msg,
- SyncMessageCallContext* context) {
- switch (context->message_type()) {
+ const MessageSent& origin) {
+ switch (origin.type) {
case AutomationMsg_CreateExternalTab::ID:
case AutomationMsg_ConnectExternalTab::ID:
- InvokeCallback<CreateExternalTabContext>(msg, context);
+ InvokeCallback<Tuple3<HWND, HWND, int> >(msg, origin);
break;
case AutomationMsg_NavigateExternalTabAtIndex::ID:
case AutomationMsg_NavigateInExternalTab::ID:
- InvokeCallback<BeginNavigateContext>(msg, context);
+ InvokeCallback<Tuple1<AutomationMsg_NavigationResponseValues> >(msg,
+ origin);
break;
case AutomationMsg_InstallExtension::ID:
- InvokeCallback<InstallExtensionContext>(msg, context);
+ InvokeCallback<Tuple1<AutomationMsg_ExtensionResponseValues> >(msg,
+ origin);
break;
case AutomationMsg_LoadExpandedExtension::ID:
- InvokeCallback<InstallExtensionContext>(msg, context);
+ InvokeCallback<Tuple1<AutomationMsg_ExtensionResponseValues> >(msg,
+ origin);
break;
case AutomationMsg_GetEnabledExtensions::ID:
- InvokeCallback<GetEnabledExtensionsContext>(msg, context);
+ InvokeCallback<Tuple1<std::vector<FilePath> > >(msg, origin);
break;
default:
NOTREACHED();
@@ -244,10 +143,9 @@ ChromeFrameAutomationProxyImpl::~ChromeFrameAutomationProxyImpl() {
TRACE_EVENT_END("chromeframe.automationproxy", this, "");
}
-void ChromeFrameAutomationProxyImpl::SendAsAsync(
- IPC::SyncMessage* msg,
- SyncMessageReplyDispatcher::SyncMessageCallContext* context, void* key) {
- sync_->Push(msg, context, key);
+void ChromeFrameAutomationProxyImpl::SendAsAsync(IPC::SyncMessage* msg,
+ void* callback, void* key) {
+ sync_->Push(msg, callback, key);
channel_->ChannelProxy::Send(msg);
}
@@ -715,8 +613,8 @@ bool ChromeFrameAutomationClient::NavigateToIndex(int index) {
IPC::SyncMessage* msg = new AutomationMsg_NavigateExternalTabAtIndex(
0, tab_->handle(), index, NULL);
- automation_server_->SendAsAsync(msg, new BeginNavigateContext(this),
- this);
+ automation_server_->SendAsAsync(msg, NewCallback(this,
+ &ChromeFrameAutomationClient::BeginNavigateCompleted), this);
return true;
}
@@ -758,7 +656,8 @@ void ChromeFrameAutomationClient::BeginNavigate(const GURL& url,
IPC::SyncMessage* msg =
new AutomationMsg_NavigateInExternalTab(0, tab_->handle(), url,
referrer, NULL);
- automation_server_->SendAsAsync(msg, new BeginNavigateContext(this), this);
+ automation_server_->SendAsAsync(msg, NewCallback(this,
+ &ChromeFrameAutomationClient::BeginNavigateCompleted), this);
RECT client_rect = {0};
chrome_frame_delegate_->GetBounds(&client_rect);
@@ -794,6 +693,32 @@ void ChromeFrameAutomationClient::FindInPage(const std::wstring& search_string,
automation_server_->SendAsAsync(msg, NULL, this);
}
+// Class that maintains context during the async load/install extension
+// operation. When done, InstallExtensionComplete is posted back to the UI
+// thread so that the users of ChromeFrameAutomationClient can be notified.
+class InstallExtensionContext {
+ public:
+ InstallExtensionContext(ChromeFrameAutomationClient* client,
+ const FilePath& crx_path, void* user_data) : client_(client),
+ crx_path_(crx_path), user_data_(user_data) {
+ }
+
+ ~InstallExtensionContext() {
+ }
+
+ void InstallExtensionComplete(AutomationMsg_ExtensionResponseValues res) {
+ client_->PostTask(FROM_HERE, NewRunnableMethod(client_.get(),
+ &ChromeFrameAutomationClient::InstallExtensionComplete, crx_path_,
+ user_data_, res));
+ delete this;
+ }
+
+ private:
+ scoped_refptr<ChromeFrameAutomationClient> client_;
+ FilePath crx_path_;
+ void* user_data_;
+};
+
void ChromeFrameAutomationClient::InstallExtension(
const FilePath& crx_path,
void* user_data) {
@@ -811,7 +736,8 @@ void ChromeFrameAutomationClient::InstallExtension(
new AutomationMsg_InstallExtension(0, crx_path, NULL);
// The context will delete itself after it is called.
- automation_server_->SendAsAsync(msg, ctx, this);
+ automation_server_->SendAsAsync(msg, NewCallback(ctx,
+ &InstallExtensionContext::InstallExtensionComplete), this);
}
void ChromeFrameAutomationClient::InstallExtensionComplete(
@@ -825,6 +751,42 @@ void ChromeFrameAutomationClient::InstallExtensionComplete(
}
}
+// Class that maintains context during the async retrieval of fetching the
+// list of enabled extensions. When done, GetEnabledExtensionsComplete is
+// posted back to the UI thread so that the users of
+// ChromeFrameAutomationClient can be notified.
+class GetEnabledExtensionsContext {
+ public:
+ GetEnabledExtensionsContext(
+ ChromeFrameAutomationClient* client, void* user_data) : client_(client),
+ user_data_(user_data) {
+ extension_directories_ = new std::vector<FilePath>();
+ }
+
+ ~GetEnabledExtensionsContext() {
+ // ChromeFrameAutomationClient::GetEnabledExtensionsComplete takes
+ // ownership of extension_directories_.
+ }
+
+ std::vector<FilePath>* extension_directories() {
+ return extension_directories_;
+ }
+
+ void GetEnabledExtensionsComplete(
+ std::vector<FilePath> result) {
+ (*extension_directories_) = result;
+ client_->PostTask(FROM_HERE, NewRunnableMethod(client_.get(),
+ &ChromeFrameAutomationClient::GetEnabledExtensionsComplete,
+ user_data_, extension_directories_));
+ delete this;
+ }
+
+ private:
+ scoped_refptr<ChromeFrameAutomationClient> client_;
+ std::vector<FilePath>* extension_directories_;
+ void* user_data_;
+};
+
void ChromeFrameAutomationClient::GetEnabledExtensions(void* user_data) {
if (automation_server_ == NULL) {
GetEnabledExtensionsComplete(user_data, &std::vector<FilePath>());
@@ -838,7 +800,8 @@ void ChromeFrameAutomationClient::GetEnabledExtensions(void* user_data) {
0, ctx->extension_directories());
// The context will delete itself after it is called.
- automation_server_->SendAsAsync(msg, ctx, this);
+ automation_server_->SendAsAsync(msg, NewCallback(ctx,
+ &GetEnabledExtensionsContext::GetEnabledExtensionsComplete), this);
}
void ChromeFrameAutomationClient::GetEnabledExtensionsComplete(
@@ -882,7 +845,8 @@ void ChromeFrameAutomationClient::LoadExpandedExtension(
new AutomationMsg_LoadExpandedExtension(0, path, NULL);
// The context will delete itself after it is called.
- automation_server_->SendAsAsync(msg, ctx, this);
+ automation_server_->SendAsAsync(msg, NewCallback(ctx,
+ &InstallExtensionContext::InstallExtensionComplete), this);
}
void ChromeFrameAutomationClient::CreateExternalTab() {
@@ -913,8 +877,8 @@ void ChromeFrameAutomationClient::CreateExternalTab() {
IPC::SyncMessage* message =
new AutomationMsg_CreateExternalTab(0, settings, NULL, NULL, NULL);
- automation_server_->SendAsAsync(message, new CreateExternalTabContext(this),
- this);
+ automation_server_->SendAsAsync(message, NewCallback(this,
+ &ChromeFrameAutomationClient::CreateExternalTabComplete), this);
}
void ChromeFrameAutomationClient::CreateExternalTabComplete(HWND chrome_window,
@@ -937,7 +901,8 @@ void ChromeFrameAutomationClient::CreateExternalTabComplete(HWND chrome_window,
tab_handle_ = tab_handle;
}
- InitializeComplete(launch_result);
+ PostTask(FROM_HERE, NewRunnableMethod(this,
+ &ChromeFrameAutomationClient::InitializeComplete, launch_result));
}
void ChromeFrameAutomationClient::SetEnableExtensionAutomation(
@@ -983,9 +948,8 @@ void ChromeFrameAutomationClient::LaunchComplete(
IPC::SyncMessage* message =
new AutomationMsg_ConnectExternalTab(0, external_tab_cookie_, true,
NULL, NULL, NULL);
- automation_server_->SendAsAsync(message,
- new CreateExternalTabContext(this),
- this);
+ automation_server_->SendAsAsync(message, NewCallback(this,
+ &ChromeFrameAutomationClient::CreateExternalTabComplete), this);
DLOG(INFO) << __FUNCTION__ << ": sending CreateExternalTabComplete";
}
}
diff --git a/chrome_frame/chrome_frame_automation.h b/chrome_frame/chrome_frame_automation.h
index 3461eba2..01a64ac 100644
--- a/chrome_frame/chrome_frame_automation.h
+++ b/chrome_frame/chrome_frame_automation.h
@@ -23,7 +23,6 @@
#include "chrome_frame/chrome_frame_delegate.h"
#include "chrome_frame/chrome_frame_histograms.h"
#include "chrome_frame/plugin_url_request.h"
-#include "chrome_frame/sync_msg_reply_dispatcher.h"
// By a convoluated route, this timeout also winds up being the sync automation
// message timeout. See the ChromeFrameAutomationProxyImpl ctor and the
@@ -36,10 +35,8 @@ enum AutomationPageFontSize;
struct DECLSPEC_NOVTABLE ChromeFrameAutomationProxy { // NOLINT
virtual bool Send(IPC::Message* msg) = 0;
- virtual void SendAsAsync(
- IPC::SyncMessage* msg,
- SyncMessageReplyDispatcher::SyncMessageCallContext* context,
- void* key) = 0;
+ virtual void SendAsAsync(IPC::SyncMessage* msg, void* callback,
+ void* key) = 0;
virtual void CancelAsync(void* key) = 0;
virtual scoped_refptr<TabProxy> CreateTabProxy(int handle) = 0;
virtual void ReleaseTabProxy(AutomationHandle handle) = 0;
@@ -58,10 +55,7 @@ class ChromeFrameAutomationProxyImpl : public ChromeFrameAutomationProxy,
// .. and non-public inheritance is verboten.
public AutomationProxy {
public:
- virtual void SendAsAsync(
- IPC::SyncMessage* msg,
- SyncMessageReplyDispatcher::SyncMessageCallContext* context,
- void* key);
+ virtual void SendAsAsync(IPC::SyncMessage* msg, void* callback, void* key);
virtual void CancelAsync(void* key);
@@ -368,9 +362,6 @@ class ChromeFrameAutomationClient
virtual void OnCookiesRetrieved(bool success, const GURL& url,
const std::string& cookie_string, int cookie_id);
- friend class BeginNavigateContext;
- friend class CreateExternalTabContext;
-
public:
void SetUrlFetcher(PluginUrlRequestManager* url_fetcher) {
DCHECK(url_fetcher != NULL);
diff --git a/chrome_frame/sync_msg_reply_dispatcher.cc b/chrome_frame/sync_msg_reply_dispatcher.cc
index 1b51516..b301698 100644
--- a/chrome_frame/sync_msg_reply_dispatcher.cc
+++ b/chrome_frame/sync_msg_reply_dispatcher.cc
@@ -6,61 +6,56 @@
#include "ipc/ipc_sync_message.h"
-void SyncMessageReplyDispatcher::Push(IPC::SyncMessage* msg,
- SyncMessageCallContext* context,
+void SyncMessageReplyDispatcher::Push(IPC::SyncMessage* msg, void* callback,
void* key) {
- context->message_type_ = msg->type();
- context->id_ = IPC::SyncMessage::GetMessageId(*msg);
- context->key_ = key;
-
+ MessageSent pending(IPC::SyncMessage::GetMessageId(*msg),
+ msg->type(), callback, key);
AutoLock lock(message_queue_lock_);
- message_queue_.push_back(context);
+ message_queue_.push_back(pending);
}
-bool SyncMessageReplyDispatcher::HandleMessageType(
- const IPC::Message& msg, SyncMessageCallContext* context) {
+bool SyncMessageReplyDispatcher::HandleMessageType(const IPC::Message& msg,
+ const MessageSent& origin) {
return false;
}
bool SyncMessageReplyDispatcher::OnMessageReceived(const IPC::Message& msg) {
- SyncMessageCallContext* context = GetContext(msg);
- // No context e.g. no return values and/or don't care
- if (!context) {
+ MessageSent origin;
+ if (!Pop(msg, &origin)) {
return false;
}
- return HandleMessageType(msg, context);
+ // No callback e.g. no return values and/or don't care
+ if (origin.callback == NULL)
+ return true;
+
+ return HandleMessageType(msg, origin);
}
void SyncMessageReplyDispatcher::Cancel(void* key) {
DCHECK(key != NULL);
AutoLock lock(message_queue_lock_);
- PendingSyncMessageQueue::iterator it = message_queue_.begin();
- while (it != message_queue_.end()) {
- SyncMessageCallContext* context = *it;
- if (context->key_ == key) {
- it = message_queue_.erase(it);
- delete context;
- } else {
- ++it;
+ PendingSyncMessageQueue::iterator it;
+ for (it = message_queue_.begin(); it != message_queue_.end(); ++it) {
+ if (it->key == key) {
+ it->key = NULL;
}
}
}
-SyncMessageReplyDispatcher::SyncMessageCallContext*
- SyncMessageReplyDispatcher::GetContext(const IPC::Message& msg) {
+bool SyncMessageReplyDispatcher::Pop(const IPC::Message& msg, MessageSent* t) {
if (!msg.is_reply())
- return NULL;
+ return false;
int id = IPC::SyncMessage::GetMessageId(msg);
AutoLock lock(message_queue_lock_);
PendingSyncMessageQueue::iterator it;
for (it = message_queue_.begin(); it != message_queue_.end(); ++it) {
- SyncMessageCallContext* context = *it;
- if (context->id_ == id) {
+ if (it->id == id) {
+ *t = *it;
message_queue_.erase(it);
- return context;
+ return true;
}
}
- return NULL;
+ return false;
}
diff --git a/chrome_frame/sync_msg_reply_dispatcher.h b/chrome_frame/sync_msg_reply_dispatcher.h
index 7d47bd1..724c007 100644
--- a/chrome_frame/sync_msg_reply_dispatcher.h
+++ b/chrome_frame/sync_msg_reply_dispatcher.h
@@ -23,22 +23,14 @@
// cases where you care about the return values of synchronous messages.
//
// Sample usage pattern:
-// Define a class which inherits from SyncMessageCallContext which specifies
-// the output_type tuple and has a Completed member function.
-// class SampleContext
-// : public SyncMessageReplyDispatcher::SyncMessageCallContext {
-// public:
-// typedef Tuple1<int> output_type;
-// void Completed(int arg) {}
-// };
//
// // Add handling for desired message types.
// class SyncMessageReplyDispatcherImpl : public SyncMessageReplyDispatcher {
// virtual bool HandleMessageType(const IPC::Message& msg,
-// SyncMessageReplyDispatcher* context) {
-// switch (context->message_type()) {
+// const MessageSent& origin) {
+// switch (origin.type) {
// case AutomationMsg_CreateExternalTab::ID:
-// InvokeCallback<CreateExternalTabContext>(msg, context);
+// InvokeCallback<Tuple3<HWND, HWND, int> >(msg, origin);
// break;
// [HANDLING FOR OTHER EXPECTED MESSAGE TYPES]
// }
@@ -48,42 +40,29 @@
// IPC::SyncChannel channel_;
// channel_.AddFilter(new SyncMessageReplyDispatcherImpl());
//
-// sync_->Push(msg, new SampleContext, this);
+// sync_->Push(msg, NewCallback(this, CallbackMethod, this);
// channel_->ChannelProxy::Send(msg);
//
class SyncMessageReplyDispatcher : public IPC::ChannelProxy::MessageFilter {
public:
- class SyncMessageCallContext {
- public:
- SyncMessageCallContext()
- : id_(0),
- message_type_(0),
- key_(NULL) {}
-
- virtual ~SyncMessageCallContext() {}
-
- uint32 message_type() const {
- return message_type_;
- }
-
- private:
- int id_;
- uint32 message_type_;
- void* key_;
-
- friend class SyncMessageReplyDispatcher;
- };
-
SyncMessageReplyDispatcher() {}
- void Push(IPC::SyncMessage* msg, SyncMessageCallContext* context,
- void* key);
+ void Push(IPC::SyncMessage* msg, void* callback, void* key);
void Cancel(void* key);
protected:
- typedef std::deque<SyncMessageCallContext*> PendingSyncMessageQueue;
+ struct MessageSent {
+ MessageSent() {}
+ MessageSent(int id, uint32 type, void* callback, void* key)
+ : id(id), callback(callback), type(type), key(key) {}
+ int id;
+ void* callback;
+ void* key;
+ uint32 type;
+ };
- SyncMessageCallContext* GetContext(const IPC::Message& msg);
+ typedef std::deque<MessageSent> PendingSyncMessageQueue;
+ bool Pop(const IPC::Message& msg, MessageSent* t);
virtual bool OnMessageReceived(const IPC::Message& msg);
// Child classes must implement a handler for the message types they are
@@ -91,22 +70,21 @@ class SyncMessageReplyDispatcher : public IPC::ChannelProxy::MessageFilter {
// to any of the sync messages you are handling, then you don't have to
// implement this.
virtual bool HandleMessageType(const IPC::Message& msg,
- SyncMessageCallContext* context);
+ const MessageSent& origin);
template <typename T>
- void InvokeCallback(const IPC::Message& msg,
- SyncMessageCallContext* call_context) {
- if (!call_context || !call_context->key_) {
- NOTREACHED() << "Invalid context parameter";
+ void InvokeCallback(const IPC::Message& msg, const MessageSent& origin) {
+ // Ensure we delete the callback
+ scoped_ptr<CallbackRunner<T> > c(
+ reinterpret_cast<CallbackRunner<T>*>(origin.callback));
+ if (origin.key == NULL) { // Canceled
return;
}
- T* context = static_cast<T*>(call_context);
- T::output_type tmp; // Acts as "initializer" for output parameters.
- IPC::ParamDeserializer<T::output_type> deserializer(tmp);
+ T tmp; // Acts as "initializer" for output parameters.
+ IPC::ParamDeserializer<T> deserializer(tmp);
if (deserializer.MessageReplyDeserializer::SerializeOutputParameters(msg)) {
- DispatchToMethod(context, &T::Completed, deserializer.out_);
- delete context;
+ c->RunWithParams(deserializer.out_);
} else {
// TODO(stoyan): How to handle errors?
}
diff --git a/chrome_frame/test/automation_client_mock.h b/chrome_frame/test/automation_client_mock.h
index 09b1484..d08d62d3 100644
--- a/chrome_frame/test/automation_client_mock.h
+++ b/chrome_frame/test/automation_client_mock.h
@@ -90,10 +90,8 @@ struct MockCFDelegate : public ChromeFrameDelegateImpl {
class MockAutomationProxy : public ChromeFrameAutomationProxy {
public:
MOCK_METHOD1(Send, bool(IPC::Message*));
- MOCK_METHOD3(SendAsAsync,
- void(IPC::SyncMessage* msg,
- SyncMessageReplyDispatcher::SyncMessageCallContext* context,
- void* key));
+ MOCK_METHOD3(SendAsAsync, void(IPC::SyncMessage* msg, void* callback,
+ void* key));
MOCK_METHOD1(CancelAsync, void(void* key));
MOCK_METHOD1(CreateTabProxy, scoped_refptr<TabProxy>(int handle));
MOCK_METHOD1(ReleaseTabProxy, void(AutomationHandle handle));