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