Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / content / public / test / browser_test_utils.cc
index db9be5b..88119c1 100644 (file)
@@ -4,9 +4,9 @@
 
 #include "content/public/test/browser_test_utils.h"
 
+#include "base/bind.h"
 #include "base/command_line.h"
 #include "base/json/json_reader.h"
-#include "base/path_service.h"
 #include "base/process/kill.h"
 #include "base/rand_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/synchronization/waitable_event.h"
 #include "base/test/test_timeouts.h"
 #include "base/values.h"
+#include "content/browser/renderer_host/render_widget_host_impl.h"
+#include "content/browser/web_contents/web_contents_view.h"
+#include "content/common/input/synthetic_web_input_event_builders.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/dom_operation_notification_details.h"
+#include "content/public/browser/histogram_fetcher.h"
 #include "content/public/browser/notification_service.h"
 #include "content/public/browser/notification_types.h"
+#include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_contents_observer.h"
-#include "content/public/browser/web_contents_view.h"
 #include "content/public/test/test_utils.h"
-#include "grit/webui_resources.h"
-#include "net/base/net_util.h"
+#include "net/base/filename_util.h"
 #include "net/cookies/cookie_store.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
+#include "net/test/embedded_test_server/http_request.h"
+#include "net/test/embedded_test_server/http_response.h"
 #include "net/test/python_utils.h"
 #include "net/url_request/url_request_context.h"
 #include "net/url_request/url_request_context_getter.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/base/resource/resource_bundle.h"
+#include "ui/compositor/test/draw_waiter_for_test.h"
+#include "ui/events/gesture_detection/gesture_configuration.h"
 #include "ui/events/keycodes/dom4/keycode_converter.h"
+#include "ui/resources/grit/webui_resources.h"
+
+#if defined(USE_AURA)
+#include "ui/aura/test/window_event_dispatcher_test_api.h"
+#include "ui/aura/window.h"
+#include "ui/aura/window_event_dispatcher.h"
+#include "ui/aura/window_tree_host.h"
+#endif  // USE_AURA
 
 namespace content {
 namespace {
@@ -44,13 +60,13 @@ class DOMOperationObserver : public NotificationObserver,
       : WebContentsObserver(WebContents::FromRenderViewHost(rvh)),
         did_respond_(false) {
     registrar_.Add(this, NOTIFICATION_DOM_OPERATION_RESPONSE,
-                   Source<RenderViewHost>(rvh));
+                   Source<WebContents>(web_contents()));
     message_loop_runner_ = new MessageLoopRunner;
   }
 
-  virtual void Observe(int type,
-                       const NotificationSource& source,
-                       const NotificationDetails& details) OVERRIDE {
+  void Observe(int type,
+               const NotificationSource& source,
+               const NotificationDetails& details) override {
     DCHECK(type == NOTIFICATION_DOM_OPERATION_RESPONSE);
     Details<DomOperationNotificationDetails> dom_op_details(details);
     response_ = dom_op_details->json;
@@ -59,7 +75,7 @@ class DOMOperationObserver : public NotificationObserver,
   }
 
   // Overridden from WebContentsObserver:
-  virtual void RenderProcessGone(base::TerminationStatus status) OVERRIDE {
+  void RenderProcessGone(base::TerminationStatus status) override {
     message_loop_runner_->Quit();
   }
 
@@ -78,26 +94,46 @@ class DOMOperationObserver : public NotificationObserver,
   DISALLOW_COPY_AND_ASSIGN(DOMOperationObserver);
 };
 
-// Specifying a prototype so that we can add the WARN_UNUSED_RESULT attribute.
-bool ExecuteScriptHelper(RenderViewHost* render_view_host,
-                         const std::string& frame_xpath,
-                         const std::string& original_script,
-                         scoped_ptr<base::Value>* result) WARN_UNUSED_RESULT;
+class InterstitialObserver : public content::WebContentsObserver {
+ public:
+  InterstitialObserver(content::WebContents* web_contents,
+                       const base::Closure& attach_callback,
+                       const base::Closure& detach_callback)
+      : WebContentsObserver(web_contents),
+        attach_callback_(attach_callback),
+        detach_callback_(detach_callback) {
+  }
+  ~InterstitialObserver() override {}
 
-// Executes the passed |original_script| in the frame pointed to by
-// |frame_xpath|.  If |result| is not NULL, stores the value that the evaluation
-// of the script in |result|.  Returns true on success.
-bool ExecuteScriptHelper(RenderViewHost* render_view_host,
-                         const std::string& frame_xpath,
+  // WebContentsObserver methods:
+  void DidAttachInterstitialPage() override { attach_callback_.Run(); }
+  void DidDetachInterstitialPage() override { detach_callback_.Run(); }
+
+ private:
+  base::Closure attach_callback_;
+  base::Closure detach_callback_;
+
+  DISALLOW_COPY_AND_ASSIGN(InterstitialObserver);
+};
+
+// Specifying a prototype so that we can add the WARN_UNUSED_RESULT attribute.
+bool ExecuteScriptHelper(
+    RenderFrameHost* render_frame_host,
+    const std::string& original_script,
+    scoped_ptr<base::Value>* result) WARN_UNUSED_RESULT;
+
+// Executes the passed |original_script| in the frame specified by
+// |render_frame_host|.  If |result| is not NULL, stores the value that the
+// evaluation of the script in |result|.  Returns true on success.
+bool ExecuteScriptHelper(RenderFrameHost* render_frame_host,
                          const std::string& original_script,
                          scoped_ptr<base::Value>* result) {
   // TODO(jcampan): we should make the domAutomationController not require an
   //                automation id.
   std::string script =
       "window.domAutomationController.setAutomationId(0);" + original_script;
-  DOMOperationObserver dom_op_observer(render_view_host);
-  render_view_host->ExecuteJavascriptInWebFrame(base::UTF8ToUTF16(frame_xpath),
-                                                base::UTF8ToUTF16(script));
+  DOMOperationObserver dom_op_observer(render_frame_host->GetRenderViewHost());
+  render_frame_host->ExecuteJavaScriptForTests(base::UTF8ToUTF16(script));
   std::string json;
   if (!dom_op_observer.WaitAndGetResponse(&json)) {
     DLOG(ERROR) << "Cannot communicate with DOMOperationObserver.";
@@ -186,6 +222,39 @@ void SetCookieOnIOThread(const GURL& url,
       base::Bind(&SetCookieCallback, result, event));
 }
 
+scoped_ptr<net::test_server::HttpResponse> CrossSiteRedirectResponseHandler(
+    const GURL& server_base_url,
+    const net::test_server::HttpRequest& request) {
+  std::string prefix("/cross-site/");
+  if (!StartsWithASCII(request.relative_url, prefix, true))
+    return scoped_ptr<net::test_server::HttpResponse>();
+
+  std::string params = request.relative_url.substr(prefix.length());
+
+  // A hostname to redirect to must be included in the URL, therefore at least
+  // one '/' character is expected.
+  size_t slash = params.find('/');
+  if (slash == std::string::npos)
+    return scoped_ptr<net::test_server::HttpResponse>();
+
+  // Replace the host of the URL with the one passed in the URL.
+  std::string host = params.substr(0, slash);
+  GURL::Replacements replace_host;
+  replace_host.SetHostStr(host);
+  GURL redirect_server = server_base_url.ReplaceComponents(replace_host);
+
+  // Append the real part of the path to the new URL.
+  std::string path = params.substr(slash + 1);
+  GURL redirect_target(redirect_server.Resolve(path));
+  DCHECK(redirect_target.is_valid());
+
+  scoped_ptr<net::test_server::BasicHttpResponse> http_response(
+      new net::test_server::BasicHttpResponse);
+  http_response->set_code(net::HTTP_MOVED_PERMANENTLY);
+  http_response->AddCustomHeader("Location", redirect_target.spec());
+  return http_response.Pass();
+}
+
 }  // namespace
 
 
@@ -201,14 +270,14 @@ GURL GetFileUrlWithQuery(const base::FilePath& path,
 }
 
 void WaitForLoadStop(WebContents* web_contents) {
-    WindowedNotificationObserver load_stop_observer(
-    NOTIFICATION_LOAD_STOP,
-    Source<NavigationController>(&web_contents->GetController()));
   // In many cases, the load may have finished before we get here.  Only wait if
   // the tab still has a pending navigation.
-  if (!web_contents->IsLoading())
-    return;
-  load_stop_observer.Wait();
+  if (web_contents->IsLoading()) {
+    WindowedNotificationObserver load_stop_observer(
+        NOTIFICATION_LOAD_STOP,
+        Source<NavigationController>(&web_contents->GetController()));
+    load_stop_observer.Wait();
+  }
 }
 
 void CrashTab(WebContents* web_contents) {
@@ -219,11 +288,37 @@ void CrashTab(WebContents* web_contents) {
   watcher.Wait();
 }
 
+#if defined(USE_AURA)
+bool IsResizeComplete(aura::test::WindowEventDispatcherTestApi* dispatcher_test,
+                      RenderWidgetHostImpl* widget_host) {
+  return !dispatcher_test->HoldingPointerMoves() &&
+      !widget_host->resize_ack_pending_for_testing();
+}
+
+void WaitForResizeComplete(WebContents* web_contents) {
+  aura::Window* content = web_contents->GetContentNativeView();
+  if (!content)
+    return;
+
+  aura::WindowTreeHost* window_host = content->GetHost();
+  aura::WindowEventDispatcher* dispatcher = window_host->dispatcher();
+  aura::test::WindowEventDispatcherTestApi dispatcher_test(dispatcher);
+  RenderWidgetHostImpl* widget_host =
+      RenderWidgetHostImpl::From(web_contents->GetRenderViewHost());
+  if (!IsResizeComplete(&dispatcher_test, widget_host)) {
+    WindowedNotificationObserver resize_observer(
+        NOTIFICATION_RENDER_WIDGET_HOST_DID_UPDATE_BACKING_STORE,
+        base::Bind(IsResizeComplete, &dispatcher_test, widget_host));
+    resize_observer.Wait();
+  }
+}
+#endif  // USE_AURA
+
 void SimulateMouseClick(WebContents* web_contents,
                         int modifiers,
                         blink::WebMouseEvent::Button button) {
-  int x = web_contents->GetView()->GetContainerSize().width() / 2;
-  int y = web_contents->GetView()->GetContainerSize().height() / 2;
+  int x = web_contents->GetContainerBounds().width() / 2;
+  int y = web_contents->GetContainerBounds().height() / 2;
   SimulateMouseClickAt(web_contents, modifiers, button, gfx::Point(x, y));
 }
 
@@ -238,8 +333,7 @@ void SimulateMouseClickAt(WebContents* web_contents,
   mouse_event.y = point.y();
   mouse_event.modifiers = modifiers;
   // Mac needs globalX/globalY for events to plugins.
-  gfx::Rect offset;
-  web_contents->GetView()->GetContainerBounds(&offset);
+  gfx::Rect offset = web_contents->GetContainerBounds();
   mouse_event.globalX = point.x() + offset.x();
   mouse_event.globalY = point.y() + offset.y();
   mouse_event.clickCount = 1;
@@ -258,6 +352,16 @@ void SimulateMouseEvent(WebContents* web_contents,
   web_contents->GetRenderViewHost()->ForwardMouseEvent(mouse_event);
 }
 
+void SimulateTapAt(WebContents* web_contents, const gfx::Point& point) {
+  blink::WebGestureEvent tap;
+  tap.type = blink::WebGestureEvent::GestureTap;
+  tap.x = point.x();
+  tap.y = point.y();
+  RenderWidgetHostImpl* widget_host =
+      RenderWidgetHostImpl::From(web_contents->GetRenderViewHost());
+  widget_host->ForwardGestureEvent(tap);
+}
+
 void SimulateKeyPress(WebContents* web_contents,
                       ui::KeyboardCode key_code,
                       bool control,
@@ -275,8 +379,7 @@ void SimulateKeyPressWithCode(WebContents* web_contents,
                               bool shift,
                               bool alt,
                               bool command) {
-  ui::KeycodeConverter* key_converter = ui::KeycodeConverter::GetInstance();
-  int native_key_code = key_converter->CodeToNativeKeycode(code);
+  int native_key_code = ui::KeycodeConverter::CodeToNativeKeycode(code);
 
   int modifiers = 0;
 
@@ -284,42 +387,38 @@ void SimulateKeyPressWithCode(WebContents* web_contents,
   // For our simulation we can use either the left keys or the right keys.
   if (control) {
     modifiers |= blink::WebInputEvent::ControlKey;
-    InjectRawKeyEvent(
-        web_contents,
-        blink::WebInputEvent::RawKeyDown,
-        ui::VKEY_CONTROL,
-        key_converter->CodeToNativeKeycode("ControlLeft"),
-        modifiers);
+    InjectRawKeyEvent(web_contents,
+                      blink::WebInputEvent::RawKeyDown,
+                      ui::VKEY_CONTROL,
+                      ui::KeycodeConverter::CodeToNativeKeycode("ControlLeft"),
+                      modifiers);
   }
 
   if (shift) {
     modifiers |= blink::WebInputEvent::ShiftKey;
-    InjectRawKeyEvent(
-        web_contents,
-        blink::WebInputEvent::RawKeyDown,
-        ui::VKEY_SHIFT,
-        key_converter->CodeToNativeKeycode("ShiftLeft"),
-        modifiers);
+    InjectRawKeyEvent(web_contents,
+                      blink::WebInputEvent::RawKeyDown,
+                      ui::VKEY_SHIFT,
+                      ui::KeycodeConverter::CodeToNativeKeycode("ShiftLeft"),
+                      modifiers);
   }
 
   if (alt) {
     modifiers |= blink::WebInputEvent::AltKey;
-    InjectRawKeyEvent(
-        web_contents,
-        blink::WebInputEvent::RawKeyDown,
-        ui::VKEY_MENU,
-        key_converter->CodeToNativeKeycode("AltLeft"),
-        modifiers);
+    InjectRawKeyEvent(web_contents,
+                      blink::WebInputEvent::RawKeyDown,
+                      ui::VKEY_MENU,
+                      ui::KeycodeConverter::CodeToNativeKeycode("AltLeft"),
+                      modifiers);
   }
 
   if (command) {
     modifiers |= blink::WebInputEvent::MetaKey;
-    InjectRawKeyEvent(
-        web_contents,
-        blink::WebInputEvent::RawKeyDown,
-        ui::VKEY_COMMAND,
-        key_converter->CodeToNativeKeycode("OSLeft"),
-        modifiers);
+    InjectRawKeyEvent(web_contents,
+                      blink::WebInputEvent::RawKeyDown,
+                      ui::VKEY_COMMAND,
+                      ui::KeycodeConverter::CodeToNativeKeycode("OSLeft"),
+                      modifiers);
   }
 
   InjectRawKeyEvent(
@@ -346,42 +445,38 @@ void SimulateKeyPressWithCode(WebContents* web_contents,
   // The order of these key releases shouldn't matter for our simulation.
   if (control) {
     modifiers &= ~blink::WebInputEvent::ControlKey;
-    InjectRawKeyEvent(
-        web_contents,
-        blink::WebInputEvent::KeyUp,
-        ui::VKEY_CONTROL,
-        key_converter->CodeToNativeKeycode("ControlLeft"),
-        modifiers);
+    InjectRawKeyEvent(web_contents,
+                      blink::WebInputEvent::KeyUp,
+                      ui::VKEY_CONTROL,
+                      ui::KeycodeConverter::CodeToNativeKeycode("ControlLeft"),
+                      modifiers);
   }
 
   if (shift) {
     modifiers &= ~blink::WebInputEvent::ShiftKey;
-    InjectRawKeyEvent(
-        web_contents,
-        blink::WebInputEvent::KeyUp,
-        ui::VKEY_SHIFT,
-        key_converter->CodeToNativeKeycode("ShiftLeft"),
-        modifiers);
+    InjectRawKeyEvent(web_contents,
+                      blink::WebInputEvent::KeyUp,
+                      ui::VKEY_SHIFT,
+                      ui::KeycodeConverter::CodeToNativeKeycode("ShiftLeft"),
+                      modifiers);
   }
 
   if (alt) {
     modifiers &= ~blink::WebInputEvent::AltKey;
-    InjectRawKeyEvent(
-        web_contents,
-        blink::WebInputEvent::KeyUp,
-        ui::VKEY_MENU,
-        key_converter->CodeToNativeKeycode("AltLeft"),
-        modifiers);
+    InjectRawKeyEvent(web_contents,
+                      blink::WebInputEvent::KeyUp,
+                      ui::VKEY_MENU,
+                      ui::KeycodeConverter::CodeToNativeKeycode("AltLeft"),
+                      modifiers);
   }
 
   if (command) {
     modifiers &= ~blink::WebInputEvent::MetaKey;
-    InjectRawKeyEvent(
-        web_contents,
-        blink::WebInputEvent::KeyUp,
-        ui::VKEY_COMMAND,
-        key_converter->CodeToNativeKeycode("OSLeft"),
-        modifiers);
+    InjectRawKeyEvent(web_contents,
+                      blink::WebInputEvent::KeyUp,
+                      ui::VKEY_COMMAND,
+                      ui::KeycodeConverter::CodeToNativeKeycode("OSLeft"),
+                      modifiers);
   }
 
   ASSERT_EQ(modifiers, 0);
@@ -389,94 +484,98 @@ void SimulateKeyPressWithCode(WebContents* web_contents,
 
 namespace internal {
 
-ToRenderViewHost::ToRenderViewHost(WebContents* web_contents)
-    : render_view_host_(web_contents->GetRenderViewHost()) {
+ToRenderFrameHost::ToRenderFrameHost(WebContents* web_contents)
+    : render_frame_host_(web_contents->GetMainFrame()) {
+}
+
+ToRenderFrameHost::ToRenderFrameHost(RenderViewHost* render_view_host)
+    : render_frame_host_(render_view_host->GetMainFrame()) {
 }
 
-ToRenderViewHost::ToRenderViewHost(RenderViewHost* render_view_host)
-    : render_view_host_(render_view_host) {
+ToRenderFrameHost::ToRenderFrameHost(RenderFrameHost* render_frame_host)
+    : render_frame_host_(render_frame_host) {
 }
 
 }  // namespace internal
 
-bool ExecuteScriptInFrame(const internal::ToRenderViewHost& adapter,
-                          const std::string& frame_xpath,
-                          const std::string& original_script) {
-  std::string script =
-      original_script + ";window.domAutomationController.send(0);";
-  return ExecuteScriptHelper(adapter.render_view_host(), frame_xpath, script,
-                             NULL);
+bool ExecuteScript(const internal::ToRenderFrameHost& adapter,
+                   const std::string& script) {
+  std::string new_script =
+      script + ";window.domAutomationController.send(0);";
+  return ExecuteScriptHelper(adapter.render_frame_host(), new_script, NULL);
 }
 
-bool ExecuteScriptInFrameAndExtractInt(
-    const internal::ToRenderViewHost& adapter,
-    const std::string& frame_xpath,
-    const std::string& script,
-    int* result) {
+bool ExecuteScriptAndExtractInt(const internal::ToRenderFrameHost& adapter,
+                                const std::string& script, int* result) {
   DCHECK(result);
   scoped_ptr<base::Value> value;
-  if (!ExecuteScriptHelper(adapter.render_view_host(), frame_xpath, script,
-                           &value) || !value.get())
+  if (!ExecuteScriptHelper(adapter.render_frame_host(), script, &value) ||
+      !value.get()) {
     return false;
+  }
 
   return value->GetAsInteger(result);
 }
 
-bool ExecuteScriptInFrameAndExtractBool(
-    const internal::ToRenderViewHost& adapter,
-    const std::string& frame_xpath,
-    const std::string& script,
-    bool* result) {
+bool ExecuteScriptAndExtractBool(const internal::ToRenderFrameHost& adapter,
+                                 const std::string& script, bool* result) {
   DCHECK(result);
   scoped_ptr<base::Value> value;
-  if (!ExecuteScriptHelper(adapter.render_view_host(), frame_xpath, script,
-                           &value) || !value.get())
+  if (!ExecuteScriptHelper(adapter.render_frame_host(), script, &value) ||
+      !value.get()) {
     return false;
+  }
 
   return value->GetAsBoolean(result);
 }
 
-bool ExecuteScriptInFrameAndExtractString(
-    const internal::ToRenderViewHost& adapter,
-    const std::string& frame_xpath,
-    const std::string& script,
-    std::string* result) {
+bool ExecuteScriptAndExtractString(const internal::ToRenderFrameHost& adapter,
+                                   const std::string& script,
+                                   std::string* result) {
   DCHECK(result);
   scoped_ptr<base::Value> value;
-  if (!ExecuteScriptHelper(adapter.render_view_host(), frame_xpath, script,
-                           &value) || !value.get())
+  if (!ExecuteScriptHelper(adapter.render_frame_host(), script, &value) ||
+      !value.get()) {
     return false;
+  }
 
   return value->GetAsString(result);
 }
 
-bool ExecuteScript(const internal::ToRenderViewHost& adapter,
-                   const std::string& script) {
-  return ExecuteScriptInFrame(adapter, std::string(), script);
+namespace {
+void AddToSetIfFrameMatchesPredicate(
+    std::set<RenderFrameHost*>* frame_set,
+    const base::Callback<bool(RenderFrameHost*)>& predicate,
+    RenderFrameHost* host) {
+  if (predicate.Run(host))
+    frame_set->insert(host);
+}
 }
 
-bool ExecuteScriptAndExtractInt(const internal::ToRenderViewHost& adapter,
-                                const std::string& script, int* result) {
-  return ExecuteScriptInFrameAndExtractInt(adapter, std::string(), script,
-                                           result);
+RenderFrameHost* FrameMatchingPredicate(
+    WebContents* web_contents,
+    const base::Callback<bool(RenderFrameHost*)>& predicate) {
+  std::set<RenderFrameHost*> frame_set;
+  web_contents->ForEachFrame(
+      base::Bind(&AddToSetIfFrameMatchesPredicate, &frame_set, predicate));
+  DCHECK_EQ(1U, frame_set.size());
+  return *frame_set.begin();
 }
 
-bool ExecuteScriptAndExtractBool(const internal::ToRenderViewHost& adapter,
-                                 const std::string& script, bool* result) {
-  return ExecuteScriptInFrameAndExtractBool(adapter, std::string(), script,
-                                            result);
+bool FrameMatchesName(const std::string& name, RenderFrameHost* frame) {
+  return frame->GetFrameName() == name;
 }
 
-bool ExecuteScriptAndExtractString(const internal::ToRenderViewHost& adapter,
-                                   const std::string& script,
-                                   std::string* result) {
-  return ExecuteScriptInFrameAndExtractString(adapter, std::string(), script,
-                                              result);
+bool FrameIsChildOfMainFrame(RenderFrameHost* frame) {
+  return frame->GetParent() && !frame->GetParent()->GetParent();
 }
 
-bool ExecuteWebUIResourceTest(
-    const internal::ToRenderViewHost& adapter,
-    const std::vector<int>& js_resource_ids) {
+bool FrameHasSourceUrl(const GURL& url, RenderFrameHost* frame) {
+  return frame->GetLastCommittedURL() == url;
+}
+
+bool ExecuteWebUIResourceTest(WebContents* web_contents,
+                              const std::vector<int>& js_resource_ids) {
   // Inject WebUI test runner script first prior to other scripts required to
   // run the test as scripts may depend on it being declared.
   std::vector<int> ids;
@@ -491,11 +590,11 @@ bool ExecuteWebUIResourceTest(
         .AppendToString(&script);
     script.append("\n");
   }
-  if (!content::ExecuteScript(adapter, script))
+  if (!ExecuteScript(web_contents, script))
     return false;
 
-  content::DOMMessageQueue message_queue;
-  if (!content::ExecuteScript(adapter, "runTests()"))
+  DOMMessageQueue message_queue;
+  if (!ExecuteScript(web_contents, "runTests()"))
     return false;
 
   std::string message;
@@ -537,6 +636,57 @@ bool SetCookie(BrowserContext* browser_context,
   return result;
 }
 
+void FetchHistogramsFromChildProcesses() {
+  scoped_refptr<content::MessageLoopRunner> runner = new MessageLoopRunner;
+
+  FetchHistogramsAsynchronously(
+      base::MessageLoop::current(),
+      runner->QuitClosure(),
+      // If this call times out, it means that a child process is not
+      // responding, which is something we should not ignore.  The timeout is
+      // set to be longer than the normal browser test timeout so that it will
+      // be prempted by the normal timeout.
+      TestTimeouts::action_max_timeout());
+  runner->Run();
+}
+
+void SetupCrossSiteRedirector(
+    net::test_server::EmbeddedTestServer* embedded_test_server) {
+   embedded_test_server->RegisterRequestHandler(
+       base::Bind(&CrossSiteRedirectResponseHandler,
+                  embedded_test_server->base_url()));
+}
+
+void WaitForInterstitialAttach(content::WebContents* web_contents) {
+  if (web_contents->ShowingInterstitialPage())
+    return;
+  scoped_refptr<content::MessageLoopRunner> loop_runner(
+      new content::MessageLoopRunner);
+  InterstitialObserver observer(web_contents,
+                                loop_runner->QuitClosure(),
+                                base::Closure());
+  loop_runner->Run();
+}
+
+void WaitForInterstitialDetach(content::WebContents* web_contents) {
+  RunTaskAndWaitForInterstitialDetach(web_contents, base::Closure());
+}
+
+void RunTaskAndWaitForInterstitialDetach(content::WebContents* web_contents,
+                                         const base::Closure& task) {
+  if (!web_contents || !web_contents->ShowingInterstitialPage())
+    return;
+  scoped_refptr<content::MessageLoopRunner> loop_runner(
+      new content::MessageLoopRunner);
+  InterstitialObserver observer(web_contents,
+                                base::Closure(),
+                                loop_runner->QuitClosure());
+  if (!task.is_null())
+    task.Run();
+  // At this point, web_contents may have been deleted.
+  loop_runner->Run();
+}
+
 TitleWatcher::TitleWatcher(WebContents* web_contents,
                            const base::string16& expected_title)
     : WebContentsObserver(web_contents),
@@ -553,6 +703,7 @@ TitleWatcher::~TitleWatcher() {
 }
 
 const base::string16& TitleWatcher::WaitAndGetTitle() {
+  TestTitle();
   message_loop_runner_->Run();
   return observed_title_;
 }
@@ -595,8 +746,7 @@ void WebContentsDestroyedWatcher::Wait() {
   message_loop_runner_->Run();
 }
 
-void WebContentsDestroyedWatcher::WebContentsDestroyed(
-    WebContents* web_contents) {
+void WebContentsDestroyedWatcher::WebContentsDestroyed() {
   message_loop_runner_->Quit();
 }
 
@@ -627,7 +777,6 @@ void RenderProcessHostWatcher::Wait() {
 
 void RenderProcessHostWatcher::RenderProcessExited(
     RenderProcessHost* host,
-    base::ProcessHandle handle,
     base::TerminationStatus status,
     int exit_code) {
   if (type_ == WATCH_FOR_PROCESS_EXIT)
@@ -641,7 +790,7 @@ void RenderProcessHostWatcher::RenderProcessHostDestroyed(
     message_loop_runner_->Quit();
 }
 
-DOMMessageQueue::DOMMessageQueue() : waiting_for_message_(false) {
+DOMMessageQueue::DOMMessageQueue() {
   registrar_.Add(this, NOTIFICATION_DOM_OPERATION_RESPONSE,
                  NotificationService::AllSources());
 }
@@ -652,12 +801,9 @@ void DOMMessageQueue::Observe(int type,
                               const NotificationSource& source,
                               const NotificationDetails& details) {
   Details<DomOperationNotificationDetails> dom_op_details(details);
-  Source<RenderViewHost> sender(source);
   message_queue_.push(dom_op_details->json);
-  if (waiting_for_message_) {
-    waiting_for_message_ = false;
+  if (message_loop_runner_.get())
     message_loop_runner_->Quit();
-  }
 }
 
 void DOMMessageQueue::ClearQueue() {
@@ -665,8 +811,8 @@ void DOMMessageQueue::ClearQueue() {
 }
 
 bool DOMMessageQueue::WaitForMessage(std::string* message) {
+  DCHECK(message);
   if (message_queue_.empty()) {
-    waiting_for_message_ = true;
     // This will be quit when a new message comes in.
     message_loop_runner_ = new MessageLoopRunner;
     message_loop_runner_->Run();
@@ -674,8 +820,7 @@ bool DOMMessageQueue::WaitForMessage(std::string* message) {
   // The queue should not be empty, unless we were quit because of a timeout.
   if (message_queue_.empty())
     return false;
-  if (message)
-    *message = message_queue_.front();
+  *message = message_queue_.front();
   message_queue_.pop();
   return true;
 }