1d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "content/test/weburl_loader_mock_factory.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/file_util.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
97dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "base/run_loop.h"
10d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "content/test/weburl_loader_mock.h"
11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "third_party/WebKit/public/platform/WebString.h"
12868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "third_party/WebKit/public/platform/WebURLError.h"
13868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "third_party/WebKit/public/platform/WebURLRequest.h"
14868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "third_party/WebKit/public/platform/WebURLResponse.h"
157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "third_party/WebKit/public/web/WebCache.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using blink::WebCache;
18f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using blink::WebData;
19f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using blink::WebString;
20f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using blink::WebURL;
21f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using blink::WebURLError;
22f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using blink::WebURLLoader;
23f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using blink::WebURLRequest;
24f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using blink::WebURLResponse;
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)WebURLLoaderMockFactory::WebURLLoaderMockFactory() {}
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)WebURLLoaderMockFactory::~WebURLLoaderMockFactory() {}
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WebURLLoaderMockFactory::RegisterURL(const WebURL& url,
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          const WebURLResponse& response,
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          const WebString& file_path) {
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ResponseInfo response_info;
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  response_info.response = response;
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!file_path.isNull() && !file_path.isEmpty()) {
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_POSIX)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // TODO(jcivelli): On Linux, UTF8 might not be correct.
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    response_info.file_path =
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::FilePath(static_cast<std::string>(file_path.utf8()));
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_WIN)
41a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    base::string16 file_path_16 = file_path;
42868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    response_info.file_path = base::FilePath(std::wstring(
43868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        file_path_16.data(), file_path_16.length()));
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    DCHECK(base::PathExists(response_info.file_path))
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        << response_info.file_path.MaybeAsASCII() << " does not exist.";
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(url_to_reponse_info_.find(url) == url_to_reponse_info_.end());
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  url_to_reponse_info_[url] = response_info;
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WebURLLoaderMockFactory::RegisterErrorURL(const WebURL& url,
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                               const WebURLResponse& response,
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                               const WebURLError& error) {
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(url_to_reponse_info_.find(url) == url_to_reponse_info_.end());
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RegisterURL(url, response, WebString());
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  url_to_error_info_[url] = error;
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
62f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void WebURLLoaderMockFactory::UnregisterURL(const blink::WebURL& url) {
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  URLToResponseMap::iterator iter = url_to_reponse_info_.find(url);
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(iter != url_to_reponse_info_.end());
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  url_to_reponse_info_.erase(iter);
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  URLToErrorMap::iterator error_iter = url_to_error_info_.find(url);
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (error_iter != url_to_error_info_.end())
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    url_to_error_info_.erase(error_iter);
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WebURLLoaderMockFactory::UnregisterAllURLs() {
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  url_to_reponse_info_.clear();
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  url_to_error_info_.clear();
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  WebCache::clear();
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WebURLLoaderMockFactory::ServeAsynchronousRequests() {
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  last_handled_asynchronous_request_.reset();
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Serving a request might trigger more requests, so we cannot iterate on
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // pending_loaders_ as it might get modified.
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (!pending_loaders_.empty()) {
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LoaderToRequestMap::iterator iter = pending_loaders_.begin();
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WebURLLoaderMock* loader = iter->first;
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const WebURLRequest& request = iter->second;
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WebURLResponse response;
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WebURLError error;
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WebData data;
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    last_handled_asynchronous_request_ = request;
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LoadRequest(request, &response, &error, &data);
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Follow any redirects while the loader is still active.
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (response.httpStatusCode() >= 300 &&
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           response.httpStatusCode() < 400) {
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      WebURLRequest newRequest = loader->ServeRedirect(response);
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!IsPending(loader) || loader->isDeferred())
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      last_handled_asynchronous_request_ = newRequest;
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LoadRequest(newRequest, &response, &error, &data);
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Serve the request if the loader is still active.
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (IsPending(loader) && !loader->isDeferred())
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      loader->ServeAsynchronousRequest(response, data, error);
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The loader might have already been removed.
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pending_loaders_.erase(loader);
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  base::RunLoop().RunUntilIdle();
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
109f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)blink::WebURLRequest
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)WebURLLoaderMockFactory::GetLastHandledAsynchronousRequest() {
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return last_handled_asynchronous_request_;
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
114f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)bool WebURLLoaderMockFactory::IsMockedURL(const blink::WebURL& url) {
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return url_to_reponse_info_.find(url) != url_to_reponse_info_.end();
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WebURLLoaderMockFactory::CancelLoad(WebURLLoaderMock* loader) {
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LoaderToRequestMap::iterator iter = pending_loaders_.find(loader);
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(iter != pending_loaders_.end());
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pending_loaders_.erase(iter);
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)WebURLLoader* WebURLLoaderMockFactory::CreateURLLoader(
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WebURLLoader* default_loader) {
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(default_loader);
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return new WebURLLoaderMock(this, default_loader);
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WebURLLoaderMockFactory::LoadSynchronously(const WebURLRequest& request,
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                WebURLResponse* response,
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                WebURLError* error,
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                WebData* data) {
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LoadRequest(request, response, error, data);
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WebURLLoaderMockFactory::LoadAsynchronouly(const WebURLRequest& request,
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                WebURLLoaderMock* loader) {
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LoaderToRequestMap::iterator iter = pending_loaders_.find(loader);
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(iter == pending_loaders_.end());
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pending_loaders_[loader] = request;
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WebURLLoaderMockFactory::LoadRequest(const WebURLRequest& request,
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          WebURLResponse* response,
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          WebURLError* error,
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          WebData* data) {
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  URLToErrorMap::const_iterator error_iter =
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      url_to_error_info_.find(request.url());
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (error_iter != url_to_error_info_.end())
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *error = error_iter->second;
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  URLToResponseMap::const_iterator iter =
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      url_to_reponse_info_.find(request.url());
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (iter == url_to_reponse_info_.end()) {
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Non mocked URLs should not have been passed to the default URLLoader.
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!error->reason && !ReadFile(iter->second.file_path, data)) {
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *response = iter->second.response;
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool WebURLLoaderMockFactory::IsPending(WebURLLoaderMock* loader) {
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LoaderToRequestMap::iterator iter = pending_loaders_.find(loader);
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return iter != pending_loaders_.end();
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool WebURLLoaderMockFactory::ReadFile(const base::FilePath& file_path,
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       WebData* data) {
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int64 file_size = 0;
178a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (!base::GetFileSize(file_path, &file_size))
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int size = static_cast<int>(file_size);
182c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<char[]> buffer(new char[size]);
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data->reset();
184a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  int read_count = base::ReadFile(file_path, buffer.get(), size);
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (read_count == -1)
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(read_count == size);
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data->assign(buffer.get(), size);
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
192