Chromium Code Reviews| Index: native_client_sdk/src/libraries/nacl_io/googledrivefs/googledrivefs_node.cc |
| diff --git a/native_client_sdk/src/libraries/nacl_io/googledrivefs/googledrivefs_node.cc b/native_client_sdk/src/libraries/nacl_io/googledrivefs/googledrivefs_node.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..ea87e144b8ffc29132b37d1d13a4e8eeead7e649 |
| --- /dev/null |
| +++ b/native_client_sdk/src/libraries/nacl_io/googledrivefs/googledrivefs_node.cc |
| @@ -0,0 +1,751 @@ |
| +// 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 "nacl_io/googledrivefs/googledrivefs_node.h" |
| + |
| +#include <stdio.h> |
| +#include <time.h> |
| + |
| +#include <algorithm> |
| + |
| +#include "ppapi/c/pp_completion_callback.h" |
| + |
| +#include "nacl_io/error.h" |
| +#include "nacl_io/filesystem.h" |
| +#include "nacl_io/getdents_helper.h" |
| +#include "nacl_io/hash.h" |
| +#include "nacl_io/kernel_handle.h" |
| +#include "nacl_io/pepper_interface.h" |
| +#include "nacl_io/statuscode.h" |
| +#include "nacl_io/googledrivefs/googledrivefs.h" |
| +#include "nacl_io/googledrivefs/googledrivefs_util.h" |
| + |
| +namespace nacl_io { |
| + |
| +GoogleDriveFsNode::GoogleDriveFsNode(Filesystem* filesystem, Path path) |
| + : Node(filesystem), path_(path) {} |
| + |
| +Error GoogleDriveFsNode::GetDents(size_t offs, |
| + struct dirent* pdir, |
| + size_t size, |
| + int* out_bytes) { |
| + *out_bytes = 0; |
| + |
| + if (!IsaDir()) { |
| + return ENOTDIR; |
| + } |
| + |
| + const ino_t kCurDirIno = -1; |
| + const ino_t kParentDirIno = -2; |
| + GetDentsHelper helper(kCurDirIno, kParentDirIno); |
| + |
| + std::vector<std::string> dirent_names; |
| + Error error = RequestDirent(&dirent_names); |
| + if (error) { |
| + return error; |
| + } |
| + |
| + for (size_t i = 0; i < dirent_names.size(); ++i) { |
| + Path child_path(path_); |
| + child_path = child_path.Append("/" + dirent_names[i]); |
| + ino_t child_ino = HashPath(child_path); |
| + |
| + helper.AddDirent(child_ino, dirent_names[i].c_str(), |
| + dirent_names[i].size()); |
| + } |
| + |
| + return helper.GetDents(offs, pdir, size, out_bytes); |
| +} |
| + |
| +Error GoogleDriveFsNode::GetStat(struct stat* pstat) { |
| + Error error = GetSize(&pstat->st_size); |
| + if (error) { |
| + return error; |
| + } |
| + |
| + error = GetModifiedTime(&pstat->st_mtime); |
| + if (error) { |
| + return error; |
| + } |
| + |
| + pstat->st_atime = 0; |
| + pstat->st_ctime = 0; |
| + |
| + pstat->st_mode = stat_.st_mode; |
| + |
| + return 0; |
| +} |
| + |
| +Error GoogleDriveFsNode::Write(const HandleAttr& attr, |
| + const void* buf, |
| + size_t count, |
| + int* out_bytes) { |
| + *out_bytes = 0; |
| + |
| + if (IsaDir()) { |
| + return EISDIR; |
| + } |
| + if ((GetMode() & S_IWRITE) == 0) { |
| + return EACCES; |
| + } |
| + |
| + off_t file_size = 0; |
| + Error error = GetSize(&file_size); |
| + if (error) { |
| + return error; |
| + } |
| + |
| + off_t file_buffer_size = std::max((unsigned long long int)file_size, |
|
binji
2016/08/22 19:21:53
use std::max<off_t> instead of casting the argumen
chanpatorikku
2016/08/29 17:14:03
Done. std::max< 'C++ variable type' > is used in v
|
| + (unsigned long long int)attr.offs + count); |
| + |
| + // use std::string for storing data in the heap, as the size of stack |
| + // is measured in megabytes, disallowing files larger than that. |
| + std::string file_buffer(file_buffer_size, '\0'); |
| + |
| + if (file_size > 0) { |
| + int read_helper_out_bytes = 0; |
| + error = ReadHelper(0, file_size - 1, &file_buffer, &read_helper_out_bytes); |
| + |
| + if (error) { |
| + return error; |
| + } |
| + } |
| + |
| + char* pChar = (char*)buf; |
| + for (size_t i = 0; i < count; ++i) { |
| + file_buffer[attr.offs + i] = pChar[i]; |
| + } |
| + |
| + error = WriteHelper(file_buffer.c_str(), file_buffer_size); |
|
binji
2016/08/22 19:21:53
Is there no better way than reading the entire fil
chanpatorikku
2016/08/29 17:14:03
No. Google Drive API v3 supports only file overwr
|
| + if (error) { |
| + return error; |
| + } |
| + |
| + *out_bytes = count; |
| + |
| + return 0; |
| +} |
| + |
| +Error GoogleDriveFsNode::FTruncate(off_t length) { |
| + if (IsaDir()) { |
| + return EISDIR; |
| + } |
| + |
| + off_t file_size = 0; |
| + Error error = GetSize(&file_size); |
| + if (error) { |
| + return error; |
| + } |
| + |
| + std::string file_buffer(length, '\0'); |
| + |
| + if (file_size > 0) { |
| + int read_helper_out_bytes = 0; |
| + off_t read_end = std::min(length, file_size); |
| + error = ReadHelper(0, read_end - 1, &file_buffer, &read_helper_out_bytes); |
| + |
| + if (error) { |
| + return error; |
| + } |
| + } |
| + |
| + error = WriteHelper(file_buffer.c_str(), length); |
| + if (error) { |
| + return error; |
| + } |
| + |
| + return 0; |
| +} |
| + |
| +Error GoogleDriveFsNode::Read(const HandleAttr& attr, |
| + void* buf, |
| + size_t count, |
| + int* out_bytes) { |
| + *out_bytes = 0; |
| + |
| + if (IsaDir()) { |
| + return EISDIR; |
| + } |
| + if ((GetMode() & S_IREAD) == 0) { |
| + return EACCES; |
| + } |
| + |
| + std::string file_buffer(count, '\0'); |
| + |
| + Error error = |
| + ReadHelper(attr.offs, attr.offs + count - 1, &file_buffer, out_bytes); |
| + if (error) { |
| + return error; |
| + } |
| + |
| + char* pChar = (char*)buf; |
| + for (size_t i = 0; i < count; ++i) { |
| + pChar[i] = file_buffer[i]; |
|
binji
2016/08/22 19:21:53
why not read directly into buf?
chanpatorikku
2016/08/29 17:14:03
buf has to be copied from a std::string object at
|
| + } |
| + |
| + return 0; |
| +} |
| + |
| +Error GoogleDriveFsNode::GetSize(off_t* out_size) { |
| + *out_size = 0; |
| + |
| + GoogleDriveFs* googledrivefs = static_cast<GoogleDriveFs*>(filesystem_); |
| + |
| + URLLoaderInterface* url_loader_iface = |
| + googledrivefs->ppapi()->GetURLLoaderInterface(); |
| + PP_Resource url_loader_object = |
| + url_loader_iface->Create(googledrivefs->instance()); |
| + URLRequestInfoInterface* url_request_info_iface = |
| + googledrivefs->ppapi()->GetURLRequestInfoInterface(); |
| + PP_Resource url_request_info_object = |
| + url_request_info_iface->Create(googledrivefs->instance()); |
| + PP_Resource url_response_info_object = 0; |
| + Error error(0); |
| + static const char base_url[] = "https://www.googleapis.com/drive/v3/files"; |
| + RequestUrlParams p; |
| + std::string output; |
| + std::string size_value; |
| + int size_index; |
| + |
| + if (IsaDir()) { |
| + goto done; |
| + } |
| + |
| + p.url = base_url; |
| + AddUrlPath(item_id_, &p.url); |
| + AddUrlFirstQueryParameter("fields", "size", &p.url); |
| + |
| + p.method = "GET"; |
| + |
| + p.headers = ""; |
| + |
| + AddHeaders("Content-type", "application/json", &p.headers); |
| + AddHeaders("Authorization", "Bearer " + googledrivefs->token(), &p.headers); |
| + |
| + error = MakeRequest(googledrivefs->ppapi(), url_loader_object, |
| + url_request_info_object, p); |
| + |
| + if (error) { |
| + goto done; |
| + } |
| + |
| + error = FinishPreparingResponse(googledrivefs->ppapi(), url_loader_object, |
| + &url_response_info_object); |
| + |
| + if (error) { |
| + goto done; |
| + } |
| + |
| + if (ReadStatusCode(googledrivefs->ppapi(), url_response_info_object) != |
| + STATUSCODE_OK) { |
| + error = EPERM; |
| + goto done; |
| + } |
| + |
| + error = ReadResponseBody(googledrivefs->ppapi(), googledrivefs->instance(), |
| + url_response_info_object, INT_MAX, &output); |
| + if (error) { |
| + goto done; |
| + } |
| + |
| + GetValue(output, "size", 0, &size_value, &size_index); |
| + if (size_index == -1) { |
| + // in a STATUSCODE_OK response, size of a directory is not written. |
| + size_value = "0"; |
| + } |
| + |
| + *out_size = (off_t)atoi(size_value.c_str()); |
| + |
| +done: |
| + if (url_loader_object) { |
| + googledrivefs->ppapi()->ReleaseResource(url_loader_object); |
| + } |
| + if (url_request_info_object) { |
| + googledrivefs->ppapi()->ReleaseResource(url_request_info_object); |
| + } |
| + if (url_response_info_object) { |
| + googledrivefs->ppapi()->ReleaseResource(url_response_info_object); |
| + } |
| + |
| + return error; |
| +} |
| + |
| +Error GoogleDriveFsNode::Init(int open_flags) { |
| + Error error = Node::Init(open_flags); |
| + |
| + if (error) { |
| + return error; |
| + } |
| + |
| + if (path_.Size() == 1) { |
| + parent_dir_id_ = ""; |
| + item_id_ = "root"; |
| + SetType(S_IFDIR); |
| + SetMode(S_IREAD); |
| + return 0; |
| + } |
| + |
| + error = RequestParentDirId(path_, filesystem_, &parent_dir_id_); |
| + if (error) { |
| + return error; |
| + } |
| + |
| + // Request the ID of an item, which is a file or a directory |
| + error = |
| + RequestItemId(parent_dir_id_, path_.Basename(), filesystem_, &item_id_); |
| + |
| + if (error == ENOENT) { |
| + // Only files are open as mode O_CREAT |
| + if ((open_flags & O_CREAT) != 0) { |
| + error = CreateEmptyFile(); |
| + if (error) { |
| + return error; |
| + } |
| + error = RequestItemId(parent_dir_id_, path_.Basename(), filesystem_, |
| + &item_id_); |
| + if (error) { |
| + return error; |
| + } |
| + SetType(S_IFREG); |
| + if ((open_flags & O_RDWR) != 0) { |
| + SetMode(S_IREAD | S_IWRITE); |
| + } else if ((open_flags & O_WRONLY) != 0) { |
| + SetMode(S_IWRITE); |
| + } else { |
| + SetMode(S_IREAD); |
| + } |
| + } else { |
| + return ENOENT; |
| + } |
| + } else if (error) { |
| + return error; |
| + } else { |
| + std::string dir_id = ""; |
| + error = |
| + RequestDirId(parent_dir_id_, path_.Basename(), filesystem_, &dir_id); |
| + if (error == ENOENT) { |
| + SetType(S_IFREG); |
| + if ((open_flags & O_RDWR) != 0) { |
| + SetMode(S_IREAD | S_IWRITE); |
| + } else if ((open_flags & O_WRONLY) != 0) { |
| + SetMode(S_IWRITE); |
| + } else { |
| + SetMode(S_IREAD); |
| + } |
| + } else if (error) { |
| + return error; |
| + } else { |
| + SetType(S_IFDIR); |
| + SetMode(S_IREAD); |
| + } |
| + |
| + if (open_flags == 0) { |
| + // open_flags == 0 for file opened on fopen with mode r and |
| + // directory opened on opendir |
| + return 0; |
| + } else if (IsaDir()) { |
| + return EPERM; |
| + } else if ((open_flags & O_TRUNC) != 0) { |
| + error = WriteHelper(NULL, 0); |
| + if (error) { |
| + return error; |
| + } |
| + } |
| + } |
| + |
| + return 0; |
| +} |
| + |
| +void GoogleDriveFsNode::Destroy() { |
| + Node::Destroy(); |
| +} |
| + |
| +Error GoogleDriveFsNode::ReadHelper(off_t start, |
| + off_t end, |
| + std::string* out_string_buffer, |
| + int* out_bytes) { |
| + (*out_string_buffer)[0] = '\0'; |
| + *out_bytes = 0; |
| + |
| + GoogleDriveFs* googledrivefs = static_cast<GoogleDriveFs*>(filesystem_); |
| + |
| + URLLoaderInterface* url_loader_iface = |
| + googledrivefs->ppapi()->GetURLLoaderInterface(); |
| + PP_Resource url_loader_object = |
| + url_loader_iface->Create(googledrivefs->instance()); |
| + URLRequestInfoInterface* url_request_info_iface = |
| + googledrivefs->ppapi()->GetURLRequestInfoInterface(); |
| + PP_Resource url_request_info_object = |
| + url_request_info_iface->Create(googledrivefs->instance()); |
| + PP_Resource url_response_info_object = 0; |
| + Error error(EPERM); |
| + static const char base_url[] = |
| + "https://www.googleapis.com/download/drive/v3/files"; |
| + RequestUrlParams p; |
| + char range_value_buffer[1024]; |
| + int char_written = 0; |
| + int status_code = 0; |
| + std::string output; |
| + |
| + p.url = base_url; |
| + AddUrlPath(item_id_, &p.url); |
| + AddUrlFirstQueryParameter("alt", "media", &p.url); |
| + |
| + p.method = "GET"; |
| + |
| + p.headers = ""; |
| + |
| + AddHeaders("Content-type", "application/json", &p.headers); |
| + AddHeaders("Authorization", "Bearer " + googledrivefs->token(), &p.headers); |
| + |
| + char_written = sprintf(range_value_buffer, "bytes=%lli-%lli", |
|
binji
2016/08/22 19:21:53
Use snprintf instead of sprintf
chanpatorikku
2016/08/29 17:14:03
Done.
|
| + (long long int)start, (long long int)end); |
| + if (char_written < 0) { |
| + error = EPERM; |
| + goto done; |
| + } |
| + |
| + AddHeaders("Range", std::string(range_value_buffer), &p.headers); |
|
binji
2016/08/22 19:21:53
Remove std::string constructor, it will be automat
chanpatorikku
2016/08/29 17:14:03
Done.
|
| + |
| + error = MakeRequest(googledrivefs->ppapi(), url_loader_object, |
| + url_request_info_object, p); |
| + |
| + if (error) { |
| + goto done; |
| + } |
| + |
| + error = FinishPreparingResponse(googledrivefs->ppapi(), url_loader_object, |
| + &url_response_info_object); |
| + |
| + if (error) { |
| + goto done; |
| + } |
| + |
| + status_code = |
| + ReadStatusCode(googledrivefs->ppapi(), url_response_info_object); |
| + |
| + if (status_code == STATUSCODE_OK || |
| + status_code == STATUSCODE_PARTIAL_CONTENT) { |
| + error = |
| + ReadResponseBody(googledrivefs->ppapi(), googledrivefs->instance(), |
| + url_response_info_object, end - start + 1, &output); |
| + |
| + if (error) { |
| + goto done; |
| + } |
| + |
| + for (size_t i = 0; i < output.size(); ++i) { |
| + (*out_string_buffer)[i] = output[i]; |
|
binji
2016/08/22 19:21:53
looks like you are assuming that out_string_buffer
chanpatorikku
2016/08/29 17:14:03
Not adding assert here, but adding assert in vario
|
| + } |
| + |
| + *out_bytes = output.size(); |
| + |
| + error = 0; |
| + goto done; |
| + } else if (status_code == STATUSCODE_REQUESTED_RANGE_NOT_SATISFIABLE) { |
| + error = 0; |
|
binji
2016/08/22 19:21:53
why isn't this an error?
chanpatorikku
2016/08/29 17:14:03
Google Drive API v3, HttpFs, and Html5Fs do not sh
|
| + goto done; |
| + } |
| + |
| +done: |
| + if (url_loader_object) { |
| + googledrivefs->ppapi()->ReleaseResource(url_loader_object); |
| + } |
| + if (url_request_info_object) { |
| + googledrivefs->ppapi()->ReleaseResource(url_request_info_object); |
| + } |
| + if (url_response_info_object) { |
| + googledrivefs->ppapi()->ReleaseResource(url_response_info_object); |
| + } |
| + |
| + return error; |
| +} |
| + |
| +Error GoogleDriveFsNode::WriteHelper(const char* body_data, |
| + uint32_t body_size) { |
| + GoogleDriveFs* googledrivefs = static_cast<GoogleDriveFs*>(filesystem_); |
| + |
| + URLLoaderInterface* url_loader_iface = |
| + googledrivefs->ppapi()->GetURLLoaderInterface(); |
| + PP_Resource url_loader_object = |
| + url_loader_iface->Create(googledrivefs->instance()); |
| + URLRequestInfoInterface* url_request_info_iface = |
| + googledrivefs->ppapi()->GetURLRequestInfoInterface(); |
| + PP_Resource url_request_info_object = |
| + url_request_info_iface->Create(googledrivefs->instance()); |
| + PP_Resource url_response_info_object = 0; |
| + Error error(0); |
| + static const char base_url[] = |
| + "https://www.googleapis.com/upload/drive/v3/files"; |
| + RequestUrlParams p; |
| + |
| + p.url = base_url; |
| + AddUrlPath(item_id_, &p.url); |
| + AddUrlFirstQueryParameter("uploadType", "media", &p.url); |
| + |
| + p.method = "PATCH"; |
| + |
| + p.headers = ""; |
| + |
| + AddHeaders("Content-type", "application/json", &p.headers); |
| + AddHeaders("Authorization", "Bearer " + googledrivefs->token(), &p.headers); |
| + |
| + p.body = std::string(body_data, body_size); |
| + |
| + error = MakeRequest(googledrivefs->ppapi(), url_loader_object, |
| + url_request_info_object, p); |
| + |
| + if (error) { |
| + goto done; |
| + } |
| + |
| + error = FinishPreparingResponse(googledrivefs->ppapi(), url_loader_object, |
| + &url_response_info_object); |
| + |
| + if (error) { |
| + goto done; |
| + } |
| + |
| + if (ReadStatusCode(googledrivefs->ppapi(), url_response_info_object) != |
| + STATUSCODE_OK) { |
| + error = EPERM; |
| + goto done; |
| + } |
| + |
| +done: |
| + if (url_loader_object) { |
| + googledrivefs->ppapi()->ReleaseResource(url_loader_object); |
| + } |
| + if (url_request_info_object) { |
| + googledrivefs->ppapi()->ReleaseResource(url_request_info_object); |
| + } |
| + if (url_response_info_object) { |
| + googledrivefs->ppapi()->ReleaseResource(url_response_info_object); |
| + } |
| + |
| + return error; |
| +} |
| + |
| +Error GoogleDriveFsNode::GetModifiedTime(time_t* out_mtime) { |
| + GoogleDriveFs* googledrivefs = static_cast<GoogleDriveFs*>(filesystem_); |
| + |
| + URLLoaderInterface* url_loader_iface = |
| + googledrivefs->ppapi()->GetURLLoaderInterface(); |
| + PP_Resource url_loader_object = |
| + url_loader_iface->Create(googledrivefs->instance()); |
| + URLRequestInfoInterface* url_request_info_iface = |
| + googledrivefs->ppapi()->GetURLRequestInfoInterface(); |
| + PP_Resource url_request_info_object = |
| + url_request_info_iface->Create(googledrivefs->instance()); |
| + PP_Resource url_response_info_object = 0; |
| + Error error(0); |
| + static const char base_url[] = "https://www.googleapis.com/drive/v3/files"; |
| + RequestUrlParams p; |
| + std::string output; |
| + std::string modified_time_value = ""; |
| + int modified_time_index = 0; |
| + struct tm timeinfo; |
| + |
| + p.url = base_url; |
| + AddUrlPath(item_id_, &p.url); |
| + AddUrlFirstQueryParameter("fields", "modifiedTime", &p.url); |
| + |
| + p.method = "GET"; |
| + |
| + p.headers = ""; |
| + |
| + AddHeaders("Content-type", "application/json", &p.headers); |
| + AddHeaders("Authorization", "Bearer " + googledrivefs->token(), &p.headers); |
| + |
| + error = MakeRequest(googledrivefs->ppapi(), url_loader_object, |
| + url_request_info_object, p); |
| + |
| + if (error) { |
| + goto done; |
| + } |
| + |
| + error = FinishPreparingResponse(googledrivefs->ppapi(), url_loader_object, |
| + &url_response_info_object); |
| + |
| + if (error) { |
| + goto done; |
| + } |
| + |
| + if (ReadStatusCode(googledrivefs->ppapi(), url_response_info_object) != |
| + STATUSCODE_OK) { |
| + error = EPERM; |
| + goto done; |
| + } |
| + |
| + error = ReadResponseBody(googledrivefs->ppapi(), googledrivefs->instance(), |
| + url_response_info_object, INT_MAX, &output); |
| + if (error) { |
| + goto done; |
| + } |
| + |
| + // the value of modifiedTime is assumed to be always in the STATUSCODE_OK |
| + // response. |
| + GetValue(output, "modifiedTime", 0, &modified_time_value, |
|
chanpatorikku
2016/08/07 02:41:03
I don't know about how practical my implementation
binji
2016/08/22 19:21:53
You may want to specify the expected format below,
chanpatorikku
2016/08/29 17:14:03
The comment becomes not applicable now.
GetValue(
|
| + &modified_time_index); |
| + |
| + timeinfo.tm_year = atoi(modified_time_value.substr(0, 4).c_str()); |
| + timeinfo.tm_mon = atoi(modified_time_value.substr(5, 2).c_str()); |
| + timeinfo.tm_mday = atoi(modified_time_value.substr(8, 2).c_str()); |
| + timeinfo.tm_hour = atoi(modified_time_value.substr(11, 2).c_str()); |
| + timeinfo.tm_min = atoi(modified_time_value.substr(14, 2).c_str()); |
| + timeinfo.tm_sec = atoi(modified_time_value.substr(17, 2).c_str()); |
| + timeinfo.tm_isdst = 0; |
| + |
| + *out_mtime = mktime(&timeinfo); |
| + |
| +done: |
| + if (url_loader_object) { |
| + googledrivefs->ppapi()->ReleaseResource(url_loader_object); |
| + } |
| + if (url_request_info_object) { |
| + googledrivefs->ppapi()->ReleaseResource(url_request_info_object); |
| + } |
| + if (url_response_info_object) { |
| + googledrivefs->ppapi()->ReleaseResource(url_response_info_object); |
| + } |
| + |
| + return error; |
| +} |
| + |
| +Error GoogleDriveFsNode::CreateEmptyFile() { |
| + GoogleDriveFs* googledrivefs = static_cast<GoogleDriveFs*>(filesystem_); |
| + |
| + URLLoaderInterface* url_loader_iface = |
| + googledrivefs->ppapi()->GetURLLoaderInterface(); |
| + PP_Resource url_loader_object = |
| + url_loader_iface->Create(googledrivefs->instance()); |
| + URLRequestInfoInterface* url_request_info_iface = |
| + googledrivefs->ppapi()->GetURLRequestInfoInterface(); |
| + PP_Resource url_request_info_object = |
| + url_request_info_iface->Create(googledrivefs->instance()); |
| + PP_Resource url_response_info_object = 0; |
| + Error error(0); |
| + static const char base_url[] = |
| + "https://www.googleapis.com/upload/drive/v3/files"; |
| + RequestUrlParams p; |
| + std::string BOUNDARY_VALUE = "foo_bar_baz"; |
| + |
| + p.url = base_url; |
| + AddUrlFirstQueryParameter("uploadType", "multipart", &p.url); |
| + |
| + p.method = "POST"; |
| + |
| + p.headers = ""; |
| + |
| + AddHeaders("Content-type", "multipart/related; boundary=" + BOUNDARY_VALUE, |
| + &p.headers); |
| + AddHeaders("Authorization", "Bearer " + googledrivefs->token(), &p.headers); |
| + |
| + p.body = ""; |
| + AddBody("--" + BOUNDARY_VALUE, &p.body); |
| + AddBody("Content-Type: application/json; charset=UTF-8", &p.body); |
| + AddBody("", &p.body); |
| + AddBody("{", &p.body); |
| + AddBody(std::string(" \"name\": \"") + path_.Basename() + std::string("\","), |
| + &p.body); |
| + AddBody(" \"parents\": [", &p.body); |
| + AddBody(" \"" + parent_dir_id_ + "\"", &p.body); |
| + AddBody(" ]", &p.body); |
| + AddBody("}", &p.body); |
| + AddBody("", &p.body); |
| + AddBody("--" + BOUNDARY_VALUE, &p.body); |
| + AddBody("Content-Type: text/plain", &p.body); |
| + AddBody("", &p.body); |
| + AddBody("", &p.body); |
| + AddBody("--" + BOUNDARY_VALUE + "--", &p.body); |
| + |
| + error = MakeRequest(googledrivefs->ppapi(), url_loader_object, |
| + url_request_info_object, p); |
| + |
| + if (error) { |
| + goto done; |
| + } |
| + |
| + error = FinishPreparingResponse(googledrivefs->ppapi(), url_loader_object, |
| + &url_response_info_object); |
| + |
| + if (error) { |
| + goto done; |
| + } |
| + |
| + if (ReadStatusCode(googledrivefs->ppapi(), url_response_info_object) != |
| + STATUSCODE_OK) { |
| + error = EPERM; |
| + goto done; |
| + } |
| + |
| +done: |
| + if (url_loader_object) { |
| + googledrivefs->ppapi()->ReleaseResource(url_loader_object); |
| + } |
| + if (url_request_info_object) { |
| + googledrivefs->ppapi()->ReleaseResource(url_request_info_object); |
| + } |
| + if (url_response_info_object) { |
| + googledrivefs->ppapi()->ReleaseResource(url_response_info_object); |
| + } |
| + |
| + return error; |
| +} |
| + |
| +Error GoogleDriveFsNode::RequestDirentHelper( |
| + const std::string& url, |
| + std::vector<std::string>* out_dirent_names) { |
| + std::string response_body; |
| + Error error = GetListFileResponseBody(url, filesystem_, &response_body); |
| + if (error) { |
| + return error; |
| + } |
| + |
| + std::string name_value = ""; |
| + int name_index = 0; |
| + |
| + GetValue(response_body, "name", name_index, &name_value, &name_index); |
| + |
| + while (name_index != -1) { |
| + out_dirent_names->push_back(name_value); |
| + |
| + GetValue(response_body, "name", name_index, &name_value, &name_index); |
| + } |
| + |
| + std::string next_page_token_value = ""; |
| + int next_page_token_index = 0; |
| + GetValue(response_body, "nextPageToken", 0, &next_page_token_value, |
| + &next_page_token_index); |
| + if (next_page_token_index != -1) { |
| + return RequestDirentWithNextPageToken(next_page_token_value, |
| + out_dirent_names); |
| + } |
| + |
| + return 0; |
| +} |
| + |
| +Error GoogleDriveFsNode::RequestDirentWithNextPageToken( |
| + const std::string& next_page_token, |
| + std::vector<std::string>* out_dirent_names) { |
| + static const char base_url[] = "https://www.googleapis.com/drive/v3/files"; |
| + |
| + std::string url = base_url; |
| + AddUrlFirstQueryParameter("pageToken", next_page_token, &url); |
| + AddUrlNextQueryParameter("q", "%27" + item_id_ + "%27+in+parents", &url); |
| + |
| + return RequestDirentHelper(url, out_dirent_names); |
| +} |
| + |
| +Error GoogleDriveFsNode::RequestDirent( |
| + std::vector<std::string>* out_dirent_names) { |
| + static const char base_url[] = "https://www.googleapis.com/drive/v3/files"; |
| + |
| + std::string url = base_url; |
| + AddUrlFirstQueryParameter("q", "%27" + item_id_ + "%27+in+parents", &url); |
|
binji
2016/08/22 19:21:53
this expression ("%27" + ...) is very common, prob
chanpatorikku
2016/08/29 17:14:03
Done.
|
| + |
| + return RequestDirentHelper(url, out_dirent_names); |
| +} |
| + |
| +} // namespace nacl_io |