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_node.h" | |
6 | |
7 #include <stdio.h> | |
8 #include <time.h> | |
9 | |
10 #include <algorithm> | |
11 | |
12 #include "ppapi/c/pp_completion_callback.h" | |
13 | |
14 #include "nacl_io/error.h" | |
15 #include "nacl_io/filesystem.h" | |
16 #include "nacl_io/getdents_helper.h" | |
17 #include "nacl_io/hash.h" | |
18 #include "nacl_io/kernel_handle.h" | |
19 #include "nacl_io/pepper_interface.h" | |
20 #include "nacl_io/statuscode.h" | |
21 #include "nacl_io/googledrivefs/googledrivefs.h" | |
22 #include "nacl_io/googledrivefs/googledrivefs_util.h" | |
23 | |
24 namespace nacl_io { | |
25 | |
26 GoogleDriveFsNode::GoogleDriveFsNode(Filesystem* filesystem, Path path) | |
27 : Node(filesystem), path_(path) {} | |
28 | |
29 Error GoogleDriveFsNode::GetDents(size_t offs, | |
30 struct dirent* pdir, | |
31 size_t size, | |
32 int* out_bytes) { | |
33 *out_bytes = 0; | |
34 | |
35 if (!IsaDir()) { | |
36 return ENOTDIR; | |
37 } | |
38 | |
39 const ino_t kCurDirIno = -1; | |
40 const ino_t kParentDirIno = -2; | |
41 GetDentsHelper helper(kCurDirIno, kParentDirIno); | |
42 | |
43 std::vector<std::string> dirent_names; | |
44 Error error = RequestDirent(&dirent_names); | |
45 if (error) { | |
46 return error; | |
47 } | |
48 | |
49 for (size_t i = 0; i < dirent_names.size(); ++i) { | |
50 Path child_path(path_); | |
51 child_path = child_path.Append("/" + dirent_names[i]); | |
52 ino_t child_ino = HashPath(child_path); | |
53 | |
54 helper.AddDirent(child_ino, dirent_names[i].c_str(), | |
55 dirent_names[i].size()); | |
56 } | |
57 | |
58 return helper.GetDents(offs, pdir, size, out_bytes); | |
59 } | |
60 | |
61 Error GoogleDriveFsNode::GetStat(struct stat* pstat) { | |
62 Error error = GetSize(&pstat->st_size); | |
63 if (error) { | |
64 return error; | |
65 } | |
66 | |
67 error = GetModifiedTime(&pstat->st_mtime); | |
68 if (error) { | |
69 return error; | |
70 } | |
71 | |
72 pstat->st_atime = 0; | |
73 pstat->st_ctime = 0; | |
74 | |
75 pstat->st_mode = stat_.st_mode; | |
76 | |
77 return 0; | |
78 } | |
79 | |
80 Error GoogleDriveFsNode::Write(const HandleAttr& attr, | |
81 const void* buf, | |
82 size_t count, | |
83 int* out_bytes) { | |
84 *out_bytes = 0; | |
85 | |
86 if (IsaDir()) { | |
87 return EISDIR; | |
88 } | |
89 if ((GetMode() & S_IWRITE) == 0) { | |
90 return EACCES; | |
91 } | |
92 | |
93 off_t file_size = 0; | |
94 Error error = GetSize(&file_size); | |
95 if (error) { | |
96 return error; | |
97 } | |
98 | |
99 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
| |
100 (unsigned long long int)attr.offs + count); | |
101 | |
102 // use std::string for storing data in the heap, as the size of stack | |
103 // is measured in megabytes, disallowing files larger than that. | |
104 std::string file_buffer(file_buffer_size, '\0'); | |
105 | |
106 if (file_size > 0) { | |
107 int read_helper_out_bytes = 0; | |
108 error = ReadHelper(0, file_size - 1, &file_buffer, &read_helper_out_bytes); | |
109 | |
110 if (error) { | |
111 return error; | |
112 } | |
113 } | |
114 | |
115 char* pChar = (char*)buf; | |
116 for (size_t i = 0; i < count; ++i) { | |
117 file_buffer[attr.offs + i] = pChar[i]; | |
118 } | |
119 | |
120 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
| |
121 if (error) { | |
122 return error; | |
123 } | |
124 | |
125 *out_bytes = count; | |
126 | |
127 return 0; | |
128 } | |
129 | |
130 Error GoogleDriveFsNode::FTruncate(off_t length) { | |
131 if (IsaDir()) { | |
132 return EISDIR; | |
133 } | |
134 | |
135 off_t file_size = 0; | |
136 Error error = GetSize(&file_size); | |
137 if (error) { | |
138 return error; | |
139 } | |
140 | |
141 std::string file_buffer(length, '\0'); | |
142 | |
143 if (file_size > 0) { | |
144 int read_helper_out_bytes = 0; | |
145 off_t read_end = std::min(length, file_size); | |
146 error = ReadHelper(0, read_end - 1, &file_buffer, &read_helper_out_bytes); | |
147 | |
148 if (error) { | |
149 return error; | |
150 } | |
151 } | |
152 | |
153 error = WriteHelper(file_buffer.c_str(), length); | |
154 if (error) { | |
155 return error; | |
156 } | |
157 | |
158 return 0; | |
159 } | |
160 | |
161 Error GoogleDriveFsNode::Read(const HandleAttr& attr, | |
162 void* buf, | |
163 size_t count, | |
164 int* out_bytes) { | |
165 *out_bytes = 0; | |
166 | |
167 if (IsaDir()) { | |
168 return EISDIR; | |
169 } | |
170 if ((GetMode() & S_IREAD) == 0) { | |
171 return EACCES; | |
172 } | |
173 | |
174 std::string file_buffer(count, '\0'); | |
175 | |
176 Error error = | |
177 ReadHelper(attr.offs, attr.offs + count - 1, &file_buffer, out_bytes); | |
178 if (error) { | |
179 return error; | |
180 } | |
181 | |
182 char* pChar = (char*)buf; | |
183 for (size_t i = 0; i < count; ++i) { | |
184 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
| |
185 } | |
186 | |
187 return 0; | |
188 } | |
189 | |
190 Error GoogleDriveFsNode::GetSize(off_t* out_size) { | |
191 *out_size = 0; | |
192 | |
193 GoogleDriveFs* googledrivefs = static_cast<GoogleDriveFs*>(filesystem_); | |
194 | |
195 URLLoaderInterface* url_loader_iface = | |
196 googledrivefs->ppapi()->GetURLLoaderInterface(); | |
197 PP_Resource url_loader_object = | |
198 url_loader_iface->Create(googledrivefs->instance()); | |
199 URLRequestInfoInterface* url_request_info_iface = | |
200 googledrivefs->ppapi()->GetURLRequestInfoInterface(); | |
201 PP_Resource url_request_info_object = | |
202 url_request_info_iface->Create(googledrivefs->instance()); | |
203 PP_Resource url_response_info_object = 0; | |
204 Error error(0); | |
205 static const char base_url[] = "https://www.googleapis.com/drive/v3/files"; | |
206 RequestUrlParams p; | |
207 std::string output; | |
208 std::string size_value; | |
209 int size_index; | |
210 | |
211 if (IsaDir()) { | |
212 goto done; | |
213 } | |
214 | |
215 p.url = base_url; | |
216 AddUrlPath(item_id_, &p.url); | |
217 AddUrlFirstQueryParameter("fields", "size", &p.url); | |
218 | |
219 p.method = "GET"; | |
220 | |
221 p.headers = ""; | |
222 | |
223 AddHeaders("Content-type", "application/json", &p.headers); | |
224 AddHeaders("Authorization", "Bearer " + googledrivefs->token(), &p.headers); | |
225 | |
226 error = MakeRequest(googledrivefs->ppapi(), url_loader_object, | |
227 url_request_info_object, p); | |
228 | |
229 if (error) { | |
230 goto done; | |
231 } | |
232 | |
233 error = FinishPreparingResponse(googledrivefs->ppapi(), url_loader_object, | |
234 &url_response_info_object); | |
235 | |
236 if (error) { | |
237 goto done; | |
238 } | |
239 | |
240 if (ReadStatusCode(googledrivefs->ppapi(), url_response_info_object) != | |
241 STATUSCODE_OK) { | |
242 error = EPERM; | |
243 goto done; | |
244 } | |
245 | |
246 error = ReadResponseBody(googledrivefs->ppapi(), googledrivefs->instance(), | |
247 url_response_info_object, INT_MAX, &output); | |
248 if (error) { | |
249 goto done; | |
250 } | |
251 | |
252 GetValue(output, "size", 0, &size_value, &size_index); | |
253 if (size_index == -1) { | |
254 // in a STATUSCODE_OK response, size of a directory is not written. | |
255 size_value = "0"; | |
256 } | |
257 | |
258 *out_size = (off_t)atoi(size_value.c_str()); | |
259 | |
260 done: | |
261 if (url_loader_object) { | |
262 googledrivefs->ppapi()->ReleaseResource(url_loader_object); | |
263 } | |
264 if (url_request_info_object) { | |
265 googledrivefs->ppapi()->ReleaseResource(url_request_info_object); | |
266 } | |
267 if (url_response_info_object) { | |
268 googledrivefs->ppapi()->ReleaseResource(url_response_info_object); | |
269 } | |
270 | |
271 return error; | |
272 } | |
273 | |
274 Error GoogleDriveFsNode::Init(int open_flags) { | |
275 Error error = Node::Init(open_flags); | |
276 | |
277 if (error) { | |
278 return error; | |
279 } | |
280 | |
281 if (path_.Size() == 1) { | |
282 parent_dir_id_ = ""; | |
283 item_id_ = "root"; | |
284 SetType(S_IFDIR); | |
285 SetMode(S_IREAD); | |
286 return 0; | |
287 } | |
288 | |
289 error = RequestParentDirId(path_, filesystem_, &parent_dir_id_); | |
290 if (error) { | |
291 return error; | |
292 } | |
293 | |
294 // Request the ID of an item, which is a file or a directory | |
295 error = | |
296 RequestItemId(parent_dir_id_, path_.Basename(), filesystem_, &item_id_); | |
297 | |
298 if (error == ENOENT) { | |
299 // Only files are open as mode O_CREAT | |
300 if ((open_flags & O_CREAT) != 0) { | |
301 error = CreateEmptyFile(); | |
302 if (error) { | |
303 return error; | |
304 } | |
305 error = RequestItemId(parent_dir_id_, path_.Basename(), filesystem_, | |
306 &item_id_); | |
307 if (error) { | |
308 return error; | |
309 } | |
310 SetType(S_IFREG); | |
311 if ((open_flags & O_RDWR) != 0) { | |
312 SetMode(S_IREAD | S_IWRITE); | |
313 } else if ((open_flags & O_WRONLY) != 0) { | |
314 SetMode(S_IWRITE); | |
315 } else { | |
316 SetMode(S_IREAD); | |
317 } | |
318 } else { | |
319 return ENOENT; | |
320 } | |
321 } else if (error) { | |
322 return error; | |
323 } else { | |
324 std::string dir_id = ""; | |
325 error = | |
326 RequestDirId(parent_dir_id_, path_.Basename(), filesystem_, &dir_id); | |
327 if (error == ENOENT) { | |
328 SetType(S_IFREG); | |
329 if ((open_flags & O_RDWR) != 0) { | |
330 SetMode(S_IREAD | S_IWRITE); | |
331 } else if ((open_flags & O_WRONLY) != 0) { | |
332 SetMode(S_IWRITE); | |
333 } else { | |
334 SetMode(S_IREAD); | |
335 } | |
336 } else if (error) { | |
337 return error; | |
338 } else { | |
339 SetType(S_IFDIR); | |
340 SetMode(S_IREAD); | |
341 } | |
342 | |
343 if (open_flags == 0) { | |
344 // open_flags == 0 for file opened on fopen with mode r and | |
345 // directory opened on opendir | |
346 return 0; | |
347 } else if (IsaDir()) { | |
348 return EPERM; | |
349 } else if ((open_flags & O_TRUNC) != 0) { | |
350 error = WriteHelper(NULL, 0); | |
351 if (error) { | |
352 return error; | |
353 } | |
354 } | |
355 } | |
356 | |
357 return 0; | |
358 } | |
359 | |
360 void GoogleDriveFsNode::Destroy() { | |
361 Node::Destroy(); | |
362 } | |
363 | |
364 Error GoogleDriveFsNode::ReadHelper(off_t start, | |
365 off_t end, | |
366 std::string* out_string_buffer, | |
367 int* out_bytes) { | |
368 (*out_string_buffer)[0] = '\0'; | |
369 *out_bytes = 0; | |
370 | |
371 GoogleDriveFs* googledrivefs = static_cast<GoogleDriveFs*>(filesystem_); | |
372 | |
373 URLLoaderInterface* url_loader_iface = | |
374 googledrivefs->ppapi()->GetURLLoaderInterface(); | |
375 PP_Resource url_loader_object = | |
376 url_loader_iface->Create(googledrivefs->instance()); | |
377 URLRequestInfoInterface* url_request_info_iface = | |
378 googledrivefs->ppapi()->GetURLRequestInfoInterface(); | |
379 PP_Resource url_request_info_object = | |
380 url_request_info_iface->Create(googledrivefs->instance()); | |
381 PP_Resource url_response_info_object = 0; | |
382 Error error(EPERM); | |
383 static const char base_url[] = | |
384 "https://www.googleapis.com/download/drive/v3/files"; | |
385 RequestUrlParams p; | |
386 char range_value_buffer[1024]; | |
387 int char_written = 0; | |
388 int status_code = 0; | |
389 std::string output; | |
390 | |
391 p.url = base_url; | |
392 AddUrlPath(item_id_, &p.url); | |
393 AddUrlFirstQueryParameter("alt", "media", &p.url); | |
394 | |
395 p.method = "GET"; | |
396 | |
397 p.headers = ""; | |
398 | |
399 AddHeaders("Content-type", "application/json", &p.headers); | |
400 AddHeaders("Authorization", "Bearer " + googledrivefs->token(), &p.headers); | |
401 | |
402 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.
| |
403 (long long int)start, (long long int)end); | |
404 if (char_written < 0) { | |
405 error = EPERM; | |
406 goto done; | |
407 } | |
408 | |
409 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.
| |
410 | |
411 error = MakeRequest(googledrivefs->ppapi(), url_loader_object, | |
412 url_request_info_object, p); | |
413 | |
414 if (error) { | |
415 goto done; | |
416 } | |
417 | |
418 error = FinishPreparingResponse(googledrivefs->ppapi(), url_loader_object, | |
419 &url_response_info_object); | |
420 | |
421 if (error) { | |
422 goto done; | |
423 } | |
424 | |
425 status_code = | |
426 ReadStatusCode(googledrivefs->ppapi(), url_response_info_object); | |
427 | |
428 if (status_code == STATUSCODE_OK || | |
429 status_code == STATUSCODE_PARTIAL_CONTENT) { | |
430 error = | |
431 ReadResponseBody(googledrivefs->ppapi(), googledrivefs->instance(), | |
432 url_response_info_object, end - start + 1, &output); | |
433 | |
434 if (error) { | |
435 goto done; | |
436 } | |
437 | |
438 for (size_t i = 0; i < output.size(); ++i) { | |
439 (*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
| |
440 } | |
441 | |
442 *out_bytes = output.size(); | |
443 | |
444 error = 0; | |
445 goto done; | |
446 } else if (status_code == STATUSCODE_REQUESTED_RANGE_NOT_SATISFIABLE) { | |
447 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
| |
448 goto done; | |
449 } | |
450 | |
451 done: | |
452 if (url_loader_object) { | |
453 googledrivefs->ppapi()->ReleaseResource(url_loader_object); | |
454 } | |
455 if (url_request_info_object) { | |
456 googledrivefs->ppapi()->ReleaseResource(url_request_info_object); | |
457 } | |
458 if (url_response_info_object) { | |
459 googledrivefs->ppapi()->ReleaseResource(url_response_info_object); | |
460 } | |
461 | |
462 return error; | |
463 } | |
464 | |
465 Error GoogleDriveFsNode::WriteHelper(const char* body_data, | |
466 uint32_t body_size) { | |
467 GoogleDriveFs* googledrivefs = static_cast<GoogleDriveFs*>(filesystem_); | |
468 | |
469 URLLoaderInterface* url_loader_iface = | |
470 googledrivefs->ppapi()->GetURLLoaderInterface(); | |
471 PP_Resource url_loader_object = | |
472 url_loader_iface->Create(googledrivefs->instance()); | |
473 URLRequestInfoInterface* url_request_info_iface = | |
474 googledrivefs->ppapi()->GetURLRequestInfoInterface(); | |
475 PP_Resource url_request_info_object = | |
476 url_request_info_iface->Create(googledrivefs->instance()); | |
477 PP_Resource url_response_info_object = 0; | |
478 Error error(0); | |
479 static const char base_url[] = | |
480 "https://www.googleapis.com/upload/drive/v3/files"; | |
481 RequestUrlParams p; | |
482 | |
483 p.url = base_url; | |
484 AddUrlPath(item_id_, &p.url); | |
485 AddUrlFirstQueryParameter("uploadType", "media", &p.url); | |
486 | |
487 p.method = "PATCH"; | |
488 | |
489 p.headers = ""; | |
490 | |
491 AddHeaders("Content-type", "application/json", &p.headers); | |
492 AddHeaders("Authorization", "Bearer " + googledrivefs->token(), &p.headers); | |
493 | |
494 p.body = std::string(body_data, body_size); | |
495 | |
496 error = MakeRequest(googledrivefs->ppapi(), url_loader_object, | |
497 url_request_info_object, p); | |
498 | |
499 if (error) { | |
500 goto done; | |
501 } | |
502 | |
503 error = FinishPreparingResponse(googledrivefs->ppapi(), url_loader_object, | |
504 &url_response_info_object); | |
505 | |
506 if (error) { | |
507 goto done; | |
508 } | |
509 | |
510 if (ReadStatusCode(googledrivefs->ppapi(), url_response_info_object) != | |
511 STATUSCODE_OK) { | |
512 error = EPERM; | |
513 goto done; | |
514 } | |
515 | |
516 done: | |
517 if (url_loader_object) { | |
518 googledrivefs->ppapi()->ReleaseResource(url_loader_object); | |
519 } | |
520 if (url_request_info_object) { | |
521 googledrivefs->ppapi()->ReleaseResource(url_request_info_object); | |
522 } | |
523 if (url_response_info_object) { | |
524 googledrivefs->ppapi()->ReleaseResource(url_response_info_object); | |
525 } | |
526 | |
527 return error; | |
528 } | |
529 | |
530 Error GoogleDriveFsNode::GetModifiedTime(time_t* out_mtime) { | |
531 GoogleDriveFs* googledrivefs = static_cast<GoogleDriveFs*>(filesystem_); | |
532 | |
533 URLLoaderInterface* url_loader_iface = | |
534 googledrivefs->ppapi()->GetURLLoaderInterface(); | |
535 PP_Resource url_loader_object = | |
536 url_loader_iface->Create(googledrivefs->instance()); | |
537 URLRequestInfoInterface* url_request_info_iface = | |
538 googledrivefs->ppapi()->GetURLRequestInfoInterface(); | |
539 PP_Resource url_request_info_object = | |
540 url_request_info_iface->Create(googledrivefs->instance()); | |
541 PP_Resource url_response_info_object = 0; | |
542 Error error(0); | |
543 static const char base_url[] = "https://www.googleapis.com/drive/v3/files"; | |
544 RequestUrlParams p; | |
545 std::string output; | |
546 std::string modified_time_value = ""; | |
547 int modified_time_index = 0; | |
548 struct tm timeinfo; | |
549 | |
550 p.url = base_url; | |
551 AddUrlPath(item_id_, &p.url); | |
552 AddUrlFirstQueryParameter("fields", "modifiedTime", &p.url); | |
553 | |
554 p.method = "GET"; | |
555 | |
556 p.headers = ""; | |
557 | |
558 AddHeaders("Content-type", "application/json", &p.headers); | |
559 AddHeaders("Authorization", "Bearer " + googledrivefs->token(), &p.headers); | |
560 | |
561 error = MakeRequest(googledrivefs->ppapi(), url_loader_object, | |
562 url_request_info_object, p); | |
563 | |
564 if (error) { | |
565 goto done; | |
566 } | |
567 | |
568 error = FinishPreparingResponse(googledrivefs->ppapi(), url_loader_object, | |
569 &url_response_info_object); | |
570 | |
571 if (error) { | |
572 goto done; | |
573 } | |
574 | |
575 if (ReadStatusCode(googledrivefs->ppapi(), url_response_info_object) != | |
576 STATUSCODE_OK) { | |
577 error = EPERM; | |
578 goto done; | |
579 } | |
580 | |
581 error = ReadResponseBody(googledrivefs->ppapi(), googledrivefs->instance(), | |
582 url_response_info_object, INT_MAX, &output); | |
583 if (error) { | |
584 goto done; | |
585 } | |
586 | |
587 // the value of modifiedTime is assumed to be always in the STATUSCODE_OK | |
588 // response. | |
589 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(
| |
590 &modified_time_index); | |
591 | |
592 timeinfo.tm_year = atoi(modified_time_value.substr(0, 4).c_str()); | |
593 timeinfo.tm_mon = atoi(modified_time_value.substr(5, 2).c_str()); | |
594 timeinfo.tm_mday = atoi(modified_time_value.substr(8, 2).c_str()); | |
595 timeinfo.tm_hour = atoi(modified_time_value.substr(11, 2).c_str()); | |
596 timeinfo.tm_min = atoi(modified_time_value.substr(14, 2).c_str()); | |
597 timeinfo.tm_sec = atoi(modified_time_value.substr(17, 2).c_str()); | |
598 timeinfo.tm_isdst = 0; | |
599 | |
600 *out_mtime = mktime(&timeinfo); | |
601 | |
602 done: | |
603 if (url_loader_object) { | |
604 googledrivefs->ppapi()->ReleaseResource(url_loader_object); | |
605 } | |
606 if (url_request_info_object) { | |
607 googledrivefs->ppapi()->ReleaseResource(url_request_info_object); | |
608 } | |
609 if (url_response_info_object) { | |
610 googledrivefs->ppapi()->ReleaseResource(url_response_info_object); | |
611 } | |
612 | |
613 return error; | |
614 } | |
615 | |
616 Error GoogleDriveFsNode::CreateEmptyFile() { | |
617 GoogleDriveFs* googledrivefs = static_cast<GoogleDriveFs*>(filesystem_); | |
618 | |
619 URLLoaderInterface* url_loader_iface = | |
620 googledrivefs->ppapi()->GetURLLoaderInterface(); | |
621 PP_Resource url_loader_object = | |
622 url_loader_iface->Create(googledrivefs->instance()); | |
623 URLRequestInfoInterface* url_request_info_iface = | |
624 googledrivefs->ppapi()->GetURLRequestInfoInterface(); | |
625 PP_Resource url_request_info_object = | |
626 url_request_info_iface->Create(googledrivefs->instance()); | |
627 PP_Resource url_response_info_object = 0; | |
628 Error error(0); | |
629 static const char base_url[] = | |
630 "https://www.googleapis.com/upload/drive/v3/files"; | |
631 RequestUrlParams p; | |
632 std::string BOUNDARY_VALUE = "foo_bar_baz"; | |
633 | |
634 p.url = base_url; | |
635 AddUrlFirstQueryParameter("uploadType", "multipart", &p.url); | |
636 | |
637 p.method = "POST"; | |
638 | |
639 p.headers = ""; | |
640 | |
641 AddHeaders("Content-type", "multipart/related; boundary=" + BOUNDARY_VALUE, | |
642 &p.headers); | |
643 AddHeaders("Authorization", "Bearer " + googledrivefs->token(), &p.headers); | |
644 | |
645 p.body = ""; | |
646 AddBody("--" + BOUNDARY_VALUE, &p.body); | |
647 AddBody("Content-Type: application/json; charset=UTF-8", &p.body); | |
648 AddBody("", &p.body); | |
649 AddBody("{", &p.body); | |
650 AddBody(std::string(" \"name\": \"") + path_.Basename() + std::string("\","), | |
651 &p.body); | |
652 AddBody(" \"parents\": [", &p.body); | |
653 AddBody(" \"" + parent_dir_id_ + "\"", &p.body); | |
654 AddBody(" ]", &p.body); | |
655 AddBody("}", &p.body); | |
656 AddBody("", &p.body); | |
657 AddBody("--" + BOUNDARY_VALUE, &p.body); | |
658 AddBody("Content-Type: text/plain", &p.body); | |
659 AddBody("", &p.body); | |
660 AddBody("", &p.body); | |
661 AddBody("--" + BOUNDARY_VALUE + "--", &p.body); | |
662 | |
663 error = MakeRequest(googledrivefs->ppapi(), url_loader_object, | |
664 url_request_info_object, p); | |
665 | |
666 if (error) { | |
667 goto done; | |
668 } | |
669 | |
670 error = FinishPreparingResponse(googledrivefs->ppapi(), url_loader_object, | |
671 &url_response_info_object); | |
672 | |
673 if (error) { | |
674 goto done; | |
675 } | |
676 | |
677 if (ReadStatusCode(googledrivefs->ppapi(), url_response_info_object) != | |
678 STATUSCODE_OK) { | |
679 error = EPERM; | |
680 goto done; | |
681 } | |
682 | |
683 done: | |
684 if (url_loader_object) { | |
685 googledrivefs->ppapi()->ReleaseResource(url_loader_object); | |
686 } | |
687 if (url_request_info_object) { | |
688 googledrivefs->ppapi()->ReleaseResource(url_request_info_object); | |
689 } | |
690 if (url_response_info_object) { | |
691 googledrivefs->ppapi()->ReleaseResource(url_response_info_object); | |
692 } | |
693 | |
694 return error; | |
695 } | |
696 | |
697 Error GoogleDriveFsNode::RequestDirentHelper( | |
698 const std::string& url, | |
699 std::vector<std::string>* out_dirent_names) { | |
700 std::string response_body; | |
701 Error error = GetListFileResponseBody(url, filesystem_, &response_body); | |
702 if (error) { | |
703 return error; | |
704 } | |
705 | |
706 std::string name_value = ""; | |
707 int name_index = 0; | |
708 | |
709 GetValue(response_body, "name", name_index, &name_value, &name_index); | |
710 | |
711 while (name_index != -1) { | |
712 out_dirent_names->push_back(name_value); | |
713 | |
714 GetValue(response_body, "name", name_index, &name_value, &name_index); | |
715 } | |
716 | |
717 std::string next_page_token_value = ""; | |
718 int next_page_token_index = 0; | |
719 GetValue(response_body, "nextPageToken", 0, &next_page_token_value, | |
720 &next_page_token_index); | |
721 if (next_page_token_index != -1) { | |
722 return RequestDirentWithNextPageToken(next_page_token_value, | |
723 out_dirent_names); | |
724 } | |
725 | |
726 return 0; | |
727 } | |
728 | |
729 Error GoogleDriveFsNode::RequestDirentWithNextPageToken( | |
730 const std::string& next_page_token, | |
731 std::vector<std::string>* out_dirent_names) { | |
732 static const char base_url[] = "https://www.googleapis.com/drive/v3/files"; | |
733 | |
734 std::string url = base_url; | |
735 AddUrlFirstQueryParameter("pageToken", next_page_token, &url); | |
736 AddUrlNextQueryParameter("q", "%27" + item_id_ + "%27+in+parents", &url); | |
737 | |
738 return RequestDirentHelper(url, out_dirent_names); | |
739 } | |
740 | |
741 Error GoogleDriveFsNode::RequestDirent( | |
742 std::vector<std::string>* out_dirent_names) { | |
743 static const char base_url[] = "https://www.googleapis.com/drive/v3/files"; | |
744 | |
745 std::string url = base_url; | |
746 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.
| |
747 | |
748 return RequestDirentHelper(url, out_dirent_names); | |
749 } | |
750 | |
751 } // namespace nacl_io | |
OLD | NEW |