OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "nacl_io/googledrivefs/googledrivefs.h" | |
6 | |
7 #include <fcntl.h> | |
8 | |
9 #include <map> | |
10 #include <algorithm> | |
11 #include <cstdio> | |
12 | |
13 #include "ppapi/cpp/url_request_info.h" | |
14 #include "ppapi/cpp/url_response_info.h" | |
15 #include "ppapi/cpp/url_loader.h" | |
16 #include "ppapi/cpp/file_ref.h" | |
17 #include "ppapi/cpp/file_io.h" | |
18 | |
19 #include "nacl_io/error.h" | |
20 #include "nacl_io/pepper_interface.h" | |
21 #include "ppapi/c/pp_completion_callback.h" | |
22 | |
23 #include "json/reader.h" | |
binji
2016/07/18 23:24:02
nacl_io currently does not depend on json; We're n
chanpatorikku
2016/08/07 02:41:02
Done.
Thanks.
Not going to add it as a new depend
| |
24 #include "json/writer.h" | |
25 | |
26 #include "nacl_io/filesystem.h" | |
27 #include "nacl_io/kernel_handle.h" | |
28 #include "nacl_io/getdents_helper.h" | |
29 | |
30 #ifdef WIN32 | |
31 #include <windows.h> | |
binji
2016/07/18 23:24:02
what is this needed for?
chanpatorikku
2016/08/07 02:41:02
This used to be needed for Sleep() from windows.h.
| |
32 #else | |
33 #include <unistd.h> | |
34 #endif | |
35 | |
36 namespace nacl_io { | |
37 | |
38 namespace { | |
39 | |
40 std::string MapToHeaders( | |
41 const std::map<std::string, std::string>& header_field_map) { | |
42 std::string request_headers = ""; | |
43 | |
44 for (std::map<std::string, std::string>::const_iterator it = | |
45 header_field_map.begin(); | |
46 it != header_field_map.end(); ++it) { | |
47 request_headers += it->first; | |
48 request_headers += ": "; | |
49 request_headers += it->second; | |
50 request_headers += "\n"; | |
51 } | |
52 return request_headers; | |
53 } | |
54 | |
55 // Continuing DJB2a hash | |
56 ino_t HashPathSegment(ino_t hash, const char* str, size_t len) { | |
57 // First add the path seperator | |
58 hash = (hash * static_cast<ino_t>(33)) ^ '/'; | |
59 while (len--) { | |
60 hash = (hash * static_cast<ino_t>(33)) ^ *str++; | |
61 } | |
62 return hash; | |
63 } | |
64 | |
65 ino_t HashPath(const Path& path) { | |
binji
2016/07/18 23:24:02
better to share the code with Html5Fs rather than
chanpatorikku
2016/08/07 02:41:02
Done.
Thanks.
Shared the code with Html5Fs.
| |
66 // Prime the DJB2a hash | |
67 ino_t hash = 5381; | |
68 | |
69 // Apply a running DJB2a to each part of the path | |
70 for (size_t segment = 0; segment < path.Size(); segment++) { | |
71 const std::string& part = path.Part(segment); | |
72 hash = HashPathSegment(hash, part.c_str(), part.length()); | |
73 } | |
74 return hash; | |
75 } | |
76 | |
77 // A Google Drive item is a file or a directory. | |
78 // RequestDirId requests to see if a directory with dir_name | |
79 // and a parent with ID parent_dir_id is there. | |
80 // If it is, dir_id is set. | |
81 // RequestDirId returns ENOENT when a file with dir_name is there | |
82 // but a directory with dir_name is not. | |
83 Error RequestDirId(const std::string& parent_dir_id, | |
84 const std::string& dir_name, | |
85 Filesystem* filesystem, | |
86 std::string& dir_id) { | |
87 dir_id = ""; | |
88 | |
89 std::string url = "https://www.googleapis.com/drive/v3/files"; | |
binji
2016/07/18 23:24:02
It's better to have these strings be constants (as
chanpatorikku
2016/08/07 02:41:02
Each URL may be different.
I don't know if the cur
| |
90 url += "?"; | |
91 url += "q="; | |
92 url += "%27"; | |
93 url += parent_dir_id; | |
94 url += "%27+in+parents"; | |
95 url += "+and+"; | |
96 url += "mimeType+=+"; | |
97 url += "%27application/vnd.google-apps.folder%27"; | |
98 url += "+and+"; | |
99 url += "name+=+%27" + dir_name + "%27"; | |
100 | |
101 GoogleDriveFs* googledrivefs = dynamic_cast<GoogleDriveFs*>(filesystem); | |
binji
2016/07/18 23:24:02
don't use dynamic_cast, it relies on RTTI. static_
chanpatorikku
2016/08/07 02:41:02
Done.
Thanks.
static_cast is called in the curren
| |
102 if (googledrivefs == NULL) { | |
103 return EINVAL; | |
104 } | |
105 | |
106 pp::URLLoader loader(pp::InstanceHandle(googledrivefs->instance())); | |
binji
2016/07/18 23:24:02
nacl_io uses the Pepper C interface, not the C++ i
chanpatorikku
2016/08/07 02:41:02
Done.
Thanks.
Pepper C interface is used in the c
| |
107 pp::URLRequestInfo request(pp::InstanceHandle(googledrivefs->instance())); | |
108 | |
109 bool set_url_ok = request.SetURL(url); | |
binji
2016/07/18 23:24:02
it's better to just inline this than to create a n
chanpatorikku
2016/08/07 02:41:02
I don't know exactly about inlining.
Please review
| |
110 if (!set_url_ok) { | |
111 return EPERM; | |
112 } | |
113 | |
114 bool set_method_ok = request.SetMethod("GET"); | |
115 if (!set_method_ok) { | |
116 return EPERM; | |
117 } | |
118 | |
119 std::map<std::string, std::string> headers_map; | |
binji
2016/07/18 23:24:02
This seems to be duplicated a number of times in t
chanpatorikku
2016/08/07 02:41:02
Done.
Thanks.
Tried factoring it in a similar way
| |
120 headers_map["Content-type"] = "application/json"; | |
121 std::string authorization_value = "Bearer "; | |
122 authorization_value += googledrivefs->token(); | |
123 headers_map["Authorization"] = authorization_value; | |
124 | |
125 std::string headers = MapToHeaders(headers_map); | |
126 | |
127 bool set_headers_ok = request.SetHeaders(headers); | |
128 if (!set_headers_ok) { | |
129 return EPERM; | |
130 } | |
131 | |
132 bool set_allow_cross_origin_requests_ok = | |
133 request.SetAllowCrossOriginRequests(true); | |
134 if (!set_allow_cross_origin_requests_ok) { | |
135 return EPERM; | |
136 } | |
137 | |
138 bool set_stream_to_file_ok = request.SetStreamToFile(true); | |
139 if (!set_stream_to_file_ok) { | |
140 return EPERM; | |
141 } | |
142 | |
143 int32_t err = loader.Open(request, pp::BlockUntilComplete()); | |
144 if (err < 0) { | |
145 return PPERROR_TO_ERRNO(err); | |
146 } | |
147 | |
148 pp::URLResponseInfo response = loader.GetResponseInfo(); | |
149 if (response.GetStatusCode() != 200) { | |
150 return EPERM; | |
151 } | |
152 | |
153 pp::FileRef file_ref = response.GetBodyAsFileRef(); | |
154 pp::FileIO file_io(pp::InstanceHandle(googledrivefs->instance())); | |
155 | |
156 int32_t open_result = | |
157 file_io.Open(file_ref, PP_FILEOPENFLAG_READ, pp::BlockUntilComplete()); | |
158 if (open_result < 0) { | |
159 return PPERROR_TO_ERRNO(open_result); | |
160 } | |
161 | |
162 int BUFFER_SIZE = 1024; | |
163 char buffer[BUFFER_SIZE]; | |
binji
2016/07/18 23:24:02
What if the result is greater than 1024 bytes?
chanpatorikku
2016/08/07 02:41:02
Done.
Thanks.
Code is rewritten for the result gr
| |
164 | |
165 int32_t byte_read = | |
166 file_io.Read(0, buffer, BUFFER_SIZE, pp::BlockUntilComplete()); | |
167 while (byte_read == 0) { | |
binji
2016/07/18 23:24:02
This loop is strange, what problem are you trying
chanpatorikku
2016/08/07 02:41:02
Done.
The problem I was trying to fix was that Fi
| |
168 #ifdef WIN32 | |
169 Sleep(1000); | |
170 #else | |
171 usleep(1000000); | |
binji
2016/07/18 23:24:02
We never want to call sleep in nacl_io, it's usual
chanpatorikku
2016/08/07 02:41:02
Done.
Sleep is not called in nacl_io in the curre
| |
172 #endif | |
173 | |
174 byte_read = file_io.Read(0, buffer, BUFFER_SIZE, pp::BlockUntilComplete()); | |
175 } | |
176 | |
177 if (byte_read < 0) { | |
178 return PPERROR_TO_ERRNO(byte_read); | |
179 } | |
180 | |
181 std::string output(buffer); | |
182 | |
183 Json::Value root; | |
184 | |
185 Json::Reader reader(Json::Features::strictMode()); | |
186 if (!reader.parse(output, root, false)) { | |
187 return EPERM; | |
188 } | |
189 | |
190 if (!root.isMember("files")) { | |
191 return EPERM; | |
192 } | |
193 | |
194 Json::Value files_array = root["files"]; | |
195 if (!files_array.isArray()) { | |
196 return EPERM; | |
197 } | |
198 if (files_array.size() == 0) { | |
199 return ENOENT; | |
200 } | |
201 | |
202 dir_id = files_array[0]["id"].asString(); | |
203 | |
204 return 0; | |
205 } | |
206 | |
207 // A Google Drive item is a file or a directory. | |
208 // RequestItemId requests to see if either a file with item_name | |
209 // or a directory with item_name is there. | |
210 // If it is, item_id is set. | |
211 Error RequestItemId(const std::string& parent_dir_id, | |
212 const std::string& item_name, | |
213 Filesystem* filesystem, | |
214 std::string& item_id) { | |
215 item_id = ""; | |
216 | |
217 std::string url = "https://www.googleapis.com/drive/v3/files"; | |
218 url += "?"; | |
219 url += "q="; | |
220 url += "%27"; | |
221 url += parent_dir_id; | |
222 url += "%27+in+parents"; | |
223 url += "+and+"; | |
224 url += "name+=+%27" + item_name + "%27"; | |
225 | |
226 GoogleDriveFs* googledrivefs = dynamic_cast<GoogleDriveFs*>(filesystem); | |
227 if (googledrivefs == NULL) { | |
228 return EINVAL; | |
229 } | |
230 | |
231 pp::URLLoader loader(pp::InstanceHandle(googledrivefs->instance())); | |
232 pp::URLRequestInfo request(pp::InstanceHandle(googledrivefs->instance())); | |
233 | |
234 bool set_url_ok = request.SetURL(url); | |
235 if (!set_url_ok) { | |
236 return EPERM; | |
237 } | |
238 | |
239 bool set_method_ok = request.SetMethod("GET"); | |
240 if (!set_method_ok) { | |
241 return EPERM; | |
242 } | |
243 | |
244 std::map<std::string, std::string> headers_map; | |
245 headers_map["Content-type"] = "application/json"; | |
246 std::string authorization_value = "Bearer "; | |
247 authorization_value += googledrivefs->token(); | |
248 headers_map["Authorization"] = authorization_value; | |
249 | |
250 std::string headers = MapToHeaders(headers_map); | |
251 | |
252 bool set_headers_ok = request.SetHeaders(headers); | |
253 if (!set_headers_ok) { | |
254 return EPERM; | |
255 } | |
256 | |
257 bool set_allow_cross_origin_requests_ok = | |
258 request.SetAllowCrossOriginRequests(true); | |
259 if (!set_allow_cross_origin_requests_ok) { | |
260 return EPERM; | |
261 } | |
262 | |
263 bool set_stream_to_file_ok = request.SetStreamToFile(true); | |
264 if (!set_stream_to_file_ok) { | |
265 return EPERM; | |
266 } | |
267 | |
268 int32_t err = loader.Open(request, pp::BlockUntilComplete()); | |
269 if (err < 0) { | |
270 return PPERROR_TO_ERRNO(err); | |
271 } | |
272 | |
273 pp::URLResponseInfo response = loader.GetResponseInfo(); | |
274 if (response.GetStatusCode() != 200) { | |
275 return EPERM; | |
276 } | |
277 | |
278 pp::FileRef file_ref = response.GetBodyAsFileRef(); | |
279 pp::FileIO file_io(pp::InstanceHandle(googledrivefs->instance())); | |
280 | |
281 int32_t open_result = | |
282 file_io.Open(file_ref, PP_FILEOPENFLAG_READ, pp::BlockUntilComplete()); | |
283 if (open_result < 0) { | |
284 return PPERROR_TO_ERRNO(open_result); | |
285 } | |
286 | |
287 int BUFFER_SIZE = 1024; | |
288 char buffer[BUFFER_SIZE]; | |
289 | |
290 int32_t byte_read = | |
291 file_io.Read(0, buffer, BUFFER_SIZE, pp::BlockUntilComplete()); | |
292 while (byte_read == 0) { | |
293 #ifdef WIN32 | |
294 Sleep(1000); | |
295 #else | |
296 usleep(1000000); | |
297 #endif | |
298 | |
299 byte_read = file_io.Read(0, buffer, BUFFER_SIZE, pp::BlockUntilComplete()); | |
300 } | |
301 | |
302 if (byte_read < 0) { | |
303 return PPERROR_TO_ERRNO(byte_read); | |
304 } | |
305 | |
306 std::string output(buffer); | |
307 | |
308 Json::Value root; | |
309 | |
310 Json::Reader reader(Json::Features::strictMode()); | |
311 if (!reader.parse(output, root, false)) { | |
312 return EPERM; | |
313 } | |
314 | |
315 if (!root.isMember("files")) { | |
316 return EPERM; | |
317 } | |
318 | |
319 Json::Value files_array = root["files"]; | |
320 | |
321 if (!files_array.isArray()) { | |
322 return EPERM; | |
323 } | |
324 if (files_array.size() == 0) { | |
325 return ENOENT; | |
326 } | |
327 | |
328 item_id = files_array[0]["id"].asString(); | |
329 | |
330 return 0; | |
331 } | |
332 | |
333 Error RequestParentDirId(const Path& path, | |
334 Filesystem* filesystem, | |
335 std::string& parent_dir_id) { | |
binji
2016/07/18 23:24:02
Out parameters should be pointers, not references,
chanpatorikku
2016/08/07 02:41:02
Done.
Thanks.
Out parameters are pointers and are
| |
336 parent_dir_id = ""; | |
337 | |
338 if (path.Size() < 2) { | |
339 return EINVAL; | |
340 } | |
341 | |
342 std::string helper_parent_dir_id = "root"; | |
343 | |
344 for (unsigned int i = 1; i < path.Size() - 1; ++i) { | |
345 std::string dir_name = path.Range(i, i + 1); | |
346 | |
347 std::string dir_id = ""; | |
348 Error error = | |
349 RequestDirId(helper_parent_dir_id, dir_name, filesystem, dir_id); | |
350 if (error) { | |
351 return error; | |
352 } | |
353 | |
354 helper_parent_dir_id = dir_id; | |
355 } | |
356 parent_dir_id = helper_parent_dir_id; | |
357 | |
358 return 0; | |
359 } | |
360 } | |
361 | |
362 class GoogleDriveFsNode : public Node { | |
binji
2016/07/18 23:24:02
It's generally nicer when the nodes are defined in
chanpatorikku
2016/08/07 02:41:02
Done.
Thanks.
Nodes are defined in a separate fil
| |
363 public: | |
364 GoogleDriveFsNode(Filesystem* filesystem, Path path) | |
365 : Node(filesystem), path_(path) {} | |
366 | |
367 Error GetDents(size_t offs, | |
368 struct dirent* pdir, | |
369 size_t size, | |
370 int* out_bytes) { | |
371 if (!IsaDir()) { | |
372 return ENOTDIR; | |
373 } | |
374 | |
375 const ino_t kCurDirIno = -1; | |
376 const ino_t kParentDirIno = -2; | |
377 GetDentsHelper helper(kCurDirIno, kParentDirIno); | |
378 | |
379 std::vector<std::string> dirent_names; | |
380 Error error = RequestDirent(dirent_names); | |
381 if (error) { | |
382 return error; | |
383 } | |
384 | |
385 for (unsigned int i = 0; i < dirent_names.size(); ++i) { | |
386 Path child_path(path_); | |
387 child_path = child_path.Append("/" + dirent_names[i]); | |
388 ino_t child_ino = HashPath(child_path); | |
389 | |
390 helper.AddDirent(child_ino, dirent_names[i].c_str(), | |
391 dirent_names[i].size()); | |
392 } | |
393 | |
394 return helper.GetDents(offs, pdir, size, out_bytes); | |
395 } | |
396 | |
397 Error GetStat(struct stat* pstat) { | |
398 Error error = GetSize(&pstat->st_size); | |
399 if (error) { | |
400 return error; | |
401 } | |
402 return 0; | |
403 } | |
404 | |
405 Error Write(const HandleAttr& attr, | |
406 const void* buf, | |
407 size_t count, | |
408 int* out_bytes) { | |
409 *out_bytes = 0; | |
410 | |
411 if (IsaDir()) { | |
412 return EISDIR; | |
413 } | |
414 | |
415 off_t file_size = 0; | |
416 Error error = GetSize(&file_size); | |
417 if (error) { | |
418 return error; | |
419 } | |
420 | |
421 off_t file_buf_size = std::max((unsigned long long int)file_size, | |
422 (unsigned long long int)attr.offs + count); | |
423 char file_buf[file_buf_size]; | |
binji
2016/07/18 23:24:02
This will allocate space for the file on the stack
chanpatorikku
2016/08/07 02:41:02
Done.
Thanks.
Heap memory, as automatically alloc
| |
424 | |
425 if (file_size > 0) { | |
426 int read_helper_out_bytes = 0; | |
427 | |
428 error = ReadHelper(0, file_size - 1, file_buf, file_size, | |
429 &read_helper_out_bytes); | |
430 | |
431 if (error) { | |
432 return error; | |
433 } | |
434 | |
435 if (read_helper_out_bytes != file_size) { | |
436 return EPERM; | |
437 } | |
438 } | |
439 | |
440 char* pChar = (char*)buf; | |
441 for (unsigned int i = 0; i < count; ++i) { | |
442 file_buf[attr.offs + i] = pChar[i]; | |
443 } | |
444 | |
445 error = WriteHelper(file_buf, file_buf_size); | |
446 if (error) { | |
447 return error; | |
448 } | |
449 | |
450 *out_bytes = count; | |
451 | |
452 return 0; | |
453 } | |
454 | |
455 Error FTruncate(off_t length) { | |
456 if (IsaDir()) { | |
457 return EISDIR; | |
458 } | |
459 | |
460 off_t file_size = 0; | |
461 Error error = GetSize(&file_size); | |
462 if (error) { | |
463 return error; | |
464 } | |
465 | |
466 char file_buf[length]; | |
467 | |
468 if (file_size > 0) { | |
469 int read_helper_out_bytes = 0; | |
470 | |
471 error = ReadHelper(0, file_size - 1, file_buf, file_size, | |
472 &read_helper_out_bytes); | |
473 if (error) { | |
474 return error; | |
475 } | |
476 | |
477 if (read_helper_out_bytes != file_size) { | |
478 return EPERM; | |
479 } | |
480 } | |
481 | |
482 for (int i = file_size; i < length; ++i) { | |
483 file_buf[i] = '\0'; | |
484 } | |
485 | |
486 error = WriteHelper(file_buf, length); | |
487 if (error) { | |
488 return error; | |
489 } | |
490 | |
491 return 0; | |
492 } | |
493 | |
494 Error Read(const HandleAttr& attr, void* buf, size_t count, int* out_bytes) { | |
495 *out_bytes = 0; | |
496 | |
497 if (IsaDir()) { | |
498 return EISDIR; | |
499 } | |
500 | |
501 Error error = | |
502 ReadHelper(attr.offs, attr.offs + count - 1, buf, count, out_bytes); | |
503 if (error) { | |
504 return error; | |
505 } | |
506 | |
507 return 0; | |
508 } | |
509 | |
510 int GetType() { return IsaDir() ? S_IFDIR : S_IFREG; } | |
511 | |
512 Error GetSize(off_t* out_size) { | |
513 *out_size = 0; | |
514 | |
515 if (IsaDir()) { | |
516 return 0; | |
517 } | |
518 | |
519 GoogleDriveFs* googledrivefs = dynamic_cast<GoogleDriveFs*>(filesystem_); | |
520 if (googledrivefs == NULL) { | |
521 return EINVAL; | |
522 } | |
523 | |
524 pp::URLLoader loader(pp::InstanceHandle(googledrivefs->instance())); | |
525 pp::URLRequestInfo request(pp::InstanceHandle(googledrivefs->instance())); | |
526 | |
527 std::string url = "https://www.googleapis.com/drive/v3/files/"; | |
528 url += item_id_; | |
529 url += "?"; | |
530 url += "fields=size"; | |
531 | |
532 bool set_url_ok = request.SetURL(url); | |
533 if (!set_url_ok) { | |
534 return EPERM; | |
535 } | |
536 | |
537 bool set_method_ok = request.SetMethod("GET"); | |
538 if (!set_method_ok) { | |
539 return EPERM; | |
540 } | |
541 | |
542 std::map<std::string, std::string> headers_map; | |
543 headers_map["Content-type"] = "application/json"; | |
544 std::string authorization_value = "Bearer "; | |
545 authorization_value += googledrivefs->token(); | |
546 headers_map["Authorization"] = authorization_value; | |
547 | |
548 std::string headers = MapToHeaders(headers_map); | |
549 | |
550 bool set_headers_ok = request.SetHeaders(headers); | |
551 if (!set_headers_ok) { | |
552 return EPERM; | |
553 } | |
554 | |
555 bool set_allow_cross_origin_requests_ok = | |
556 request.SetAllowCrossOriginRequests(true); | |
557 if (!set_allow_cross_origin_requests_ok) { | |
558 return EPERM; | |
559 } | |
560 | |
561 bool set_stream_to_file_ok = request.SetStreamToFile(true); | |
562 if (!set_stream_to_file_ok) { | |
563 return EPERM; | |
564 } | |
565 | |
566 int32_t err = loader.Open(request, pp::BlockUntilComplete()); | |
567 if (err < 0) { | |
568 return PPERROR_TO_ERRNO(err); | |
569 } | |
570 | |
571 pp::URLResponseInfo response = loader.GetResponseInfo(); | |
572 if (response.GetStatusCode() != 200) { | |
573 return EPERM; | |
574 } | |
575 | |
576 pp::FileRef file_ref = response.GetBodyAsFileRef(); | |
577 pp::FileIO file_io(pp::InstanceHandle(googledrivefs->instance())); | |
578 int32_t open_result = | |
579 file_io.Open(file_ref, PP_FILEOPENFLAG_READ, pp::BlockUntilComplete()); | |
580 | |
581 if (open_result < 0) { | |
582 return PPERROR_TO_ERRNO(open_result); | |
583 } | |
584 | |
585 int BUFFER_SIZE = 1024; | |
586 char buffer[BUFFER_SIZE]; | |
587 | |
588 int32_t byte_read = | |
589 file_io.Read(0, buffer, BUFFER_SIZE, pp::BlockUntilComplete()); | |
590 while (byte_read == 0) { | |
591 #ifdef WIN32 | |
592 Sleep(1000); | |
593 #else | |
594 usleep(1000000); | |
595 #endif | |
596 | |
597 byte_read = | |
598 file_io.Read(0, buffer, BUFFER_SIZE, pp::BlockUntilComplete()); | |
599 } | |
600 if (byte_read < 0) { | |
601 return PPERROR_TO_ERRNO(byte_read); | |
602 } | |
603 | |
604 std::string output(buffer); | |
605 Json::Value root; | |
606 | |
607 Json::Reader reader(Json::Features::strictMode()); | |
608 if (!reader.parse(output, root, false)) { | |
609 return EPERM; | |
610 } | |
611 | |
612 if (!root.isMember("size")) { | |
613 return EPERM; | |
614 } | |
615 | |
616 Json::Value size_value = root["size"]; | |
617 | |
618 *out_size = (off_t)atoi(size_value.asCString()); | |
619 | |
620 return 0; | |
621 } | |
622 | |
623 Error Init(int open_flags) { | |
624 Error error = Node::Init(open_flags); | |
625 | |
626 if (error) { | |
627 return error; | |
628 } | |
629 | |
630 if (path_.Size() == 1) { | |
631 parent_dir_id_ = ""; | |
632 item_id_ = "root"; | |
633 is_dir_item_ = true; | |
634 return 0; | |
635 } | |
636 | |
637 error = RequestParentDirId(path_, filesystem_, parent_dir_id_); | |
638 if (error) { | |
639 return error; | |
640 } | |
641 | |
642 // Request the ID of an item, which is a file or a directory | |
643 error = | |
644 RequestItemId(parent_dir_id_, path_.Basename(), filesystem_, item_id_); | |
645 | |
646 if (error == ENOENT) { | |
647 // Only files are open as mode O_CREAT | |
648 if ((open_flags & O_CREAT) != 0) { | |
649 error = CreateEmptyFile(); | |
650 if (error) { | |
651 return error; | |
652 } | |
653 error = RequestItemId(parent_dir_id_, path_.Basename(), filesystem_, | |
654 item_id_); | |
655 if (error) { | |
656 return error; | |
657 } | |
658 is_dir_item_ = false; | |
659 } else { | |
660 return ENOENT; | |
661 } | |
662 } else if (error) { | |
663 return error; | |
664 } else { | |
665 std::string dir_id = ""; | |
666 error = | |
667 RequestDirId(parent_dir_id_, path_.Basename(), filesystem_, dir_id); | |
668 if (error == ENOENT) { | |
669 is_dir_item_ = false; | |
670 } else if (error) { | |
671 return error; | |
672 } else { | |
673 is_dir_item_ = true; | |
674 } | |
675 | |
676 if (open_flags == 0) { | |
677 // open_flags == 0 for file opened on fopen with mode r and directory | |
678 // opened on opendir | |
679 return 0; | |
680 } else if (is_dir_item_ && open_flags != 0) { | |
681 return EPERM; | |
682 } else if ((open_flags & O_TRUNC) != 0) { | |
683 error = WriteHelper(NULL, 0); | |
684 if (error) { | |
685 return error; | |
686 } | |
687 } | |
688 } | |
689 | |
690 return 0; | |
691 } | |
692 | |
693 void Destroy() { Node::Destroy(); } | |
694 | |
695 bool IsaDir() { return is_dir_item_; } | |
696 | |
697 private: | |
698 Error ReadHelper(off_t start, | |
699 off_t end, | |
700 void* buf, | |
701 size_t count, | |
702 int* out_bytes) { | |
703 *out_bytes = 0; | |
704 | |
705 GoogleDriveFs* googledrivefs = dynamic_cast<GoogleDriveFs*>(filesystem_); | |
706 if (googledrivefs == NULL) { | |
707 return EINVAL; | |
708 } | |
709 | |
710 pp::URLLoader loader(pp::InstanceHandle(googledrivefs->instance())); | |
711 pp::URLRequestInfo request(pp::InstanceHandle(googledrivefs->instance())); | |
712 | |
713 std::string url = "https://www.googleapis.com/download/drive/v3/files/"; | |
714 url += item_id_; | |
715 url += "?"; | |
716 url += "alt=media"; | |
717 | |
718 bool set_url_ok = request.SetURL(url); | |
719 if (!set_url_ok) { | |
720 return EPERM; | |
721 } | |
722 | |
723 bool set_method_ok = request.SetMethod("GET"); | |
724 if (!set_method_ok) { | |
725 return EPERM; | |
726 } | |
727 | |
728 std::map<std::string, std::string> headers_map; | |
729 headers_map["Content-type"] = "application/json"; | |
730 std::string authorization_value = "Bearer "; | |
731 authorization_value += googledrivefs->token(); | |
732 headers_map["Authorization"] = authorization_value; | |
733 char range_value_buffer[1024]; | |
734 int char_written = sprintf(range_value_buffer, "bytes=%lli-%lli", | |
735 (long long int)start, (long long int)end); | |
736 if (char_written < 0) { | |
737 return EPERM; | |
738 } | |
739 std::string range_value(range_value_buffer); | |
740 headers_map["Range"] = range_value; | |
741 | |
742 std::string headers = MapToHeaders(headers_map); | |
743 | |
744 bool set_headers_ok = request.SetHeaders(headers); | |
745 if (!set_headers_ok) { | |
746 return EPERM; | |
747 } | |
748 | |
749 bool set_allow_cross_origin_requests_ok = | |
750 request.SetAllowCrossOriginRequests(true); | |
751 if (!set_allow_cross_origin_requests_ok) { | |
752 return EPERM; | |
753 } | |
754 | |
755 bool set_stream_to_file_ok = request.SetStreamToFile(true); | |
756 if (!set_stream_to_file_ok) { | |
757 return EPERM; | |
758 } | |
759 | |
760 int32_t err = loader.Open(request, pp::BlockUntilComplete()); | |
761 if (err < 0) { | |
762 return PPERROR_TO_ERRNO(err); | |
763 } | |
764 | |
765 pp::URLResponseInfo response = loader.GetResponseInfo(); | |
766 | |
767 if (response.GetStatusCode() == 200 || response.GetStatusCode() == 206) { | |
binji
2016/07/18 23:24:02
use consts for the status codes instead (see http_
chanpatorikku
2016/08/07 02:41:02
Done.
Thanks.
Used consts for the status codes, a
| |
768 pp::FileRef file_ref = response.GetBodyAsFileRef(); | |
769 pp::FileIO file_io(pp::InstanceHandle(googledrivefs->instance())); | |
770 | |
771 int32_t open_result = file_io.Open(file_ref, PP_FILEOPENFLAG_READ, | |
772 pp::BlockUntilComplete()); | |
773 if (open_result < 0) { | |
774 return PPERROR_TO_ERRNO(open_result); | |
775 } | |
776 | |
777 int32_t byte_read = | |
778 file_io.Read(0, (char*)buf, count, pp::BlockUntilComplete()); | |
779 while (byte_read == 0) { | |
780 #ifdef WIN32 | |
781 Sleep(1000); | |
782 #else | |
783 usleep(1000000); | |
784 #endif | |
785 | |
786 byte_read = | |
787 file_io.Read(0, (char*)buf, count, pp::BlockUntilComplete()); | |
788 } | |
789 | |
790 if (byte_read < 0) { | |
791 return PPERROR_TO_ERRNO(byte_read); | |
792 } | |
793 | |
794 *out_bytes = byte_read; | |
795 | |
796 return 0; | |
797 | |
798 } else if (response.GetStatusCode() == 416) { | |
799 *out_bytes = 0; | |
800 | |
801 char* pChar = (char*)buf; | |
802 pChar[0] = '\0'; | |
803 | |
804 return 0; | |
805 } | |
806 | |
807 return EPERM; | |
808 } | |
809 | |
810 Error WriteHelper(const void* request_body_data, uint32_t request_body_size) { | |
811 GoogleDriveFs* googledrivefs = dynamic_cast<GoogleDriveFs*>(filesystem_); | |
812 if (googledrivefs == NULL) { | |
813 return EINVAL; | |
814 } | |
815 | |
816 pp::URLLoader loader(pp::InstanceHandle(googledrivefs->instance())); | |
817 pp::URLRequestInfo request(pp::InstanceHandle(googledrivefs->instance())); | |
818 | |
819 std::string url = "https://www.googleapis.com/upload/drive/v3/files/"; | |
820 url += item_id_; | |
821 url += "?"; | |
822 url += "uploadType=media"; | |
823 | |
824 bool set_url_ok = request.SetURL(url); | |
825 if (!set_url_ok) { | |
826 return EPERM; | |
827 } | |
828 bool set_method_ok = request.SetMethod("PATCH"); | |
829 if (!set_method_ok) { | |
830 return EPERM; | |
831 } | |
832 | |
833 std::map<std::string, std::string> headers_map; | |
834 headers_map["Content-type"] = "application/json"; | |
835 std::string authorization_value = "Bearer "; | |
836 authorization_value += googledrivefs->token(); | |
837 headers_map["Authorization"] = authorization_value; | |
838 | |
839 std::string headers = MapToHeaders(headers_map); | |
840 | |
841 bool set_headers_ok = request.SetHeaders(headers); | |
842 if (!set_headers_ok) { | |
843 return EPERM; | |
844 } | |
845 | |
846 bool set_allow_cross_origin_requests_ok = | |
847 request.SetAllowCrossOriginRequests(true); | |
848 if (!set_allow_cross_origin_requests_ok) { | |
849 return EPERM; | |
850 } | |
851 | |
852 bool set_stream_to_file_ok = request.SetStreamToFile(true); | |
853 if (!set_stream_to_file_ok) { | |
854 return EPERM; | |
855 } | |
856 | |
857 bool append_data_to_body_ok = | |
858 request.AppendDataToBody(request_body_data, request_body_size); | |
859 if (!append_data_to_body_ok) { | |
860 return EPERM; | |
861 } | |
862 | |
863 int32_t err = loader.Open(request, pp::BlockUntilComplete()); | |
864 if (err < 0) { | |
865 return PPERROR_TO_ERRNO(err); | |
866 } | |
867 | |
868 pp::URLResponseInfo response = loader.GetResponseInfo(); | |
869 if (response.GetStatusCode() != 200) { | |
870 return EPERM; | |
871 } | |
872 | |
873 return 0; | |
874 } | |
875 | |
876 Error CreateEmptyFile() { | |
877 std::string url = | |
878 "https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart"; | |
879 | |
880 GoogleDriveFs* googledrivefs = dynamic_cast<GoogleDriveFs*>(filesystem_); | |
881 if (googledrivefs == NULL) { | |
882 return EINVAL; | |
883 } | |
884 | |
885 pp::URLLoader loader(pp::InstanceHandle(googledrivefs->instance())); | |
886 pp::URLRequestInfo request(pp::InstanceHandle(googledrivefs->instance())); | |
887 | |
888 bool set_url_ok = request.SetURL(url); | |
889 if (!set_url_ok) { | |
890 return EPERM; | |
891 } | |
892 | |
893 bool set_method_ok = request.SetMethod("POST"); | |
894 if (!set_method_ok) { | |
895 return EPERM; | |
896 } | |
897 | |
898 std::string BOUNDARY_VALUE = "foo_bar_baz"; | |
899 | |
900 std::map<std::string, std::string> headers_map; | |
901 headers_map["Content-type"] = | |
902 "multipart/related; boundary=" + BOUNDARY_VALUE; | |
903 std::string authorization_value = "Bearer "; | |
904 authorization_value += googledrivefs->token(); | |
905 headers_map["Authorization"] = authorization_value; | |
906 | |
907 std::string headers = MapToHeaders(headers_map); | |
908 | |
909 bool set_headers_ok = request.SetHeaders(headers); | |
910 if (!set_headers_ok) { | |
911 return EPERM; | |
912 } | |
913 | |
914 bool set_allow_cross_origin_requests_ok = | |
915 request.SetAllowCrossOriginRequests(true); | |
916 if (!set_allow_cross_origin_requests_ok) { | |
917 return EPERM; | |
918 } | |
919 | |
920 bool set_stream_to_file_ok = request.SetStreamToFile(true); | |
921 if (!set_stream_to_file_ok) { | |
922 return EPERM; | |
923 } | |
924 | |
925 std::string request_body = "--"; | |
926 request_body += BOUNDARY_VALUE; | |
927 request_body += "\n"; | |
928 | |
929 request_body += "Content-Type: application/json; charset=UTF-8"; | |
930 request_body += "\n"; | |
931 | |
932 request_body += "\n"; | |
933 | |
934 request_body += "{"; | |
935 request_body += "\n"; | |
936 | |
937 request_body += " \"name\": "; | |
938 request_body += "\""; | |
939 request_body += path_.Basename(); | |
940 request_body += "\""; | |
941 request_body += ","; | |
942 request_body += "\n"; | |
943 | |
944 request_body += " \"parents\": "; | |
945 request_body += "["; | |
946 request_body += "\n"; | |
947 | |
948 request_body += " \""; | |
949 request_body += parent_dir_id_; | |
950 request_body += "\""; | |
951 request_body += "\n"; | |
952 | |
953 request_body += " ]"; | |
954 request_body += "\n"; | |
955 | |
956 request_body += "}"; | |
957 request_body += "\n"; | |
958 | |
959 request_body += "\n"; | |
960 | |
961 request_body += "--"; | |
962 request_body += BOUNDARY_VALUE; | |
963 request_body += "\n"; | |
964 | |
965 request_body += "Content-Type: text/plain"; | |
966 request_body += "\n"; | |
967 | |
968 request_body += "\n"; | |
969 | |
970 request_body += "\n"; | |
971 | |
972 request_body += "--"; | |
973 request_body += BOUNDARY_VALUE; | |
974 request_body += "--"; | |
975 | |
976 bool append_data_to_body_ok = | |
977 request.AppendDataToBody(request_body.data(), request_body.size()); | |
978 if (!append_data_to_body_ok) { | |
979 return EPERM; | |
980 } | |
981 | |
982 int32_t err = loader.Open(request, pp::BlockUntilComplete()); | |
983 if (err < 0) { | |
984 return PPERROR_TO_ERRNO(err); | |
985 } | |
986 | |
987 pp::URLResponseInfo response = loader.GetResponseInfo(); | |
988 if (response.GetStatusCode() != 200) { | |
989 return EPERM; | |
990 } | |
991 | |
992 return 0; | |
993 } | |
994 | |
995 Error RequestDirent(std::vector<std::string>& dirent_names) { | |
996 std::string url = "https://www.googleapis.com/drive/v3/files"; | |
997 url += "?"; | |
998 url += "q="; | |
999 url += "%27"; | |
1000 url += item_id_; | |
1001 url += "%27+in+parents"; | |
1002 | |
1003 GoogleDriveFs* googledrivefs = dynamic_cast<GoogleDriveFs*>(filesystem_); | |
1004 if (googledrivefs == NULL) { | |
1005 return EINVAL; | |
1006 } | |
1007 | |
1008 pp::URLLoader loader(pp::InstanceHandle(googledrivefs->instance())); | |
1009 pp::URLRequestInfo request(pp::InstanceHandle(googledrivefs->instance())); | |
1010 | |
1011 bool set_url_ok = request.SetURL(url); | |
1012 if (!set_url_ok) { | |
1013 return EPERM; | |
1014 } | |
1015 | |
1016 bool set_method_ok = request.SetMethod("GET"); | |
1017 if (!set_method_ok) { | |
1018 return EPERM; | |
1019 } | |
1020 | |
1021 std::map<std::string, std::string> headers_map; | |
1022 headers_map["Content-type"] = "application/json"; | |
1023 std::string authorization_value = "Bearer "; | |
1024 authorization_value += googledrivefs->token(); | |
1025 headers_map["Authorization"] = authorization_value; | |
1026 | |
1027 std::string headers = MapToHeaders(headers_map); | |
1028 | |
1029 bool set_headers_ok = request.SetHeaders(headers); | |
1030 if (!set_headers_ok) { | |
1031 return EPERM; | |
1032 } | |
1033 | |
1034 bool set_allow_cross_origin_requests_ok = | |
1035 request.SetAllowCrossOriginRequests(true); | |
1036 if (!set_allow_cross_origin_requests_ok) { | |
1037 return EPERM; | |
1038 } | |
1039 | |
1040 bool set_stream_to_file_ok = request.SetStreamToFile(true); | |
1041 if (!set_stream_to_file_ok) { | |
1042 return EPERM; | |
1043 } | |
1044 | |
1045 int32_t err = loader.Open(request, pp::BlockUntilComplete()); | |
1046 if (err < 0) { | |
1047 return PPERROR_TO_ERRNO(err); | |
1048 } | |
1049 | |
1050 pp::URLResponseInfo response = loader.GetResponseInfo(); | |
1051 if (response.GetStatusCode() != 200) { | |
1052 return EPERM; | |
1053 } | |
1054 | |
1055 pp::FileRef file_ref = response.GetBodyAsFileRef(); | |
1056 pp::FileIO file_io(pp::InstanceHandle(googledrivefs->instance())); | |
1057 | |
1058 int32_t open_result = | |
1059 file_io.Open(file_ref, PP_FILEOPENFLAG_READ, pp::BlockUntilComplete()); | |
1060 if (open_result < 0) { | |
1061 return PPERROR_TO_ERRNO(open_result); | |
1062 } | |
1063 | |
1064 std::string output = ""; | |
1065 int BUFFER_SIZE = 1024; | |
1066 char buffer[BUFFER_SIZE]; | |
1067 int byte_read = | |
1068 file_io.Read(0, buffer, BUFFER_SIZE, pp::BlockUntilComplete()); | |
1069 | |
1070 while (byte_read == 0) { | |
1071 #ifdef WIN32 | |
1072 Sleep(1000); | |
1073 #else | |
1074 usleep(1000000); | |
1075 #endif | |
1076 | |
1077 byte_read = | |
1078 file_io.Read(0, buffer, BUFFER_SIZE, pp::BlockUntilComplete()); | |
1079 } | |
1080 | |
1081 while (byte_read > 0) { | |
1082 output += buffer; | |
1083 | |
1084 byte_read = file_io.Read(byte_read, buffer, BUFFER_SIZE, | |
1085 pp::BlockUntilComplete()); | |
1086 } | |
1087 | |
1088 if (byte_read < 0) { | |
1089 return PPERROR_TO_ERRNO(byte_read); | |
1090 } | |
1091 | |
1092 Json::Value root; | |
1093 | |
1094 Json::Reader reader(Json::Features::strictMode()); | |
1095 if (!reader.parse(output, root, false)) { | |
1096 return EPERM; | |
1097 } | |
1098 | |
1099 if (!root.isMember("files")) { | |
1100 return EPERM; | |
1101 } | |
1102 | |
1103 Json::Value files_array = root["files"]; | |
1104 | |
1105 if (!files_array.isArray()) { | |
1106 return EPERM; | |
1107 } | |
1108 | |
1109 for (unsigned int i = 0; i < files_array.size(); ++i) { | |
1110 dirent_names.push_back(files_array[i]["name"].asString()); | |
1111 } | |
1112 | |
1113 // TODO: Too many entries result in nextPageToken in API response and | |
1114 // out-of-memory in output variable. | |
1115 | |
1116 return 0; | |
1117 } | |
1118 | |
1119 std::string parent_dir_id_; | |
1120 std::string item_id_; | |
1121 bool is_dir_item_; | |
1122 Path path_; | |
1123 | |
1124 friend class GoogleDriveFs; | |
1125 }; | |
1126 | |
1127 GoogleDriveFs::GoogleDriveFs() {} | |
1128 | |
1129 GoogleDriveFs::~GoogleDriveFs() {} | |
1130 | |
1131 Error GoogleDriveFs::Init(const FsInitArgs& args) { | |
1132 Error error = Filesystem::Init(args); | |
1133 if (error) { | |
1134 return error; | |
1135 } | |
1136 | |
1137 std::map<std::string, std::string>::const_iterator instance_it = | |
1138 args.string_map.find("instance"); | |
1139 | |
1140 if (instance_it == args.string_map.end()) { | |
1141 return EINVAL; | |
1142 } | |
1143 | |
1144 instance_ = atoi(instance_it->second.c_str()); | |
1145 | |
1146 std::map<std::string, std::string>::const_iterator token_it = | |
1147 args.string_map.find("token"); | |
1148 | |
1149 if (token_it == args.string_map.end()) { | |
1150 return EINVAL; | |
1151 } | |
1152 | |
1153 token_ = token_it->second; | |
1154 | |
1155 return 0; | |
1156 } | |
1157 | |
1158 void GoogleDriveFs::Destroy() {} | |
1159 | |
1160 Error GoogleDriveFs::OpenWithMode(const Path& path, | |
1161 int open_flags, | |
1162 mode_t mode, | |
1163 ScopedNode* out_node) { | |
1164 ScopedNode node(new GoogleDriveFsNode(this, path)); | |
1165 | |
1166 Error error = node->Init(open_flags); | |
1167 if (error) { | |
1168 return error; | |
1169 } | |
1170 | |
1171 *out_node = node; | |
1172 | |
1173 return 0; | |
1174 } | |
1175 | |
1176 Error GoogleDriveFs::Rename(const Path& path, const Path& newPath) { | |
1177 LOG_ERROR("rename not supported."); | |
1178 return EPERM; | |
1179 } | |
1180 | |
1181 Error GoogleDriveFs::Unlink(const Path& path) { | |
1182 LOG_ERROR("unlink not supported."); | |
1183 return EPERM; | |
1184 } | |
1185 | |
1186 Error GoogleDriveFs::Mkdir(const Path& path, int permissions) { | |
1187 std::string parent_dir_id = ""; | |
1188 Error error = RequestParentDirId(path, this, parent_dir_id); | |
1189 if (error) { | |
1190 return error; | |
1191 } | |
1192 | |
1193 std::string item_id = ""; | |
1194 error = RequestItemId(parent_dir_id, path.Basename(), this, item_id); | |
1195 | |
1196 // mkdir does not create a directory when a file with path.Basename() | |
1197 // already exists | |
1198 if (error == ENOENT) { | |
1199 std::string url = "https://www.googleapis.com/drive/v3/files"; | |
1200 | |
1201 pp::URLLoader loader(pp::InstanceHandle(this->instance())); | |
1202 pp::URLRequestInfo request(pp::InstanceHandle(this->instance())); | |
1203 | |
1204 bool set_url_ok = request.SetURL(url); | |
1205 if (!set_url_ok) { | |
1206 return EPERM; | |
1207 } | |
1208 | |
1209 bool set_method_ok = request.SetMethod("POST"); | |
1210 if (!set_method_ok) { | |
1211 return EPERM; | |
1212 } | |
1213 | |
1214 std::map<std::string, std::string> headers_map; | |
1215 headers_map["Content-type"] = "application/json"; | |
1216 std::string authorization_value = "Bearer "; | |
1217 authorization_value += token_; | |
1218 headers_map["Authorization"] = authorization_value; | |
1219 | |
1220 std::string headers = MapToHeaders(headers_map); | |
1221 | |
1222 bool set_headers_ok = request.SetHeaders(headers); | |
1223 if (!set_headers_ok) { | |
1224 return EPERM; | |
1225 } | |
1226 | |
1227 Json::Value json_value; | |
1228 json_value["name"] = path.Basename(); | |
1229 json_value["mimeType"] = "application/vnd.google-apps.folder"; | |
1230 Json::FastWriter fast_writer; | |
1231 std::string request_body = fast_writer.write(json_value); | |
1232 | |
1233 bool append_data_to_body_ok = | |
1234 request.AppendDataToBody(request_body.data(), request_body.size()); | |
1235 if (!append_data_to_body_ok) { | |
1236 return EPERM; | |
1237 } | |
1238 | |
1239 bool set_allow_cross_origin_requests_ok = | |
1240 request.SetAllowCrossOriginRequests(true); | |
1241 if (!set_allow_cross_origin_requests_ok) { | |
1242 return EPERM; | |
1243 } | |
1244 | |
1245 bool set_stream_to_file_ok = request.SetStreamToFile(true); | |
1246 if (!set_stream_to_file_ok) { | |
1247 return EPERM; | |
1248 } | |
1249 | |
1250 int32_t err = loader.Open(request, pp::BlockUntilComplete()); | |
1251 if (err < 0) { | |
1252 return PPERROR_TO_ERRNO(err); | |
1253 } | |
1254 | |
1255 pp::URLResponseInfo response = loader.GetResponseInfo(); | |
1256 if (response.GetStatusCode() != 200) { | |
1257 return EPERM; | |
1258 } | |
1259 | |
1260 return 0; | |
1261 } | |
1262 | |
1263 return EEXIST; | |
1264 } | |
1265 | |
1266 Error GoogleDriveFs::Rmdir(const Path& path) { | |
1267 std::string parent_dir_id = ""; | |
1268 Error error = RequestParentDirId(path, this, parent_dir_id); | |
1269 if (error) { | |
1270 return error; | |
1271 } | |
1272 | |
1273 std::string dir_id = ""; | |
1274 error = RequestDirId(parent_dir_id, path.Basename(), this, dir_id); | |
1275 if (error) { | |
1276 return error; | |
1277 } | |
1278 | |
1279 std::string url = "https://www.googleapis.com/drive/v3/files"; | |
1280 | |
1281 url += "/"; | |
1282 url += dir_id; | |
1283 | |
1284 pp::URLLoader loader(pp::InstanceHandle(this->instance())); | |
1285 pp::URLRequestInfo request(pp::InstanceHandle(this->instance())); | |
1286 | |
1287 bool set_url_ok = request.SetURL(url); | |
1288 if (!set_url_ok) { | |
1289 return EPERM; | |
1290 } | |
1291 bool set_method_ok = request.SetMethod("DELETE"); | |
1292 if (!set_method_ok) { | |
1293 return EPERM; | |
1294 } | |
1295 | |
1296 std::map<std::string, std::string> headers_map; | |
1297 headers_map["Content-type"] = "application/json"; | |
1298 std::string authorization_value = "Bearer "; | |
1299 authorization_value += token_; | |
1300 headers_map["Authorization"] = authorization_value; | |
1301 | |
1302 std::string headers = MapToHeaders(headers_map); | |
1303 | |
1304 bool set_headers_ok = request.SetHeaders(headers); | |
1305 if (!set_headers_ok) { | |
1306 return EPERM; | |
1307 } | |
1308 | |
1309 bool set_allow_cross_origin_requests_ok = | |
1310 request.SetAllowCrossOriginRequests(true); | |
1311 if (!set_allow_cross_origin_requests_ok) { | |
1312 return EPERM; | |
1313 } | |
1314 | |
1315 bool set_stream_to_file_ok = request.SetStreamToFile(true); | |
1316 if (!set_stream_to_file_ok) { | |
1317 return EPERM; | |
1318 } | |
1319 | |
1320 int32_t err = loader.Open(request, pp::BlockUntilComplete()); | |
1321 if (err < 0) { | |
1322 return PPERROR_TO_ERRNO(err); | |
1323 } | |
1324 | |
1325 pp::URLResponseInfo response = loader.GetResponseInfo(); | |
1326 if (response.GetStatusCode() != 204) { | |
1327 return EPERM; | |
1328 } | |
1329 | |
1330 return 0; | |
1331 } | |
1332 | |
1333 Error GoogleDriveFs::Remove(const Path& path) { | |
1334 LOG_ERROR("remove not supported."); | |
1335 return EPERM; | |
1336 } | |
1337 | |
1338 std::string GoogleDriveFs::token() { | |
1339 return token_; | |
1340 } | |
1341 | |
1342 PP_Instance GoogleDriveFs::instance() { | |
1343 return instance_; | |
1344 } | |
1345 | |
1346 } // namespace nacl_io | |
OLD | NEW |