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 |