summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrobertshield@google.com <robertshield@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-04-13 16:45:29 +0000
committerrobertshield@google.com <robertshield@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-04-13 16:45:29 +0000
commitc6cb199d2d1d67af63d7227eff77e0a4163629fd (patch)
tree4b3686a906c056f3ad417deeff255cbfcce6f4dd
parent8830998f7436edb5aabd1a3465d7ba5e7b77fd05 (diff)
downloadchromium_src-c6cb199d2d1d67af63d7227eff77e0a4163629fd.zip
chromium_src-c6cb199d2d1d67af63d7227eff77e0a4163629fd.tar.gz
chromium_src-c6cb199d2d1d67af63d7227eff77e0a4163629fd.tar.bz2
Adding versioning support to the chrome automation protocol.
Review URL: http://codereview.chromium.org/62061 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@13598 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/automation/automation_provider.cc8
-rw-r--r--chrome/test/automation/automation_constants.h9
-rw-r--r--chrome/test/automation/automation_messages_internal.h9
-rw-r--r--chrome/test/automation/automation_proxy.cc70
-rw-r--r--chrome/test/automation/automation_proxy.h37
5 files changed, 116 insertions, 17 deletions
diff --git a/chrome/browser/automation/automation_provider.cc b/chrome/browser/automation/automation_provider.cc
index 067302a..9dee930 100644
--- a/chrome/browser/automation/automation_provider.cc
+++ b/chrome/browser/automation/automation_provider.cc
@@ -4,6 +4,7 @@
#include "chrome/browser/automation/automation_provider.h"
+#include "base/file_version_info.h"
#include "base/message_loop.h"
#include "base/path_service.h"
#include "base/string_util.h"
@@ -774,7 +775,12 @@ void AutomationProvider::ConnectToChannel(const std::wstring& channel_id) {
new IPC::SyncChannel(channel_id, IPC::Channel::MODE_CLIENT, this, NULL,
g_browser_process->io_thread()->message_loop(),
true, g_browser_process->shutdown_event()));
- channel_->Send(new AutomationMsg_Hello(0));
+ FileVersionInfo* file_version_info =
+ FileVersionInfo::CreateFileVersionInfoForCurrentModule();
+ std::string version_string(WideToASCII(file_version_info->file_version()));
+
+ // Send a hello message with our current automation protocol version.
+ channel_->Send(new AutomationMsg_Hello(0, version_string.c_str()));
}
void AutomationProvider::SetExpectedTabCount(size_t expected_tabs) {
diff --git a/chrome/test/automation/automation_constants.h b/chrome/test/automation/automation_constants.h
index b31139e..06d13e0 100644
--- a/chrome/test/automation/automation_constants.h
+++ b/chrome/test/automation/automation_constants.h
@@ -10,6 +10,15 @@ namespace automation {
static const int kSleepTime = 250;
}
+// Used by AutomationProxy, declared here so that other headers don't need
+// to include automation_proxy.h.
+enum AutomationLaunchResult {
+ AUTOMATION_SUCCESS,
+ AUTOMATION_TIMEOUT,
+ AUTOMATION_VERSION_MISMATCH,
+ AUTOMATION_CREATE_TAB_FAILED
+};
+
enum AutomationMsg_NavigationResponseValues {
AUTOMATION_MSG_NAVIGATION_ERROR = 0,
AUTOMATION_MSG_NAVIGATION_SUCCESS,
diff --git a/chrome/test/automation/automation_messages_internal.h b/chrome/test/automation/automation_messages_internal.h
index b954b3f..f6ed6d5 100644
--- a/chrome/test/automation/automation_messages_internal.h
+++ b/chrome/test/automation/automation_messages_internal.h
@@ -34,8 +34,13 @@
IPC_BEGIN_MESSAGES(Automation)
// This message is fired when the AutomationProvider is up and running
- // in the app (the app is not fully up at this point).
- IPC_MESSAGE_ROUTED0(AutomationMsg_Hello)
+ // in the app (the app is not fully up at this point). The parameter to this
+ // message is the version string of the automation provider. This parameter
+ // is defined to be the version string as returned by
+ // FileVersionInfo::file_version().
+ // The client can choose to use this version string to decide whether or not
+ // it can talk to the provider.
+ IPC_MESSAGE_ROUTED1(AutomationMsg_Hello, std::string)
// This message is fired when the initial tab(s) are finished loading.
IPC_MESSAGE_ROUTED0(AutomationMsg_InitialLoadsComplete)
diff --git a/chrome/test/automation/automation_proxy.cc b/chrome/test/automation/automation_proxy.cc
index 416d0c9..5715aac 100644
--- a/chrome/test/automation/automation_proxy.cc
+++ b/chrome/test/automation/automation_proxy.cc
@@ -7,6 +7,7 @@
#include "chrome/test/automation/automation_proxy.h"
#include "base/basictypes.h"
+#include "base/file_version_info.h"
#include "base/logging.h"
#include "base/platform_thread.h"
#include "base/process_util.h"
@@ -28,9 +29,9 @@ using base::TimeTicks;
// This class exists to group together the data and functionality used for
// synchronous automation requests.
-class AutomationRequest :
- public base::RefCountedThreadSafe<AutomationRequest> {
-public:
+class AutomationRequest
+ : public base::RefCountedThreadSafe<AutomationRequest> {
+ public:
AutomationRequest() : received_response_(true, false) {
static int32 routing_id = 0;
routing_id_ = ++routing_id;
@@ -59,12 +60,12 @@ public:
return *(response_.get());
}
-private:
- DISALLOW_EVIL_CONSTRUCTORS(AutomationRequest);
-
+ private:
int32 routing_id_;
scoped_ptr<IPC::Message> response_;
base::WaitableEvent received_response_;
+
+ DISALLOW_EVIL_CONSTRUCTORS(AutomationRequest);
};
namespace {
@@ -103,8 +104,8 @@ class AutomationMessageFilter : public IPC::ChannelProxy::MessageFilter {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(AutomationMessageFilter, message)
- IPC_MESSAGE_HANDLER_GENERIC(
- AutomationMsg_Hello, server_->SignalAppLaunch());
+ IPC_MESSAGE_HANDLER_GENERIC(AutomationMsg_Hello,
+ OnAutomationHello(message));
IPC_MESSAGE_HANDLER_GENERIC(
AutomationMsg_InitialLoadsComplete, server_->SignalInitialLoads());
IPC_MESSAGE_HANDLER(AutomationMsg_InitialNewTabUILoadComplete,
@@ -121,6 +122,19 @@ class AutomationMessageFilter : public IPC::ChannelProxy::MessageFilter {
server_->SignalNewTabUITab(load_time);
}
+ void OnAutomationHello(const IPC::Message& hello_message) {
+ std::string server_version;
+ void* iter = NULL;
+ if (!hello_message.ReadString(&iter, &server_version)) {
+ // We got an AutomationMsg_Hello from an old automation provider
+ // that doesn't send version info. Leave server_version as an empty
+ // string to signal a version mismatch.
+ LOG(ERROR) << "Pre-versioning protocol detected in automation provider.";
+ }
+
+ server_->SignalAppLaunch(server_version);
+ }
+
private:
AutomationProxy* server_;
};
@@ -134,6 +148,8 @@ AutomationProxy::AutomationProxy(int command_execution_timeout_ms)
new_tab_ui_load_complete_(true, false),
shutdown_event_(new base::WaitableEvent(true, false)),
current_request_(NULL),
+ app_launch_signaled_(0),
+ perform_version_check_(false),
command_execution_timeout_(
TimeDelta::FromMilliseconds(command_execution_timeout_ms)) {
InitializeChannelID();
@@ -199,11 +215,43 @@ void AutomationProxy::InitializeHandleTracker() {
tracker_.reset(new AutomationHandleTracker(this));
}
-bool AutomationProxy::WaitForAppLaunch() {
- return app_launched_.TimedWait(command_execution_timeout_);
+AutomationLaunchResult AutomationProxy::WaitForAppLaunch() {
+ AutomationLaunchResult result = AUTOMATION_SUCCESS;
+ if (app_launched_.TimedWait(command_execution_timeout_)) {
+ if (perform_version_check_) {
+ // Obtain our own version number and compare it to what the automation
+ // provider sent.
+ FileVersionInfo* file_version_info =
+ FileVersionInfo::CreateFileVersionInfoForCurrentModule();
+ DCHECK(file_version_info);
+ std::string version_string(
+ WideToASCII(file_version_info->file_version()));
+
+ // Note that we use a simple string comparison since we expect the version
+ // to be a punctuated numeric string. Consider using base/Version if we
+ // ever need something more complicated here.
+ if (server_version_ != version_string) {
+ result = AUTOMATION_VERSION_MISMATCH;
+ }
+ }
+ } else {
+ result = AUTOMATION_TIMEOUT;
+ }
+ return result;
}
-void AutomationProxy::SignalAppLaunch() {
+void AutomationProxy::SignalAppLaunch(const std::string& version_string) {
+ // The synchronization of the reading / writing of server_version_ is a bit
+ // messy but does work as long as SignalAppLaunch is only called once.
+ // Review this if we ever want an AutomationProxy instance to launch
+ // multiple AutomationProviders.
+ app_launch_signaled_++;
+ if (app_launch_signaled_ > 1) {
+ NOTREACHED();
+ LOG(ERROR) << "Multiple AutomationMsg_Hello messages received";
+ return;
+ }
+ server_version_ = version_string;
app_launched_.Signal();
}
diff --git a/chrome/test/automation/automation_proxy.h b/chrome/test/automation/automation_proxy.h
index 46a3b23..e229001 100644
--- a/chrome/test/automation/automation_proxy.h
+++ b/chrome/test/automation/automation_proxy.h
@@ -66,8 +66,13 @@ class AutomationProxy : public IPC::Channel::Listener,
// Waits for the app to launch and the automation provider to say hello
// (the app isn't fully done loading by this point).
- // Returns true if the launch is successful
- bool WaitForAppLaunch();
+ // Returns SUCCESS if the launch is successful.
+ // Returns TIMEOUT if there was no response by command_execution_timeout_
+ // Returns VERSION_MISMATCH if the automation protocol version of the
+ // automation provider does not match and if perform_version_check_ is set
+ // to true. Note that perform_version_check_ defaults to false, call
+ // set_perform_version_check() to set it.
+ AutomationLaunchResult WaitForAppLaunch();
// Waits for any initial page loads to complete.
// NOTE: this only fires once for a run of the application.
@@ -140,7 +145,7 @@ class AutomationProxy : public IPC::Channel::Listener,
// These methods are intended to be called by the background thread
// to signal that the given event has occurred, and that any corresponding
// Wait... function can return.
- void SignalAppLaunch();
+ void SignalAppLaunch(const std::string& version_string);
void SignalInitialLoads();
// load_time is how long, in ms, the tab contents took to load.
void SignalNewTabUITab(int load_time);
@@ -187,6 +192,20 @@ class AutomationProxy : public IPC::Channel::Listener,
return static_cast<int>(command_execution_timeout_.InMilliseconds());
}
+ // Returns the server version of the server connected. You may only call this
+ // method after WaitForAppLaunch() has returned SUCCESS or VERSION_MISMATCH.
+ // If you call it before this, the return value is undefined.
+ std::string server_version() const {
+ return server_version_;
+ }
+
+ // Call this while passing true to tell the automation proxy to perform
+ // a version check when WaitForAppLaunch() is called. Note that
+ // platform_version_check_ defaults to false.
+ void set_perform_version_check(bool perform_version_check) {
+ perform_version_check_ = perform_version_check;
+ }
+
private:
void InitializeChannelID();
void InitializeThread();
@@ -208,6 +227,18 @@ class AutomationProxy : public IPC::Channel::Listener,
AutomationRequest* current_request_;
+ // The version of the automation provider we are communicating with.
+ std::string server_version_;
+
+ // Used to guard against multiple hello messages being received.
+ int app_launch_signaled_;
+
+ // Whether to perform a version check between the automation proxy and
+ // the automation provider at connection time. Defaults to false, you can
+ // set this to true if building the automation proxy into a module with
+ // a version resource.
+ bool perform_version_check_;
+
// Delay to let the browser execute the command.
base::TimeDelta command_execution_timeout_;