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.
5 #include "chrome/browser/google_apis/drive_api_operations.h"
8 #include "base/callback.h"
9 #include "base/json/json_writer.h"
10 #include "base/values.h"
11 #include "chrome/browser/google_apis/drive_api_parser.h"
12 #include "chrome/browser/google_apis/operation_util.h"
13 #include "content/public/browser/browser_thread.h"
15 using content::BrowserThread
;
17 namespace google_apis
{
20 const char kContentTypeApplicationJson
[] = "application/json";
21 const char kDirectoryMimeType
[] = "application/vnd.google-apps.folder";
22 const char kParentLinkKind
[] = "drive#fileLink";
24 // Parses the JSON value to a resource typed |T| and runs |callback| on the UI
25 // thread once parsing is done.
28 const base::Callback
<void(GDataErrorCode
, scoped_ptr
<T
>)>& callback
,
30 scoped_ptr
<base::Value
> value
) {
31 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
32 DCHECK(!callback
.is_null());
34 scoped_ptr
<T
> resource
;
36 resource
= T::CreateFrom(*value
);
38 // Failed to parse the JSON value, although the JSON value is available,
39 // so let the callback know the parsing error.
40 error
= GDATA_PARSE_ERROR
;
44 callback
.Run(error
, resource
.Pass());
47 // Parses the JSON value to FileResource instance and runs |callback| on the
48 // UI thread once parsing is done.
49 // This is customized version of ParseJsonAndRun defined above to adapt the
50 // remaining response type.
51 void ParseFileResourceWithUploadRangeAndRun(
52 const drive::UploadRangeCallback
& callback
,
53 const UploadRangeResponse
& response
,
54 scoped_ptr
<base::Value
> value
) {
55 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
56 DCHECK(!callback
.is_null());
58 scoped_ptr
<FileResource
> file_resource
;
60 file_resource
= FileResource::CreateFrom(*value
);
63 UploadRangeResponse(GDATA_PARSE_ERROR
,
64 response
.start_position_received
,
65 response
.end_position_received
),
66 scoped_ptr
<FileResource
>());
71 callback
.Run(response
, file_resource
.Pass());
76 //============================== GetAboutOperation =============================
78 GetAboutOperation::GetAboutOperation(
79 OperationRegistry
* registry
,
80 net::URLRequestContextGetter
* url_request_context_getter
,
81 const DriveApiUrlGenerator
& url_generator
,
82 const GetAboutResourceCallback
& callback
)
83 : GetDataOperation(registry
, url_request_context_getter
,
84 base::Bind(&ParseJsonAndRun
<AboutResource
>, callback
)),
85 url_generator_(url_generator
) {
86 DCHECK(!callback
.is_null());
89 GetAboutOperation::~GetAboutOperation() {}
91 GURL
GetAboutOperation::GetURL() const {
92 return url_generator_
.GetAboutUrl();
95 //============================== GetApplistOperation ===========================
97 GetApplistOperation::GetApplistOperation(
98 OperationRegistry
* registry
,
99 net::URLRequestContextGetter
* url_request_context_getter
,
100 const DriveApiUrlGenerator
& url_generator
,
101 const GetDataCallback
& callback
)
102 : GetDataOperation(registry
, url_request_context_getter
, callback
),
103 url_generator_(url_generator
) {
104 DCHECK(!callback
.is_null());
107 GetApplistOperation::~GetApplistOperation() {}
109 GURL
GetApplistOperation::GetURL() const {
110 return url_generator_
.GetApplistUrl();
113 //============================ GetChangelistOperation ==========================
115 GetChangelistOperation::GetChangelistOperation(
116 OperationRegistry
* registry
,
117 net::URLRequestContextGetter
* url_request_context_getter
,
118 const DriveApiUrlGenerator
& url_generator
,
119 bool include_deleted
,
120 int64 start_changestamp
,
121 const GetDataCallback
& callback
)
122 : GetDataOperation(registry
, url_request_context_getter
, callback
),
123 url_generator_(url_generator
),
124 include_deleted_(include_deleted
),
125 start_changestamp_(start_changestamp
) {
126 DCHECK(!callback
.is_null());
129 GetChangelistOperation::~GetChangelistOperation() {}
131 GURL
GetChangelistOperation::GetURL() const {
132 return url_generator_
.GetChangelistUrl(include_deleted_
, start_changestamp_
);
135 //============================= GetFilelistOperation ===========================
137 GetFilelistOperation::GetFilelistOperation(
138 OperationRegistry
* registry
,
139 net::URLRequestContextGetter
* url_request_context_getter
,
140 const DriveApiUrlGenerator
& url_generator
,
141 const std::string
& search_string
,
142 const GetDataCallback
& callback
)
143 : GetDataOperation(registry
, url_request_context_getter
, callback
),
144 url_generator_(url_generator
),
145 search_string_(search_string
) {
146 DCHECK(!callback
.is_null());
149 GetFilelistOperation::~GetFilelistOperation() {}
151 GURL
GetFilelistOperation::GetURL() const {
152 return url_generator_
.GetFilelistUrl(search_string_
);
155 //=============================== GetFileOperation =============================
157 GetFileOperation::GetFileOperation(
158 OperationRegistry
* registry
,
159 net::URLRequestContextGetter
* url_request_context_getter
,
160 const DriveApiUrlGenerator
& url_generator
,
161 const std::string
& file_id
,
162 const FileResourceCallback
& callback
)
163 : GetDataOperation(registry
, url_request_context_getter
,
164 base::Bind(&ParseJsonAndRun
<FileResource
>, callback
)),
165 url_generator_(url_generator
),
167 DCHECK(!callback
.is_null());
170 GetFileOperation::~GetFileOperation() {}
172 GURL
GetFileOperation::GetURL() const {
173 return url_generator_
.GetFileUrl(file_id_
);
178 //======================= ContinueGetFileListOperation =========================
180 ContinueGetFileListOperation::ContinueGetFileListOperation(
181 OperationRegistry
* registry
,
182 net::URLRequestContextGetter
* url_request_context_getter
,
184 const GetDataCallback
& callback
)
185 : GetDataOperation(registry
, url_request_context_getter
, callback
),
187 DCHECK(!callback
.is_null());
190 ContinueGetFileListOperation::~ContinueGetFileListOperation() {}
192 GURL
ContinueGetFileListOperation::GetURL() const {
196 //========================== CreateDirectoryOperation ==========================
198 CreateDirectoryOperation::CreateDirectoryOperation(
199 OperationRegistry
* registry
,
200 net::URLRequestContextGetter
* url_request_context_getter
,
201 const DriveApiUrlGenerator
& url_generator
,
202 const std::string
& parent_resource_id
,
203 const std::string
& directory_name
,
204 const FileResourceCallback
& callback
)
205 : GetDataOperation(registry
, url_request_context_getter
,
206 base::Bind(&ParseJsonAndRun
<FileResource
>, callback
)),
207 url_generator_(url_generator
),
208 parent_resource_id_(parent_resource_id
),
209 directory_name_(directory_name
) {
210 DCHECK(!callback
.is_null());
213 CreateDirectoryOperation::~CreateDirectoryOperation() {}
215 GURL
CreateDirectoryOperation::GetURL() const {
216 if (parent_resource_id_
.empty() || directory_name_
.empty()) {
219 return url_generator_
.GetFilelistUrl(std::string());
222 net::URLFetcher::RequestType
CreateDirectoryOperation::GetRequestType() const {
223 return net::URLFetcher::POST
;
226 bool CreateDirectoryOperation::GetContentData(std::string
* upload_content_type
,
227 std::string
* upload_content
) {
228 *upload_content_type
= kContentTypeApplicationJson
;
230 base::DictionaryValue root
;
231 root
.SetString("title", directory_name_
);
233 base::DictionaryValue
* parent_value
= new base::DictionaryValue
;
234 parent_value
->SetString("id", parent_resource_id_
);
235 base::ListValue
* parent_list_value
= new base::ListValue
;
236 parent_list_value
->Append(parent_value
);
237 root
.Set("parents", parent_list_value
);
239 root
.SetString("mimeType", kDirectoryMimeType
);
241 base::JSONWriter::Write(&root
, upload_content
);
243 DVLOG(1) << "CreateDirectory data: " << *upload_content_type
<< ", ["
244 << *upload_content
<< "]";
248 //=========================== RenameResourceOperation ==========================
250 RenameResourceOperation::RenameResourceOperation(
251 OperationRegistry
* registry
,
252 net::URLRequestContextGetter
* url_request_context_getter
,
253 const DriveApiUrlGenerator
& url_generator
,
254 const std::string
& resource_id
,
255 const std::string
& new_name
,
256 const EntryActionCallback
& callback
)
257 : EntryActionOperation(registry
, url_request_context_getter
, callback
),
258 url_generator_(url_generator
),
259 resource_id_(resource_id
),
260 new_name_(new_name
) {
261 DCHECK(!callback
.is_null());
264 RenameResourceOperation::~RenameResourceOperation() {}
266 net::URLFetcher::RequestType
RenameResourceOperation::GetRequestType() const {
267 return net::URLFetcher::PATCH
;
270 std::vector
<std::string
>
271 RenameResourceOperation::GetExtraRequestHeaders() const {
272 std::vector
<std::string
> headers
;
273 headers
.push_back(util::kIfMatchAllHeader
);
277 GURL
RenameResourceOperation::GetURL() const {
278 return url_generator_
.GetFileUrl(resource_id_
);
281 bool RenameResourceOperation::GetContentData(std::string
* upload_content_type
,
282 std::string
* upload_content
) {
283 *upload_content_type
= kContentTypeApplicationJson
;
285 base::DictionaryValue root
;
286 root
.SetString("title", new_name_
);
287 base::JSONWriter::Write(&root
, upload_content
);
289 DVLOG(1) << "RenameResource data: " << *upload_content_type
<< ", ["
290 << *upload_content
<< "]";
294 //=========================== CopyResourceOperation ============================
296 CopyResourceOperation::CopyResourceOperation(
297 OperationRegistry
* registry
,
298 net::URLRequestContextGetter
* url_request_context_getter
,
299 const DriveApiUrlGenerator
& url_generator
,
300 const std::string
& resource_id
,
301 const std::string
& new_name
,
302 const FileResourceCallback
& callback
)
303 : GetDataOperation(registry
, url_request_context_getter
,
304 base::Bind(&ParseJsonAndRun
<FileResource
>, callback
)),
305 url_generator_(url_generator
),
306 resource_id_(resource_id
),
307 new_name_(new_name
) {
308 DCHECK(!callback
.is_null());
311 CopyResourceOperation::~CopyResourceOperation() {
314 net::URLFetcher::RequestType
CopyResourceOperation::GetRequestType() const {
315 return net::URLFetcher::POST
;
318 GURL
CopyResourceOperation::GetURL() const {
319 return url_generator_
.GetFileCopyUrl(resource_id_
);
322 bool CopyResourceOperation::GetContentData(std::string
* upload_content_type
,
323 std::string
* upload_content
) {
324 *upload_content_type
= kContentTypeApplicationJson
;
326 base::DictionaryValue root
;
327 root
.SetString("title", new_name_
);
328 base::JSONWriter::Write(&root
, upload_content
);
330 DVLOG(1) << "CopyResource data: " << *upload_content_type
<< ", ["
331 << *upload_content
<< "]";
335 //=========================== TrashResourceOperation ===========================
337 TrashResourceOperation::TrashResourceOperation(
338 OperationRegistry
* registry
,
339 net::URLRequestContextGetter
* url_request_context_getter
,
340 const DriveApiUrlGenerator
& url_generator
,
341 const std::string
& resource_id
,
342 const EntryActionCallback
& callback
)
343 : EntryActionOperation(registry
, url_request_context_getter
, callback
),
344 url_generator_(url_generator
),
345 resource_id_(resource_id
) {
346 DCHECK(!callback
.is_null());
349 TrashResourceOperation::~TrashResourceOperation() {}
351 GURL
TrashResourceOperation::GetURL() const {
352 return url_generator_
.GetFileTrashUrl(resource_id_
);
355 net::URLFetcher::RequestType
TrashResourceOperation::GetRequestType() const {
356 return net::URLFetcher::POST
;
359 //========================== InsertResourceOperation ===========================
361 InsertResourceOperation::InsertResourceOperation(
362 OperationRegistry
* registry
,
363 net::URLRequestContextGetter
* url_request_context_getter
,
364 const DriveApiUrlGenerator
& url_generator
,
365 const std::string
& parent_resource_id
,
366 const std::string
& resource_id
,
367 const EntryActionCallback
& callback
)
368 : EntryActionOperation(registry
, url_request_context_getter
, callback
),
369 url_generator_(url_generator
),
370 parent_resource_id_(parent_resource_id
),
371 resource_id_(resource_id
) {
372 DCHECK(!callback
.is_null());
375 InsertResourceOperation::~InsertResourceOperation() {}
377 GURL
InsertResourceOperation::GetURL() const {
378 return url_generator_
.GetChildrenUrl(parent_resource_id_
);
381 net::URLFetcher::RequestType
InsertResourceOperation::GetRequestType() const {
382 return net::URLFetcher::POST
;
385 bool InsertResourceOperation::GetContentData(std::string
* upload_content_type
,
386 std::string
* upload_content
) {
387 *upload_content_type
= kContentTypeApplicationJson
;
389 base::DictionaryValue root
;
390 root
.SetString("id", resource_id_
);
391 base::JSONWriter::Write(&root
, upload_content
);
393 DVLOG(1) << "InsertResource data: " << *upload_content_type
<< ", ["
394 << *upload_content
<< "]";
398 //========================== DeleteResourceOperation ===========================
400 DeleteResourceOperation::DeleteResourceOperation(
401 OperationRegistry
* registry
,
402 net::URLRequestContextGetter
* url_request_context_getter
,
403 const DriveApiUrlGenerator
& url_generator
,
404 const std::string
& parent_resource_id
,
405 const std::string
& resource_id
,
406 const EntryActionCallback
& callback
)
407 : EntryActionOperation(registry
, url_request_context_getter
, callback
),
408 url_generator_(url_generator
),
409 parent_resource_id_(parent_resource_id
),
410 resource_id_(resource_id
) {
411 DCHECK(!callback
.is_null());
414 DeleteResourceOperation::~DeleteResourceOperation() {}
416 GURL
DeleteResourceOperation::GetURL() const {
417 return url_generator_
.GetChildrenUrlForRemoval(
418 parent_resource_id_
, resource_id_
);
421 net::URLFetcher::RequestType
DeleteResourceOperation::GetRequestType() const {
422 return net::URLFetcher::DELETE_REQUEST
;
425 //======================= InitiateUploadNewFileOperation =======================
427 InitiateUploadNewFileOperation::InitiateUploadNewFileOperation(
428 OperationRegistry
* registry
,
429 net::URLRequestContextGetter
* url_request_context_getter
,
430 const DriveApiUrlGenerator
& url_generator
,
431 const base::FilePath
& drive_file_path
,
432 const std::string
& content_type
,
433 int64 content_length
,
434 const std::string
& parent_resource_id
,
435 const std::string
& title
,
436 const InitiateUploadCallback
& callback
)
437 : InitiateUploadOperationBase(registry
,
438 url_request_context_getter
,
443 url_generator_(url_generator
),
444 parent_resource_id_(parent_resource_id
),
448 InitiateUploadNewFileOperation::~InitiateUploadNewFileOperation() {}
450 GURL
InitiateUploadNewFileOperation::GetURL() const {
451 return url_generator_
.GetInitiateUploadNewFileUrl();
454 net::URLFetcher::RequestType
455 InitiateUploadNewFileOperation::GetRequestType() const {
456 return net::URLFetcher::POST
;
459 bool InitiateUploadNewFileOperation::GetContentData(
460 std::string
* upload_content_type
,
461 std::string
* upload_content
) {
462 *upload_content_type
= kContentTypeApplicationJson
;
464 base::DictionaryValue root
;
465 root
.SetString("title", title_
);
469 scoped_ptr
<base::DictionaryValue
> parent(new base::DictionaryValue
);
470 parent
->SetString("kind", kParentLinkKind
);
471 parent
->SetString("id", parent_resource_id_
);
473 scoped_ptr
<base::ListValue
> parents(new base::ListValue
);
474 parents
->Append(parent
.release());
476 root
.Set("parents", parents
.release());
479 base::JSONWriter::Write(&root
, upload_content
);
481 DVLOG(1) << "InitiateUploadNewFile data: " << *upload_content_type
<< ", ["
482 << *upload_content
<< "]";
486 //===================== InitiateUploadExistingFileOperation ====================
488 InitiateUploadExistingFileOperation::InitiateUploadExistingFileOperation(
489 OperationRegistry
* registry
,
490 net::URLRequestContextGetter
* url_request_context_getter
,
491 const DriveApiUrlGenerator
& url_generator
,
492 const base::FilePath
& drive_file_path
,
493 const std::string
& content_type
,
494 int64 content_length
,
495 const std::string
& resource_id
,
496 const std::string
& etag
,
497 const InitiateUploadCallback
& callback
)
498 : InitiateUploadOperationBase(registry
,
499 url_request_context_getter
,
504 url_generator_(url_generator
),
505 resource_id_(resource_id
),
509 InitiateUploadExistingFileOperation::~InitiateUploadExistingFileOperation() {}
511 GURL
InitiateUploadExistingFileOperation::GetURL() const {
512 return url_generator_
.GetInitiateUploadExistingFileUrl(resource_id_
);
515 net::URLFetcher::RequestType
516 InitiateUploadExistingFileOperation::GetRequestType() const {
517 return net::URLFetcher::PUT
;
520 std::vector
<std::string
>
521 InitiateUploadExistingFileOperation::GetExtraRequestHeaders() const {
522 std::vector
<std::string
> headers(
523 InitiateUploadOperationBase::GetExtraRequestHeaders());
524 headers
.push_back(util::GenerateIfMatchHeader(etag_
));
528 //============================ ResumeUploadOperation ===========================
530 ResumeUploadOperation::ResumeUploadOperation(
531 OperationRegistry
* registry
,
532 net::URLRequestContextGetter
* url_request_context_getter
,
533 UploadMode upload_mode
,
534 const base::FilePath
& drive_file_path
,
535 const GURL
& upload_location
,
536 int64 start_position
,
538 int64 content_length
,
539 const std::string
& content_type
,
540 const scoped_refptr
<net::IOBuffer
>& buf
,
541 const UploadRangeCallback
& callback
,
542 const ProgressCallback
& progress_callback
)
543 : ResumeUploadOperationBase(registry
,
544 url_request_context_getter
,
554 progress_callback_(progress_callback
) {
555 DCHECK(!callback_
.is_null());
558 ResumeUploadOperation::~ResumeUploadOperation() {}
560 void ResumeUploadOperation::OnRangeOperationComplete(
561 const UploadRangeResponse
& response
, scoped_ptr
<base::Value
> value
) {
562 ParseFileResourceWithUploadRangeAndRun(callback_
, response
, value
.Pass());
565 void ResumeUploadOperation::OnURLFetchUploadProgress(
566 const net::URLFetcher
* source
, int64 current
, int64 total
) {
567 ResumeUploadOperationBase::OnURLFetchUploadProgress(source
, current
, total
);
568 if (!progress_callback_
.is_null())
569 progress_callback_
.Run(current
, total
);
573 } // namespace google_apis