15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/test/automation/automation_proxy.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sstream>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/debug/trace_event.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/ref_counted.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/synchronization/waitable_event.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/platform_thread.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/automation_constants.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/automation_messages.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_version_info.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/test/automation/automation_json_requests.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/test/automation/browser_proxy.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/test/automation/tab_proxy.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/test/automation/window_proxy.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ipc/ipc_descriptors.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(port): Enable when dialog_delegate is ported.
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/window/dialog_delegate.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::TimeDelta;
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::TimeTicks;
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kChannelErrorVersionString[] = "***CHANNEL_ERROR***";
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This object allows messages received on the background thread to be
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// properly triaged.
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class AutomationMessageFilter : public IPC::ChannelProxy::MessageFilter {
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit AutomationMessageFilter(AutomationProxy* server) : server_(server) {}
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Return true to indicate that the message was handled, or false to let
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the message be handled in the default way.
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool handled = true;
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_BEGIN_MESSAGE_MAP(AutomationMessageFilter, message)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      IPC_MESSAGE_HANDLER_GENERIC(AutomationMsg_Hello,
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  OnAutomationHello(message))
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      IPC_MESSAGE_HANDLER_GENERIC(
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        AutomationMsg_InitialLoadsComplete, server_->SignalInitialLoads())
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      IPC_MESSAGE_HANDLER(AutomationMsg_InitialNewTabUILoadComplete,
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          NewTabLoaded)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      IPC_MESSAGE_HANDLER_GENERIC(
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        AutomationMsg_InvalidateHandle, server_->InvalidateHandle(message))
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      IPC_MESSAGE_UNHANDLED(handled = false)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_END_MESSAGE_MAP()
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return handled;
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnFilterAdded(IPC::Channel* channel) OVERRIDE {
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    server_->SetChannel(channel);
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnFilterRemoved() OVERRIDE {
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    server_->ResetChannel();
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnChannelError() OVERRIDE {
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    server_->SignalAppLaunch(kChannelErrorVersionString);
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    server_->SignalNewTabUITab(-1);
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void NewTabLoaded(int load_time) {
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    server_->SignalNewTabUITab(load_time);
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnAutomationHello(const IPC::Message& hello_message) {
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string server_version;
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PickleIterator iter(hello_message);
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!hello_message.ReadString(&iter, &server_version)) {
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // We got an AutomationMsg_Hello from an old automation provider
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // that doesn't send version info. Leave server_version as an empty
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // string to signal a version mismatch.
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(ERROR) << "Pre-versioning protocol detected in automation provider.";
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    server_->SignalAppLaunch(server_version);
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AutomationProxy* server_;
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(AutomationMessageFilter);
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // anonymous namespace
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AutomationProxy::AutomationProxy(base::TimeDelta action_timeout,
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 bool disconnect_on_failure)
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : app_launched_(true, false),
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      initial_loads_complete_(true, false),
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new_tab_ui_load_complete_(true, false),
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      shutdown_event_(new base::WaitableEvent(true, false)),
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      perform_version_check_(false),
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      disconnect_on_failure_(disconnect_on_failure),
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      channel_disconnected_on_failure_(false),
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      action_timeout_(action_timeout),
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      listener_thread_id_(0) {
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // base::WaitableEvent::TimedWait() will choke if we give it a negative value.
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Zero also seems unreasonable, since we need to wait for IPC, but at
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // least it is legal... ;-)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_GE(action_timeout.InMilliseconds(), 0);
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  listener_thread_id_ = base::PlatformThread::CurrentId();
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InitializeHandleTracker();
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InitializeThread();
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AutomationProxy::~AutomationProxy() {
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Destruction order is important. Thread has to outlive the channel and
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // tracker has to outlive the thread since we access the tracker inside
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // AutomationMessageFilter::OnMessageReceived.
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Disconnect();
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  thread_.reset();
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tracker_.reset();
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string AutomationProxy::GenerateChannelID() {
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The channel counter keeps us out of trouble if we create and destroy
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // several AutomationProxies sequentially over the course of a test run.
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // (Creating the channel sometimes failed before when running a lot of
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // tests in sequence, and our theory is that sometimes the channel ID
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // wasn't getting freed up in time for the next test.)
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static int channel_counter = 0;
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::ostringstream buf;
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  buf << "ChromeTestingInterface:" << base::GetCurrentProcId() <<
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         "." << ++channel_counter;
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return buf.str();
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AutomationProxy::InitializeThread() {
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<base::Thread> thread(
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new base::Thread("AutomationProxy_BackgroundThread"));
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Thread::Options options;
146a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  options.message_loop_type = base::MessageLoop::TYPE_IO;
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool thread_result = thread->StartWithOptions(options);
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(thread_result);
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  thread_.swap(thread);
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AutomationProxy::InitializeChannel(const std::string& channel_id,
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        bool use_named_interface) {
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(shutdown_event_.get() != NULL);
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(iyengar)
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The shutdown event could be global on the same lines as the automation
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // provider, where we use the shutdown event provided by the chrome browser
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // process.
1607d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  channel_.reset(new IPC::SyncChannel(this,  // we are the listener
1617d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                      thread_->message_loop_proxy().get(),
1627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                      shutdown_event_.get()));
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  channel_->AddFilter(new AutomationMessageFilter(this));
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create the pipe synchronously so that Chrome doesn't try to connect to an
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // unready server. Note this is done after adding a message filter to
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // guarantee that it doesn't miss any messages when we are the client.
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // See crbug.com/102894.
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  channel_->Init(
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      channel_id,
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      use_named_interface ? IPC::Channel::MODE_NAMED_CLIENT
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          : IPC::Channel::MODE_SERVER,
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      true /* create_pipe_now */);
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AutomationProxy::InitializeHandleTracker() {
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tracker_.reset(new AutomationHandleTracker());
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AutomationLaunchResult AutomationProxy::WaitForAppLaunch() {
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AutomationLaunchResult result = AUTOMATION_SUCCESS;
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (app_launched_.TimedWait(action_timeout_)) {
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (server_version_ == kChannelErrorVersionString) {
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      result = AUTOMATION_CHANNEL_ERROR;
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (perform_version_check_) {
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Obtain our own version number and compare it to what the automation
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // provider sent.
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      chrome::VersionInfo version_info;
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DCHECK(version_info.is_valid());
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Note that we use a simple string comparison since we expect the version
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // to be a punctuated numeric string. Consider using base/Version if we
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // ever need something more complicated here.
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (server_version_ != version_info.Version()) {
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        result = AUTOMATION_VERSION_MISMATCH;
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result = AUTOMATION_TIMEOUT;
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AutomationProxy::SignalAppLaunch(const std::string& version_string) {
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  server_version_ = version_string;
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  app_launched_.Signal();
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool AutomationProxy::WaitForProcessLauncherThreadToGoIdle() {
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Send(new AutomationMsg_WaitForProcessLauncherThreadToGoIdle());
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool AutomationProxy::WaitForInitialLoads() {
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return initial_loads_complete_.TimedWait(action_timeout_);
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool AutomationProxy::WaitForInitialNewTabUILoad(int* load_time) {
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (new_tab_ui_load_complete_.TimedWait(action_timeout_)) {
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *load_time = new_tab_ui_load_time_;
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    new_tab_ui_load_complete_.Reset();
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AutomationProxy::SignalInitialLoads() {
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  initial_loads_complete_.Signal();
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AutomationProxy::SignalNewTabUITab(int load_time) {
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  new_tab_ui_load_time_ = load_time;
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  new_tab_ui_load_complete_.Signal();
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool AutomationProxy::GetBrowserWindowCount(int* num_windows) {
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!num_windows) {
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Send(new AutomationMsg_BrowserWindowCount(num_windows));
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool AutomationProxy::GetNormalBrowserWindowCount(int* num_windows) {
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!num_windows) {
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Send(new AutomationMsg_NormalBrowserWindowCount(num_windows));
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool AutomationProxy::WaitForWindowCountToBecome(int count) {
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool wait_success = false;
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!Send(new AutomationMsg_WaitForBrowserWindowCountToBecome(
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                count, &wait_success))) {
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return wait_success;
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool AutomationProxy::IsURLDisplayed(GURL url) {
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int window_count;
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!GetBrowserWindowCount(&window_count))
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < window_count; i++) {
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_refptr<BrowserProxy> window = GetBrowserWindow(i);
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!window.get())
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int tab_count;
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!window->GetTabCount(&tab_count))
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int j = 0; j < tab_count; j++) {
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      scoped_refptr<TabProxy> tab = window->GetTab(j);
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!tab.get())
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GURL tab_url;
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!tab->GetCurrentURL(&tab_url))
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        continue;
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (tab_url == url)
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return true;
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool AutomationProxy::GetMetricEventDuration(const std::string& event_name,
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             int* duration_ms) {
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Send(new AutomationMsg_GetMetricEventDuration(event_name,
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                       duration_ms));
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool AutomationProxy::SendProxyConfig(const std::string& new_proxy_config) {
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Send(new AutomationMsg_SetProxyConfig(new_proxy_config));
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AutomationProxy::Disconnect() {
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(shutdown_event_.get() != NULL);
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  shutdown_event_->Signal();
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  channel_.reset();
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool AutomationProxy::OnMessageReceived(const IPC::Message& msg) {
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This won't get called unless AutomationProxy is run from
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // inside a message loop.
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTREACHED();
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AutomationProxy::OnChannelError() {
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LOG(ERROR) << "Channel error in AutomationProxy.";
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (disconnect_on_failure_)
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Disconnect();
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)scoped_refptr<BrowserProxy> AutomationProxy::GetBrowserWindow(
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int window_index) {
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int handle = 0;
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!Send(new AutomationMsg_BrowserWindow(window_index, &handle)))
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ProxyObjectFromHandle<BrowserProxy>(handle);
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IPC::SyncChannel* AutomationProxy::channel() {
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return channel_.get();
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool AutomationProxy::Send(IPC::Message* message) {
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Send(message,
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    static_cast<int>(action_timeout_.InMilliseconds()));
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool AutomationProxy::Send(IPC::Message* message, int timeout_ms) {
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!channel_.get()) {
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Automation channel has been closed; dropping message!";
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete message;
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool success = channel_->SendWithTimeout(message, timeout_ms);
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!success && disconnect_on_failure_) {
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Send failed (possibly due to a timeout). Browser is likely in a weird
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // state, and further IPC requests are extremely likely to fail (possibly
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // timeout, which would make tests slower). Disconnect the channel now
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // to avoid the slowness.
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    channel_disconnected_on_failure_ = true;
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Disconnecting channel after error!";
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Disconnect();
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return success;
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AutomationProxy::InvalidateHandle(const IPC::Message& message) {
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PickleIterator iter(message);
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int handle;
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (message.ReadInt(&iter, &handle)) {
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tracker_->InvalidateHandle(handle);
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool AutomationProxy::OpenNewBrowserWindow(Browser::Type type, bool show) {
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Send(
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new AutomationMsg_OpenNewBrowserWindowOfType(static_cast<int>(type),
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                   show));
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <class T> scoped_refptr<T> AutomationProxy::ProxyObjectFromHandle(
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int handle) {
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!handle)
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Get AddRef-ed pointer to the object if handle is already seen.
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  T* p = static_cast<T*>(tracker_->GetResource(handle));
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!p) {
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    p = new T(this, tracker_.get(), handle);
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    p->AddRef();
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Since there is no scoped_refptr::attach.
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<T> result;
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result.swap(&p);
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AutomationProxy::SetChannel(IPC::Channel* channel) {
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (tracker_.get())
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tracker_->put_channel(channel);
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AutomationProxy::ResetChannel() {
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (tracker_.get())
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tracker_->put_channel(NULL);
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
405c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool AutomationProxy::BeginTracing(const std::string& category_patterns) {
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool result = false;
407c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool send_success = Send(new AutomationMsg_BeginTracing(category_patterns,
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                          &result));
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return send_success && result;
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool AutomationProxy::EndTracing(std::string* json_trace_output) {
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool success = false;
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t num_trace_chunks = 0;
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!Send(new AutomationMsg_EndTracing(&num_trace_chunks, &success)) ||
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !success)
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string chunk;
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::debug::TraceResultBuffer buffer;
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::debug::TraceResultBuffer::SimpleOutput output;
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  buffer.SetOutputCallback(output.GetCallback());
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(jbates): See bug 100255, IPC send fails if message is too big. This
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // code can be simplified if that limitation is fixed.
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Workaround IPC payload size limitation by getting chunks.
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  buffer.Start();
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < num_trace_chunks; ++i) {
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The broswer side AutomationProvider resets state at BeginTracing,
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // so it can recover even after this fails mid-way.
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!Send(new AutomationMsg_GetTracingOutput(&chunk, &success)) ||
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        !success)
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    buffer.AddFragment(chunk);
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  buffer.Finish();
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *json_trace_output = output.json_output;
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool AutomationProxy::SendJSONRequest(const std::string& request,
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      int timeout_ms,
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      std::string* response) {
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool result = false;
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!SendAutomationJSONRequest(this, request, timeout_ms, response, &result))
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
450