1 // Copyright (c) 2014 The Chromium Embedded Framework Authors. All rights
2 // reserved. Use of this source code is governed by a BSD-style license that
3 // can be found in the LICENSE file.
4
5 #include <cstdlib>
6 #include <set>
7 #include <sstream>
8 #include <vector>
9
10 #include "include/base/cef_bind.h"
11 #include "include/base/cef_weak_ptr.h"
12 #include "include/cef_v8.h"
13 #include "include/wrapper/cef_closure_task.h"
14 #include "tests/ceftests/routing_test_handler.h"
15 #include "tests/gtest/include/gtest/gtest.h"
16 #include "tests/shared/renderer/client_app_renderer.h"
17
18 using client::ClientAppRenderer;
19
20 namespace {
21
22 const char kTestDomainRoot[] = "http://tests-mr";
23 const char kTestDomain1[] = "http://tests-mr1.com/";
24 const char kTestDomain2[] = "http://tests-mr2.com/";
25 const char kTestDomain3[] = "http://tests-mr3.com/";
26
27 const char kDoneMessageName[] = "mrtNotifyMsg";
28
29 const char kJSNotifyFunc[] = "mrtNotify";
30 const char kJSAssertTotalCountFunc[] = "mrtAssertTotalCount";
31 const char kJSAssertBrowserCountFunc[] = "mrtAssertBrowserCount";
32 const char kJSAssertContextCountFunc[] = "mrtAssertContextCount";
33
SetRouterConfig(CefMessageRouterConfig & config)34 void SetRouterConfig(CefMessageRouterConfig& config) {
35 config.js_query_function = "mrtQuery";
36 config.js_cancel_function = "mrtQueryCancel";
37 }
38
39 // Handle the renderer side of the routing implementation.
40 class MRRenderDelegate : public ClientAppRenderer::Delegate {
41 public:
42 class V8HandlerImpl : public CefV8Handler {
43 public:
V8HandlerImpl(CefRefPtr<MRRenderDelegate> delegate)44 explicit V8HandlerImpl(CefRefPtr<MRRenderDelegate> delegate)
45 : delegate_(delegate) {}
46
Execute(const CefString & name,CefRefPtr<CefV8Value> object,const CefV8ValueList & arguments,CefRefPtr<CefV8Value> & retval,CefString & exception)47 bool Execute(const CefString& name,
48 CefRefPtr<CefV8Value> object,
49 const CefV8ValueList& arguments,
50 CefRefPtr<CefV8Value>& retval,
51 CefString& exception) override {
52 const std::string& message_name = name;
53 if (message_name == kJSNotifyFunc) {
54 EXPECT_EQ(1U, arguments.size());
55 EXPECT_TRUE(arguments[0]->IsString());
56
57 const CefString& msg = arguments[0]->GetStringValue();
58 CefRefPtr<CefV8Context> context = CefV8Context::GetCurrentContext();
59 CefRefPtr<CefFrame> frame = context->GetFrame();
60
61 CefRefPtr<CefProcessMessage> message =
62 CefProcessMessage::Create(kDoneMessageName);
63 CefRefPtr<CefListValue> args = message->GetArgumentList();
64 args->SetString(0, msg);
65 frame->SendProcessMessage(PID_BROWSER, message);
66 return true;
67 } else {
68 EXPECT_EQ(1U, arguments.size());
69 EXPECT_TRUE(arguments[0]->IsInt());
70
71 const int expected_count = arguments[0]->GetIntValue();
72 int actual_count = -1;
73
74 CefRefPtr<CefV8Context> context = CefV8Context::GetCurrentContext();
75 CefRefPtr<CefBrowser> browser = context->GetBrowser();
76
77 if (name == kJSAssertTotalCountFunc) {
78 actual_count =
79 delegate_->message_router_->GetPendingCount(nullptr, nullptr);
80 } else if (name == kJSAssertBrowserCountFunc) {
81 actual_count =
82 delegate_->message_router_->GetPendingCount(browser, nullptr);
83 } else if (name == kJSAssertContextCountFunc) {
84 actual_count =
85 delegate_->message_router_->GetPendingCount(browser, context);
86 }
87
88 if (expected_count != actual_count) {
89 std::stringstream ss;
90 ss << message_name << " failed; expected " << expected_count
91 << ", got " << actual_count;
92 exception = ss.str();
93 }
94 }
95
96 return true;
97 }
98
99 private:
100 CefRefPtr<MRRenderDelegate> delegate_;
101
102 IMPLEMENT_REFCOUNTING(V8HandlerImpl);
103 };
104
MRRenderDelegate()105 MRRenderDelegate() {}
106
OnWebKitInitialized(CefRefPtr<ClientAppRenderer> app)107 void OnWebKitInitialized(CefRefPtr<ClientAppRenderer> app) override {
108 // Create the renderer-side router for query handling.
109 CefMessageRouterConfig config;
110 SetRouterConfig(config);
111 message_router_ = CefMessageRouterRendererSide::Create(config);
112 }
113
OnContextCreated(CefRefPtr<ClientAppRenderer> app,CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,CefRefPtr<CefV8Context> context)114 void OnContextCreated(CefRefPtr<ClientAppRenderer> app,
115 CefRefPtr<CefBrowser> browser,
116 CefRefPtr<CefFrame> frame,
117 CefRefPtr<CefV8Context> context) override {
118 const std::string& url = frame->GetURL();
119 if (url.find(kTestDomainRoot) != 0)
120 return;
121
122 message_router_->OnContextCreated(browser, frame, context);
123
124 // Register function handlers with the 'window' object.
125 CefRefPtr<CefV8Value> window = context->GetGlobal();
126
127 CefRefPtr<V8HandlerImpl> handler = new V8HandlerImpl(this);
128 CefV8Value::PropertyAttribute attributes =
129 static_cast<CefV8Value::PropertyAttribute>(
130 V8_PROPERTY_ATTRIBUTE_READONLY | V8_PROPERTY_ATTRIBUTE_DONTENUM |
131 V8_PROPERTY_ATTRIBUTE_DONTDELETE);
132
133 CefRefPtr<CefV8Value> notify_func =
134 CefV8Value::CreateFunction(kJSNotifyFunc, handler.get());
135 window->SetValue(kJSNotifyFunc, notify_func, attributes);
136
137 CefRefPtr<CefV8Value> total_count_func =
138 CefV8Value::CreateFunction(kJSAssertTotalCountFunc, handler.get());
139 window->SetValue(kJSAssertTotalCountFunc, total_count_func, attributes);
140
141 CefRefPtr<CefV8Value> browser_count_func =
142 CefV8Value::CreateFunction(kJSAssertBrowserCountFunc, handler.get());
143 window->SetValue(kJSAssertBrowserCountFunc, browser_count_func, attributes);
144
145 CefRefPtr<CefV8Value> context_count_func =
146 CefV8Value::CreateFunction(kJSAssertContextCountFunc, handler.get());
147 window->SetValue(kJSAssertContextCountFunc, context_count_func, attributes);
148 }
149
OnContextReleased(CefRefPtr<ClientAppRenderer> app,CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,CefRefPtr<CefV8Context> context)150 void OnContextReleased(CefRefPtr<ClientAppRenderer> app,
151 CefRefPtr<CefBrowser> browser,
152 CefRefPtr<CefFrame> frame,
153 CefRefPtr<CefV8Context> context) override {
154 const std::string& url = frame->GetURL();
155 if (url.find(kTestDomainRoot) != 0)
156 return;
157
158 message_router_->OnContextReleased(browser, frame, context);
159 }
160
OnProcessMessageReceived(CefRefPtr<ClientAppRenderer> app,CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,CefProcessId source_process,CefRefPtr<CefProcessMessage> message)161 bool OnProcessMessageReceived(CefRefPtr<ClientAppRenderer> app,
162 CefRefPtr<CefBrowser> browser,
163 CefRefPtr<CefFrame> frame,
164 CefProcessId source_process,
165 CefRefPtr<CefProcessMessage> message) override {
166 const std::string& url = frame->GetURL();
167 if (url.find(kTestDomainRoot) != 0)
168 return false;
169
170 return message_router_->OnProcessMessageReceived(browser, frame,
171 source_process, message);
172 }
173
174 private:
175 CefRefPtr<CefMessageRouterRendererSide> message_router_;
176
177 IMPLEMENT_REFCOUNTING(MRRenderDelegate);
178 };
179
180 } // namespace
181
182 // Entry point for creating the test delegate.
183 // Called from client_app_delegates.cc.
CreateMessageRouterRendererTests(ClientAppRenderer::DelegateSet & delegates)184 void CreateMessageRouterRendererTests(
185 ClientAppRenderer::DelegateSet& delegates) {
186 delegates.insert(new MRRenderDelegate);
187 }
188
189 namespace {
190
191 class MRTestHandler : public TestHandler {
192 public:
MRTestHandler()193 MRTestHandler() {}
194
RunTest()195 void RunTest() override {
196 RunMRTest();
197
198 // Time out the test after a reasonable period of time.
199 SetTestTimeout(10000);
200 }
201
OnAfterCreated(CefRefPtr<CefBrowser> browser)202 void OnAfterCreated(CefRefPtr<CefBrowser> browser) override {
203 if (!message_router_.get()) {
204 // Create the browser-side router for query handling.
205 CefMessageRouterConfig config;
206 SetRouterConfig(config);
207 message_router_ = CefMessageRouterBrowserSide::Create(config);
208 AddHandlers(message_router_);
209 }
210 TestHandler::OnAfterCreated(browser);
211 }
212
OnBeforeClose(CefRefPtr<CefBrowser> browser)213 void OnBeforeClose(CefRefPtr<CefBrowser> browser) override {
214 message_router_->OnBeforeClose(browser);
215 TestHandler::OnBeforeClose(browser);
216 }
217
OnRenderProcessTerminated(CefRefPtr<CefBrowser> browser,TerminationStatus status)218 void OnRenderProcessTerminated(CefRefPtr<CefBrowser> browser,
219 TerminationStatus status) override {
220 message_router_->OnRenderProcessTerminated(browser);
221 }
222
223 // Only call this method if the navigation isn't canceled.
OnBeforeBrowse(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,CefRefPtr<CefRequest> request,bool user_gesture,bool is_redirect)224 bool OnBeforeBrowse(CefRefPtr<CefBrowser> browser,
225 CefRefPtr<CefFrame> frame,
226 CefRefPtr<CefRequest> request,
227 bool user_gesture,
228 bool is_redirect) override {
229 message_router_->OnBeforeBrowse(browser, frame);
230 return false;
231 }
232
233 // Returns true if the router handled the navigation.
OnProcessMessageReceived(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,CefProcessId source_process,CefRefPtr<CefProcessMessage> message)234 bool OnProcessMessageReceived(CefRefPtr<CefBrowser> browser,
235 CefRefPtr<CefFrame> frame,
236 CefProcessId source_process,
237 CefRefPtr<CefProcessMessage> message) override {
238 const std::string& message_name = message->GetName();
239 if (message_name == kDoneMessageName) {
240 CefRefPtr<CefListValue> args = message->GetArgumentList();
241 EXPECT_EQ(1U, args->GetSize());
242 EXPECT_EQ(VTYPE_STRING, args->GetType(0));
243 OnNotify(browser, frame, args->GetString(0));
244 return true;
245 }
246
247 return message_router_->OnProcessMessageReceived(browser, frame,
248 source_process, message);
249 }
250
GetRouter() const251 CefRefPtr<CefMessageRouterBrowserSide> GetRouter() const {
252 return message_router_;
253 }
254
255 protected:
256 virtual void RunMRTest() = 0;
257
258 virtual void AddHandlers(
259 CefRefPtr<CefMessageRouterBrowserSide> message_router) = 0;
260
261 virtual void OnNotify(CefRefPtr<CefBrowser> browser,
262 CefRefPtr<CefFrame> frame,
263 const std::string& message) = 0;
264
AssertQueryCount(CefRefPtr<CefBrowser> browser,CefMessageRouterBrowserSide::Handler * handler,int expected_count)265 bool AssertQueryCount(CefRefPtr<CefBrowser> browser,
266 CefMessageRouterBrowserSide::Handler* handler,
267 int expected_count) {
268 int actual_count = message_router_->GetPendingCount(browser, handler);
269 EXPECT_EQ(expected_count, actual_count);
270 return (expected_count == actual_count);
271 }
272
AssertMainBrowser(CefRefPtr<CefBrowser> browser)273 void AssertMainBrowser(CefRefPtr<CefBrowser> browser) {
274 EXPECT_TRUE(browser.get());
275 EXPECT_EQ(GetBrowserId(), browser->GetIdentifier());
276 }
277
278 private:
279 CefRefPtr<CefMessageRouterBrowserSide> message_router_;
280
281 IMPLEMENT_REFCOUNTING(MRTestHandler);
282 };
283
284 // Implementation of MRTestHandler that loads a single page.
285 class SingleLoadTestHandler : public MRTestHandler,
286 public CefMessageRouterBrowserSide::Handler {
287 public:
SingleLoadTestHandler()288 SingleLoadTestHandler()
289 : main_url_(std::string(kTestDomain1) + "main.html") {}
290
GetMainURL()291 const std::string& GetMainURL() { return main_url_; }
292
293 protected:
RunMRTest()294 void RunMRTest() override {
295 AddOtherResources();
296 AddResource(main_url_, GetMainHTML(), "text/html");
297
298 CreateBrowser(main_url_, nullptr);
299 }
300
AddHandlers(CefRefPtr<CefMessageRouterBrowserSide> message_router)301 void AddHandlers(
302 CefRefPtr<CefMessageRouterBrowserSide> message_router) override {
303 message_router->AddHandler(this, false);
304 }
305
AddOtherResources()306 virtual void AddOtherResources() {}
307
308 virtual std::string GetMainHTML() = 0;
309
AssertMainFrame(CefRefPtr<CefFrame> frame)310 void AssertMainFrame(CefRefPtr<CefFrame> frame) {
311 EXPECT_TRUE(frame.get());
312 EXPECT_TRUE(frame->IsMain());
313 EXPECT_STREQ(main_url_.c_str(), frame->GetURL().ToString().c_str());
314 }
315
316 private:
317 const std::string main_url_;
318 };
319
320 // Used to verify that the test harness (bound functions) behave correctly.
321 class HarnessTestHandler : public SingleLoadTestHandler {
322 public:
HarnessTestHandler(bool test_success)323 HarnessTestHandler(bool test_success) : test_success_(test_success) {}
324
GetMainHTML()325 std::string GetMainHTML() override {
326 std::string html;
327 if (test_success_) {
328 // All assertions should pass.
329 html =
330 "<html><body><script>\n"
331 "var fail_ct = 0;\n"
332 "try { window.mrtAssertTotalCount(0); } catch (e) { fail_ct++; }\n"
333 "try { window.mrtAssertBrowserCount(0); } catch (e) { fail_ct++; }\n"
334 "try { window.mrtAssertContextCount(0); } catch (e) { fail_ct++; }\n"
335 "window.mrtNotify('' + (fail_ct == 0));"
336 "</script></body></html>";
337 } else {
338 // All assertions should fail.
339 html =
340 "<html><body><script>\n"
341 "var fail_ct = 0;\n"
342 "try { window.mrtAssertTotalCount(1); } catch (e) { fail_ct++; }\n"
343 "try { window.mrtAssertBrowserCount(1); } catch (e) { fail_ct++; }\n"
344 "try { window.mrtAssertContextCount(1); } catch (e) { fail_ct++; }\n"
345 "window.mrtNotify('' + (fail_ct == 3));"
346 "</script></body></html>";
347 }
348 return html;
349 }
350
OnNotify(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,const std::string & message)351 void OnNotify(CefRefPtr<CefBrowser> browser,
352 CefRefPtr<CefFrame> frame,
353 const std::string& message) override {
354 AssertMainBrowser(browser);
355 AssertMainFrame(frame);
356
357 got_done_.yes();
358 EXPECT_STREQ("true", message.c_str());
359 DestroyTest();
360 }
361
DestroyTest()362 void DestroyTest() override {
363 EXPECT_TRUE(got_done_);
364 TestHandler::DestroyTest();
365 }
366
367 private:
368 const bool test_success_;
369 TrackCallback got_done_;
370 };
371
372 } // namespace
373
374 // Verify that the test harness works with successful assertions.
TEST(MessageRouterTest,HarnessSuccess)375 TEST(MessageRouterTest, HarnessSuccess) {
376 CefRefPtr<HarnessTestHandler> handler = new HarnessTestHandler(true);
377 handler->ExecuteTest();
378 ReleaseAndWaitForDestructor(handler);
379 }
380
381 // Verify that the test harness works with failed assertions.
TEST(MessageRouterTest,HarnessFailure)382 TEST(MessageRouterTest, HarnessFailure) {
383 CefRefPtr<HarnessTestHandler> handler = new HarnessTestHandler(false);
384 handler->ExecuteTest();
385 ReleaseAndWaitForDestructor(handler);
386 }
387
388 namespace {
389
390 const char kSingleQueryRequest[] = "request_context";
391 const char kSingleQueryResponse[] = "success_response";
392 const int kSingleQueryErrorCode = 5;
393 const char kSingleQueryErrorMessage[] = "error_message";
394
395 // Test a single query in a single page load.
396 class SingleQueryTestHandler : public SingleLoadTestHandler {
397 public:
398 enum TestType {
399 SUCCESS,
400 FAILURE,
401 CANCEL,
402 };
403
SingleQueryTestHandler(TestType type,bool sync_callback)404 SingleQueryTestHandler(TestType type, bool sync_callback)
405 : test_type_(type), sync_callback_(sync_callback), query_id_(0) {}
406
GetMainHTML()407 std::string GetMainHTML() override {
408 std::string html;
409
410 std::stringstream ss;
411 ss << kSingleQueryErrorCode;
412 const std::string& errorCodeStr = ss.str();
413
414 html =
415 "<html><body><script>\n"
416 // No requests should exist.
417 "window.mrtAssertTotalCount(0);\n"
418 "window.mrtAssertBrowserCount(0);\n"
419 "window.mrtAssertContextCount(0);\n"
420 // Send the query.
421 "var request_id = window.mrtQuery({\n"
422 " request: '" +
423 std::string(kSingleQueryRequest) +
424 "',\n"
425 " persistent: false,\n"
426 " onSuccess: function(response) {\n"
427 // Request should be removed before callback is executed.
428 " window.mrtAssertTotalCount(0);\n"
429 " window.mrtAssertBrowserCount(0);\n"
430 " window.mrtAssertContextCount(0);\n"
431 " if (response == '" +
432 std::string(kSingleQueryResponse) +
433 "')\n"
434 " window.mrtNotify('success');\n"
435 " else\n"
436 " window.mrtNotify('error-onSuccess');\n"
437 " },\n"
438 " onFailure: function(error_code, error_message) {\n"
439 // Request should be removed before callback is executed.
440 " window.mrtAssertTotalCount(0);\n"
441 " window.mrtAssertBrowserCount(0);\n"
442 " window.mrtAssertContextCount(0);\n"
443 " if (error_code == " +
444 errorCodeStr + " && error_message == '" +
445 std::string(kSingleQueryErrorMessage) +
446 "')\n"
447 " window.mrtNotify('failure');\n"
448 " else\n"
449 " window.mrtNotify('error-onFailure');\n"
450 " }\n"
451 "});\n"
452 // Request should exist.
453 "window.mrtAssertTotalCount(1);\n"
454 "window.mrtAssertBrowserCount(1);\n"
455 "window.mrtAssertContextCount(1);\n";
456
457 if (test_type_ == CANCEL) {
458 html +=
459 "window.mrtQueryCancel(request_id);\n"
460 // Request should be removed immediately.
461 "window.mrtAssertTotalCount(0);\n"
462 "window.mrtAssertBrowserCount(0);\n"
463 "window.mrtAssertContextCount(0);\n"
464 "window.mrtNotify('cancel');\n";
465 }
466
467 html += "</script></body></html>";
468 return html;
469 }
470
OnNotify(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,const std::string & message)471 void OnNotify(CefRefPtr<CefBrowser> browser,
472 CefRefPtr<CefFrame> frame,
473 const std::string& message) override {
474 AssertMainBrowser(browser);
475 AssertMainFrame(frame);
476
477 // OnNotify only be called once.
478 EXPECT_FALSE(got_notify_);
479 got_notify_.yes();
480
481 if (test_type_ == SUCCESS) {
482 EXPECT_STREQ("success", message.c_str());
483 } else if (test_type_ == FAILURE) {
484 EXPECT_STREQ("failure", message.c_str());
485 } else if (test_type_ == CANCEL) {
486 EXPECT_STREQ("cancel", message.c_str());
487 }
488
489 DestroyTestIfDone();
490 }
491
ExecuteCallback()492 void ExecuteCallback() {
493 EXPECT_TRUE(callback_.get());
494 if (test_type_ == SUCCESS) {
495 callback_->Success(kSingleQueryResponse);
496 } else if (test_type_ == FAILURE) {
497 callback_->Failure(kSingleQueryErrorCode, kSingleQueryErrorMessage);
498 } else {
499 EXPECT_TRUE(false); // Not reached.
500 }
501 callback_ = nullptr;
502 }
503
OnQuery(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,int64 query_id,const CefString & request,bool persistent,CefRefPtr<Callback> callback)504 bool OnQuery(CefRefPtr<CefBrowser> browser,
505 CefRefPtr<CefFrame> frame,
506 int64 query_id,
507 const CefString& request,
508 bool persistent,
509 CefRefPtr<Callback> callback) override {
510 AssertMainBrowser(browser);
511 AssertMainFrame(frame);
512 EXPECT_NE(0, query_id);
513 EXPECT_FALSE(persistent);
514 EXPECT_STREQ(kSingleQueryRequest, request.ToString().c_str());
515
516 got_on_query_.yes();
517
518 query_id_ = query_id;
519 callback_ = callback;
520
521 if (test_type_ == SUCCESS || test_type_ == FAILURE) {
522 if (sync_callback_) {
523 ExecuteCallback();
524 } else {
525 CefPostTask(TID_UI,
526 base::Bind(&SingleQueryTestHandler::ExecuteCallback, this));
527 }
528 }
529
530 return true;
531 }
532
OnQueryCanceled(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,int64 query_id)533 void OnQueryCanceled(CefRefPtr<CefBrowser> browser,
534 CefRefPtr<CefFrame> frame,
535 int64 query_id) override {
536 AssertMainBrowser(browser);
537 AssertMainFrame(frame);
538 EXPECT_EQ(test_type_, CANCEL);
539 EXPECT_EQ(query_id_, query_id);
540 EXPECT_TRUE(got_on_query_);
541 EXPECT_TRUE(callback_.get());
542
543 got_on_query_canceled_.yes();
544 callback_ = nullptr;
545
546 DestroyTestIfDone();
547 }
548
DestroyTestIfDone()549 void DestroyTestIfDone() {
550 bool destroy_test = false;
551 if (test_type_ == CANCEL)
552 destroy_test = got_notify_ && got_on_query_canceled_;
553 else
554 destroy_test = got_notify_;
555 if (destroy_test)
556 DestroyTest();
557 }
558
DestroyTest()559 void DestroyTest() override {
560 EXPECT_TRUE(got_notify_);
561 EXPECT_TRUE(got_on_query_);
562 EXPECT_FALSE(callback_.get());
563
564 if (test_type_ == CANCEL)
565 EXPECT_TRUE(got_on_query_canceled_);
566 else
567 EXPECT_FALSE(got_on_query_canceled_);
568
569 TestHandler::DestroyTest();
570 }
571
572 private:
573 const TestType test_type_;
574 const bool sync_callback_;
575
576 int64 query_id_;
577 CefRefPtr<Callback> callback_;
578
579 TrackCallback got_on_query_;
580 TrackCallback got_on_query_canceled_;
581 TrackCallback got_notify_;
582 };
583
584 } // namespace
585
586 // Test that a single query with successful result delivered synchronously.
TEST(MessageRouterTest,SingleQuerySuccessSyncCallback)587 TEST(MessageRouterTest, SingleQuerySuccessSyncCallback) {
588 CefRefPtr<SingleQueryTestHandler> handler =
589 new SingleQueryTestHandler(SingleQueryTestHandler::SUCCESS, true);
590 handler->ExecuteTest();
591 ReleaseAndWaitForDestructor(handler);
592 }
593
594 // Test that a single query with successful result delivered asynchronously.
TEST(MessageRouterTest,SingleQuerySuccessAsyncCallback)595 TEST(MessageRouterTest, SingleQuerySuccessAsyncCallback) {
596 CefRefPtr<SingleQueryTestHandler> handler =
597 new SingleQueryTestHandler(SingleQueryTestHandler::SUCCESS, false);
598 handler->ExecuteTest();
599 ReleaseAndWaitForDestructor(handler);
600 }
601
602 // Test that a single query with failure result delivered synchronously.
TEST(MessageRouterTest,SingleQueryFailureSyncCallback)603 TEST(MessageRouterTest, SingleQueryFailureSyncCallback) {
604 CefRefPtr<SingleQueryTestHandler> handler =
605 new SingleQueryTestHandler(SingleQueryTestHandler::FAILURE, true);
606 handler->ExecuteTest();
607 ReleaseAndWaitForDestructor(handler);
608 }
609
610 // Test that a single query with failure result delivered asynchronously.
TEST(MessageRouterTest,SingleQueryFailureAsyncCallback)611 TEST(MessageRouterTest, SingleQueryFailureAsyncCallback) {
612 CefRefPtr<SingleQueryTestHandler> handler =
613 new SingleQueryTestHandler(SingleQueryTestHandler::FAILURE, false);
614 handler->ExecuteTest();
615 ReleaseAndWaitForDestructor(handler);
616 }
617
618 // Test that a single query with cancellation.
TEST(MessageRouterTest,SingleQueryCancel)619 TEST(MessageRouterTest, SingleQueryCancel) {
620 CefRefPtr<SingleQueryTestHandler> handler =
621 new SingleQueryTestHandler(SingleQueryTestHandler::CANCEL, true);
622 handler->ExecuteTest();
623 ReleaseAndWaitForDestructor(handler);
624 }
625
626 namespace {
627
628 const int kSinglePersistentQueryResponseCount = 10;
629
630 // Test a single persistent query in a single page load.
631 class SinglePersistentQueryTestHandler : public SingleLoadTestHandler {
632 public:
633 enum TestType {
634 SUCCESS,
635 FAILURE,
636 };
637
SinglePersistentQueryTestHandler(TestType test_type,bool sync_callback)638 SinglePersistentQueryTestHandler(TestType test_type, bool sync_callback)
639 : test_type_(test_type), sync_callback_(sync_callback), query_id_(0) {}
640
GetMainHTML()641 std::string GetMainHTML() override {
642 std::string html;
643
644 std::stringstream ss;
645 ss << kSinglePersistentQueryResponseCount;
646 const std::string& responseCountStr = ss.str();
647 ss.str("");
648 ss << kSingleQueryErrorCode;
649 const std::string& errorCodeStr = ss.str();
650
651 html =
652 "<html><body><script>\n"
653 // No requests should exist.
654 "window.mrtAssertTotalCount(0);\n"
655 "window.mrtAssertBrowserCount(0);\n"
656 "window.mrtAssertContextCount(0);\n"
657 // Keep track of the number of responses.
658 "var count = 0;\n"
659 // Send the query.
660 "var request_id = window.mrtQuery({\n"
661 " request: '" +
662 std::string(kSingleQueryRequest) +
663 "',\n"
664 " persistent: true,\n"
665 " onSuccess: function(response) {\n"
666 // Request should not be removed.
667 " window.mrtAssertTotalCount(1);\n"
668 " window.mrtAssertBrowserCount(1);\n"
669 " window.mrtAssertContextCount(1);\n"
670 " if (response == '" +
671 std::string(kSingleQueryResponse) +
672 "') {\n"
673 " if (++count == " +
674 responseCountStr +
675 ") {\n"
676 " window.mrtNotify('success');\n"
677 " window.mrtQueryCancel(request_id);\n"
678 // Request should be removed immediately.
679 " window.mrtAssertTotalCount(0);\n"
680 " window.mrtAssertBrowserCount(0);\n"
681 " window.mrtAssertContextCount(0);\n"
682 " }\n"
683 " } else {\n"
684 " window.mrtNotify('error-onSuccess');\n"
685 " }\n"
686 " },\n"
687 " onFailure: function(error_code, error_message) {\n"
688 // Request should be removed before callback is executed.
689 " window.mrtAssertTotalCount(0);\n"
690 " window.mrtAssertBrowserCount(0);\n"
691 " window.mrtAssertContextCount(0);\n"
692 " if (error_code == " +
693 errorCodeStr + " && error_message == '" +
694 std::string(kSingleQueryErrorMessage) +
695 "') {\n"
696 " window.mrtNotify('failure');\n"
697 " } else {\n"
698 " window.mrtNotify('error-onFailure');\n"
699 " }\n"
700 " }\n"
701 "});\n"
702 // Request should exist.
703 "window.mrtAssertTotalCount(1);\n"
704 "window.mrtAssertBrowserCount(1);\n"
705 "window.mrtAssertContextCount(1);\n";
706
707 html += "</script></body></html>";
708 return html;
709 }
710
OnNotify(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,const std::string & message)711 void OnNotify(CefRefPtr<CefBrowser> browser,
712 CefRefPtr<CefFrame> frame,
713 const std::string& message) override {
714 AssertMainBrowser(browser);
715 AssertMainFrame(frame);
716
717 if (test_type_ == SUCCESS) {
718 EXPECT_STREQ("success", message.c_str());
719 } else if (test_type_ == FAILURE) {
720 EXPECT_STREQ("failure", message.c_str());
721 }
722
723 got_notify_.yes();
724
725 DestroyTestIfDone();
726 }
727
ExecuteCallback()728 void ExecuteCallback() {
729 EXPECT_TRUE(callback_.get());
730 if (test_type_ == SUCCESS) {
731 callback_->Success(kSingleQueryResponse);
732 } else {
733 callback_->Failure(kSingleQueryErrorCode, kSingleQueryErrorMessage);
734 callback_ = nullptr;
735 }
736 }
737
OnQuery(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,int64 query_id,const CefString & request,bool persistent,CefRefPtr<Callback> callback)738 bool OnQuery(CefRefPtr<CefBrowser> browser,
739 CefRefPtr<CefFrame> frame,
740 int64 query_id,
741 const CefString& request,
742 bool persistent,
743 CefRefPtr<Callback> callback) override {
744 AssertMainBrowser(browser);
745 AssertMainFrame(frame);
746 EXPECT_NE(0, query_id);
747 EXPECT_TRUE(persistent);
748 EXPECT_STREQ(kSingleQueryRequest, request.ToString().c_str());
749
750 got_on_query_.yes();
751
752 query_id_ = query_id;
753 callback_ = callback;
754
755 int repeat =
756 (test_type_ == SUCCESS ? kSinglePersistentQueryResponseCount : 1);
757
758 for (int i = 0; i < repeat; ++i) {
759 if (sync_callback_) {
760 ExecuteCallback();
761 } else {
762 CefPostTask(
763 TID_UI,
764 base::Bind(&SinglePersistentQueryTestHandler::ExecuteCallback,
765 this));
766 }
767 }
768
769 return true;
770 }
771
OnQueryCanceled(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,int64 query_id)772 void OnQueryCanceled(CefRefPtr<CefBrowser> browser,
773 CefRefPtr<CefFrame> frame,
774 int64 query_id) override {
775 AssertMainBrowser(browser);
776 AssertMainFrame(frame);
777 EXPECT_EQ(query_id_, query_id);
778 EXPECT_TRUE(got_on_query_);
779 EXPECT_TRUE(callback_.get());
780
781 got_on_query_canceled_.yes();
782 callback_ = nullptr;
783
784 DestroyTestIfDone();
785 }
786
DestroyTestIfDone()787 void DestroyTestIfDone() {
788 bool destroy_test = false;
789 if (test_type_ == SUCCESS) {
790 if (got_on_query_ && got_on_query_canceled_ && got_notify_)
791 destroy_test = true;
792 } else if (got_on_query_ && got_notify_) {
793 destroy_test = true;
794 }
795
796 if (destroy_test)
797 DestroyTest();
798 }
799
DestroyTest()800 void DestroyTest() override {
801 EXPECT_TRUE(got_notify_);
802 EXPECT_TRUE(got_on_query_);
803 EXPECT_FALSE(callback_.get());
804
805 if (test_type_ == SUCCESS)
806 EXPECT_TRUE(got_on_query_canceled_);
807 else
808 EXPECT_FALSE(got_on_query_canceled_);
809
810 TestHandler::DestroyTest();
811 }
812
813 private:
814 const TestType test_type_;
815 const bool sync_callback_;
816
817 int64 query_id_;
818 CefRefPtr<Callback> callback_;
819
820 TrackCallback got_on_query_;
821 TrackCallback got_on_query_canceled_;
822 TrackCallback got_notify_;
823 };
824
825 } // namespace
826
827 // Test that a single query with successful result delivered synchronously.
TEST(MessageRouterTest,SinglePersistentQuerySuccessSyncCallback)828 TEST(MessageRouterTest, SinglePersistentQuerySuccessSyncCallback) {
829 CefRefPtr<SinglePersistentQueryTestHandler> handler =
830 new SinglePersistentQueryTestHandler(
831 SinglePersistentQueryTestHandler::SUCCESS, true);
832 handler->ExecuteTest();
833 ReleaseAndWaitForDestructor(handler);
834 }
835
836 // Test that a single query with successful result delivered asynchronously.
TEST(MessageRouterTest,SinglePersistentQuerySuccessAsyncCallback)837 TEST(MessageRouterTest, SinglePersistentQuerySuccessAsyncCallback) {
838 CefRefPtr<SinglePersistentQueryTestHandler> handler =
839 new SinglePersistentQueryTestHandler(
840 SinglePersistentQueryTestHandler::SUCCESS, false);
841 handler->ExecuteTest();
842 ReleaseAndWaitForDestructor(handler);
843 }
844
845 // Test that a single query with failure result delivered synchronously.
TEST(MessageRouterTest,SinglePersistentQueryFailureSyncCallback)846 TEST(MessageRouterTest, SinglePersistentQueryFailureSyncCallback) {
847 CefRefPtr<SinglePersistentQueryTestHandler> handler =
848 new SinglePersistentQueryTestHandler(
849 SinglePersistentQueryTestHandler::FAILURE, true);
850 handler->ExecuteTest();
851 ReleaseAndWaitForDestructor(handler);
852 }
853
854 // Test that a single query with failure result delivered asynchronously.
TEST(MessageRouterTest,SinglePersistentQueryFailureAsyncCallback)855 TEST(MessageRouterTest, SinglePersistentQueryFailureAsyncCallback) {
856 CefRefPtr<SinglePersistentQueryTestHandler> handler =
857 new SinglePersistentQueryTestHandler(
858 SinglePersistentQueryTestHandler::FAILURE, false);
859 handler->ExecuteTest();
860 ReleaseAndWaitForDestructor(handler);
861 }
862
863 namespace {
864
865 // Test a single unhandled query in a single page load.
866 class SingleUnhandledQueryTestHandler : public SingleLoadTestHandler {
867 public:
SingleUnhandledQueryTestHandler()868 SingleUnhandledQueryTestHandler() {}
869
GetMainHTML()870 std::string GetMainHTML() override {
871 std::string html;
872
873 html =
874 "<html><body><script>\n"
875 // No requests should exist.
876 "window.mrtAssertTotalCount(0);\n"
877 "window.mrtAssertBrowserCount(0);\n"
878 "window.mrtAssertContextCount(0);\n"
879 // Keep track of the number of responses.
880 "var count = 0;\n"
881 // Send the query.
882 "var request_id = window.mrtQuery({\n"
883 " request: '" +
884 std::string(kSingleQueryRequest) +
885 "',\n"
886 " persistent: false,\n"
887 " onSuccess: function(response) {\n"
888 " window.mrtNotify('error-onSuccess');\n"
889 " },\n"
890 " onFailure: function(error_code, error_message) {\n"
891 // Request should be removed before callback is executed.
892 " window.mrtAssertTotalCount(0);\n"
893 " window.mrtAssertBrowserCount(0);\n"
894 " window.mrtAssertContextCount(0);\n"
895 " if (error_code == -1 && "
896 "error_message == 'The query has been canceled') {\n"
897 " window.mrtNotify('failure');\n"
898 " } else {\n"
899 " window.mrtNotify('error-onFailure');\n"
900 " }\n"
901 " }\n"
902 "});\n"
903 // Request should exist.
904 "window.mrtAssertTotalCount(1);\n"
905 "window.mrtAssertBrowserCount(1);\n"
906 "window.mrtAssertContextCount(1);\n";
907
908 html += "</script></body></html>";
909 return html;
910 }
911
OnNotify(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,const std::string & message)912 void OnNotify(CefRefPtr<CefBrowser> browser,
913 CefRefPtr<CefFrame> frame,
914 const std::string& message) override {
915 AssertMainBrowser(browser);
916 AssertMainFrame(frame);
917 EXPECT_STREQ("failure", message.c_str());
918
919 got_notify_.yes();
920
921 DestroyTest();
922 }
923
OnQuery(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,int64 query_id,const CefString & request,bool persistent,CefRefPtr<Callback> callback)924 bool OnQuery(CefRefPtr<CefBrowser> browser,
925 CefRefPtr<CefFrame> frame,
926 int64 query_id,
927 const CefString& request,
928 bool persistent,
929 CefRefPtr<Callback> callback) override {
930 AssertMainBrowser(browser);
931 AssertMainFrame(frame);
932 EXPECT_NE(0, query_id);
933 EXPECT_FALSE(persistent);
934 EXPECT_STREQ(kSingleQueryRequest, request.ToString().c_str());
935
936 got_on_query_.yes();
937
938 return false;
939 }
940
OnQueryCanceled(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,int64 query_id)941 void OnQueryCanceled(CefRefPtr<CefBrowser> browser,
942 CefRefPtr<CefFrame> frame,
943 int64 query_id) override {
944 EXPECT_FALSE(true); // Not reached.
945 }
946
DestroyTest()947 void DestroyTest() override {
948 EXPECT_TRUE(got_on_query_);
949 EXPECT_TRUE(got_notify_);
950
951 TestHandler::DestroyTest();
952 }
953
954 private:
955 TrackCallback got_on_query_;
956 TrackCallback got_notify_;
957 };
958
959 } // namespace
960
961 // Test that a single unhandled query results in a call to onFailure.
TEST(MessageRouterTest,SingleUnhandledQuery)962 TEST(MessageRouterTest, SingleUnhandledQuery) {
963 CefRefPtr<SingleUnhandledQueryTestHandler> handler =
964 new SingleUnhandledQueryTestHandler();
965 handler->ExecuteTest();
966 ReleaseAndWaitForDestructor(handler);
967 }
968
969 namespace {
970
971 const char kMultiQueryRequestId[] = "request_id";
972 const char kMultiQueryRepeatCt[] = "repeat_ct";
973 const char kMultiQueryRequest[] = "request";
974 const char kMultiQueryResponse[] = "response";
975 const char kMultiQuerySuccess[] = "success";
976 const char kMultiQueryError[] = "error";
977 const char kMultiQueryErrorMessage[] = "errormsg";
978 const int kMultiQueryPersistentResponseCount = 5;
979
980 // Generates HTML and verifies results for multiple simultanious queries.
981 class MultiQueryManager : public CefMessageRouterBrowserSide::Handler {
982 public:
983 enum TestType {
984 // Initiates a non-persistent query with a successful response.
985 // OnQuery and OnNotify will be called.
986 SUCCESS,
987
988 // Initiates a non-persistent query with a failure response.
989 // OnQuery and OnNotify will be called.
990 FAILURE,
991
992 // Initiates a persistent query with multiple successful responses.
993 // OnQuery, OnNotify and OnQueryCanceled will be called.
994 PERSISTENT_SUCCESS,
995
996 // Initiates a persistent query with multiple successful responses and one
997 // failure response.
998 // OnQuery and OnNotify will be called.
999 PERSISTENT_FAILURE,
1000
1001 // Initiates a non-persistent query that will be canceled via JavaScript.
1002 // No JavaScript callbacks will be executed.
1003 // OnQuery and OnQueryCanceled will be called.
1004 CANCEL,
1005
1006 // Initiates a non-persistent query that will not be manually canceled.
1007 // No JavaScript callbacks will be executed.
1008 // OnQuery and OnQueryCanceled will be called.
1009 AUTOCANCEL,
1010
1011 // Initiates a persistent query with multiple successful responses that will
1012 // not be manually canceled.
1013 // OnQuery, OnNotify and OnQueryCanceled will be called.
1014 PERSISTENT_AUTOCANCEL,
1015 };
1016
1017 class Observer {
1018 public:
1019 // Called when all manual queries are complete.
OnManualQueriesCompleted(MultiQueryManager * manager)1020 virtual void OnManualQueriesCompleted(MultiQueryManager* manager) {}
1021
1022 // Called when all queries are complete.
OnAllQueriesCompleted(MultiQueryManager * manager)1023 virtual void OnAllQueriesCompleted(MultiQueryManager* manager) {}
1024
1025 protected:
~Observer()1026 virtual ~Observer() {}
1027 };
1028
MultiQueryManager(const std::string & label,bool synchronous,int id_offset=0)1029 MultiQueryManager(const std::string& label,
1030 bool synchronous,
1031 int id_offset = 0)
1032 : label_(label),
1033 synchronous_(synchronous),
1034 id_offset_(id_offset),
1035 finalized_(false),
1036 running_(false),
1037 manual_total_(0),
1038 received_count_(0),
1039 manual_complete_count_(0),
1040 auto_complete_count_(0),
1041 will_cancel_by_removing_handler_(false),
1042 weak_ptr_factory_(this) {}
1043
~MultiQueryManager()1044 virtual ~MultiQueryManager() {}
1045
label() const1046 std::string label() const { return label_; }
1047
AddObserver(Observer * observer)1048 void AddObserver(Observer* observer) {
1049 EXPECT_FALSE(running_);
1050 observer_set_.insert(observer);
1051 }
1052
RemoveObserver(Observer * observer)1053 void RemoveObserver(Observer* observer) {
1054 EXPECT_FALSE(running_);
1055 EXPECT_TRUE(observer_set_.erase(observer));
1056 }
1057
1058 // Can be called from any thread, but should always be called from the same
1059 // thread.
AddTestQuery(TestType type)1060 void AddTestQuery(TestType type) {
1061 EXPECT_FALSE(finalized_);
1062 test_query_vector_.push_back(TestQuery(type));
1063 if (!IsAuto(type))
1064 manual_total_++;
1065 }
1066
1067 // Must be called after AddTestQuery and before the manager is used.
Finalize()1068 void Finalize() {
1069 EXPECT_FALSE(finalized_);
1070 finalized_ = true;
1071 }
1072
1073 // Call after all manual queries have completed if you intend to cancel auto
1074 // queries by removing the handler.
WillCancelByRemovingHandler()1075 void WillCancelByRemovingHandler() {
1076 EXPECT_TRUE(IsManualComplete());
1077 will_cancel_by_removing_handler_ = true;
1078 }
1079
GetHTML(bool assert_total,bool assert_browser) const1080 std::string GetHTML(bool assert_total, bool assert_browser) const {
1081 EXPECT_TRUE(finalized_);
1082 EXPECT_FALSE(running_);
1083
1084 std::string html;
1085
1086 html = "<html><body>" + label_ + "<script>\n";
1087
1088 // No requests should exist.
1089 if (assert_total)
1090 html += "window.mrtAssertTotalCount(0);\n";
1091 if (assert_browser)
1092 html += "window.mrtAssertBrowserCount(0);\n";
1093 html += "window.mrtAssertContextCount(0);\n";
1094
1095 if (synchronous_) {
1096 // Run all of the queries synchronously. None will complete before the
1097 // last one begins.
1098 for (size_t i = 0; i < test_query_vector_.size(); ++i) {
1099 const TestQuery& query = test_query_vector_[i];
1100 html += GetQueryHTML(static_cast<int>(i), query);
1101 }
1102
1103 const int total_ct = static_cast<int>(test_query_vector_.size());
1104
1105 // Pending requests should match the total created.
1106 const std::string& total_val = GetIntString(total_ct);
1107 if (assert_total)
1108 html += "window.mrtAssertTotalCount(" + total_val + ");\n";
1109 if (assert_browser)
1110 html += "window.mrtAssertBrowserCount(" + total_val + ");\n";
1111 html += "window.mrtAssertContextCount(" + total_val + ");\n";
1112
1113 int cancel_ct = 0;
1114
1115 // Cancel all of the queries with type CANCEL.
1116 for (size_t i = 0; i < test_query_vector_.size(); ++i) {
1117 const TestQuery& query = test_query_vector_[i];
1118 if (query.type == CANCEL) {
1119 html += GetCancelHTML(static_cast<int>(i), query);
1120 cancel_ct++;
1121 }
1122 }
1123
1124 if (cancel_ct > 0) {
1125 // Pending requests should match the total not canceled.
1126 const std::string& cancel_val = GetIntString(total_ct - cancel_ct);
1127 if (assert_total)
1128 html += "window.mrtAssertTotalCount(" + cancel_val + ");\n";
1129 if (assert_browser)
1130 html += "window.mrtAssertBrowserCount(" + cancel_val + ");\n";
1131 html += "window.mrtAssertContextCount(" + cancel_val + ");\n";
1132 }
1133 } else {
1134 // Run all of the queries asynchronously. Some may complete before
1135 // others begin.
1136 for (size_t i = 0; i < test_query_vector_.size(); ++i) {
1137 const TestQuery& query = test_query_vector_[i];
1138
1139 const int index = static_cast<int>(i);
1140
1141 // Each request is delayed by 10ms from the previous request.
1142 const std::string& delay_val = GetIntString(index);
1143 const std::string& query_html = GetQueryHTML(index, query);
1144
1145 html += "window.setTimeout(function() {\n" + query_html;
1146
1147 if (query.type == CANCEL) {
1148 // Cancel the query asynchronously with a 10ms delay.
1149 const std::string& request_id_var =
1150 GetIDString(kMultiQueryRequestId, index);
1151 html +=
1152 " window.setTimeout(function() {\n"
1153 " window.mrtQueryCancel(" +
1154 request_id_var +
1155 ");\n"
1156 " }, 1);\n";
1157 }
1158
1159 html += "\n}, " + delay_val + ");\n";
1160 }
1161 }
1162
1163 html += "</script></body></html>";
1164
1165 return html;
1166 }
1167
OnNotify(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,const std::string & message)1168 void OnNotify(CefRefPtr<CefBrowser> browser,
1169 CefRefPtr<CefFrame> frame,
1170 const std::string& message) {
1171 EXPECT_TRUE(finalized_);
1172 EXPECT_UI_THREAD();
1173
1174 if (!running_)
1175 running_ = true;
1176
1177 EXPECT_TRUE(browser.get());
1178 EXPECT_TRUE(frame.get());
1179
1180 std::string value;
1181 int index = 0;
1182 EXPECT_TRUE(SplitIDString(message, &value, &index));
1183
1184 TestQuery& query = test_query_vector_[index];
1185
1186 // Verify that browser and frame are the same.
1187 EXPECT_EQ(query.browser_id, browser->GetIdentifier()) << index;
1188 EXPECT_EQ(query.frame_id, frame->GetIdentifier()) << index;
1189
1190 // Verify a successful/expected result.
1191 if (will_cancel_by_removing_handler_) {
1192 // Auto queries receive an onFailure callback which will notify with error
1193 // when the handler is removed.
1194 EXPECT_STREQ(kMultiQueryError, value.c_str()) << index;
1195 EXPECT_TRUE(IsAuto(query.type)) << index;
1196 EXPECT_TRUE(query.got_query) << index;
1197 if (query.type == PERSISTENT_AUTOCANCEL)
1198 EXPECT_TRUE(query.got_success) << index;
1199 else
1200 EXPECT_FALSE(query.got_success) << index;
1201
1202 query.got_error.yes();
1203
1204 // There's a race between OnQueryCanceled and OnNotification. Only call
1205 // OnQueryCompleted a single time.
1206 if (query.got_query_canceled)
1207 OnQueryCompleted(query.type);
1208 } else {
1209 EXPECT_STREQ(kMultiQuerySuccess, value.c_str()) << index;
1210 EXPECT_TRUE(WillNotify(query.type)) << index;
1211 EXPECT_TRUE(query.got_query) << index;
1212 EXPECT_FALSE(query.got_query_canceled) << index;
1213 EXPECT_FALSE(query.got_success) << index;
1214
1215 query.got_success.yes();
1216
1217 // PERSISTENT_AUTOCANCEL doesn't call OnReceiveCompleted from OnQuery.
1218 if (query.type == PERSISTENT_AUTOCANCEL)
1219 OnReceiveCompleted(query.type);
1220
1221 // Call OnQueryCompleted for types that don't get OnQueryCanceled.
1222 if (!WillCancel(query.type))
1223 OnQueryCompleted(query.type);
1224 }
1225 }
1226
OnQuery(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,int64 query_id,const CefString & request,bool persistent,CefRefPtr<Callback> callback)1227 bool OnQuery(CefRefPtr<CefBrowser> browser,
1228 CefRefPtr<CefFrame> frame,
1229 int64 query_id,
1230 const CefString& request,
1231 bool persistent,
1232 CefRefPtr<Callback> callback) override {
1233 EXPECT_TRUE(finalized_);
1234 EXPECT_UI_THREAD();
1235
1236 if (!running_)
1237 running_ = true;
1238
1239 EXPECT_TRUE(browser.get());
1240 EXPECT_TRUE(frame.get());
1241 EXPECT_NE(0, query_id);
1242
1243 std::string value;
1244 int index = 0;
1245 EXPECT_TRUE(SplitIDString(request, &value, &index));
1246
1247 TestQuery& query = test_query_vector_[index];
1248
1249 if (IsPersistent(query.type))
1250 EXPECT_TRUE(persistent);
1251 else
1252 EXPECT_FALSE(persistent);
1253
1254 // Verify expected request.
1255 EXPECT_STREQ(kMultiQueryRequest, value.c_str()) << index;
1256
1257 // Verify that call order is correct.
1258 EXPECT_FALSE(query.got_query) << index;
1259 EXPECT_FALSE(query.got_query_canceled) << index;
1260 EXPECT_FALSE(query.got_success) << index;
1261 EXPECT_FALSE(query.got_error) << index;
1262
1263 query.got_query.yes();
1264
1265 query.browser_id = browser->GetIdentifier();
1266 query.frame_id = frame->GetIdentifier();
1267 query.is_main_frame = frame->IsMain();
1268
1269 if (query.type == SUCCESS) {
1270 // Send the single success response.
1271 callback->Success(GetIDString(kMultiQueryResponse, index));
1272 } else if (IsPersistent(query.type)) {
1273 // Send the required number of successful responses.
1274 const std::string& response = GetIDString(kMultiQueryResponse, index);
1275 for (int i = 0; i < kMultiQueryPersistentResponseCount; ++i)
1276 callback->Success(response);
1277 }
1278
1279 if (WillFail(query.type)) {
1280 // Send the single failure response.
1281 callback->Failure(index, GetIDString(kMultiQueryErrorMessage, index));
1282 }
1283
1284 if (WillCancel(query.type)) {
1285 // Hold onto the callback until the query is canceled.
1286 query.query_id = query_id;
1287 query.callback = callback;
1288 }
1289
1290 // PERSISTENT_AUTOCANCEL will call OnReceiveCompleted once the success
1291 // notification is received.
1292 if (query.type != PERSISTENT_AUTOCANCEL)
1293 OnReceiveCompleted(query.type);
1294
1295 return true;
1296 }
1297
OnQueryCanceled(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,int64 query_id)1298 void OnQueryCanceled(CefRefPtr<CefBrowser> browser,
1299 CefRefPtr<CefFrame> frame,
1300 int64 query_id) override {
1301 EXPECT_TRUE(finalized_);
1302 EXPECT_UI_THREAD();
1303
1304 if (!running_)
1305 running_ = true;
1306
1307 EXPECT_TRUE(browser.get());
1308 EXPECT_TRUE(frame.get());
1309 EXPECT_NE(0, query_id);
1310
1311 bool found = false;
1312 for (size_t i = 0; i < test_query_vector_.size(); ++i) {
1313 TestQuery& query = test_query_vector_[i];
1314 if (query.query_id == query_id) {
1315 // Verify that browser and frame are the same.
1316 EXPECT_EQ(query.browser_id, browser->GetIdentifier()) << i;
1317 if (query.is_main_frame) {
1318 EXPECT_TRUE(frame->IsMain()) << i;
1319 } else {
1320 EXPECT_FALSE(frame->IsMain()) << i;
1321 EXPECT_EQ(query.frame_id, frame->GetIdentifier()) << i;
1322 }
1323
1324 // Verify a successful/expected result.
1325 EXPECT_TRUE(WillCancel(query.type)) << i;
1326 EXPECT_TRUE(query.callback.get()) << i;
1327
1328 // Release the callback.
1329 query.callback = nullptr;
1330
1331 // Verify that call order is correct.
1332 EXPECT_TRUE(query.got_query) << i;
1333
1334 if (query.type == CANCEL || query.type == AUTOCANCEL) {
1335 // No JavaScript onSuccess callback executes.
1336 EXPECT_FALSE(query.got_success) << i;
1337 } else {
1338 // JavaScript onSuccess does execute before cancellation.
1339 EXPECT_TRUE(query.got_success) << i;
1340 }
1341
1342 query.got_query_canceled.yes();
1343
1344 if (will_cancel_by_removing_handler_) {
1345 // There's a race between OnQueryCanceled and OnNotification. Only
1346 // call OnQueryCompleted a single time.
1347 if (query.got_error)
1348 OnQueryCompleted(query.type);
1349 } else {
1350 EXPECT_FALSE(query.got_error) << i;
1351
1352 // Cancellation is always completion.
1353 OnQueryCompleted(query.type);
1354 }
1355
1356 found = true;
1357 break;
1358 }
1359 }
1360 EXPECT_TRUE(found);
1361 }
1362
1363 // Asserts that all queries have completed.
AssertAllComplete() const1364 void AssertAllComplete() const {
1365 EXPECT_TRUE(finalized_);
1366 EXPECT_FALSE(running_);
1367 EXPECT_UI_THREAD();
1368
1369 for (size_t i = 0; i < test_query_vector_.size(); ++i) {
1370 const TestQuery& query = test_query_vector_[i];
1371 EXPECT_TRUE(query.got_query) << i;
1372
1373 if (WillCancel(query.type))
1374 EXPECT_TRUE(query.got_query_canceled) << i;
1375 else
1376 EXPECT_FALSE(query.got_query_canceled) << i;
1377
1378 if (WillNotify(query.type))
1379 EXPECT_TRUE(query.got_success) << i;
1380 else
1381 EXPECT_FALSE(query.got_success) << i;
1382
1383 if (IsAuto(query.type) && will_cancel_by_removing_handler_)
1384 EXPECT_TRUE(query.got_error);
1385 else
1386 EXPECT_FALSE(query.got_error);
1387
1388 EXPECT_FALSE(query.callback.get()) << i;
1389 }
1390 }
1391
1392 // Returns true if all manual queries have completed.
IsManualComplete() const1393 bool IsManualComplete() const {
1394 EXPECT_TRUE(finalized_);
1395 EXPECT_UI_THREAD();
1396
1397 return (manual_complete_count_ == manual_total_);
1398 }
1399
1400 // Returns true if all queries have completed.
IsAllComplete() const1401 bool IsAllComplete() const {
1402 EXPECT_TRUE(finalized_);
1403 EXPECT_UI_THREAD();
1404
1405 return (manual_complete_count_ + auto_complete_count_ ==
1406 static_cast<int>(test_query_vector_.size()));
1407 }
1408
HasAutoQueries() const1409 bool HasAutoQueries() const {
1410 return (manual_total_ != static_cast<int>(test_query_vector_.size()));
1411 }
1412
1413 private:
1414 struct TestQuery {
TestQuery__anon5aaa418e0611::MultiQueryManager::TestQuery1415 explicit TestQuery(TestType test_type)
1416 : type(test_type),
1417 browser_id(0),
1418 frame_id(0),
1419 is_main_frame(false),
1420 query_id(0) {}
1421
1422 TestType type;
1423
1424 // Set in OnQuery and verified in OnNotify or OnQueryCanceled.
1425 int browser_id;
1426 int64 frame_id;
1427 bool is_main_frame;
1428
1429 // Used when a query is canceled.
1430 int64 query_id;
1431 CefRefPtr<Callback> callback;
1432
1433 TrackCallback got_query;
1434 TrackCallback got_query_canceled;
1435 TrackCallback got_success;
1436 TrackCallback got_error;
1437 };
1438
1439 class NotifyTask : public CefTask {
1440 public:
NotifyTask(base::WeakPtr<MultiQueryManager> weak_ptr,bool notify_all)1441 NotifyTask(base::WeakPtr<MultiQueryManager> weak_ptr, bool notify_all)
1442 : weak_ptr_(weak_ptr), notify_all_(notify_all) {}
1443
Execute()1444 void Execute() override {
1445 if (weak_ptr_) {
1446 if (notify_all_)
1447 weak_ptr_->NotifyAllQueriesCompleted();
1448 else
1449 weak_ptr_->NotifyManualQueriesCompleted();
1450 }
1451 }
1452
1453 private:
1454 base::WeakPtr<MultiQueryManager> weak_ptr_;
1455 const bool notify_all_;
1456
1457 IMPLEMENT_REFCOUNTING(NotifyTask);
1458 };
1459
IsAuto(TestType type)1460 static bool IsAuto(TestType type) {
1461 return (type == AUTOCANCEL || type == PERSISTENT_AUTOCANCEL);
1462 }
1463
IsPersistent(TestType type)1464 static bool IsPersistent(TestType type) {
1465 return (type == PERSISTENT_SUCCESS || type == PERSISTENT_FAILURE ||
1466 type == PERSISTENT_AUTOCANCEL);
1467 }
1468
WillFail(TestType type)1469 static bool WillFail(TestType type) {
1470 return (type == FAILURE || type == PERSISTENT_FAILURE);
1471 }
1472
WillCancel(TestType type)1473 static bool WillCancel(TestType type) {
1474 return (type == PERSISTENT_SUCCESS || type == CANCEL ||
1475 type == AUTOCANCEL || type == PERSISTENT_AUTOCANCEL);
1476 }
1477
WillNotify(TestType type)1478 static bool WillNotify(TestType type) {
1479 return (type == SUCCESS || type == PERSISTENT_SUCCESS || type == FAILURE ||
1480 type == PERSISTENT_FAILURE || type == PERSISTENT_AUTOCANCEL);
1481 }
1482
OnReceiveCompleted(TestType type)1483 void OnReceiveCompleted(TestType type) {
1484 const int total_count = static_cast<int>(test_query_vector_.size());
1485 if (++received_count_ == total_count && manual_total_ == 0) {
1486 // There aren't any manual queries so notify here.
1487 CefPostTask(TID_UI,
1488 new NotifyTask(weak_ptr_factory_.GetWeakPtr(), false));
1489 }
1490 }
1491
OnQueryCompleted(TestType type)1492 void OnQueryCompleted(TestType type) {
1493 const int total_count = static_cast<int>(test_query_vector_.size());
1494 EXPECT_LT(manual_complete_count_ + auto_complete_count_, total_count);
1495 EXPECT_LE(manual_complete_count_, manual_total_);
1496
1497 const bool is_auto = IsAuto(type);
1498 if (is_auto)
1499 auto_complete_count_++;
1500 else if (++manual_complete_count_ == manual_total_) {
1501 CefPostTask(TID_UI,
1502 new NotifyTask(weak_ptr_factory_.GetWeakPtr(), false));
1503 }
1504
1505 if (auto_complete_count_ + manual_complete_count_ == total_count) {
1506 running_ = false;
1507 CefPostTask(TID_UI, new NotifyTask(weak_ptr_factory_.GetWeakPtr(), true));
1508 }
1509 }
1510
NotifyManualQueriesCompleted()1511 void NotifyManualQueriesCompleted() {
1512 if (observer_set_.empty())
1513 return;
1514
1515 // Use a copy of the set in case an Observer is removed while we're
1516 // iterating.
1517 ObserverSet observer_set = observer_set_;
1518
1519 ObserverSet::const_iterator it = observer_set.begin();
1520 for (; it != observer_set.end(); ++it) {
1521 (*it)->OnManualQueriesCompleted(this);
1522 }
1523 }
1524
NotifyAllQueriesCompleted()1525 void NotifyAllQueriesCompleted() {
1526 if (observer_set_.empty())
1527 return;
1528
1529 // Use a copy of the set in case an Observer is removed while we're
1530 // iterating.
1531 ObserverSet observer_set = observer_set_;
1532
1533 ObserverSet::const_iterator it = observer_set.begin();
1534 for (; it != observer_set.end(); ++it) {
1535 (*it)->OnAllQueriesCompleted(this);
1536 }
1537 }
1538
GetQueryHTML(const int index,const TestQuery & query) const1539 std::string GetQueryHTML(const int index, const TestQuery& query) const {
1540 const std::string& request_id_var =
1541 GetIDString(kMultiQueryRequestId, index);
1542 const std::string& repeat_ct_var = GetIDString(kMultiQueryRepeatCt, index);
1543 const std::string& request_val =
1544 GetIDString(std::string(kMultiQueryRequest) + ":", index);
1545 const std::string& success_val =
1546 GetIDString(std::string(kMultiQuerySuccess) + ":", index);
1547 const std::string& error_val =
1548 GetIDString(std::string(kMultiQueryError) + ":", index);
1549
1550 std::string html;
1551
1552 const bool persistent = IsPersistent(query.type);
1553
1554 if (persistent)
1555 html += "var " + repeat_ct_var + " = 0;\n";
1556
1557 html += "var " + request_id_var +
1558 " = window.mrtQuery({\n"
1559 " request: '" +
1560 request_val +
1561 "',\n"
1562 " persistent: " +
1563 (persistent ? "true" : "false") + ",\n";
1564
1565 if (query.type == SUCCESS) {
1566 const std::string& response_val = GetIDString(kMultiQueryResponse, index);
1567
1568 html +=
1569 " onSuccess: function(response) {\n"
1570 " if (response == '" +
1571 response_val +
1572 "')\n"
1573 " window.mrtNotify('" +
1574 success_val +
1575 "');\n"
1576 " else\n"
1577 " window.mrtNotify('" +
1578 error_val +
1579 "');\n"
1580 " },\n"
1581 " onFailure: function(error_code, error_message) {\n"
1582 " window.mrtNotify('" +
1583 error_val +
1584 "');\n"
1585 " }\n";
1586 } else if (query.type == FAILURE) {
1587 const std::string& error_code_val = GetIntString(index);
1588 const std::string& error_message_val =
1589 GetIDString(kMultiQueryErrorMessage, index);
1590
1591 html +=
1592 " onSuccess: function(response) {\n"
1593 " window.mrtNotify('" +
1594 error_val +
1595 "');\n"
1596 " },\n"
1597 " onFailure: function(error_code, error_message) {\n"
1598 " if (error_code == " +
1599 error_code_val + " && error_message == '" + error_message_val +
1600 "')\n"
1601 " window.mrtNotify('" +
1602 success_val +
1603 "');\n"
1604 " else\n"
1605 " window.mrtNotify('" +
1606 error_val +
1607 "');\n"
1608 " }\n";
1609 } else if (query.type == PERSISTENT_SUCCESS ||
1610 query.type == PERSISTENT_AUTOCANCEL) {
1611 const std::string& response_val = GetIDString(kMultiQueryResponse, index);
1612 const std::string& repeat_ct =
1613 GetIntString(kMultiQueryPersistentResponseCount);
1614
1615 html +=
1616 " onSuccess: function(response) {\n"
1617 " if (response == '" +
1618 response_val +
1619 "') {\n"
1620 // Should get repeat_ct number of successful responses.
1621 " if (++" +
1622 repeat_ct_var + " == " + repeat_ct +
1623 ") {\n"
1624 " window.mrtNotify('" +
1625 success_val + "');\n";
1626
1627 if (query.type == PERSISTENT_SUCCESS) {
1628 // Manually cancel the request.
1629 html += " window.mrtQueryCancel(" + request_id_var + ");\n";
1630 }
1631
1632 html +=
1633 " }\n"
1634 " } else {\n"
1635 " window.mrtNotify('" +
1636 error_val +
1637 "');\n"
1638 " }\n"
1639 " },\n"
1640 " onFailure: function(error_code, error_message) {\n"
1641 " window.mrtNotify('" +
1642 error_val +
1643 "');\n"
1644 " }\n";
1645 } else if (query.type == PERSISTENT_FAILURE) {
1646 const std::string& error_code_val = GetIntString(index);
1647 const std::string& error_message_val =
1648 GetIDString(kMultiQueryErrorMessage, index);
1649 const std::string& repeat_ct =
1650 GetIntString(kMultiQueryPersistentResponseCount);
1651
1652 html +=
1653 " onSuccess: function(response) {\n"
1654 // Should get some successful responses before failure.
1655 " if (++" +
1656 repeat_ct_var + " > " + repeat_ct +
1657 ") {\n"
1658 " window.mrtNotify('" +
1659 error_val +
1660 "');\n"
1661 " }\n"
1662 " },\n"
1663 " onFailure: function(error_code, error_message) {\n"
1664 " if (error_code == " +
1665 error_code_val + " && error_message == '" + error_message_val +
1666 "'"
1667 " && " +
1668 repeat_ct_var + " == " + repeat_ct +
1669 ")\n"
1670 " window.mrtNotify('" +
1671 success_val +
1672 "');\n"
1673 " else\n"
1674 " window.mrtNotify('" +
1675 error_val +
1676 "');\n"
1677 " }\n";
1678 } else if (query.type == CANCEL || query.type == AUTOCANCEL) {
1679 html +=
1680 " onSuccess: function(response) {\n"
1681 " window.mrtNotify('" +
1682 error_val +
1683 "');\n"
1684 " },\n"
1685 " onFailure: function(error_code, error_message) {\n"
1686 " window.mrtNotify('" +
1687 error_val +
1688 "');\n"
1689 " }\n";
1690 }
1691
1692 html += "});\n";
1693
1694 return html;
1695 }
1696
GetCancelHTML(const int index,const TestQuery & query) const1697 std::string GetCancelHTML(const int index, const TestQuery& query) const {
1698 const std::string& request_id_var =
1699 GetIDString(kMultiQueryRequestId, index);
1700 return "window.mrtQueryCancel(" + request_id_var + ");\n";
1701 }
1702
GetIDString(const std::string & prefix,int index) const1703 std::string GetIDString(const std::string& prefix, int index) const {
1704 EXPECT_TRUE(!prefix.empty());
1705 std::stringstream ss;
1706 ss << prefix << GetIDFromIndex(index);
1707 return ss.str();
1708 }
1709
SplitIDString(const std::string & str,std::string * value,int * index) const1710 bool SplitIDString(const std::string& str,
1711 std::string* value,
1712 int* index) const {
1713 size_t pos = str.find(':');
1714 if (pos != std::string::npos) {
1715 *value = str.substr(0, pos);
1716 *index = GetIndexFromID(atoi(str.substr(pos + 1).c_str()));
1717 return (*index >= 0 &&
1718 *index < static_cast<int>(test_query_vector_.size()));
1719 }
1720
1721 return false;
1722 }
1723
GetIntString(int val) const1724 std::string GetIntString(int val) const {
1725 std::stringstream ss;
1726 ss << val;
1727 return ss.str();
1728 }
1729
GetIDFromIndex(int index) const1730 int GetIDFromIndex(int index) const { return id_offset_ + index; }
GetIndexFromID(int id) const1731 int GetIndexFromID(int id) const { return id - id_offset_; }
1732
1733 const std::string label_;
1734 const bool synchronous_;
1735 const int id_offset_;
1736
1737 typedef std::vector<TestQuery> TestQueryVector;
1738 TestQueryVector test_query_vector_;
1739
1740 typedef std::set<Observer*> ObserverSet;
1741 ObserverSet observer_set_;
1742
1743 // Set to true after all queries have been added.
1744 bool finalized_;
1745 // Set to true while queries are pending.
1746 bool running_;
1747
1748 // Total number of queries that will manually complete.
1749 int manual_total_;
1750
1751 // Number of queries that have been received.
1752 int received_count_;
1753
1754 // Number of queries that have completed successfully.
1755 int manual_complete_count_;
1756 int auto_complete_count_;
1757
1758 // If true any pending queries will receive an onFailure callback in addition
1759 // to be canceled.
1760 bool will_cancel_by_removing_handler_;
1761
1762 // Should always be the last member.
1763 base::WeakPtrFactory<MultiQueryManager> weak_ptr_factory_;
1764 };
1765
MakeTestQueries(MultiQueryManager * manager,bool some,int many_count=200)1766 void MakeTestQueries(MultiQueryManager* manager,
1767 bool some,
1768 int many_count = 200) {
1769 if (some) {
1770 // Test some queries of arbitrary types.
1771 // Use a hard-coded list so the behavior is deterministic across test runs.
1772 MultiQueryManager::TestType types[] = {
1773 MultiQueryManager::PERSISTENT_AUTOCANCEL,
1774 MultiQueryManager::SUCCESS,
1775 MultiQueryManager::AUTOCANCEL,
1776 MultiQueryManager::PERSISTENT_FAILURE,
1777 MultiQueryManager::CANCEL,
1778 MultiQueryManager::FAILURE,
1779 MultiQueryManager::AUTOCANCEL,
1780 MultiQueryManager::SUCCESS,
1781 MultiQueryManager::PERSISTENT_SUCCESS,
1782 MultiQueryManager::SUCCESS,
1783 MultiQueryManager::PERSISTENT_AUTOCANCEL,
1784 MultiQueryManager::CANCEL,
1785 MultiQueryManager::PERSISTENT_SUCCESS,
1786 MultiQueryManager::FAILURE,
1787 };
1788 for (size_t i = 0; i < sizeof(types) / sizeof(types[0]); ++i) {
1789 manager->AddTestQuery(types[i]);
1790 }
1791 } else {
1792 // Test every type of query.
1793 for (int i = 0; i < many_count; ++i) {
1794 MultiQueryManager::TestType type = MultiQueryManager::SUCCESS;
1795 switch (i % 7) {
1796 case 0:
1797 type = MultiQueryManager::SUCCESS;
1798 break;
1799 case 1:
1800 type = MultiQueryManager::FAILURE;
1801 break;
1802 case 2:
1803 type = MultiQueryManager::PERSISTENT_SUCCESS;
1804 break;
1805 case 3:
1806 type = MultiQueryManager::PERSISTENT_FAILURE;
1807 break;
1808 case 4:
1809 type = MultiQueryManager::CANCEL;
1810 break;
1811 case 5:
1812 type = MultiQueryManager::AUTOCANCEL;
1813 break;
1814 case 6:
1815 type = MultiQueryManager::PERSISTENT_AUTOCANCEL;
1816 break;
1817 }
1818 manager->AddTestQuery(type);
1819 }
1820 }
1821 manager->Finalize();
1822 }
1823
1824 // Test multiple queries in a single page load with a single frame.
1825 class MultiQuerySingleFrameTestHandler : public SingleLoadTestHandler,
1826 public MultiQueryManager::Observer {
1827 public:
1828 enum CancelType {
1829 CANCEL_BY_NAVIGATION,
1830 CANCEL_BY_REMOVING_HANDLER,
1831 CANCEL_BY_CLOSING_BROWSER,
1832 };
1833
MultiQuerySingleFrameTestHandler(bool synchronous,CancelType cancel_type=CANCEL_BY_NAVIGATION)1834 MultiQuerySingleFrameTestHandler(
1835 bool synchronous,
1836 CancelType cancel_type = CANCEL_BY_NAVIGATION)
1837 : manager_(std::string(), synchronous), cancel_type_(cancel_type) {
1838 manager_.AddObserver(this);
1839 }
1840
GetMainHTML()1841 std::string GetMainHTML() override { return manager_.GetHTML(true, true); }
1842
OnNotify(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,const std::string & message)1843 void OnNotify(CefRefPtr<CefBrowser> browser,
1844 CefRefPtr<CefFrame> frame,
1845 const std::string& message) override {
1846 AssertMainBrowser(browser);
1847 AssertMainFrame(frame);
1848
1849 manager_.OnNotify(browser, frame, message);
1850 }
1851
OnQuery(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,int64 query_id,const CefString & request,bool persistent,CefRefPtr<Callback> callback)1852 bool OnQuery(CefRefPtr<CefBrowser> browser,
1853 CefRefPtr<CefFrame> frame,
1854 int64 query_id,
1855 const CefString& request,
1856 bool persistent,
1857 CefRefPtr<Callback> callback) override {
1858 AssertMainBrowser(browser);
1859 AssertMainFrame(frame);
1860
1861 return manager_.OnQuery(browser, frame, query_id, request, persistent,
1862 callback);
1863 }
1864
OnQueryCanceled(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,int64 query_id)1865 void OnQueryCanceled(CefRefPtr<CefBrowser> browser,
1866 CefRefPtr<CefFrame> frame,
1867 int64 query_id) override {
1868 AssertMainBrowser(browser);
1869 AssertMainFrame(frame);
1870
1871 manager_.OnQueryCanceled(browser, frame, query_id);
1872 }
1873
OnManualQueriesCompleted(MultiQueryManager * manager)1874 void OnManualQueriesCompleted(MultiQueryManager* manager) override {
1875 EXPECT_EQ(manager, &manager_);
1876 if (manager_.HasAutoQueries()) {
1877 if (cancel_type_ == CANCEL_BY_NAVIGATION) {
1878 // Navigate somewhere else to terminate the auto queries.
1879 GetBrowser()->GetMainFrame()->LoadURL(std::string(kTestDomain1) +
1880 "cancel.html");
1881 } else if (cancel_type_ == CANCEL_BY_REMOVING_HANDLER) {
1882 // Change the expected behavior in the manager.
1883 manager_.WillCancelByRemovingHandler();
1884 GetRouter()->RemoveHandler(this);
1885 // All queries should be immediately canceled.
1886 AssertQueryCount(nullptr, nullptr, 0);
1887 } else if (cancel_type_ == CANCEL_BY_CLOSING_BROWSER) {
1888 // Change the expected behavior in the handler.
1889 SetSignalCompletionWhenAllBrowsersClose(false);
1890 CloseBrowser(GetBrowser(), false);
1891 }
1892 }
1893 }
1894
OnAllQueriesCompleted(MultiQueryManager * manager)1895 void OnAllQueriesCompleted(MultiQueryManager* manager) override {
1896 EXPECT_EQ(manager, &manager_);
1897
1898 // All queries should be canceled.
1899 AssertQueryCount(nullptr, nullptr, 0);
1900
1901 DestroyTest();
1902
1903 if (!SignalCompletionWhenAllBrowsersClose()) {
1904 // Complete asynchronously so the call stack has a chance to unwind.
1905 CefPostTask(
1906 TID_UI,
1907 base::Bind(&MultiQuerySingleFrameTestHandler::TestComplete, this));
1908 }
1909 }
1910
DestroyTest()1911 void DestroyTest() override {
1912 manager_.AssertAllComplete();
1913 TestHandler::DestroyTest();
1914 }
1915
GetManager()1916 MultiQueryManager* GetManager() { return &manager_; }
1917
1918 private:
1919 MultiQueryManager manager_;
1920 const CancelType cancel_type_;
1921 };
1922
1923 } // namespace
1924
1925 #define MULTI_QUERY_SINGLE_FRAME_TYPE_TEST(name, type, synchronous) \
1926 TEST(MessageRouterTest, name) { \
1927 CefRefPtr<MultiQuerySingleFrameTestHandler> handler = \
1928 new MultiQuerySingleFrameTestHandler(synchronous); \
1929 MultiQueryManager* manager = handler->GetManager(); \
1930 manager->AddTestQuery(MultiQueryManager::type); \
1931 manager->Finalize(); \
1932 handler->ExecuteTest(); \
1933 ReleaseAndWaitForDestructor(handler); \
1934 }
1935
1936 // Test the query types individually.
MULTI_QUERY_SINGLE_FRAME_TYPE_TEST(MultiQuerySingleFrameSyncSuccess,SUCCESS,true)1937 MULTI_QUERY_SINGLE_FRAME_TYPE_TEST(MultiQuerySingleFrameSyncSuccess,
1938 SUCCESS,
1939 true)
1940 MULTI_QUERY_SINGLE_FRAME_TYPE_TEST(MultiQuerySingleFrameAsyncSuccess,
1941 SUCCESS,
1942 false)
1943 MULTI_QUERY_SINGLE_FRAME_TYPE_TEST(MultiQuerySingleFrameSyncFailure,
1944 FAILURE,
1945 true)
1946 MULTI_QUERY_SINGLE_FRAME_TYPE_TEST(MultiQuerySingleFrameAsyncFailure,
1947 FAILURE,
1948 false)
1949 MULTI_QUERY_SINGLE_FRAME_TYPE_TEST(MultiQuerySingleFrameSyncPersistentSuccess,
1950 PERSISTENT_SUCCESS,
1951 true)
1952 MULTI_QUERY_SINGLE_FRAME_TYPE_TEST(MultiQuerySingleFrameAsyncPersistentSuccess,
1953 PERSISTENT_SUCCESS,
1954 false)
1955 MULTI_QUERY_SINGLE_FRAME_TYPE_TEST(MultiQuerySingleFrameSyncPersistentFailure,
1956 PERSISTENT_FAILURE,
1957 true)
1958 MULTI_QUERY_SINGLE_FRAME_TYPE_TEST(MultiQuerySingleFrameAsyncPersistentFailure,
1959 PERSISTENT_FAILURE,
1960 false)
1961 MULTI_QUERY_SINGLE_FRAME_TYPE_TEST(MultiQuerySingleFrameCancel, CANCEL, true)
1962 MULTI_QUERY_SINGLE_FRAME_TYPE_TEST(MultiQuerySingleFrameAutoCancel,
1963 AUTOCANCEL,
1964 true)
1965 MULTI_QUERY_SINGLE_FRAME_TYPE_TEST(MultiQuerySingleFramePersistentAutoCancel,
1966 PERSISTENT_AUTOCANCEL,
1967 true)
1968
1969 // Test that one frame can run some queries successfully in a synchronous
1970 // manner.
1971 TEST(MessageRouterTest, MultiQuerySingleFrameSyncSome) {
1972 CefRefPtr<MultiQuerySingleFrameTestHandler> handler =
1973 new MultiQuerySingleFrameTestHandler(true);
1974 MakeTestQueries(handler->GetManager(), true);
1975 handler->ExecuteTest();
1976 ReleaseAndWaitForDestructor(handler);
1977 }
1978
1979 // Test that one frame can run some queries successfully in an asynchronous
1980 // manner.
TEST(MessageRouterTest,MultiQuerySingleFrameAsyncSome)1981 TEST(MessageRouterTest, MultiQuerySingleFrameAsyncSome) {
1982 CefRefPtr<MultiQuerySingleFrameTestHandler> handler =
1983 new MultiQuerySingleFrameTestHandler(false);
1984 MakeTestQueries(handler->GetManager(), true);
1985 handler->ExecuteTest();
1986 ReleaseAndWaitForDestructor(handler);
1987 }
1988
1989 // Test that one frame can run many queries successfully in a synchronous
1990 // manner.
TEST(MessageRouterTest,MultiQuerySingleFrameSyncMany)1991 TEST(MessageRouterTest, MultiQuerySingleFrameSyncMany) {
1992 CefRefPtr<MultiQuerySingleFrameTestHandler> handler =
1993 new MultiQuerySingleFrameTestHandler(true);
1994 MakeTestQueries(handler->GetManager(), false);
1995 handler->ExecuteTest();
1996 ReleaseAndWaitForDestructor(handler);
1997 }
1998
1999 // Test that one frame can run many queries successfully in an asynchronous
2000 // manner.
TEST(MessageRouterTest,MultiQuerySingleFrameAsyncMany)2001 TEST(MessageRouterTest, MultiQuerySingleFrameAsyncMany) {
2002 CefRefPtr<MultiQuerySingleFrameTestHandler> handler =
2003 new MultiQuerySingleFrameTestHandler(false);
2004 MakeTestQueries(handler->GetManager(), false);
2005 handler->ExecuteTest();
2006 ReleaseAndWaitForDestructor(handler);
2007 }
2008
2009 // Test that pending queries can be canceled by removing the handler.
TEST(MessageRouterTest,MultiQuerySingleFrameCancelByRemovingHandler)2010 TEST(MessageRouterTest, MultiQuerySingleFrameCancelByRemovingHandler) {
2011 CefRefPtr<MultiQuerySingleFrameTestHandler> handler =
2012 new MultiQuerySingleFrameTestHandler(
2013 false, MultiQuerySingleFrameTestHandler::CANCEL_BY_REMOVING_HANDLER);
2014 MakeTestQueries(handler->GetManager(), false);
2015 handler->ExecuteTest();
2016 ReleaseAndWaitForDestructor(handler);
2017 }
2018
2019 // Test that pending queries can be canceled by closing the browser.
TEST(MessageRouterTest,MultiQuerySingleFrameCancelByClosingBrowser)2020 TEST(MessageRouterTest, MultiQuerySingleFrameCancelByClosingBrowser) {
2021 CefRefPtr<MultiQuerySingleFrameTestHandler> handler =
2022 new MultiQuerySingleFrameTestHandler(
2023 false, MultiQuerySingleFrameTestHandler::CANCEL_BY_CLOSING_BROWSER);
2024 MakeTestQueries(handler->GetManager(), false);
2025 handler->ExecuteTest();
2026 ReleaseAndWaitForDestructor(handler);
2027 }
2028
2029 namespace {
2030
2031 // Test multiple handlers.
2032 class MultiQueryMultiHandlerTestHandler : public SingleLoadTestHandler,
2033 public MultiQueryManager::Observer {
2034 public:
2035 class Handler : public CefMessageRouterBrowserSide::Handler {
2036 public:
Handler(MultiQueryMultiHandlerTestHandler * test_handler,int index)2037 Handler(MultiQueryMultiHandlerTestHandler* test_handler, int index)
2038 : test_handler_(test_handler), index_(index), query_id_(0) {}
2039
OnQuery(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,int64 query_id,const CefString & request,bool persistent,CefRefPtr<Callback> callback)2040 bool OnQuery(CefRefPtr<CefBrowser> browser,
2041 CefRefPtr<CefFrame> frame,
2042 int64 query_id,
2043 const CefString& request,
2044 bool persistent,
2045 CefRefPtr<Callback> callback) override {
2046 // Each handler only handles a single request.
2047 std::stringstream ss;
2048 ss << kMultiQueryRequest << ":" << index_;
2049 const std::string& handled_request = ss.str();
2050 if (request != handled_request)
2051 return false;
2052
2053 // Verify that handlers are called in the correct order.
2054 if (index_ == 0) {
2055 EXPECT_FALSE(test_handler_->got_query0_);
2056 EXPECT_FALSE(test_handler_->got_query1_);
2057 EXPECT_FALSE(test_handler_->got_query2_);
2058
2059 test_handler_->got_query0_.yes();
2060 } else if (index_ == 1) {
2061 EXPECT_TRUE(test_handler_->got_query0_);
2062 EXPECT_FALSE(test_handler_->got_query1_);
2063 EXPECT_FALSE(test_handler_->got_query2_);
2064
2065 test_handler_->got_query1_.yes();
2066 } else if (index_ == 2) {
2067 EXPECT_TRUE(test_handler_->got_query0_);
2068 EXPECT_TRUE(test_handler_->got_query1_);
2069 EXPECT_FALSE(test_handler_->got_query2_);
2070
2071 test_handler_->got_query2_.yes();
2072 }
2073
2074 query_id_ = query_id;
2075 return test_handler_->OnQuery(browser, frame, query_id, request,
2076 persistent, callback);
2077 }
2078
OnQueryCanceled(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,int64 query_id)2079 void OnQueryCanceled(CefRefPtr<CefBrowser> browser,
2080 CefRefPtr<CefFrame> frame,
2081 int64 query_id) override {
2082 // Verify that the correct handler is called for cancellation.
2083 EXPECT_EQ(query_id_, query_id);
2084
2085 if (index_ == 0) {
2086 EXPECT_FALSE(test_handler_->got_query_canceled0_);
2087 test_handler_->got_query_canceled0_.yes();
2088 } else if (index_ == 1) {
2089 EXPECT_FALSE(test_handler_->got_query_canceled1_);
2090 test_handler_->got_query_canceled1_.yes();
2091 } else if (index_ == 2) {
2092 EXPECT_FALSE(test_handler_->got_query_canceled2_);
2093 test_handler_->got_query_canceled2_.yes();
2094 }
2095
2096 test_handler_->OnQueryCanceled(browser, frame, query_id);
2097 }
2098
2099 private:
2100 MultiQueryMultiHandlerTestHandler* test_handler_;
2101 const int index_;
2102 int query_id_;
2103 };
2104
MultiQueryMultiHandlerTestHandler(bool synchronous,bool cancel_by_removing_handler)2105 MultiQueryMultiHandlerTestHandler(bool synchronous,
2106 bool cancel_by_removing_handler)
2107 : manager_(std::string(), synchronous, 0),
2108 handler0_(this, 0),
2109 handler1_(this, 1),
2110 handler2_(this, 2),
2111 cancel_by_removing_handler_(cancel_by_removing_handler) {
2112 manager_.AddObserver(this);
2113
2114 // Each handler will handle one of the queries.
2115 manager_.AddTestQuery(MultiQueryManager::PERSISTENT_AUTOCANCEL);
2116 manager_.AddTestQuery(MultiQueryManager::PERSISTENT_AUTOCANCEL);
2117 manager_.AddTestQuery(MultiQueryManager::PERSISTENT_AUTOCANCEL);
2118 manager_.Finalize();
2119 }
2120
GetMainHTML()2121 std::string GetMainHTML() override { return manager_.GetHTML(true, true); }
2122
OnNotify(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,const std::string & message)2123 void OnNotify(CefRefPtr<CefBrowser> browser,
2124 CefRefPtr<CefFrame> frame,
2125 const std::string& message) override {
2126 AssertMainBrowser(browser);
2127 AssertMainFrame(frame);
2128
2129 manager_.OnNotify(browser, frame, message);
2130 }
2131
OnQuery(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,int64 query_id,const CefString & request,bool persistent,CefRefPtr<Callback> callback)2132 bool OnQuery(CefRefPtr<CefBrowser> browser,
2133 CefRefPtr<CefFrame> frame,
2134 int64 query_id,
2135 const CefString& request,
2136 bool persistent,
2137 CefRefPtr<Callback> callback) override {
2138 AssertMainBrowser(browser);
2139 AssertMainFrame(frame);
2140
2141 return manager_.OnQuery(browser, frame, query_id, request, persistent,
2142 callback);
2143 }
2144
OnQueryCanceled(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,int64 query_id)2145 void OnQueryCanceled(CefRefPtr<CefBrowser> browser,
2146 CefRefPtr<CefFrame> frame,
2147 int64 query_id) override {
2148 AssertMainBrowser(browser);
2149 AssertMainFrame(frame);
2150
2151 manager_.OnQueryCanceled(browser, frame, query_id);
2152 }
2153
OnManualQueriesCompleted(MultiQueryManager * manager)2154 void OnManualQueriesCompleted(MultiQueryManager* manager) override {
2155 EXPECT_EQ(manager, &manager_);
2156
2157 EXPECT_TRUE(got_query0_);
2158 EXPECT_TRUE(got_query1_);
2159 EXPECT_TRUE(got_query2_);
2160 EXPECT_FALSE(got_query_canceled0_);
2161 EXPECT_FALSE(got_query_canceled1_);
2162 EXPECT_FALSE(got_query_canceled2_);
2163
2164 EXPECT_TRUE(manager_.HasAutoQueries());
2165
2166 CefRefPtr<CefMessageRouterBrowserSide> router = GetRouter();
2167
2168 // Remove one handler to cancel a query.
2169
2170 if (cancel_by_removing_handler_) {
2171 manager_.WillCancelByRemovingHandler();
2172
2173 // Each query should be canceled as the handler is removed.
2174 EXPECT_TRUE(router->RemoveHandler(&handler1_));
2175 EXPECT_FALSE(got_query_canceled0_);
2176 EXPECT_TRUE(got_query_canceled1_);
2177 EXPECT_FALSE(got_query_canceled2_);
2178
2179 EXPECT_TRUE(router->RemoveHandler(&handler2_));
2180 EXPECT_FALSE(got_query_canceled0_);
2181 EXPECT_TRUE(got_query_canceled2_);
2182
2183 EXPECT_TRUE(router->RemoveHandler(&handler0_));
2184 EXPECT_TRUE(got_query_canceled0_);
2185 } else {
2186 GetBrowser()->GetMainFrame()->LoadURL(std::string(kTestDomain1) +
2187 "cancel.html");
2188 }
2189 }
2190
OnAllQueriesCompleted(MultiQueryManager * manager)2191 void OnAllQueriesCompleted(MultiQueryManager* manager) override {
2192 EXPECT_EQ(manager, &manager_);
2193
2194 // All queries should be canceled.
2195 AssertQueryCount(nullptr, nullptr, 0);
2196
2197 DestroyTest();
2198 }
2199
DestroyTest()2200 void DestroyTest() override {
2201 EXPECT_TRUE(got_query0_);
2202 EXPECT_TRUE(got_query1_);
2203 EXPECT_TRUE(got_query2_);
2204 EXPECT_TRUE(got_query_canceled0_);
2205 EXPECT_TRUE(got_query_canceled1_);
2206 EXPECT_TRUE(got_query_canceled2_);
2207
2208 manager_.AssertAllComplete();
2209 TestHandler::DestroyTest();
2210 }
2211
2212 protected:
AddHandlers(CefRefPtr<CefMessageRouterBrowserSide> message_router)2213 void AddHandlers(
2214 CefRefPtr<CefMessageRouterBrowserSide> message_router) override {
2215 // OnQuery call order will verify that the first/last ordering works as
2216 // expected.
2217 EXPECT_TRUE(message_router->AddHandler(&handler1_, true));
2218 EXPECT_TRUE(message_router->AddHandler(&handler0_, true));
2219 EXPECT_TRUE(message_router->AddHandler(&handler2_, false));
2220
2221 // Can't add the same handler multiple times.
2222 EXPECT_FALSE(message_router->AddHandler(&handler1_, true));
2223 }
2224
2225 private:
2226 MultiQueryManager manager_;
2227 Handler handler0_;
2228 Handler handler1_;
2229 Handler handler2_;
2230
2231 const bool cancel_by_removing_handler_;
2232
2233 TrackCallback got_query0_;
2234 TrackCallback got_query1_;
2235 TrackCallback got_query2_;
2236
2237 TrackCallback got_query_canceled0_;
2238 TrackCallback got_query_canceled1_;
2239 TrackCallback got_query_canceled2_;
2240 };
2241
2242 } // namespace
2243
2244 // Test that multiple handlers behave correctly.
TEST(MessageRouterTest,MultiQueryMultiHandler)2245 TEST(MessageRouterTest, MultiQueryMultiHandler) {
2246 CefRefPtr<MultiQueryMultiHandlerTestHandler> handler =
2247 new MultiQueryMultiHandlerTestHandler(false, false);
2248 handler->ExecuteTest();
2249 ReleaseAndWaitForDestructor(handler);
2250 }
2251
2252 // Test that multiple handlers behave correctly. Cancel by removing the
2253 // handlers.
TEST(MessageRouterTest,MultiQueryMultiHandlerCancelByRemovingHandler)2254 TEST(MessageRouterTest, MultiQueryMultiHandlerCancelByRemovingHandler) {
2255 CefRefPtr<MultiQueryMultiHandlerTestHandler> handler =
2256 new MultiQueryMultiHandlerTestHandler(false, true);
2257 handler->ExecuteTest();
2258 ReleaseAndWaitForDestructor(handler);
2259 }
2260
2261 namespace {
2262
2263 // Map of managers on a per-URL basis.
2264 class MultiQueryManagerMap : public CefMessageRouterBrowserSide::Handler,
2265 public MultiQueryManager::Observer {
2266 public:
2267 class Observer {
2268 public:
2269 // Called when all manual queries are complete.
OnMapManualQueriesCompleted(MultiQueryManagerMap * map)2270 virtual void OnMapManualQueriesCompleted(MultiQueryManagerMap* map) {}
2271
2272 // Called when all queries are complete.
OnMapAllQueriesCompleted(MultiQueryManagerMap * map)2273 virtual void OnMapAllQueriesCompleted(MultiQueryManagerMap* map) {}
2274
2275 protected:
~Observer()2276 virtual ~Observer() {}
2277 };
2278
MultiQueryManagerMap()2279 MultiQueryManagerMap()
2280 : finalized_(false),
2281 running_(false),
2282 manual_complete_count_(0),
2283 total_complete_count_(0) {}
2284
~MultiQueryManagerMap()2285 virtual ~MultiQueryManagerMap() { RemoveAllManagers(); }
2286
AddObserver(Observer * observer)2287 void AddObserver(Observer* observer) {
2288 EXPECT_FALSE(running_);
2289 observer_set_.insert(observer);
2290 }
2291
RemoveObserver(Observer * observer)2292 void RemoveObserver(Observer* observer) {
2293 EXPECT_FALSE(running_);
2294 EXPECT_TRUE(observer_set_.erase(observer));
2295 }
2296
CreateManager(const std::string & url,bool synchronous)2297 MultiQueryManager* CreateManager(const std::string& url, bool synchronous) {
2298 EXPECT_FALSE(finalized_);
2299
2300 MultiQueryManager* manager = new MultiQueryManager(
2301 url, synchronous, static_cast<int>(manager_map_.size()) * 1000);
2302 manager->AddObserver(this);
2303 all_managers_.push_back(manager);
2304 pending_managers_.push_back(manager);
2305
2306 return manager;
2307 }
2308
Finalize()2309 void Finalize() {
2310 EXPECT_FALSE(finalized_);
2311 finalized_ = true;
2312 }
2313
GetMainHTML() const2314 std::string GetMainHTML() const {
2315 EXPECT_TRUE(finalized_);
2316 EXPECT_FALSE(running_);
2317
2318 std::string html = "<html><body>\n";
2319
2320 for (size_t i = 0; i < all_managers_.size(); ++i) {
2321 const std::string& url = all_managers_[i]->label();
2322 const std::string& name = GetNameForURL(url);
2323 html += "<iframe id=\"" + name + "\" src=\"" + url + "\"></iframe>\n";
2324 }
2325
2326 html += "</body></html>";
2327 return html;
2328 }
2329
OnNotify(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,const std::string & message)2330 void OnNotify(CefRefPtr<CefBrowser> browser,
2331 CefRefPtr<CefFrame> frame,
2332 const std::string& message) {
2333 EXPECT_TRUE(finalized_);
2334 if (!running_)
2335 running_ = true;
2336
2337 MultiQueryManager* manager = GetManager(browser, frame);
2338 manager->OnNotify(browser, frame, message);
2339 }
2340
OnQuery(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,int64 query_id,const CefString & request,bool persistent,CefRefPtr<Callback> callback)2341 bool OnQuery(CefRefPtr<CefBrowser> browser,
2342 CefRefPtr<CefFrame> frame,
2343 int64 query_id,
2344 const CefString& request,
2345 bool persistent,
2346 CefRefPtr<Callback> callback) override {
2347 EXPECT_TRUE(finalized_);
2348 if (!running_)
2349 running_ = true;
2350
2351 MultiQueryManager* manager = GetManager(browser, frame);
2352 return manager->OnQuery(browser, frame, query_id, request, persistent,
2353 callback);
2354 }
2355
OnQueryCanceled(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,int64 query_id)2356 void OnQueryCanceled(CefRefPtr<CefBrowser> browser,
2357 CefRefPtr<CefFrame> frame,
2358 int64 query_id) override {
2359 EXPECT_TRUE(finalized_);
2360 if (!running_)
2361 running_ = true;
2362
2363 MultiQueryManager* manager = GetManager(browser, frame);
2364 manager->OnQueryCanceled(browser, frame, query_id);
2365 }
2366
OnManualQueriesCompleted(MultiQueryManager * manager)2367 void OnManualQueriesCompleted(MultiQueryManager* manager) override {
2368 const int size = static_cast<int>(all_managers_.size());
2369 EXPECT_LT(manual_complete_count_, size);
2370 if (++manual_complete_count_ == size) {
2371 running_ = false;
2372
2373 // Notify observers.
2374 if (!observer_set_.empty()) {
2375 // Use a copy of the set in case an Observer is removed while we're
2376 // iterating.
2377 ObserverSet observer_set = observer_set_;
2378
2379 ObserverSet::const_iterator it = observer_set.begin();
2380 for (; it != observer_set.end(); ++it) {
2381 (*it)->OnMapManualQueriesCompleted(this);
2382 }
2383 }
2384 }
2385 }
2386
OnAllQueriesCompleted(MultiQueryManager * manager)2387 void OnAllQueriesCompleted(MultiQueryManager* manager) override {
2388 const int size = static_cast<int>(all_managers_.size());
2389 EXPECT_LT(total_complete_count_, size);
2390 if (++total_complete_count_ == size) {
2391 running_ = false;
2392
2393 // Notify observers.
2394 if (!observer_set_.empty()) {
2395 // Use a copy of the set in case an Observer is removed while we're
2396 // iterating.
2397 ObserverSet observer_set = observer_set_;
2398
2399 ObserverSet::const_iterator it = observer_set.begin();
2400 for (; it != observer_set.end(); ++it) {
2401 (*it)->OnMapAllQueriesCompleted(this);
2402 }
2403 }
2404 }
2405 }
2406
AllComplete() const2407 bool AllComplete() const {
2408 EXPECT_TRUE(finalized_);
2409
2410 for (size_t i = 0; i < all_managers_.size(); ++i) {
2411 if (!all_managers_[i]->IsAllComplete())
2412 return false;
2413 }
2414 return true;
2415 }
2416
AssertAllComplete() const2417 void AssertAllComplete() const {
2418 EXPECT_TRUE(finalized_);
2419 EXPECT_TRUE(pending_managers_.empty());
2420 EXPECT_FALSE(running_);
2421
2422 for (size_t i = 0; i < all_managers_.size(); ++i) {
2423 all_managers_[i]->AssertAllComplete();
2424 }
2425 }
2426
HasAutoQueries() const2427 bool HasAutoQueries() const {
2428 for (size_t i = 0; i < all_managers_.size(); ++i) {
2429 if (all_managers_[i]->HasAutoQueries())
2430 return true;
2431 }
2432
2433 return false;
2434 }
2435
OnLoadStart(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame)2436 void OnLoadStart(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame) {
2437 if (pending_managers_.empty())
2438 return;
2439
2440 const std::string& expected_url = frame->GetURL();
2441 MultiQueryManager* next_manager = nullptr;
2442
2443 // Find the pending manager that matches the expected URL.
2444 ManagerList::iterator it = pending_managers_.begin();
2445 for (; it != pending_managers_.end(); ++it) {
2446 if ((*it)->label() == expected_url) {
2447 next_manager = *it;
2448 pending_managers_.erase(it);
2449 break;
2450 }
2451 }
2452
2453 EXPECT_TRUE(next_manager);
2454
2455 const int browser_id = browser->GetIdentifier();
2456 // Always use the same ID for the main frame.
2457 const int64 frame_id = frame->IsMain() ? -1 : frame->GetIdentifier();
2458
2459 const std::pair<int, int64>& id = std::make_pair(browser_id, frame_id);
2460
2461 // Remove the currently active manager, if any.
2462 ManagerMap::iterator it2 = manager_map_.find(id);
2463 if (it2 != manager_map_.end())
2464 manager_map_.erase(it2);
2465
2466 // Add the next manager to the active map.
2467 manager_map_.insert(std::make_pair(id, next_manager));
2468 }
2469
GetManager(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame) const2470 MultiQueryManager* GetManager(CefRefPtr<CefBrowser> browser,
2471 CefRefPtr<CefFrame> frame) const {
2472 const int browser_id = browser->GetIdentifier();
2473 // Always use the same ID for the main frame.
2474 const int64 frame_id = frame->IsMain() ? -1 : frame->GetIdentifier();
2475
2476 // Find the manager in the active map.
2477 ManagerMap::const_iterator it =
2478 manager_map_.find(std::make_pair(browser_id, frame_id));
2479 EXPECT_NE(it, manager_map_.end())
2480 << "browser_id = " << browser_id << ", frame_id = " << frame_id;
2481 return it->second;
2482 }
2483
RemoveAllManagers()2484 void RemoveAllManagers() {
2485 EXPECT_TRUE(pending_managers_.empty());
2486 if (all_managers_.empty())
2487 return;
2488
2489 for (size_t i = 0; i < all_managers_.size(); ++i) {
2490 delete all_managers_[i];
2491 }
2492 all_managers_.clear();
2493 manager_map_.clear();
2494 }
2495
GetNameForURL(const std::string & url)2496 static std::string GetNameForURL(const std::string& url) {
2497 // Extract the file name without extension.
2498 int pos1 = static_cast<int>(url.rfind("/"));
2499 int pos2 = static_cast<int>(url.rfind("."));
2500 EXPECT_TRUE(pos1 >= 0 && pos2 >= 0 && pos1 < pos2);
2501 return url.substr(pos1 + 1, pos2 - pos1 - 1);
2502 }
2503
2504 private:
2505 typedef std::vector<MultiQueryManager*> ManagerList;
2506 // Map of (browser ID, frame ID) to manager.
2507 typedef std::map<std::pair<int, int64>, MultiQueryManager*> ManagerMap;
2508
2509 // All managers that have been created.
2510 ManagerList all_managers_;
2511 // Managers that have not yet associated with a frame.
2512 ManagerList pending_managers_;
2513 // Managers that are currently active.
2514 ManagerMap manager_map_;
2515
2516 typedef std::set<Observer*> ObserverSet;
2517 ObserverSet observer_set_;
2518
2519 // Set to true after all query managers have been added.
2520 bool finalized_;
2521 // Set to true while queries are pending.
2522 bool running_;
2523
2524 // Number of managers that have completed.
2525 int manual_complete_count_;
2526 int total_complete_count_;
2527 };
2528
2529 // Test multiple queries in a single page load with multiple frames.
2530 class MultiQueryMultiFrameTestHandler : public SingleLoadTestHandler,
2531 public MultiQueryManagerMap::Observer {
2532 public:
MultiQueryMultiFrameTestHandler(bool synchronous,bool cancel_with_subnav)2533 MultiQueryMultiFrameTestHandler(bool synchronous, bool cancel_with_subnav)
2534 : synchronous_(synchronous), cancel_with_subnav_(cancel_with_subnav) {
2535 manager_map_.AddObserver(this);
2536 }
2537
AddOtherResources()2538 void AddOtherResources() override {
2539 AddSubFrameResource("sub1");
2540 AddSubFrameResource("sub2");
2541 AddSubFrameResource("sub3");
2542 manager_map_.Finalize();
2543
2544 if (manager_map_.HasAutoQueries()) {
2545 cancel_url_ = std::string(kTestDomain1) + "cancel.html";
2546 AddResource(cancel_url_, "<html><body>cancel</body></html>", "text/html");
2547 }
2548 }
2549
GetMainHTML()2550 std::string GetMainHTML() override { return manager_map_.GetMainHTML(); }
2551
OnLoadStart(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,TransitionType transition_type)2552 void OnLoadStart(CefRefPtr<CefBrowser> browser,
2553 CefRefPtr<CefFrame> frame,
2554 TransitionType transition_type) override {
2555 AssertMainBrowser(browser);
2556 if (!frame->IsMain())
2557 manager_map_.OnLoadStart(browser, frame);
2558 }
2559
OnNotify(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,const std::string & message)2560 void OnNotify(CefRefPtr<CefBrowser> browser,
2561 CefRefPtr<CefFrame> frame,
2562 const std::string& message) override {
2563 AssertMainBrowser(browser);
2564 EXPECT_FALSE(frame->IsMain());
2565
2566 manager_map_.OnNotify(browser, frame, message);
2567 }
2568
OnQuery(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,int64 query_id,const CefString & request,bool persistent,CefRefPtr<Callback> callback)2569 bool OnQuery(CefRefPtr<CefBrowser> browser,
2570 CefRefPtr<CefFrame> frame,
2571 int64 query_id,
2572 const CefString& request,
2573 bool persistent,
2574 CefRefPtr<Callback> callback) override {
2575 AssertMainBrowser(browser);
2576 EXPECT_FALSE(frame->IsMain());
2577
2578 return manager_map_.OnQuery(browser, frame, query_id, request, persistent,
2579 callback);
2580 }
2581
OnQueryCanceled(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,int64 query_id)2582 void OnQueryCanceled(CefRefPtr<CefBrowser> browser,
2583 CefRefPtr<CefFrame> frame,
2584 int64 query_id) override {
2585 AssertMainBrowser(browser);
2586 EXPECT_FALSE(frame->IsMain());
2587
2588 manager_map_.OnQueryCanceled(browser, frame, query_id);
2589 }
2590
OnMapManualQueriesCompleted(MultiQueryManagerMap * map)2591 void OnMapManualQueriesCompleted(MultiQueryManagerMap* map) override {
2592 EXPECT_EQ(map, &manager_map_);
2593 if (manager_map_.HasAutoQueries()) {
2594 CefRefPtr<CefFrame> frame = GetBrowser()->GetMainFrame();
2595
2596 // Navigate somewhere else to terminate the auto queries.
2597 if (cancel_with_subnav_) {
2598 // Navigate each subframe individually.
2599 const std::string js = "document.getElementById('sub1').src = '" +
2600 cancel_url_ +
2601 "';"
2602 "document.getElementById('sub2').src = '" +
2603 cancel_url_ +
2604 "';"
2605 "document.getElementById('sub3').src = '" +
2606 cancel_url_ + "';";
2607
2608 frame->ExecuteJavaScript(js, frame->GetURL(), 0);
2609 } else {
2610 // Navigate the main frame.
2611 frame->LoadURL(cancel_url_);
2612 }
2613 }
2614 }
2615
OnMapAllQueriesCompleted(MultiQueryManagerMap * map)2616 void OnMapAllQueriesCompleted(MultiQueryManagerMap* map) override {
2617 EXPECT_EQ(map, &manager_map_);
2618 DestroyTest();
2619 }
2620
DestroyTest()2621 void DestroyTest() override {
2622 manager_map_.AssertAllComplete();
2623 TestHandler::DestroyTest();
2624 }
2625
2626 private:
AddSubFrameResource(const std::string & name)2627 void AddSubFrameResource(const std::string& name) {
2628 const std::string& url = std::string(kTestDomain1) + name + ".html";
2629
2630 MultiQueryManager* manager = manager_map_.CreateManager(url, synchronous_);
2631 MakeTestQueries(manager, false, 100);
2632
2633 const std::string& html = manager->GetHTML(false, false);
2634 AddResource(url, html, "text/html");
2635 }
2636
2637 const bool synchronous_;
2638 const bool cancel_with_subnav_;
2639
2640 MultiQueryManagerMap manager_map_;
2641
2642 std::string cancel_url_;
2643 };
2644
2645 } // namespace
2646
2647 // Test that multiple frames can run many queries successfully in a synchronous
2648 // manner.
TEST(MessageRouterTest,MultiQueryMultiFrameSync)2649 TEST(MessageRouterTest, MultiQueryMultiFrameSync) {
2650 CefRefPtr<MultiQueryMultiFrameTestHandler> handler =
2651 new MultiQueryMultiFrameTestHandler(true, false);
2652 handler->ExecuteTest();
2653 ReleaseAndWaitForDestructor(handler);
2654 }
2655
2656 // Test that multiple frames can run many queries successfully in an
2657 // asynchronous manner.
TEST(MessageRouterTest,MultiQueryMultiFrameAsync)2658 TEST(MessageRouterTest, MultiQueryMultiFrameAsync) {
2659 CefRefPtr<MultiQueryMultiFrameTestHandler> handler =
2660 new MultiQueryMultiFrameTestHandler(false, false);
2661 handler->ExecuteTest();
2662 ReleaseAndWaitForDestructor(handler);
2663 }
2664
2665 // Test that multiple frames can run many queries successfully in a synchronous
2666 // manner. Cancel auto queries with sub-frame navigation.
TEST(MessageRouterTest,MultiQueryMultiFrameSyncSubnavCancel)2667 TEST(MessageRouterTest, MultiQueryMultiFrameSyncSubnavCancel) {
2668 CefRefPtr<MultiQueryMultiFrameTestHandler> handler =
2669 new MultiQueryMultiFrameTestHandler(true, true);
2670 handler->ExecuteTest();
2671 ReleaseAndWaitForDestructor(handler);
2672 }
2673
2674 // Test that multiple frames can run many queries successfully in an
2675 // asynchronous manner. Cancel auto queries with sub-frame navigation.
TEST(MessageRouterTest,MultiQueryMultiFrameAsyncSubnavCancel)2676 TEST(MessageRouterTest, MultiQueryMultiFrameAsyncSubnavCancel) {
2677 CefRefPtr<MultiQueryMultiFrameTestHandler> handler =
2678 new MultiQueryMultiFrameTestHandler(false, true);
2679 handler->ExecuteTest();
2680 ReleaseAndWaitForDestructor(handler);
2681 }
2682
2683 namespace {
2684
2685 // Implementation of MRTestHandler that loads multiple pages and/or browsers and
2686 // executes multiple queries.
2687 class MultiQueryMultiLoadTestHandler
2688 : public MRTestHandler,
2689 public CefMessageRouterBrowserSide::Handler,
2690 public MultiQueryManagerMap::Observer,
2691 public MultiQueryManager::Observer {
2692 public:
MultiQueryMultiLoadTestHandler(bool some,bool synchronous)2693 MultiQueryMultiLoadTestHandler(bool some, bool synchronous)
2694 : some_(some), synchronous_(synchronous) {
2695 manager_map_.AddObserver(this);
2696 }
2697
OnLoadStart(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,TransitionType transition_type)2698 void OnLoadStart(CefRefPtr<CefBrowser> browser,
2699 CefRefPtr<CefFrame> frame,
2700 TransitionType transition_type) override {
2701 manager_map_.OnLoadStart(browser, frame);
2702 }
2703
OnNotify(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,const std::string & message)2704 void OnNotify(CefRefPtr<CefBrowser> browser,
2705 CefRefPtr<CefFrame> frame,
2706 const std::string& message) override {
2707 manager_map_.OnNotify(browser, frame, message);
2708 }
2709
OnQuery(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,int64 query_id,const CefString & request,bool persistent,CefRefPtr<Callback> callback)2710 bool OnQuery(CefRefPtr<CefBrowser> browser,
2711 CefRefPtr<CefFrame> frame,
2712 int64 query_id,
2713 const CefString& request,
2714 bool persistent,
2715 CefRefPtr<Callback> callback) override {
2716 return manager_map_.OnQuery(browser, frame, query_id, request, persistent,
2717 callback);
2718 }
2719
OnQueryCanceled(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,int64 query_id)2720 void OnQueryCanceled(CefRefPtr<CefBrowser> browser,
2721 CefRefPtr<CefFrame> frame,
2722 int64 query_id) override {
2723 manager_map_.OnQueryCanceled(browser, frame, query_id);
2724 }
2725
OnMapManualQueriesCompleted(MultiQueryManagerMap * map)2726 void OnMapManualQueriesCompleted(MultiQueryManagerMap* map) override {
2727 EXPECT_EQ(map, &manager_map_);
2728 if (manager_map_.HasAutoQueries()) {
2729 // Navigate all browsers somewhere else to terminate the auto queries.
2730 BrowserMap browser_map;
2731 GetAllBrowsers(&browser_map);
2732
2733 BrowserMap::const_iterator it = browser_map.begin();
2734 for (; it != browser_map.end(); ++it) {
2735 it->second->GetMainFrame()->LoadURL(cancel_url_);
2736 }
2737 }
2738 }
2739
OnMapAllQueriesCompleted(MultiQueryManagerMap * map)2740 void OnMapAllQueriesCompleted(MultiQueryManagerMap* map) override {
2741 EXPECT_EQ(map, &manager_map_);
2742 DestroyTest();
2743 }
2744
DestroyTest()2745 void DestroyTest() override {
2746 manager_map_.AssertAllComplete();
2747 TestHandler::DestroyTest();
2748 }
2749
2750 protected:
AddHandlers(CefRefPtr<CefMessageRouterBrowserSide> message_router)2751 void AddHandlers(
2752 CefRefPtr<CefMessageRouterBrowserSide> message_router) override {
2753 message_router->AddHandler(this, false);
2754 }
2755
AddManagedResource(const std::string & url,bool assert_total,bool assert_browser)2756 void AddManagedResource(const std::string& url,
2757 bool assert_total,
2758 bool assert_browser) {
2759 MultiQueryManager* manager = manager_map_.CreateManager(url, synchronous_);
2760 manager->AddObserver(this);
2761 MakeTestQueries(manager, some_, 75);
2762
2763 const std::string& html = manager->GetHTML(assert_total, assert_browser);
2764 AddResource(url, html, "text/html");
2765 }
2766
Finalize()2767 void Finalize() {
2768 manager_map_.Finalize();
2769
2770 if (manager_map_.HasAutoQueries()) {
2771 cancel_url_ = std::string(kTestDomain1) + "cancel.html";
2772 AddResource(cancel_url_, "<html><body>cancel</body></html>", "text/html");
2773 }
2774 }
2775
2776 MultiQueryManagerMap manager_map_;
2777
2778 private:
2779 const bool some_;
2780 const bool synchronous_;
2781
2782 std::string cancel_url_;
2783 };
2784
2785 // Test multiple browsers that send queries at the same time.
2786 class MultiQueryMultiBrowserTestHandler
2787 : public MultiQueryMultiLoadTestHandler {
2788 public:
MultiQueryMultiBrowserTestHandler(bool synchronous,bool same_origin)2789 MultiQueryMultiBrowserTestHandler(bool synchronous, bool same_origin)
2790 : MultiQueryMultiLoadTestHandler(false, synchronous),
2791 same_origin_(same_origin) {}
2792
2793 protected:
RunMRTest()2794 void RunMRTest() override {
2795 const std::string& url1 = std::string(kTestDomain1) + "browser1.html";
2796 const std::string& url2 =
2797 std::string(same_origin_ ? kTestDomain1 : kTestDomain2) +
2798 "browser2.html";
2799 const std::string& url3 =
2800 std::string(same_origin_ ? kTestDomain1 : kTestDomain3) +
2801 "browser3.html";
2802
2803 AddManagedResource(url1, false, true);
2804 AddManagedResource(url2, false, true);
2805 AddManagedResource(url3, false, true);
2806 Finalize();
2807
2808 // Create 2 browsers simultaniously.
2809 CreateBrowser(url1, nullptr);
2810 CreateBrowser(url2, nullptr);
2811 CreateBrowser(url3, nullptr);
2812 }
2813
2814 private:
2815 bool same_origin_;
2816 };
2817
2818 } // namespace
2819
2820 // Test that multiple browsers can query simultaniously from the same origin.
TEST(MessageRouterTest,MultiQueryMultiBrowserSameOriginSync)2821 TEST(MessageRouterTest, MultiQueryMultiBrowserSameOriginSync) {
2822 CefRefPtr<MultiQueryMultiBrowserTestHandler> handler =
2823 new MultiQueryMultiBrowserTestHandler(true, true);
2824 handler->ExecuteTest();
2825 ReleaseAndWaitForDestructor(handler);
2826 }
2827
2828 // Test that multiple browsers can query simultaniously from the same origin.
TEST(MessageRouterTest,MultiQueryMultiBrowserSameOriginAsync)2829 TEST(MessageRouterTest, MultiQueryMultiBrowserSameOriginAsync) {
2830 CefRefPtr<MultiQueryMultiBrowserTestHandler> handler =
2831 new MultiQueryMultiBrowserTestHandler(false, true);
2832 handler->ExecuteTest();
2833 ReleaseAndWaitForDestructor(handler);
2834 }
2835
2836 // Test that multiple browsers can query simultaniously from different origins.
TEST(MessageRouterTest,MultiQueryMultiBrowserDifferentOriginSync)2837 TEST(MessageRouterTest, MultiQueryMultiBrowserDifferentOriginSync) {
2838 CefRefPtr<MultiQueryMultiBrowserTestHandler> handler =
2839 new MultiQueryMultiBrowserTestHandler(true, false);
2840 handler->ExecuteTest();
2841 ReleaseAndWaitForDestructor(handler);
2842 }
2843
2844 // Test that multiple browsers can query simultaniously from different origins.
TEST(MessageRouterTest,MultiQueryMultiBrowserDifferentOriginAsync)2845 TEST(MessageRouterTest, MultiQueryMultiBrowserDifferentOriginAsync) {
2846 CefRefPtr<MultiQueryMultiBrowserTestHandler> handler =
2847 new MultiQueryMultiBrowserTestHandler(false, false);
2848 handler->ExecuteTest();
2849 ReleaseAndWaitForDestructor(handler);
2850 }
2851
2852 namespace {
2853
2854 // Test multiple navigations that send queries sequentially.
2855 class MultiQueryMultiNavigateTestHandler
2856 : public MultiQueryMultiLoadTestHandler {
2857 public:
MultiQueryMultiNavigateTestHandler(bool synchronous,bool same_origin)2858 MultiQueryMultiNavigateTestHandler(bool synchronous, bool same_origin)
2859 : MultiQueryMultiLoadTestHandler(false, synchronous),
2860 same_origin_(same_origin) {}
2861
OnManualQueriesCompleted(MultiQueryManager * manager)2862 void OnManualQueriesCompleted(MultiQueryManager* manager) override {
2863 const std::string& url = manager->label();
2864 if (url == url1_) // 2. Load the 2nd url.
2865 GetBrowser()->GetMainFrame()->LoadURL(url2_);
2866 else if (url == url2_) // 3. Load the 3rd url.
2867 GetBrowser()->GetMainFrame()->LoadURL(url3_);
2868 }
2869
2870 protected:
RunMRTest()2871 void RunMRTest() override {
2872 url1_ = std::string(kTestDomain1) + "browser1.html";
2873 url2_ = std::string(same_origin_ ? kTestDomain1 : kTestDomain2) +
2874 "browser2.html";
2875 url3_ = std::string(same_origin_ ? kTestDomain1 : kTestDomain3) +
2876 "browser3.html";
2877
2878 AddManagedResource(url1_, true, true);
2879 AddManagedResource(url2_, true, true);
2880 AddManagedResource(url3_, true, true);
2881 Finalize();
2882
2883 // 1. Load the 1st url.
2884 CreateBrowser(url1_, nullptr);
2885 }
2886
2887 private:
2888 bool same_origin_;
2889
2890 std::string url1_;
2891 std::string url2_;
2892 std::string url3_;
2893 };
2894
2895 } // namespace
2896
2897 // Test that multiple navigations can query from the same origin.
TEST(MessageRouterTest,MultiQueryMultiNavigateSameOriginSync)2898 TEST(MessageRouterTest, MultiQueryMultiNavigateSameOriginSync) {
2899 CefRefPtr<MultiQueryMultiNavigateTestHandler> handler =
2900 new MultiQueryMultiNavigateTestHandler(true, true);
2901 handler->ExecuteTest();
2902 ReleaseAndWaitForDestructor(handler);
2903 }
2904
2905 // Test that multiple navigations can query from the same origin.
TEST(MessageRouterTest,MultiQueryMultiNavigateSameOriginAsync)2906 TEST(MessageRouterTest, MultiQueryMultiNavigateSameOriginAsync) {
2907 CefRefPtr<MultiQueryMultiNavigateTestHandler> handler =
2908 new MultiQueryMultiNavigateTestHandler(false, true);
2909 handler->ExecuteTest();
2910 ReleaseAndWaitForDestructor(handler);
2911 }
2912
2913 // Test that multiple navigations can query from different origins.
TEST(MessageRouterTest,MultiQueryMultiNavigateDifferentOriginSync)2914 TEST(MessageRouterTest, MultiQueryMultiNavigateDifferentOriginSync) {
2915 CefRefPtr<MultiQueryMultiNavigateTestHandler> handler =
2916 new MultiQueryMultiNavigateTestHandler(true, false);
2917 handler->ExecuteTest();
2918 ReleaseAndWaitForDestructor(handler);
2919 }
2920
2921 // Test that multiple navigations can query from different origins.
TEST(MessageRouterTest,MultiQueryMultiNavigateDifferentOriginAsync)2922 TEST(MessageRouterTest, MultiQueryMultiNavigateDifferentOriginAsync) {
2923 CefRefPtr<MultiQueryMultiNavigateTestHandler> handler =
2924 new MultiQueryMultiNavigateTestHandler(false, false);
2925 handler->ExecuteTest();
2926 ReleaseAndWaitForDestructor(handler);
2927 }
2928