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 "content/public/test/browser_test_utils.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/json/json_reader.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/path_service.h"
1058e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch#include "base/process/kill.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/rand_util.h"
127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/strings/string_number_conversions.h"
13868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/synchronization/waitable_event.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/test/test_timeouts.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/values.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_context.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/dom_operation_notification_details.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_service.h"
20868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/public/browser/notification_types.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/render_process_host.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/render_view_host.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_contents.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_contents_observer.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_contents_view.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/test/test_utils.h"
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/base/net_util.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/cookies/cookie_store.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/test/python_utils.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_request_context.h"
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_request_context_getter.h"
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kDefaultWsPort = 8880;
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace content {
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class DOMOperationObserver : public NotificationObserver,
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             public WebContentsObserver {
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  explicit DOMOperationObserver(RenderViewHost* rvh)
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      : WebContentsObserver(WebContents::FromRenderViewHost(rvh)),
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        did_respond_(false) {
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    registrar_.Add(this, NOTIFICATION_DOM_OPERATION_RESPONSE,
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   Source<RenderViewHost>(rvh));
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    message_loop_runner_ = new MessageLoopRunner;
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void Observe(int type,
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       const NotificationSource& source,
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       const NotificationDetails& details) OVERRIDE {
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(type == NOTIFICATION_DOM_OPERATION_RESPONSE);
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Details<DomOperationNotificationDetails> dom_op_details(details);
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    response_ = dom_op_details->json;
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    did_respond_ = true;
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    message_loop_runner_->Quit();
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Overridden from WebContentsObserver:
617dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  virtual void RenderProcessGone(base::TerminationStatus status) OVERRIDE {
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    message_loop_runner_->Quit();
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool WaitAndGetResponse(std::string* response) WARN_UNUSED_RESULT {
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    message_loop_runner_->Run();
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *response = response_;
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return did_respond_;
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NotificationRegistrar registrar_;
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string response_;
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool did_respond_;
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<MessageLoopRunner> message_loop_runner_;
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(DOMOperationObserver);
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Specifying a prototype so that we can add the WARN_UNUSED_RESULT attribute.
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool ExecuteScriptHelper(RenderViewHost* render_view_host,
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         const std::string& frame_xpath,
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         const std::string& original_script,
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         scoped_ptr<Value>* result) WARN_UNUSED_RESULT;
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Executes the passed |original_script| in the frame pointed to by
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |frame_xpath|.  If |result| is not NULL, stores the value that the evaluation
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// of the script in |result|.  Returns true on success.
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool ExecuteScriptHelper(RenderViewHost* render_view_host,
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         const std::string& frame_xpath,
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         const std::string& original_script,
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         scoped_ptr<Value>* result) {
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(jcampan): we should make the domAutomationController not require an
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //                automation id.
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string script =
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "window.domAutomationController.setAutomationId(0);" + original_script;
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DOMOperationObserver dom_op_observer(render_view_host);
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  render_view_host->ExecuteJavascriptInWebFrame(UTF8ToUTF16(frame_xpath),
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                UTF8ToUTF16(script));
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string json;
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!dom_op_observer.WaitAndGetResponse(&json)) {
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DLOG(ERROR) << "Cannot communicate with DOMOperationObserver.";
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Nothing more to do for callers that ignore the returned JS value.
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!result)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::JSONReader reader(base::JSON_ALLOW_TRAILING_COMMAS);
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result->reset(reader.ReadToValue(json));
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!result->get()) {
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DLOG(ERROR) << reader.GetErrorMessage();
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BuildSimpleWebKeyEvent(WebKit::WebInputEvent::Type type,
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            ui::KeyboardCode key,
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            bool control,
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            bool shift,
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            bool alt,
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            bool command,
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            NativeWebKeyboardEvent* event) {
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  event->nativeKeyCode = 0;
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  event->windowsKeyCode = key;
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  event->setKeyIdentifierFromWindowsKeyCode();
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  event->type = type;
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  event->modifiers = 0;
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  event->isSystemKey = false;
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  event->timeStampSeconds = base::Time::Now().ToDoubleT();
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  event->skip_in_browser = true;
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (type == WebKit::WebInputEvent::Char ||
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      type == WebKit::WebInputEvent::RawKeyDown) {
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    event->text[0] = key;
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    event->unmodifiedText[0] = key;
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (control)
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    event->modifiers |= WebKit::WebInputEvent::ControlKey;
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (shift)
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    event->modifiers |= WebKit::WebInputEvent::ShiftKey;
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (alt)
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    event->modifiers |= WebKit::WebInputEvent::AltKey;
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (command)
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    event->modifiers |= WebKit::WebInputEvent::MetaKey;
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GetCookiesCallback(std::string* cookies_out,
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        base::WaitableEvent* event,
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        const std::string& cookies) {
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *cookies_out = cookies;
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  event->Signal();
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GetCookiesOnIOThread(const GURL& url,
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          net::URLRequestContextGetter* context_getter,
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          base::WaitableEvent* event,
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          std::string* cookies) {
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net::CookieStore* cookie_store =
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      context_getter->GetURLRequestContext()->cookie_store();
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cookie_store->GetCookiesWithOptionsAsync(
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      url, net::CookieOptions(),
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&GetCookiesCallback, cookies, event));
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SetCookieCallback(bool* result,
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       base::WaitableEvent* event,
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       bool success) {
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *result = success;
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  event->Signal();
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SetCookieOnIOThread(const GURL& url,
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         const std::string& value,
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         net::URLRequestContextGetter* context_getter,
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         base::WaitableEvent* event,
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         bool* result) {
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net::CookieStore* cookie_store =
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      context_getter->GetURLRequestContext()->cookie_store();
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cookie_store->SetCookieWithOptionsAsync(
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      url, value, net::CookieOptions(),
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&SetCookieCallback, result, event));
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)GURL GetFileUrlWithQuery(const base::FilePath& path,
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         const std::string& query_string) {
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL url = net::FilePathToFileURL(path);
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!query_string.empty()) {
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GURL::Replacements replacements;
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    replacements.SetQueryStr(query_string);
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return url.ReplaceComponents(replacements);
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return url;
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WaitForLoadStop(WebContents* web_contents) {
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WindowedNotificationObserver load_stop_observer(
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTIFICATION_LOAD_STOP,
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Source<NavigationController>(&web_contents->GetController()));
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // In many cases, the load may have finished before we get here.  Only wait if
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the tab still has a pending navigation.
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!web_contents->IsLoading())
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  load_stop_observer.Wait();
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CrashTab(WebContents* web_contents) {
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RenderProcessHost* rph = web_contents->GetRenderProcessHost();
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WindowedNotificationObserver observer(
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTIFICATION_RENDERER_PROCESS_CLOSED,
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Source<RenderProcessHost>(rph));
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::KillProcess(rph->GetHandle(), 0, false);
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  observer.Wait();
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SimulateMouseClick(WebContents* web_contents,
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        int modifiers,
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        WebKit::WebMouseEvent::Button button) {
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int x = web_contents->GetView()->GetContainerSize().width() / 2;
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int y = web_contents->GetView()->GetContainerSize().height() / 2;
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SimulateMouseClickAt(web_contents, modifiers, button, gfx::Point(x, y));
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SimulateMouseClickAt(WebContents* web_contents,
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          int modifiers,
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          WebKit::WebMouseEvent::Button button,
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          const gfx::Point& point) {
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WebKit::WebMouseEvent mouse_event;
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mouse_event.type = WebKit::WebInputEvent::MouseDown;
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mouse_event.button = button;
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  mouse_event.x = point.x();
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  mouse_event.y = point.y();
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mouse_event.modifiers = modifiers;
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Mac needs globalX/globalY for events to plugins.
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Rect offset;
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  web_contents->GetView()->GetContainerBounds(&offset);
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  mouse_event.globalX = point.x() + offset.x();
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  mouse_event.globalY = point.y() + offset.y();
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mouse_event.clickCount = 1;
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  web_contents->GetRenderViewHost()->ForwardMouseEvent(mouse_event);
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mouse_event.type = WebKit::WebInputEvent::MouseUp;
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  web_contents->GetRenderViewHost()->ForwardMouseEvent(mouse_event);
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SimulateMouseEvent(WebContents* web_contents,
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        WebKit::WebInputEvent::Type type,
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        const gfx::Point& point) {
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WebKit::WebMouseEvent mouse_event;
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mouse_event.type = type;
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mouse_event.x = point.x();
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mouse_event.y = point.y();
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  web_contents->GetRenderViewHost()->ForwardMouseEvent(mouse_event);
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SimulateKeyPress(WebContents* web_contents,
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      ui::KeyboardCode key,
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      bool control,
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      bool shift,
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      bool alt,
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      bool command) {
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NativeWebKeyboardEvent event_down;
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BuildSimpleWebKeyEvent(
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      WebKit::WebInputEvent::RawKeyDown, key, control, shift, alt, command,
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &event_down);
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  web_contents->GetRenderViewHost()->ForwardKeyboardEvent(event_down);
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NativeWebKeyboardEvent char_event;
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BuildSimpleWebKeyEvent(
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      WebKit::WebInputEvent::Char, key, control, shift, alt, command,
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &char_event);
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  web_contents->GetRenderViewHost()->ForwardKeyboardEvent(char_event);
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NativeWebKeyboardEvent event_up;
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BuildSimpleWebKeyEvent(
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      WebKit::WebInputEvent::KeyUp, key, control, shift, alt, command,
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &event_up);
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  web_contents->GetRenderViewHost()->ForwardKeyboardEvent(event_up);
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace internal {
2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ToRenderViewHost::ToRenderViewHost(WebContents* web_contents)
2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : render_view_host_(web_contents->GetRenderViewHost()) {
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ToRenderViewHost::ToRenderViewHost(RenderViewHost* render_view_host)
2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : render_view_host_(render_view_host) {
2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace internal
3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool ExecuteScriptInFrame(const internal::ToRenderViewHost& adapter,
3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          const std::string& frame_xpath,
3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          const std::string& original_script) {
3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string script =
3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      original_script + ";window.domAutomationController.send(0);";
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return ExecuteScriptHelper(adapter.render_view_host(), frame_xpath, script,
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             NULL);
3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool ExecuteScriptInFrameAndExtractInt(
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const internal::ToRenderViewHost& adapter,
3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& frame_xpath,
3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& script,
3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int* result) {
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(result);
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<Value> value;
3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!ExecuteScriptHelper(adapter.render_view_host(), frame_xpath, script,
3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           &value) || !value.get())
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return value->GetAsInteger(result);
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool ExecuteScriptInFrameAndExtractBool(
3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const internal::ToRenderViewHost& adapter,
3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& frame_xpath,
3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& script,
3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool* result) {
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(result);
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<Value> value;
3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!ExecuteScriptHelper(adapter.render_view_host(), frame_xpath, script,
3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           &value) || !value.get())
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return value->GetAsBoolean(result);
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool ExecuteScriptInFrameAndExtractString(
3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const internal::ToRenderViewHost& adapter,
3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& frame_xpath,
3422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& script,
3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::string* result) {
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(result);
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<Value> value;
3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!ExecuteScriptHelper(adapter.render_view_host(), frame_xpath, script,
3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           &value) || !value.get())
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return value->GetAsString(result);
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool ExecuteScript(const internal::ToRenderViewHost& adapter,
3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   const std::string& script) {
3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return ExecuteScriptInFrame(adapter, std::string(), script);
3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool ExecuteScriptAndExtractInt(const internal::ToRenderViewHost& adapter,
3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                const std::string& script, int* result) {
3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return ExecuteScriptInFrameAndExtractInt(adapter, std::string(), script,
3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                           result);
3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool ExecuteScriptAndExtractBool(const internal::ToRenderViewHost& adapter,
3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 const std::string& script, bool* result) {
3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return ExecuteScriptInFrameAndExtractBool(adapter, std::string(), script,
3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                            result);
3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool ExecuteScriptAndExtractString(const internal::ToRenderViewHost& adapter,
3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                   const std::string& script,
3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                   std::string* result) {
3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return ExecuteScriptInFrameAndExtractString(adapter, std::string(), script,
3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                              result);
3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string GetCookies(BrowserContext* browser_context, const GURL& url) {
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string cookies;
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::WaitableEvent event(true, false);
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net::URLRequestContextGetter* context_getter =
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      browser_context->GetRequestContext();
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserThread::PostTask(
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      BrowserThread::IO, FROM_HERE,
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&GetCookiesOnIOThread, url,
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 make_scoped_refptr(context_getter), &event, &cookies));
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  event.Wait();
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return cookies;
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SetCookie(BrowserContext* browser_context,
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               const GURL& url,
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               const std::string& value) {
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool result = false;
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::WaitableEvent event(true, false);
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net::URLRequestContextGetter* context_getter =
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      browser_context->GetRequestContext();
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserThread::PostTask(
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      BrowserThread::IO, FROM_HERE,
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&SetCookieOnIOThread, url, value,
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 make_scoped_refptr(context_getter), &event, &result));
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  event.Wait();
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TitleWatcher::TitleWatcher(WebContents* web_contents,
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           const string16& expected_title)
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : web_contents_(web_contents),
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      expected_title_observed_(false),
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      quit_loop_on_observation_(false) {
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(web_contents != NULL);
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected_titles_.push_back(expected_title);
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  notification_registrar_.Add(this,
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              NOTIFICATION_WEB_CONTENTS_TITLE_UPDATED,
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              Source<WebContents>(web_contents));
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // When navigating through the history, the restored NavigationEntry's title
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // will be used. If the entry ends up having the same title after we return
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to it, as will usually be the case, the
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // NOTIFICATION_WEB_CONTENTS_TITLE_UPDATED will then be suppressed, since the
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // NavigationEntry's title hasn't changed.
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  notification_registrar_.Add(
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      this,
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTIFICATION_LOAD_STOP,
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Source<NavigationController>(&web_contents->GetController()));
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TitleWatcher::AlsoWaitForTitle(const string16& expected_title) {
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected_titles_.push_back(expected_title);
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TitleWatcher::~TitleWatcher() {
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const string16& TitleWatcher::WaitAndGetTitle() {
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (expected_title_observed_)
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return observed_title_;
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  quit_loop_on_observation_ = true;
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  message_loop_runner_ = new MessageLoopRunner;
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  message_loop_runner_->Run();
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return observed_title_;
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TitleWatcher::Observe(int type,
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           const NotificationSource& source,
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           const NotificationDetails& details) {
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (type == NOTIFICATION_WEB_CONTENTS_TITLE_UPDATED) {
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WebContents* source_contents = Source<WebContents>(source).ptr();
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(web_contents_, source_contents);
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (type == NOTIFICATION_LOAD_STOP) {
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NavigationController* controller =
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Source<NavigationController>(source).ptr();
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(&web_contents_->GetController(), controller);
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FAIL() << "Unexpected notification received.";
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<string16>::const_iterator it =
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::find(expected_titles_.begin(),
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                expected_titles_.end(),
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                web_contents_->GetTitle());
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (it == expected_titles_.end())
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  observed_title_ = *it;
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected_title_observed_ = true;
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (quit_loop_on_observation_) {
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Only call Quit once, on first Observe:
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    quit_loop_on_observation_ = false;
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    message_loop_runner_->Quit();
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DOMMessageQueue::DOMMessageQueue() : waiting_for_message_(false) {
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  registrar_.Add(this, NOTIFICATION_DOM_OPERATION_RESPONSE,
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 NotificationService::AllSources());
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DOMMessageQueue::~DOMMessageQueue() {}
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DOMMessageQueue::Observe(int type,
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              const NotificationSource& source,
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              const NotificationDetails& details) {
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Details<DomOperationNotificationDetails> dom_op_details(details);
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Source<RenderViewHost> sender(source);
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  message_queue_.push(dom_op_details->json);
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (waiting_for_message_) {
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    waiting_for_message_ = false;
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    message_loop_runner_->Quit();
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DOMMessageQueue::ClearQueue() {
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  message_queue_ = std::queue<std::string>();
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool DOMMessageQueue::WaitForMessage(std::string* message) {
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (message_queue_.empty()) {
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    waiting_for_message_ = true;
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // This will be quit when a new message comes in.
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    message_loop_runner_ = new MessageLoopRunner;
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    message_loop_runner_->Run();
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The queue should not be empty, unless we were quit because of a timeout.
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (message_queue_.empty())
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (message)
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *message = message_queue_.front();
509eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  message_queue_.pop();
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace content
514