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