OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2011 The Native Client 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 "native_client/tests/ppapi_geturl/url_load_request.h" |
| 6 |
| 7 #include <stdio.h> |
| 8 #include <string> |
| 9 #include <sstream> |
| 10 |
| 11 #include "native_client/src/include/portability.h" |
| 12 #include "native_client/src/include/nacl_macros.h" |
| 13 #include "native_client/src/shared/platform/nacl_check.h" |
| 14 #include "native_client/tests/ppapi_geturl/module.h" |
| 15 #include "ppapi/c/pp_bool.h" |
| 16 #include "ppapi/c/pp_completion_callback.h" |
| 17 #include "ppapi/c/pp_errors.h" |
| 18 |
| 19 namespace { |
| 20 |
| 21 // A local helper that does not contribute to loading/reading of urls, but |
| 22 // allows us to test proxying of Is<Interface> functions. |
| 23 // TODO(polina): when we have unit tests, move this there. |
| 24 void TestIsInterface(std::string test_interface, |
| 25 PP_Resource resource, |
| 26 const PPB_FileIO* ppb_fileio, |
| 27 const PPB_URLRequestInfo* ppb_url_request_info, |
| 28 const PPB_URLResponseInfo* ppb_url_response_info, |
| 29 const PPB_URLLoader* ppb_url_loader) { |
| 30 printf("--- TestIsInterface: %s\n", test_interface.c_str()); |
| 31 if (test_interface == PPB_FILEIO_INTERFACE) { |
| 32 CHECK(ppb_fileio->IsFileIO(resource) == PP_TRUE); |
| 33 CHECK(ppb_url_request_info->IsURLRequestInfo(resource) == PP_FALSE); |
| 34 CHECK(ppb_url_response_info->IsURLResponseInfo(resource) == PP_FALSE); |
| 35 CHECK(ppb_url_loader->IsURLLoader(resource) == PP_FALSE); |
| 36 } else if (test_interface == PPB_URLREQUESTINFO_INTERFACE) { |
| 37 CHECK(ppb_fileio->IsFileIO(resource) == PP_FALSE); |
| 38 CHECK(ppb_url_request_info->IsURLRequestInfo(resource) == PP_TRUE); |
| 39 CHECK(ppb_url_response_info->IsURLResponseInfo(resource) == PP_FALSE); |
| 40 CHECK(ppb_url_loader->IsURLLoader(resource) == PP_FALSE); |
| 41 } else if (test_interface == PPB_URLRESPONSEINFO_INTERFACE) { |
| 42 CHECK(ppb_fileio->IsFileIO(resource) == PP_FALSE); |
| 43 CHECK(ppb_url_request_info->IsURLRequestInfo(resource) == PP_FALSE); |
| 44 CHECK(ppb_url_response_info->IsURLResponseInfo(resource) == PP_TRUE); |
| 45 CHECK(ppb_url_loader->IsURLLoader(resource) == PP_FALSE); |
| 46 } else if (test_interface == PPB_URLLOADER_INTERFACE) { |
| 47 CHECK(ppb_fileio->IsFileIO(resource) == PP_FALSE); |
| 48 CHECK(ppb_url_request_info->IsURLRequestInfo(resource) == PP_FALSE); |
| 49 CHECK(ppb_url_response_info->IsURLResponseInfo(resource) == PP_FALSE); |
| 50 CHECK(ppb_url_loader->IsURLLoader(resource) == PP_TRUE); |
| 51 } |
| 52 } |
| 53 |
| 54 void OpenCallback(void* user_data, int32_t pp_error) { |
| 55 UrlLoadRequest* obj = reinterpret_cast<UrlLoadRequest*>(user_data); |
| 56 if (NULL != obj) |
| 57 obj->OpenCallback(pp_error); |
| 58 } |
| 59 |
| 60 void FinishStreamingToFileCallback(void* user_data, int32_t pp_error) { |
| 61 UrlLoadRequest* obj = reinterpret_cast<UrlLoadRequest*>(user_data); |
| 62 if (NULL != obj) |
| 63 obj->FinishStreamingToFileCallback(pp_error); |
| 64 } |
| 65 |
| 66 void ReadResponseBodyCallback(void* user_data, int32_t pp_error_or_bytes) { |
| 67 UrlLoadRequest* obj = reinterpret_cast<UrlLoadRequest*>(user_data); |
| 68 if (NULL != obj) |
| 69 obj->ReadResponseBodyCallback(pp_error_or_bytes); |
| 70 } |
| 71 |
| 72 void OpenFileBodyCallback(void* user_data, int32_t pp_error) { |
| 73 UrlLoadRequest* obj = reinterpret_cast<UrlLoadRequest*>(user_data); |
| 74 if (NULL != obj) |
| 75 obj->OpenFileBodyCallback(pp_error); |
| 76 } |
| 77 |
| 78 void ReadFileBodyCallback(void* user_data, int32_t pp_error_or_bytes) { |
| 79 UrlLoadRequest* obj = reinterpret_cast<UrlLoadRequest*>(user_data); |
| 80 if (NULL != obj) |
| 81 obj->ReadFileBodyCallback(pp_error_or_bytes); |
| 82 } |
| 83 |
| 84 } // namespace |
| 85 |
| 86 |
| 87 UrlLoadRequest::UrlLoadRequest(PP_Instance instance) |
| 88 : delete_this_after_report(false), |
| 89 as_file_(false), |
| 90 instance_(instance), |
| 91 request_(0), |
| 92 loader_(0), |
| 93 response_(0), |
| 94 fileio_(0), |
| 95 request_interface_(NULL), |
| 96 loader_interface_(NULL), |
| 97 fileio_interface_(NULL), |
| 98 read_offset_(0) { |
| 99 } |
| 100 |
| 101 UrlLoadRequest::~UrlLoadRequest() { |
| 102 Clear(); |
| 103 } |
| 104 |
| 105 void UrlLoadRequest::Clear() { |
| 106 Module* module = Module::Get(); |
| 107 if (0 != request_) { |
| 108 module->ppb_core_interface()->ReleaseResource(request_); |
| 109 request_ = 0; |
| 110 } |
| 111 if (0 != loader_) { |
| 112 module->ppb_core_interface()->ReleaseResource(loader_); |
| 113 loader_ = 0; |
| 114 } |
| 115 if (0 != response_) { |
| 116 module->ppb_core_interface()->ReleaseResource(response_); |
| 117 response_ = 0; |
| 118 } |
| 119 if (0 != fileio_) { |
| 120 module->ppb_core_interface()->ReleaseResource(fileio_); |
| 121 fileio_ = 0; |
| 122 } |
| 123 url_body_.clear(); |
| 124 } |
| 125 |
| 126 bool UrlLoadRequest::ReportSuccess() { |
| 127 Module::Get()->ReportResult( |
| 128 instance_, url_.c_str(), as_file_, url_body_.c_str(), true); |
| 129 if (delete_this_after_report) { |
| 130 delete this; |
| 131 } |
| 132 return true; |
| 133 } |
| 134 |
| 135 bool UrlLoadRequest::ReportFailure(const std::string& error) { |
| 136 Module::Get()->ReportResult( |
| 137 instance_, url_.c_str(), as_file_, error.c_str(), false); |
| 138 if (delete_this_after_report) { |
| 139 delete this; |
| 140 } |
| 141 return false; |
| 142 } |
| 143 |
| 144 bool UrlLoadRequest::ReportFailure(const std::string& message, |
| 145 int32_t pp_error) { |
| 146 std::string error = message; |
| 147 error.append(Module::ErrorCodeToStr(pp_error)); |
| 148 return ReportFailure(error); |
| 149 } |
| 150 |
| 151 bool UrlLoadRequest::Load(bool as_file, std::string url) { |
| 152 printf("--- UrlLoadRequest::Load(as_file=%d, '%s')\n", as_file, url.c_str()); |
| 153 url_ = url; |
| 154 as_file_ = as_file; |
| 155 Clear(); |
| 156 std::string error; |
| 157 if (!GetRequiredInterfaces(&error)) { |
| 158 return ReportFailure(error); |
| 159 } |
| 160 PP_Bool set_url = request_interface_->SetProperty( |
| 161 request_, PP_URLREQUESTPROPERTY_URL, Module::StrToVar(url)); |
| 162 PP_Bool set_method = request_interface_->SetProperty( |
| 163 request_, PP_URLREQUESTPROPERTY_METHOD, Module::StrToVar("GET")); |
| 164 PP_Bool pp_as_file = as_file ? PP_TRUE : PP_FALSE; |
| 165 PP_Bool set_file = request_interface_->SetProperty( |
| 166 request_, PP_URLREQUESTPROPERTY_STREAMTOFILE, PP_MakeBool(pp_as_file)); |
| 167 if (set_url != PP_TRUE || set_method != PP_TRUE || set_file != PP_TRUE) { |
| 168 return ReportFailure("PPB_URLRequestInfo::SetProperty: failed"); |
| 169 } |
| 170 loader_interface_->Open( |
| 171 loader_, |
| 172 request_, |
| 173 PP_MakeCompletionCallback(::OpenCallback, this)); |
| 174 return true; |
| 175 } |
| 176 |
| 177 bool UrlLoadRequest::GetRequiredInterfaces(std::string* error) { |
| 178 Module* module = Module::Get(); |
| 179 |
| 180 request_interface_ = static_cast<const PPB_URLRequestInfo*>( |
| 181 module->GetBrowserInterface(PPB_URLREQUESTINFO_INTERFACE)); |
| 182 if (NULL == request_interface_) { |
| 183 *error = "Failed to get browser interface '" PPB_URLREQUESTINFO_INTERFACE; |
| 184 return false; |
| 185 } |
| 186 request_ = request_interface_->Create(instance_); |
| 187 if (0 == request_) { |
| 188 *error = "PPB_URLRequestInfo::Create: failed"; |
| 189 return false; |
| 190 } |
| 191 |
| 192 response_interface_ = static_cast<const PPB_URLResponseInfo*>( |
| 193 module->GetBrowserInterface(PPB_URLRESPONSEINFO_INTERFACE)); |
| 194 if (NULL == response_interface_) { |
| 195 *error = "Failed to get browser interface '" PPB_URLRESPONSEINFO_INTERFACE; |
| 196 return false; |
| 197 } |
| 198 |
| 199 loader_interface_ = static_cast<const PPB_URLLoader*>( |
| 200 module->GetBrowserInterface(PPB_URLLOADER_INTERFACE)); |
| 201 if (NULL == loader_interface_) { |
| 202 *error = "Failed to get browser interface '" PPB_URLLOADER_INTERFACE; |
| 203 return false; |
| 204 } |
| 205 loader_ = loader_interface_->Create(instance_); |
| 206 if (0 == loader_) { |
| 207 *error = "PPB_URLLoader::Create: failed"; |
| 208 return false; |
| 209 } |
| 210 |
| 211 fileio_interface_ = static_cast<const PPB_FileIO*>( |
| 212 module->GetBrowserInterface(PPB_FILEIO_INTERFACE)); |
| 213 if (NULL == fileio_interface_) { |
| 214 *error = "Failed to get browser interface '" PPB_FILEIO_INTERFACE; |
| 215 return false; |
| 216 } |
| 217 fileio_ = fileio_interface_->Create(instance_); |
| 218 if (0 == fileio_) { |
| 219 *error = "PPB_FileIO::Create: failed"; |
| 220 return false; |
| 221 } |
| 222 |
| 223 TestIsInterface(PPB_URLREQUESTINFO_INTERFACE, request_, |
| 224 fileio_interface_, request_interface_, response_interface_, |
| 225 loader_interface_); |
| 226 TestIsInterface(PPB_URLLOADER_INTERFACE, loader_, |
| 227 fileio_interface_, request_interface_, response_interface_, |
| 228 loader_interface_); |
| 229 TestIsInterface(PPB_FILEIO_INTERFACE, fileio_, |
| 230 fileio_interface_, request_interface_, response_interface_, |
| 231 loader_interface_); |
| 232 |
| 233 return true; |
| 234 } |
| 235 |
| 236 void UrlLoadRequest::ReadResponseBody() { |
| 237 loader_interface_->ReadResponseBody( |
| 238 loader_, |
| 239 buffer_, |
| 240 sizeof(buffer_), |
| 241 PP_MakeCompletionCallback(::ReadResponseBodyCallback, this)); |
| 242 } |
| 243 |
| 244 void UrlLoadRequest::ReadFileBody() { |
| 245 fileio_interface_->Read( |
| 246 fileio_, |
| 247 read_offset_, |
| 248 buffer_, |
| 249 sizeof(buffer_), |
| 250 PP_MakeCompletionCallback(::ReadFileBodyCallback, this)); |
| 251 } |
| 252 |
| 253 void UrlLoadRequest::OpenCallback(int32_t pp_error) { |
| 254 printf("--- UrlLoadRequest::OpenCallback\n"); |
| 255 if (pp_error != PP_OK) { |
| 256 ReportFailure("UrlLoadRequest::OpenCallback: ", pp_error); |
| 257 return; |
| 258 } |
| 259 |
| 260 // Validating response headers to confirm successful loading. |
| 261 response_ = loader_interface_->GetResponseInfo(loader_); |
| 262 if (0 == response_) { |
| 263 ReportFailure("UrlLoadRequest::OpenCallback: null response"); |
| 264 return; |
| 265 } |
| 266 TestIsInterface(PPB_URLRESPONSEINFO_INTERFACE, response_, |
| 267 fileio_interface_, request_interface_, response_interface_, |
| 268 loader_interface_); |
| 269 PP_Var url = response_interface_->GetProperty(response_, |
| 270 PP_URLRESPONSEPROPERTY_URL); |
| 271 if (url.type != PP_VARTYPE_STRING) { |
| 272 ReportFailure("URLLoadRequest::OpenCallback: bad url type"); |
| 273 return; |
| 274 } |
| 275 url_ = Module::VarToStr(url); // Update url to be fully qualified. |
| 276 PP_Var status_code = |
| 277 response_interface_->GetProperty(response_, |
| 278 PP_URLRESPONSEPROPERTY_STATUSCODE); |
| 279 int32_t status_code_as_int = status_code.value.as_int; |
| 280 if (status_code_as_int != 200) { // Not HTTP OK. |
| 281 std::stringstream error; |
| 282 error << "OpenCallback: status_code=" << status_code_as_int; |
| 283 ReportFailure(error.str()); |
| 284 return; |
| 285 } |
| 286 |
| 287 if (as_file_) { |
| 288 loader_interface_->FinishStreamingToFile( |
| 289 loader_, |
| 290 PP_MakeCompletionCallback(::FinishStreamingToFileCallback, this)); |
| 291 } else { |
| 292 ReadResponseBody(); |
| 293 } |
| 294 } |
| 295 |
| 296 void UrlLoadRequest::FinishStreamingToFileCallback(int32_t pp_error) { |
| 297 printf("--- UrlLoadRequest::FinishStreamingToFileCallback\n"); |
| 298 if (pp_error != PP_OK) { |
| 299 ReportFailure("UrlLoadRequest::FinishStreamingToFileCallback: ", pp_error); |
| 300 return; |
| 301 } |
| 302 PP_Resource fileref = response_interface_->GetBodyAsFileRef(response_); |
| 303 if (0 == fileref) { |
| 304 ReportFailure("UrlLoadRequest::FinishStreamingToFileCallback: null file"); |
| 305 return; |
| 306 } |
| 307 fileio_interface_->Open( |
| 308 fileio_, |
| 309 fileref, |
| 310 PP_FILEOPENFLAG_READ, |
| 311 PP_MakeCompletionCallback(::OpenFileBodyCallback, this)); |
| 312 } |
| 313 |
| 314 void UrlLoadRequest::ReadResponseBodyCallback(int32_t pp_error_or_bytes) { |
| 315 printf("--- UrlLoadRequest::ReadResponseBodyCallback\n"); |
| 316 if (pp_error_or_bytes < PP_OK) { |
| 317 ReportFailure("UrlLoadRequest::ReadResponseBodyCallback: ", |
| 318 pp_error_or_bytes); |
| 319 } else if (pp_error_or_bytes == PP_OK) { // Reached EOF. |
| 320 ReportSuccess(); |
| 321 } else { // Partial read, so copy out the buffer and continue reading. |
| 322 for (int32_t i = 0; i < pp_error_or_bytes; i++) |
| 323 url_body_.push_back(buffer_[i]); |
| 324 ReadResponseBody(); |
| 325 } |
| 326 } |
| 327 |
| 328 void UrlLoadRequest::ReadFileBodyCallback(int32_t pp_error_or_bytes) { |
| 329 printf("--- UrlLoadRequest::ReadFileBodyCallback\n"); |
| 330 if (pp_error_or_bytes < PP_OK) { |
| 331 ReportFailure("UrlLoadRequest::ReadFileBodyCallback: ", |
| 332 pp_error_or_bytes); |
| 333 } else if (pp_error_or_bytes == PP_OK) { // Reached EOF. |
| 334 ReportSuccess(); |
| 335 } else { // Partial read, so copy out the buffer and continue reading. |
| 336 for (int32_t i = 0; i < pp_error_or_bytes; i++) |
| 337 url_body_.push_back(buffer_[i]); |
| 338 read_offset_ += pp_error_or_bytes; |
| 339 ReadFileBody(); |
| 340 } |
| 341 } |
| 342 |
| 343 void UrlLoadRequest::OpenFileBodyCallback(int32_t pp_error) { |
| 344 printf("--- UrlLoadRequest::OpenFileBodyCallback\n"); |
| 345 if (pp_error != PP_OK) { |
| 346 ReportFailure("UrlLoadRequest::OpenFileBodyCallback: ", pp_error); |
| 347 return; |
| 348 } |
| 349 ReadFileBody(); |
| 350 } |
OLD | NEW |