Chromium Code Reviews| Index: native_client_sdk/src/libraries/nacl_io/googledrivefs/googledrivefs.cc |
| diff --git a/native_client_sdk/src/libraries/nacl_io/googledrivefs/googledrivefs.cc b/native_client_sdk/src/libraries/nacl_io/googledrivefs/googledrivefs.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..706c1b627aa38fd308d253a85631baab3ce3c29e |
| --- /dev/null |
| +++ b/native_client_sdk/src/libraries/nacl_io/googledrivefs/googledrivefs.cc |
| @@ -0,0 +1,292 @@ |
| +// 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.h" |
| + |
| +#include <map> |
| + |
| +#include "nacl_io/filesystem.h" |
| +#include "nacl_io/statuscode.h" |
| +#include "nacl_io/googledrivefs/googledrivefs_node.h" |
| +#include "nacl_io/googledrivefs/googledrivefs_util.h" |
| + |
| +namespace nacl_io { |
| + |
| +GoogleDriveFs::GoogleDriveFs() {} |
| + |
| +GoogleDriveFs::~GoogleDriveFs() {} |
| + |
| +Error GoogleDriveFs::Init(const FsInitArgs& args) { |
| + Error error = Filesystem::Init(args); |
| + if (error) { |
| + return error; |
| + } |
| + |
| + std::map<std::string, std::string>::const_iterator instance_it = |
| + args.string_map.find("instance"); |
| + |
| + if (instance_it == args.string_map.end()) { |
| + return EINVAL; |
| + } |
| + |
| + instance_ = atoi(instance_it->second.c_str()); |
|
binji
2016/08/22 19:21:52
you don't need to get this instance from the user,
chanpatorikku
2016/08/29 17:14:03
Done.
|
| + |
| + std::map<std::string, std::string>::const_iterator token_it = |
|
binji
2016/08/22 19:21:52
nit: Use StringMap_t instead of std::map<std::stri
chanpatorikku
2016/08/29 17:14:03
Done.
StringMap_t is defined the same in http_fs_
binji
2016/08/30 01:39:34
It's fine to redefine it.
|
| + args.string_map.find("token"); |
| + |
| + if (token_it == args.string_map.end()) { |
| + return EINVAL; |
| + } |
| + |
| + token_ = token_it->second; |
| + |
| + return 0; |
| +} |
| + |
| +void GoogleDriveFs::Destroy() {} |
| + |
| +Error GoogleDriveFs::OpenWithMode(const Path& path, |
| + int open_flags, |
| + mode_t mode, |
| + ScopedNode* out_node) { |
| + ScopedNode node(new GoogleDriveFsNode(this, path)); |
| + |
| + Error error = node->Init(open_flags); |
| + if (error) { |
| + return error; |
| + } |
| + |
| + *out_node = node; |
| + |
| + return 0; |
| +} |
| + |
| +Error GoogleDriveFs::Mkdir(const Path& path, int permissions) { |
| + URLLoaderInterface* url_loader_iface = ppapi()->GetURLLoaderInterface(); |
|
binji
2016/08/22 19:21:52
you could cache these interface pointers as member
chanpatorikku
2016/08/29 17:14:02
The interface pointers in googledrivefs are not ca
|
| + PP_Resource url_loader_object = url_loader_iface->Create(instance()); |
| + URLRequestInfoInterface* url_request_info_iface = |
| + ppapi()->GetURLRequestInfoInterface(); |
| + PP_Resource url_request_info_object = |
| + url_request_info_iface->Create(instance()); |
| + PP_Resource url_response_info_object = 0; |
| + Error error(0); |
| + std::string parent_dir_id = ""; |
|
binji
2016/08/22 19:21:52
nit: it's not necessary to initialize to "", that
chanpatorikku
2016/08/29 17:14:02
Done.
|
| + std::string item_id = ""; |
| + static const char base_url[] = "https://www.googleapis.com/drive/v3/files"; |
| + RequestUrlParams p; |
| + |
| + // Error on making the root directory |
| + if (path.Size() < 2) { |
| + error = EEXIST; |
| + goto done; |
| + } |
| + |
| + error = RequestParentDirId(path, this, &parent_dir_id); |
| + if (error) { |
| + goto done; |
| + } |
| + |
| + error = RequestItemId(parent_dir_id, path.Basename(), this, &item_id); |
| + |
| + if (!error) { |
| + error = EEXIST; |
| + goto done; |
| + } else if (error == ENOENT) { |
| + // mkdir does not create a directory when a file with path.Basename() |
| + // already exists. |
| + |
| + p.url = base_url; |
|
chanpatorikku
2016/08/07 02:41:02
Lines 99-113 are samples of how codes imitate the
|
| + p.method = "POST"; |
| + |
| + p.headers = ""; |
| + AddHeaders("Content-type", "application/json", &p.headers); |
| + AddHeaders("Authorization", "Bearer " + token_, &p.headers); |
| + |
| + p.body = ""; |
| + AddBody("{", &p.body); |
| + AddBody(" \"name\": \"" + path.Basename() + "\",", &p.body); |
| + AddBody(" \"mimeType\": \"application/vnd.google-apps.folder\",", &p.body); |
| + AddBody(" \"parents\": [", &p.body); |
| + AddBody(" \"" + parent_dir_id + "\"", &p.body); |
| + AddBody(" ]", &p.body); |
| + AddBody("}", &p.body); |
| + |
| + error = MakeRequest(ppapi(), url_loader_object, url_request_info_object, p); |
| + |
| + if (error) { |
| + goto done; |
| + } |
| + |
| + error = FinishPreparingResponse(ppapi(), url_loader_object, |
| + &url_response_info_object); |
| + |
| + if (error) { |
| + goto done; |
| + } |
| + |
| + if (ReadStatusCode(ppapi(), url_response_info_object) != STATUSCODE_OK) { |
| + error = EPERM; |
| + goto done; |
| + } |
| + |
| + error = 0; |
| + } |
| + |
| +done: |
| + if (url_loader_object) { |
|
binji
2016/08/22 19:21:52
Use the ScopedResource instead (see pepper_interfa
chanpatorikku
2016/08/29 17:14:03
Done.
|
| + ppapi()->ReleaseResource(url_loader_object); |
| + } |
| + if (url_request_info_object) { |
| + ppapi()->ReleaseResource(url_request_info_object); |
| + } |
| + if (url_response_info_object) { |
| + ppapi()->ReleaseResource(url_response_info_object); |
| + } |
| + |
| + return error; |
| +} |
| + |
| +Error GoogleDriveFs::Rmdir(const Path& path) { |
| + URLLoaderInterface* url_loader_iface = ppapi()->GetURLLoaderInterface(); |
| + PP_Resource url_loader_object = url_loader_iface->Create(instance()); |
| + URLRequestInfoInterface* url_request_info_iface = |
| + ppapi()->GetURLRequestInfoInterface(); |
| + PP_Resource url_request_info_object = |
| + url_request_info_iface->Create(instance()); |
| + PP_Resource url_response_info_object = 0; |
| + Error error(0); |
| + std::string parent_dir_id = ""; |
| + std::string dir_id = ""; |
| + std::string item_id = ""; |
| + bool is_empty_dir = true; |
| + static const char base_url[] = "https://www.googleapis.com/drive/v3/files"; |
|
binji
2016/08/22 19:21:52
This seems to be repeated quite a bit, can you mov
chanpatorikku
2016/08/29 17:14:02
Yes. Done.
|
| + RequestUrlParams p; |
| + |
| + // Error on removing the root directory |
| + if (path.Size() < 2) { |
| + error = EEXIST; |
| + goto done; |
| + } |
| + |
| + error = RequestParentDirId(path, this, &parent_dir_id); |
| + if (error) { |
| + goto done; |
| + } |
| + |
| + error = RequestDirId(parent_dir_id, path.Basename(), this, &dir_id); |
| + if (error == ENOENT) { |
| + error = RequestItemId(parent_dir_id, path.Basename(), this, &item_id); |
| + |
| + if (error) { |
| + goto done; |
| + } |
| + |
| + error = ENOTDIR; |
| + goto done; |
| + } else if (error) { |
| + goto done; |
| + } |
| + |
| + error = IsEmpty(dir_id, &is_empty_dir); |
| + if (error) { |
| + goto done; |
| + } |
| + |
| + if (!is_empty_dir) { |
| + error = ENOTEMPTY; |
| + goto done; |
| + } |
| + |
| + p.url = base_url; |
| + AddUrlPath(dir_id, &p.url); |
| + |
| + p.method = "DELETE"; |
| + |
| + p.headers = ""; |
| + AddHeaders("Content-type", "application/json", &p.headers); |
| + AddHeaders("Authorization", "Bearer " + token_, &p.headers); |
| + |
| + error = MakeRequest(ppapi(), url_loader_object, url_request_info_object, p); |
| + |
| + if (error) { |
| + goto done; |
| + } |
| + |
| + error = FinishPreparingResponse(ppapi(), url_loader_object, |
| + &url_response_info_object); |
| + |
| + if (error) { |
| + goto done; |
| + } |
| + |
| + if (ReadStatusCode(ppapi(), url_response_info_object) != |
| + STATUSCODE_NO_CONTENT) { |
| + error = EPERM; |
| + goto done; |
| + } |
| + |
| +done: |
| + if (url_loader_object) { |
| + ppapi()->ReleaseResource(url_loader_object); |
| + } |
| + if (url_request_info_object) { |
| + ppapi()->ReleaseResource(url_request_info_object); |
| + } |
| + if (url_response_info_object) { |
| + ppapi()->ReleaseResource(url_response_info_object); |
| + } |
| + |
| + return error; |
| +} |
| + |
| +Error GoogleDriveFs::Rename(const Path& path, const Path& newPath) { |
| + // TODO: support rename |
| + LOG_ERROR("rename not supported."); |
| + return EPERM; |
| +} |
| + |
| +Error GoogleDriveFs::Unlink(const Path& path) { |
| + // TODO: support unlink |
| + LOG_ERROR("unlink not supported."); |
| + return EPERM; |
| +} |
| + |
| +Error GoogleDriveFs::Remove(const Path& path) { |
| + // TODO: support remove |
| + LOG_ERROR("remove not supported."); |
| + return EPERM; |
| +} |
| + |
| +Error GoogleDriveFs::IsEmpty(const std::string& dir_id, |
| + bool* out_is_empty_dir) { |
| + static const char base_url[] = "https://www.googleapis.com/drive/v3/files"; |
| + |
| + std::string url = base_url; |
| + AddUrlFirstQueryParameter("q", "%27" + dir_id + "%27+in+parents", &url); |
| + |
| + std::string response_body; |
| + Error error = GetListFileResponseBody(url, this, &response_body); |
| + if (error) { |
| + return error; |
| + } |
| + |
| + std::string name_value = ""; |
| + int name_index = 0; |
| + |
| + GetValue(response_body, "name", name_index, &name_value, &name_index); |
| + |
| + *out_is_empty_dir = (name_index == -1); |
| + |
| + return 0; |
| +} |
| + |
| +std::string GoogleDriveFs::token() { |
| + return token_; |
| +} |
| + |
| +PP_Instance GoogleDriveFs::instance() { |
| + return instance_; |
| +} |
| + |
| +} // namespace nacl_io |