| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/url_request/sdch_dictionary_fetcher.h" | 5 #include "net/url_request/sdch_dictionary_fetcher.h" |
| 6 | 6 |
| 7 #include <string> | 7 #include <string> |
| 8 #include <utility> | 8 #include <utility> |
| 9 #include <vector> | 9 #include <vector> |
| 10 | 10 |
| 11 #include "base/bind.h" | 11 #include "base/bind.h" |
| 12 #include "base/callback.h" | 12 #include "base/callback.h" |
| 13 #include "base/logging.h" | 13 #include "base/logging.h" |
| 14 #include "base/macros.h" | 14 #include "base/macros.h" |
| 15 #include "base/run_loop.h" | 15 #include "base/run_loop.h" |
| 16 #include "base/strings/stringprintf.h" | 16 #include "base/strings/stringprintf.h" |
| 17 #include "base/thread_task_runner_handle.h" | 17 #include "base/thread_task_runner_handle.h" |
| 18 #include "net/base/load_flags.h" | 18 #include "net/base/load_flags.h" |
| 19 #include "net/base/sdch_manager.h" | 19 #include "net/base/sdch_manager.h" |
| 20 #include "net/http/http_response_headers.h" | 20 #include "net/http/http_response_headers.h" |
| 21 #include "net/url_request/url_request_data_job.h" | 21 #include "net/url_request/url_request_data_job.h" |
| 22 #include "net/url_request/url_request_filter.h" | 22 #include "net/url_request/url_request_filter.h" |
| 23 #include "net/url_request/url_request_interceptor.h" | 23 #include "net/url_request/url_request_interceptor.h" |
| 24 #include "net/url_request/url_request_redirect_job.h" |
| 24 #include "net/url_request/url_request_test_util.h" | 25 #include "net/url_request/url_request_test_util.h" |
| 25 #include "testing/gtest/include/gtest/gtest.h" | 26 #include "testing/gtest/include/gtest/gtest.h" |
| 26 | 27 |
| 27 namespace net { | 28 namespace net { |
| 28 | 29 |
| 29 namespace { | 30 namespace { |
| 30 | 31 |
| 31 const char kSampleBufferContext[] = "This is a sample buffer."; | 32 const char kSampleBufferContext[] = "This is a sample buffer."; |
| 32 const char kTestDomain[] = "top.domain.test"; | 33 const char kTestDomain1[] = "top.domain.test"; |
| 34 const char kTestDomain2[] = "top2.domain.test"; |
| 33 | 35 |
| 34 class URLRequestSpecifiedResponseJob : public URLRequestSimpleJob { | 36 class URLRequestSpecifiedResponseJob : public URLRequestSimpleJob { |
| 35 public: | 37 public: |
| 36 // Called on destruction with load flags used for this request. | 38 // Called on destruction with load flags used for this request. |
| 37 typedef base::Callback<void(int)> DestructionCallback; | 39 typedef base::Callback<void(int)> DestructionCallback; |
| 38 | 40 |
| 39 URLRequestSpecifiedResponseJob( | 41 URLRequestSpecifiedResponseJob( |
| 40 URLRequest* request, | 42 URLRequest* request, |
| 41 NetworkDelegate* network_delegate, | 43 NetworkDelegate* network_delegate, |
| 42 const HttpResponseInfo& response_info_to_return, | 44 const HttpResponseInfo& response_info_to_return, |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 75 return OK; | 77 return OK; |
| 76 } | 78 } |
| 77 | 79 |
| 78 const HttpResponseInfo response_info_to_return_; | 80 const HttpResponseInfo response_info_to_return_; |
| 79 int last_load_flags_seen_; | 81 int last_load_flags_seen_; |
| 80 const DestructionCallback destruction_callback_; | 82 const DestructionCallback destruction_callback_; |
| 81 | 83 |
| 82 DISALLOW_COPY_AND_ASSIGN(URLRequestSpecifiedResponseJob); | 84 DISALLOW_COPY_AND_ASSIGN(URLRequestSpecifiedResponseJob); |
| 83 }; | 85 }; |
| 84 | 86 |
| 85 class SpecifiedResponseJobInterceptor : public URLRequestInterceptor { | 87 // Wrap URLRequestRedirectJob in a destruction callback. |
| 88 class TestURLRequestRedirectJob : public URLRequestRedirectJob { |
| 86 public: | 89 public: |
| 87 // A callback to be called whenever a URLRequestSpecifiedResponseJob is | 90 TestURLRequestRedirectJob(URLRequest* request, |
| 88 // created or destroyed. The first argument will be the change in number of | 91 NetworkDelegate* network_delegate, |
| 89 // jobs (i.e. +1 for created, -1 for destroyed). | 92 const GURL& redirect_destination, |
| 90 // The second argument will be undefined if the job is being created, | 93 ResponseCode response_code, |
| 91 // and will contain the load flags passed to the request the | 94 const std::string& redirect_reason, |
| 92 // job was created for if the job is being destroyed. | 95 base::Closure destruction_callback) |
| 96 : URLRequestRedirectJob(request, |
| 97 network_delegate, |
| 98 redirect_destination, |
| 99 response_code, |
| 100 redirect_reason), |
| 101 destruction_callback_(destruction_callback) {} |
| 102 ~TestURLRequestRedirectJob() override { destruction_callback_.Run(); } |
| 103 |
| 104 private: |
| 105 const base::Closure destruction_callback_; |
| 106 }; |
| 107 |
| 108 static const char* redirect_signal = "/redirect/"; |
| 109 class SDCHTestRequestInterceptor : public URLRequestInterceptor { |
| 110 public: |
| 111 // A callback to be called whenever a URLRequestJob child of this |
| 112 // interceptor is created or destroyed. The first argument will be the |
| 113 // change in number of jobs (i.e. +1 for created, -1 for destroyed). |
| 114 // The second argument will be undefined if the job is being created |
| 115 // or a redirect job is being destroyed, and (for non-redirect job |
| 116 // destruction) will contain the load flags passed to the request the |
| 117 // job was created for. |
| 93 typedef base::Callback<void(int outstanding_job_delta, | 118 typedef base::Callback<void(int outstanding_job_delta, |
| 94 int destruction_load_flags)> LifecycleCallback; | 119 int destruction_load_flags)> LifecycleCallback; |
| 95 | 120 |
| 96 // |*info| will be returned from all child URLRequestSpecifiedResponseJobs. | 121 // |*info| will be returned from all child URLRequestSpecifiedResponseJobs. |
| 97 // Note that: a) this pointer is shared with the caller, and the caller must | 122 // Note that: a) this pointer is shared with the caller, and the caller must |
| 98 // guarantee that |*info| outlives the SpecifiedResponseJobInterceptor, and | 123 // guarantee that |*info| outlives the SDCHTestRequestInterceptor, and |
| 99 // b) |*info| is mutable, and changes to should propagate to | 124 // b) |*info| is mutable, and changes to should propagate to |
| 100 // URLRequestSpecifiedResponseJobs created after any change. | 125 // URLRequestSpecifiedResponseJobs created after any change. |
| 101 SpecifiedResponseJobInterceptor(HttpResponseInfo* http_response_info, | 126 SDCHTestRequestInterceptor(HttpResponseInfo* http_response_info, |
| 102 const LifecycleCallback& lifecycle_callback) | 127 const LifecycleCallback& lifecycle_callback) |
| 103 : http_response_info_(http_response_info), | 128 : http_response_info_(http_response_info), |
| 104 lifecycle_callback_(lifecycle_callback) { | 129 lifecycle_callback_(lifecycle_callback) { |
| 105 DCHECK(!lifecycle_callback_.is_null()); | 130 DCHECK(!lifecycle_callback_.is_null()); |
| 106 } | 131 } |
| 107 ~SpecifiedResponseJobInterceptor() override {} | 132 ~SDCHTestRequestInterceptor() override {} |
| 108 | 133 |
| 109 URLRequestJob* MaybeInterceptRequest( | 134 URLRequestJob* MaybeInterceptRequest( |
| 110 URLRequest* request, | 135 URLRequest* request, |
| 111 NetworkDelegate* network_delegate) const override { | 136 NetworkDelegate* network_delegate) const override { |
| 112 lifecycle_callback_.Run(1, 0); | 137 lifecycle_callback_.Run(1, 0); |
| 113 | 138 |
| 139 std::string path = request->url().path(); |
| 140 if (path.substr(0, strlen(redirect_signal)) == redirect_signal) { |
| 141 return new TestURLRequestRedirectJob( |
| 142 request, network_delegate, GURL(path.substr(strlen(redirect_signal))), |
| 143 URLRequestRedirectJob::REDIRECT_307_TEMPORARY_REDIRECT, "testing", |
| 144 base::Bind(lifecycle_callback_, -1, 0)); |
| 145 } |
| 146 |
| 114 return new URLRequestSpecifiedResponseJob( | 147 return new URLRequestSpecifiedResponseJob( |
| 115 request, network_delegate, *http_response_info_, | 148 request, network_delegate, *http_response_info_, |
| 116 base::Bind(lifecycle_callback_, -1)); | 149 base::Bind(lifecycle_callback_, -1)); |
| 117 } | 150 } |
| 118 | 151 |
| 119 // The caller must ensure that both |*http_response_info| and the | 152 // The caller must ensure that both |*http_response_info| and the |
| 120 // callback remain valid for the lifetime of the | 153 // callback remain valid for the lifetime of the |
| 121 // SpecifiedResponseJobInterceptor (i.e. until Unregister() is called). | 154 // SDCHTestRequestInterceptor (i.e. until Unregister() is called). |
| 122 static void RegisterWithFilter(HttpResponseInfo* http_response_info, | 155 static void RegisterWithFilter(HttpResponseInfo* http_response_info, |
| 123 const LifecycleCallback& lifecycle_callback) { | 156 const LifecycleCallback& lifecycle_callback) { |
| 124 scoped_ptr<SpecifiedResponseJobInterceptor> interceptor( | 157 URLRequestFilter::GetInstance()->AddHostnameInterceptor( |
| 125 new SpecifiedResponseJobInterceptor(http_response_info, | 158 "http", kTestDomain1, |
| 126 lifecycle_callback)); | 159 scoped_ptr<URLRequestInterceptor>(new SDCHTestRequestInterceptor( |
| 160 http_response_info, lifecycle_callback))); |
| 127 | 161 |
| 128 URLRequestFilter::GetInstance()->AddHostnameInterceptor( | 162 URLRequestFilter::GetInstance()->AddHostnameInterceptor( |
| 129 "http", kTestDomain, std::move(interceptor)); | 163 "https", kTestDomain1, |
| 164 scoped_ptr<URLRequestInterceptor>(new SDCHTestRequestInterceptor( |
| 165 http_response_info, lifecycle_callback))); |
| 166 |
| 167 URLRequestFilter::GetInstance()->AddHostnameInterceptor( |
| 168 "http", kTestDomain2, |
| 169 scoped_ptr<URLRequestInterceptor>(new SDCHTestRequestInterceptor( |
| 170 http_response_info, lifecycle_callback))); |
| 171 |
| 172 URLRequestFilter::GetInstance()->AddHostnameInterceptor( |
| 173 "https", kTestDomain2, |
| 174 scoped_ptr<URLRequestInterceptor>(new SDCHTestRequestInterceptor( |
| 175 http_response_info, lifecycle_callback))); |
| 130 } | 176 } |
| 131 | 177 |
| 132 static void Unregister() { | 178 static void Unregister() { |
| 133 URLRequestFilter::GetInstance()->RemoveHostnameHandler("http", kTestDomain); | 179 URLRequestFilter::GetInstance()->RemoveHostnameHandler("http", |
| 180 kTestDomain1); |
| 181 URLRequestFilter::GetInstance()->RemoveHostnameHandler("https", |
| 182 kTestDomain1); |
| 183 URLRequestFilter::GetInstance()->RemoveHostnameHandler("http", |
| 184 kTestDomain2); |
| 185 URLRequestFilter::GetInstance()->RemoveHostnameHandler("https", |
| 186 kTestDomain2); |
| 134 } | 187 } |
| 135 | 188 |
| 136 private: | 189 private: |
| 137 HttpResponseInfo* http_response_info_; | 190 HttpResponseInfo* http_response_info_; |
| 138 LifecycleCallback lifecycle_callback_; | 191 LifecycleCallback lifecycle_callback_; |
| 139 DISALLOW_COPY_AND_ASSIGN(SpecifiedResponseJobInterceptor); | 192 DISALLOW_COPY_AND_ASSIGN(SDCHTestRequestInterceptor); |
| 140 }; | 193 }; |
| 141 | 194 |
| 142 // Local test infrastructure | 195 // Local test infrastructure |
| 143 // * URLRequestSpecifiedResponseJob: A URLRequestJob that returns | 196 // * URLRequestSpecifiedResponseJob: A URLRequestJob that returns |
| 144 // a different but derivable response for each URL (used for all | 197 // a different but derivable response for each URL (used for all |
| 145 // url requests in this file). This class is initialized with | 198 // url requests in this file). This class is initialized with |
| 146 // the HttpResponseInfo to return (if any), as well as a callback | 199 // the HttpResponseInfo to return (if any), as well as a callback |
| 147 // that is called when the class is destroyed. That callback | 200 // that is called when the class is destroyed. That callback |
| 148 // takes as arguemnt the load flags used for the request the | 201 // takes as arguemnt the load flags used for the request the |
| 149 // job was created for. | 202 // job was created for. |
| 150 // * SpecifiedResponseJobInterceptor: This class is a | 203 // * SDCHTestRequestInterceptor: This class is a |
| 151 // URLRequestInterceptor that generates the class above. It is constructed | 204 // URLRequestInterceptor that generates either the class above or an |
| 205 // instance of URLRequestRedirectJob (if the first component of the path |
| 206 // is "redirect"). It is constructed |
| 152 // with a pointer to the (mutable) resposne info that should be | 207 // with a pointer to the (mutable) resposne info that should be |
| 153 // returned from the URLRequestSpecifiedResponseJob children, as well as | 208 // returned from constructed URLRequestSpecifiedResponseJobs, as well as |
| 154 // a callback that is run when URLRequestSpecifiedResponseJobs are | 209 // a callback that is run when URLRequestSpecifiedResponseJobs are |
| 155 // created or destroyed. | 210 // created or destroyed. |
| 156 // * SdchDictionaryFetcherTest: This class registers the above interceptor, | 211 // * SdchDictionaryFetcherTest: This class registers the above interceptor, |
| 157 // tracks the number of jobs requested and the subset of those | 212 // tracks the number of jobs requested and the subset of those |
| 158 // that are still outstanding. It exports an interface to wait until there | 213 // that are still outstanding. It exports an interface to wait until there |
| 159 // are no jobs outstanding. It shares an HttpResponseInfo structure | 214 // are no jobs outstanding. It shares an HttpResponseInfo structure |
| 160 // with the SpecifiedResponseJobInterceptor to control the response | 215 // with the SDCHTestRequestInterceptor to control the response |
| 161 // information returned by the jbos. | 216 // information returned by the jbos. |
| 162 // The standard pattern for tests is to schedule a dictionary fetch, wait | 217 // The standard pattern for tests is to schedule a dictionary fetch, wait |
| 163 // for no jobs outstanding, then test that the fetch results are as expected. | 218 // for no jobs outstanding, then test that the fetch results are as expected. |
| 164 | 219 |
| 165 class SdchDictionaryFetcherTest : public ::testing::Test { | 220 class SdchDictionaryFetcherTest : public ::testing::Test { |
| 166 public: | 221 public: |
| 167 struct DictionaryAdditions { | 222 struct DictionaryAdditions { |
| 168 DictionaryAdditions(const std::string& dictionary_text, | 223 DictionaryAdditions(const std::string& dictionary_text, |
| 169 const GURL& dictionary_url) | 224 const GURL& dictionary_url) |
| 170 : dictionary_text(dictionary_text), dictionary_url(dictionary_url) {} | 225 : dictionary_text(dictionary_text), dictionary_url(dictionary_url) {} |
| 171 | 226 |
| 172 std::string dictionary_text; | 227 std::string dictionary_text; |
| 173 GURL dictionary_url; | 228 GURL dictionary_url; |
| 174 }; | 229 }; |
| 175 | 230 |
| 176 SdchDictionaryFetcherTest() | 231 SdchDictionaryFetcherTest() |
| 177 : jobs_requested_(0), | 232 : jobs_requested_(0), |
| 178 jobs_outstanding_(0), | 233 jobs_outstanding_(0), |
| 179 last_load_flags_seen_(LOAD_NORMAL), | 234 last_load_flags_seen_(LOAD_NORMAL), |
| 180 context_(new TestURLRequestContext), | 235 context_(new TestURLRequestContext), |
| 181 fetcher_(new SdchDictionaryFetcher(context_.get())), | 236 fetcher_(new SdchDictionaryFetcher(context_.get())), |
| 182 factory_(this) { | 237 factory_(this) { |
| 183 response_info_to_return_.request_time = base::Time::Now(); | 238 response_info_to_return_.request_time = base::Time::Now(); |
| 184 response_info_to_return_.response_time = base::Time::Now(); | 239 response_info_to_return_.response_time = base::Time::Now(); |
| 185 SpecifiedResponseJobInterceptor::RegisterWithFilter( | 240 SDCHTestRequestInterceptor::RegisterWithFilter( |
| 186 &response_info_to_return_, | 241 &response_info_to_return_, |
| 187 base::Bind(&SdchDictionaryFetcherTest::OnNumberJobsChanged, | 242 base::Bind(&SdchDictionaryFetcherTest::OnNumberJobsChanged, |
| 188 factory_.GetWeakPtr())); | 243 factory_.GetWeakPtr())); |
| 189 } | 244 } |
| 190 | 245 |
| 191 ~SdchDictionaryFetcherTest() override { | 246 ~SdchDictionaryFetcherTest() override { |
| 192 SpecifiedResponseJobInterceptor::Unregister(); | 247 SDCHTestRequestInterceptor::Unregister(); |
| 193 } | 248 } |
| 194 | 249 |
| 195 void OnDictionaryFetched(const std::string& dictionary_text, | 250 void OnDictionaryFetched(const std::string& dictionary_text, |
| 196 const GURL& dictionary_url, | 251 const GURL& dictionary_url, |
| 197 const BoundNetLog& net_log, | 252 const BoundNetLog& net_log, |
| 198 bool was_from_cache) { | 253 bool was_from_cache) { |
| 199 dictionary_additions_.push_back( | 254 dictionary_additions_.push_back( |
| 200 DictionaryAdditions(dictionary_text, dictionary_url)); | 255 DictionaryAdditions(dictionary_text, dictionary_url)); |
| 201 } | 256 } |
| 202 | 257 |
| 203 // Return (in |*out|) all dictionary additions since the last time | 258 // Return (in |*out|) all dictionary additions since the last time |
| 204 // this function was called. | 259 // this function was called. |
| 205 void GetDictionaryAdditions(std::vector<DictionaryAdditions>* out) { | 260 void GetDictionaryAdditions(std::vector<DictionaryAdditions>* out) { |
| 206 out->swap(dictionary_additions_); | 261 out->swap(dictionary_additions_); |
| 207 dictionary_additions_.clear(); | 262 dictionary_additions_.clear(); |
| 208 } | 263 } |
| 209 | 264 |
| 210 SdchDictionaryFetcher* fetcher() { return fetcher_.get(); } | 265 SdchDictionaryFetcher* fetcher() { return fetcher_.get(); } |
| 211 | 266 |
| 212 // May not be called outside the SetUp()/TearDown() interval. | 267 // May not be called outside the SetUp()/TearDown() interval. |
| 213 int jobs_requested() const { return jobs_requested_; } | 268 int jobs_requested() const { return jobs_requested_; } |
| 214 | 269 |
| 215 GURL PathToGurl(const char* path) const { | 270 GURL PathToGurl(const char* path) const { |
| 216 std::string gurl_string("http://"); | 271 std::string gurl_string("http://"); |
| 217 gurl_string += kTestDomain; | 272 gurl_string += kTestDomain1; |
| 218 gurl_string += "/"; | 273 gurl_string += "/"; |
| 219 gurl_string += path; | 274 gurl_string += path; |
| 220 return GURL(gurl_string); | 275 return GURL(gurl_string); |
| 221 } | 276 } |
| 222 | 277 |
| 223 // Block until there are no outstanding URLRequestSpecifiedResponseJobs. | 278 // Block until there are no outstanding URLRequestSpecifiedResponseJobs. |
| 224 void WaitForNoJobs() { | 279 void WaitForNoJobs() { |
| 225 // A job may be started after the previous one was destroyed, with a brief | 280 // A job may be started after the previous one was destroyed, with a brief |
| 226 // period of 0 jobs in between, so may have to start the run loop multiple | 281 // period of 0 jobs in between, so may have to start the run loop multiple |
| 227 // times. | 282 // times. |
| (...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 427 EXPECT_EQ(1, jobs_requested()); | 482 EXPECT_EQ(1, jobs_requested()); |
| 428 | 483 |
| 429 fetcher()->Cancel(); | 484 fetcher()->Cancel(); |
| 430 WaitForNoJobs(); | 485 WaitForNoJobs(); |
| 431 EXPECT_TRUE(fetcher()->Schedule(dictionary_url, GetDefaultCallback())); | 486 EXPECT_TRUE(fetcher()->Schedule(dictionary_url, GetDefaultCallback())); |
| 432 | 487 |
| 433 WaitForNoJobs(); | 488 WaitForNoJobs(); |
| 434 EXPECT_EQ(2, jobs_requested()); | 489 EXPECT_EQ(2, jobs_requested()); |
| 435 } | 490 } |
| 436 | 491 |
| 492 TEST_F(SdchDictionaryFetcherTest, InOriginRedirect) { |
| 493 GURL dictionary_url(PathToGurl("dictionary")); |
| 494 GURL local_redirect_url(dictionary_url.GetWithEmptyPath().spec() + |
| 495 "redirect/" + dictionary_url.spec()); |
| 496 EXPECT_TRUE(fetcher()->Schedule(local_redirect_url, GetDefaultCallback())); |
| 497 WaitForNoJobs(); |
| 498 |
| 499 // Both the redirect job and the job retrieving the actual dictionary |
| 500 // should have been executed. |
| 501 EXPECT_EQ(2, jobs_requested()); |
| 502 std::vector<DictionaryAdditions> additions; |
| 503 GetDictionaryAdditions(&additions); |
| 504 EXPECT_EQ(1u, additions.size()); |
| 505 } |
| 506 |
| 507 TEST_F(SdchDictionaryFetcherTest, CrossSecurityRedirect) { |
| 508 std::string dictionary_url_spec("https://" + std::string(kTestDomain1) + |
| 509 "/dictionary"); |
| 510 GURL local_redirect_url("http://" + std::string(kTestDomain1) + "/redirect/" + |
| 511 dictionary_url_spec); |
| 512 |
| 513 EXPECT_TRUE(fetcher()->Schedule(local_redirect_url, GetDefaultCallback())); |
| 514 WaitForNoJobs(); |
| 515 |
| 516 // The fetcher should have refused the redirect job. |
| 517 EXPECT_EQ(1, jobs_requested()); |
| 518 std::vector<DictionaryAdditions> additions; |
| 519 GetDictionaryAdditions(&additions); |
| 520 // And there should be no dictionaries added. |
| 521 EXPECT_EQ(0u, additions.size()); |
| 522 } |
| 523 |
| 524 TEST_F(SdchDictionaryFetcherTest, CrossSiteRedirect) { |
| 525 std::string dictionary_url_spec("https://" + std::string(kTestDomain1) + |
| 526 "/dictionary"); |
| 527 GURL local_redirect_url("https://" + std::string(kTestDomain2) + |
| 528 "/redirect/" + dictionary_url_spec); |
| 529 |
| 530 EXPECT_TRUE(fetcher()->Schedule(local_redirect_url, GetDefaultCallback())); |
| 531 WaitForNoJobs(); |
| 532 |
| 533 // The fetcher should have refused the redirect job. |
| 534 EXPECT_EQ(1, jobs_requested()); |
| 535 std::vector<DictionaryAdditions> additions; |
| 536 GetDictionaryAdditions(&additions); |
| 537 // And there should be no dictionaries added. |
| 538 EXPECT_EQ(0u, additions.size()); |
| 539 } |
| 540 |
| 541 TEST_F(SdchDictionaryFetcherTest, CrossSiteSecurityRedirect) { |
| 542 std::string dictionary_url_spec("https://" + std::string(kTestDomain1) + |
| 543 "/dictionary"); |
| 544 GURL local_redirect_url("http://" + std::string(kTestDomain2) + "/redirect/" + |
| 545 dictionary_url_spec); |
| 546 |
| 547 EXPECT_TRUE(fetcher()->Schedule(local_redirect_url, GetDefaultCallback())); |
| 548 WaitForNoJobs(); |
| 549 |
| 550 // The fetcher should have refused the redirect job. |
| 551 EXPECT_EQ(1, jobs_requested()); |
| 552 std::vector<DictionaryAdditions> additions; |
| 553 GetDictionaryAdditions(&additions); |
| 554 // And there should be no dictionaries added. |
| 555 EXPECT_EQ(0u, additions.size()); |
| 556 } |
| 557 |
| 437 } // namespace | 558 } // namespace |
| 438 | 559 |
| 439 } // namespace net | 560 } // namespace net |
| OLD | NEW |