Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / google_apis / drive / base_requests.h
blobac64a54fa979ec8b768e80a89655abc94d1ecb45
1 // Copyright (c) 2012 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 // This file provides base classes used to issue HTTP requests for Google
6 // APIs.
8 #ifndef GOOGLE_APIS_DRIVE_BASE_REQUESTS_H_
9 #define GOOGLE_APIS_DRIVE_BASE_REQUESTS_H_
11 #include <string>
12 #include <vector>
14 #include "base/callback.h"
15 #include "base/files/file_path.h"
16 #include "base/memory/weak_ptr.h"
17 #include "base/threading/thread_checker.h"
18 #include "google_apis/drive/drive_api_error_codes.h"
19 #include "net/url_request/url_fetcher.h"
20 #include "net/url_request/url_fetcher_delegate.h"
21 #include "net/url_request/url_fetcher_response_writer.h"
22 #include "url/gurl.h"
24 namespace base {
25 class Value;
26 } // namespace base
28 namespace google_apis {
30 class FileResource;
31 class RequestSender;
33 // Content type for multipart body.
34 enum MultipartType {
35 MULTIPART_RELATED,
36 MULTIPART_MIXED
39 // Pair of content type and data.
40 struct ContentTypeAndData {
41 std::string type;
42 std::string data;
45 typedef base::Callback<void(DriveApiErrorCode)> PrepareCallback;
47 // Callback used for requests that the server returns FileResource data
48 // formatted into JSON value.
49 typedef base::Callback<void(DriveApiErrorCode error,
50 scoped_ptr<FileResource> entry)>
51 FileResourceCallback;
53 // Callback used for DownloadFileRequest and ResumeUploadRequestBase.
54 typedef base::Callback<void(int64 progress, int64 total)> ProgressCallback;
56 // Callback used to get the content from DownloadFileRequest.
57 typedef base::Callback<void(
58 DriveApiErrorCode error,
59 scoped_ptr<std::string> content)> GetContentCallback;
61 // Parses JSON passed in |json|. Returns NULL on failure.
62 scoped_ptr<base::Value> ParseJson(const std::string& json);
64 // Generate multipart body. If |predetermined_boundary| is not empty, it uses
65 // the string as boundary. Otherwise it generates random boundary that does not
66 // conflict with |parts|. If |data_offset| is not nullptr, it stores the
67 // index of first byte of each part in multipart body.
68 void GenerateMultipartBody(MultipartType multipart_type,
69 const std::string& predetermined_boundary,
70 const std::vector<ContentTypeAndData>& parts,
71 ContentTypeAndData* output,
72 std::vector<uint64>* data_offset);
74 //======================= AuthenticatedRequestInterface ======================
76 // An interface class for implementing a request which requires OAuth2
77 // authentication.
78 class AuthenticatedRequestInterface {
79 public:
80 // Called when re-authentication is required. See Start() for details.
81 typedef base::Callback<void(AuthenticatedRequestInterface* request)>
82 ReAuthenticateCallback;
84 virtual ~AuthenticatedRequestInterface() {}
86 // Starts the request with |access_token|. User-Agent header will be set
87 // to |custom_user_agent| if the value is not empty.
89 // |callback| is called when re-authentication is needed for a certain
90 // number of times (see kMaxReAuthenticateAttemptsPerRequest in .cc).
91 // The callback should retry by calling Start() again with a new access
92 // token, or just call OnAuthFailed() if a retry is not attempted.
93 // |callback| must not be null.
94 virtual void Start(const std::string& access_token,
95 const std::string& custom_user_agent,
96 const ReAuthenticateCallback& callback) = 0;
98 // Invoked when the authentication failed with an error code |code|.
99 virtual void OnAuthFailed(DriveApiErrorCode code) = 0;
101 // Gets a weak pointer to this request object. Since requests may be
102 // deleted when it is canceled by user action, for posting asynchronous tasks
103 // on the authentication request object, weak pointers have to be used.
104 // TODO(kinaba): crbug.com/134814 use more clean life time management than
105 // using weak pointers.
106 virtual base::WeakPtr<AuthenticatedRequestInterface> GetWeakPtr() = 0;
108 // Cancels the request. It will invoke the callback object passed in
109 // each request's constructor with error code DRIVE_CANCELLED.
110 virtual void Cancel() = 0;
113 //=========================== ResponseWriter ==================================
115 // Saves the response for the request to a file or string.
116 class ResponseWriter : public net::URLFetcherResponseWriter {
117 public:
118 // If file_path is not empty, the response will be saved with file_writer_,
119 // otherwise it will be saved to data_.
120 ResponseWriter(base::SequencedTaskRunner* file_task_runner,
121 const base::FilePath& file_path,
122 const GetContentCallback& get_content_callback);
123 ~ResponseWriter() override;
125 const std::string& data() const { return data_; }
127 // Disowns the output file.
128 void DisownFile();
130 // URLFetcherResponseWriter overrides:
131 int Initialize(const net::CompletionCallback& callback) override;
132 int Write(net::IOBuffer* buffer,
133 int num_bytes,
134 const net::CompletionCallback& callback) override;
135 int Finish(const net::CompletionCallback& callback) override;
137 private:
138 void DidWrite(scoped_refptr<net::IOBuffer> buffer,
139 const net::CompletionCallback& callback,
140 int result);
142 const GetContentCallback get_content_callback_;
143 std::string data_;
144 scoped_ptr<net::URLFetcherFileWriter> file_writer_;
145 base::WeakPtrFactory<ResponseWriter> weak_ptr_factory_;
147 DISALLOW_COPY_AND_ASSIGN(ResponseWriter);
150 //============================ UrlFetchRequestBase ===========================
152 // Base class for requests that are fetching URLs.
153 class UrlFetchRequestBase : public AuthenticatedRequestInterface,
154 public net::URLFetcherDelegate {
155 public:
156 // AuthenticatedRequestInterface overrides.
157 void Start(const std::string& access_token,
158 const std::string& custom_user_agent,
159 const ReAuthenticateCallback& callback) override;
160 base::WeakPtr<AuthenticatedRequestInterface> GetWeakPtr() override;
161 void Cancel() override;
163 protected:
164 explicit UrlFetchRequestBase(RequestSender* sender);
165 ~UrlFetchRequestBase() override;
167 // Does async initialization for the request. |Start| calls this method so you
168 // don't need to call this before |Start|.
169 virtual void Prepare(const PrepareCallback& callback);
171 // Gets URL for the request.
172 virtual GURL GetURL() const = 0;
174 // Returns the request type. A derived class should override this method
175 // for a request type other than HTTP GET.
176 virtual net::URLFetcher::RequestType GetRequestType() const;
178 // Returns the extra HTTP headers for the request. A derived class should
179 // override this method to specify any extra headers needed for the request.
180 virtual std::vector<std::string> GetExtraRequestHeaders() const;
182 // Used by a derived class to add any content data to the request.
183 // Returns true if |upload_content_type| and |upload_content| are updated
184 // with the content type and data for the request.
185 // Note that this and GetContentFile() cannot be used together.
186 virtual bool GetContentData(std::string* upload_content_type,
187 std::string* upload_content);
189 // Used by a derived class to add content data which is the whole file or
190 // a part of the file at |local_file_path|.
191 // Returns true if all the arguments are updated for the content being
192 // uploaded.
193 // Note that this and GetContentData() cannot be used together.
194 virtual bool GetContentFile(base::FilePath* local_file_path,
195 int64* range_offset,
196 int64* range_length,
197 std::string* upload_content_type);
199 // Used by a derived class to set an output file path if they want to save
200 // the downloaded content to a file at a specific path.
201 // Sets |get_content_callback|, which is called when some part of the response
202 // is read.
203 virtual void GetOutputFilePath(base::FilePath* local_file_path,
204 GetContentCallback* get_content_callback);
206 // Invoked by OnURLFetchComplete when the request completes without an
207 // authentication error. Must be implemented by a derived class.
208 virtual void ProcessURLFetchResults(const net::URLFetcher* source) = 0;
210 // Invoked by this base class upon an authentication error or cancel by
211 // a user request. Must be implemented by a derived class.
212 virtual void RunCallbackOnPrematureFailure(DriveApiErrorCode code) = 0;
214 // Invoked from derived classes when ProcessURLFetchResults() is completed.
215 void OnProcessURLFetchResultsComplete();
217 // Returns an appropriate DriveApiErrorCode based on the HTTP response code
218 // and the status of the URLFetcher.
219 DriveApiErrorCode GetErrorCode();
221 // Returns true if called on the thread where the constructor was called.
222 bool CalledOnValidThread();
224 // Returns the writer which is used to save the response for the request.
225 ResponseWriter* response_writer() const { return response_writer_; }
227 // Returns the task runner that should be used for blocking tasks.
228 base::SequencedTaskRunner* blocking_task_runner() const;
230 private:
231 // Continues |Start| function after |Prepare|.
232 void StartAfterPrepare(const std::string& access_token,
233 const std::string& custom_user_agent,
234 const ReAuthenticateCallback& callback,
235 DriveApiErrorCode code);
237 // Invokes callback with |code| and request to delete the request to
238 // |sender_|.
239 void CompleteRequestWithError(DriveApiErrorCode code);
241 // URLFetcherDelegate overrides.
242 void OnURLFetchComplete(const net::URLFetcher* source) override;
244 // AuthenticatedRequestInterface overrides.
245 void OnAuthFailed(DriveApiErrorCode code) override;
247 ReAuthenticateCallback re_authenticate_callback_;
248 int re_authenticate_count_;
249 scoped_ptr<net::URLFetcher> url_fetcher_;
250 ResponseWriter* response_writer_; // Owned by |url_fetcher_|.
251 RequestSender* sender_;
252 DriveApiErrorCode error_code_;
254 base::ThreadChecker thread_checker_;
256 // Note: This should remain the last member so it'll be destroyed and
257 // invalidate its weak pointers before any other members are destroyed.
258 base::WeakPtrFactory<UrlFetchRequestBase> weak_ptr_factory_;
260 DISALLOW_COPY_AND_ASSIGN(UrlFetchRequestBase);
263 //============================ BatchableDelegate ============================
265 // Delegate to be used by |SingleBatchableDelegateRequest| and
266 // |BatchUploadRequest|.
267 class BatchableDelegate {
268 public:
269 virtual ~BatchableDelegate() {}
271 // See UrlFetchRequestBase.
272 virtual GURL GetURL() const = 0;
273 virtual net::URLFetcher::RequestType GetRequestType() const = 0;
274 virtual std::vector<std::string> GetExtraRequestHeaders() const = 0;
275 virtual void Prepare(const PrepareCallback& callback) = 0;
276 virtual bool GetContentData(std::string* upload_content_type,
277 std::string* upload_content) = 0;
279 // Notifies result of the request. Usually, it parses the |code| and
280 // |response_body|, then notifies the parsed value to client code of the
281 // API. |callback| must be called on completion. The instance must not
282 // do anything after calling |callback| since the instance may be deleted in
283 // |callback|.
284 virtual void NotifyResult(DriveApiErrorCode code,
285 const std::string& response_body,
286 const base::Closure& callback) = 0;
288 // Notifies error. Unlike |NotifyResult|, it must report error
289 // synchronously. The instance may be deleted just after calling
290 // NotifyError.
291 virtual void NotifyError(DriveApiErrorCode code) = 0;
293 // Notifies progress.
294 virtual void NotifyUploadProgress(const net::URLFetcher* source,
295 int64 current,
296 int64 total) = 0;
299 //============================ EntryActionRequest ============================
301 // Callback type for requests that return only error status, like: Delete/Move.
302 typedef base::Callback<void(DriveApiErrorCode error)> EntryActionCallback;
304 // This class performs a simple action over a given entry (document/file).
305 // It is meant to be used for requests that return no JSON blobs.
306 class EntryActionRequest : public UrlFetchRequestBase {
307 public:
308 // |callback| is called when the request is finished either by success or by
309 // failure. It must not be null.
310 EntryActionRequest(RequestSender* sender,
311 const EntryActionCallback& callback);
312 ~EntryActionRequest() override;
314 protected:
315 // Overridden from UrlFetchRequestBase.
316 void ProcessURLFetchResults(const net::URLFetcher* source) override;
317 void RunCallbackOnPrematureFailure(DriveApiErrorCode code) override;
319 private:
320 const EntryActionCallback callback_;
322 DISALLOW_COPY_AND_ASSIGN(EntryActionRequest);
325 //=========================== InitiateUploadRequestBase=======================
327 // Callback type for DriveServiceInterface::InitiateUpload.
328 typedef base::Callback<void(DriveApiErrorCode error,
329 const GURL& upload_url)> InitiateUploadCallback;
331 // This class provides base implementation for performing the request for
332 // initiating the upload of a file.
333 // |callback| will be called with the obtained upload URL. The URL will be
334 // used with requests for resuming the file uploading.
336 // Here's the flow of uploading:
337 // 1) Get the upload URL with a class inheriting InitiateUploadRequestBase.
338 // 2) Upload the first 1GB (see kUploadChunkSize in drive_uploader.cc)
339 // of the target file to the upload URL
340 // 3) If there is more data to upload, go to 2).
342 class InitiateUploadRequestBase : public UrlFetchRequestBase {
343 protected:
344 // |callback| will be called with the upload URL, where upload data is
345 // uploaded to with ResumeUploadRequestBase. It must not be null.
346 // |content_type| and |content_length| should be the attributes of the
347 // uploading file.
348 InitiateUploadRequestBase(RequestSender* sender,
349 const InitiateUploadCallback& callback,
350 const std::string& content_type,
351 int64 content_length);
352 ~InitiateUploadRequestBase() override;
354 // UrlFetchRequestBase overrides.
355 void ProcessURLFetchResults(const net::URLFetcher* source) override;
356 void RunCallbackOnPrematureFailure(DriveApiErrorCode code) override;
357 std::vector<std::string> GetExtraRequestHeaders() const override;
359 private:
360 const InitiateUploadCallback callback_;
361 const std::string content_type_;
362 const int64 content_length_;
364 DISALLOW_COPY_AND_ASSIGN(InitiateUploadRequestBase);
367 //========================== UploadRangeRequestBase ==========================
369 // Struct for response to ResumeUpload and GetUploadStatus.
370 struct UploadRangeResponse {
371 UploadRangeResponse();
372 UploadRangeResponse(DriveApiErrorCode code,
373 int64 start_position_received,
374 int64 end_position_received);
375 ~UploadRangeResponse();
377 DriveApiErrorCode code;
378 // The values of "Range" header returned from the server. The values are
379 // used to continue uploading more data. These are set to -1 if an upload
380 // is complete.
381 // |start_position_received| is inclusive and |end_position_received| is
382 // exclusive to follow the common C++ manner, although the response from
383 // the server has "Range" header in inclusive format at both sides.
384 int64 start_position_received;
385 int64 end_position_received;
388 // Base class for a URL fetch request expecting the response containing the
389 // current uploading range. This class processes the response containing
390 // "Range" header and invoke OnRangeRequestComplete.
391 class UploadRangeRequestBase : public UrlFetchRequestBase {
392 protected:
393 // |upload_url| is the URL of where to upload the file to.
394 UploadRangeRequestBase(RequestSender* sender, const GURL& upload_url);
395 ~UploadRangeRequestBase() override;
397 // UrlFetchRequestBase overrides.
398 GURL GetURL() const override;
399 net::URLFetcher::RequestType GetRequestType() const override;
400 void ProcessURLFetchResults(const net::URLFetcher* source) override;
401 void RunCallbackOnPrematureFailure(DriveApiErrorCode code) override;
403 // This method will be called when the request is done, regardless of
404 // whether it is succeeded or failed.
406 // 1) If there is more data to upload, |code| of |response| is set to
407 // HTTP_RESUME_INCOMPLETE, and positions are set appropriately. Also, |value|
408 // will be set to NULL.
409 // 2) If the upload is complete, |code| is set to HTTP_CREATED for a new file
410 // or HTTP_SUCCESS for an existing file. Positions are set to -1, and |value|
411 // is set to a parsed JSON value representing the uploaded file.
412 // 3) If a premature failure is found, |code| is set to a value representing
413 // the situation. Positions are set to 0, and |value| is set to NULL.
415 // See also the comments for UploadRangeResponse.
416 // Note: Subclasses should have responsibility to run some callback
417 // in this method to notify the finish status to its clients (or ignore it
418 // under its responsibility).
419 virtual void OnRangeRequestComplete(
420 const UploadRangeResponse& response, scoped_ptr<base::Value> value) = 0;
422 private:
423 // Called when ParseJson() is completed.
424 void OnDataParsed(DriveApiErrorCode code, scoped_ptr<base::Value> value);
426 const GURL upload_url_;
428 // Note: This should remain the last member so it'll be destroyed and
429 // invalidate its weak pointers before any other members are destroyed.
430 base::WeakPtrFactory<UploadRangeRequestBase> weak_ptr_factory_;
432 DISALLOW_COPY_AND_ASSIGN(UploadRangeRequestBase);
435 //========================== ResumeUploadRequestBase =========================
437 // This class performs the request for resuming the upload of a file.
438 // More specifically, this request uploads a chunk of data carried in |buf|
439 // of ResumeUploadResponseBase. This class is designed to share the
440 // implementation of upload resuming between GData WAPI and Drive API v2.
441 // The subclasses should implement OnRangeRequestComplete inherited by
442 // UploadRangeRequestBase, because the type of the response should be
443 // different (although the format in the server response is JSON).
444 class ResumeUploadRequestBase : public UploadRangeRequestBase {
445 protected:
446 // |start_position| is the start of range of contents currently stored in
447 // |buf|. |end_position| is the end of range of contents currently stared in
448 // |buf|. This is exclusive. For instance, if you are to upload the first
449 // 500 bytes of data, |start_position| is 0 and |end_position| is 500.
450 // |content_length| and |content_type| are the length and type of the
451 // file content to be uploaded respectively.
452 // |buf| holds current content to be uploaded.
453 // See also UploadRangeRequestBase's comment for remaining parameters
454 // meaning.
455 ResumeUploadRequestBase(RequestSender* sender,
456 const GURL& upload_location,
457 int64 start_position,
458 int64 end_position,
459 int64 content_length,
460 const std::string& content_type,
461 const base::FilePath& local_file_path);
462 ~ResumeUploadRequestBase() override;
464 // UrlFetchRequestBase overrides.
465 std::vector<std::string> GetExtraRequestHeaders() const override;
466 bool GetContentFile(base::FilePath* local_file_path,
467 int64* range_offset,
468 int64* range_length,
469 std::string* upload_content_type) override;
471 private:
472 // The parameters for the request. See ResumeUploadParams for the details.
473 const int64 start_position_;
474 const int64 end_position_;
475 const int64 content_length_;
476 const std::string content_type_;
477 const base::FilePath local_file_path_;
479 DISALLOW_COPY_AND_ASSIGN(ResumeUploadRequestBase);
482 //======================== GetUploadStatusRequestBase ========================
484 // This class performs the request for getting the current upload status
485 // of a file.
486 // This request calls OnRangeRequestComplete() with:
487 // - HTTP_RESUME_INCOMPLETE and the range of previously uploaded data,
488 // if a file has been partially uploaded. |value| is not used.
489 // - HTTP_SUCCESS or HTTP_CREATED (up to the upload mode) and |value|
490 // for the uploaded data, if a file has been completely uploaded.
491 // See also UploadRangeRequestBase.
492 class GetUploadStatusRequestBase : public UploadRangeRequestBase {
493 public:
494 // |content_length| is the whole data size to be uploaded.
495 // See also UploadRangeRequestBase's constructor comment for other
496 // parameters.
497 GetUploadStatusRequestBase(RequestSender* sender,
498 const GURL& upload_url,
499 int64 content_length);
500 ~GetUploadStatusRequestBase() override;
502 protected:
503 // UrlFetchRequestBase overrides.
504 std::vector<std::string> GetExtraRequestHeaders() const override;
506 private:
507 const int64 content_length_;
509 DISALLOW_COPY_AND_ASSIGN(GetUploadStatusRequestBase);
512 //=========================== MultipartUploadRequestBase=======================
514 // This class provides base implementation for performing the request for
515 // uploading a file by multipart body.
516 class MultipartUploadRequestBase : public BatchableDelegate {
517 public:
518 // Set boundary. Only tests can use this method.
519 void SetBoundaryForTesting(const std::string& boundary);
521 protected:
522 // |callback| will be called with the file resource.upload URL.
523 // |content_type| and |content_length| should be the attributes of the
524 // uploading file. Other parameters are optional and can be empty or null
525 // depending on Upload URL provided by the subclasses.
526 MultipartUploadRequestBase(base::SequencedTaskRunner* blocking_task_runner,
527 const std::string& metadata_json,
528 const std::string& content_type,
529 int64 content_length,
530 const base::FilePath& local_file_path,
531 const FileResourceCallback& callback,
532 const ProgressCallback& progress_callback);
533 ~MultipartUploadRequestBase() override;
535 // BatchableDelegate.
536 std::vector<std::string> GetExtraRequestHeaders() const override;
537 void Prepare(const PrepareCallback& callback) override;
538 bool GetContentData(std::string* upload_content_type,
539 std::string* upload_content) override;
540 void NotifyResult(DriveApiErrorCode code,
541 const std::string& body,
542 const base::Closure& callback) override;
543 void NotifyError(DriveApiErrorCode code) override;
544 void NotifyUploadProgress(const net::URLFetcher* source,
545 int64 current,
546 int64 total) override;
547 // Parses the response value and invokes |callback_| with |FileResource|.
548 void OnDataParsed(DriveApiErrorCode code,
549 const base::Closure& callback,
550 scoped_ptr<base::Value> value);
552 private:
553 // Continues to rest part of |Start| method after determining boundary string
554 // of multipart/related.
555 void OnPrepareUploadContent(const PrepareCallback& callback,
556 std::string* upload_content_type,
557 std::string* upload_content_data,
558 bool result);
560 scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_;
561 const std::string metadata_json_;
562 const std::string content_type_;
563 const base::FilePath local_path_;
564 const FileResourceCallback callback_;
565 const ProgressCallback progress_callback_;
567 // Boundary of multipart body.
568 std::string boundary_;
570 // Upload content of multipart body.
571 std::string upload_content_type_;
572 std::string upload_content_data_;
574 base::ThreadChecker thread_checker_;
576 // Note: This should remain the last member so it'll be destroyed and
577 // invalidate its weak pointers before any other members are destroyed.
578 base::WeakPtrFactory<MultipartUploadRequestBase> weak_ptr_factory_;
580 DISALLOW_COPY_AND_ASSIGN(MultipartUploadRequestBase);
583 //============================ DownloadFileRequest ===========================
585 // Callback type for receiving the completion of DownloadFileRequest.
586 typedef base::Callback<void(DriveApiErrorCode error,
587 const base::FilePath& temp_file)>
588 DownloadActionCallback;
590 // This is a base class for performing the request for downloading a file.
591 class DownloadFileRequestBase : public UrlFetchRequestBase {
592 public:
593 // download_action_callback:
594 // This callback is called when the download is complete. Must not be null.
596 // get_content_callback:
597 // This callback is called when some part of the content is
598 // read. Used to read the download content progressively. May be null.
600 // progress_callback:
601 // This callback is called for periodically reporting the number of bytes
602 // downloaded so far. May be null.
604 // download_url:
605 // Specifies the target file to download.
607 // output_file_path:
608 // Specifies the file path to save the downloaded file.
610 DownloadFileRequestBase(
611 RequestSender* sender,
612 const DownloadActionCallback& download_action_callback,
613 const GetContentCallback& get_content_callback,
614 const ProgressCallback& progress_callback,
615 const GURL& download_url,
616 const base::FilePath& output_file_path);
617 ~DownloadFileRequestBase() override;
619 protected:
620 // UrlFetchRequestBase overrides.
621 GURL GetURL() const override;
622 void GetOutputFilePath(base::FilePath* local_file_path,
623 GetContentCallback* get_content_callback) override;
624 void ProcessURLFetchResults(const net::URLFetcher* source) override;
625 void RunCallbackOnPrematureFailure(DriveApiErrorCode code) override;
627 // net::URLFetcherDelegate overrides.
628 void OnURLFetchDownloadProgress(const net::URLFetcher* source,
629 int64 current,
630 int64 total) override;
632 private:
633 const DownloadActionCallback download_action_callback_;
634 const GetContentCallback get_content_callback_;
635 const ProgressCallback progress_callback_;
636 const GURL download_url_;
637 const base::FilePath output_file_path_;
639 DISALLOW_COPY_AND_ASSIGN(DownloadFileRequestBase);
642 } // namespace google_apis
644 #endif // GOOGLE_APIS_DRIVE_BASE_REQUESTS_H_