• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2011 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 <algorithm>
6 #include <vector>
7 
8 #include "include/base/cef_callback.h"
9 #include "include/cef_callback.h"
10 #include "include/cef_origin_whitelist.h"
11 #include "include/cef_scheme.h"
12 #include "include/wrapper/cef_closure_task.h"
13 #include "tests/ceftests/test_handler.h"
14 #include "tests/ceftests/test_suite.h"
15 #include "tests/ceftests/test_util.h"
16 
17 namespace {
18 
19 class TestResults {
20  public:
TestResults()21   TestResults() : status_code(200), sub_status_code(200), delay(0) {}
22 
reset()23   void reset() {
24     url.clear();
25     html.clear();
26     status_code = 200;
27     response_error_code = ERR_NONE;
28     expected_error_code = ERR_NONE;
29     redirect_url.clear();
30     sub_url.clear();
31     sub_html.clear();
32     sub_status_code = 200;
33     sub_allow_origin.clear();
34     exit_url.clear();
35     accept_language.clear();
36     console_messages.clear();
37     delay = 0;
38     got_request.reset();
39     got_read.reset();
40     got_output.reset();
41     got_sub_output.reset();
42     got_redirect.reset();
43     got_error.reset();
44     got_sub_error.reset();
45     got_sub_request.reset();
46     got_sub_read.reset();
47     got_sub_success.reset();
48     got_exit_request.reset();
49   }
50 
51   std::string url;
52   std::string html;
53   int status_code;
54 
55   // Error code set on the response.
56   cef_errorcode_t response_error_code;
57   // Error code expected in OnLoadError.
58   cef_errorcode_t expected_error_code;
59 
60   // Used for testing redirects
61   std::string redirect_url;
62 
63   // Used for testing XHR requests
64   std::string sub_url;
65   std::string sub_html;
66   int sub_status_code;
67   std::string sub_allow_origin;
68   std::string sub_redirect_url;
69   std::string exit_url;
70 
71   // Used for testing per-browser Accept-Language.
72   std::string accept_language;
73 
74   // Used for testing received console messages.
75   std::vector<std::string> console_messages;
76 
77   // Delay for returning scheme handler results.
78   int delay;
79 
80   TrackCallback got_request, got_read, got_output, got_sub_output, got_redirect,
81       got_error, got_sub_error, got_sub_redirect, got_sub_request, got_sub_read,
82       got_sub_success, got_exit_request;
83 };
84 
85 // Current scheme handler object. Used when destroying the test from
86 // ClientSchemeHandler::ProcessRequest().
87 class TestSchemeHandler;
88 TestSchemeHandler* g_current_handler = nullptr;
89 
90 class TestSchemeHandler : public TestHandler {
91  public:
TestSchemeHandler(TestResults * tr)92   explicit TestSchemeHandler(TestResults* tr) : test_results_(tr) {
93     g_current_handler = this;
94   }
95 
PopulateBrowserSettings(CefBrowserSettings * settings)96   void PopulateBrowserSettings(CefBrowserSettings* settings) override {
97     if (!test_results_->accept_language.empty()) {
98       CefString(&settings->accept_language_list) =
99           test_results_->accept_language;
100     }
101   }
102 
RunTest()103   void RunTest() override {
104     CreateBrowser(test_results_->url);
105 
106     // Time out the test after a reasonable period of time.
107     SetTestTimeout();
108   }
109 
110   // Necessary to make the method public in order to destroy the test from
111   // ClientSchemeHandler::ProcessRequest().
DestroyTest()112   void DestroyTest() override {
113     EXPECT_TRUE(test_results_->console_messages.empty())
114         << "Did not receive expected console message: "
115         << test_results_->console_messages.front();
116 
117     TestHandler::DestroyTest();
118   }
119 
DestroyTestIfDone()120   void DestroyTestIfDone() {
121     if (!test_results_->exit_url.empty() && !test_results_->got_exit_request) {
122       return;
123     }
124 
125     if (!test_results_->sub_url.empty() &&
126         !(test_results_->got_sub_output || test_results_->got_sub_error ||
127           test_results_->got_exit_request)) {
128       return;
129     }
130 
131     if (!(test_results_->got_output || test_results_->got_error)) {
132       return;
133     }
134 
135     DestroyTest();
136   }
137 
IsExitURL(const std::string & url) const138   bool IsExitURL(const std::string& url) const {
139     return !test_results_->exit_url.empty() &&
140            url.find(test_results_->exit_url) != std::string::npos;
141   }
142 
OnBeforeResourceLoad(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,CefRefPtr<CefRequest> request,CefRefPtr<CefCallback> callback)143   cef_return_value_t OnBeforeResourceLoad(
144       CefRefPtr<CefBrowser> browser,
145       CefRefPtr<CefFrame> frame,
146       CefRefPtr<CefRequest> request,
147       CefRefPtr<CefCallback> callback) override {
148     if (IsChromeRuntimeEnabled() && request->GetResourceType() == RT_FAVICON) {
149       // Ignore favicon requests.
150       return RV_CANCEL;
151     }
152 
153     const std::string& newUrl = request->GetURL();
154     if (IsExitURL(newUrl)) {
155       test_results_->got_exit_request.yes();
156       // XHR tests use an exit URL to destroy the test.
157       if (newUrl.find("SUCCESS") != std::string::npos)
158         test_results_->got_sub_success.yes();
159       DestroyTestIfDone();
160       return RV_CANCEL;
161     }
162 
163     if (!test_results_->sub_redirect_url.empty() &&
164         newUrl == test_results_->sub_redirect_url) {
165       test_results_->got_sub_redirect.yes();
166       // Redirect to the sub URL.
167       request->SetURL(test_results_->sub_url);
168     } else if (newUrl == test_results_->redirect_url) {
169       test_results_->got_redirect.yes();
170 
171       // No read should have occurred for the redirect.
172       EXPECT_TRUE(test_results_->got_request);
173       EXPECT_FALSE(test_results_->got_read);
174 
175       // Now loading the redirect URL.
176       test_results_->url = test_results_->redirect_url;
177       test_results_->redirect_url.clear();
178     }
179 
180     return RV_CONTINUE;
181   }
182 
OnLoadEnd(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,int httpStatusCode)183   void OnLoadEnd(CefRefPtr<CefBrowser> browser,
184                  CefRefPtr<CefFrame> frame,
185                  int httpStatusCode) override {
186     const std::string& url = frame->GetURL();
187     if (url == test_results_->url)
188       test_results_->got_output.yes();
189     else if (url == test_results_->sub_url)
190       test_results_->got_sub_output.yes();
191     else if (IsExitURL(url))
192       return;
193 
194     if (url == test_results_->url || test_results_->status_code != 200) {
195       // Test that the status code is correct.
196       EXPECT_EQ(httpStatusCode, test_results_->status_code);
197     }
198 
199     DestroyTestIfDone();
200   }
201 
OnLoadError(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,ErrorCode errorCode,const CefString & errorText,const CefString & failedUrl)202   void OnLoadError(CefRefPtr<CefBrowser> browser,
203                    CefRefPtr<CefFrame> frame,
204                    ErrorCode errorCode,
205                    const CefString& errorText,
206                    const CefString& failedUrl) override {
207     const std::string& url = failedUrl;
208     if (url == test_results_->url)
209       test_results_->got_error.yes();
210     else if (url == test_results_->sub_url)
211       test_results_->got_sub_error.yes();
212     else if (IsExitURL(url))
213       return;
214 
215     // Tests sometimes also fail with ERR_ABORTED or ERR_UNKNOWN_URL_SCHEME.
216     if (!(test_results_->expected_error_code == 0 &&
217           (errorCode == ERR_ABORTED || errorCode == ERR_UNKNOWN_URL_SCHEME))) {
218       EXPECT_EQ(test_results_->expected_error_code, errorCode)
219           << failedUrl.ToString();
220     }
221 
222     DestroyTestIfDone();
223   }
224 
OnConsoleMessage(CefRefPtr<CefBrowser> browser,cef_log_severity_t level,const CefString & message,const CefString & source,int line)225   bool OnConsoleMessage(CefRefPtr<CefBrowser> browser,
226                         cef_log_severity_t level,
227                         const CefString& message,
228                         const CefString& source,
229                         int line) override {
230     bool expected = false;
231     if (!test_results_->console_messages.empty()) {
232       std::vector<std::string>::iterator it =
233           test_results_->console_messages.begin();
234       for (; it != test_results_->console_messages.end(); ++it) {
235         const std::string& possible = *it;
236         const std::string& actual = message.ToString();
237         if (actual.find(possible) == 0U) {
238           expected = true;
239           test_results_->console_messages.erase(it);
240           break;
241         }
242       }
243     }
244 
245     EXPECT_TRUE(expected) << "Unexpected console message: "
246                           << message.ToString();
247     return false;
248   }
249 
250  protected:
251   TestResults* test_results_;
252 
253   IMPLEMENT_REFCOUNTING(TestSchemeHandler);
254 };
255 
256 class ClientSchemeHandlerOld : public CefResourceHandler {
257  public:
ClientSchemeHandlerOld(TestResults * tr)258   explicit ClientSchemeHandlerOld(TestResults* tr)
259       : test_results_(tr), offset_(0), is_sub_(false), has_delayed_(false) {}
260 
ProcessRequest(CefRefPtr<CefRequest> request,CefRefPtr<CefCallback> callback)261   bool ProcessRequest(CefRefPtr<CefRequest> request,
262                       CefRefPtr<CefCallback> callback) override {
263     EXPECT_TRUE(CefCurrentlyOn(TID_IO));
264 
265     bool handled = false;
266 
267     std::string url = request->GetURL();
268     is_sub_ =
269         (!test_results_->sub_url.empty() && test_results_->sub_url == url);
270 
271     if (is_sub_) {
272       test_results_->got_sub_request.yes();
273 
274       if (!test_results_->sub_html.empty())
275         handled = true;
276     } else {
277       EXPECT_EQ(url, test_results_->url);
278 
279       test_results_->got_request.yes();
280 
281       if (!test_results_->html.empty())
282         handled = true;
283     }
284 
285     std::string accept_language;
286     CefRequest::HeaderMap headerMap;
287     CefRequest::HeaderMap::iterator headerIter;
288     request->GetHeaderMap(headerMap);
289     headerIter = headerMap.find("Accept-Language");
290     if (headerIter != headerMap.end())
291       accept_language = headerIter->second;
292     EXPECT_TRUE(!accept_language.empty());
293 
294     if (!test_results_->accept_language.empty()) {
295       // Value from CefBrowserSettings.accept_language set in
296       // PopulateBrowserSettings().
297       EXPECT_STREQ(test_results_->accept_language.data(),
298                    accept_language.data());
299     } else {
300       // CEF_SETTINGS_ACCEPT_LANGUAGE value from
301       // CefSettings.accept_language_list set in CefTestSuite::GetSettings()
302       // and expanded internally by ComputeAcceptLanguageFromPref.
303       EXPECT_STREQ("en-GB,en;q=0.9", accept_language.data());
304     }
305 
306     if (handled) {
307       if (test_results_->delay > 0) {
308         // Continue after the delay.
309         CefPostDelayedTask(
310             TID_IO, base::BindOnce(&CefCallback::Continue, callback.get()),
311             test_results_->delay);
312       } else {
313         // Continue immediately.
314         callback->Continue();
315       }
316       return true;
317     } else if (test_results_->response_error_code != ERR_NONE) {
318       // Propagate the error code.
319       callback->Continue();
320       return true;
321     }
322 
323     // Response was canceled.
324     if (g_current_handler)
325       g_current_handler->DestroyTest();
326     return false;
327   }
328 
GetResponseHeaders(CefRefPtr<CefResponse> response,int64 & response_length,CefString & redirectUrl)329   void GetResponseHeaders(CefRefPtr<CefResponse> response,
330                           int64& response_length,
331                           CefString& redirectUrl) override {
332     if (is_sub_) {
333       response->SetStatus(test_results_->sub_status_code);
334 
335       if (!test_results_->sub_allow_origin.empty()) {
336         // Set the Access-Control-Allow-Origin header to allow cross-domain
337         // scripting.
338         CefResponse::HeaderMap headers;
339         headers.insert(std::make_pair("Access-Control-Allow-Origin",
340                                       test_results_->sub_allow_origin));
341         response->SetHeaderMap(headers);
342       }
343 
344       if (!test_results_->sub_html.empty()) {
345         response->SetMimeType("text/html");
346         response_length = test_results_->sub_html.size();
347       }
348     } else if (!test_results_->redirect_url.empty()) {
349       redirectUrl = test_results_->redirect_url;
350     } else if (test_results_->response_error_code != ERR_NONE) {
351       response->SetError(test_results_->response_error_code);
352     } else {
353       response->SetStatus(test_results_->status_code);
354 
355       if (!test_results_->html.empty()) {
356         response->SetMimeType("text/html");
357         response_length = test_results_->html.size();
358       }
359     }
360   }
361 
Cancel()362   void Cancel() override { EXPECT_TRUE(CefCurrentlyOn(TID_IO)); }
363 
ReadResponse(void * data_out,int bytes_to_read,int & bytes_read,CefRefPtr<CefCallback> callback)364   bool ReadResponse(void* data_out,
365                     int bytes_to_read,
366                     int& bytes_read,
367                     CefRefPtr<CefCallback> callback) override {
368     EXPECT_TRUE(CefCurrentlyOn(TID_IO));
369 
370     if (test_results_->delay > 0) {
371       if (!has_delayed_) {
372         // Continue after a delay.
373         CefPostDelayedTask(
374             TID_IO,
375             base::BindOnce(&ClientSchemeHandlerOld::ContinueAfterDelay, this,
376                            callback),
377             test_results_->delay);
378         bytes_read = 0;
379         return true;
380       }
381 
382       has_delayed_ = false;
383     }
384 
385     std::string* data;
386 
387     if (is_sub_) {
388       test_results_->got_sub_read.yes();
389       data = &test_results_->sub_html;
390     } else {
391       test_results_->got_read.yes();
392       data = &test_results_->html;
393     }
394 
395     bool has_data = false;
396     bytes_read = 0;
397 
398     size_t size = data->size();
399     if (offset_ < size) {
400       int transfer_size =
401           std::min(bytes_to_read, static_cast<int>(size - offset_));
402       memcpy(data_out, data->c_str() + offset_, transfer_size);
403       offset_ += transfer_size;
404 
405       bytes_read = transfer_size;
406       has_data = true;
407     }
408 
409     return has_data;
410   }
411 
412  private:
ContinueAfterDelay(CefRefPtr<CefCallback> callback)413   void ContinueAfterDelay(CefRefPtr<CefCallback> callback) {
414     has_delayed_ = true;
415     callback->Continue();
416   }
417 
418   TestResults* test_results_;
419   size_t offset_;
420   bool is_sub_;
421   bool has_delayed_;
422 
423   IMPLEMENT_REFCOUNTING(ClientSchemeHandlerOld);
424   DISALLOW_COPY_AND_ASSIGN(ClientSchemeHandlerOld);
425 };
426 
427 class ClientSchemeHandler : public CefResourceHandler {
428  public:
ClientSchemeHandler(TestResults * tr)429   explicit ClientSchemeHandler(TestResults* tr)
430       : test_results_(tr), offset_(0), is_sub_(false), has_delayed_(false) {}
431 
Open(CefRefPtr<CefRequest> request,bool & handle_request,CefRefPtr<CefCallback> callback)432   bool Open(CefRefPtr<CefRequest> request,
433             bool& handle_request,
434             CefRefPtr<CefCallback> callback) override {
435     EXPECT_FALSE(CefCurrentlyOn(TID_UI) || CefCurrentlyOn(TID_IO));
436 
437     if (IsChromeRuntimeEnabled() && request->GetResourceType() == RT_FAVICON) {
438       // Ignore favicon requests.
439       return false;
440     }
441 
442     bool handled = false;
443 
444     std::string url = request->GetURL();
445     is_sub_ =
446         (!test_results_->sub_url.empty() && test_results_->sub_url == url);
447 
448     if (is_sub_) {
449       test_results_->got_sub_request.yes();
450 
451       if (!test_results_->sub_html.empty())
452         handled = true;
453     } else {
454       EXPECT_EQ(url, test_results_->url);
455 
456       test_results_->got_request.yes();
457 
458       if (!test_results_->html.empty())
459         handled = true;
460     }
461 
462     std::string accept_language;
463     CefRequest::HeaderMap headerMap;
464     CefRequest::HeaderMap::iterator headerIter;
465     request->GetHeaderMap(headerMap);
466     headerIter = headerMap.find("Accept-Language");
467     if (headerIter != headerMap.end())
468       accept_language = headerIter->second;
469     EXPECT_TRUE(!accept_language.empty());
470 
471     if (!test_results_->accept_language.empty()) {
472       // Value from CefBrowserSettings.accept_language set in
473       // PopulateBrowserSettings().
474       EXPECT_STREQ(test_results_->accept_language.data(),
475                    accept_language.data());
476     } else {
477       // CEF_SETTINGS_ACCEPT_LANGUAGE value from
478       // CefSettings.accept_language_list set in CefTestSuite::GetSettings()
479       // and expanded internally by ComputeAcceptLanguageFromPref.
480       EXPECT_STREQ("en-GB,en;q=0.9", accept_language.data());
481     }
482 
483     // Continue or cancel the request immediately based on the return value.
484     handle_request = true;
485 
486     if (handled) {
487       if (test_results_->delay > 0) {
488         // Continue after the delay.
489         handle_request = false;
490         CefPostDelayedTask(
491             TID_FILE_USER_BLOCKING,
492             base::BindOnce(&CefCallback::Continue, callback.get()),
493             test_results_->delay);
494       }
495       return true;
496     } else if (test_results_->response_error_code != ERR_NONE) {
497       // Propagate the error code.
498       return true;
499     }
500 
501     // Response was canceled.
502     if (g_current_handler)
503       g_current_handler->DestroyTest();
504     return false;
505   }
506 
ProcessRequest(CefRefPtr<CefRequest> request,CefRefPtr<CefCallback> callback)507   bool ProcessRequest(CefRefPtr<CefRequest> request,
508                       CefRefPtr<CefCallback> callback) override {
509     if (IsChromeRuntimeEnabled() && request->GetResourceType() == RT_FAVICON) {
510       // Ignore favicon requests.
511       return false;
512     }
513 
514     EXPECT_TRUE(false);  // Not reached.
515     return false;
516   }
517 
GetResponseHeaders(CefRefPtr<CefResponse> response,int64 & response_length,CefString & redirectUrl)518   void GetResponseHeaders(CefRefPtr<CefResponse> response,
519                           int64& response_length,
520                           CefString& redirectUrl) override {
521     if (is_sub_) {
522       response->SetStatus(test_results_->sub_status_code);
523 
524       if (!test_results_->sub_allow_origin.empty()) {
525         // Set the Access-Control-Allow-Origin header to allow cross-domain
526         // scripting.
527         CefResponse::HeaderMap headers;
528         headers.insert(std::make_pair("Access-Control-Allow-Origin",
529                                       test_results_->sub_allow_origin));
530         response->SetHeaderMap(headers);
531       }
532 
533       if (!test_results_->sub_html.empty()) {
534         response->SetMimeType("text/html");
535         response_length = test_results_->sub_html.size();
536       }
537     } else if (!test_results_->redirect_url.empty()) {
538       redirectUrl = test_results_->redirect_url;
539     } else if (test_results_->response_error_code != ERR_NONE) {
540       response->SetError(test_results_->response_error_code);
541     } else {
542       response->SetStatus(test_results_->status_code);
543 
544       if (!test_results_->html.empty()) {
545         response->SetMimeType("text/html");
546         response_length = test_results_->html.size();
547       }
548     }
549   }
550 
Cancel()551   void Cancel() override { EXPECT_TRUE(CefCurrentlyOn(TID_IO)); }
552 
Read(void * data_out,int bytes_to_read,int & bytes_read,CefRefPtr<CefResourceReadCallback> callback)553   bool Read(void* data_out,
554             int bytes_to_read,
555             int& bytes_read,
556             CefRefPtr<CefResourceReadCallback> callback) override {
557     EXPECT_FALSE(CefCurrentlyOn(TID_UI) || CefCurrentlyOn(TID_IO));
558 
559     if (test_results_->delay > 0) {
560       if (!has_delayed_) {
561         // Continue after a delay.
562         CefPostDelayedTask(
563             TID_FILE_USER_BLOCKING,
564             base::BindOnce(&ClientSchemeHandler::ContinueAfterDelay, this,
565                            data_out, bytes_to_read, callback),
566             test_results_->delay);
567         bytes_read = 0;
568         return true;
569       }
570 
571       has_delayed_ = false;
572     }
573 
574     return GetData(data_out, bytes_to_read, bytes_read);
575   }
576 
ReadResponse(void * data_out,int bytes_to_read,int & bytes_read,CefRefPtr<CefCallback> callback)577   bool ReadResponse(void* data_out,
578                     int bytes_to_read,
579                     int& bytes_read,
580                     CefRefPtr<CefCallback> callback) override {
581     EXPECT_TRUE(false);  // Not reached.
582     bytes_read = -2;
583     return false;
584   }
585 
586  private:
ContinueAfterDelay(void * data_out,int bytes_to_read,CefRefPtr<CefResourceReadCallback> callback)587   void ContinueAfterDelay(void* data_out,
588                           int bytes_to_read,
589                           CefRefPtr<CefResourceReadCallback> callback) {
590     EXPECT_FALSE(CefCurrentlyOn(TID_UI) || CefCurrentlyOn(TID_IO));
591 
592     has_delayed_ = true;
593 
594     int bytes_read = 0;
595     GetData(data_out, bytes_to_read, bytes_read);
596     callback->Continue(bytes_read);
597   }
598 
GetData(void * data_out,int bytes_to_read,int & bytes_read)599   bool GetData(void* data_out, int bytes_to_read, int& bytes_read) {
600     std::string* data;
601 
602     if (is_sub_) {
603       test_results_->got_sub_read.yes();
604       data = &test_results_->sub_html;
605     } else {
606       test_results_->got_read.yes();
607       data = &test_results_->html;
608     }
609 
610     // Default to response complete.
611     bool has_data = false;
612     bytes_read = 0;
613 
614     size_t size = data->size();
615     if (offset_ < size) {
616       int transfer_size =
617           std::min(bytes_to_read, static_cast<int>(size - offset_));
618       memcpy(data_out, data->c_str() + offset_, transfer_size);
619       offset_ += transfer_size;
620 
621       bytes_read = transfer_size;
622       has_data = true;
623     }
624 
625     return has_data;
626   }
627 
628   TestResults* test_results_;
629   size_t offset_;
630   bool is_sub_;
631   bool has_delayed_;
632 
633   IMPLEMENT_REFCOUNTING(ClientSchemeHandler);
634   DISALLOW_COPY_AND_ASSIGN(ClientSchemeHandler);
635 };
636 
637 class ClientSchemeHandlerFactory : public CefSchemeHandlerFactory {
638  public:
ClientSchemeHandlerFactory(TestResults * tr)639   explicit ClientSchemeHandlerFactory(TestResults* tr) : test_results_(tr) {}
640 
Create(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,const CefString & scheme_name,CefRefPtr<CefRequest> request)641   CefRefPtr<CefResourceHandler> Create(CefRefPtr<CefBrowser> browser,
642                                        CefRefPtr<CefFrame> frame,
643                                        const CefString& scheme_name,
644                                        CefRefPtr<CefRequest> request) override {
645     EXPECT_TRUE(CefCurrentlyOn(TID_IO));
646     if (TestOldResourceAPI()) {
647       return new ClientSchemeHandlerOld(test_results_);
648     }
649     return new ClientSchemeHandler(test_results_);
650   }
651 
652   TestResults* test_results_;
653 
654   IMPLEMENT_REFCOUNTING(ClientSchemeHandlerFactory);
655   DISALLOW_COPY_AND_ASSIGN(ClientSchemeHandlerFactory);
656 };
657 
658 // Global test results object.
659 TestResults g_TestResults;
660 
661 // If |domain| is empty the scheme will be registered as non-standard.
RegisterTestScheme(const std::string & scheme,const std::string & domain)662 void RegisterTestScheme(const std::string& scheme, const std::string& domain) {
663   g_TestResults.reset();
664 
665   EXPECT_TRUE(CefRegisterSchemeHandlerFactory(
666       scheme, domain, new ClientSchemeHandlerFactory(&g_TestResults)));
667   WaitForIOThread();
668 }
669 
ClearTestSchemes()670 void ClearTestSchemes() {
671   EXPECT_TRUE(CefClearSchemeHandlerFactories());
672   WaitForIOThread();
673 }
674 
675 struct XHRTestSettings {
XHRTestSettings__anona20967f80111::XHRTestSettings676   XHRTestSettings() : synchronous(true) {}
677 
678   std::string url;
679   std::string sub_url;
680   std::string sub_allow_origin;
681   std::string sub_redirect_url;
682   bool synchronous;
683 };
684 
SetUpXHR(const XHRTestSettings & settings)685 void SetUpXHR(const XHRTestSettings& settings) {
686   g_TestResults.sub_url = settings.sub_url;
687   g_TestResults.sub_html = "SUCCESS";
688   g_TestResults.sub_allow_origin = settings.sub_allow_origin;
689   g_TestResults.sub_redirect_url = settings.sub_redirect_url;
690 
691   std::string request_url;
692   if (!settings.sub_redirect_url.empty())
693     request_url = settings.sub_redirect_url;
694   else
695     request_url = settings.sub_url;
696 
697   g_TestResults.url = settings.url;
698   std::stringstream ss;
699   ss << "<html><head>"
700         "<script language=\"JavaScript\">"
701         "function onResult(val) {"
702         "  document.location = \"http://tests/exit?result=\"+val;"
703         "}"
704         "function execXMLHttpRequest() {";
705   if (settings.synchronous) {
706     ss << "var result = 'FAILURE';"
707           "try {"
708           "  xhr = new XMLHttpRequest();"
709           "  xhr.open(\"GET\", \""
710        << request_url.c_str()
711        << "\", false);"
712           "  xhr.send();"
713           "  result = xhr.responseText;"
714           "} catch(e) {}"
715           "onResult(result)";
716   } else {
717     ss << "xhr = new XMLHttpRequest();"
718           "xhr.open(\"GET\", \""
719        << request_url.c_str()
720        << "\", true);"
721           "xhr.onload = function(e) {"
722           "  if (xhr.readyState === 4) {"
723           "    if (xhr.status === 200) {"
724           "      onResult(xhr.responseText);"
725           "    } else {"
726           "      console.log('XMLHttpRequest failed with status ' + "
727           "xhr.status);"
728           "      onResult('FAILURE');"
729           "    }"
730           "  }"
731           "};"
732           "xhr.onerror = function(e) {"
733           "  onResult('FAILURE');"
734           "};"
735           "xhr.send()";
736   }
737   ss << "}"
738         "</script>"
739         "</head><body onload=\"execXMLHttpRequest();\">"
740         "Running execXMLHttpRequest..."
741         "</body></html>";
742   g_TestResults.html = ss.str();
743 
744   g_TestResults.exit_url = "http://tests/exit";
745 }
746 
747 struct FetchTestSettings {
FetchTestSettings__anona20967f80111::FetchTestSettings748   FetchTestSettings() {}
749 
750   std::string url;
751   std::string sub_url;
752   std::string sub_allow_origin;
753   std::string sub_redirect_url;
754 };
755 
SetUpFetch(const FetchTestSettings & settings)756 void SetUpFetch(const FetchTestSettings& settings) {
757   g_TestResults.sub_url = settings.sub_url;
758   g_TestResults.sub_html = "SUCCESS";
759   g_TestResults.sub_allow_origin = settings.sub_allow_origin;
760   g_TestResults.sub_redirect_url = settings.sub_redirect_url;
761 
762   std::string request_url;
763   if (!settings.sub_redirect_url.empty())
764     request_url = settings.sub_redirect_url;
765   else
766     request_url = settings.sub_url;
767 
768   g_TestResults.url = settings.url;
769   std::stringstream ss;
770   ss << "<html><head>"
771         "<script language=\"JavaScript\">"
772         "function onResult(val) {"
773         "  document.location = \"http://tests/exit?result=\"+val;"
774         "}"
775         "function execFetchHttpRequest() {";
776   ss << "fetch('" << request_url.c_str()
777      << "')"
778         ".then(function(response) {"
779         "  if (response.status === 200) {"
780         "      response.text().then(function(text) {"
781         "          onResult(text);"
782         "      }).catch(function(e) {"
783         "          onResult('FAILURE');        "
784         "      });"
785         "  } else {"
786         "      onResult('FAILURE');"
787         "  }"
788         "}).catch(function(e) {"
789         "  onResult('FAILURE');"
790         "});"
791      << "}"
792         "</script>"
793         "</head><body onload=\"execFetchHttpRequest();\">"
794         "Running execFetchHttpRequest..."
795         "</body></html>";
796   g_TestResults.html = ss.str();
797 
798   g_TestResults.exit_url = "http://tests/exit";
799 }  // namespace
800 
SetUpXSS(const std::string & url,const std::string & sub_url,const std::string & domain=std::string ())801 void SetUpXSS(const std::string& url,
802               const std::string& sub_url,
803               const std::string& domain = std::string()) {
804   // 1. Load |url| which contains an iframe.
805   // 2. The iframe loads |sub_url|.
806   // 3. |sub_url| tries to call a JS function in |url|.
807   // 4. |url| tries to call a JS function in |sub_url|.
808 
809   std::stringstream ss;
810   std::string domain_line;
811   if (!domain.empty())
812     domain_line = "document.domain = '" + domain + "';";
813 
814   g_TestResults.sub_url = sub_url;
815   ss << "<html><head>"
816         "<script language=\"JavaScript\">"
817      << domain_line
818      << "function getResult() {"
819         "  return 'SUCCESS';"
820         "}"
821         "function execXSSRequest() {"
822         "  var result = 'FAILURE';"
823         "  try {"
824         "    result = parent.getResult();"
825         "  } catch(e) { console.log(e.stack); }"
826         "  document.location = \"http://tests/exit?result=\"+result;"
827         "}"
828         "</script>"
829         "</head><body onload=\"execXSSRequest();\">"
830         "Running execXSSRequest..."
831         "</body></html>";
832   g_TestResults.sub_html = ss.str();
833 
834   g_TestResults.url = url;
835   ss.str("");
836   ss << "<html><head>"
837         "<script language=\"JavaScript\">"
838      << domain_line
839      << ""
840         "function getResult() {"
841         "  try {"
842         "    return document.getElementById('s').contentWindow.getResult();"
843         "  } catch(e) { console.log(e.stack); }"
844         "  return 'FAILURE';"
845         "}"
846         "</script>"
847         "</head><body>"
848         "<iframe src=\""
849      << sub_url.c_str()
850      << "\" id=\"s\">"
851         "</body></html>";
852   g_TestResults.html = ss.str();
853 
854   g_TestResults.exit_url = "http://tests/exit";
855 }
856 
857 }  // namespace
858 
859 // Test that scheme registration/unregistration works as expected.
TEST(SchemeHandlerTest,Registration)860 TEST(SchemeHandlerTest, Registration) {
861   RegisterTestScheme("customstd", "test");
862   g_TestResults.url = "customstd://test/run.html";
863   g_TestResults.html =
864       "<html><head></head><body><h1>Success!</h1></body></html>";
865 
866   CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
867   handler->ExecuteTest();
868 
869   EXPECT_TRUE(g_TestResults.got_request);
870   EXPECT_TRUE(g_TestResults.got_read);
871   EXPECT_TRUE(g_TestResults.got_output);
872 
873   // Unregister the handler.
874   EXPECT_TRUE(CefRegisterSchemeHandlerFactory("customstd", "test", nullptr));
875   WaitForIOThread();
876 
877   g_TestResults.got_request.reset();
878   g_TestResults.got_read.reset();
879   g_TestResults.got_output.reset();
880   g_TestResults.expected_error_code = ERR_UNKNOWN_URL_SCHEME;
881   handler->ExecuteTest();
882 
883   EXPECT_TRUE(g_TestResults.got_error);
884   EXPECT_FALSE(g_TestResults.got_request);
885   EXPECT_FALSE(g_TestResults.got_read);
886   EXPECT_FALSE(g_TestResults.got_output);
887 
888   // Re-register the handler.
889   EXPECT_TRUE(CefRegisterSchemeHandlerFactory(
890       "customstd", "test", new ClientSchemeHandlerFactory(&g_TestResults)));
891   WaitForIOThread();
892 
893   g_TestResults.got_error.reset();
894   g_TestResults.expected_error_code = ERR_NONE;
895   handler->ExecuteTest();
896 
897   ReleaseAndWaitForDestructor(handler);
898 
899   EXPECT_FALSE(g_TestResults.got_error);
900   EXPECT_TRUE(g_TestResults.got_request);
901   EXPECT_TRUE(g_TestResults.got_read);
902   EXPECT_TRUE(g_TestResults.got_output);
903 
904   ClearTestSchemes();
905 }
906 
907 // Test that a custom standard scheme can return normal results.
TEST(SchemeHandlerTest,CustomStandardNormalResponse)908 TEST(SchemeHandlerTest, CustomStandardNormalResponse) {
909   RegisterTestScheme("customstd", "test");
910   g_TestResults.url = "customstd://test/run.html";
911   g_TestResults.html =
912       "<html><head></head><body><h1>Success!</h1></body></html>";
913 
914   CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
915   handler->ExecuteTest();
916   ReleaseAndWaitForDestructor(handler);
917 
918   EXPECT_TRUE(g_TestResults.got_request);
919   EXPECT_TRUE(g_TestResults.got_read);
920   EXPECT_TRUE(g_TestResults.got_output);
921 
922   ClearTestSchemes();
923 }
924 
925 // Test that a custom standard scheme can return normal results with delayed
926 // responses.
TEST(SchemeHandlerTest,CustomStandardNormalResponseDelayed)927 TEST(SchemeHandlerTest, CustomStandardNormalResponseDelayed) {
928   RegisterTestScheme("customstd", "test");
929   g_TestResults.url = "customstd://test/run.html";
930   g_TestResults.html =
931       "<html><head></head><body><h1>Success!</h1></body></html>";
932   g_TestResults.delay = 100;
933 
934   CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
935   handler->ExecuteTest();
936   ReleaseAndWaitForDestructor(handler);
937 
938   EXPECT_TRUE(g_TestResults.got_request);
939   EXPECT_TRUE(g_TestResults.got_read);
940   EXPECT_TRUE(g_TestResults.got_output);
941 
942   ClearTestSchemes();
943 }
944 
945 // Test that a custom nonstandard scheme can return normal results.
TEST(SchemeHandlerTest,CustomNonStandardNormalResponse)946 TEST(SchemeHandlerTest, CustomNonStandardNormalResponse) {
947   RegisterTestScheme("customnonstd", std::string());
948   g_TestResults.url = "customnonstd:some%20value";
949   g_TestResults.html =
950       "<html><head></head><body><h1>Success!</h1></body></html>";
951 
952   CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
953   handler->ExecuteTest();
954   ReleaseAndWaitForDestructor(handler);
955 
956   EXPECT_TRUE(g_TestResults.got_request);
957   EXPECT_TRUE(g_TestResults.got_read);
958   EXPECT_TRUE(g_TestResults.got_output);
959 
960   ClearTestSchemes();
961 }
962 
963 // Test that a custom standard scheme can return an error code.
TEST(SchemeHandlerTest,CustomStandardErrorResponse)964 TEST(SchemeHandlerTest, CustomStandardErrorResponse) {
965   RegisterTestScheme("customstd", "test");
966   g_TestResults.url = "customstd://test/run.html";
967   g_TestResults.html = "<html><head></head><body><h1>404</h1></body></html>";
968   g_TestResults.status_code = 404;
969 
970   CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
971   handler->ExecuteTest();
972   ReleaseAndWaitForDestructor(handler);
973 
974   EXPECT_TRUE(g_TestResults.got_request);
975   EXPECT_TRUE(g_TestResults.got_read);
976   EXPECT_TRUE(g_TestResults.got_output);
977 
978   ClearTestSchemes();
979 }
980 
981 // Test that a custom standard scheme can return a CEF error code in the
982 // response.
TEST(SchemeHandlerTest,CustomStandardErrorCodeResponse)983 TEST(SchemeHandlerTest, CustomStandardErrorCodeResponse) {
984   RegisterTestScheme("customstd", "test");
985   g_TestResults.url = "customstd://test/run.html";
986   g_TestResults.response_error_code = ERR_FILE_TOO_BIG;
987   g_TestResults.expected_error_code = ERR_FILE_TOO_BIG;
988 
989   CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
990   handler->ExecuteTest();
991   ReleaseAndWaitForDestructor(handler);
992 
993   EXPECT_TRUE(g_TestResults.got_request);
994   EXPECT_FALSE(g_TestResults.got_read);
995   EXPECT_FALSE(g_TestResults.got_output);
996   EXPECT_TRUE(g_TestResults.got_error);
997 
998   ClearTestSchemes();
999 }
1000 
1001 // Test that a custom nonstandard scheme can return an error code.
TEST(SchemeHandlerTest,CustomNonStandardErrorResponse)1002 TEST(SchemeHandlerTest, CustomNonStandardErrorResponse) {
1003   RegisterTestScheme("customnonstd", std::string());
1004   g_TestResults.url = "customnonstd:some%20value";
1005   g_TestResults.html = "<html><head></head><body><h1>404</h1></body></html>";
1006   g_TestResults.status_code = 404;
1007 
1008   CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
1009   handler->ExecuteTest();
1010   ReleaseAndWaitForDestructor(handler);
1011 
1012   EXPECT_TRUE(g_TestResults.got_request);
1013   EXPECT_TRUE(g_TestResults.got_read);
1014   EXPECT_TRUE(g_TestResults.got_output);
1015 
1016   ClearTestSchemes();
1017 }
1018 
1019 // Test that custom standard scheme handling fails when the scheme name is
1020 // incorrect.
TEST(SchemeHandlerTest,CustomStandardNameNotHandled)1021 TEST(SchemeHandlerTest, CustomStandardNameNotHandled) {
1022   RegisterTestScheme("customstd", "test");
1023   g_TestResults.url = "customstd2://test/run.html";
1024   g_TestResults.expected_error_code = ERR_UNKNOWN_URL_SCHEME;
1025 
1026   CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
1027   handler->ExecuteTest();
1028   ReleaseAndWaitForDestructor(handler);
1029 
1030   EXPECT_FALSE(g_TestResults.got_request);
1031   EXPECT_FALSE(g_TestResults.got_read);
1032   EXPECT_FALSE(g_TestResults.got_output);
1033   EXPECT_TRUE(g_TestResults.got_error);
1034 
1035   ClearTestSchemes();
1036 }
1037 
1038 // Test that custom nonstandard scheme handling fails when the scheme name is
1039 // incorrect.
TEST(SchemeHandlerTest,CustomNonStandardNameNotHandled)1040 TEST(SchemeHandlerTest, CustomNonStandardNameNotHandled) {
1041   RegisterTestScheme("customnonstd", std::string());
1042   g_TestResults.url = "customnonstd2:some%20value";
1043   g_TestResults.expected_error_code = ERR_UNKNOWN_URL_SCHEME;
1044 
1045   CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
1046   handler->ExecuteTest();
1047   ReleaseAndWaitForDestructor(handler);
1048 
1049   EXPECT_FALSE(g_TestResults.got_request);
1050   EXPECT_FALSE(g_TestResults.got_read);
1051   EXPECT_FALSE(g_TestResults.got_output);
1052   EXPECT_TRUE(g_TestResults.got_error);
1053 
1054   ClearTestSchemes();
1055 }
1056 
1057 // Test that custom standard scheme handling fails when the domain name is
1058 // incorrect.
TEST(SchemeHandlerTest,CustomStandardDomainNotHandled)1059 TEST(SchemeHandlerTest, CustomStandardDomainNotHandled) {
1060   RegisterTestScheme("customstd", "test");
1061   g_TestResults.url = "customstd://noexist/run.html";
1062   g_TestResults.expected_error_code = ERR_UNKNOWN_URL_SCHEME;
1063 
1064   CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
1065   handler->ExecuteTest();
1066   ReleaseAndWaitForDestructor(handler);
1067 
1068   EXPECT_FALSE(g_TestResults.got_request);
1069   EXPECT_FALSE(g_TestResults.got_read);
1070   EXPECT_FALSE(g_TestResults.got_output);
1071   EXPECT_TRUE(g_TestResults.got_error);
1072 
1073   ClearTestSchemes();
1074 }
1075 
1076 // Test that a custom standard scheme can return no response.
TEST(SchemeHandlerTest,CustomStandardNoResponse)1077 TEST(SchemeHandlerTest, CustomStandardNoResponse) {
1078   RegisterTestScheme("customstd", "test");
1079   g_TestResults.url = "customstd://test/run.html";
1080 
1081   CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
1082   handler->ExecuteTest();
1083   ReleaseAndWaitForDestructor(handler);
1084 
1085   EXPECT_TRUE(g_TestResults.got_request);
1086   EXPECT_FALSE(g_TestResults.got_read);
1087   EXPECT_FALSE(g_TestResults.got_output);
1088 
1089   ClearTestSchemes();
1090 }
1091 
1092 // Test that a custom nonstandard scheme can return no response.
TEST(SchemeHandlerTest,CustomNonStandardNoResponse)1093 TEST(SchemeHandlerTest, CustomNonStandardNoResponse) {
1094   RegisterTestScheme("customnonstd", std::string());
1095   g_TestResults.url = "customnonstd:some%20value";
1096 
1097   CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
1098   handler->ExecuteTest();
1099   ReleaseAndWaitForDestructor(handler);
1100 
1101   EXPECT_TRUE(g_TestResults.got_request);
1102   EXPECT_FALSE(g_TestResults.got_read);
1103   EXPECT_FALSE(g_TestResults.got_output);
1104 
1105   ClearTestSchemes();
1106 }
1107 
1108 // Test that a custom standard scheme can generate redirects.
TEST(SchemeHandlerTest,CustomStandardRedirect)1109 TEST(SchemeHandlerTest, CustomStandardRedirect) {
1110   RegisterTestScheme("customstd", "test");
1111   g_TestResults.url = "customstd://test/run.html";
1112   g_TestResults.redirect_url = "customstd://test/redirect.html";
1113   g_TestResults.html =
1114       "<html><head></head><body><h1>Redirected</h1></body></html>";
1115 
1116   CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
1117   handler->ExecuteTest();
1118   ReleaseAndWaitForDestructor(handler);
1119 
1120   EXPECT_TRUE(g_TestResults.got_request);
1121   EXPECT_TRUE(g_TestResults.got_read);
1122   EXPECT_TRUE(g_TestResults.got_output);
1123   EXPECT_TRUE(g_TestResults.got_redirect);
1124 
1125   ClearTestSchemes();
1126 }
1127 
1128 // Test that a custom nonstandard scheme can generate redirects.
TEST(SchemeHandlerTest,CustomNonStandardRedirect)1129 TEST(SchemeHandlerTest, CustomNonStandardRedirect) {
1130   RegisterTestScheme("customnonstd", std::string());
1131   g_TestResults.url = "customnonstd:some%20value";
1132   g_TestResults.redirect_url = "customnonstd:some%20other%20value";
1133   g_TestResults.html =
1134       "<html><head></head><body><h1>Redirected</h1></body></html>";
1135 
1136   CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
1137   handler->ExecuteTest();
1138   ReleaseAndWaitForDestructor(handler);
1139 
1140   EXPECT_TRUE(g_TestResults.got_request);
1141   EXPECT_TRUE(g_TestResults.got_read);
1142   EXPECT_TRUE(g_TestResults.got_output);
1143   EXPECT_TRUE(g_TestResults.got_redirect);
1144 
1145   ClearTestSchemes();
1146 }
1147 
1148 // Test that a custom standard scheme can generate same origin XHR requests.
TEST(SchemeHandlerTest,CustomStandardXHRSameOriginSync)1149 TEST(SchemeHandlerTest, CustomStandardXHRSameOriginSync) {
1150   RegisterTestScheme("customstd", "test");
1151 
1152   XHRTestSettings settings;
1153   settings.url = "customstd://test/run.html";
1154   settings.sub_url = "customstd://test/xhr.html";
1155   SetUpXHR(settings);
1156 
1157   CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
1158   handler->ExecuteTest();
1159   ReleaseAndWaitForDestructor(handler);
1160 
1161   EXPECT_TRUE(g_TestResults.got_request);
1162   EXPECT_TRUE(g_TestResults.got_read);
1163   EXPECT_TRUE(g_TestResults.got_output);
1164   EXPECT_TRUE(g_TestResults.got_sub_request);
1165   EXPECT_TRUE(g_TestResults.got_sub_read);
1166   EXPECT_TRUE(g_TestResults.got_sub_success);
1167 
1168   ClearTestSchemes();
1169 }
1170 
1171 // Test that a custom standard scheme can generate same origin XHR requests.
TEST(SchemeHandlerTest,CustomStandardXHRSameOriginAsync)1172 TEST(SchemeHandlerTest, CustomStandardXHRSameOriginAsync) {
1173   RegisterTestScheme("customstd", "test");
1174 
1175   XHRTestSettings settings;
1176   settings.url = "customstd://test/run.html";
1177   settings.sub_url = "customstd://test/xhr.html";
1178   settings.synchronous = false;
1179   SetUpXHR(settings);
1180 
1181   CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
1182   handler->ExecuteTest();
1183   ReleaseAndWaitForDestructor(handler);
1184 
1185   EXPECT_TRUE(g_TestResults.got_request);
1186   EXPECT_TRUE(g_TestResults.got_read);
1187   EXPECT_TRUE(g_TestResults.got_output);
1188   EXPECT_TRUE(g_TestResults.got_sub_request);
1189   EXPECT_TRUE(g_TestResults.got_sub_read);
1190   EXPECT_TRUE(g_TestResults.got_sub_success);
1191 
1192   ClearTestSchemes();
1193 }
1194 
1195 // Test that custom nonstandard schemes are treated as unique origins that
1196 // cannot generate XHR requests.
TEST(SchemeHandlerTest,CustomNonStandardXHRSameOriginSync)1197 TEST(SchemeHandlerTest, CustomNonStandardXHRSameOriginSync) {
1198   RegisterTestScheme("customnonstd", std::string());
1199 
1200   XHRTestSettings settings;
1201   settings.url = "customnonstd:some%20value";
1202   settings.sub_url = "customnonstd:xhr%20value";
1203   SetUpXHR(settings);
1204 
1205   g_TestResults.console_messages.push_back(
1206       "Access to XMLHttpRequest at 'customnonstd:xhr%20value' from origin "
1207       "'null' has been blocked by CORS policy: Cross origin requests are only "
1208       "supported for protocol schemes:");
1209 
1210   CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
1211   handler->ExecuteTest();
1212   ReleaseAndWaitForDestructor(handler);
1213 
1214   EXPECT_TRUE(g_TestResults.got_request);
1215   EXPECT_TRUE(g_TestResults.got_read);
1216   EXPECT_TRUE(g_TestResults.got_output);
1217   EXPECT_FALSE(g_TestResults.got_sub_request);
1218   EXPECT_FALSE(g_TestResults.got_sub_read);
1219   EXPECT_FALSE(g_TestResults.got_sub_success);
1220 
1221   ClearTestSchemes();
1222 }
1223 
1224 // Test that custom nonstandard schemes are treated as unique origins that
1225 // cannot generate XHR requests.
TEST(SchemeHandlerTest,CustomNonStandardXHRSameOriginAsync)1226 TEST(SchemeHandlerTest, CustomNonStandardXHRSameOriginAsync) {
1227   RegisterTestScheme("customnonstd", std::string());
1228 
1229   XHRTestSettings settings;
1230   settings.url = "customnonstd:some%20value";
1231   settings.sub_url = "customnonstd:xhr%20value";
1232   settings.synchronous = false;
1233   SetUpXHR(settings);
1234 
1235   g_TestResults.console_messages.push_back(
1236       "Access to XMLHttpRequest at 'customnonstd:xhr%20value' from origin "
1237       "'null' has been blocked by CORS policy: Cross origin requests are only "
1238       "supported for protocol schemes:");
1239 
1240   CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
1241   handler->ExecuteTest();
1242   ReleaseAndWaitForDestructor(handler);
1243 
1244   EXPECT_TRUE(g_TestResults.got_request);
1245   EXPECT_TRUE(g_TestResults.got_read);
1246   EXPECT_TRUE(g_TestResults.got_output);
1247   EXPECT_FALSE(g_TestResults.got_sub_request);
1248   EXPECT_FALSE(g_TestResults.got_sub_read);
1249   EXPECT_FALSE(g_TestResults.got_sub_success);
1250 
1251   ClearTestSchemes();
1252 }
1253 
1254 // Test that a non fetch enabled custom standard scheme can't generate same
1255 // origin Fetch requests.
TEST(SchemeHandlerTest,CustomStandardFetchSameOrigin)1256 TEST(SchemeHandlerTest, CustomStandardFetchSameOrigin) {
1257   RegisterTestScheme("customstd", "test");
1258 
1259   FetchTestSettings settings;
1260   settings.url = "customstd://test/run.html";
1261   settings.sub_url = "customstd://test/fetch.html";
1262   SetUpFetch(settings);
1263 
1264   g_TestResults.console_messages.push_back(
1265       "Fetch API cannot load customstd://test/fetch.html. URL scheme "
1266       "\"customstd\" is not supported.");
1267 
1268   CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
1269   handler->ExecuteTest();
1270   ReleaseAndWaitForDestructor(handler);
1271 
1272   EXPECT_TRUE(g_TestResults.got_request);
1273   EXPECT_TRUE(g_TestResults.got_read);
1274   EXPECT_TRUE(g_TestResults.got_output);
1275   EXPECT_FALSE(g_TestResults.got_sub_request);
1276   EXPECT_FALSE(g_TestResults.got_sub_read);
1277   EXPECT_FALSE(g_TestResults.got_sub_success);
1278 
1279   ClearTestSchemes();
1280 }
1281 
1282 // Test that a fetch enabled custom standard scheme can generate same origin
1283 // Fetch requests.
TEST(SchemeHandlerTest,FetchCustomStandardFetchSameOrigin)1284 TEST(SchemeHandlerTest, FetchCustomStandardFetchSameOrigin) {
1285   RegisterTestScheme("customstdfetch", "test");
1286 
1287   FetchTestSettings settings;
1288   settings.url = "customstdfetch://test/run.html";
1289   settings.sub_url = "customstdfetch://test/fetch.html";
1290   SetUpFetch(settings);
1291 
1292   CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
1293   handler->ExecuteTest();
1294   ReleaseAndWaitForDestructor(handler);
1295 
1296   EXPECT_TRUE(g_TestResults.got_request);
1297   EXPECT_TRUE(g_TestResults.got_read);
1298   EXPECT_TRUE(g_TestResults.got_output);
1299   EXPECT_TRUE(g_TestResults.got_sub_request);
1300   EXPECT_TRUE(g_TestResults.got_sub_read);
1301   EXPECT_TRUE(g_TestResults.got_sub_success);
1302 
1303   ClearTestSchemes();
1304 }
1305 
1306 // Test that custom nonstandard schemes are treated as unique origins that
1307 // cannot generate Fetch requests.
TEST(SchemeHandlerTest,CustomNonStandardFetchSameOrigin)1308 TEST(SchemeHandlerTest, CustomNonStandardFetchSameOrigin) {
1309   RegisterTestScheme("customnonstd", std::string());
1310 
1311   FetchTestSettings settings;
1312   settings.url = "customnonstd:some%20value";
1313   settings.sub_url = "customnonstd:xhr%20value";
1314   SetUpFetch(settings);
1315 
1316   g_TestResults.console_messages.push_back(
1317       "Fetch API cannot load customnonstd:xhr%20value. URL scheme "
1318       "\"customnonstd\" is not supported.");
1319 
1320   CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
1321   handler->ExecuteTest();
1322   ReleaseAndWaitForDestructor(handler);
1323 
1324   EXPECT_TRUE(g_TestResults.got_request);
1325   EXPECT_TRUE(g_TestResults.got_read);
1326   EXPECT_TRUE(g_TestResults.got_output);
1327   EXPECT_FALSE(g_TestResults.got_sub_request);
1328   EXPECT_FALSE(g_TestResults.got_sub_read);
1329   EXPECT_FALSE(g_TestResults.got_sub_success);
1330 
1331   ClearTestSchemes();
1332 }
1333 
1334 // Test that a custom standard scheme can generate same origin XSS requests.
TEST(SchemeHandlerTest,CustomStandardXSSSameOrigin)1335 TEST(SchemeHandlerTest, CustomStandardXSSSameOrigin) {
1336   RegisterTestScheme("customstd", "test");
1337   SetUpXSS("customstd://test/run.html", "customstd://test/iframe.html");
1338 
1339   CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
1340   handler->ExecuteTest();
1341   ReleaseAndWaitForDestructor(handler);
1342 
1343   EXPECT_TRUE(g_TestResults.got_request);
1344   EXPECT_TRUE(g_TestResults.got_read);
1345   EXPECT_TRUE(g_TestResults.got_output);
1346   EXPECT_TRUE(g_TestResults.got_sub_request);
1347   EXPECT_TRUE(g_TestResults.got_sub_read);
1348   EXPECT_TRUE(g_TestResults.got_sub_success);
1349 
1350   ClearTestSchemes();
1351 }
1352 
1353 // Test that custom nonstandard schemes are treated as unique origins that
1354 // cannot generate XSS requests.
TEST(SchemeHandlerTest,CustomNonStandardXSSSameOrigin)1355 TEST(SchemeHandlerTest, CustomNonStandardXSSSameOrigin) {
1356   RegisterTestScheme("customnonstd", std::string());
1357   SetUpXSS("customnonstd:some%20value", "customnonstd:xhr%20value");
1358 
1359   g_TestResults.console_messages.push_back(
1360       "Error: Blocked a frame with origin \"null\" from accessing a "
1361       "cross-origin frame.");
1362 
1363   CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
1364   handler->ExecuteTest();
1365   ReleaseAndWaitForDestructor(handler);
1366 
1367   EXPECT_TRUE(g_TestResults.got_request);
1368   EXPECT_TRUE(g_TestResults.got_read);
1369   EXPECT_TRUE(g_TestResults.got_output);
1370   EXPECT_TRUE(g_TestResults.got_sub_request);
1371   EXPECT_TRUE(g_TestResults.got_sub_read);
1372   EXPECT_FALSE(g_TestResults.got_sub_success);
1373 
1374   ClearTestSchemes();
1375 }
1376 
1377 // Test that a custom standard scheme cannot generate cross-domain XHR requests
1378 // by default. Behavior should be the same as with HTTP.
TEST(SchemeHandlerTest,CustomStandardXHRDifferentOriginSync)1379 TEST(SchemeHandlerTest, CustomStandardXHRDifferentOriginSync) {
1380   RegisterTestScheme("customstd", "test1");
1381   RegisterTestScheme("customstd", "test2");
1382 
1383   XHRTestSettings settings;
1384   settings.url = "customstd://test1/run.html";
1385   settings.sub_url = "customstd://test2/xhr.html";
1386   SetUpXHR(settings);
1387 
1388   g_TestResults.console_messages.push_back(
1389       "Access to XMLHttpRequest at 'customstd://test2/xhr.html' from origin "
1390       "'customstd://test1' has been blocked by CORS policy: No "
1391       "'Access-Control-Allow-Origin' header is present on the requested "
1392       "resource.");
1393 
1394   CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
1395   handler->ExecuteTest();
1396   ReleaseAndWaitForDestructor(handler);
1397 
1398   EXPECT_TRUE(g_TestResults.got_request);
1399   EXPECT_TRUE(g_TestResults.got_read);
1400   EXPECT_TRUE(g_TestResults.got_output);
1401   EXPECT_TRUE(g_TestResults.got_sub_request);
1402   EXPECT_FALSE(g_TestResults.got_sub_read);
1403   EXPECT_FALSE(g_TestResults.got_sub_success);
1404 
1405   ClearTestSchemes();
1406 }
1407 
1408 // Test that a custom standard scheme cannot generate cross-domain XHR requests
1409 // by default. Behavior should be the same as with HTTP.
TEST(SchemeHandlerTest,CustomStandardXHRDifferentOriginAsync)1410 TEST(SchemeHandlerTest, CustomStandardXHRDifferentOriginAsync) {
1411   RegisterTestScheme("customstd", "test1");
1412   RegisterTestScheme("customstd", "test2");
1413 
1414   XHRTestSettings settings;
1415   settings.url = "customstd://test1/run.html";
1416   settings.sub_url = "customstd://test2/xhr.html";
1417   settings.synchronous = false;
1418   SetUpXHR(settings);
1419 
1420   g_TestResults.console_messages.push_back(
1421       "Access to XMLHttpRequest at 'customstd://test2/xhr.html' from origin "
1422       "'customstd://test1' has been blocked by CORS policy: No "
1423       "'Access-Control-Allow-Origin' header is present on the requested "
1424       "resource.");
1425 
1426   CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
1427   handler->ExecuteTest();
1428   ReleaseAndWaitForDestructor(handler);
1429 
1430   EXPECT_TRUE(g_TestResults.got_request);
1431   EXPECT_TRUE(g_TestResults.got_read);
1432   EXPECT_TRUE(g_TestResults.got_output);
1433   EXPECT_TRUE(g_TestResults.got_sub_request);
1434   EXPECT_FALSE(g_TestResults.got_sub_read);
1435   EXPECT_FALSE(g_TestResults.got_sub_success);
1436 
1437   ClearTestSchemes();
1438 }
1439 
1440 // Test that a custom standard scheme cannot generate cross-domain Fetch
1441 // requests by default. Behavior should be the same as with HTTP.
TEST(SchemeHandlerTest,CustomStandardFetchDifferentOrigin)1442 TEST(SchemeHandlerTest, CustomStandardFetchDifferentOrigin) {
1443   RegisterTestScheme("customstdfetch", "test1");
1444   RegisterTestScheme("customstdfetch", "test2");
1445 
1446   FetchTestSettings settings;
1447   settings.url = "customstdfetch://test1/run.html";
1448   settings.sub_url = "customstdfetch://test2/fetch.html";
1449   SetUpFetch(settings);
1450 
1451   g_TestResults.console_messages.push_back(
1452       "Access to fetch at 'customstdfetch://test2/fetch.html' from origin "
1453       "'customstdfetch://test1' has been blocked by CORS policy: No "
1454       "'Access-Control-Allow-Origin' header is present on the requested "
1455       "resource. If an opaque response serves your needs, set the request's "
1456       "mode to 'no-cors' to fetch the resource with CORS disabled.");
1457 
1458   CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
1459   handler->ExecuteTest();
1460   ReleaseAndWaitForDestructor(handler);
1461 
1462   EXPECT_TRUE(g_TestResults.got_request);
1463   EXPECT_TRUE(g_TestResults.got_read);
1464   EXPECT_TRUE(g_TestResults.got_output);
1465   EXPECT_TRUE(g_TestResults.got_sub_request);
1466   EXPECT_FALSE(g_TestResults.got_sub_read);
1467   EXPECT_FALSE(g_TestResults.got_sub_success);
1468 
1469   ClearTestSchemes();
1470 }
1471 
1472 // Test that a custom standard scheme cannot generate cross-domain XSS requests
1473 // by default.
TEST(SchemeHandlerTest,CustomStandardXSSDifferentOrigin)1474 TEST(SchemeHandlerTest, CustomStandardXSSDifferentOrigin) {
1475   RegisterTestScheme("customstd", "test1");
1476   RegisterTestScheme("customstd", "test2");
1477   SetUpXSS("customstd://test1/run.html", "customstd://test2/iframe.html");
1478 
1479   g_TestResults.console_messages.push_back(
1480       "Error: Blocked a frame with origin \"customstd://test2\" from accessing "
1481       "a cross-origin frame.");
1482 
1483   CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
1484   handler->ExecuteTest();
1485   ReleaseAndWaitForDestructor(handler);
1486 
1487   EXPECT_TRUE(g_TestResults.got_request);
1488   EXPECT_TRUE(g_TestResults.got_read);
1489   EXPECT_TRUE(g_TestResults.got_output);
1490   EXPECT_TRUE(g_TestResults.got_sub_request);
1491   EXPECT_TRUE(g_TestResults.got_sub_read);
1492   EXPECT_FALSE(g_TestResults.got_sub_success);
1493 
1494   ClearTestSchemes();
1495 }
1496 
1497 // Test that a cross-protocol iframe load succeeds, and that the custom
1498 // standard scheme cannot generate XSS requests to the HTTP protocol by default.
TEST(SchemeHandlerTest,CustomStandardXSSDifferentProtocolHttp)1499 TEST(SchemeHandlerTest, CustomStandardXSSDifferentProtocolHttp) {
1500   RegisterTestScheme("customstd", "test1");
1501   RegisterTestScheme("http", "test2");
1502   SetUpXSS("customstd://test1/run.html", "http://test2/iframe.html");
1503 
1504   g_TestResults.console_messages.push_back(
1505       "Error: Blocked a frame with origin \"http://test2\" from accessing a "
1506       "cross-origin frame.");
1507 
1508   CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
1509   handler->ExecuteTest();
1510   ReleaseAndWaitForDestructor(handler);
1511 
1512   EXPECT_TRUE(g_TestResults.got_request);
1513   EXPECT_TRUE(g_TestResults.got_read);
1514   EXPECT_TRUE(g_TestResults.got_output);
1515   EXPECT_TRUE(g_TestResults.got_sub_request);
1516   EXPECT_TRUE(g_TestResults.got_sub_read);
1517   EXPECT_FALSE(g_TestResults.got_sub_success);
1518 
1519   ClearTestSchemes();
1520 }
1521 
1522 // Test that a cross-protocol iframe load succeeds, and that the custom
1523 // standard scheme cannot generate XSS requests to a non-standard scheme by
1524 // default.
TEST(SchemeHandlerTest,CustomStandardXSSDifferentProtocolCustomNonStandard)1525 TEST(SchemeHandlerTest, CustomStandardXSSDifferentProtocolCustomNonStandard) {
1526   RegisterTestScheme("customstd", "test1");
1527   RegisterTestScheme("customnonstd", std::string());
1528   SetUpXSS("customstd://test1/run.html", "customnonstd:some%20value");
1529 
1530   g_TestResults.console_messages.push_back(
1531       "Error: Blocked a frame with origin \"null\" from accessing a "
1532       "cross-origin frame.");
1533 
1534   CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
1535   handler->ExecuteTest();
1536   ReleaseAndWaitForDestructor(handler);
1537 
1538   EXPECT_TRUE(g_TestResults.got_request);
1539   EXPECT_TRUE(g_TestResults.got_read);
1540   EXPECT_TRUE(g_TestResults.got_output);
1541   EXPECT_TRUE(g_TestResults.got_sub_request);
1542   EXPECT_TRUE(g_TestResults.got_sub_read);
1543   EXPECT_FALSE(g_TestResults.got_sub_success);
1544 
1545   ClearTestSchemes();
1546 }
1547 
1548 // Test that a cross-protocol iframe load succeeds, and that the HTTP protocol
1549 // cannot generate XSS requests to the custom standard scheme by default.
TEST(SchemeHandlerTest,HttpXSSDifferentProtocolCustomStandard)1550 TEST(SchemeHandlerTest, HttpXSSDifferentProtocolCustomStandard) {
1551   RegisterTestScheme("http", "test1");
1552   RegisterTestScheme("customstd", "test2");
1553   SetUpXSS("http://test1/run.html", "customstd://test2/iframe.html");
1554 
1555   g_TestResults.console_messages.push_back(
1556       "Error: Blocked a frame with origin \"customstd://test2\" from accessing "
1557       "a cross-origin frame.");
1558 
1559   CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
1560   handler->ExecuteTest();
1561   ReleaseAndWaitForDestructor(handler);
1562 
1563   EXPECT_TRUE(g_TestResults.got_request);
1564   EXPECT_TRUE(g_TestResults.got_read);
1565   EXPECT_TRUE(g_TestResults.got_output);
1566   EXPECT_TRUE(g_TestResults.got_sub_request);
1567   EXPECT_TRUE(g_TestResults.got_sub_read);
1568   EXPECT_FALSE(g_TestResults.got_sub_success);
1569 
1570   ClearTestSchemes();
1571 }
1572 
1573 // Test that a cross-protocol iframe load succeeds, and that the HTTP protocol
1574 // cannot generate XSS requests to the custom non-standard scheme by default.
TEST(SchemeHandlerTest,HttpXSSDifferentProtocolCustomNonStandard)1575 TEST(SchemeHandlerTest, HttpXSSDifferentProtocolCustomNonStandard) {
1576   RegisterTestScheme("http", "test1");
1577   RegisterTestScheme("customnonstd", std::string());
1578   SetUpXSS("http://test1/run.html", "customnonstd:some%20value");
1579 
1580   g_TestResults.console_messages.push_back(
1581       "Error: Blocked a frame with origin \"null\" from accessing a "
1582       "cross-origin frame.");
1583 
1584   CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
1585   handler->ExecuteTest();
1586   ReleaseAndWaitForDestructor(handler);
1587 
1588   EXPECT_TRUE(g_TestResults.got_request);
1589   EXPECT_TRUE(g_TestResults.got_read);
1590   EXPECT_TRUE(g_TestResults.got_output);
1591   EXPECT_TRUE(g_TestResults.got_sub_request);
1592   EXPECT_TRUE(g_TestResults.got_sub_read);
1593   EXPECT_FALSE(g_TestResults.got_sub_success);
1594 
1595   ClearTestSchemes();
1596 }
1597 
1598 // Test that an HTTP scheme cannot generate cross-domain XHR requests by
1599 // default.
TEST(SchemeHandlerTest,HttpXHRDifferentOriginSync)1600 TEST(SchemeHandlerTest, HttpXHRDifferentOriginSync) {
1601   RegisterTestScheme("http", "test1");
1602   RegisterTestScheme("http", "test2");
1603 
1604   XHRTestSettings settings;
1605   settings.url = "http://test1/run.html";
1606   settings.sub_url = "http://test2/xhr.html";
1607   SetUpXHR(settings);
1608 
1609   g_TestResults.console_messages.push_back(
1610       "Access to XMLHttpRequest at 'http://test2/xhr.html' from origin "
1611       "'http://test1' has been blocked by CORS policy: No "
1612       "'Access-Control-Allow-Origin' header is present on the requested "
1613       "resource.");
1614 
1615   CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
1616   handler->ExecuteTest();
1617   ReleaseAndWaitForDestructor(handler);
1618 
1619   EXPECT_TRUE(g_TestResults.got_request);
1620   EXPECT_TRUE(g_TestResults.got_read);
1621   EXPECT_TRUE(g_TestResults.got_output);
1622   EXPECT_TRUE(g_TestResults.got_sub_request);
1623   EXPECT_FALSE(g_TestResults.got_sub_read);
1624   EXPECT_FALSE(g_TestResults.got_sub_success);
1625 
1626   ClearTestSchemes();
1627 }
1628 
1629 // Test that an HTTP scheme cannot generate cross-domain XHR requests by
1630 // default.
TEST(SchemeHandlerTest,HttpXHRDifferentOriginAsync)1631 TEST(SchemeHandlerTest, HttpXHRDifferentOriginAsync) {
1632   RegisterTestScheme("http", "test1");
1633   RegisterTestScheme("http", "test2");
1634 
1635   XHRTestSettings settings;
1636   settings.url = "http://test1/run.html";
1637   settings.sub_url = "http://test2/xhr.html";
1638   settings.synchronous = false;
1639   SetUpXHR(settings);
1640 
1641   g_TestResults.console_messages.push_back(
1642       "Access to XMLHttpRequest at 'http://test2/xhr.html' from origin "
1643       "'http://test1' has been blocked by CORS policy: No "
1644       "'Access-Control-Allow-Origin' header is present on the requested "
1645       "resource.");
1646 
1647   CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
1648   handler->ExecuteTest();
1649   ReleaseAndWaitForDestructor(handler);
1650 
1651   EXPECT_TRUE(g_TestResults.got_request);
1652   EXPECT_TRUE(g_TestResults.got_read);
1653   EXPECT_TRUE(g_TestResults.got_output);
1654   EXPECT_TRUE(g_TestResults.got_sub_request);
1655   EXPECT_FALSE(g_TestResults.got_sub_read);
1656   EXPECT_FALSE(g_TestResults.got_sub_success);
1657 
1658   ClearTestSchemes();
1659 }
1660 
1661 // Test that an HTTP scheme cannot generate cross-domain Fetch requests by
1662 // default.
TEST(SchemeHandlerTest,HttpFetchDifferentOriginAsync)1663 TEST(SchemeHandlerTest, HttpFetchDifferentOriginAsync) {
1664   RegisterTestScheme("http", "test1");
1665   RegisterTestScheme("http", "test2");
1666 
1667   FetchTestSettings settings;
1668   settings.url = "http://test1/run.html";
1669   settings.sub_url = "http://test2/fetch.html";
1670   SetUpFetch(settings);
1671 
1672   g_TestResults.console_messages.push_back(
1673       "Access to fetch at 'http://test2/fetch.html' from origin 'http://test1' "
1674       "has been blocked by CORS policy: No 'Access-Control-Allow-Origin' "
1675       "header is present on the requested resource. If an opaque response "
1676       "serves your needs, set the request's mode to 'no-cors' to fetch the "
1677       "resource with CORS disabled.");
1678 
1679   CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
1680   handler->ExecuteTest();
1681   ReleaseAndWaitForDestructor(handler);
1682 
1683   EXPECT_TRUE(g_TestResults.got_request);
1684   EXPECT_TRUE(g_TestResults.got_read);
1685   EXPECT_TRUE(g_TestResults.got_output);
1686   EXPECT_TRUE(g_TestResults.got_sub_request);
1687   EXPECT_FALSE(g_TestResults.got_sub_read);
1688   EXPECT_FALSE(g_TestResults.got_sub_success);
1689 
1690   ClearTestSchemes();
1691 }
1692 
1693 // Test that an HTTP scheme cannot generate cross-domain XSS requests by
1694 // default.
TEST(SchemeHandlerTest,HttpXSSDifferentOrigin)1695 TEST(SchemeHandlerTest, HttpXSSDifferentOrigin) {
1696   RegisterTestScheme("http", "test1");
1697   RegisterTestScheme("http", "test2");
1698   SetUpXSS("http://test1/run.html", "http://test2/xss.html");
1699 
1700   g_TestResults.console_messages.push_back(
1701       "Error: Blocked a frame with origin \"http://test2\" from accessing a "
1702       "cross-origin frame.");
1703 
1704   CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
1705   handler->ExecuteTest();
1706   ReleaseAndWaitForDestructor(handler);
1707 
1708   EXPECT_TRUE(g_TestResults.got_request);
1709   EXPECT_TRUE(g_TestResults.got_read);
1710   EXPECT_TRUE(g_TestResults.got_output);
1711   EXPECT_TRUE(g_TestResults.got_sub_request);
1712   EXPECT_TRUE(g_TestResults.got_sub_read);
1713   EXPECT_FALSE(g_TestResults.got_sub_success);
1714 
1715   ClearTestSchemes();
1716 }
1717 
1718 // Test that a custom standard scheme can generate cross-domain XHR requests
1719 // when setting the Access-Control-Allow-Origin header. Should behave the same
1720 // as HTTP.
TEST(SchemeHandlerTest,CustomStandardXHRDifferentOriginWithHeaderSync)1721 TEST(SchemeHandlerTest, CustomStandardXHRDifferentOriginWithHeaderSync) {
1722   RegisterTestScheme("customstd", "test1");
1723   RegisterTestScheme("customstd", "test2");
1724 
1725   XHRTestSettings settings;
1726   settings.url = "customstd://test1/run.html";
1727   settings.sub_url = "customstd://test2/xhr.html";
1728   settings.sub_allow_origin = "customstd://test1";
1729   SetUpXHR(settings);
1730 
1731   CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
1732   handler->ExecuteTest();
1733   ReleaseAndWaitForDestructor(handler);
1734 
1735   EXPECT_TRUE(g_TestResults.got_request);
1736   EXPECT_TRUE(g_TestResults.got_read);
1737   EXPECT_TRUE(g_TestResults.got_output);
1738   EXPECT_TRUE(g_TestResults.got_sub_request);
1739   EXPECT_TRUE(g_TestResults.got_sub_read);
1740   EXPECT_TRUE(g_TestResults.got_sub_success);
1741 
1742   ClearTestSchemes();
1743 }
1744 
1745 // Test that a custom standard scheme can generate cross-domain XHR requests
1746 // when setting the Access-Control-Allow-Origin header. Should behave the same
1747 // as HTTP.
TEST(SchemeHandlerTest,CustomStandardXHRDifferentOriginWithHeaderAsync)1748 TEST(SchemeHandlerTest, CustomStandardXHRDifferentOriginWithHeaderAsync) {
1749   RegisterTestScheme("customstd", "test1");
1750   RegisterTestScheme("customstd", "test2");
1751 
1752   XHRTestSettings settings;
1753   settings.url = "customstd://test1/run.html";
1754   settings.sub_url = "customstd://test2/xhr.html";
1755   settings.sub_allow_origin = "customstd://test1";
1756   settings.synchronous = false;
1757   SetUpXHR(settings);
1758 
1759   CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
1760   handler->ExecuteTest();
1761   ReleaseAndWaitForDestructor(handler);
1762 
1763   EXPECT_TRUE(g_TestResults.got_request);
1764   EXPECT_TRUE(g_TestResults.got_read);
1765   EXPECT_TRUE(g_TestResults.got_output);
1766   EXPECT_TRUE(g_TestResults.got_sub_request);
1767   EXPECT_TRUE(g_TestResults.got_sub_read);
1768   EXPECT_TRUE(g_TestResults.got_sub_success);
1769 
1770   ClearTestSchemes();
1771 }
1772 
1773 // Test that a custom standard scheme can generate cross-domain Fetch requests
1774 // when setting the Access-Control-Allow-Origin header. Should behave the same
1775 // as HTTP.
TEST(SchemeHandlerTest,CustomStandardFetchDifferentOriginWithHeader)1776 TEST(SchemeHandlerTest, CustomStandardFetchDifferentOriginWithHeader) {
1777   RegisterTestScheme("customstdfetch", "test1");
1778   RegisterTestScheme("customstdfetch", "test2");
1779 
1780   FetchTestSettings settings;
1781   settings.url = "customstdfetch://test1/run.html";
1782   settings.sub_url = "customstdfetch://test2/fetch.html";
1783   settings.sub_allow_origin = "customstdfetch://test1";
1784   SetUpFetch(settings);
1785 
1786   CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
1787   handler->ExecuteTest();
1788   ReleaseAndWaitForDestructor(handler);
1789 
1790   EXPECT_TRUE(g_TestResults.got_request);
1791   EXPECT_TRUE(g_TestResults.got_read);
1792   EXPECT_TRUE(g_TestResults.got_output);
1793   EXPECT_TRUE(g_TestResults.got_sub_request);
1794   EXPECT_TRUE(g_TestResults.got_sub_read);
1795   EXPECT_TRUE(g_TestResults.got_sub_success);
1796 
1797   ClearTestSchemes();
1798 }
1799 
1800 // Test that a custom standard scheme can generate cross-domain XHR requests
1801 // when using the cross-origin whitelist.
TEST(SchemeHandlerTest,CustomStandardXHRDifferentOriginWithWhitelistSync1)1802 TEST(SchemeHandlerTest, CustomStandardXHRDifferentOriginWithWhitelistSync1) {
1803   RegisterTestScheme("customstd", "test1");
1804   RegisterTestScheme("customstd", "test2");
1805 
1806   XHRTestSettings settings;
1807   settings.url = "customstd://test1/run.html";
1808   settings.sub_url = "customstd://test2/xhr.html";
1809   SetUpXHR(settings);
1810 
1811   EXPECT_TRUE(CefAddCrossOriginWhitelistEntry("customstd://test1", "customstd",
1812                                               "test2", false));
1813   WaitForUIThread();
1814 
1815   CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
1816   handler->ExecuteTest();
1817   ReleaseAndWaitForDestructor(handler);
1818 
1819   EXPECT_TRUE(g_TestResults.got_request);
1820   EXPECT_TRUE(g_TestResults.got_read);
1821   EXPECT_TRUE(g_TestResults.got_output);
1822   EXPECT_TRUE(g_TestResults.got_sub_request);
1823   EXPECT_TRUE(g_TestResults.got_sub_read);
1824   EXPECT_TRUE(g_TestResults.got_sub_success);
1825 
1826   EXPECT_TRUE(CefClearCrossOriginWhitelist());
1827   WaitForUIThread();
1828 
1829   ClearTestSchemes();
1830 }
1831 
1832 // Same as above but origin whitelist matches any domain.
TEST(SchemeHandlerTest,CustomStandardXHRDifferentOriginWithWhitelistSync2)1833 TEST(SchemeHandlerTest, CustomStandardXHRDifferentOriginWithWhitelistSync2) {
1834   RegisterTestScheme("customstd", "test1");
1835   RegisterTestScheme("customstd", "test2");
1836 
1837   XHRTestSettings settings;
1838   settings.url = "customstd://test1/run.html";
1839   settings.sub_url = "customstd://test2/xhr.html";
1840   SetUpXHR(settings);
1841 
1842   EXPECT_TRUE(CefAddCrossOriginWhitelistEntry("customstd://test1", "customstd",
1843                                               CefString(), true));
1844   WaitForUIThread();
1845 
1846   CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
1847   handler->ExecuteTest();
1848   ReleaseAndWaitForDestructor(handler);
1849 
1850   EXPECT_TRUE(g_TestResults.got_request);
1851   EXPECT_TRUE(g_TestResults.got_read);
1852   EXPECT_TRUE(g_TestResults.got_output);
1853   EXPECT_TRUE(g_TestResults.got_sub_request);
1854   EXPECT_TRUE(g_TestResults.got_sub_read);
1855   EXPECT_TRUE(g_TestResults.got_sub_success);
1856 
1857   EXPECT_TRUE(CefClearCrossOriginWhitelist());
1858   WaitForUIThread();
1859 
1860   ClearTestSchemes();
1861 }
1862 
1863 // Same as above but origin whitelist matches sub-domains.
TEST(SchemeHandlerTest,CustomStandardXHRDifferentOriginWithWhitelistSync3)1864 TEST(SchemeHandlerTest, CustomStandardXHRDifferentOriginWithWhitelistSync3) {
1865   RegisterTestScheme("customstd", "test1");
1866   RegisterTestScheme("customstd", "a.test2.foo");
1867 
1868   XHRTestSettings settings;
1869   settings.url = "customstd://test1/run.html";
1870   settings.sub_url = "customstd://a.test2.foo/xhr.html";
1871   SetUpXHR(settings);
1872 
1873   EXPECT_TRUE(CefAddCrossOriginWhitelistEntry("customstd://test1", "customstd",
1874                                               "test2.foo", true));
1875   WaitForUIThread();
1876 
1877   CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
1878   handler->ExecuteTest();
1879   ReleaseAndWaitForDestructor(handler);
1880 
1881   EXPECT_TRUE(g_TestResults.got_request);
1882   EXPECT_TRUE(g_TestResults.got_read);
1883   EXPECT_TRUE(g_TestResults.got_output);
1884   EXPECT_TRUE(g_TestResults.got_sub_request);
1885   EXPECT_TRUE(g_TestResults.got_sub_read);
1886   EXPECT_TRUE(g_TestResults.got_sub_success);
1887 
1888   EXPECT_TRUE(CefClearCrossOriginWhitelist());
1889   WaitForUIThread();
1890 
1891   ClearTestSchemes();
1892 }
1893 
1894 // Test that a custom standard scheme can generate cross-domain XHR requests
1895 // when using the cross-origin whitelist.
TEST(SchemeHandlerTest,CustomStandardXHRDifferentOriginWithWhitelistAsync1)1896 TEST(SchemeHandlerTest, CustomStandardXHRDifferentOriginWithWhitelistAsync1) {
1897   RegisterTestScheme("customstd", "test1");
1898   RegisterTestScheme("customstd", "test2");
1899 
1900   XHRTestSettings settings;
1901   settings.url = "customstd://test1/run.html";
1902   settings.sub_url = "customstd://test2/xhr.html";
1903   settings.synchronous = false;
1904   SetUpXHR(settings);
1905 
1906   EXPECT_TRUE(CefAddCrossOriginWhitelistEntry("customstd://test1", "customstd",
1907                                               "test2", false));
1908   WaitForUIThread();
1909 
1910   CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
1911   handler->ExecuteTest();
1912   ReleaseAndWaitForDestructor(handler);
1913 
1914   EXPECT_TRUE(g_TestResults.got_request);
1915   EXPECT_TRUE(g_TestResults.got_read);
1916   EXPECT_TRUE(g_TestResults.got_output);
1917   EXPECT_TRUE(g_TestResults.got_sub_request);
1918   EXPECT_TRUE(g_TestResults.got_sub_read);
1919   EXPECT_TRUE(g_TestResults.got_sub_success);
1920 
1921   EXPECT_TRUE(CefClearCrossOriginWhitelist());
1922   WaitForUIThread();
1923 
1924   ClearTestSchemes();
1925 }
1926 
1927 // Same as above but origin whitelist matches any domain.
TEST(SchemeHandlerTest,CustomStandardXHRDifferentOriginWithWhitelistAsync2)1928 TEST(SchemeHandlerTest, CustomStandardXHRDifferentOriginWithWhitelistAsync2) {
1929   RegisterTestScheme("customstd", "test1");
1930   RegisterTestScheme("customstd", "test2");
1931 
1932   XHRTestSettings settings;
1933   settings.url = "customstd://test1/run.html";
1934   settings.sub_url = "customstd://test2/xhr.html";
1935   settings.synchronous = false;
1936   SetUpXHR(settings);
1937 
1938   EXPECT_TRUE(CefAddCrossOriginWhitelistEntry("customstd://test1", "customstd",
1939                                               CefString(), true));
1940   WaitForUIThread();
1941 
1942   CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
1943   handler->ExecuteTest();
1944   ReleaseAndWaitForDestructor(handler);
1945 
1946   EXPECT_TRUE(g_TestResults.got_request);
1947   EXPECT_TRUE(g_TestResults.got_read);
1948   EXPECT_TRUE(g_TestResults.got_output);
1949   EXPECT_TRUE(g_TestResults.got_sub_request);
1950   EXPECT_TRUE(g_TestResults.got_sub_read);
1951   EXPECT_TRUE(g_TestResults.got_sub_success);
1952 
1953   EXPECT_TRUE(CefClearCrossOriginWhitelist());
1954   WaitForUIThread();
1955 
1956   ClearTestSchemes();
1957 }
1958 
1959 // Same as above but origin whitelist matches sub-domains.
TEST(SchemeHandlerTest,CustomStandardXHRDifferentOriginWithWhitelistAsync3)1960 TEST(SchemeHandlerTest, CustomStandardXHRDifferentOriginWithWhitelistAsync3) {
1961   RegisterTestScheme("customstd", "test1");
1962   RegisterTestScheme("customstd", "a.test2.foo");
1963 
1964   XHRTestSettings settings;
1965   settings.url = "customstd://test1/run.html";
1966   settings.sub_url = "customstd://a.test2.foo/xhr.html";
1967   settings.synchronous = false;
1968   SetUpXHR(settings);
1969 
1970   EXPECT_TRUE(CefAddCrossOriginWhitelistEntry("customstd://test1", "customstd",
1971                                               "test2.foo", true));
1972   WaitForUIThread();
1973 
1974   CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
1975   handler->ExecuteTest();
1976   ReleaseAndWaitForDestructor(handler);
1977 
1978   EXPECT_TRUE(g_TestResults.got_request);
1979   EXPECT_TRUE(g_TestResults.got_read);
1980   EXPECT_TRUE(g_TestResults.got_output);
1981   EXPECT_TRUE(g_TestResults.got_sub_request);
1982   EXPECT_TRUE(g_TestResults.got_sub_read);
1983   EXPECT_TRUE(g_TestResults.got_sub_success);
1984 
1985   EXPECT_TRUE(CefClearCrossOriginWhitelist());
1986   WaitForUIThread();
1987 
1988   ClearTestSchemes();
1989 }
1990 
1991 // Test that a custom standard scheme can generate cross-domain Fetch requests
1992 // when using the cross-origin whitelist.
TEST(SchemeHandlerTest,CustomStandardFetchDifferentOriginWithWhitelist1)1993 TEST(SchemeHandlerTest, CustomStandardFetchDifferentOriginWithWhitelist1) {
1994   RegisterTestScheme("customstdfetch", "test1");
1995   RegisterTestScheme("customstdfetch", "test2");
1996 
1997   FetchTestSettings settings;
1998   settings.url = "customstdfetch://test1/run.html";
1999   settings.sub_url = "customstdfetch://test2/fetch.html";
2000   SetUpFetch(settings);
2001 
2002   EXPECT_TRUE(CefAddCrossOriginWhitelistEntry(
2003       "customstdfetch://test1", "customstdfetch", "test2", false));
2004   WaitForUIThread();
2005 
2006   CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
2007   handler->ExecuteTest();
2008   ReleaseAndWaitForDestructor(handler);
2009 
2010   EXPECT_TRUE(g_TestResults.got_request);
2011   EXPECT_TRUE(g_TestResults.got_read);
2012   EXPECT_TRUE(g_TestResults.got_output);
2013   EXPECT_TRUE(g_TestResults.got_sub_request);
2014   EXPECT_TRUE(g_TestResults.got_sub_read);
2015   EXPECT_TRUE(g_TestResults.got_sub_success);
2016 
2017   EXPECT_TRUE(CefClearCrossOriginWhitelist());
2018   WaitForUIThread();
2019 
2020   ClearTestSchemes();
2021 }
2022 
2023 // Same as above but origin whitelist matches any domain.
TEST(SchemeHandlerTest,CustomStandardFetchDifferentOriginWithWhitelist2)2024 TEST(SchemeHandlerTest, CustomStandardFetchDifferentOriginWithWhitelist2) {
2025   RegisterTestScheme("customstdfetch", "test1");
2026   RegisterTestScheme("customstdfetch", "test2");
2027 
2028   FetchTestSettings settings;
2029   settings.url = "customstdfetch://test1/run.html";
2030   settings.sub_url = "customstdfetch://test2/fetch.html";
2031   SetUpFetch(settings);
2032 
2033   EXPECT_TRUE(CefAddCrossOriginWhitelistEntry(
2034       "customstdfetch://test1", "customstdfetch", CefString(), true));
2035   WaitForUIThread();
2036 
2037   CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
2038   handler->ExecuteTest();
2039   ReleaseAndWaitForDestructor(handler);
2040 
2041   EXPECT_TRUE(g_TestResults.got_request);
2042   EXPECT_TRUE(g_TestResults.got_read);
2043   EXPECT_TRUE(g_TestResults.got_output);
2044   EXPECT_TRUE(g_TestResults.got_sub_request);
2045   EXPECT_TRUE(g_TestResults.got_sub_read);
2046   EXPECT_TRUE(g_TestResults.got_sub_success);
2047 
2048   EXPECT_TRUE(CefClearCrossOriginWhitelist());
2049   WaitForUIThread();
2050 
2051   ClearTestSchemes();
2052 }
2053 
2054 // Same as above but origin whitelist matches sub-domains.
TEST(SchemeHandlerTest,CustomStandardFetchDifferentOriginWithWhitelist3)2055 TEST(SchemeHandlerTest, CustomStandardFetchDifferentOriginWithWhitelist3) {
2056   RegisterTestScheme("customstdfetch", "test1");
2057   RegisterTestScheme("customstdfetch", "a.test2.foo");
2058 
2059   FetchTestSettings settings;
2060   settings.url = "customstdfetch://test1/run.html";
2061   settings.sub_url = "customstdfetch://a.test2.foo/fetch.html";
2062   SetUpFetch(settings);
2063 
2064   EXPECT_TRUE(CefAddCrossOriginWhitelistEntry(
2065       "customstdfetch://test1", "customstdfetch", "test2.foo", true));
2066   WaitForUIThread();
2067 
2068   CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
2069   handler->ExecuteTest();
2070   ReleaseAndWaitForDestructor(handler);
2071 
2072   EXPECT_TRUE(g_TestResults.got_request);
2073   EXPECT_TRUE(g_TestResults.got_read);
2074   EXPECT_TRUE(g_TestResults.got_output);
2075   EXPECT_TRUE(g_TestResults.got_sub_request);
2076   EXPECT_TRUE(g_TestResults.got_sub_read);
2077   EXPECT_TRUE(g_TestResults.got_sub_success);
2078 
2079   EXPECT_TRUE(CefClearCrossOriginWhitelist());
2080   WaitForUIThread();
2081 
2082   ClearTestSchemes();
2083 }
2084 
2085 // Test that an HTTP scheme can generate cross-domain XHR requests when setting
2086 // the Access-Control-Allow-Origin header.
TEST(SchemeHandlerTest,HttpXHRDifferentOriginWithHeaderSync)2087 TEST(SchemeHandlerTest, HttpXHRDifferentOriginWithHeaderSync) {
2088   RegisterTestScheme("http", "test1");
2089   RegisterTestScheme("http", "test2");
2090 
2091   XHRTestSettings settings;
2092   settings.url = "http://test1/run.html";
2093   settings.sub_url = "http://test2/xhr.html";
2094   settings.sub_allow_origin = "http://test1";
2095   SetUpXHR(settings);
2096 
2097   CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
2098   handler->ExecuteTest();
2099   ReleaseAndWaitForDestructor(handler);
2100 
2101   EXPECT_TRUE(g_TestResults.got_request);
2102   EXPECT_TRUE(g_TestResults.got_read);
2103   EXPECT_TRUE(g_TestResults.got_output);
2104   EXPECT_TRUE(g_TestResults.got_sub_request);
2105   EXPECT_TRUE(g_TestResults.got_sub_read);
2106   EXPECT_TRUE(g_TestResults.got_sub_success);
2107 
2108   ClearTestSchemes();
2109 }
2110 
2111 // Test that an HTTP scheme can generate cross-domain XHR requests when setting
2112 // the Access-Control-Allow-Origin header.
TEST(SchemeHandlerTest,HttpXHRDifferentOriginWithHeaderAsync)2113 TEST(SchemeHandlerTest, HttpXHRDifferentOriginWithHeaderAsync) {
2114   RegisterTestScheme("http", "test1");
2115   RegisterTestScheme("http", "test2");
2116 
2117   XHRTestSettings settings;
2118   settings.url = "http://test1/run.html";
2119   settings.sub_url = "http://test2/xhr.html";
2120   settings.sub_allow_origin = "http://test1";
2121   settings.synchronous = false;
2122   SetUpXHR(settings);
2123 
2124   CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
2125   handler->ExecuteTest();
2126   ReleaseAndWaitForDestructor(handler);
2127 
2128   EXPECT_TRUE(g_TestResults.got_request);
2129   EXPECT_TRUE(g_TestResults.got_read);
2130   EXPECT_TRUE(g_TestResults.got_output);
2131   EXPECT_TRUE(g_TestResults.got_sub_request);
2132   EXPECT_TRUE(g_TestResults.got_sub_read);
2133   EXPECT_TRUE(g_TestResults.got_sub_success);
2134 
2135   ClearTestSchemes();
2136 }
2137 
2138 // Test that an HTTP scheme can generate cross-domain XHR requests when setting
2139 // the Access-Control-Allow-Origin header.
TEST(SchemeHandlerTest,HttpFetchDifferentOriginWithHeader)2140 TEST(SchemeHandlerTest, HttpFetchDifferentOriginWithHeader) {
2141   RegisterTestScheme("http", "test1");
2142   RegisterTestScheme("http", "test2");
2143 
2144   FetchTestSettings settings;
2145   settings.url = "http://test1/run.html";
2146   settings.sub_url = "http://test2/fetch.html";
2147   settings.sub_allow_origin = "http://test1";
2148   SetUpFetch(settings);
2149 
2150   CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
2151   handler->ExecuteTest();
2152   ReleaseAndWaitForDestructor(handler);
2153 
2154   EXPECT_TRUE(g_TestResults.got_request);
2155   EXPECT_TRUE(g_TestResults.got_read);
2156   EXPECT_TRUE(g_TestResults.got_output);
2157   EXPECT_TRUE(g_TestResults.got_sub_request);
2158   EXPECT_TRUE(g_TestResults.got_sub_read);
2159   EXPECT_TRUE(g_TestResults.got_sub_success);
2160 
2161   ClearTestSchemes();
2162 }
2163 
2164 // Test that a custom standard scheme can generate cross-domain XSS requests
2165 // when using document.domain.
TEST(SchemeHandlerTest,CustomStandardXSSDifferentOriginWithDomain)2166 TEST(SchemeHandlerTest, CustomStandardXSSDifferentOriginWithDomain) {
2167   RegisterTestScheme("customstd", "a.test.com");
2168   RegisterTestScheme("customstd", "b.test.com");
2169   SetUpXSS("customstd://a.test.com/run.html",
2170            "customstd://b.test.com/iframe.html", "test.com");
2171 
2172   CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
2173   handler->ExecuteTest();
2174   ReleaseAndWaitForDestructor(handler);
2175 
2176   EXPECT_TRUE(g_TestResults.got_request);
2177   EXPECT_TRUE(g_TestResults.got_read);
2178   EXPECT_TRUE(g_TestResults.got_output);
2179   EXPECT_TRUE(g_TestResults.got_sub_request);
2180   EXPECT_TRUE(g_TestResults.got_sub_read);
2181   EXPECT_TRUE(g_TestResults.got_sub_success);
2182 
2183   ClearTestSchemes();
2184 }
2185 
2186 // Test that an HTTP scheme can generate cross-domain XSS requests when using
2187 // document.domain.
TEST(SchemeHandlerTest,HttpXSSDifferentOriginWithDomain)2188 TEST(SchemeHandlerTest, HttpXSSDifferentOriginWithDomain) {
2189   RegisterTestScheme("http", "a.test.com");
2190   RegisterTestScheme("http", "b.test.com");
2191   SetUpXSS("http://a.test.com/run.html", "http://b.test.com/iframe.html",
2192            "test.com");
2193 
2194   CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
2195   handler->ExecuteTest();
2196   ReleaseAndWaitForDestructor(handler);
2197 
2198   EXPECT_TRUE(g_TestResults.got_request);
2199   EXPECT_TRUE(g_TestResults.got_read);
2200   EXPECT_TRUE(g_TestResults.got_output);
2201   EXPECT_TRUE(g_TestResults.got_sub_request);
2202   EXPECT_TRUE(g_TestResults.got_sub_read);
2203   EXPECT_TRUE(g_TestResults.got_sub_success);
2204 
2205   ClearTestSchemes();
2206 }
2207 
2208 // Test that a custom standard scheme cannot generate cross-domain XHR requests
2209 // that perform redirects.
TEST(SchemeHandlerTest,CustomStandardXHRDifferentOriginRedirectSync)2210 TEST(SchemeHandlerTest, CustomStandardXHRDifferentOriginRedirectSync) {
2211   RegisterTestScheme("customstd", "test1");
2212   RegisterTestScheme("customstd", "test2");
2213 
2214   XHRTestSettings settings;
2215   settings.url = "customstd://test1/run.html";
2216   settings.sub_url = "customstd://test2/xhr.html";
2217   settings.sub_redirect_url = "customstd://test1/xhr.html";
2218   SetUpXHR(settings);
2219 
2220   g_TestResults.console_messages.push_back(
2221       "Access to XMLHttpRequest at 'customstd://test2/xhr.html' (redirected "
2222       "from 'customstd://test1/xhr.html') from origin 'customstd://test1' has "
2223       "been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is "
2224       "present on the requested resource.");
2225 
2226   CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
2227   handler->ExecuteTest();
2228   ReleaseAndWaitForDestructor(handler);
2229 
2230   EXPECT_TRUE(g_TestResults.got_request);
2231   EXPECT_TRUE(g_TestResults.got_read);
2232   EXPECT_TRUE(g_TestResults.got_output);
2233   EXPECT_TRUE(g_TestResults.got_sub_redirect);
2234   EXPECT_TRUE(g_TestResults.got_sub_request);
2235   EXPECT_FALSE(g_TestResults.got_sub_read);
2236   EXPECT_FALSE(g_TestResults.got_sub_success);
2237 
2238   ClearTestSchemes();
2239 }
2240 
2241 // Test that a custom standard scheme cannot generate cross-domain XHR requests
2242 // that perform redirects.
TEST(SchemeHandlerTest,CustomStandardXHRDifferentOriginRedirectAsync)2243 TEST(SchemeHandlerTest, CustomStandardXHRDifferentOriginRedirectAsync) {
2244   RegisterTestScheme("customstd", "test1");
2245   RegisterTestScheme("customstd", "test2");
2246 
2247   XHRTestSettings settings;
2248   settings.url = "customstd://test1/run.html";
2249   settings.sub_url = "customstd://test2/xhr.html";
2250   settings.sub_redirect_url = "customstd://test1/xhr.html";
2251   settings.synchronous = false;
2252   SetUpXHR(settings);
2253 
2254   g_TestResults.console_messages.push_back(
2255       "Access to XMLHttpRequest at 'customstd://test2/xhr.html' (redirected "
2256       "from 'customstd://test1/xhr.html') from origin 'customstd://test1' has "
2257       "been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is "
2258       "present on the requested resource.");
2259 
2260   CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
2261   handler->ExecuteTest();
2262   ReleaseAndWaitForDestructor(handler);
2263 
2264   EXPECT_TRUE(g_TestResults.got_request);
2265   EXPECT_TRUE(g_TestResults.got_read);
2266   EXPECT_TRUE(g_TestResults.got_output);
2267   EXPECT_TRUE(g_TestResults.got_sub_redirect);
2268   EXPECT_TRUE(g_TestResults.got_sub_request);
2269   EXPECT_FALSE(g_TestResults.got_sub_read);
2270   EXPECT_FALSE(g_TestResults.got_sub_success);
2271 
2272   ClearTestSchemes();
2273 }
2274 
2275 // Test that a custom standard scheme cannot generate cross-domain Fetch
2276 // requests that perform redirects.
TEST(SchemeHandlerTest,CustomStandardFetchDifferentOriginRedirect)2277 TEST(SchemeHandlerTest, CustomStandardFetchDifferentOriginRedirect) {
2278   RegisterTestScheme("customstdfetch", "test1");
2279   RegisterTestScheme("customstdfetch", "test2");
2280 
2281   FetchTestSettings settings;
2282   settings.url = "customstdfetch://test1/run.html";
2283   settings.sub_url = "customstdfetch://test2/fetch.html";
2284   settings.sub_redirect_url = "customstdfetch://test1/fetch.html";
2285   SetUpFetch(settings);
2286 
2287   g_TestResults.console_messages.push_back(
2288       "Access to fetch at 'customstdfetch://test2/fetch.html' (redirected from "
2289       "'customstdfetch://test1/fetch.html') from origin "
2290       "'customstdfetch://test1' has been blocked by CORS policy: No "
2291       "'Access-Control-Allow-Origin' header is present on the requested "
2292       "resource. If an opaque response serves your needs, set the request's "
2293       "mode to 'no-cors' to fetch the resource with CORS disabled.");
2294 
2295   CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
2296   handler->ExecuteTest();
2297   ReleaseAndWaitForDestructor(handler);
2298 
2299   EXPECT_TRUE(g_TestResults.got_request);
2300   EXPECT_TRUE(g_TestResults.got_read);
2301   EXPECT_TRUE(g_TestResults.got_output);
2302   EXPECT_TRUE(g_TestResults.got_sub_redirect);
2303   EXPECT_TRUE(g_TestResults.got_sub_request);
2304   EXPECT_FALSE(g_TestResults.got_sub_read);
2305   EXPECT_FALSE(g_TestResults.got_sub_success);
2306 
2307   ClearTestSchemes();
2308 }
2309 
2310 // Test that a custom standard scheme can generate cross-domain XHR requests
2311 // that perform redirects when using the cross-origin whitelist.
TEST(SchemeHandlerTest,CustomStandardXHRDifferentOriginRedirectWithWhitelistSync)2312 TEST(SchemeHandlerTest,
2313      CustomStandardXHRDifferentOriginRedirectWithWhitelistSync) {
2314   RegisterTestScheme("customstd", "test1");
2315   RegisterTestScheme("customstd", "test2");
2316 
2317   XHRTestSettings settings;
2318   settings.url = "customstd://test1/run.html";
2319   settings.sub_url = "customstd://test2/xhr.html";
2320   settings.sub_redirect_url = "customstd://test1/xhr.html";
2321   SetUpXHR(settings);
2322 
2323   EXPECT_TRUE(CefAddCrossOriginWhitelistEntry("customstd://test1", "customstd",
2324                                               "test2", false));
2325   WaitForUIThread();
2326 
2327   CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
2328   handler->ExecuteTest();
2329   ReleaseAndWaitForDestructor(handler);
2330 
2331   EXPECT_TRUE(g_TestResults.got_request);
2332   EXPECT_TRUE(g_TestResults.got_read);
2333   EXPECT_TRUE(g_TestResults.got_output);
2334   EXPECT_TRUE(g_TestResults.got_sub_redirect);
2335   EXPECT_TRUE(g_TestResults.got_sub_request);
2336   EXPECT_TRUE(g_TestResults.got_sub_read);
2337   EXPECT_TRUE(g_TestResults.got_sub_success);
2338 
2339   EXPECT_TRUE(CefClearCrossOriginWhitelist());
2340   WaitForUIThread();
2341 
2342   ClearTestSchemes();
2343 }
2344 
2345 // Test that a custom standard scheme can generate cross-domain XHR requests
2346 // that perform redirects when using the cross-origin whitelist.
TEST(SchemeHandlerTest,CustomStandardXHRDifferentOriginRedirectWithWhitelistAsync1)2347 TEST(SchemeHandlerTest,
2348      CustomStandardXHRDifferentOriginRedirectWithWhitelistAsync1) {
2349   RegisterTestScheme("customstd", "test1");
2350   RegisterTestScheme("customstd", "test2");
2351 
2352   XHRTestSettings settings;
2353   settings.url = "customstd://test1/run.html";
2354   settings.sub_url = "customstd://test2/xhr.html";
2355   settings.sub_redirect_url = "customstd://test1/xhr.html";
2356   settings.synchronous = false;
2357   SetUpXHR(settings);
2358 
2359   EXPECT_TRUE(CefAddCrossOriginWhitelistEntry("customstd://test1", "customstd",
2360                                               "test2", false));
2361   WaitForUIThread();
2362 
2363   CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
2364   handler->ExecuteTest();
2365   ReleaseAndWaitForDestructor(handler);
2366 
2367   EXPECT_TRUE(g_TestResults.got_request);
2368   EXPECT_TRUE(g_TestResults.got_read);
2369   EXPECT_TRUE(g_TestResults.got_output);
2370   EXPECT_TRUE(g_TestResults.got_sub_redirect);
2371   EXPECT_TRUE(g_TestResults.got_sub_request);
2372   EXPECT_TRUE(g_TestResults.got_sub_read);
2373   EXPECT_TRUE(g_TestResults.got_sub_success);
2374 
2375   EXPECT_TRUE(CefClearCrossOriginWhitelist());
2376   WaitForUIThread();
2377 
2378   ClearTestSchemes();
2379 }
2380 
2381 // Same as above but origin whitelist matches any domain.
TEST(SchemeHandlerTest,CustomStandardXHRDifferentOriginRedirectWithWhitelistAsync2)2382 TEST(SchemeHandlerTest,
2383      CustomStandardXHRDifferentOriginRedirectWithWhitelistAsync2) {
2384   RegisterTestScheme("customstd", "test1");
2385   RegisterTestScheme("customstd", "test2");
2386 
2387   XHRTestSettings settings;
2388   settings.url = "customstd://test1/run.html";
2389   settings.sub_url = "customstd://test2/xhr.html";
2390   settings.sub_redirect_url = "customstd://test1/xhr.html";
2391   settings.synchronous = false;
2392   SetUpXHR(settings);
2393 
2394   EXPECT_TRUE(CefAddCrossOriginWhitelistEntry("customstd://test1", "customstd",
2395                                               CefString(), true));
2396   WaitForUIThread();
2397 
2398   CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
2399   handler->ExecuteTest();
2400   ReleaseAndWaitForDestructor(handler);
2401 
2402   EXPECT_TRUE(g_TestResults.got_request);
2403   EXPECT_TRUE(g_TestResults.got_read);
2404   EXPECT_TRUE(g_TestResults.got_output);
2405   EXPECT_TRUE(g_TestResults.got_sub_redirect);
2406   EXPECT_TRUE(g_TestResults.got_sub_request);
2407   EXPECT_TRUE(g_TestResults.got_sub_read);
2408   EXPECT_TRUE(g_TestResults.got_sub_success);
2409 
2410   EXPECT_TRUE(CefClearCrossOriginWhitelist());
2411   WaitForUIThread();
2412 
2413   ClearTestSchemes();
2414 }
2415 
2416 // Same as above but origin whitelist matches sub-domains.
TEST(SchemeHandlerTest,CustomStandardXHRDifferentOriginRedirectWithWhitelistAsync3)2417 TEST(SchemeHandlerTest,
2418      CustomStandardXHRDifferentOriginRedirectWithWhitelistAsync3) {
2419   RegisterTestScheme("customstd", "test1");
2420   RegisterTestScheme("customstd", "a.test2.foo");
2421 
2422   XHRTestSettings settings;
2423   settings.url = "customstd://test1/run.html";
2424   settings.sub_url = "customstd://a.test2.foo/xhr.html";
2425   settings.sub_redirect_url = "customstd://test1/xhr.html";
2426   settings.synchronous = false;
2427   SetUpXHR(settings);
2428 
2429   EXPECT_TRUE(CefAddCrossOriginWhitelistEntry("customstd://test1", "customstd",
2430                                               "test2.foo", true));
2431   WaitForUIThread();
2432 
2433   CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
2434   handler->ExecuteTest();
2435   ReleaseAndWaitForDestructor(handler);
2436 
2437   EXPECT_TRUE(g_TestResults.got_request);
2438   EXPECT_TRUE(g_TestResults.got_read);
2439   EXPECT_TRUE(g_TestResults.got_output);
2440   EXPECT_TRUE(g_TestResults.got_sub_redirect);
2441   EXPECT_TRUE(g_TestResults.got_sub_request);
2442   EXPECT_TRUE(g_TestResults.got_sub_read);
2443   EXPECT_TRUE(g_TestResults.got_sub_success);
2444 
2445   EXPECT_TRUE(CefClearCrossOriginWhitelist());
2446   WaitForUIThread();
2447 
2448   ClearTestSchemes();
2449 }
2450 
2451 // Test that a custom standard scheme can generate cross-domain Fetch requests
2452 // that perform redirects when using the cross-origin whitelist.
TEST(SchemeHandlerTest,CustomStandardFetchDifferentOriginRedirectWithWhitelist1)2453 TEST(SchemeHandlerTest,
2454      CustomStandardFetchDifferentOriginRedirectWithWhitelist1) {
2455   RegisterTestScheme("customstdfetch", "test1");
2456   RegisterTestScheme("customstdfetch", "test2");
2457 
2458   FetchTestSettings settings;
2459   settings.url = "customstdfetch://test1/run.html";
2460   settings.sub_url = "customstdfetch://test2/fetch.html";
2461   settings.sub_redirect_url = "customstdfetch://test1/fetch.html";
2462   SetUpFetch(settings);
2463 
2464   EXPECT_TRUE(CefAddCrossOriginWhitelistEntry(
2465       "customstdfetch://test1", "customstdfetch", "test2", false));
2466   WaitForUIThread();
2467 
2468   CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
2469   handler->ExecuteTest();
2470   ReleaseAndWaitForDestructor(handler);
2471 
2472   EXPECT_TRUE(g_TestResults.got_request);
2473   EXPECT_TRUE(g_TestResults.got_read);
2474   EXPECT_TRUE(g_TestResults.got_output);
2475   EXPECT_TRUE(g_TestResults.got_sub_redirect);
2476   EXPECT_TRUE(g_TestResults.got_sub_request);
2477   EXPECT_TRUE(g_TestResults.got_sub_read);
2478   EXPECT_TRUE(g_TestResults.got_sub_success);
2479 
2480   EXPECT_TRUE(CefClearCrossOriginWhitelist());
2481   WaitForUIThread();
2482 
2483   ClearTestSchemes();
2484 }
2485 
2486 // Same as above but origin whitelist matches any domain.
TEST(SchemeHandlerTest,CustomStandardFetchDifferentOriginRedirectWithWhitelist2)2487 TEST(SchemeHandlerTest,
2488      CustomStandardFetchDifferentOriginRedirectWithWhitelist2) {
2489   RegisterTestScheme("customstdfetch", "test1");
2490   RegisterTestScheme("customstdfetch", "test2");
2491 
2492   FetchTestSettings settings;
2493   settings.url = "customstdfetch://test1/run.html";
2494   settings.sub_url = "customstdfetch://test2/fetch.html";
2495   settings.sub_redirect_url = "customstdfetch://test1/fetch.html";
2496   SetUpFetch(settings);
2497 
2498   EXPECT_TRUE(CefAddCrossOriginWhitelistEntry(
2499       "customstdfetch://test1", "customstdfetch", CefString(), true));
2500   WaitForUIThread();
2501 
2502   CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
2503   handler->ExecuteTest();
2504   ReleaseAndWaitForDestructor(handler);
2505 
2506   EXPECT_TRUE(g_TestResults.got_request);
2507   EXPECT_TRUE(g_TestResults.got_read);
2508   EXPECT_TRUE(g_TestResults.got_output);
2509   EXPECT_TRUE(g_TestResults.got_sub_redirect);
2510   EXPECT_TRUE(g_TestResults.got_sub_request);
2511   EXPECT_TRUE(g_TestResults.got_sub_read);
2512   EXPECT_TRUE(g_TestResults.got_sub_success);
2513 
2514   EXPECT_TRUE(CefClearCrossOriginWhitelist());
2515   WaitForUIThread();
2516 
2517   ClearTestSchemes();
2518 }
2519 
2520 // Same as above but origin whitelist matches sub-domains.
TEST(SchemeHandlerTest,CustomStandardFetchDifferentOriginRedirectWithWhitelist3)2521 TEST(SchemeHandlerTest,
2522      CustomStandardFetchDifferentOriginRedirectWithWhitelist3) {
2523   RegisterTestScheme("customstdfetch", "test1");
2524   RegisterTestScheme("customstdfetch", "a.test2.foo");
2525 
2526   FetchTestSettings settings;
2527   settings.url = "customstdfetch://test1/run.html";
2528   settings.sub_url = "customstdfetch://a.test2.foo/fetch.html";
2529   settings.sub_redirect_url = "customstdfetch://test1/fetch.html";
2530   SetUpFetch(settings);
2531 
2532   EXPECT_TRUE(CefAddCrossOriginWhitelistEntry(
2533       "customstdfetch://test1", "customstdfetch", "test2.foo", true));
2534   WaitForUIThread();
2535 
2536   CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
2537   handler->ExecuteTest();
2538   ReleaseAndWaitForDestructor(handler);
2539 
2540   EXPECT_TRUE(g_TestResults.got_request);
2541   EXPECT_TRUE(g_TestResults.got_read);
2542   EXPECT_TRUE(g_TestResults.got_output);
2543   EXPECT_TRUE(g_TestResults.got_sub_redirect);
2544   EXPECT_TRUE(g_TestResults.got_sub_request);
2545   EXPECT_TRUE(g_TestResults.got_sub_read);
2546   EXPECT_TRUE(g_TestResults.got_sub_success);
2547 
2548   EXPECT_TRUE(CefClearCrossOriginWhitelist());
2549   WaitForUIThread();
2550 
2551   ClearTestSchemes();
2552 }
2553 
2554 // Test per-browser setting of Accept-Language.
TEST(SchemeHandlerTest,AcceptLanguage)2555 TEST(SchemeHandlerTest, AcceptLanguage) {
2556   RegisterTestScheme("customstd", "test");
2557   g_TestResults.url = "customstd://test/run.html";
2558   g_TestResults.html =
2559       "<html><head></head><body><h1>Success!</h1></body></html>";
2560 
2561   // Value that will be set via CefBrowserSettings.accept_language in
2562   // PopulateBrowserSettings().
2563   g_TestResults.accept_language = "uk";
2564 
2565   CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
2566   handler->ExecuteTest();
2567   ReleaseAndWaitForDestructor(handler);
2568 
2569   EXPECT_TRUE(g_TestResults.got_request);
2570   EXPECT_TRUE(g_TestResults.got_read);
2571   EXPECT_TRUE(g_TestResults.got_output);
2572 
2573   ClearTestSchemes();
2574 }
2575 
2576 // Entry point for registering custom schemes.
2577 // Called from client_app_delegates.cc.
RegisterSchemeHandlerCustomSchemes(CefRawPtr<CefSchemeRegistrar> registrar)2578 void RegisterSchemeHandlerCustomSchemes(
2579     CefRawPtr<CefSchemeRegistrar> registrar) {
2580   // Registering the custom standard schemes as secure because requests from
2581   // non-secure origins to the loopback address will be blocked by
2582   // https://chromestatus.com/feature/5436853517811712.
2583 
2584   // Add a custom standard scheme.
2585   registrar->AddCustomScheme("customstd", CEF_SCHEME_OPTION_STANDARD |
2586                                               CEF_SCHEME_OPTION_SECURE |
2587                                               CEF_SCHEME_OPTION_CORS_ENABLED);
2588   // Also used in cors_unittest.cc.
2589   registrar->AddCustomScheme(
2590       "customstdfetch", CEF_SCHEME_OPTION_STANDARD | CEF_SCHEME_OPTION_SECURE |
2591                             CEF_SCHEME_OPTION_CORS_ENABLED |
2592                             CEF_SCHEME_OPTION_FETCH_ENABLED);
2593   // Add a custom non-standard scheme.
2594   registrar->AddCustomScheme("customnonstd", CEF_SCHEME_OPTION_NONE);
2595   registrar->AddCustomScheme("customnonstdfetch",
2596                              CEF_SCHEME_OPTION_FETCH_ENABLED);
2597 }
2598 
2599 // Entry point for registering cookieable schemes.
2600 // Called from client_app_delegates.cc.
RegisterSchemeHandlerCookieableSchemes(std::vector<std::string> & cookieable_schemes)2601 void RegisterSchemeHandlerCookieableSchemes(
2602     std::vector<std::string>& cookieable_schemes) {
2603   cookieable_schemes.push_back("customstd");
2604   // Also used in cors_unittest.cc.
2605   cookieable_schemes.push_back("customstdfetch");
2606 }
2607