summaryrefslogtreecommitdiffstats
path: root/chrome_frame/cfproxy_support.cc
diff options
context:
space:
mode:
authorstoyan@chromium.org <stoyan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-10-05 23:38:55 +0000
committerstoyan@chromium.org <stoyan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-10-05 23:38:55 +0000
commit23f5ee3f8b0c9f854c080db48b1f97603576d865 (patch)
tree0b244a27b3a84e61fcea00316b5ff578b38d4ed4 /chrome_frame/cfproxy_support.cc
parent06552c1abc14f20e5dcc374a44c17e2cd29d9746 (diff)
downloadchromium_src-23f5ee3f8b0c9f854c080db48b1f97603576d865.zip
chromium_src-23f5ee3f8b0c9f854c080db48b1f97603576d865.tar.gz
chromium_src-23f5ee3f8b0c9f854c080db48b1f97603576d865.tar.bz2
Initial skeleton for refactored ChromeFrameAutomationClient and AutomationProxy for the needs of ChromeFrame.
CFProxy is ready to some extent, while CFAC is mostly structure-only. Review URL: http://codereview.chromium.org/3528004 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@61583 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome_frame/cfproxy_support.cc')
-rw-r--r--chrome_frame/cfproxy_support.cc450
1 files changed, 450 insertions, 0 deletions
diff --git a/chrome_frame/cfproxy_support.cc b/chrome_frame/cfproxy_support.cc
new file mode 100644
index 0000000..72454c0
--- /dev/null
+++ b/chrome_frame/cfproxy_support.cc
@@ -0,0 +1,450 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome_frame/cfproxy_private.h"
+
+#include "base/atomic_sequence_num.h"
+#include "base/command_line.h"
+#include "base/process_util.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/test/automation/automation_messages.h"
+#include "chrome_frame/chrome_launcher_utils.h"
+#include "chrome_frame/utils.h" // for IsHeadlessMode();
+
+
+namespace {
+void DispatchReplyFail(uint32 type,
+ ChromeProxyDelegate* delegate,
+ SyncMessageContext* ctx) {
+ switch (type) {
+ case AutomationMsg_CreateExternalTab::ID:
+ delegate->Completed_CreateTab(false, NULL, NULL, NULL);
+ break;
+ case AutomationMsg_ConnectExternalTab::ID:
+ delegate->Completed_ConnectToTab(false, NULL, NULL, NULL);
+ break;
+ case AutomationMsg_InstallExtension::ID:
+ delegate->Completed_InstallExtension(false,
+ AUTOMATION_MSG_EXTENSION_INSTALL_FAILED, ctx);
+ break;
+ }
+}
+
+bool DispatchReplyOk(const IPC::Message* reply_msg, uint32 type,
+ ChromeProxyDelegate* delegate, SyncMessageContext* ctx,
+ TabsMap* tab2delegate) {
+ void* iter = IPC::SyncMessage::GetDataIterator(reply_msg);
+ switch (type) {
+ case AutomationMsg_CreateExternalTab::ID: {
+ // Tuple3<HWND, HWND, int> out;
+ TupleTypes<AutomationMsg_CreateExternalTab::ReplyParam>::ValueTuple out;
+ if (ReadParam(reply_msg, &iter, &out)) {
+ DCHECK(tab2delegate->find(out.c) == tab2delegate->end());
+ (*tab2delegate)[out.c] = delegate;
+ delegate->Completed_CreateTab(true, out.a, out.b, out.c);
+ }
+ return true;
+ }
+
+ case AutomationMsg_ConnectExternalTab::ID: {
+ // Tuple3<HWND, HWND, int> out;
+ TupleTypes<AutomationMsg_ConnectExternalTab::ReplyParam>::ValueTuple out;
+ if (ReadParam(reply_msg, &iter, &out)) {
+ DCHECK(tab2delegate->find(out.c) == tab2delegate->end());
+ (*tab2delegate)[out.c] = delegate;
+ delegate->Completed_ConnectToTab(true, out.a, out.b, out.c);
+ }
+ return true;
+ }
+
+ case AutomationMsg_InstallExtension::ID: {
+ // Tuple1<AutomationMsg_ExtensionResponseValues> out;
+ TupleTypes<AutomationMsg_InstallExtension::ReplyParam>::ValueTuple out;
+ if (ReadParam(reply_msg, &iter, &out))
+ delegate->Completed_InstallExtension(true, out.a, ctx);
+ return true;
+ }
+
+ case AutomationMsg_LoadExpandedExtension::ID: {
+ // Tuple1<AutomationMsg_ExtensionResponseValues> out;
+ TupleTypes<AutomationMsg_LoadExpandedExtension::ReplyParam>::ValueTuple
+ out;
+ if (ReadParam(reply_msg, &iter, &out))
+ delegate->Completed_LoadExpandedExtension(true, out.a, ctx);
+ break;
+ }
+
+ case AutomationMsg_GetEnabledExtensions::ID: {
+ // Tuple1<std::vector<FilePath> >
+ TupleTypes<AutomationMsg_GetEnabledExtensions::ReplyParam>::ValueTuple
+ out;
+ if (ReadParam(reply_msg, &iter, &out))
+ delegate->Completed_GetEnabledExtensions(true, &out.a);
+ break;
+ }
+ } // switch
+
+ return false;
+}
+} // namespace
+
+// Itf2IPCMessage
+// Converts and sends trivial messages.
+void Interface2IPCMessage::RemoveBrowsingData(int mask) {
+ sender_->Send(new AutomationMsg_RemoveBrowsingData(0, mask));
+}
+
+void Interface2IPCMessage::SetProxyConfig(
+ const std::string& json_encoded_proxy_cfg) {
+ sender_->Send(new AutomationMsg_SetProxyConfig(0, json_encoded_proxy_cfg));
+}
+
+// Tab related.
+void Interface2IPCMessage::Tab_PostMessage(int tab, const std::string& message,
+ const std::string& origin, const std::string& target) {
+ sender_->Send(new AutomationMsg_HandleMessageFromExternalHost(
+ 0, tab, message, origin, target));
+}
+
+void Interface2IPCMessage::Tab_Reload(int tab) {
+ sender_->Send(new AutomationMsg_ReloadAsync(0, tab));
+}
+
+void Interface2IPCMessage::Tab_Stop(int tab) {
+ sender_->Send(new AutomationMsg_StopAsync(0, tab));
+}
+
+void Interface2IPCMessage::Tab_SaveAs(int tab) {
+ sender_->Send(new AutomationMsg_SaveAsAsync(0, tab));
+}
+
+void Interface2IPCMessage::Tab_Print(int tab) {
+ sender_->Send(new AutomationMsg_PrintAsync(0, tab));
+}
+
+void Interface2IPCMessage::Tab_Cut(int tab) {
+ sender_->Send(new AutomationMsg_Cut(0, tab));
+}
+
+void Interface2IPCMessage::Tab_Copy(int tab) {
+ sender_->Send(new AutomationMsg_Copy(0, tab));
+}
+
+void Interface2IPCMessage::Tab_Paste(int tab) {
+ sender_->Send(new AutomationMsg_Paste(0, tab));
+}
+
+void Interface2IPCMessage::Tab_SelectAll(int tab) {
+ sender_->Send(new AutomationMsg_SelectAll(0, tab));
+}
+
+void Interface2IPCMessage::Tab_MenuCommand(int tab, int selected_command) {
+ sender_->Send(new AutomationMsg_ForwardContextMenuCommandToChrome(
+ 0, tab, selected_command));
+}
+
+void Interface2IPCMessage::Tab_Zoom(int tab, PageZoom::Function zoom_level) {
+ sender_->Send(new AutomationMsg_SetZoomLevel(0, tab, zoom_level));
+}
+
+void Interface2IPCMessage::Tab_FontSize(int tab,
+ enum AutomationPageFontSize font_size) {
+ sender_->Send(new AutomationMsg_SetPageFontSize(0, tab, font_size));
+}
+
+void Interface2IPCMessage::Tab_SetInitialFocus(int tab, bool reverse,
+ bool restore_focus_to_view) {
+ sender_->Send(new AutomationMsg_SetInitialFocus(0, tab, reverse,
+ restore_focus_to_view));
+}
+
+void Interface2IPCMessage::Tab_SetParentWindow(int tab) {
+ CHECK(0) << "Implement me";
+ // AutomationMsg_TabReposition
+}
+
+void Interface2IPCMessage::Tab_Resize(int tab) {
+ CHECK(0) << "Implement me";
+ // AutomationMsg_TabReposition
+}
+
+void Interface2IPCMessage::Tab_ProcessAccelerator(int tab, const MSG& msg) {
+ sender_->Send(new AutomationMsg_ProcessUnhandledAccelerator(0, tab, msg));
+}
+
+// Misc.
+void Interface2IPCMessage::Tab_OnHostMoved(int tab) {
+ sender_->Send(new AutomationMsg_BrowserMove(0, tab));
+}
+
+void Interface2IPCMessage::Tab_SetEnableExtensionAutomation(int tab,
+ const std::vector<std::string>& functions_enabled) {
+ sender_->Send(new AutomationMsg_SetEnableExtensionAutomation(0, tab,
+ functions_enabled));
+}
+
+void DelegateHolder::AddDelegate(ChromeProxyDelegate* p) {
+ delegate_list_.insert(p);
+}
+
+void DelegateHolder::RemoveDelegate(ChromeProxyDelegate* p) {
+ // DCHECK(CalledOnValidThread());
+ int tab_handle = p->tab_handle(); // Could be 0.
+ delegate_list_.erase(p);
+ tab2delegate_.erase(tab_handle);
+}
+
+ChromeProxyDelegate* DelegateHolder::Tab2Delegate(int tab_handle) {
+ TabsMap::const_iterator iter = tab2delegate_.find(tab_handle);
+ if (iter != tab2delegate_.end())
+ return iter->second;
+ return NULL;
+}
+
+SyncMsgSender::SyncMsgSender(TabsMap* tab2delegate)
+ : tab2delegate_(tab2delegate) {
+}
+
+// The outgoing queue of sync messages must be locked.
+// Case: ui thread is sending message and waits for event, that is going to be
+// signaled by completion handler in ipc_thread.
+// We must append the message to the outgoing queue in UI thread,
+// otherwise if channel is disconnected before having a chance to
+// send the message, the ChromeProxyDelegate::_Disconnect implementation
+// shall know how to unblock arbitrary sync call. Instead
+// ChromeProxyDelgate::Completed_XXXX knows how to unblock a specific one.
+void SyncMsgSender::QueueSyncMessage(const IPC::SyncMessage* msg,
+ ChromeProxyDelegate* delegate,
+ SyncMessageContext* ctx) {
+ if (delegate) {
+ // We are interested of the result.
+ AutoLock lock(messages_lock_);
+ int id = IPC::SyncMessage::GetMessageId(*msg);
+ // A message can be sent only once.
+ DCHECK(messages_.end() == messages_.find(id));
+ messages_[id] = new SingleSentMessage(msg->type(), delegate, ctx);
+ }
+}
+
+void SyncMsgSender::Cancel(ChromeProxyDelegate* delegate) {
+ // TODO(stoyan): Cancel all outgoing calls for this delegate
+ // We may not need this. :)
+}
+
+SyncMsgSender::SingleSentMessage* SyncMsgSender::RemoveMessage(int id) {
+ AutoLock lock(messages_lock_);
+ SentMessages::iterator it = messages_.find(id);
+ if (it == messages_.end()) {
+ // Delegate is not interested in this sync message response.
+ return NULL;
+ }
+
+ // See what message is this.
+ SingleSentMessage* origin = it->second;
+ messages_.erase(it);
+ return origin;
+}
+
+bool SyncMsgSender::OnReplyReceived(const IPC::Message* reply_msg) {
+ if (!reply_msg->is_reply())
+ return false; // Not a reply to sync message.
+
+ // Find message by id.
+ int id = IPC::SyncMessage::GetMessageId(*reply_msg);
+ SingleSentMessage* origin = RemoveMessage(id);
+ if (origin) {
+ DispatchReplyOk(reply_msg, origin->type_, origin->delegate_, origin->ctx_,
+ tab2delegate_);
+ delete origin;
+ }
+
+ return true;
+}
+
+void SyncMsgSender::OnChannelClosed() {
+ SentMessages messages_sent;
+ // Make a copy of the messages queue
+ {
+ AutoLock lock(messages_lock_);
+ messages_.swap(messages_sent);
+ }
+
+
+ SentMessages::reverse_iterator it = messages_sent.rbegin();
+ for (; it != messages_sent.rend(); ++it) {
+ SingleSentMessage* origin = it->second;
+ DispatchReplyFail(origin->type_, origin->delegate_, origin->ctx_);
+ delete origin;
+ }
+ messages_sent.clear();
+}
+
+static base::AtomicSequenceNumber g_proxy_channel_id(base::LINKER_INITIALIZED);
+std::string GenerateChannelId() {
+ return StringPrintf("ChromeTestingInterface:%u.%d",
+ base::GetCurrentProcId(), g_proxy_channel_id.GetNext() + 0xC000);
+}
+
+std::wstring BuildCmdLine(const std::string& channel_id,
+ const FilePath& profile_path,
+ const std::wstring& extra_args) {
+ scoped_ptr<CommandLine> command_line(
+ chrome_launcher::CreateLaunchCommandLine());
+ command_line->AppendSwitchASCII(switches::kAutomationClientChannelID,
+ channel_id);
+ // Run Chrome in Chrome Frame mode. In practice, this modifies the paths
+ // and registry keys that Chrome looks in via the BrowserDistribution
+ // mechanism.
+ command_line->AppendSwitch(switches::kChromeFrame);
+ // Chrome Frame never wants Chrome to start up with a First Run UI.
+ command_line->AppendSwitch(switches::kNoFirstRun);
+ command_line->AppendSwitch(switches::kDisablePopupBlocking);
+
+#ifndef NDEBUG
+ // Disable the "Whoa! Chrome has crashed." dialog, because that isn't very
+ // useful for Chrome Frame users.
+ command_line->AppendSwitch(switches::kNoErrorDialogs);
+#endif
+
+ // In headless mode runs like reliability test runs we want full crash dumps
+ // from chrome.
+ if (IsHeadlessMode())
+ command_line->AppendSwitch(switches::kFullMemoryCrashReport);
+
+ command_line->AppendSwitchPath(switches::kUserDataDir, profile_path);
+
+ std::wstring command_line_string(command_line->command_line_string());
+ if (!extra_args.empty()) {
+ command_line_string.append(L" ");
+ command_line_string.append(extra_args);
+ }
+ return command_line_string;
+}
+
+int IsTabMessage(const IPC::Message& message) {
+ switch (message.type()) {
+ case AutomationMsg_NavigationStateChanged__ID:
+ case AutomationMsg_UpdateTargetUrl__ID:
+ case AutomationMsg_HandleAccelerator__ID:
+ case AutomationMsg_TabbedOut__ID:
+ case AutomationMsg_OpenURL__ID:
+ case AutomationMsg_NavigationFailed__ID:
+ case AutomationMsg_DidNavigate__ID:
+ case AutomationMsg_TabLoaded__ID:
+ case AutomationMsg_ForwardMessageToExternalHost__ID:
+ case AutomationMsg_ForwardContextMenuToExternalHost__ID:
+ case AutomationMsg_RequestStart__ID:
+ case AutomationMsg_RequestRead__ID:
+ case AutomationMsg_RequestEnd__ID:
+ case AutomationMsg_DownloadRequestInHost__ID:
+ case AutomationMsg_SetCookieAsync__ID:
+ case AutomationMsg_AttachExternalTab__ID:
+ case AutomationMsg_RequestGoToHistoryEntryOffset__ID:
+ case AutomationMsg_GetCookiesFromHost__ID:
+ case AutomationMsg_CloseExternalTab__ID: {
+ // Read tab handle from the message.
+ void* iter = NULL;
+ int tab_handle = 0;
+ message.ReadInt(&iter, &tab_handle);
+ return tab_handle;
+ }
+ }
+
+ return 0;
+}
+
+bool DispatchTabMessageToDelegate(ChromeProxyDelegate* delegate,
+ const IPC::Message& m) {
+ void* iter = 0;
+ switch (m.type()) {
+ case AutomationMsg_NavigationStateChanged__ID: {
+ // Tuple3<int, int, IPC::NavigationInfo>
+ AutomationMsg_NavigationStateChanged::Param params;
+ if (ReadParam(&m, &iter, &params))
+ delegate->NavigationStateChanged(params.b, params.c);
+ return true;
+ }
+
+ case AutomationMsg_UpdateTargetUrl__ID: {
+ // Tuple2<int, std::wstring>
+ AutomationMsg_UpdateTargetUrl::Param params;
+ if (ReadParam(&m, &iter, &params))
+ delegate->UpdateTargetUrl(params.b);
+ return true;
+ }
+
+ case AutomationMsg_HandleAccelerator__ID: {
+ AutomationMsg_HandleAccelerator::Param params;
+ return true;
+ }
+
+ case AutomationMsg_TabbedOut__ID: {
+ AutomationMsg_TabbedOut::Param params;
+ return true;
+ }
+
+ case AutomationMsg_OpenURL__ID: {
+ AutomationMsg_OpenURL::Param params;
+ return true;
+ }
+
+ case AutomationMsg_NavigationFailed__ID: {
+ AutomationMsg_NavigationFailed::Param params;
+ return true;
+ }
+
+ case AutomationMsg_DidNavigate__ID: {
+ AutomationMsg_DidNavigate::Param params;
+ return true;
+ }
+
+ case AutomationMsg_TabLoaded__ID: {
+ return true;
+ }
+ case AutomationMsg_ForwardMessageToExternalHost__ID: {
+ return true;
+ }
+
+ case AutomationMsg_ForwardContextMenuToExternalHost__ID: {
+ return true;
+ }
+
+ case AutomationMsg_RequestStart__ID: {
+ return true;
+ }
+
+ case AutomationMsg_RequestRead__ID: {
+ return true;
+ }
+
+ case AutomationMsg_RequestEnd__ID: {
+ return true;
+ }
+
+ case AutomationMsg_DownloadRequestInHost__ID: {
+ return true;
+ }
+
+ case AutomationMsg_SetCookieAsync__ID: {
+ return true;
+ }
+
+ case AutomationMsg_AttachExternalTab__ID: {
+ return true;
+ }
+
+ case AutomationMsg_RequestGoToHistoryEntryOffset__ID: {
+ return true;
+ }
+
+ case AutomationMsg_GetCookiesFromHost__ID: {
+ return true;
+ }
+
+ case AutomationMsg_CloseExternalTab__ID: {
+ return true;
+ }
+ }
+ return true;
+}