| Index: ppapi/native_client/tests/ppapi_geturl/url_load_request.cc
|
| ===================================================================
|
| --- ppapi/native_client/tests/ppapi_geturl/url_load_request.cc (revision 0)
|
| +++ ppapi/native_client/tests/ppapi_geturl/url_load_request.cc (revision 0)
|
| @@ -0,0 +1,350 @@
|
| +// Copyright (c) 2011 The Native Client Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "native_client/tests/ppapi_geturl/url_load_request.h"
|
| +
|
| +#include <stdio.h>
|
| +#include <string>
|
| +#include <sstream>
|
| +
|
| +#include "native_client/src/include/portability.h"
|
| +#include "native_client/src/include/nacl_macros.h"
|
| +#include "native_client/src/shared/platform/nacl_check.h"
|
| +#include "native_client/tests/ppapi_geturl/module.h"
|
| +#include "ppapi/c/pp_bool.h"
|
| +#include "ppapi/c/pp_completion_callback.h"
|
| +#include "ppapi/c/pp_errors.h"
|
| +
|
| +namespace {
|
| +
|
| +// A local helper that does not contribute to loading/reading of urls, but
|
| +// allows us to test proxying of Is<Interface> functions.
|
| +// TODO(polina): when we have unit tests, move this there.
|
| +void TestIsInterface(std::string test_interface,
|
| + PP_Resource resource,
|
| + const PPB_FileIO* ppb_fileio,
|
| + const PPB_URLRequestInfo* ppb_url_request_info,
|
| + const PPB_URLResponseInfo* ppb_url_response_info,
|
| + const PPB_URLLoader* ppb_url_loader) {
|
| + printf("--- TestIsInterface: %s\n", test_interface.c_str());
|
| + if (test_interface == PPB_FILEIO_INTERFACE) {
|
| + CHECK(ppb_fileio->IsFileIO(resource) == PP_TRUE);
|
| + CHECK(ppb_url_request_info->IsURLRequestInfo(resource) == PP_FALSE);
|
| + CHECK(ppb_url_response_info->IsURLResponseInfo(resource) == PP_FALSE);
|
| + CHECK(ppb_url_loader->IsURLLoader(resource) == PP_FALSE);
|
| + } else if (test_interface == PPB_URLREQUESTINFO_INTERFACE) {
|
| + CHECK(ppb_fileio->IsFileIO(resource) == PP_FALSE);
|
| + CHECK(ppb_url_request_info->IsURLRequestInfo(resource) == PP_TRUE);
|
| + CHECK(ppb_url_response_info->IsURLResponseInfo(resource) == PP_FALSE);
|
| + CHECK(ppb_url_loader->IsURLLoader(resource) == PP_FALSE);
|
| + } else if (test_interface == PPB_URLRESPONSEINFO_INTERFACE) {
|
| + CHECK(ppb_fileio->IsFileIO(resource) == PP_FALSE);
|
| + CHECK(ppb_url_request_info->IsURLRequestInfo(resource) == PP_FALSE);
|
| + CHECK(ppb_url_response_info->IsURLResponseInfo(resource) == PP_TRUE);
|
| + CHECK(ppb_url_loader->IsURLLoader(resource) == PP_FALSE);
|
| + } else if (test_interface == PPB_URLLOADER_INTERFACE) {
|
| + CHECK(ppb_fileio->IsFileIO(resource) == PP_FALSE);
|
| + CHECK(ppb_url_request_info->IsURLRequestInfo(resource) == PP_FALSE);
|
| + CHECK(ppb_url_response_info->IsURLResponseInfo(resource) == PP_FALSE);
|
| + CHECK(ppb_url_loader->IsURLLoader(resource) == PP_TRUE);
|
| + }
|
| +}
|
| +
|
| +void OpenCallback(void* user_data, int32_t pp_error) {
|
| + UrlLoadRequest* obj = reinterpret_cast<UrlLoadRequest*>(user_data);
|
| + if (NULL != obj)
|
| + obj->OpenCallback(pp_error);
|
| +}
|
| +
|
| +void FinishStreamingToFileCallback(void* user_data, int32_t pp_error) {
|
| + UrlLoadRequest* obj = reinterpret_cast<UrlLoadRequest*>(user_data);
|
| + if (NULL != obj)
|
| + obj->FinishStreamingToFileCallback(pp_error);
|
| +}
|
| +
|
| +void ReadResponseBodyCallback(void* user_data, int32_t pp_error_or_bytes) {
|
| + UrlLoadRequest* obj = reinterpret_cast<UrlLoadRequest*>(user_data);
|
| + if (NULL != obj)
|
| + obj->ReadResponseBodyCallback(pp_error_or_bytes);
|
| +}
|
| +
|
| +void OpenFileBodyCallback(void* user_data, int32_t pp_error) {
|
| + UrlLoadRequest* obj = reinterpret_cast<UrlLoadRequest*>(user_data);
|
| + if (NULL != obj)
|
| + obj->OpenFileBodyCallback(pp_error);
|
| +}
|
| +
|
| +void ReadFileBodyCallback(void* user_data, int32_t pp_error_or_bytes) {
|
| + UrlLoadRequest* obj = reinterpret_cast<UrlLoadRequest*>(user_data);
|
| + if (NULL != obj)
|
| + obj->ReadFileBodyCallback(pp_error_or_bytes);
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +
|
| +UrlLoadRequest::UrlLoadRequest(PP_Instance instance)
|
| + : delete_this_after_report(false),
|
| + as_file_(false),
|
| + instance_(instance),
|
| + request_(0),
|
| + loader_(0),
|
| + response_(0),
|
| + fileio_(0),
|
| + request_interface_(NULL),
|
| + loader_interface_(NULL),
|
| + fileio_interface_(NULL),
|
| + read_offset_(0) {
|
| +}
|
| +
|
| +UrlLoadRequest::~UrlLoadRequest() {
|
| + Clear();
|
| +}
|
| +
|
| +void UrlLoadRequest::Clear() {
|
| + Module* module = Module::Get();
|
| + if (0 != request_) {
|
| + module->ppb_core_interface()->ReleaseResource(request_);
|
| + request_ = 0;
|
| + }
|
| + if (0 != loader_) {
|
| + module->ppb_core_interface()->ReleaseResource(loader_);
|
| + loader_ = 0;
|
| + }
|
| + if (0 != response_) {
|
| + module->ppb_core_interface()->ReleaseResource(response_);
|
| + response_ = 0;
|
| + }
|
| + if (0 != fileio_) {
|
| + module->ppb_core_interface()->ReleaseResource(fileio_);
|
| + fileio_ = 0;
|
| + }
|
| + url_body_.clear();
|
| +}
|
| +
|
| +bool UrlLoadRequest::ReportSuccess() {
|
| + Module::Get()->ReportResult(
|
| + instance_, url_.c_str(), as_file_, url_body_.c_str(), true);
|
| + if (delete_this_after_report) {
|
| + delete this;
|
| + }
|
| + return true;
|
| +}
|
| +
|
| +bool UrlLoadRequest::ReportFailure(const std::string& error) {
|
| + Module::Get()->ReportResult(
|
| + instance_, url_.c_str(), as_file_, error.c_str(), false);
|
| + if (delete_this_after_report) {
|
| + delete this;
|
| + }
|
| + return false;
|
| +}
|
| +
|
| +bool UrlLoadRequest::ReportFailure(const std::string& message,
|
| + int32_t pp_error) {
|
| + std::string error = message;
|
| + error.append(Module::ErrorCodeToStr(pp_error));
|
| + return ReportFailure(error);
|
| +}
|
| +
|
| +bool UrlLoadRequest::Load(bool as_file, std::string url) {
|
| + printf("--- UrlLoadRequest::Load(as_file=%d, '%s')\n", as_file, url.c_str());
|
| + url_ = url;
|
| + as_file_ = as_file;
|
| + Clear();
|
| + std::string error;
|
| + if (!GetRequiredInterfaces(&error)) {
|
| + return ReportFailure(error);
|
| + }
|
| + PP_Bool set_url = request_interface_->SetProperty(
|
| + request_, PP_URLREQUESTPROPERTY_URL, Module::StrToVar(url));
|
| + PP_Bool set_method = request_interface_->SetProperty(
|
| + request_, PP_URLREQUESTPROPERTY_METHOD, Module::StrToVar("GET"));
|
| + PP_Bool pp_as_file = as_file ? PP_TRUE : PP_FALSE;
|
| + PP_Bool set_file = request_interface_->SetProperty(
|
| + request_, PP_URLREQUESTPROPERTY_STREAMTOFILE, PP_MakeBool(pp_as_file));
|
| + if (set_url != PP_TRUE || set_method != PP_TRUE || set_file != PP_TRUE) {
|
| + return ReportFailure("PPB_URLRequestInfo::SetProperty: failed");
|
| + }
|
| + loader_interface_->Open(
|
| + loader_,
|
| + request_,
|
| + PP_MakeCompletionCallback(::OpenCallback, this));
|
| + return true;
|
| +}
|
| +
|
| +bool UrlLoadRequest::GetRequiredInterfaces(std::string* error) {
|
| + Module* module = Module::Get();
|
| +
|
| + request_interface_ = static_cast<const PPB_URLRequestInfo*>(
|
| + module->GetBrowserInterface(PPB_URLREQUESTINFO_INTERFACE));
|
| + if (NULL == request_interface_) {
|
| + *error = "Failed to get browser interface '" PPB_URLREQUESTINFO_INTERFACE;
|
| + return false;
|
| + }
|
| + request_ = request_interface_->Create(instance_);
|
| + if (0 == request_) {
|
| + *error = "PPB_URLRequestInfo::Create: failed";
|
| + return false;
|
| + }
|
| +
|
| + response_interface_ = static_cast<const PPB_URLResponseInfo*>(
|
| + module->GetBrowserInterface(PPB_URLRESPONSEINFO_INTERFACE));
|
| + if (NULL == response_interface_) {
|
| + *error = "Failed to get browser interface '" PPB_URLRESPONSEINFO_INTERFACE;
|
| + return false;
|
| + }
|
| +
|
| + loader_interface_ = static_cast<const PPB_URLLoader*>(
|
| + module->GetBrowserInterface(PPB_URLLOADER_INTERFACE));
|
| + if (NULL == loader_interface_) {
|
| + *error = "Failed to get browser interface '" PPB_URLLOADER_INTERFACE;
|
| + return false;
|
| + }
|
| + loader_ = loader_interface_->Create(instance_);
|
| + if (0 == loader_) {
|
| + *error = "PPB_URLLoader::Create: failed";
|
| + return false;
|
| + }
|
| +
|
| + fileio_interface_ = static_cast<const PPB_FileIO*>(
|
| + module->GetBrowserInterface(PPB_FILEIO_INTERFACE));
|
| + if (NULL == fileio_interface_) {
|
| + *error = "Failed to get browser interface '" PPB_FILEIO_INTERFACE;
|
| + return false;
|
| + }
|
| + fileio_ = fileio_interface_->Create(instance_);
|
| + if (0 == fileio_) {
|
| + *error = "PPB_FileIO::Create: failed";
|
| + return false;
|
| + }
|
| +
|
| + TestIsInterface(PPB_URLREQUESTINFO_INTERFACE, request_,
|
| + fileio_interface_, request_interface_, response_interface_,
|
| + loader_interface_);
|
| + TestIsInterface(PPB_URLLOADER_INTERFACE, loader_,
|
| + fileio_interface_, request_interface_, response_interface_,
|
| + loader_interface_);
|
| + TestIsInterface(PPB_FILEIO_INTERFACE, fileio_,
|
| + fileio_interface_, request_interface_, response_interface_,
|
| + loader_interface_);
|
| +
|
| + return true;
|
| +}
|
| +
|
| +void UrlLoadRequest::ReadResponseBody() {
|
| + loader_interface_->ReadResponseBody(
|
| + loader_,
|
| + buffer_,
|
| + sizeof(buffer_),
|
| + PP_MakeCompletionCallback(::ReadResponseBodyCallback, this));
|
| +}
|
| +
|
| +void UrlLoadRequest::ReadFileBody() {
|
| + fileio_interface_->Read(
|
| + fileio_,
|
| + read_offset_,
|
| + buffer_,
|
| + sizeof(buffer_),
|
| + PP_MakeCompletionCallback(::ReadFileBodyCallback, this));
|
| +}
|
| +
|
| +void UrlLoadRequest::OpenCallback(int32_t pp_error) {
|
| + printf("--- UrlLoadRequest::OpenCallback\n");
|
| + if (pp_error != PP_OK) {
|
| + ReportFailure("UrlLoadRequest::OpenCallback: ", pp_error);
|
| + return;
|
| + }
|
| +
|
| + // Validating response headers to confirm successful loading.
|
| + response_ = loader_interface_->GetResponseInfo(loader_);
|
| + if (0 == response_) {
|
| + ReportFailure("UrlLoadRequest::OpenCallback: null response");
|
| + return;
|
| + }
|
| + TestIsInterface(PPB_URLRESPONSEINFO_INTERFACE, response_,
|
| + fileio_interface_, request_interface_, response_interface_,
|
| + loader_interface_);
|
| + PP_Var url = response_interface_->GetProperty(response_,
|
| + PP_URLRESPONSEPROPERTY_URL);
|
| + if (url.type != PP_VARTYPE_STRING) {
|
| + ReportFailure("URLLoadRequest::OpenCallback: bad url type");
|
| + return;
|
| + }
|
| + url_ = Module::VarToStr(url); // Update url to be fully qualified.
|
| + PP_Var status_code =
|
| + response_interface_->GetProperty(response_,
|
| + PP_URLRESPONSEPROPERTY_STATUSCODE);
|
| + int32_t status_code_as_int = status_code.value.as_int;
|
| + if (status_code_as_int != 200) { // Not HTTP OK.
|
| + std::stringstream error;
|
| + error << "OpenCallback: status_code=" << status_code_as_int;
|
| + ReportFailure(error.str());
|
| + return;
|
| + }
|
| +
|
| + if (as_file_) {
|
| + loader_interface_->FinishStreamingToFile(
|
| + loader_,
|
| + PP_MakeCompletionCallback(::FinishStreamingToFileCallback, this));
|
| + } else {
|
| + ReadResponseBody();
|
| + }
|
| +}
|
| +
|
| +void UrlLoadRequest::FinishStreamingToFileCallback(int32_t pp_error) {
|
| + printf("--- UrlLoadRequest::FinishStreamingToFileCallback\n");
|
| + if (pp_error != PP_OK) {
|
| + ReportFailure("UrlLoadRequest::FinishStreamingToFileCallback: ", pp_error);
|
| + return;
|
| + }
|
| + PP_Resource fileref = response_interface_->GetBodyAsFileRef(response_);
|
| + if (0 == fileref) {
|
| + ReportFailure("UrlLoadRequest::FinishStreamingToFileCallback: null file");
|
| + return;
|
| + }
|
| + fileio_interface_->Open(
|
| + fileio_,
|
| + fileref,
|
| + PP_FILEOPENFLAG_READ,
|
| + PP_MakeCompletionCallback(::OpenFileBodyCallback, this));
|
| +}
|
| +
|
| +void UrlLoadRequest::ReadResponseBodyCallback(int32_t pp_error_or_bytes) {
|
| + printf("--- UrlLoadRequest::ReadResponseBodyCallback\n");
|
| + if (pp_error_or_bytes < PP_OK) {
|
| + ReportFailure("UrlLoadRequest::ReadResponseBodyCallback: ",
|
| + pp_error_or_bytes);
|
| + } else if (pp_error_or_bytes == PP_OK) { // Reached EOF.
|
| + ReportSuccess();
|
| + } else { // Partial read, so copy out the buffer and continue reading.
|
| + for (int32_t i = 0; i < pp_error_or_bytes; i++)
|
| + url_body_.push_back(buffer_[i]);
|
| + ReadResponseBody();
|
| + }
|
| +}
|
| +
|
| +void UrlLoadRequest::ReadFileBodyCallback(int32_t pp_error_or_bytes) {
|
| + printf("--- UrlLoadRequest::ReadFileBodyCallback\n");
|
| + if (pp_error_or_bytes < PP_OK) {
|
| + ReportFailure("UrlLoadRequest::ReadFileBodyCallback: ",
|
| + pp_error_or_bytes);
|
| + } else if (pp_error_or_bytes == PP_OK) { // Reached EOF.
|
| + ReportSuccess();
|
| + } else { // Partial read, so copy out the buffer and continue reading.
|
| + for (int32_t i = 0; i < pp_error_or_bytes; i++)
|
| + url_body_.push_back(buffer_[i]);
|
| + read_offset_ += pp_error_or_bytes;
|
| + ReadFileBody();
|
| + }
|
| +}
|
| +
|
| +void UrlLoadRequest::OpenFileBodyCallback(int32_t pp_error) {
|
| + printf("--- UrlLoadRequest::OpenFileBodyCallback\n");
|
| + if (pp_error != PP_OK) {
|
| + ReportFailure("UrlLoadRequest::OpenFileBodyCallback: ", pp_error);
|
| + return;
|
| + }
|
| + ReadFileBody();
|
| +}
|
|
|