Home | History | Annotate | Download | only in support
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "webkit/support/weburl_loader_mock_factory.h"
      6 
      7 #include "base/file_util.h"
      8 #include "base/logging.h"
      9 #include "base/run_loop.h"
     10 #include "third_party/WebKit/public/platform/WebString.h"
     11 #include "third_party/WebKit/public/platform/WebURLError.h"
     12 #include "third_party/WebKit/public/platform/WebURLRequest.h"
     13 #include "third_party/WebKit/public/platform/WebURLResponse.h"
     14 #include "third_party/WebKit/public/web/WebCache.h"
     15 #include "webkit/support/webkit_support.h"
     16 #include "webkit/support/weburl_loader_mock.h"
     17 
     18 using WebKit::WebCache;
     19 using WebKit::WebData;
     20 using WebKit::WebString;
     21 using WebKit::WebURL;
     22 using WebKit::WebURLError;
     23 using WebKit::WebURLLoader;
     24 using WebKit::WebURLRequest;
     25 using WebKit::WebURLResponse;
     26 
     27 struct WebURLLoaderMockFactory::ResponseInfo {
     28   WebKit::WebURLResponse response;
     29   base::FilePath file_path;
     30 };
     31 
     32 WebURLLoaderMockFactory::WebURLLoaderMockFactory() {}
     33 
     34 WebURLLoaderMockFactory::~WebURLLoaderMockFactory() {}
     35 
     36 void WebURLLoaderMockFactory::RegisterURL(const WebURL& url,
     37                                           const WebURLResponse& response,
     38                                           const WebString& file_path) {
     39   ResponseInfo response_info;
     40   response_info.response = response;
     41   if (!file_path.isNull() && !file_path.isEmpty()) {
     42 #if defined(OS_POSIX)
     43     // TODO(jcivelli): On Linux, UTF8 might not be correct.
     44     response_info.file_path =
     45         base::FilePath(static_cast<std::string>(file_path.utf8()));
     46 #elif defined(OS_WIN)
     47     string16 file_path_16 = file_path;
     48     response_info.file_path = base::FilePath(std::wstring(
     49         file_path_16.data(), file_path_16.length()));
     50 #endif
     51     DCHECK(base::PathExists(response_info.file_path))
     52         << response_info.file_path.MaybeAsASCII() << " does not exist.";
     53   }
     54 
     55   DCHECK(url_to_reponse_info_.find(url) == url_to_reponse_info_.end());
     56   url_to_reponse_info_[url] = response_info;
     57 }
     58 
     59 
     60 void WebURLLoaderMockFactory::RegisterErrorURL(const WebURL& url,
     61                                                const WebURLResponse& response,
     62                                                const WebURLError& error) {
     63   DCHECK(url_to_reponse_info_.find(url) == url_to_reponse_info_.end());
     64   RegisterURL(url, response, WebString());
     65   url_to_error_info_[url] = error;
     66 }
     67 
     68 void WebURLLoaderMockFactory::UnregisterURL(const WebKit::WebURL& url) {
     69   URLToResponseMap::iterator iter = url_to_reponse_info_.find(url);
     70   DCHECK(iter != url_to_reponse_info_.end());
     71   url_to_reponse_info_.erase(iter);
     72 
     73   URLToErrorMap::iterator error_iter = url_to_error_info_.find(url);
     74   if (error_iter != url_to_error_info_.end())
     75     url_to_error_info_.erase(error_iter);
     76 }
     77 
     78 void WebURLLoaderMockFactory::UnregisterAllURLs() {
     79   url_to_reponse_info_.clear();
     80   url_to_error_info_.clear();
     81   WebCache::clear();
     82 }
     83 
     84 void WebURLLoaderMockFactory::ServeAsynchronousRequests() {
     85   last_handled_asynchronous_request_.reset();
     86   // Serving a request might trigger more requests, so we cannot iterate on
     87   // pending_loaders_ as it might get modified.
     88   while (!pending_loaders_.empty()) {
     89     LoaderToRequestMap::iterator iter = pending_loaders_.begin();
     90     WebURLLoaderMock* loader = iter->first;
     91     const WebURLRequest& request = iter->second;
     92     WebURLResponse response;
     93     WebURLError error;
     94     WebData data;
     95     last_handled_asynchronous_request_ = request;
     96     LoadRequest(request, &response, &error, &data);
     97     // Follow any redirects while the loader is still active.
     98     while (response.httpStatusCode() >= 300 &&
     99            response.httpStatusCode() < 400) {
    100       WebURLRequest newRequest = loader->ServeRedirect(response);
    101       if (!IsPending(loader) || loader->isDeferred())
    102         break;
    103       last_handled_asynchronous_request_ = newRequest;
    104       LoadRequest(newRequest, &response, &error, &data);
    105     }
    106     // Serve the request if the loader is still active.
    107     if (IsPending(loader) && !loader->isDeferred())
    108       loader->ServeAsynchronousRequest(response, data, error);
    109     // The loader might have already been removed.
    110     pending_loaders_.erase(loader);
    111   }
    112   base::RunLoop().RunUntilIdle();
    113 }
    114 
    115 WebKit::WebURLRequest
    116 WebURLLoaderMockFactory::GetLastHandledAsynchronousRequest() {
    117   return last_handled_asynchronous_request_;
    118 }
    119 
    120 bool WebURLLoaderMockFactory::IsMockedURL(const WebKit::WebURL& url) {
    121   return url_to_reponse_info_.find(url) != url_to_reponse_info_.end();
    122 }
    123 
    124 void WebURLLoaderMockFactory::CancelLoad(WebURLLoaderMock* loader) {
    125   LoaderToRequestMap::iterator iter = pending_loaders_.find(loader);
    126   DCHECK(iter != pending_loaders_.end());
    127   pending_loaders_.erase(iter);
    128 }
    129 
    130 WebURLLoader* WebURLLoaderMockFactory::CreateURLLoader(
    131     WebURLLoader* default_loader) {
    132   DCHECK(default_loader);
    133   return new WebURLLoaderMock(this, default_loader);
    134 }
    135 
    136 void WebURLLoaderMockFactory::LoadSynchronously(const WebURLRequest& request,
    137                                                 WebURLResponse* response,
    138                                                 WebURLError* error,
    139                                                 WebData* data) {
    140   LoadRequest(request, response, error, data);
    141 }
    142 
    143 void WebURLLoaderMockFactory::LoadAsynchronouly(const WebURLRequest& request,
    144                                                 WebURLLoaderMock* loader) {
    145   LoaderToRequestMap::iterator iter = pending_loaders_.find(loader);
    146   DCHECK(iter == pending_loaders_.end());
    147   pending_loaders_[loader] = request;
    148 }
    149 
    150 void WebURLLoaderMockFactory::LoadRequest(const WebURLRequest& request,
    151                                           WebURLResponse* response,
    152                                           WebURLError* error,
    153                                           WebData* data) {
    154   URLToErrorMap::const_iterator error_iter =
    155       url_to_error_info_.find(request.url());
    156   if (error_iter != url_to_error_info_.end())
    157     *error = error_iter->second;
    158 
    159   URLToResponseMap::const_iterator iter =
    160       url_to_reponse_info_.find(request.url());
    161   if (iter == url_to_reponse_info_.end()) {
    162     // Non mocked URLs should not have been passed to the default URLLoader.
    163     NOTREACHED();
    164     return;
    165   }
    166 
    167   if (!error->reason && !ReadFile(iter->second.file_path, data)) {
    168     NOTREACHED();
    169     return;
    170   }
    171 
    172   *response = iter->second.response;
    173 }
    174 
    175 bool WebURLLoaderMockFactory::IsPending(WebURLLoaderMock* loader) {
    176   LoaderToRequestMap::iterator iter = pending_loaders_.find(loader);
    177   return iter != pending_loaders_.end();
    178 }
    179 
    180 // static
    181 bool WebURLLoaderMockFactory::ReadFile(const base::FilePath& file_path,
    182                                        WebData* data) {
    183   int64 file_size = 0;
    184   if (!file_util::GetFileSize(file_path, &file_size))
    185     return false;
    186 
    187   int size = static_cast<int>(file_size);
    188   scoped_ptr<char[]> buffer(new char[size]);
    189   data->reset();
    190   int read_count = file_util::ReadFile(file_path, buffer.get(), size);
    191   if (read_count == -1)
    192     return false;
    193   DCHECK(read_count == size);
    194   data->assign(buffer.get(), size);
    195 
    196   return true;
    197 }
    198