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