#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 {
: 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;
}
// Overridden from WebContentsObserver:
- virtual void RenderProcessGone(base::TerminationStatus status) OVERRIDE {
+ void RenderProcessGone(base::TerminationStatus status) override {
message_loop_runner_->Quit();
}
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.";
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
}
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) {
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));
}
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;
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,
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;
// 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(
// 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);
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;
.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;
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),
}
const base::string16& TitleWatcher::WaitAndGetTitle() {
+ TestTitle();
message_loop_runner_->Run();
return observed_title_;
}
message_loop_runner_->Run();
}
-void WebContentsDestroyedWatcher::WebContentsDestroyed(
- WebContents* web_contents) {
+void WebContentsDestroyedWatcher::WebContentsDestroyed() {
message_loop_runner_->Quit();
}
void RenderProcessHostWatcher::RenderProcessExited(
RenderProcessHost* host,
- base::ProcessHandle handle,
base::TerminationStatus status,
int exit_code) {
if (type_ == WATCH_FOR_PROCESS_EXIT)
message_loop_runner_->Quit();
}
-DOMMessageQueue::DOMMessageQueue() : waiting_for_message_(false) {
+DOMMessageQueue::DOMMessageQueue() {
registrar_.Add(this, NOTIFICATION_DOM_OPERATION_RESPONSE,
NotificationService::AllSources());
}
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() {
}
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();
// 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;
}