| Index: native_client_sdk/src/tests/nacl_io_test/fake_ppapi/fake_pepper_interface_googledrivefs.cc
|
| diff --git a/native_client_sdk/src/tests/nacl_io_test/fake_ppapi/fake_pepper_interface_googledrivefs.cc b/native_client_sdk/src/tests/nacl_io_test/fake_ppapi/fake_pepper_interface_googledrivefs.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..b9e095b64f84203f359696f1dc1dab47232654aa
|
| --- /dev/null
|
| +++ b/native_client_sdk/src/tests/nacl_io_test/fake_ppapi/fake_pepper_interface_googledrivefs.cc
|
| @@ -0,0 +1,1032 @@
|
| +// Copyright 2016 The Chromium 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 "fake_ppapi/fake_pepper_interface_googledrivefs.h"
|
| +
|
| +#include <algorithm>
|
| +
|
| +#include <ppapi/c/pp_completion_callback.h>
|
| +#include <ppapi/c/pp_errors.h>
|
| +
|
| +#include "gtest/gtest.h"
|
| +
|
| +#include "nacl_io/osinttypes.h"
|
| +
|
| +#include "fake_ppapi/fake_core_interface.h"
|
| +#include "fake_ppapi/fake_file_io_interface.h"
|
| +#include "fake_ppapi/fake_pepper_interface_url_loader.h"
|
| +#include "fake_ppapi/fake_util.h"
|
| +#include "fake_ppapi/fake_var_interface.h"
|
| +
|
| +class FakeGoogleDriveInstanceResource : public FakeResource {
|
| + public:
|
| + FakeGoogleDriveInstanceResource() : server_template(NULL) {}
|
| + static const char* classname() { return "FakeGoogleDriveInstanceResource"; }
|
| +
|
| + FakeGoogleDriveServer* server_template;
|
| +};
|
| +
|
| +class FakeGoogleDriveURLLoaderResource : public FakeResource {
|
| + public:
|
| + FakeGoogleDriveURLLoaderResource() : server(NULL), response_pp_resource(0) {}
|
| +
|
| + virtual void Destroy() {
|
| + EXPECT_TRUE(manager != NULL);
|
| + if (response_pp_resource != 0) {
|
| + manager->Release(response_pp_resource);
|
| + }
|
| + }
|
| +
|
| + static const char* classname() { return "FakeGoogleDriveURLLoaderResource"; }
|
| +
|
| + FakeResourceManager* manager;
|
| + FakeGoogleDriveServer* server;
|
| + PP_Resource response_pp_resource;
|
| + std::string response_body;
|
| +};
|
| +
|
| +FakeGoogleDriveServer::FakeGoogleDriveServer() : token_id_(0), item_id_(0) {
|
| + FakeGoogleDriveItem item("root", "root_directory", "",
|
| + "2016-07-24T08:21:28.940Z", "no_parent_dir_id",
|
| + true);
|
| + item_map_["root"] = item;
|
| + vector_of_items_map_["root"] = std::vector<FakeGoogleDriveItem*>();
|
| +}
|
| +
|
| +void FakeGoogleDriveServer::AddBody(const std::string& data,
|
| + std::string* out_body) {
|
| + *out_body += data;
|
| + *out_body += "\n";
|
| +}
|
| +
|
| +int32_t FakeGoogleDriveServer::PauseValueStringFromUrlQuery(
|
| + const std::string& url,
|
| + const std::string& key,
|
| + std::string* out_value_string) {
|
| + out_value_string->clear();
|
| +
|
| + // Get filed from a url in the following format:
|
| + // https://../drive/v3/files/..?<key>=<value>
|
| + // https://../drive/v3/files/..?<key>=<value>&..
|
| + // https://../drive/v3/files/..?..&<key>=<value>
|
| +
|
| + std::string s_key_equal = key + "=";
|
| + int start_key_index = url.find(s_key_equal, 0);
|
| + if (start_key_index == std::string::npos) {
|
| + return PP_ERROR_FAILED;
|
| + }
|
| +
|
| + start_key_index += s_key_equal.size();
|
| +
|
| + int end_key_index = url.find("&", start_key_index);
|
| + if (end_key_index == std::string::npos) {
|
| + end_key_index = url.size();
|
| + }
|
| +
|
| + *out_value_string =
|
| + url.substr(start_key_index, end_key_index - start_key_index);
|
| +
|
| + return PP_OK;
|
| +}
|
| +
|
| +int32_t FakeGoogleDriveServer::PauseIdFromUrlPath(const std::string& url,
|
| + std::string* out_id) {
|
| + out_id->clear();
|
| +
|
| + // Get id from a url in the following format:
|
| + // https://../drive/v3/files/<id>?..
|
| +
|
| + int end_id_index = url.find("?", 0);
|
| + if (end_id_index == std::string::npos) {
|
| + return PP_ERROR_FAILED;
|
| + }
|
| +
|
| + const char* s_slash = "/";
|
| + int start_id_index = url.rfind(s_slash, end_id_index);
|
| + if (start_id_index == std::string::npos) {
|
| + return PP_ERROR_FAILED;
|
| + }
|
| + start_id_index += strlen(s_slash);
|
| +
|
| + *out_id = url.substr(start_id_index, end_id_index - start_id_index);
|
| +
|
| + return PP_OK;
|
| +}
|
| +
|
| +int32_t FakeGoogleDriveServer::PauseParentDirIdFromUrlQuery(
|
| + const std::string& url,
|
| + std::string* out_parent_dir_id) {
|
| + out_parent_dir_id->clear();
|
| +
|
| + // Get id from the following url format:
|
| + // https://../drive/v3/files?q=%27<id>%27+in+parents
|
| +
|
| + int end_id_index = url.find("%27+in+parents", 0);
|
| + if (end_id_index == std::string::npos) {
|
| + return PP_ERROR_FAILED;
|
| + }
|
| +
|
| + const char* s_quote = "%27";
|
| + int start_id_index = url.rfind(s_quote, end_id_index - 1);
|
| + if (start_id_index == std::string::npos) {
|
| + return PP_ERROR_FAILED;
|
| + }
|
| +
|
| + start_id_index += strlen(s_quote);
|
| +
|
| + *out_parent_dir_id =
|
| + url.substr(start_id_index, end_id_index - start_id_index);
|
| +
|
| + return PP_OK;
|
| +}
|
| +
|
| +int32_t FakeGoogleDriveServer::PauseNameFromUrlQuery(const std::string& url,
|
| + std::string* out_name) {
|
| + out_name->clear();
|
| +
|
| + // Get name from the following url format:
|
| + // https://../drive/v3/files?q=..name+=+%27<name>%27..
|
| +
|
| + const char* s_name_equal_quote = "name+=+%27";
|
| + int start_name_index = url.find(s_name_equal_quote, 0);
|
| + if (start_name_index == std::string::npos) {
|
| + return PP_ERROR_FAILED;
|
| + }
|
| +
|
| + start_name_index += strlen(s_name_equal_quote);
|
| +
|
| + int end_name_index = url.find("%27", start_name_index);
|
| + if (end_name_index == std::string::npos) {
|
| + return PP_ERROR_FAILED;
|
| + }
|
| +
|
| + *out_name = url.substr(start_name_index, end_name_index - start_name_index);
|
| +
|
| + return PP_OK;
|
| +}
|
| +
|
| +int32_t FakeGoogleDriveServer::PauseNameFromBody(const std::string& body,
|
| + std::string* out_name) {
|
| + out_name->clear();
|
| +
|
| + // Get name from the following body format:
|
| + // {
|
| + // ..
|
| + // "name": "<name>",
|
| + // ..
|
| + // }
|
| +
|
| + const char* s_name_quote_colon_quote = "name\": \"";
|
| + int start_name_index = body.find(s_name_quote_colon_quote, 0);
|
| + if (start_name_index == std::string::npos) {
|
| + return PP_ERROR_FAILED;
|
| + }
|
| +
|
| + start_name_index += strlen(s_name_quote_colon_quote);
|
| +
|
| + int end_name_index = body.find("\"", start_name_index);
|
| + if (end_name_index == std::string::npos) {
|
| + return PP_ERROR_FAILED;
|
| + }
|
| +
|
| + *out_name = body.substr(start_name_index, end_name_index - start_name_index);
|
| +
|
| + return PP_OK;
|
| +}
|
| +
|
| +int32_t FakeGoogleDriveServer::PauseParentDirIdFromBody(
|
| + const std::string& body,
|
| + std::string* out_parent_dir_id) {
|
| + out_parent_dir_id->clear();
|
| +
|
| + // Get id from the following body format:
|
| + // {
|
| + // ..
|
| + // "parents": [
|
| + // "<id>"
|
| + // ]
|
| + // ..
|
| + // }
|
| +
|
| + const char* s_parents_quote = "parents\"";
|
| +
|
| + int end_parent_key_index = body.find(s_parents_quote, 0);
|
| + if (end_parent_key_index == std::string::npos) {
|
| + return PP_ERROR_FAILED;
|
| + }
|
| + end_parent_key_index += strlen(s_parents_quote);
|
| +
|
| + const char* s_quote = "\"";
|
| + int start_parent_dir_id_index = body.find(s_quote, end_parent_key_index);
|
| + if (start_parent_dir_id_index == std::string::npos) {
|
| + return PP_ERROR_FAILED;
|
| + }
|
| + start_parent_dir_id_index += strlen(s_quote);
|
| +
|
| + int end_parent_dir_id_index = body.find(s_quote, start_parent_dir_id_index);
|
| + if (end_parent_dir_id_index == std::string::npos) {
|
| + return PP_ERROR_FAILED;
|
| + }
|
| +
|
| + *out_parent_dir_id =
|
| + body.substr(start_parent_dir_id_index,
|
| + end_parent_dir_id_index - start_parent_dir_id_index);
|
| +
|
| + return PP_OK;
|
| +}
|
| +
|
| +void FakeGoogleDriveServer::MakeDriveFileListResponse(
|
| + const std::vector<FakeGoogleDriveItem*>& dirents,
|
| + size_t start_index,
|
| + size_t end_index,
|
| + const std::string& optional_next_page_token,
|
| + std::string* out_body) {
|
| + AddBody("{", out_body);
|
| +
|
| + if (start_index == end_index) {
|
| + AddBody(" \"files\": [],", out_body);
|
| + } else {
|
| + if (!optional_next_page_token.empty()) {
|
| + AddBody(" \"nextPageToken\": \"" + optional_next_page_token + "\",",
|
| + out_body);
|
| + }
|
| +
|
| + AddBody(" \"files\": [", out_body);
|
| +
|
| + for (size_t i = start_index; i < end_index; ++i) {
|
| + AddBody(" {", out_body);
|
| +
|
| + std::string mime_type = (dirents[i]->is_dir())
|
| + ? folder_mime_type()
|
| + : "file mime type";
|
| + AddBody(" \"mimeType\": \"" + mime_type + "\",", out_body);
|
| +
|
| + AddBody(" \"kind\": \"drive#file\",", out_body);
|
| + AddBody(" \"id\": \"" + dirents[i]->id() + "\",", out_body);
|
| + AddBody(" \"name\": \"" + dirents[i]->name() + "\"", out_body);
|
| +
|
| + std::string closing_bracket = (i == end_index - 1) ? " }" : " },";
|
| + AddBody(closing_bracket, out_body);
|
| + }
|
| +
|
| + AddBody(" ],", out_body);
|
| + }
|
| +
|
| + AddBody(" \"kind\": \"drive#fileList\"", out_body);
|
| + AddBody("}", out_body);
|
| +}
|
| +
|
| +int32_t FakeGoogleDriveServer::GetItemField(const FakeGoogleDriveItem& item,
|
| + const std::string& field,
|
| + std::string* out_value) {
|
| + out_value->clear();
|
| +
|
| + if (field == "modifiedTime") {
|
| + *out_value = item.modified_time();
|
| +
|
| + return PP_OK;
|
| + } else if (field == "size") {
|
| + char buffer[33];
|
| + int char_written =
|
| + snprintf(buffer, sizeof(buffer), "%u", item.contents().size());
|
| + if (char_written < 0 || char_written >= (signed int)sizeof(buffer)) {
|
| + return PP_ERROR_FAILED;
|
| + }
|
| + *out_value = buffer;
|
| +
|
| + return PP_OK;
|
| + }
|
| +
|
| + return PP_ERROR_FAILED;
|
| +}
|
| +
|
| +FakeGoogleDriveServerResponse FakeGoogleDriveServer::RespondItemFieldValue(
|
| + const std::string url) {
|
| + // url string:
|
| + // https://www.googleapis.com/drive/v3/files/<itemid>?fields=<field>
|
| +
|
| + FakeGoogleDriveServerResponse response;
|
| +
|
| + std::string id;
|
| + int32_t result = PauseIdFromUrlPath(url, &id);
|
| + if (result != PP_OK) {
|
| + response.status_code = STATUSCODE_INTERNAL_SERVER_ERROR;
|
| +
|
| + return response;
|
| + }
|
| +
|
| + if (item_map_.find(id) == item_map_.end()) {
|
| + response.status_code = STATUSCODE_NOT_FOUND;
|
| +
|
| + return response;
|
| + }
|
| +
|
| + std::string field;
|
| + result = PauseValueStringFromUrlQuery(url, "fields", &field);
|
| + if (result != PP_OK) {
|
| + response.status_code = STATUSCODE_INTERNAL_SERVER_ERROR;
|
| +
|
| + return response;
|
| + }
|
| +
|
| + std::string field_value;
|
| + result = GetItemField(item_map_[id], field, &field_value);
|
| + if (result != PP_OK) {
|
| + response.status_code = STATUSCODE_INTERNAL_SERVER_ERROR;
|
| +
|
| + return response;
|
| + }
|
| +
|
| + response.status_code = STATUSCODE_OK;
|
| +
|
| + AddBody("{", &response.body);
|
| + AddBody(" \"" + field + "\": \"" + field_value + "\"", &response.body);
|
| + AddBody("}", &response.body);
|
| +
|
| + return response;
|
| +}
|
| +
|
| +FakeGoogleDriveServerResponse FakeGoogleDriveServer::RespondItemId(
|
| + const std::string& url) {
|
| + // url string:
|
| + // https://www.googleapis.com/drive/v3/files
|
| + // ?q=%27<itemid>%27+in+parents+and+name+=+%27<name>%27
|
| +
|
| + FakeGoogleDriveServerResponse response;
|
| +
|
| + std::string parent_dir_id;
|
| + int32_t result = PauseParentDirIdFromUrlQuery(url, &parent_dir_id);
|
| + if (result != PP_OK) {
|
| + response.status_code = STATUSCODE_INTERNAL_SERVER_ERROR;
|
| +
|
| + return response;
|
| + }
|
| +
|
| + if (vector_of_items_map_.find(parent_dir_id) == vector_of_items_map_.end()) {
|
| + response.status_code = STATUSCODE_NOT_FOUND;
|
| +
|
| + return response;
|
| + }
|
| +
|
| + std::string name;
|
| + result = PauseNameFromUrlQuery(url, &name);
|
| + if (result != PP_OK) {
|
| + response.status_code = STATUSCODE_INTERNAL_SERVER_ERROR;
|
| +
|
| + return response;
|
| + }
|
| +
|
| + for (size_t i = 0; i < vector_of_items_map_[parent_dir_id].size(); ++i) {
|
| + if (vector_of_items_map_[parent_dir_id][i]->name() == name) {
|
| + response.status_code = STATUSCODE_OK;
|
| +
|
| + MakeDriveFileListResponse(vector_of_items_map_[parent_dir_id], i, i + 1,
|
| + "", &response.body);
|
| +
|
| + return response;
|
| + }
|
| + }
|
| +
|
| + response.status_code = STATUSCODE_OK;
|
| +
|
| + MakeDriveFileListResponse(vector_of_items_map_[parent_dir_id], 0, 0, "",
|
| + &response.body);
|
| +
|
| + return response;
|
| +}
|
| +
|
| +int32_t FakeGoogleDriveServer::GenerateItemId(std::string* out_item_id) {
|
| + out_item_id->clear();
|
| +
|
| + char buffer[33];
|
| + int char_written = snprintf(buffer, sizeof(buffer), "%i", item_id_);
|
| +
|
| + if (char_written < 0 || char_written >= (signed int)sizeof(buffer)) {
|
| + return PP_ERROR_FAILED;
|
| + }
|
| + *out_item_id = buffer;
|
| +
|
| + item_id_++;
|
| +
|
| + return PP_OK;
|
| +}
|
| +
|
| +int32_t FakeGoogleDriveServer::ProduceNextPageToken(
|
| + const std::string& parent_dir_id,
|
| + size_t cur_index,
|
| + std::string* out_next_page_token) {
|
| + out_next_page_token->clear();
|
| +
|
| + char buffer[33];
|
| + int char_written = snprintf(buffer, sizeof(buffer), "%i", token_id_);
|
| +
|
| + if (char_written < 0 || char_written >= (signed int)sizeof(buffer)) {
|
| + return PP_ERROR_FAILED;
|
| + }
|
| + *out_next_page_token = buffer;
|
| + token_id_++;
|
| +
|
| + dirent_map_[*out_next_page_token] =
|
| + FakeGoogleDriveDirent(parent_dir_id, cur_index + files_per_page());
|
| +
|
| + return PP_OK;
|
| +}
|
| +
|
| +FakeGoogleDriveServerResponse FakeGoogleDriveServer::RespondDirent(
|
| + const std::string& url) {
|
| + // url string:
|
| + // https://www.googleapis.com/drive/v3/files
|
| + // ?q=%27<itemid>%27+in+parents
|
| + FakeGoogleDriveServerResponse response;
|
| +
|
| + std::string parent_dir_id;
|
| + int32_t result = PauseParentDirIdFromUrlQuery(url, &parent_dir_id);
|
| + if (result != PP_OK) {
|
| + response.status_code = STATUSCODE_INTERNAL_SERVER_ERROR;
|
| +
|
| + return response;
|
| + }
|
| +
|
| + if (vector_of_items_map_.find(parent_dir_id) == vector_of_items_map_.end()) {
|
| + response.status_code = STATUSCODE_NOT_FOUND;
|
| +
|
| + return response;
|
| + }
|
| +
|
| + if (vector_of_items_map_[parent_dir_id].size() == 0) {
|
| + response.status_code = STATUSCODE_OK;
|
| +
|
| + MakeDriveFileListResponse(vector_of_items_map_[parent_dir_id], 0, 0, "",
|
| + &response.body);
|
| +
|
| + return response;
|
| + }
|
| +
|
| + response.status_code = STATUSCODE_OK;
|
| +
|
| + std::string next_page_token;
|
| + if (vector_of_items_map_[parent_dir_id].size() > files_per_page()) {
|
| + result = ProduceNextPageToken(parent_dir_id, 0, &next_page_token);
|
| + if (result != PP_OK) {
|
| + response.status_code = STATUSCODE_INTERNAL_SERVER_ERROR;
|
| +
|
| + return response;
|
| + }
|
| + }
|
| +
|
| + MakeDriveFileListResponse(
|
| + vector_of_items_map_[parent_dir_id], 0,
|
| + std::min(files_per_page(), vector_of_items_map_[parent_dir_id].size()),
|
| + next_page_token, &response.body);
|
| +
|
| + return response;
|
| +}
|
| +
|
| +FakeGoogleDriveServerResponse FakeGoogleDriveServer::RespondDirentNextPage(
|
| + const std::string& url) {
|
| + // url string:
|
| + // https://www.googleapis.com/drive/v3/files?pageToken=<pagetoken>&q=%27<id>%27+in+parents
|
| +
|
| + FakeGoogleDriveServerResponse response;
|
| +
|
| + std::string parent_dir_id;
|
| + int32_t result = PauseParentDirIdFromUrlQuery(url, &parent_dir_id);
|
| + if (result != PP_OK) {
|
| + response.status_code = STATUSCODE_INTERNAL_SERVER_ERROR;
|
| +
|
| + return response;
|
| + }
|
| + std::string page_token;
|
| + result = PauseValueStringFromUrlQuery(url, "pageToken", &page_token);
|
| + if (result != PP_OK) {
|
| + response.status_code = STATUSCODE_INTERNAL_SERVER_ERROR;
|
| +
|
| + return response;
|
| + }
|
| +
|
| + FakeGoogleDriveDirent entry = dirent_map_[page_token];
|
| +
|
| + if (entry.parent_dir_id() != parent_dir_id) {
|
| + // When <id> in <id>+in+parents is not equal to the id of the
|
| + // parent directory that the page token is related to, Google
|
| + // Drive API v3 returns a status code 200 but a list of files
|
| + // that does not make sense. Return the status code 500 for
|
| + // the error of returning a list of files that does not make
|
| + // sense.
|
| + response.status_code = STATUSCODE_INTERNAL_SERVER_ERROR;
|
| +
|
| + return response;
|
| + }
|
| +
|
| + response.status_code = STATUSCODE_OK;
|
| +
|
| + std::string next_page_token;
|
| + if (vector_of_items_map_[parent_dir_id].size() >
|
| + entry.index() + files_per_page()) {
|
| + result =
|
| + ProduceNextPageToken(parent_dir_id, entry.index(), &next_page_token);
|
| + if (result != PP_OK) {
|
| + response.status_code = STATUSCODE_INTERNAL_SERVER_ERROR;
|
| +
|
| + return response;
|
| + }
|
| + }
|
| +
|
| + MakeDriveFileListResponse(
|
| + vector_of_items_map_[parent_dir_id], entry.index(),
|
| + std::min(entry.index() + files_per_page(),
|
| + vector_of_items_map_[parent_dir_id].size()),
|
| + next_page_token, &response.body);
|
| +
|
| + return response;
|
| +}
|
| +
|
| +FakeGoogleDriveServerResponse FakeGoogleDriveServer::RespondFileWriteRequest(
|
| + const std::string& url,
|
| + const std::string& body) {
|
| + // url string:
|
| + // https://www.googleapis.com/upload/drive/v3/files/<itemid>?uploadType=media
|
| +
|
| + FakeGoogleDriveServerResponse response;
|
| +
|
| + std::string id;
|
| + int32_t result = PauseIdFromUrlPath(url, &id);
|
| + if (result != PP_OK) {
|
| + response.status_code = STATUSCODE_INTERNAL_SERVER_ERROR;
|
| +
|
| + return response;
|
| + }
|
| +
|
| + if (item_map_.find(id) == item_map_.end()) {
|
| + response.status_code = STATUSCODE_NOT_FOUND;
|
| +
|
| + return response;
|
| + }
|
| +
|
| + response.status_code = STATUSCODE_OK;
|
| +
|
| + item_map_[id].set_contents(body);
|
| +
|
| + return response;
|
| +}
|
| +
|
| +FakeGoogleDriveServerResponse FakeGoogleDriveServer::RespondFileCreationRequest(
|
| + const std::string& url,
|
| + const std::string& body) {
|
| + // url string:
|
| + // https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart
|
| +
|
| + // body string:
|
| + // --foo_bar_baz
|
| + // Content-Type: application/json; charset=UTF-8
|
| + //
|
| + // {
|
| + // "name": "<itemname>",
|
| + // "parents": [
|
| + // "<parentdirid>"
|
| + // ]
|
| + // }
|
| + //
|
| + // --foo_bar_baz
|
| + // Content-Type: text/plain
|
| + //
|
| + //
|
| + // --foo_bar_baz--
|
| + FakeGoogleDriveServerResponse response;
|
| +
|
| + std::string name;
|
| + int32_t result = PauseNameFromBody(body, &name);
|
| + if (result != PP_OK) {
|
| + response.status_code = STATUSCODE_INTERNAL_SERVER_ERROR;
|
| +
|
| + return response;
|
| + }
|
| +
|
| + std::string parent_dir_id;
|
| + result = PauseParentDirIdFromBody(body, &parent_dir_id);
|
| + if (result != PP_OK) {
|
| + response.status_code = STATUSCODE_INTERNAL_SERVER_ERROR;
|
| +
|
| + return response;
|
| + }
|
| +
|
| + if (vector_of_items_map_.find(parent_dir_id) == vector_of_items_map_.end()) {
|
| + response.status_code = STATUSCODE_NOT_FOUND;
|
| +
|
| + return response;
|
| + }
|
| +
|
| + std::string file_id;
|
| + result = GenerateItemId(&file_id);
|
| + if (result != PP_OK) {
|
| + response.status_code = STATUSCODE_INTERNAL_SERVER_ERROR;
|
| +
|
| + return response;
|
| + }
|
| +
|
| + response.status_code = STATUSCODE_OK;
|
| +
|
| + FakeGoogleDriveItem item(file_id, name, "", "2016-07-24T08:21:28.940Z",
|
| + parent_dir_id, false);
|
| +
|
| + item_map_[file_id] = item;
|
| + vector_of_items_map_[parent_dir_id].push_back(&item_map_[file_id]);
|
| +
|
| + return response;
|
| +}
|
| +
|
| +FakeGoogleDriveServerResponse FakeGoogleDriveServer::RespondFileReadRequest(
|
| + const std::string& url,
|
| + const std::string& headers) {
|
| + // url string:
|
| + // https://www.googleapis.com/download/drive/v3/files/<itemid>?alt=media
|
| + FakeGoogleDriveServerResponse response;
|
| +
|
| + std::string id;
|
| + int32_t result = PauseIdFromUrlPath(url, &id);
|
| + if (result != PP_OK) {
|
| + response.status_code = STATUSCODE_INTERNAL_SERVER_ERROR;
|
| +
|
| + return response;
|
| + }
|
| +
|
| + if (item_map_.find(id) == item_map_.end()) {
|
| + response.status_code = STATUSCODE_INTERNAL_SERVER_ERROR;
|
| +
|
| + return response;
|
| + }
|
| +
|
| + std::string range;
|
| + if (!GetHeaderValue(headers, "Range", &range)) {
|
| + response.status_code = STATUSCODE_OK;
|
| +
|
| + response.body = item_map_[id].contents();
|
| +
|
| + return response;
|
| + }
|
| +
|
| + // We don't support all range requests, just bytes=<num>-<num>
|
| + // Google Drive files have the max size of uint32_t when the files
|
| + // are written from nacl_io, so lo and hi are in uint32_t.
|
| + uint32_t lo;
|
| + uint32_t hi;
|
| + if (sscanf(range.c_str(), "bytes=%u-%u", &lo, &hi) != 2) {
|
| + // Couldn't parse the range value.
|
| + response.status_code = STATUSCODE_INTERNAL_SERVER_ERROR;
|
| +
|
| + return response;
|
| + }
|
| +
|
| + size_t content_length = item_map_[id].contents().size();
|
| + if (lo >= content_length) {
|
| + // Trying to start reading past the end of the file contents is
|
| + // unsatisfiable.
|
| + response.status_code =
|
| + STATUSCODE_REQUESTED_RANGE_NOT_SATISFIABLE; // Request range not
|
| + // satisfiable.
|
| +
|
| + return response;
|
| + }
|
| +
|
| + // Clamp the hi value to the content length.
|
| + if (hi >= content_length) {
|
| + hi = content_length - 1;
|
| + }
|
| +
|
| + if (lo > hi) {
|
| + response.status_code = STATUSCODE_OK;
|
| +
|
| + response.body = item_map_[id].contents();
|
| +
|
| + return response;
|
| + }
|
| +
|
| + response.status_code = STATUSCODE_PARTIAL_CONTENT;
|
| +
|
| + response.body = item_map_[id].contents().substr(lo, hi - lo + 1);
|
| +
|
| + return response;
|
| +}
|
| +
|
| +FakeGoogleDriveServerResponse FakeGoogleDriveServer::RespondRemoveDirRequest(
|
| + const std::string& url) {
|
| + // url string:
|
| + // https://www.googleapis.com/drive/v3/files/<dirid>
|
| + FakeGoogleDriveServerResponse response;
|
| +
|
| + int start_id_index = url.rfind("/", url.size() - 1);
|
| + if (start_id_index == std::string::npos) {
|
| + response.status_code = STATUSCODE_INTERNAL_SERVER_ERROR;
|
| +
|
| + return response;
|
| + }
|
| +
|
| + start_id_index += strlen("/");
|
| + std::string id = url.substr(start_id_index, url.size() - start_id_index);
|
| +
|
| + VectorOfItemsMap::const_iterator map_iter = vector_of_items_map_.find(id);
|
| +
|
| + if (map_iter == vector_of_items_map_.end()) {
|
| + response.status_code = STATUSCODE_NOT_FOUND;
|
| +
|
| + return response;
|
| + }
|
| +
|
| + if (vector_of_items_map_[id].size() > 0) {
|
| + // Posix rmdir(3) is supposed to remove a directory when the directory is
|
| + // empty. Return a client error when the client requests to remove a
|
| + // directory that has items.
|
| + response.status_code = STATUSCODE_BAD_REQUEST;
|
| +
|
| + return response;
|
| + }
|
| + ItemMap::const_iterator item_map_iter = item_map_.find(id);
|
| +
|
| + for (std::vector<FakeGoogleDriveItem*>::const_iterator it =
|
| + vector_of_items_map_[item_map_iter->second.parent_dir_id()].begin();
|
| + it != vector_of_items_map_[item_map_iter->second.parent_dir_id()].end();
|
| + ++it) {
|
| + if ((*it)->id() == id) {
|
| + vector_of_items_map_[item_map_iter->second.parent_dir_id()].erase(it);
|
| + break;
|
| + }
|
| + }
|
| +
|
| + vector_of_items_map_.erase(map_iter);
|
| +
|
| + // id in vector_of_items_map_ also is in item_map_.
|
| + // Do not check to see if iterator == item_map_.end().
|
| + item_map_.erase(item_map_.find(id));
|
| +
|
| + response.status_code = STATUSCODE_NO_CONTENT;
|
| +
|
| + return response;
|
| +}
|
| +
|
| +FakeGoogleDriveServerResponse FakeGoogleDriveServer::RespondMakeDirRequest(
|
| + const std::string& url,
|
| + const std::string& body) {
|
| + // url string:
|
| + // https://www.googleapis.com/drive/v3/files
|
| +
|
| + // body string:
|
| + // {
|
| + // "name": "<dirname>",
|
| + // "mimeType": "application/vnd.google-apps.folder"
|
| + // "parents": [
|
| + // "<parentdirid>"
|
| + // ]
|
| + // }
|
| + FakeGoogleDriveServerResponse response;
|
| +
|
| + std::string name;
|
| + int32_t result = PauseNameFromBody(body, &name);
|
| + if (result != PP_OK) {
|
| + response.status_code = STATUSCODE_INTERNAL_SERVER_ERROR;
|
| +
|
| + return response;
|
| + }
|
| +
|
| + std::string parent_dir_id;
|
| + result = PauseParentDirIdFromBody(body, &parent_dir_id);
|
| + if (result != PP_OK) {
|
| + response.status_code = STATUSCODE_INTERNAL_SERVER_ERROR;
|
| +
|
| + return response;
|
| + }
|
| +
|
| + if (vector_of_items_map_.find(parent_dir_id) == vector_of_items_map_.end()) {
|
| + response.status_code = STATUSCODE_UNAUTHORIZED;
|
| +
|
| + return response;
|
| + }
|
| +
|
| + std::string dir_id;
|
| + result = GenerateItemId(&dir_id);
|
| + if (result != PP_OK) {
|
| + response.status_code = STATUSCODE_INTERNAL_SERVER_ERROR;
|
| +
|
| + return response;
|
| + }
|
| +
|
| + response.status_code = STATUSCODE_OK;
|
| +
|
| + FakeGoogleDriveItem item(dir_id, name, "", "2016-07-24T08:21:28.940Z",
|
| + parent_dir_id, true);
|
| +
|
| + item_map_[dir_id] = item;
|
| + vector_of_items_map_[dir_id] = std::vector<FakeGoogleDriveItem*>();
|
| + vector_of_items_map_[parent_dir_id].push_back(&item_map_[dir_id]);
|
| +
|
| + return response;
|
| +}
|
| +
|
| +FakeGoogleDriveServerResponse FakeGoogleDriveServer::Respond(
|
| + const std::string& url,
|
| + const std::string& headers,
|
| + const std::string& method,
|
| + const std::string& body) {
|
| + if (url.find("fields=", 0) != std::string::npos) {
|
| + return RespondItemFieldValue(url);
|
| + } else if (url.find("name", 0) != std::string::npos &&
|
| + url.find("+in+parents", 0) != std::string::npos) {
|
| + return RespondItemId(url);
|
| + } else if (url.find("pageToken", 0) != std::string::npos &&
|
| + url.find("+in+parents", 0) != std::string::npos) {
|
| + return RespondDirentNextPage(url);
|
| + } else if (url.find("+in+parents", 0) != std::string::npos) {
|
| + return RespondDirent(url);
|
| + } else if (url.find("uploadType=media", 0) != std::string::npos) {
|
| + return RespondFileWriteRequest(url, body);
|
| + } else if (url.find("uploadType=multipart", 0) != std::string::npos) {
|
| + return RespondFileCreationRequest(url, body);
|
| + } else if (url.find("download/drive", 0) != std::string::npos) {
|
| + return RespondFileReadRequest(url, headers);
|
| + } else if (method == "DELETE") {
|
| + return RespondRemoveDirRequest(url);
|
| + } else if (body.find("\"name\"", 0) != std::string::npos &&
|
| + body.find("\"mimeType\": \"" + folder_mime_type() + "\"",
|
| + 0) != std::string::npos &&
|
| + body.find("\"parents\"", 0) != std::string::npos) {
|
| + return RespondMakeDirRequest(url, body);
|
| + }
|
| + FakeGoogleDriveServerResponse response;
|
| +
|
| + response.status_code = STATUSCODE_NOT_IMPLEMENTED;
|
| +
|
| + return response;
|
| +}
|
| +
|
| +FakeGoogleDriveURLLoaderInterface::FakeGoogleDriveURLLoaderInterface(
|
| + FakeCoreInterface* core_interface)
|
| + : FakeURLLoaderInterface(core_interface) {}
|
| +
|
| +PP_Resource FakeGoogleDriveURLLoaderInterface::Create(PP_Instance instance) {
|
| + FakeGoogleDriveInstanceResource* instance_resource =
|
| + core_interface_->resource_manager()->Get<FakeGoogleDriveInstanceResource>(
|
| + instance);
|
| + if (instance_resource == NULL)
|
| + return PP_ERROR_BADRESOURCE;
|
| +
|
| + FakeGoogleDriveURLLoaderResource* loader_resource =
|
| + new FakeGoogleDriveURLLoaderResource;
|
| + loader_resource->manager = core_interface_->resource_manager();
|
| + loader_resource->server = instance_resource->server_template;
|
| +
|
| + return CREATE_RESOURCE(core_interface_->resource_manager(),
|
| + FakeGoogleDriveURLLoaderResource, loader_resource);
|
| +}
|
| +
|
| +int32_t FakeGoogleDriveURLLoaderInterface::Open(
|
| + PP_Resource loader,
|
| + PP_Resource request,
|
| + PP_CompletionCallback callback) {
|
| + FakeGoogleDriveURLLoaderResource* loader_resource =
|
| + core_interface_->resource_manager()
|
| + ->Get<FakeGoogleDriveURLLoaderResource>(loader);
|
| +
|
| + if (loader_resource == NULL)
|
| + return PP_ERROR_BADRESOURCE;
|
| +
|
| + FakeURLRequestInfoResource* request_resource =
|
| + core_interface_->resource_manager()->Get<FakeURLRequestInfoResource>(
|
| + request);
|
| + if (request_resource == NULL)
|
| + return PP_ERROR_BADRESOURCE;
|
| +
|
| + // Create a response resource.
|
| + FakeURLResponseInfoResource* response_resource =
|
| + new FakeURLResponseInfoResource;
|
| + loader_resource->response_pp_resource =
|
| + CREATE_RESOURCE(core_interface_->resource_manager(),
|
| + FakeURLResponseInfoResource, response_resource);
|
| +
|
| + FakeGoogleDriveServerResponse response = loader_resource->server->Respond(
|
| + request_resource->url, request_resource->headers,
|
| + request_resource->method, request_resource->body);
|
| +
|
| + response_resource->status_code = response.status_code;
|
| + loader_resource->response_body = response.body;
|
| +
|
| + // Call the callback.
|
| + return RunCompletionCallback(&callback, PP_OK);
|
| +}
|
| +
|
| +PP_Resource FakeGoogleDriveURLLoaderInterface::GetResponseInfo(
|
| + PP_Resource loader) {
|
| + FakeGoogleDriveURLLoaderResource* loader_resource =
|
| + core_interface_->resource_manager()
|
| + ->Get<FakeGoogleDriveURLLoaderResource>(loader);
|
| + if (loader_resource == NULL)
|
| + return 0;
|
| +
|
| + // Returned resources have an implicit AddRef.
|
| + core_interface_->resource_manager()->AddRef(
|
| + loader_resource->response_pp_resource);
|
| + return loader_resource->response_pp_resource;
|
| +}
|
| +
|
| +int32_t FakeGoogleDriveURLLoaderInterface::FinishStreamingToFile(
|
| + PP_Resource loader,
|
| + PP_CompletionCallback callback) {
|
| + FakeGoogleDriveURLLoaderResource* loader_resource =
|
| + core_interface_->resource_manager()
|
| + ->Get<FakeGoogleDriveURLLoaderResource>(loader);
|
| + if (loader_resource == NULL)
|
| + return PP_ERROR_BADRESOURCE;
|
| +
|
| + FakeURLResponseInfoResource* response_pp_resource =
|
| + core_interface_->resource_manager()->Get<FakeURLResponseInfoResource>(
|
| + loader_resource->response_pp_resource);
|
| + if (response_pp_resource == NULL)
|
| + return PP_ERROR_BADRESOURCE;
|
| +
|
| + response_pp_resource->body = loader_resource->response_body;
|
| +
|
| + return response_pp_resource->body.size();
|
| +}
|
| +
|
| +void FakeGoogleDriveURLLoaderInterface::Close(PP_Resource loader) {
|
| + FakeGoogleDriveURLLoaderResource* loader_resource =
|
| + core_interface_->resource_manager()
|
| + ->Get<FakeGoogleDriveURLLoaderResource>(loader);
|
| + if (loader_resource == NULL)
|
| + return;
|
| +
|
| + core_interface_->resource_manager()->Release(
|
| + loader_resource->response_pp_resource);
|
| +
|
| + loader_resource->server = NULL;
|
| + loader_resource->response_pp_resource = 0;
|
| +}
|
| +
|
| +FakePepperInterfaceGoogleDriveFs::FakePepperInterfaceGoogleDriveFs()
|
| + : core_interface_(&resource_manager_),
|
| + var_interface_(&var_manager_),
|
| + file_io_interface_(&core_interface_),
|
| + file_ref_interface_(&core_interface_, &var_interface_),
|
| + google_drive_url_loader_interface_(&core_interface_),
|
| + url_request_info_interface_(&core_interface_, &var_interface_),
|
| + url_response_info_interface_(&core_interface_,
|
| + &var_interface_,
|
| + &file_ref_interface_) {
|
| + Init();
|
| +}
|
| +
|
| +void FakePepperInterfaceGoogleDriveFs::Init() {
|
| + FakeGoogleDriveInstanceResource* instance_resource =
|
| + new FakeGoogleDriveInstanceResource;
|
| + instance_resource->server_template = &google_drive_server_template_;
|
| +
|
| + instance_ =
|
| + CREATE_RESOURCE(core_interface_.resource_manager(),
|
| + FakeGoogleDriveInstanceResource, instance_resource);
|
| +}
|
| +
|
| +FakePepperInterfaceGoogleDriveFs::~FakePepperInterfaceGoogleDriveFs() {
|
| + core_interface_.ReleaseResource(instance_);
|
| +}
|
| +
|
| +nacl_io::CoreInterface* FakePepperInterfaceGoogleDriveFs::GetCoreInterface() {
|
| + return &core_interface_;
|
| +}
|
| +
|
| +nacl_io::FileRefInterface*
|
| +FakePepperInterfaceGoogleDriveFs::GetFileRefInterface() {
|
| + return &file_ref_interface_;
|
| +}
|
| +
|
| +nacl_io::FileIoInterface*
|
| +FakePepperInterfaceGoogleDriveFs::GetFileIoInterface() {
|
| + return &file_io_interface_;
|
| +}
|
| +
|
| +nacl_io::URLLoaderInterface*
|
| +FakePepperInterfaceGoogleDriveFs::GetURLLoaderInterface() {
|
| + return &google_drive_url_loader_interface_;
|
| +}
|
| +
|
| +nacl_io::URLRequestInfoInterface*
|
| +FakePepperInterfaceGoogleDriveFs::GetURLRequestInfoInterface() {
|
| + return &url_request_info_interface_;
|
| +}
|
| +
|
| +nacl_io::URLResponseInfoInterface*
|
| +FakePepperInterfaceGoogleDriveFs::GetURLResponseInfoInterface() {
|
| + return &url_response_info_interface_;
|
| +}
|
| +
|
| +nacl_io::VarInterface* FakePepperInterfaceGoogleDriveFs::GetVarInterface() {
|
| + return &var_interface_;
|
| +}
|
| +
|
| +// static
|
| +size_t FakeGoogleDriveServer::files_per_page() {
|
| + return 100;
|
| +}
|
| +
|
| +// static
|
| +std::string FakeGoogleDriveServer::folder_mime_type() {
|
| + return "application/vnd.google-apps.folder";
|
| +}
|
|
|