browser_test_utils.cc revision f2477e01787aa58f445919b809d89e252beef54f
1f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// Use of this source code is governed by a BSD-style license that can be
3f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// found in the LICENSE file.
4f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
5f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "content/public/test/browser_test_utils.h"
6f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
7f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "base/command_line.h"
8f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "base/json/json_reader.h"
9f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "base/path_service.h"
10f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "base/process/kill.h"
11f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "base/rand_util.h"
12f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "base/strings/string_number_conversions.h"
13f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "base/strings/utf_string_conversions.h"
14f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "base/synchronization/waitable_event.h"
15f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "base/test/test_timeouts.h"
16f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "base/values.h"
17f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "content/public/browser/browser_context.h"
18f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "content/public/browser/dom_operation_notification_details.h"
19f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "content/public/browser/notification_service.h"
20f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "content/public/browser/notification_types.h"
21f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "content/public/browser/render_process_host.h"
22f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "content/public/browser/render_view_host.h"
23f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "content/public/browser/web_contents.h"
24f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "content/public/browser/web_contents_observer.h"
25f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "content/public/browser/web_contents_view.h"
26f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "content/public/test/test_utils.h"
27f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "grit/webui_resources.h"
28f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "net/base/net_util.h"
29f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "net/cookies/cookie_store.h"
30f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "net/test/python_utils.h"
31f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "net/url_request/url_request_context.h"
32f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "net/url_request/url_request_context_getter.h"
33f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "testing/gtest/include/gtest/gtest.h"
34f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "ui/base/resource/resource_bundle.h"
35f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "ui/events/keycodes/dom4/keycode_converter.h"
36f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
37f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgnamespace content {
38f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgnamespace {
39f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
40f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgclass DOMOperationObserver : public NotificationObserver,
41f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                             public WebContentsObserver {
42f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org public:
43f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  explicit DOMOperationObserver(RenderViewHost* rvh)
44f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      : WebContentsObserver(WebContents::FromRenderViewHost(rvh)),
45f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        did_respond_(false) {
46f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    registrar_.Add(this, NOTIFICATION_DOM_OPERATION_RESPONSE,
47f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                   Source<RenderViewHost>(rvh));
48f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    message_loop_runner_ = new MessageLoopRunner;
49f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  }
50f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
51f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  virtual void Observe(int type,
52f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                       const NotificationSource& source,
53f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                       const NotificationDetails& details) OVERRIDE {
54f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    DCHECK(type == NOTIFICATION_DOM_OPERATION_RESPONSE);
55f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    Details<DomOperationNotificationDetails> dom_op_details(details);
56f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    response_ = dom_op_details->json;
57f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    did_respond_ = true;
58f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    message_loop_runner_->Quit();
59f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  }
60f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
61f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  // Overridden from WebContentsObserver:
62f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  virtual void RenderProcessGone(base::TerminationStatus status) OVERRIDE {
63f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    message_loop_runner_->Quit();
64f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  }
65f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
66f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  bool WaitAndGetResponse(std::string* response) WARN_UNUSED_RESULT {
67f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    message_loop_runner_->Run();
68f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    *response = response_;
69f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    return did_respond_;
70f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  }
71f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
72f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org private:
73f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  NotificationRegistrar registrar_;
74f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  std::string response_;
75f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  bool did_respond_;
76f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  scoped_refptr<MessageLoopRunner> message_loop_runner_;
77f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
78f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  DISALLOW_COPY_AND_ASSIGN(DOMOperationObserver);
79f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org};
80f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
81f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// Specifying a prototype so that we can add the WARN_UNUSED_RESULT attribute.
82f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgbool ExecuteScriptHelper(RenderViewHost* render_view_host,
83f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                         const std::string& frame_xpath,
84f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                         const std::string& original_script,
85f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                         scoped_ptr<Value>* result) WARN_UNUSED_RESULT;
86f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
87f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// Executes the passed |original_script| in the frame pointed to by
88f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// |frame_xpath|.  If |result| is not NULL, stores the value that the evaluation
89f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// of the script in |result|.  Returns true on success.
90f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgbool ExecuteScriptHelper(RenderViewHost* render_view_host,
91f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                         const std::string& frame_xpath,
92f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                         const std::string& original_script,
93f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                         scoped_ptr<Value>* result) {
94f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  // TODO(jcampan): we should make the domAutomationController not require an
95f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  //                automation id.
96f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  std::string script =
97f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      "window.domAutomationController.setAutomationId(0);" + original_script;
98f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  DOMOperationObserver dom_op_observer(render_view_host);
99f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  render_view_host->ExecuteJavascriptInWebFrame(UTF8ToUTF16(frame_xpath),
100f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                                UTF8ToUTF16(script));
101f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  std::string json;
102f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  if (!dom_op_observer.WaitAndGetResponse(&json)) {
103f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    DLOG(ERROR) << "Cannot communicate with DOMOperationObserver.";
104f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    return false;
105f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  }
106f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
107f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  // Nothing more to do for callers that ignore the returned JS value.
108f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  if (!result)
109f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    return true;
110f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
111f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  base::JSONReader reader(base::JSON_ALLOW_TRAILING_COMMAS);
112f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  result->reset(reader.ReadToValue(json));
113f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  if (!result->get()) {
114f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    DLOG(ERROR) << reader.GetErrorMessage();
115f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    return false;
116f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  }
117f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
118f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  return true;
119f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
120f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
121f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid BuildSimpleWebKeyEvent(blink::WebInputEvent::Type type,
122f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                            ui::KeyboardCode key_code,
123f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                            int native_key_code,
124f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                            int modifiers,
125f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                            NativeWebKeyboardEvent* event) {
126f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  event->nativeKeyCode = native_key_code;
127f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  event->windowsKeyCode = key_code;
128f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  event->setKeyIdentifierFromWindowsKeyCode();
129f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  event->type = type;
130f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  event->modifiers = modifiers;
131f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  event->isSystemKey = false;
132f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  event->timeStampSeconds = base::Time::Now().ToDoubleT();
133f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  event->skip_in_browser = true;
134f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
135f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  if (type == blink::WebInputEvent::Char ||
136f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      type == blink::WebInputEvent::RawKeyDown) {
137f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    event->text[0] = key_code;
138f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    event->unmodifiedText[0] = key_code;
139f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  }
140f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
141f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
142f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid InjectRawKeyEvent(WebContents* web_contents,
143f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                       blink::WebInputEvent::Type type,
144f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                       ui::KeyboardCode key_code,
145f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                       int native_key_code,
146f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                       int modifiers) {
147f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  NativeWebKeyboardEvent event;
148f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  BuildSimpleWebKeyEvent(type, key_code, native_key_code, modifiers, &event);
149f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  web_contents->GetRenderViewHost()->ForwardKeyboardEvent(event);
150f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
151f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
152f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid GetCookiesCallback(std::string* cookies_out,
153f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                        base::WaitableEvent* event,
154f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                        const std::string& cookies) {
155f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  *cookies_out = cookies;
156f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  event->Signal();
157f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
158f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
159f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid GetCookiesOnIOThread(const GURL& url,
160f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                          net::URLRequestContextGetter* context_getter,
161f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                          base::WaitableEvent* event,
162f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                          std::string* cookies) {
163f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  net::CookieStore* cookie_store =
164f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      context_getter->GetURLRequestContext()->cookie_store();
165f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  cookie_store->GetCookiesWithOptionsAsync(
166f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      url, net::CookieOptions(),
167f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      base::Bind(&GetCookiesCallback, cookies, event));
168f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
169f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
170f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid SetCookieCallback(bool* result,
171f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                       base::WaitableEvent* event,
172f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                       bool success) {
173f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  *result = success;
174f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  event->Signal();
175f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
176f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
177f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid SetCookieOnIOThread(const GURL& url,
178f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                         const std::string& value,
179f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                         net::URLRequestContextGetter* context_getter,
180f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                         base::WaitableEvent* event,
181f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                         bool* result) {
182f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  net::CookieStore* cookie_store =
183f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      context_getter->GetURLRequestContext()->cookie_store();
184f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  cookie_store->SetCookieWithOptionsAsync(
185f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      url, value, net::CookieOptions(),
186f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      base::Bind(&SetCookieCallback, result, event));
187f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
188f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
189f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}  // namespace
190f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
191f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
192f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgGURL GetFileUrlWithQuery(const base::FilePath& path,
193f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                         const std::string& query_string) {
194f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  GURL url = net::FilePathToFileURL(path);
195f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  if (!query_string.empty()) {
196f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    GURL::Replacements replacements;
197f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    replacements.SetQueryStr(query_string);
198f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    return url.ReplaceComponents(replacements);
199f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  }
200f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  return url;
201f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
202f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
203f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid WaitForLoadStop(WebContents* web_contents) {
204f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    WindowedNotificationObserver load_stop_observer(
205f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    NOTIFICATION_LOAD_STOP,
206f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    Source<NavigationController>(&web_contents->GetController()));
207f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  // In many cases, the load may have finished before we get here.  Only wait if
208f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  // the tab still has a pending navigation.
209f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  if (!web_contents->IsLoading())
210f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    return;
211f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  load_stop_observer.Wait();
212f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
213f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
214f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid CrashTab(WebContents* web_contents) {
215f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  RenderProcessHost* rph = web_contents->GetRenderProcessHost();
216f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  WindowedNotificationObserver observer(
217f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      NOTIFICATION_RENDERER_PROCESS_CLOSED,
218f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      Source<RenderProcessHost>(rph));
219f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  base::KillProcess(rph->GetHandle(), 0, false);
220f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  observer.Wait();
221f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
222f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
223f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid SimulateMouseClick(WebContents* web_contents,
224f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                        int modifiers,
225f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                        blink::WebMouseEvent::Button button) {
226f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  int x = web_contents->GetView()->GetContainerSize().width() / 2;
227f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  int y = web_contents->GetView()->GetContainerSize().height() / 2;
228f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  SimulateMouseClickAt(web_contents, modifiers, button, gfx::Point(x, y));
229f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
230f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
231f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid SimulateMouseClickAt(WebContents* web_contents,
232f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                          int modifiers,
233f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                          blink::WebMouseEvent::Button button,
234f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                          const gfx::Point& point) {
235f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  blink::WebMouseEvent mouse_event;
236f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  mouse_event.type = blink::WebInputEvent::MouseDown;
237f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  mouse_event.button = button;
238f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  mouse_event.x = point.x();
239f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  mouse_event.y = point.y();
240f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  mouse_event.modifiers = modifiers;
241f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  // Mac needs globalX/globalY for events to plugins.
242f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  gfx::Rect offset;
243f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  web_contents->GetView()->GetContainerBounds(&offset);
244f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  mouse_event.globalX = point.x() + offset.x();
245f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  mouse_event.globalY = point.y() + offset.y();
246f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  mouse_event.clickCount = 1;
247f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  web_contents->GetRenderViewHost()->ForwardMouseEvent(mouse_event);
248f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  mouse_event.type = blink::WebInputEvent::MouseUp;
249f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  web_contents->GetRenderViewHost()->ForwardMouseEvent(mouse_event);
250f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
251f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
252f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid SimulateMouseEvent(WebContents* web_contents,
253f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                        blink::WebInputEvent::Type type,
254f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                        const gfx::Point& point) {
255f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  blink::WebMouseEvent mouse_event;
256f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  mouse_event.type = type;
257f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  mouse_event.x = point.x();
258f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  mouse_event.y = point.y();
259f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  web_contents->GetRenderViewHost()->ForwardMouseEvent(mouse_event);
260f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
261f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
262f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid SimulateKeyPress(WebContents* web_contents,
263f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                      ui::KeyboardCode key_code,
264f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                      bool control,
265f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                      bool shift,
266f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                      bool alt,
267f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                      bool command) {
268f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  SimulateKeyPressWithCode(
269f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      web_contents, key_code, NULL, control, shift, alt, command);
270f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
271f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
272f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid SimulateKeyPressWithCode(WebContents* web_contents,
273f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                              ui::KeyboardCode key_code,
274f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                              const char* code,
275f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                              bool control,
276f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                              bool shift,
277f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                              bool alt,
278f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                              bool command) {
279f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  ui::KeycodeConverter* key_converter = ui::KeycodeConverter::GetInstance();
280f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  int native_key_code = key_converter->CodeToNativeKeycode(code);
281f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
282f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  int modifiers = 0;
283f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
284f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  // The order of these key down events shouldn't matter for our simulation.
285f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  // For our simulation we can use either the left keys or the right keys.
286f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  if (control) {
287f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    modifiers |= blink::WebInputEvent::ControlKey;
288f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    InjectRawKeyEvent(
289f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        web_contents,
290f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        blink::WebInputEvent::RawKeyDown,
291f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        ui::VKEY_CONTROL,
292f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        key_converter->CodeToNativeKeycode("ControlLeft"),
293f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        modifiers);
294f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  }
295f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
296f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  if (shift) {
297f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    modifiers |= blink::WebInputEvent::ShiftKey;
298f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    InjectRawKeyEvent(
299f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        web_contents,
300f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        blink::WebInputEvent::RawKeyDown,
301f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        ui::VKEY_SHIFT,
302f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        key_converter->CodeToNativeKeycode("ShiftLeft"),
303f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        modifiers);
304f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  }
305f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
306f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  if (alt) {
307f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    modifiers |= blink::WebInputEvent::AltKey;
308f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    InjectRawKeyEvent(
309f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        web_contents,
310f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        blink::WebInputEvent::RawKeyDown,
311f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        ui::VKEY_MENU,
312f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        key_converter->CodeToNativeKeycode("AltLeft"),
313f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        modifiers);
314f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  }
315f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
316f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  if (command) {
317f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    modifiers |= blink::WebInputEvent::MetaKey;
318f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    InjectRawKeyEvent(
319f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        web_contents,
320f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        blink::WebInputEvent::RawKeyDown,
321f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        ui::VKEY_COMMAND,
322f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        key_converter->CodeToNativeKeycode("OSLeft"),
323f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        modifiers);
324f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  }
325f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
326f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  InjectRawKeyEvent(
327f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      web_contents,
328f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      blink::WebInputEvent::RawKeyDown,
329f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      key_code,
330f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      native_key_code,
331f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      modifiers);
332f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
333f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  InjectRawKeyEvent(
334f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      web_contents,
335f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      blink::WebInputEvent::Char,
336f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      key_code,
337f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      native_key_code,
338f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      modifiers);
339f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
340f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  InjectRawKeyEvent(
341f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      web_contents,
342f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      blink::WebInputEvent::KeyUp,
343f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      key_code,
344f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      native_key_code,
345f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      modifiers);
346f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
347f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  // The order of these key releases shouldn't matter for our simulation.
348f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  if (control) {
349f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    modifiers &= ~blink::WebInputEvent::ControlKey;
350f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    InjectRawKeyEvent(
351f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        web_contents,
352f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        blink::WebInputEvent::KeyUp,
353f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        ui::VKEY_CONTROL,
354f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        key_converter->CodeToNativeKeycode("ControlLeft"),
355f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        modifiers);
356f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  }
357f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
358f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  if (shift) {
359f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    modifiers &= ~blink::WebInputEvent::ShiftKey;
360f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    InjectRawKeyEvent(
361f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        web_contents,
362f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        blink::WebInputEvent::KeyUp,
363f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        ui::VKEY_SHIFT,
364f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        key_converter->CodeToNativeKeycode("ShiftLeft"),
365f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        modifiers);
366f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  }
367f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
368f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  if (alt) {
369f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    modifiers &= ~blink::WebInputEvent::AltKey;
370f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    InjectRawKeyEvent(
371f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        web_contents,
372f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        blink::WebInputEvent::KeyUp,
373f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        ui::VKEY_MENU,
374f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        key_converter->CodeToNativeKeycode("AltLeft"),
375f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        modifiers);
376f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  }
377f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
378f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  if (command) {
379f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    modifiers &= ~blink::WebInputEvent::MetaKey;
380f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    InjectRawKeyEvent(
381f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        web_contents,
382f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        blink::WebInputEvent::KeyUp,
383f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        ui::VKEY_COMMAND,
384f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        key_converter->CodeToNativeKeycode("OSLeft"),
385f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        modifiers);
386f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  }
387f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
388f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  ASSERT_EQ(modifiers, 0);
389f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
390f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
391f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgnamespace internal {
392f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
393f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgToRenderViewHost::ToRenderViewHost(WebContents* web_contents)
394f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    : render_view_host_(web_contents->GetRenderViewHost()) {
395f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
396f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
397f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgToRenderViewHost::ToRenderViewHost(RenderViewHost* render_view_host)
398f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    : render_view_host_(render_view_host) {
399f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
400f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
401f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}  // namespace internal
402f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
403f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgbool ExecuteScriptInFrame(const internal::ToRenderViewHost& adapter,
404f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                          const std::string& frame_xpath,
405f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                          const std::string& original_script) {
406f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  std::string script =
407f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      original_script + ";window.domAutomationController.send(0);";
408f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  return ExecuteScriptHelper(adapter.render_view_host(), frame_xpath, script,
409f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                             NULL);
410f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
411f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
412f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgbool ExecuteScriptInFrameAndExtractInt(
413f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    const internal::ToRenderViewHost& adapter,
414f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    const std::string& frame_xpath,
415f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    const std::string& script,
416f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    int* result) {
417f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  DCHECK(result);
418f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  scoped_ptr<Value> value;
419f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  if (!ExecuteScriptHelper(adapter.render_view_host(), frame_xpath, script,
420f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                           &value) || !value.get())
421f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    return false;
422f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
423f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  return value->GetAsInteger(result);
424f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
425f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
426f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgbool ExecuteScriptInFrameAndExtractBool(
427f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    const internal::ToRenderViewHost& adapter,
428f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    const std::string& frame_xpath,
429f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    const std::string& script,
430f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    bool* result) {
431f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  DCHECK(result);
432f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  scoped_ptr<Value> value;
433f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  if (!ExecuteScriptHelper(adapter.render_view_host(), frame_xpath, script,
434f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                           &value) || !value.get())
435f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    return false;
436f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
437f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  return value->GetAsBoolean(result);
438f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
439f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
440f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgbool ExecuteScriptInFrameAndExtractString(
441f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    const internal::ToRenderViewHost& adapter,
442f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    const std::string& frame_xpath,
443f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    const std::string& script,
444f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    std::string* result) {
445f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  DCHECK(result);
446f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  scoped_ptr<Value> value;
447f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  if (!ExecuteScriptHelper(adapter.render_view_host(), frame_xpath, script,
448f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                           &value) || !value.get())
449f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    return false;
450f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
451f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  return value->GetAsString(result);
452f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
453f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
454f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgbool ExecuteScript(const internal::ToRenderViewHost& adapter,
455f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                   const std::string& script) {
456f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  return ExecuteScriptInFrame(adapter, std::string(), script);
457f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
458f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
459f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgbool ExecuteScriptAndExtractInt(const internal::ToRenderViewHost& adapter,
460f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                const std::string& script, int* result) {
461f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  return ExecuteScriptInFrameAndExtractInt(adapter, std::string(), script,
462f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                           result);
463f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
464f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
465f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgbool ExecuteScriptAndExtractBool(const internal::ToRenderViewHost& adapter,
466f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                 const std::string& script, bool* result) {
467f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  return ExecuteScriptInFrameAndExtractBool(adapter, std::string(), script,
468f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                            result);
469f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
470f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
471f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgbool ExecuteScriptAndExtractString(const internal::ToRenderViewHost& adapter,
472f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                   const std::string& script,
473f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                   std::string* result) {
474f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  return ExecuteScriptInFrameAndExtractString(adapter, std::string(), script,
475f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                              result);
476f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
477f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
478f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgbool ExecuteWebUIResourceTest(
479f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    const internal::ToRenderViewHost& adapter,
480f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    const std::vector<int>& js_resource_ids) {
481f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  // Inject WebUI test runner script first prior to other scripts required to
482f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  // run the test as scripts may depend on it being declared.
483f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  std::vector<int> ids;
484f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  ids.push_back(IDR_WEBUI_JS_WEBUI_RESOURCE_TEST);
485f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  ids.insert(ids.end(), js_resource_ids.begin(), js_resource_ids.end());
486f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
487f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  std::string script;
488f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  for (std::vector<int>::iterator iter = ids.begin();
489f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       iter != ids.end();
490f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       ++iter) {
491f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    ResourceBundle::GetSharedInstance().GetRawDataResource(*iter)
492f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        .AppendToString(&script);
493f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    script.append("\n");
494f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  }
495f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  if (!content::ExecuteScript(adapter, script))
496f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    return false;
497f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
498f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  content::DOMMessageQueue message_queue;
499f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  if (!content::ExecuteScript(adapter, "runTests()"))
500f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    return false;
501f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
502f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  std::string message;
503f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  do {
504f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    if (!message_queue.WaitForMessage(&message))
505f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return false;
506f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  } while (message.compare("\"PENDING\"") == 0);
507f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
508f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  return message.compare("\"SUCCESS\"") == 0;
509f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
510f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
511f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstd::string GetCookies(BrowserContext* browser_context, const GURL& url) {
512f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  std::string cookies;
513f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  base::WaitableEvent event(true, false);
514f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  net::URLRequestContextGetter* context_getter =
515f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      browser_context->GetRequestContext();
516f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
517f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  BrowserThread::PostTask(
518f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      BrowserThread::IO, FROM_HERE,
519f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      base::Bind(&GetCookiesOnIOThread, url,
520f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                 make_scoped_refptr(context_getter), &event, &cookies));
521f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  event.Wait();
522f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  return cookies;
523f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
524f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
525f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgbool SetCookie(BrowserContext* browser_context,
526f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org               const GURL& url,
527f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org               const std::string& value) {
528f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  bool result = false;
529f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  base::WaitableEvent event(true, false);
530f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  net::URLRequestContextGetter* context_getter =
531f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      browser_context->GetRequestContext();
532f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
533f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  BrowserThread::PostTask(
534f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      BrowserThread::IO, FROM_HERE,
535f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      base::Bind(&SetCookieOnIOThread, url, value,
536f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                 make_scoped_refptr(context_getter), &event, &result));
537f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  event.Wait();
538f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  return result;
539f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
540f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
541f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgTitleWatcher::TitleWatcher(WebContents* web_contents,
542f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                           const string16& expected_title)
543f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    : WebContentsObserver(web_contents),
544f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      message_loop_runner_(new MessageLoopRunner) {
545f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  EXPECT_TRUE(web_contents != NULL);
546f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  expected_titles_.push_back(expected_title);
547f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
548f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
549f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid TitleWatcher::AlsoWaitForTitle(const string16& expected_title) {
550f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  expected_titles_.push_back(expected_title);
551f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
552f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
553f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgTitleWatcher::~TitleWatcher() {
554f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
555f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
556f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgconst string16& TitleWatcher::WaitAndGetTitle() {
557f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  message_loop_runner_->Run();
558f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  return observed_title_;
559f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
560f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
561f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid TitleWatcher::DidStopLoading(RenderViewHost* render_view_host) {
562f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  // When navigating through the history, the restored NavigationEntry's title
563f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  // will be used. If the entry ends up having the same title after we return
564f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  // to it, as will usually be the case, then WebContentsObserver::TitleSet
565f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  // will then be suppressed, since the NavigationEntry's title hasn't changed.
566f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  TestTitle();
567f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
568
569void TitleWatcher::TitleWasSet(NavigationEntry* entry, bool explicit_set) {
570  TestTitle();
571}
572
573void TitleWatcher::TestTitle() {
574  std::vector<string16>::const_iterator it =
575      std::find(expected_titles_.begin(),
576                expected_titles_.end(),
577                web_contents()->GetTitle());
578  if (it == expected_titles_.end())
579    return;
580
581  observed_title_ = *it;
582  message_loop_runner_->Quit();
583}
584
585WebContentsDestroyedWatcher::WebContentsDestroyedWatcher(
586    WebContents* web_contents)
587    : WebContentsObserver(web_contents),
588      message_loop_runner_(new MessageLoopRunner) {
589  EXPECT_TRUE(web_contents != NULL);
590}
591
592WebContentsDestroyedWatcher::~WebContentsDestroyedWatcher() {
593}
594
595void WebContentsDestroyedWatcher::Wait() {
596  message_loop_runner_->Run();
597}
598
599void WebContentsDestroyedWatcher::WebContentsDestroyed(
600    WebContents* web_contents) {
601  message_loop_runner_->Quit();
602}
603
604DOMMessageQueue::DOMMessageQueue() : waiting_for_message_(false) {
605  registrar_.Add(this, NOTIFICATION_DOM_OPERATION_RESPONSE,
606                 NotificationService::AllSources());
607}
608
609DOMMessageQueue::~DOMMessageQueue() {}
610
611void DOMMessageQueue::Observe(int type,
612                              const NotificationSource& source,
613                              const NotificationDetails& details) {
614  Details<DomOperationNotificationDetails> dom_op_details(details);
615  Source<RenderViewHost> sender(source);
616  message_queue_.push(dom_op_details->json);
617  if (waiting_for_message_) {
618    waiting_for_message_ = false;
619    message_loop_runner_->Quit();
620  }
621}
622
623void DOMMessageQueue::ClearQueue() {
624  message_queue_ = std::queue<std::string>();
625}
626
627bool DOMMessageQueue::WaitForMessage(std::string* message) {
628  if (message_queue_.empty()) {
629    waiting_for_message_ = true;
630    // This will be quit when a new message comes in.
631    message_loop_runner_ = new MessageLoopRunner;
632    message_loop_runner_->Run();
633  }
634  // The queue should not be empty, unless we were quit because of a timeout.
635  if (message_queue_.empty())
636    return false;
637  if (message)
638    *message = message_queue_.front();
639  message_queue_.pop();
640  return true;
641}
642
643}  // namespace content
644