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