drive_api_service.cc 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857
  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. #include "components/drive/service/drive_api_service.h"
  5. #include <stddef.h>
  6. #include <memory>
  7. #include <string>
  8. #include <utility>
  9. #include <vector>
  10. #include "base/bind.h"
  11. #include "base/observer_list.h"
  12. #include "base/strings/stringprintf.h"
  13. #include "components/drive/drive_api_util.h"
  14. #include "google_apis/common/auth_service.h"
  15. #include "google_apis/common/request_sender.h"
  16. #include "google_apis/drive/drive_api_parser.h"
  17. #include "google_apis/drive/drive_api_requests.h"
  18. #include "google_apis/drive/drive_base_requests.h"
  19. #include "google_apis/drive/files_list_request_runner.h"
  20. #include "services/network/public/cpp/shared_url_loader_factory.h"
  21. using google_apis::AboutResourceCallback;
  22. using google_apis::ApiErrorCode;
  23. using google_apis::AuthStatusCallback;
  24. using google_apis::CancelCallbackOnce;
  25. using google_apis::CancelCallbackRepeating;
  26. using google_apis::ChangeList;
  27. using google_apis::ChangeListCallback;
  28. using google_apis::DownloadActionCallback;
  29. using google_apis::EntryActionCallback;
  30. using google_apis::FileList;
  31. using google_apis::FileListCallback;
  32. using google_apis::FileResource;
  33. using google_apis::FileResourceCallback;
  34. using google_apis::FilesListCorpora;
  35. using google_apis::FilesListRequestRunner;
  36. using google_apis::GetContentCallback;
  37. using google_apis::HTTP_NOT_IMPLEMENTED;
  38. using google_apis::HTTP_SUCCESS;
  39. using google_apis::InitiateUploadCallback;
  40. using google_apis::OTHER_ERROR;
  41. using google_apis::PARSE_ERROR;
  42. using google_apis::ProgressCallback;
  43. using google_apis::RequestSender;
  44. using google_apis::StartPageTokenCallback;
  45. using google_apis::TeamDriveListCallback;
  46. using google_apis::UploadRangeResponse;
  47. using google_apis::drive::AboutGetRequest;
  48. using google_apis::drive::ChangesListNextPageRequest;
  49. using google_apis::drive::ChangesListRequest;
  50. using google_apis::drive::ChildrenDeleteRequest;
  51. using google_apis::drive::ChildrenInsertRequest;
  52. using google_apis::drive::DownloadFileRequest;
  53. using google_apis::drive::FilesCopyRequest;
  54. using google_apis::drive::FilesDeleteRequest;
  55. using google_apis::drive::FilesGetRequest;
  56. using google_apis::drive::FilesInsertRequest;
  57. using google_apis::drive::FilesListNextPageRequest;
  58. using google_apis::drive::FilesListRequest;
  59. using google_apis::drive::FilesPatchRequest;
  60. using google_apis::drive::FilesTrashRequest;
  61. using google_apis::drive::GetUploadStatusRequest;
  62. using google_apis::drive::InitiateUploadExistingFileRequest;
  63. using google_apis::drive::InitiateUploadNewFileRequest;
  64. using google_apis::drive::ResumeUploadRequest;
  65. using google_apis::drive::StartPageTokenRequest;
  66. using google_apis::drive::TeamDriveListRequest;
  67. using google_apis::drive::UploadRangeCallback;
  68. namespace drive {
  69. namespace {
  70. // OAuth2 scopes for Drive API.
  71. const char kDriveScope[] = "https://www.googleapis.com/auth/drive";
  72. const char kDriveAppsReadonlyScope[] =
  73. "https://www.googleapis.com/auth/drive.apps.readonly";
  74. const char kDriveAppsScope[] = "https://www.googleapis.com/auth/drive.apps";
  75. // Mime type to create a directory.
  76. const char kFolderMimeType[] = "application/vnd.google-apps.folder";
  77. // Max number of Team Drive entries to be fetched in a single http request.
  78. const int kMaxNumTeamDriveResourcePerRequest = 100;
  79. // Max number of file entries to be fetched in a single http request.
  80. //
  81. // The larger the number is,
  82. // - The total running time to fetch the whole file list will become shorter.
  83. // - The running time for a single request tends to become longer.
  84. // Since the file list fetching is a completely background task, for our side,
  85. // only the total time matters. However, the server seems to have a time limit
  86. // per single request, which disables us to set the largest value (1000).
  87. // TODO(kinaba): make it larger when the server gets faster.
  88. const int kMaxNumFilesResourcePerRequest = 300;
  89. const int kMaxNumFilesResourcePerRequestForSearch = 100;
  90. // For performance, we declare all fields we use.
  91. const char kAboutResourceFields[] =
  92. "kind,quotaBytesTotal,quotaBytesUsedAggregate,largestChangeId,rootFolderId";
  93. const char kFileResourceFields[] =
  94. "kind,id,title,createdDate,sharedWithMeDate,mimeType,"
  95. "md5Checksum,fileSize,labels/trashed,labels/starred,"
  96. "imageMediaMetadata/width,"
  97. "imageMediaMetadata/height,imageMediaMetadata/rotation,etag,"
  98. "parents(id,parentLink),alternateLink,"
  99. "modifiedDate,lastViewedByMeDate,shared,modifiedByMeDate";
  100. const char kFileListFields[] =
  101. "kind,items(kind,id,title,createdDate,sharedWithMeDate,"
  102. "mimeType,md5Checksum,fileSize,labels/trashed,labels/starred,"
  103. "imageMediaMetadata/width,"
  104. "imageMediaMetadata/height,imageMediaMetadata/rotation,etag,"
  105. "parents(id,parentLink),alternateLink,"
  106. "modifiedDate,lastViewedByMeDate,shared,modifiedByMeDate,capabilities),"
  107. "nextLink";
  108. const char kChangeListFields[] =
  109. "kind,items(type,file(kind,id,title,createdDate,sharedWithMeDate,"
  110. "mimeType,md5Checksum,fileSize,labels/trashed,labels/starred,"
  111. "imageMediaMetadata/width,"
  112. "imageMediaMetadata/height,imageMediaMetadata/rotation,etag,"
  113. "parents(id,parentLink),alternateLink,modifiedDate,"
  114. "lastViewedByMeDate,shared,modifiedByMeDate,capabilities),"
  115. "teamDrive(kind,id,name,capabilities),teamDriveId,"
  116. "deleted,id,fileId,modificationDate),nextLink,"
  117. "largestChangeId,newStartPageToken";
  118. const char kTeamDrivesListFields[] =
  119. "nextPageToken,kind,items(kind,id,name,capabilities)";
  120. // Ignores the |entry|, and runs the |callback|.
  121. void EntryActionCallbackAdapter(EntryActionCallback callback,
  122. ApiErrorCode error,
  123. std::unique_ptr<FileResource> entry) {
  124. std::move(callback).Run(error);
  125. }
  126. // The resource ID for the root directory for Drive API is defined in the spec:
  127. // https://developers.google.com/drive/folder
  128. const char kDriveApiRootDirectoryResourceId[] = "root";
  129. } // namespace
  130. BatchRequestConfigurator::BatchRequestConfigurator(
  131. const base::WeakPtr<google_apis::drive::BatchUploadRequest>& batch_request,
  132. base::SequencedTaskRunner* task_runner,
  133. const google_apis::DriveApiUrlGenerator& url_generator,
  134. const google_apis::CancelCallbackRepeating& cancel_callback)
  135. : batch_request_(batch_request),
  136. task_runner_(task_runner),
  137. url_generator_(url_generator),
  138. cancel_callback_(cancel_callback) {}
  139. BatchRequestConfigurator::~BatchRequestConfigurator() {
  140. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  141. // The batch requst has not been committed.
  142. if (batch_request_)
  143. cancel_callback_.Run();
  144. }
  145. google_apis::CancelCallbackOnce
  146. BatchRequestConfigurator::MultipartUploadNewFile(
  147. const std::string& content_type,
  148. int64_t content_length,
  149. const std::string& parent_resource_id,
  150. const std::string& title,
  151. const base::FilePath& local_file_path,
  152. const UploadNewFileOptions& options,
  153. FileResourceCallback callback,
  154. ProgressCallback progress_callback) {
  155. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  156. DCHECK(!callback.is_null());
  157. std::unique_ptr<google_apis::BatchableDelegate> delegate(
  158. new google_apis::drive::MultipartUploadNewFileDelegate(
  159. task_runner_.get(), title, parent_resource_id, content_type,
  160. content_length, options.modified_date, options.last_viewed_by_me_date,
  161. local_file_path, options.properties, url_generator_,
  162. std::move(callback), progress_callback));
  163. // Batch request can be null when pre-authorization for the requst is failed
  164. // in request sender.
  165. if (batch_request_)
  166. batch_request_->AddRequest(delegate.release());
  167. else
  168. delegate->NotifyError(OTHER_ERROR);
  169. return cancel_callback_;
  170. }
  171. google_apis::CancelCallbackOnce
  172. BatchRequestConfigurator::MultipartUploadExistingFile(
  173. const std::string& content_type,
  174. int64_t content_length,
  175. const std::string& resource_id,
  176. const base::FilePath& local_file_path,
  177. const UploadExistingFileOptions& options,
  178. FileResourceCallback callback,
  179. ProgressCallback progress_callback) {
  180. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  181. DCHECK(!callback.is_null());
  182. std::unique_ptr<google_apis::BatchableDelegate> delegate(
  183. new google_apis::drive::MultipartUploadExistingFileDelegate(
  184. task_runner_.get(), options.title, resource_id,
  185. options.parent_resource_id, content_type, content_length,
  186. options.modified_date, options.last_viewed_by_me_date,
  187. local_file_path, options.etag, options.properties, url_generator_,
  188. std::move(callback), progress_callback));
  189. // Batch request can be null when pre-authorization for the requst is failed
  190. // in request sender.
  191. if (batch_request_)
  192. batch_request_->AddRequest(delegate.release());
  193. else
  194. delegate->NotifyError(OTHER_ERROR);
  195. return cancel_callback_;
  196. }
  197. void BatchRequestConfigurator::Commit() {
  198. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  199. if (!batch_request_)
  200. return;
  201. batch_request_->Commit();
  202. batch_request_.reset();
  203. }
  204. DriveAPIService::DriveAPIService(
  205. signin::IdentityManager* identity_manager,
  206. scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
  207. base::SequencedTaskRunner* blocking_task_runner,
  208. const GURL& base_url,
  209. const GURL& base_thumbnail_url,
  210. const std::string& custom_user_agent,
  211. const net::NetworkTrafficAnnotationTag& traffic_annotation)
  212. : identity_manager_(identity_manager),
  213. url_loader_factory_(url_loader_factory),
  214. blocking_task_runner_(blocking_task_runner),
  215. url_generator_(base_url, base_thumbnail_url),
  216. custom_user_agent_(custom_user_agent),
  217. traffic_annotation_(traffic_annotation) {}
  218. DriveAPIService::~DriveAPIService() {
  219. DCHECK(thread_checker_.CalledOnValidThread());
  220. if (sender_)
  221. sender_->auth_service()->RemoveObserver(this);
  222. }
  223. void DriveAPIService::Initialize(const CoreAccountId& account_id) {
  224. DCHECK(thread_checker_.CalledOnValidThread());
  225. std::vector<std::string> scopes;
  226. scopes.push_back(kDriveScope);
  227. scopes.push_back(kDriveAppsReadonlyScope);
  228. scopes.push_back(kDriveAppsScope);
  229. sender_ = std::make_unique<RequestSender>(
  230. std::make_unique<google_apis::AuthService>(identity_manager_, account_id,
  231. url_loader_factory_, scopes),
  232. url_loader_factory_, blocking_task_runner_.get(), custom_user_agent_,
  233. traffic_annotation_);
  234. sender_->auth_service()->AddObserver(this);
  235. files_list_request_runner_ =
  236. std::make_unique<FilesListRequestRunner>(sender_.get(), url_generator_);
  237. }
  238. void DriveAPIService::AddObserver(DriveServiceObserver* observer) {
  239. observers_.AddObserver(observer);
  240. }
  241. void DriveAPIService::RemoveObserver(DriveServiceObserver* observer) {
  242. observers_.RemoveObserver(observer);
  243. }
  244. bool DriveAPIService::CanSendRequest() const {
  245. DCHECK(thread_checker_.CalledOnValidThread());
  246. return HasRefreshToken();
  247. }
  248. std::string DriveAPIService::GetRootResourceId() const {
  249. return kDriveApiRootDirectoryResourceId;
  250. }
  251. CancelCallbackOnce DriveAPIService::GetAllTeamDriveList(
  252. TeamDriveListCallback callback) {
  253. DCHECK(thread_checker_.CalledOnValidThread());
  254. DCHECK(callback);
  255. std::unique_ptr<TeamDriveListRequest> request =
  256. std::make_unique<TeamDriveListRequest>(sender_.get(), url_generator_,
  257. std::move(callback));
  258. request->set_max_results(kMaxNumTeamDriveResourcePerRequest);
  259. request->set_fields(kTeamDrivesListFields);
  260. return sender_->StartRequestWithAuthRetry(std::move(request));
  261. }
  262. CancelCallbackOnce DriveAPIService::GetAllFileList(
  263. const std::string& team_drive_id,
  264. FileListCallback callback) {
  265. DCHECK(thread_checker_.CalledOnValidThread());
  266. DCHECK(!callback.is_null());
  267. std::unique_ptr<FilesListRequest> request =
  268. std::make_unique<FilesListRequest>(sender_.get(), url_generator_,
  269. std::move(callback));
  270. request->set_max_results(kMaxNumFilesResourcePerRequest);
  271. request->set_q("trashed = false"); // Exclude trashed files.
  272. request->set_fields(kFileListFields);
  273. if (team_drive_id.empty()) {
  274. request->set_corpora(google_apis::FilesListCorpora::DEFAULT);
  275. } else {
  276. request->set_team_drive_id(team_drive_id);
  277. request->set_corpora(google_apis::FilesListCorpora::TEAM_DRIVE);
  278. }
  279. return sender_->StartRequestWithAuthRetry(std::move(request));
  280. }
  281. CancelCallbackOnce DriveAPIService::GetFileListInDirectory(
  282. const std::string& directory_resource_id,
  283. FileListCallback callback) {
  284. DCHECK(thread_checker_.CalledOnValidThread());
  285. DCHECK(!directory_resource_id.empty());
  286. DCHECK(!callback.is_null());
  287. // TODO(yamaguchi): Use FileListScope::CreateForTeamDrive instead of
  288. // kAllTeamDrives for efficiency. It'll require to add a new parameter to tell
  289. // which team drive the directory resource belongs to.
  290. FilesListCorpora corpora = google_apis::FilesListCorpora::ALL_TEAM_DRIVES;
  291. // Because children.list method on Drive API v2 returns only the list of
  292. // children's references, but we need all file resource list.
  293. // So, here we use files.list method instead, with setting parents query.
  294. // After the migration from GData WAPI to Drive API v2, we should clean the
  295. // code up by moving the responsibility to include "parents" in the query
  296. // to client side.
  297. // We aren't interested in files in trash in this context, neither.
  298. return files_list_request_runner_->CreateAndStartWithSizeBackoff(
  299. kMaxNumFilesResourcePerRequest, corpora, std::string(),
  300. base::StringPrintf(
  301. "'%s' in parents and trashed = false",
  302. util::EscapeQueryStringValue(directory_resource_id).c_str()),
  303. kFileListFields, std::move(callback));
  304. }
  305. CancelCallbackOnce DriveAPIService::Search(const std::string& search_query,
  306. FileListCallback callback) {
  307. DCHECK(thread_checker_.CalledOnValidThread());
  308. DCHECK(!search_query.empty());
  309. DCHECK(!callback.is_null());
  310. FilesListCorpora corpora = google_apis::FilesListCorpora::ALL_TEAM_DRIVES;
  311. std::string query = util::TranslateQuery(search_query);
  312. if (!query.empty())
  313. query += " and ";
  314. query += "trashed = false";
  315. return files_list_request_runner_->CreateAndStartWithSizeBackoff(
  316. kMaxNumFilesResourcePerRequestForSearch, corpora, std::string(), query,
  317. kFileListFields, std::move(callback));
  318. }
  319. CancelCallbackOnce DriveAPIService::SearchByTitle(
  320. const std::string& title,
  321. const std::string& directory_resource_id,
  322. FileListCallback callback) {
  323. DCHECK(thread_checker_.CalledOnValidThread());
  324. DCHECK(!title.empty());
  325. DCHECK(!callback.is_null());
  326. std::string query;
  327. base::StringAppendF(&query, "title = '%s'",
  328. util::EscapeQueryStringValue(title).c_str());
  329. if (!directory_resource_id.empty()) {
  330. base::StringAppendF(
  331. &query, " and '%s' in parents",
  332. util::EscapeQueryStringValue(directory_resource_id).c_str());
  333. }
  334. query += " and trashed = false";
  335. std::unique_ptr<FilesListRequest> request =
  336. std::make_unique<FilesListRequest>(sender_.get(), url_generator_,
  337. std::move(callback));
  338. request->set_max_results(kMaxNumFilesResourcePerRequest);
  339. request->set_q(query);
  340. request->set_fields(kFileListFields);
  341. return sender_->StartRequestWithAuthRetry(std::move(request));
  342. }
  343. CancelCallbackOnce DriveAPIService::GetChangeList(int64_t start_changestamp,
  344. ChangeListCallback callback) {
  345. DCHECK(thread_checker_.CalledOnValidThread());
  346. DCHECK(callback);
  347. std::unique_ptr<ChangesListRequest> request =
  348. std::make_unique<ChangesListRequest>(sender_.get(), url_generator_,
  349. std::move(callback));
  350. request->set_max_results(kMaxNumFilesResourcePerRequest);
  351. request->set_start_change_id(start_changestamp);
  352. request->set_fields(kChangeListFields);
  353. return sender_->StartRequestWithAuthRetry(std::move(request));
  354. }
  355. CancelCallbackOnce DriveAPIService::GetChangeListByToken(
  356. const std::string& team_drive_id,
  357. const std::string& start_page_token,
  358. ChangeListCallback callback) {
  359. DCHECK(thread_checker_.CalledOnValidThread());
  360. DCHECK(callback);
  361. std::unique_ptr<ChangesListRequest> request =
  362. std::make_unique<ChangesListRequest>(sender_.get(), url_generator_,
  363. std::move(callback));
  364. request->set_max_results(kMaxNumFilesResourcePerRequest);
  365. request->set_page_token(start_page_token);
  366. request->set_team_drive_id(team_drive_id);
  367. request->set_fields(kChangeListFields);
  368. return sender_->StartRequestWithAuthRetry(std::move(request));
  369. }
  370. CancelCallbackOnce DriveAPIService::GetRemainingChangeList(
  371. const GURL& next_link,
  372. ChangeListCallback callback) {
  373. DCHECK(thread_checker_.CalledOnValidThread());
  374. DCHECK(!next_link.is_empty());
  375. DCHECK(callback);
  376. std::unique_ptr<ChangesListNextPageRequest> request =
  377. std::make_unique<ChangesListNextPageRequest>(sender_.get(),
  378. std::move(callback));
  379. request->set_next_link(next_link);
  380. request->set_fields(kChangeListFields);
  381. return sender_->StartRequestWithAuthRetry(std::move(request));
  382. }
  383. CancelCallbackOnce DriveAPIService::GetRemainingTeamDriveList(
  384. const std::string& page_token,
  385. TeamDriveListCallback callback) {
  386. DCHECK(thread_checker_.CalledOnValidThread());
  387. DCHECK(!page_token.empty());
  388. DCHECK(callback);
  389. std::unique_ptr<TeamDriveListRequest> request =
  390. std::make_unique<TeamDriveListRequest>(sender_.get(), url_generator_,
  391. std::move(callback));
  392. request->set_page_token(page_token);
  393. request->set_max_results(kMaxNumTeamDriveResourcePerRequest);
  394. request->set_fields(kTeamDrivesListFields);
  395. return sender_->StartRequestWithAuthRetry(std::move(request));
  396. }
  397. CancelCallbackOnce DriveAPIService::GetRemainingFileList(
  398. const GURL& next_link,
  399. FileListCallback callback) {
  400. DCHECK(thread_checker_.CalledOnValidThread());
  401. DCHECK(!next_link.is_empty());
  402. DCHECK(!callback.is_null());
  403. std::unique_ptr<FilesListNextPageRequest> request =
  404. std::make_unique<FilesListNextPageRequest>(sender_.get(),
  405. std::move(callback));
  406. request->set_next_link(next_link);
  407. request->set_fields(kFileListFields);
  408. return sender_->StartRequestWithAuthRetry(std::move(request));
  409. }
  410. CancelCallbackOnce DriveAPIService::GetFileResource(
  411. const std::string& resource_id,
  412. FileResourceCallback callback) {
  413. DCHECK(thread_checker_.CalledOnValidThread());
  414. DCHECK(!callback.is_null());
  415. std::unique_ptr<FilesGetRequest> request = std::make_unique<FilesGetRequest>(
  416. sender_.get(), url_generator_, std::move(callback));
  417. request->set_file_id(resource_id);
  418. request->set_fields(kFileResourceFields);
  419. return sender_->StartRequestWithAuthRetry(std::move(request));
  420. }
  421. CancelCallbackOnce DriveAPIService::GetAboutResource(
  422. AboutResourceCallback callback) {
  423. DCHECK(thread_checker_.CalledOnValidThread());
  424. DCHECK(callback);
  425. std::unique_ptr<AboutGetRequest> request = std::make_unique<AboutGetRequest>(
  426. sender_.get(), url_generator_, std::move(callback));
  427. request->set_fields(kAboutResourceFields);
  428. return sender_->StartRequestWithAuthRetry(std::move(request));
  429. }
  430. CancelCallbackOnce DriveAPIService::GetStartPageToken(
  431. const std::string& team_drive_id,
  432. StartPageTokenCallback callback) {
  433. DCHECK(thread_checker_.CalledOnValidThread());
  434. DCHECK(!callback.is_null());
  435. std::unique_ptr<StartPageTokenRequest> request =
  436. std::make_unique<StartPageTokenRequest>(sender_.get(), url_generator_,
  437. std::move(callback));
  438. request->set_team_drive_id(team_drive_id);
  439. return sender_->StartRequestWithAuthRetry(std::move(request));
  440. }
  441. CancelCallbackOnce DriveAPIService::DownloadFile(
  442. const base::FilePath& local_cache_path,
  443. const std::string& resource_id,
  444. DownloadActionCallback download_action_callback,
  445. const GetContentCallback& get_content_callback,
  446. ProgressCallback progress_callback) {
  447. DCHECK(thread_checker_.CalledOnValidThread());
  448. DCHECK(!download_action_callback.is_null());
  449. // get_content_callback may be null.
  450. return sender_->StartRequestWithAuthRetry(
  451. std::make_unique<DownloadFileRequest>(
  452. sender_.get(), url_generator_, resource_id, local_cache_path,
  453. std::move(download_action_callback), get_content_callback,
  454. progress_callback));
  455. }
  456. CancelCallbackOnce DriveAPIService::DeleteResource(
  457. const std::string& resource_id,
  458. const std::string& etag,
  459. EntryActionCallback callback) {
  460. DCHECK(thread_checker_.CalledOnValidThread());
  461. DCHECK(callback);
  462. std::unique_ptr<FilesDeleteRequest> request =
  463. std::make_unique<FilesDeleteRequest>(sender_.get(), url_generator_,
  464. std::move(callback));
  465. request->set_file_id(resource_id);
  466. request->set_etag(etag);
  467. return sender_->StartRequestWithAuthRetry(std::move(request));
  468. }
  469. CancelCallbackOnce DriveAPIService::TrashResource(
  470. const std::string& resource_id,
  471. EntryActionCallback callback) {
  472. DCHECK(thread_checker_.CalledOnValidThread());
  473. DCHECK(callback);
  474. std::unique_ptr<FilesTrashRequest> request =
  475. std::make_unique<FilesTrashRequest>(
  476. sender_.get(), url_generator_,
  477. base::BindOnce(&EntryActionCallbackAdapter, std::move(callback)));
  478. request->set_file_id(resource_id);
  479. request->set_fields(kFileResourceFields);
  480. return sender_->StartRequestWithAuthRetry(std::move(request));
  481. }
  482. CancelCallbackOnce DriveAPIService::AddNewDirectory(
  483. const std::string& parent_resource_id,
  484. const std::string& directory_title,
  485. const AddNewDirectoryOptions& options,
  486. FileResourceCallback callback) {
  487. DCHECK(thread_checker_.CalledOnValidThread());
  488. DCHECK(!callback.is_null());
  489. std::unique_ptr<FilesInsertRequest> request =
  490. std::make_unique<FilesInsertRequest>(sender_.get(), url_generator_,
  491. std::move(callback));
  492. request->set_visibility(options.visibility);
  493. request->set_last_viewed_by_me_date(options.last_viewed_by_me_date);
  494. request->set_mime_type(kFolderMimeType);
  495. request->set_modified_date(options.modified_date);
  496. request->add_parent(parent_resource_id);
  497. request->set_title(directory_title);
  498. request->set_properties(options.properties);
  499. request->set_fields(kFileResourceFields);
  500. return sender_->StartRequestWithAuthRetry(std::move(request));
  501. }
  502. CancelCallbackOnce DriveAPIService::CopyResource(
  503. const std::string& resource_id,
  504. const std::string& parent_resource_id,
  505. const std::string& new_title,
  506. const base::Time& last_modified,
  507. FileResourceCallback callback) {
  508. DCHECK(thread_checker_.CalledOnValidThread());
  509. DCHECK(!callback.is_null());
  510. std::unique_ptr<FilesCopyRequest> request =
  511. std::make_unique<FilesCopyRequest>(sender_.get(), url_generator_,
  512. std::move(callback));
  513. request->set_file_id(resource_id);
  514. request->add_parent(parent_resource_id);
  515. request->set_title(new_title);
  516. request->set_modified_date(last_modified);
  517. request->set_fields(kFileResourceFields);
  518. return sender_->StartRequestWithAuthRetry(std::move(request));
  519. }
  520. CancelCallbackOnce DriveAPIService::UpdateResource(
  521. const std::string& resource_id,
  522. const std::string& parent_resource_id,
  523. const std::string& new_title,
  524. const base::Time& last_modified,
  525. const base::Time& last_viewed_by_me,
  526. const google_apis::drive::Properties& properties,
  527. FileResourceCallback callback) {
  528. DCHECK(thread_checker_.CalledOnValidThread());
  529. DCHECK(!callback.is_null());
  530. std::unique_ptr<FilesPatchRequest> request =
  531. std::make_unique<FilesPatchRequest>(sender_.get(), url_generator_,
  532. std::move(callback));
  533. request->set_file_id(resource_id);
  534. request->set_title(new_title);
  535. if (!parent_resource_id.empty())
  536. request->add_parent(parent_resource_id);
  537. if (!last_modified.is_null()) {
  538. // Need to set setModifiedDate to true to overwrite modifiedDate.
  539. request->set_set_modified_date(true);
  540. request->set_modified_date(last_modified);
  541. }
  542. if (!last_viewed_by_me.is_null()) {
  543. // Need to set updateViewedDate to false, otherwise the lastViewedByMeDate
  544. // will be set to the request time (not the specified time via request).
  545. request->set_update_viewed_date(false);
  546. request->set_last_viewed_by_me_date(last_viewed_by_me);
  547. }
  548. request->set_fields(kFileResourceFields);
  549. request->set_properties(properties);
  550. return sender_->StartRequestWithAuthRetry(std::move(request));
  551. }
  552. CancelCallbackOnce DriveAPIService::AddResourceToDirectory(
  553. const std::string& parent_resource_id,
  554. const std::string& resource_id,
  555. EntryActionCallback callback) {
  556. DCHECK(thread_checker_.CalledOnValidThread());
  557. DCHECK(callback);
  558. std::unique_ptr<ChildrenInsertRequest> request =
  559. std::make_unique<ChildrenInsertRequest>(sender_.get(), url_generator_,
  560. std::move(callback));
  561. request->set_folder_id(parent_resource_id);
  562. request->set_id(resource_id);
  563. return sender_->StartRequestWithAuthRetry(std::move(request));
  564. }
  565. CancelCallbackOnce DriveAPIService::RemoveResourceFromDirectory(
  566. const std::string& parent_resource_id,
  567. const std::string& resource_id,
  568. EntryActionCallback callback) {
  569. DCHECK(thread_checker_.CalledOnValidThread());
  570. DCHECK(callback);
  571. std::unique_ptr<ChildrenDeleteRequest> request =
  572. std::make_unique<ChildrenDeleteRequest>(sender_.get(), url_generator_,
  573. std::move(callback));
  574. request->set_child_id(resource_id);
  575. request->set_folder_id(parent_resource_id);
  576. return sender_->StartRequestWithAuthRetry(std::move(request));
  577. }
  578. CancelCallbackOnce DriveAPIService::InitiateUploadNewFile(
  579. const std::string& content_type,
  580. int64_t content_length,
  581. const std::string& parent_resource_id,
  582. const std::string& title,
  583. const UploadNewFileOptions& options,
  584. InitiateUploadCallback callback) {
  585. DCHECK(thread_checker_.CalledOnValidThread());
  586. DCHECK(!callback.is_null());
  587. std::unique_ptr<InitiateUploadNewFileRequest> request =
  588. std::make_unique<InitiateUploadNewFileRequest>(
  589. sender_.get(), url_generator_, content_type, content_length,
  590. parent_resource_id, title, std::move(callback));
  591. request->set_modified_date(options.modified_date);
  592. request->set_last_viewed_by_me_date(options.last_viewed_by_me_date);
  593. request->set_properties(options.properties);
  594. return sender_->StartRequestWithAuthRetry(std::move(request));
  595. }
  596. CancelCallbackOnce DriveAPIService::InitiateUploadExistingFile(
  597. const std::string& content_type,
  598. int64_t content_length,
  599. const std::string& resource_id,
  600. const UploadExistingFileOptions& options,
  601. InitiateUploadCallback callback) {
  602. DCHECK(thread_checker_.CalledOnValidThread());
  603. DCHECK(!callback.is_null());
  604. std::unique_ptr<InitiateUploadExistingFileRequest> request =
  605. std::make_unique<InitiateUploadExistingFileRequest>(
  606. sender_.get(), url_generator_, content_type, content_length,
  607. resource_id, options.etag, std::move(callback));
  608. request->set_parent_resource_id(options.parent_resource_id);
  609. request->set_title(options.title);
  610. request->set_modified_date(options.modified_date);
  611. request->set_last_viewed_by_me_date(options.last_viewed_by_me_date);
  612. request->set_properties(options.properties);
  613. return sender_->StartRequestWithAuthRetry(std::move(request));
  614. }
  615. CancelCallbackOnce DriveAPIService::ResumeUpload(
  616. const GURL& upload_url,
  617. int64_t start_position,
  618. int64_t end_position,
  619. int64_t content_length,
  620. const std::string& content_type,
  621. const base::FilePath& local_file_path,
  622. UploadRangeCallback callback,
  623. ProgressCallback progress_callback) {
  624. DCHECK(thread_checker_.CalledOnValidThread());
  625. DCHECK(!callback.is_null());
  626. return sender_->StartRequestWithAuthRetry(
  627. std::make_unique<ResumeUploadRequest>(
  628. sender_.get(), upload_url, start_position, end_position,
  629. content_length, content_type, local_file_path, std::move(callback),
  630. progress_callback));
  631. }
  632. CancelCallbackOnce DriveAPIService::GetUploadStatus(
  633. const GURL& upload_url,
  634. int64_t content_length,
  635. UploadRangeCallback callback) {
  636. DCHECK(thread_checker_.CalledOnValidThread());
  637. DCHECK(!callback.is_null());
  638. return sender_->StartRequestWithAuthRetry(
  639. std::make_unique<GetUploadStatusRequest>(
  640. sender_.get(), upload_url, content_length, std::move(callback)));
  641. }
  642. CancelCallbackOnce DriveAPIService::MultipartUploadNewFile(
  643. const std::string& content_type,
  644. int64_t content_length,
  645. const std::string& parent_resource_id,
  646. const std::string& title,
  647. const base::FilePath& local_file_path,
  648. const drive::UploadNewFileOptions& options,
  649. FileResourceCallback callback,
  650. ProgressCallback progress_callback) {
  651. DCHECK(thread_checker_.CalledOnValidThread());
  652. DCHECK(!callback.is_null());
  653. return sender_->StartRequestWithAuthRetry(
  654. std::make_unique<google_apis::drive::SingleBatchableDelegateRequest>(
  655. sender_.get(),
  656. std::make_unique<google_apis::drive::MultipartUploadNewFileDelegate>(
  657. sender_->blocking_task_runner(), title, parent_resource_id,
  658. content_type, content_length, options.modified_date,
  659. options.last_viewed_by_me_date, local_file_path,
  660. options.properties, url_generator_, std::move(callback),
  661. progress_callback)));
  662. }
  663. CancelCallbackOnce DriveAPIService::MultipartUploadExistingFile(
  664. const std::string& content_type,
  665. int64_t content_length,
  666. const std::string& resource_id,
  667. const base::FilePath& local_file_path,
  668. const drive::UploadExistingFileOptions& options,
  669. FileResourceCallback callback,
  670. ProgressCallback progress_callback) {
  671. DCHECK(thread_checker_.CalledOnValidThread());
  672. DCHECK(!callback.is_null());
  673. return sender_->StartRequestWithAuthRetry(
  674. std::make_unique<google_apis::drive::SingleBatchableDelegateRequest>(
  675. sender_.get(),
  676. std::make_unique<
  677. google_apis::drive::MultipartUploadExistingFileDelegate>(
  678. sender_->blocking_task_runner(), options.title, resource_id,
  679. options.parent_resource_id, content_type, content_length,
  680. options.modified_date, options.last_viewed_by_me_date,
  681. local_file_path, options.etag, options.properties, url_generator_,
  682. std::move(callback), progress_callback)));
  683. }
  684. google_apis::CancelCallbackOnce DriveAPIService::AddPermission(
  685. const std::string& resource_id,
  686. const std::string& email,
  687. google_apis::drive::PermissionRole role,
  688. google_apis::EntryActionCallback callback) {
  689. DCHECK(thread_checker_.CalledOnValidThread());
  690. DCHECK(callback);
  691. std::unique_ptr<google_apis::drive::PermissionsInsertRequest> request =
  692. std::make_unique<google_apis::drive::PermissionsInsertRequest>(
  693. sender_.get(), url_generator_, std::move(callback));
  694. request->set_id(resource_id);
  695. request->set_role(role);
  696. request->set_type(google_apis::drive::PERMISSION_TYPE_USER);
  697. request->set_value(email);
  698. return sender_->StartRequestWithAuthRetry(std::move(request));
  699. }
  700. bool DriveAPIService::HasAccessToken() const {
  701. DCHECK(thread_checker_.CalledOnValidThread());
  702. return sender_->auth_service()->HasAccessToken();
  703. }
  704. void DriveAPIService::RequestAccessToken(AuthStatusCallback callback) {
  705. DCHECK(thread_checker_.CalledOnValidThread());
  706. DCHECK(callback);
  707. const std::string access_token = sender_->auth_service()->access_token();
  708. if (!access_token.empty()) {
  709. std::move(callback).Run(google_apis::HTTP_NOT_MODIFIED, access_token);
  710. return;
  711. }
  712. // Retrieve the new auth token.
  713. sender_->auth_service()->StartAuthentication(std::move(callback));
  714. }
  715. bool DriveAPIService::HasRefreshToken() const {
  716. DCHECK(thread_checker_.CalledOnValidThread());
  717. return sender_->auth_service()->HasRefreshToken();
  718. }
  719. void DriveAPIService::ClearAccessToken() {
  720. DCHECK(thread_checker_.CalledOnValidThread());
  721. sender_->auth_service()->ClearAccessToken();
  722. }
  723. void DriveAPIService::ClearRefreshToken() {
  724. DCHECK(thread_checker_.CalledOnValidThread());
  725. sender_->auth_service()->ClearRefreshToken();
  726. }
  727. void DriveAPIService::OnOAuth2RefreshTokenChanged() {
  728. DCHECK(thread_checker_.CalledOnValidThread());
  729. if (CanSendRequest()) {
  730. for (auto& observer : observers_)
  731. observer.OnReadyToSendRequests();
  732. } else if (!HasRefreshToken()) {
  733. for (auto& observer : observers_)
  734. observer.OnRefreshTokenInvalid();
  735. }
  736. }
  737. std::unique_ptr<BatchRequestConfiguratorInterface>
  738. DriveAPIService::StartBatchRequest() {
  739. std::unique_ptr<google_apis::drive::BatchUploadRequest> request =
  740. std::make_unique<google_apis::drive::BatchUploadRequest>(sender_.get(),
  741. url_generator_);
  742. const base::WeakPtr<google_apis::drive::BatchUploadRequest> weak_ref =
  743. request->GetWeakPtrAsBatchUploadRequest();
  744. // Have sender_ manage the lifetime of the request.
  745. // TODO(hirono): Currently we need to pass the ownership of the request to
  746. // RequestSender before the request is committed because the request has a
  747. // reference to RequestSender and we should ensure to delete the request when
  748. // the sender is deleted. Resolve the circulating dependency and fix it.
  749. const google_apis::CancelCallbackRepeating callback =
  750. sender_->StartRequestWithAuthRetry(std::move(request));
  751. return std::make_unique<BatchRequestConfigurator>(
  752. weak_ref, sender_->blocking_task_runner(), url_generator_, callback);
  753. }
  754. } // namespace drive