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..f8d6cfc8e158a9588181fd0b62a39020bdeaec20 |
--- /dev/null |
+++ b/native_client_sdk/src/libraries/nacl_io/googledrivefs/googledrivefs.cc |
@@ -0,0 +1,234 @@ |
+// 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 <stdint.h> |
+ |
+#include <limits> |
+ |
+#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() {} |
+ |
+Error GoogleDriveFs::Init(const FsInitArgs& args) { |
+ Error error = Filesystem::Init(args); |
+ if (error) { |
+ return error; |
+ } |
+ |
+ if (!ppapi()) { |
+ return ENOSYS; |
+ } |
+ |
+ StringMap_t::const_iterator token_it = args.string_map.find("token"); |
+ |
+ if (token_it == args.string_map.end()) { |
+ return EINVAL; |
+ } |
+ |
+ token_ = token_it->second; |
+ |
+ return 0; |
+} |
+ |
+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) { |
+ if (path.IsRoot()) { |
+ return EEXIST; |
+ } |
+ |
+ std::string parent_dir_id; |
+ Error error = RequestParentDirId(path, this, &parent_dir_id); |
+ if (error) { |
+ return error; |
+ } |
+ |
+ std::string item_id; |
+ bool is_dir_type; |
+ error = RequestItemIdAndItemType(parent_dir_id, path.Basename(), this, |
+ &item_id, &is_dir_type); |
+ |
+ // mkdir does not create a directory when a directory or a file with |
+ // path.Basename() already exists. |
+ if (!error) { |
+ return EEXIST; |
+ } else if (error != ENOENT) { |
+ return error; |
+ } |
+ |
+ RequestUrlParams p; |
+ |
+ p.url = DRIVE_URL; |
+ p.method = "POST"; |
+ |
+ AddHeaders("Content-type", "application/json", &p.headers); |
+ AddHeaders("Authorization", "Bearer " + token_, &p.headers); |
+ |
+ AddBody("{", &p.body); |
+ AddBody(" \"name\": \"" + path.Basename() + "\",", &p.body); |
+ AddBody( |
+ std::string(" \"mimeType\": \"") + FOLDER_MIME_TYPE + std::string("\","), |
+ &p.body); |
+ AddBody(" \"parents\": [", &p.body); |
+ AddBody(" \"" + parent_dir_id + "\"", &p.body); |
+ AddBody(" ]", &p.body); |
+ AddBody("}", &p.body); |
+ |
+ ScopedResource url_response_info_resource(ppapi()); |
+ error = LoadUrl(ppapi(), p, &url_response_info_resource); |
+ if (error) { |
+ return error; |
+ } |
+ |
+ if (ReadStatusCode(ppapi(), url_response_info_resource.pp_resource()) != |
+ STATUSCODE_OK) { |
+ return EPERM; |
+ } |
+ |
+ return 0; |
+} |
+ |
+Error GoogleDriveFs::Rmdir(const Path& path) { |
+ if (path.IsRoot()) { |
+ return EEXIST; |
+ } |
+ |
+ std::string parent_dir_id; |
+ Error error = RequestParentDirId(path, this, &parent_dir_id); |
+ if (error) { |
+ return error; |
+ } |
+ |
+ std::string item_id; |
+ bool is_dir_type; |
+ error = RequestItemIdAndItemType(parent_dir_id, path.Basename(), this, |
+ &item_id, &is_dir_type); |
+ if (error) { |
+ return error; |
+ } |
+ |
+ if (!is_dir_type) { |
+ return ENOTDIR; |
+ } |
+ |
+ bool is_empty_dir; |
+ error = IsEmptyDir(item_id, &is_empty_dir); |
+ if (error) { |
+ return error; |
+ } |
+ |
+ if (!is_empty_dir) { |
+ return ENOTEMPTY; |
+ } |
+ |
+ RequestUrlParams p; |
+ |
+ p.url = DRIVE_URL; |
+ AddUrlPath(item_id, &p.url); |
+ |
+ p.method = "DELETE"; |
+ |
+ AddHeaders("Content-type", "application/json", &p.headers); |
+ AddHeaders("Authorization", "Bearer " + token_, &p.headers); |
+ |
+ ScopedResource url_response_info_resource(ppapi()); |
+ error = LoadUrl(ppapi(), p, &url_response_info_resource); |
+ if (error) { |
+ return error; |
+ } |
+ |
+ if (ReadStatusCode(ppapi(), url_response_info_resource.pp_resource()) != |
+ STATUSCODE_NO_CONTENT) { |
+ return EPERM; |
+ } |
+ |
+ return 0; |
+} |
+ |
+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::IsEmptyDir(const std::string& dir_id, |
+ bool* out_is_empty_dir) { |
+ RequestUrlParams p; |
+ |
+ p.url = DRIVE_URL; |
+ AddUrlFirstQueryParameter("q", ParentEqualClause(dir_id), &p.url); |
+ |
+ p.method = "GET"; |
+ |
+ AddHeaders("Content-type", "application/json", &p.headers); |
+ AddHeaders("Authorization", "Bearer " + token_, &p.headers); |
+ |
+ ScopedResource url_response_info_resource(ppapi()); |
+ Error error = LoadUrl(ppapi(), p, &url_response_info_resource); |
+ if (error) { |
+ return error; |
+ } |
+ |
+ if (ReadStatusCode(ppapi(), url_response_info_resource.pp_resource()) != |
+ STATUSCODE_OK) { |
+ return EPERM; |
+ } |
+ |
+ std::string output; |
+ error = ReadResponseBody(ppapi(), url_response_info_resource.pp_resource(), |
+ std::numeric_limits<int32_t>::max(), &output); |
+ if (error) { |
+ return error; |
+ } |
+ |
+ std::string name_value; |
+ size_t name_index; |
+ error = |
+ GetValueStringAndValuePos(output, "name", 0, &name_value, &name_index); |
+ if (error && error != EINVAL) { |
+ return error; |
+ } |
+ |
+ *out_is_empty_dir = (error == EINVAL); |
+ |
+ return 0; |
+} |
+ |
+std::string GoogleDriveFs::token() { |
+ return token_; |
+} |
+ |
+} // namespace nacl_io |