Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(793)

Side by Side Diff: native_client_sdk/src/libraries/nacl_io/googledrivefs/googledrivefs_util.cc

Issue 2156503002: [NaCl SDK] Expose Google Drive to nacl_io. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 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_util.h"
6
7 #include <stdlib.h>
8 #include <string.h>
9
10 #include "ppapi/c/pp_completion_callback.h"
11
12 #include "nacl_io/error.h"
13 #include "nacl_io/filesystem.h"
14 #include "nacl_io/path.h"
15 #include "nacl_io/pepper_interface.h"
16 #include "nacl_io/statuscode.h"
17 #include "nacl_io/googledrivefs/googledrivefs.h"
18
19 namespace nacl_io {
20
21 std::string ParentEqualClause(const std::string& parent_dir_id) {
22 return "%27" + parent_dir_id + "%27+in+parents";
23 }
24
25 std::string NameEqualClause(const std::string& name) {
26 return "name+=+%27" + name + "%27";
27 }
28
29 int ExtractYearFromRFC3339(const std::string& date_time) {
30 return atoi(date_time.substr(0, 4).c_str());
31 }
32
33 int ExtractMonthFromRFC3339(const std::string& date_time) {
34 return atoi(date_time.substr(5, 2).c_str());
35 }
36
37 int ExtractDayFromRFC3339(const std::string& date_time) {
38 return atoi(date_time.substr(8, 2).c_str());
39 }
40
41 int ExtractHourFromRFC3339(const std::string& date_time) {
42 return atoi(date_time.substr(11, 2).c_str());
43 }
44
45 int ExtractMinuteFromRFC3339(const std::string& date_time) {
46 return atoi(date_time.substr(14, 2).c_str());
47 }
48
49 int ExtractSecondFromRFC3339(const std::string& date_time) {
50 return atoi(date_time.substr(17, 2).c_str());
51 }
52
53 time_t ConvertDateTimeToEpochTime(int year,
54 int month,
55 int day,
56 int hour,
57 int minute,
58 int second) {
59 time_t epoch_time = 0;
60
61 for (int i = 1970; i < year; ++i) {
62 if (i % 4 == 0 && (i % 100 != 0 || i % 400 == 0)) {
63 epoch_time += 366 * 24 * 60 * 60;
64 } else {
65 epoch_time += 365 * 24 * 60 * 60;
66 }
67 }
68 int month_to_number_of_days[] = {31, 28, 31, 30, 31, 30,
69 31, 31, 30, 31, 30, 31};
70
71 for (int i = 1; i < month; ++i) {
72 epoch_time += month_to_number_of_days[i - 1] * 24 * 60 * 60;
73 if (i == 2 && (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0))) {
74 epoch_time += 24 * 60 * 60;
75 }
76 }
77
78 epoch_time += (day - 1) * 24 * 60 * 60;
79
80 if (hour > 0) {
81 epoch_time += hour * 60 * 60;
82 }
83
84 if (minute > 0) {
85 epoch_time += minute * 60;
86 }
87
88 epoch_time += second;
89
90 return epoch_time;
91 }
92
93 void AddUrlPath(const std::string& path, std::string* out_url) {
94 *out_url += "/";
95 *out_url += path;
96 }
97
98 void AddUrlQAttributeValue(std::string* array,
99 size_t size,
100 std::string* out_q_attribute_value) {
101 *out_q_attribute_value = array[0];
102 for (size_t i = 1; i < size; ++i) {
103 *out_q_attribute_value += "+and+";
104 *out_q_attribute_value += array[i];
105 }
106 }
107
108 void AddUrlFirstQueryParameter(const std::string& attribute,
109 const std::string& value,
110 std::string* out_url) {
111 *out_url += "?";
112 *out_url += attribute;
113 *out_url += "=";
114 *out_url += value;
115 }
116
117 void AddUrlNextQueryParameter(const std::string& attribute,
118 const std::string& value,
119 std::string* out_url) {
120 *out_url += "&";
121 *out_url += attribute;
122 *out_url += "=";
123 *out_url += value;
124 }
125
126 void AddHeaders(const std::string& header_field_key,
127 const std::string& header_field_value,
128 std::string* out_headers) {
129 *out_headers += header_field_key;
130 *out_headers += ": ";
131 *out_headers += header_field_value;
132 *out_headers += "\n";
133 }
134
135 void AddBody(const std::string& data, std::string* out_body) {
136 *out_body += data;
137 *out_body += "\n";
138 }
139
140 Error LoadUrl(PepperInterface* ppapi,
141 const RequestUrlParams& params,
142 ScopedResource* out_url_response_info_resource) {
143 out_url_response_info_resource->Reset(0);
144
145 URLLoaderInterface* url_loader_iface = ppapi->GetURLLoaderInterface();
146 ScopedResource url_loader_resource(
147 ppapi, url_loader_iface->Create(ppapi->GetInstance()));
148 if (!url_loader_resource.pp_resource()) {
149 return EPERM;
150 }
151
152 URLRequestInfoInterface* url_request_info_iface =
153 ppapi->GetURLRequestInfoInterface();
154 ScopedResource url_request_info_resource(
155 ppapi, url_request_info_iface->Create(ppapi->GetInstance()));
156 if (!url_request_info_resource.pp_resource()) {
157 return EPERM;
158 }
159
160 VarInterface* var_iface = ppapi->GetVarInterface();
161
162 struct PP_Var pp_var =
163 var_iface->VarFromUtf8(params.url.c_str(), params.url.size());
164 if (!url_request_info_iface->SetProperty(
165 url_request_info_resource.pp_resource(), PP_URLREQUESTPROPERTY_URL,
166 pp_var)) {
167 return EPERM;
168 }
169
170 pp_var = var_iface->VarFromUtf8(params.method.c_str(), params.method.size());
171 if (!url_request_info_iface->SetProperty(
172 url_request_info_resource.pp_resource(), PP_URLREQUESTPROPERTY_METHOD,
173 pp_var)) {
174 return EPERM;
175 }
176
177 pp_var =
178 var_iface->VarFromUtf8(params.headers.c_str(), params.headers.size());
179 if (!url_request_info_iface->SetProperty(
180 url_request_info_resource.pp_resource(),
181 PP_URLREQUESTPROPERTY_HEADERS, pp_var)) {
182 return EPERM;
183 }
184
185 if (!url_request_info_iface->AppendDataToBody(
186 url_request_info_resource.pp_resource(), params.body.data(),
187 params.body.size())) {
188 return EPERM;
189 }
190
191 pp_var = PP_MakeBool(PP_TRUE);
192 if (!url_request_info_iface->SetProperty(
193 url_request_info_resource.pp_resource(),
194 PP_URLREQUESTPROPERTY_ALLOWCROSSORIGINREQUESTS, pp_var)) {
195 return EPERM;
196 }
197
198 pp_var = PP_MakeBool(PP_TRUE);
199 if (!url_request_info_iface->SetProperty(
200 url_request_info_resource.pp_resource(),
201 PP_URLREQUESTPROPERTY_STREAMTOFILE, pp_var)) {
202 return EPERM;
203 }
204
205 int32_t err = url_loader_iface->Open(url_loader_resource.pp_resource(),
206 url_request_info_resource.pp_resource(),
207 PP_BlockUntilComplete());
208 if (err < 0) {
209 return PPERROR_TO_ERRNO(err);
210 }
211
212 int32_t bytes_read = url_loader_iface->FinishStreamingToFile(
213 url_loader_resource.pp_resource(), PP_BlockUntilComplete());
214 if (bytes_read < 0) {
215 return PPERROR_TO_ERRNO(bytes_read);
216 }
217
218 out_url_response_info_resource->Reset(
219 url_loader_iface->GetResponseInfo(url_loader_resource.pp_resource()));
220 if (!out_url_response_info_resource->pp_resource()) {
221 return EPERM;
222 }
223
chanpatorikku 2016/08/29 17:14:04 Not calling url_loader_iface->Close(url_loader_o
224 return 0;
225 }
226
227 Error ReadResponseBody(PepperInterface* ppapi,
228 PP_Resource url_response_info_object,
229 uint32_t bytes_to_read,
230 std::string* out_output) {
231 out_output->clear();
232
233 URLResponseInfoInterface* url_response_info_iface =
234 ppapi->GetURLResponseInfoInterface();
235 FileIoInterface* file_io_iface = ppapi->GetFileIoInterface();
236
237 ScopedResource file_ref_resource(
238 ppapi,
239 url_response_info_iface->GetBodyAsFileRef(url_response_info_object));
240 if (!file_ref_resource.pp_resource()) {
241 return EPERM;
242 }
243
244 ScopedResource file_io_resource(ppapi,
245 file_io_iface->Create(ppapi->GetInstance()));
246 if (!file_io_resource.pp_resource()) {
247 return EPERM;
248 }
249
250 int32_t open_result = file_io_iface->Open(
251 file_io_resource.pp_resource(), file_ref_resource.pp_resource(),
252 PP_FILEOPENFLAG_READ, PP_BlockUntilComplete());
253 if (open_result < 0) {
254 return PPERROR_TO_ERRNO(open_result);
255 }
256
257 std::string string_buffer(1024, '\0');
binji 2016/08/30 01:39:35 Use std::vector instead of std::string for raw dat
chanpatorikku 2016/09/06 14:49:38 std::string can handle raw data. There're cases w
binji 2016/09/20 01:22:04 Yes, you can use std::string; it's not guaranteed
chanpatorikku 2016/09/21 16:41:09 Code not changing. The reason is that the buffer
258 int32_t bytes_read =
259 file_io_iface->Read(file_io_resource.pp_resource(), 0, &string_buffer[0],
260 string_buffer.size(), PP_BlockUntilComplete());
261
262 while (bytes_read > 0) {
263 *out_output += string_buffer.substr(0, bytes_read);
264
265 bytes_read = file_io_iface->Read(
266 file_io_resource.pp_resource(), out_output->size(), &string_buffer[0],
267 string_buffer.size(), PP_BlockUntilComplete());
268 }
269
270 if (bytes_read < 0) {
271 return PPERROR_TO_ERRNO(bytes_read);
272 }
273
274 out_output->resize(std::min<size_t>(out_output->size(), bytes_to_read));
275
276 return 0;
277 }
278
279 int32_t ReadStatusCode(PepperInterface* ppapi,
280 PP_Resource url_response_info_object) {
281 URLResponseInfoInterface* url_response_info_iface =
282 ppapi->GetURLResponseInfoInterface();
283
284 struct PP_Var status_code_var = url_response_info_iface->GetProperty(
285 url_response_info_object, PP_URLRESPONSEPROPERTY_STATUSCODE);
286
287 return status_code_var.value.as_int;
288 }
289
290 Error GetValueStringAndValuePos(const std::string& json,
291 const std::string& key,
292 size_t key_search_pos,
293 std::string* out_value_string,
294 size_t* out_value_pos) {
295 out_value_string->clear();
296 *out_value_pos = std::string::npos;
297
298 // json format is
299 // ..
300 // "<key1>": "<value1>"
301 // ..
302 // "<key2>": "<value2>"
303 // ..
304 // The variable key_location stores the index of the first character
305 // of a target key.
306 const char* s_quote_colon_quote = "\": \"";
307 size_t key_location = json.find(key + s_quote_colon_quote, key_search_pos);
308 if (key_location == std::string::npos) {
309 return EINVAL;
310 }
311
312 size_t start_value_index =
313 key_location + key.size() + strlen(s_quote_colon_quote);
314 size_t end_value_index = json.find("\"", start_value_index);
315 if (end_value_index == std::string::npos) {
316 return EPERM;
317 }
318
319 *out_value_string =
320 json.substr(start_value_index, end_value_index - start_value_index);
321 *out_value_pos = start_value_index;
322
323 return 0;
324 }
325
326 // A Google Drive item is a file or a directory.
327 // RequestItemIdAndItemType requests to see if either a file
328 // with item_name or a directory with item_name is there.
329 Error RequestItemIdAndItemType(const std::string& parent_dir_id,
330 const std::string& item_name,
331 Filesystem* filesystem,
332 std::string* out_item_id,
333 bool* out_is_dir_type) {
334 out_item_id->clear();
335 *out_is_dir_type = false;
336
337 GoogleDriveFs* googledrivefs = static_cast<GoogleDriveFs*>(filesystem);
338
339 RequestUrlParams p;
340
341 p.url = DRIVE_URL;
342 std::string q_attribute_value;
343 std::string attribute_values[] = {ParentEqualClause(parent_dir_id),
344 NameEqualClause(item_name)};
345
346 AddUrlQAttributeValue(attribute_values,
347 NACL_ARRAY_SIZE_UNSAFE(attribute_values),
chanpatorikku 2016/08/29 17:14:04 NACL_ARRAY_SIZE_UNSAFE(arr) borrows from native_cl
binji 2016/08/30 01:39:35 This definition is fine. Also, don't use the NACL_
chanpatorikku 2016/09/06 14:49:38 Done. Moved the macro into the .cc file if possib
348 &q_attribute_value);
349 AddUrlFirstQueryParameter("q", q_attribute_value, &p.url);
350
351 p.method = "GET";
352
353 AddHeaders("Content-type", "application/json", &p.headers);
354 AddHeaders("Authorization", "Bearer " + googledrivefs->token(), &p.headers);
355
356 ScopedResource url_response_info_resource(googledrivefs->ppapi());
357 Error error = LoadUrl(googledrivefs->ppapi(), p, &url_response_info_resource);
358 if (error) {
359 return error;
360 }
361
362 if (ReadStatusCode(googledrivefs->ppapi(),
363 url_response_info_resource.pp_resource()) !=
364 STATUSCODE_OK) {
365 return EPERM;
366 }
367
368 std::string output;
369 error = ReadResponseBody(googledrivefs->ppapi(),
370 url_response_info_resource.pp_resource(), UINT_MAX,
371 &output);
372 if (error) {
373 return error;
374 }
375
376 size_t id_index;
377 error = GetValueStringAndValuePos(output, "id", 0, out_item_id, &id_index);
378 if (error == EINVAL) {
379 return ENOENT;
380 } else if (error) {
381 return error;
382 }
383
384 std::string mime_type_value;
385 size_t mime_type_index;
386 error = GetValueStringAndValuePos(output, "mimeType", 0, &mime_type_value,
387 &mime_type_index);
388 if (error) {
389 return EPERM;
390 }
391
392 *out_is_dir_type = (mime_type_value == FOLDER_MIME_TYPE);
393
394 return 0;
395 }
396
397 Error RequestParentDirId(const Path& path,
398 Filesystem* filesystem,
399 std::string* out_parent_dir_id) {
400 out_parent_dir_id->clear();
401
402 if (path.IsRoot()) {
403 return EINVAL;
404 }
405
406 std::string helper_parent_dir_id = "root";
407
408 for (size_t i = 1; i < path.Size() - 1; ++i) {
409 std::string dir_name = path.Range(i, i + 1);
410 std::string dir_id;
411 bool is_dir_type;
412 Error error = RequestItemIdAndItemType(helper_parent_dir_id, dir_name,
413 filesystem, &dir_id, &is_dir_type);
414 if (error || !is_dir_type) {
415 return EPERM;
416 }
417
418 helper_parent_dir_id = dir_id;
419 }
420 *out_parent_dir_id = helper_parent_dir_id;
421
422 return 0;
423 }
424
425 } // namespace nacl_io
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698