1 // Copyright 2013 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/chromeos/extensions/file_manager/private_api_drive.h"
10 #include "base/command_line.h"
11 #include "chrome/browser/browser_process.h"
12 #include "chrome/browser/chromeos/drive/drive_integration_service.h"
13 #include "chrome/browser/chromeos/drive/file_system_util.h"
14 #include "chrome/browser/chromeos/extensions/file_manager/private_api_util.h"
15 #include "chrome/browser/chromeos/file_manager/file_tasks.h"
16 #include "chrome/browser/chromeos/file_manager/fileapi_util.h"
17 #include "chrome/browser/chromeos/file_manager/url_util.h"
18 #include "chrome/browser/chromeos/file_system_provider/mount_path_util.h"
19 #include "chrome/browser/chromeos/file_system_provider/provided_file_system_interface.h"
20 #include "chrome/browser/chromeos/fileapi/external_file_url_util.h"
21 #include "chrome/browser/chromeos/fileapi/file_system_backend.h"
22 #include "chrome/browser/chromeos/profiles/profile_helper.h"
23 #include "chrome/browser/profiles/profile.h"
24 #include "chrome/browser/profiles/profile_manager.h"
25 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
26 #include "chrome/browser/signin/signin_manager_factory.h"
27 #include "chrome/common/extensions/api/file_manager_private_internal.h"
28 #include "chromeos/chromeos_switches.h"
29 #include "chromeos/network/network_handler.h"
30 #include "chromeos/network/network_state_handler.h"
31 #include "components/drive/drive_app_registry.h"
32 #include "components/drive/event_logger.h"
33 #include "components/signin/core/browser/profile_oauth2_token_service.h"
34 #include "components/signin/core/browser/signin_manager.h"
35 #include "content/public/browser/browser_thread.h"
36 #include "google_apis/drive/auth_service.h"
37 #include "google_apis/drive/drive_api_url_generator.h"
38 #include "storage/common/fileapi/file_system_info.h"
39 #include "storage/common/fileapi/file_system_util.h"
42 using content::BrowserThread
;
44 using chromeos::file_system_provider::EntryMetadata
;
45 using chromeos::file_system_provider::ProvidedFileSystemInterface
;
46 using chromeos::file_system_provider::util::FileSystemURLParser
;
47 using extensions::api::file_manager_private::EntryProperties
;
48 using extensions::api::file_manager_private::EntryPropertyName
;
49 using file_manager::util::EntryDefinition
;
50 using file_manager::util::EntryDefinitionCallback
;
51 using file_manager::util::EntryDefinitionList
;
52 using file_manager::util::EntryDefinitionListCallback
;
53 using file_manager::util::FileDefinition
;
54 using file_manager::util::FileDefinitionList
;
55 using google_apis::DriveApiUrlGenerator
;
57 namespace extensions
{
60 // List of connection types of drive.
61 // Keep this in sync with the DriveConnectionType in common/js/util.js.
62 const char kDriveConnectionTypeOffline
[] = "offline";
63 const char kDriveConnectionTypeMetered
[] = "metered";
64 const char kDriveConnectionTypeOnline
[] = "online";
66 // List of reasons of kDriveConnectionType*.
67 // Keep this in sync with the DriveConnectionReason in common/js/util.js.
68 const char kDriveConnectionReasonNotReady
[] = "not_ready";
69 const char kDriveConnectionReasonNoNetwork
[] = "no_network";
70 const char kDriveConnectionReasonNoService
[] = "no_service";
72 // Maximum dimension of thumbnail in file manager. File manager shows 180x180
73 // thumbnail. Given that we support hdpi devices, maximum dimension is 360.
74 const int kFileManagerMaximumThumbnailDimension
= 360;
76 // Copies properties from |entry_proto| to |properties|. |shared_with_me| is
77 // given from the running profile.
78 void FillEntryPropertiesValueForDrive(const drive::ResourceEntry
& entry_proto
,
80 EntryProperties
* properties
) {
81 properties
->shared_with_me
.reset(new bool(shared_with_me
));
82 properties
->shared
.reset(new bool(entry_proto
.shared()));
84 const drive::PlatformFileInfoProto
& file_info
= entry_proto
.file_info();
85 properties
->size
.reset(new double(file_info
.size()));
86 properties
->modification_time
.reset(new double(
87 base::Time::FromInternalValue(file_info
.last_modified()).ToJsTime()));
89 if (!entry_proto
.has_file_specific_info())
92 const drive::FileSpecificInfo
& file_specific_info
=
93 entry_proto
.file_specific_info();
95 if (!entry_proto
.resource_id().empty()) {
96 DriveApiUrlGenerator
url_generator(
97 (GURL(google_apis::DriveApiUrlGenerator::kBaseUrlForProduction
)),
99 google_apis::DriveApiUrlGenerator::kBaseDownloadUrlForProduction
)));
100 properties
->thumbnail_url
.reset(new std::string(
101 url_generator
.GetThumbnailUrl(entry_proto
.resource_id(),
102 500 /* width */, 500 /* height */,
103 false /* not cropped */).spec()));
104 properties
->cropped_thumbnail_url
.reset(new std::string(
105 url_generator
.GetThumbnailUrl(
106 entry_proto
.resource_id(),
107 kFileManagerMaximumThumbnailDimension
/* width */,
108 kFileManagerMaximumThumbnailDimension
/* height */,
109 true /* cropped */).spec()));
111 if (file_specific_info
.has_image_width()) {
112 properties
->image_width
.reset(
113 new int(file_specific_info
.image_width()));
115 if (file_specific_info
.has_image_height()) {
116 properties
->image_height
.reset(
117 new int(file_specific_info
.image_height()));
119 if (file_specific_info
.has_image_rotation()) {
120 properties
->image_rotation
.reset(
121 new int(file_specific_info
.image_rotation()));
123 properties
->hosted
.reset(new bool(file_specific_info
.is_hosted_document()));
124 properties
->content_mime_type
.reset(
125 new std::string(file_specific_info
.content_mime_type()));
126 properties
->pinned
.reset(
127 new bool(file_specific_info
.cache_state().is_pinned()));
128 properties
->dirty
.reset(
129 new bool(file_specific_info
.cache_state().is_dirty()));
130 properties
->present
.reset(
131 new bool(file_specific_info
.cache_state().is_present()));
133 if (file_specific_info
.cache_state().is_present()) {
134 properties
->available_offline
.reset(new bool(true));
135 } else if (file_specific_info
.is_hosted_document() &&
136 file_specific_info
.has_document_extension()) {
137 const std::string file_extension
= file_specific_info
.document_extension();
138 // What's available offline? See the 'Web' column at:
139 // https://support.google.com/drive/answer/1628467
140 properties
->available_offline
.reset(
141 new bool(file_extension
== ".gdoc" || file_extension
== ".gdraw" ||
142 file_extension
== ".gsheet" || file_extension
== ".gslides"));
144 properties
->available_offline
.reset(new bool(false));
147 properties
->available_when_metered
.reset(
148 new bool(file_specific_info
.cache_state().is_present() ||
149 file_specific_info
.is_hosted_document()));
152 // Creates entry definition list for (metadata) search result info list.
154 void ConvertSearchResultInfoListToEntryDefinitionList(
156 const std::string
& extension_id
,
157 const std::vector
<T
>& search_result_info_list
,
158 const EntryDefinitionListCallback
& callback
) {
159 FileDefinitionList file_definition_list
;
161 for (size_t i
= 0; i
< search_result_info_list
.size(); ++i
) {
162 FileDefinition file_definition
;
163 file_definition
.virtual_path
=
164 file_manager::util::ConvertDrivePathToRelativeFileSystemPath(
165 profile
, extension_id
, search_result_info_list
.at(i
).path
);
166 file_definition
.is_directory
= search_result_info_list
.at(i
).is_directory
;
167 file_definition_list
.push_back(file_definition
);
170 file_manager::util::ConvertFileDefinitionListToEntryDefinitionList(
173 file_definition_list
, // Safe, since copied internally.
177 class SingleEntryPropertiesGetterForDrive
{
179 typedef base::Callback
<void(scoped_ptr
<EntryProperties
> properties
,
180 base::File::Error error
)> ResultCallback
;
182 // Creates an instance and starts the process.
183 static void Start(const base::FilePath local_path
,
184 const std::set
<EntryPropertyName
>& names
,
185 Profile
* const profile
,
186 const ResultCallback
& callback
) {
187 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
189 SingleEntryPropertiesGetterForDrive
* instance
=
190 new SingleEntryPropertiesGetterForDrive(local_path
, names
, profile
,
192 instance
->StartProcess();
194 // The instance will be destroyed by itself.
197 virtual ~SingleEntryPropertiesGetterForDrive() {}
200 SingleEntryPropertiesGetterForDrive(
201 const base::FilePath local_path
,
202 const std::set
<EntryPropertyName
>& /* names */,
203 Profile
* const profile
,
204 const ResultCallback
& callback
)
205 : callback_(callback
),
206 local_path_(local_path
),
207 running_profile_(profile
),
208 properties_(new EntryProperties
),
209 file_owner_profile_(NULL
),
210 weak_ptr_factory_(this) {
211 DCHECK(!callback_
.is_null());
215 void StartProcess() {
216 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
218 file_path_
= drive::util::ExtractDrivePath(local_path_
);
219 file_owner_profile_
= drive::util::ExtractProfileFromPath(local_path_
);
221 if (!file_owner_profile_
||
222 !g_browser_process
->profile_manager()->IsValidProfile(
223 file_owner_profile_
)) {
224 CompleteGetEntryProperties(drive::FILE_ERROR_FAILED
);
228 // Start getting the file info.
229 drive::FileSystemInterface
* const file_system
=
230 drive::util::GetFileSystemByProfile(file_owner_profile_
);
232 // |file_system| is NULL if Drive is disabled or not mounted.
233 CompleteGetEntryProperties(drive::FILE_ERROR_FAILED
);
237 file_system
->GetResourceEntry(
239 base::Bind(&SingleEntryPropertiesGetterForDrive::OnGetFileInfo
,
240 weak_ptr_factory_
.GetWeakPtr()));
243 void OnGetFileInfo(drive::FileError error
,
244 scoped_ptr
<drive::ResourceEntry
> entry
) {
245 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
247 if (error
!= drive::FILE_ERROR_OK
) {
248 CompleteGetEntryProperties(error
);
253 owner_resource_entry_
.swap(entry
);
255 if (running_profile_
->IsSameProfile(file_owner_profile_
)) {
256 StartParseFileInfo(owner_resource_entry_
->shared_with_me());
260 // If the running profile does not own the file, obtain the shared_with_me
261 // flag from the running profile's value.
262 drive::FileSystemInterface
* const file_system
=
263 drive::util::GetFileSystemByProfile(running_profile_
);
265 CompleteGetEntryProperties(drive::FILE_ERROR_FAILED
);
268 file_system
->GetPathFromResourceId(
269 owner_resource_entry_
->resource_id(),
270 base::Bind(&SingleEntryPropertiesGetterForDrive::OnGetRunningPath
,
271 weak_ptr_factory_
.GetWeakPtr()));
274 void OnGetRunningPath(drive::FileError error
,
275 const base::FilePath
& file_path
) {
276 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
278 if (error
!= drive::FILE_ERROR_OK
) {
279 // The running profile does not know the file.
280 StartParseFileInfo(false);
284 drive::FileSystemInterface
* const file_system
=
285 drive::util::GetFileSystemByProfile(running_profile_
);
287 // The drive is disable for the running profile.
288 StartParseFileInfo(false);
292 file_system
->GetResourceEntry(
294 base::Bind(&SingleEntryPropertiesGetterForDrive::OnGetShareInfo
,
295 weak_ptr_factory_
.GetWeakPtr()));
298 void OnGetShareInfo(drive::FileError error
,
299 scoped_ptr
<drive::ResourceEntry
> entry
) {
300 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
302 if (error
!= drive::FILE_ERROR_OK
) {
303 CompleteGetEntryProperties(error
);
308 StartParseFileInfo(entry
->shared_with_me());
311 void StartParseFileInfo(bool shared_with_me
) {
312 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
314 FillEntryPropertiesValueForDrive(
315 *owner_resource_entry_
, shared_with_me
, properties_
.get());
317 drive::FileSystemInterface
* const file_system
=
318 drive::util::GetFileSystemByProfile(file_owner_profile_
);
319 drive::DriveAppRegistry
* const app_registry
=
320 drive::util::GetDriveAppRegistryByProfile(file_owner_profile_
);
321 if (!file_system
|| !app_registry
) {
322 // |file_system| or |app_registry| is NULL if Drive is disabled.
323 CompleteGetEntryProperties(drive::FILE_ERROR_FAILED
);
327 // The properties meaningful for directories are already filled in
328 // FillEntryPropertiesValueForDrive().
329 if (!owner_resource_entry_
->has_file_specific_info()) {
330 CompleteGetEntryProperties(drive::FILE_ERROR_OK
);
334 const drive::FileSpecificInfo
& file_specific_info
=
335 owner_resource_entry_
->file_specific_info();
337 // Get drive WebApps that can accept this file. We just need to extract the
338 // doc icon for the drive app, which is set as default.
339 std::vector
<drive::DriveAppInfo
> drive_apps
;
340 app_registry
->GetAppsForFile(file_path_
.Extension(),
341 file_specific_info
.content_mime_type(),
343 if (!drive_apps
.empty()) {
344 std::string default_task_id
=
345 file_manager::file_tasks::GetDefaultTaskIdFromPrefs(
346 *file_owner_profile_
->GetPrefs(),
347 file_specific_info
.content_mime_type(),
348 file_path_
.Extension());
349 file_manager::file_tasks::TaskDescriptor default_task
;
350 file_manager::file_tasks::ParseTaskID(default_task_id
, &default_task
);
351 DCHECK(default_task_id
.empty() || !default_task
.app_id
.empty());
352 for (size_t i
= 0; i
< drive_apps
.size(); ++i
) {
353 const drive::DriveAppInfo
& app_info
= drive_apps
[i
];
354 if (default_task
.app_id
== app_info
.app_id
) {
355 // The drive app is set as default. Files.app should use the doc icon.
356 const GURL doc_icon
= drive::util::FindPreferredIcon(
357 app_info
.document_icons
, drive::util::kPreferredIconSize
);
358 properties_
->custom_icon_url
.reset(new std::string(doc_icon
.spec()));
363 CompleteGetEntryProperties(drive::FILE_ERROR_OK
);
366 void CompleteGetEntryProperties(drive::FileError error
) {
367 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
368 DCHECK(!callback_
.is_null());
370 callback_
.Run(properties_
.Pass(), drive::FileErrorToBaseFileError(error
));
371 BrowserThread::DeleteSoon(BrowserThread::UI
, FROM_HERE
, this);
375 const ResultCallback callback_
;
376 const base::FilePath local_path_
;
377 Profile
* const running_profile_
;
379 // Values used in the process.
380 scoped_ptr
<EntryProperties
> properties_
;
381 Profile
* file_owner_profile_
;
382 base::FilePath file_path_
;
383 scoped_ptr
<drive::ResourceEntry
> owner_resource_entry_
;
385 base::WeakPtrFactory
<SingleEntryPropertiesGetterForDrive
> weak_ptr_factory_
;
386 }; // class SingleEntryPropertiesGetterForDrive
388 class SingleEntryPropertiesGetterForFileSystemProvider
{
390 typedef base::Callback
<void(scoped_ptr
<EntryProperties
> properties
,
391 base::File::Error error
)> ResultCallback
;
393 // Creates an instance and starts the process.
394 static void Start(const storage::FileSystemURL file_system_url
,
395 const std::set
<EntryPropertyName
>& names
,
396 const ResultCallback
& callback
) {
397 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
399 SingleEntryPropertiesGetterForFileSystemProvider
* instance
=
400 new SingleEntryPropertiesGetterForFileSystemProvider(file_system_url
,
402 instance
->StartProcess();
404 // The instance will be destroyed by itself.
407 virtual ~SingleEntryPropertiesGetterForFileSystemProvider() {}
410 SingleEntryPropertiesGetterForFileSystemProvider(
411 const storage::FileSystemURL
& file_system_url
,
412 const std::set
<EntryPropertyName
>& names
,
413 const ResultCallback
& callback
)
414 : callback_(callback
),
415 file_system_url_(file_system_url
),
417 properties_(new EntryProperties
),
418 weak_ptr_factory_(this) {
419 DCHECK(!callback_
.is_null());
422 void StartProcess() {
423 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
425 FileSystemURLParser
parser(file_system_url_
);
426 if (!parser
.Parse()) {
427 CompleteGetEntryProperties(base::File::FILE_ERROR_NOT_FOUND
);
431 ProvidedFileSystemInterface::MetadataFieldMask field_mask
=
432 ProvidedFileSystemInterface::METADATA_FIELD_DEFAULT
;
433 // TODO(mtomasz): Add other fields. All of them should be requested on
434 // demand. crbug.com/413161.
436 api::file_manager_private::ENTRY_PROPERTY_NAME_THUMBNAILURL
) !=
438 field_mask
|= ProvidedFileSystemInterface::METADATA_FIELD_THUMBNAIL
;
440 parser
.file_system()->GetMetadata(
441 parser
.file_path(), field_mask
,
442 base::Bind(&SingleEntryPropertiesGetterForFileSystemProvider::
443 OnGetMetadataCompleted
,
444 weak_ptr_factory_
.GetWeakPtr()));
447 void OnGetMetadataCompleted(scoped_ptr
<EntryMetadata
> metadata
,
448 base::File::Error result
) {
449 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
451 if (result
!= base::File::FILE_OK
) {
452 CompleteGetEntryProperties(result
);
456 properties_
->size
.reset(new double(metadata
->size
));
457 properties_
->modification_time
.reset(
458 new double(metadata
->modification_time
.ToJsTime()));
460 if (!metadata
->thumbnail
.empty())
461 properties_
->thumbnail_url
.reset(new std::string(metadata
->thumbnail
));
462 if (!metadata
->mime_type
.empty()) {
463 properties_
->content_mime_type
.reset(
464 new std::string(metadata
->mime_type
));
467 CompleteGetEntryProperties(base::File::FILE_OK
);
470 void CompleteGetEntryProperties(base::File::Error result
) {
471 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
472 DCHECK(!callback_
.is_null());
474 callback_
.Run(properties_
.Pass(), result
);
475 BrowserThread::DeleteSoon(BrowserThread::UI
, FROM_HERE
, this);
479 const ResultCallback callback_
;
480 const storage::FileSystemURL file_system_url_
;
481 const std::set
<EntryPropertyName
> names_
;
483 // Values used in the process.
484 scoped_ptr
<EntryProperties
> properties_
;
486 base::WeakPtrFactory
<SingleEntryPropertiesGetterForFileSystemProvider
>
488 }; // class SingleEntryPropertiesGetterForDrive
492 FileManagerPrivateInternalGetEntryPropertiesFunction::
493 FileManagerPrivateInternalGetEntryPropertiesFunction()
494 : processed_count_(0) {
497 FileManagerPrivateInternalGetEntryPropertiesFunction::
498 ~FileManagerPrivateInternalGetEntryPropertiesFunction() {
501 bool FileManagerPrivateInternalGetEntryPropertiesFunction::RunAsync() {
502 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
504 using api::file_manager_private_internal::GetEntryProperties::Params
;
505 const scoped_ptr
<Params
> params(Params::Create(*args_
));
506 EXTENSION_FUNCTION_VALIDATE(params
);
508 scoped_refptr
<storage::FileSystemContext
> file_system_context
=
509 file_manager::util::GetFileSystemContextForRenderFrameHost(
510 GetProfile(), render_frame_host());
512 properties_list_
.resize(params
->urls
.size());
513 const std::set
<EntryPropertyName
> names_as_set(params
->names
.begin(),
514 params
->names
.end());
515 for (size_t i
= 0; i
< params
->urls
.size(); i
++) {
516 const GURL url
= GURL(params
->urls
[i
]);
517 const storage::FileSystemURL file_system_url
=
518 file_system_context
->CrackURL(url
);
519 switch (file_system_url
.type()) {
520 case storage::kFileSystemTypeDrive
:
521 SingleEntryPropertiesGetterForDrive::Start(
522 file_system_url
.path(), names_as_set
, GetProfile(),
523 base::Bind(&FileManagerPrivateInternalGetEntryPropertiesFunction::
524 CompleteGetEntryProperties
,
525 this, i
, file_system_url
));
527 case storage::kFileSystemTypeProvided
:
528 SingleEntryPropertiesGetterForFileSystemProvider::Start(
529 file_system_url
, names_as_set
,
530 base::Bind(&FileManagerPrivateInternalGetEntryPropertiesFunction::
531 CompleteGetEntryProperties
,
532 this, i
, file_system_url
));
535 // TODO(yawano) Change this to support other voluems (e.g. local) ,and
536 // integrate fileManagerPrivate.getMimeType to this method.
537 LOG(ERROR
) << "Not supported file system type.";
538 CompleteGetEntryProperties(i
, file_system_url
,
539 make_scoped_ptr(new EntryProperties
),
540 base::File::FILE_ERROR_INVALID_OPERATION
);
547 void FileManagerPrivateInternalGetEntryPropertiesFunction::
548 CompleteGetEntryProperties(size_t index
,
549 const storage::FileSystemURL
& url
,
550 scoped_ptr
<EntryProperties
> properties
,
551 base::File::Error error
) {
552 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
553 DCHECK(0 <= processed_count_
&& processed_count_
< properties_list_
.size());
555 properties_list_
[index
] = make_linked_ptr(properties
.release());
556 if (error
== base::File::FILE_OK
) {
557 properties_list_
[index
]->external_file_url
.reset(
558 new std::string(chromeos::FileSystemURLToExternalFileURL(url
).spec()));
562 if (processed_count_
< properties_list_
.size())
565 results_
= extensions::api::file_manager_private_internal::
566 GetEntryProperties::Results::Create(properties_list_
);
570 bool FileManagerPrivateInternalPinDriveFileFunction::RunAsync() {
571 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
573 using extensions::api::file_manager_private_internal::PinDriveFile::Params
;
574 const scoped_ptr
<Params
> params(Params::Create(*args_
));
575 EXTENSION_FUNCTION_VALIDATE(params
);
577 drive::FileSystemInterface
* const file_system
=
578 drive::util::GetFileSystemByProfile(GetProfile());
579 if (!file_system
) // |file_system| is NULL if Drive is disabled.
582 const base::FilePath drive_path
=
583 drive::util::ExtractDrivePath(file_manager::util::GetLocalPathFromURL(
584 render_frame_host(), GetProfile(), GURL(params
->url
)));
589 &FileManagerPrivateInternalPinDriveFileFunction::OnPinStateSet
,
595 &FileManagerPrivateInternalPinDriveFileFunction::OnPinStateSet
,
601 void FileManagerPrivateInternalPinDriveFileFunction::OnPinStateSet(
602 drive::FileError error
) {
603 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
605 if (error
== drive::FILE_ERROR_OK
) {
608 SetError(drive::FileErrorToString(error
));
613 bool FileManagerPrivateInternalCancelFileTransfersFunction::RunAsync() {
614 using extensions::api::file_manager_private_internal::CancelFileTransfers::
616 const scoped_ptr
<Params
> params(Params::Create(*args_
));
617 EXTENSION_FUNCTION_VALIDATE(params
);
619 drive::DriveIntegrationService
* integration_service
=
620 drive::DriveIntegrationServiceFactory::FindForProfile(GetProfile());
621 if (!integration_service
|| !integration_service
->IsMounted())
624 drive::JobListInterface
* const job_list
= integration_service
->job_list();
626 const std::vector
<drive::JobInfo
> jobs
= job_list
->GetJobInfoList();
628 // Create the mapping from file path to job ID.
629 typedef std::map
<base::FilePath
, std::vector
<drive::JobID
>> PathToIdMap
;
630 PathToIdMap path_to_id_map
;
631 for (size_t i
= 0; i
< jobs
.size(); ++i
) {
632 if (drive::IsActiveFileTransferJobInfo(jobs
[i
]))
633 path_to_id_map
[jobs
[i
].file_path
].push_back(jobs
[i
].job_id
);
636 for (size_t i
= 0; i
< params
->urls
.size(); ++i
) {
637 base::FilePath file_path
= file_manager::util::GetLocalPathFromURL(
638 render_frame_host(), GetProfile(), GURL(params
->urls
[i
]));
639 if (file_path
.empty())
642 file_path
= drive::util::ExtractDrivePath(file_path
);
643 DCHECK(file_path
.empty());
645 // Cancel all the jobs for the file.
646 PathToIdMap::iterator it
= path_to_id_map
.find(file_path
);
647 if (it
!= path_to_id_map
.end()) {
648 for (size_t i
= 0; i
< it
->second
.size(); ++i
)
649 job_list
->CancelJob(it
->second
[i
]);
657 bool FileManagerPrivateCancelAllFileTransfersFunction::RunAsync() {
658 drive::DriveIntegrationService
* const integration_service
=
659 drive::DriveIntegrationServiceFactory::FindForProfile(GetProfile());
660 if (!integration_service
|| !integration_service
->IsMounted())
663 drive::JobListInterface
* const job_list
= integration_service
->job_list();
665 const std::vector
<drive::JobInfo
> jobs
= job_list
->GetJobInfoList();
667 for (size_t i
= 0; i
< jobs
.size(); ++i
) {
668 if (drive::IsActiveFileTransferJobInfo(jobs
[i
]))
669 job_list
->CancelJob(jobs
[i
].job_id
);
676 bool FileManagerPrivateSearchDriveFunction::RunAsync() {
677 using extensions::api::file_manager_private::SearchDrive::Params
;
678 const scoped_ptr
<Params
> params(Params::Create(*args_
));
679 EXTENSION_FUNCTION_VALIDATE(params
);
681 drive::FileSystemInterface
* const file_system
=
682 drive::util::GetFileSystemByProfile(GetProfile());
684 // |file_system| is NULL if Drive is disabled.
689 params
->search_params
.query
, GURL(params
->search_params
.next_feed
),
690 base::Bind(&FileManagerPrivateSearchDriveFunction::OnSearch
, this));
694 void FileManagerPrivateSearchDriveFunction::OnSearch(
695 drive::FileError error
,
696 const GURL
& next_link
,
697 scoped_ptr
<SearchResultInfoList
> results
) {
698 if (error
!= drive::FILE_ERROR_OK
) {
703 // Outlives the following conversion, since the pointer is bound to the
705 DCHECK(results
.get());
706 const SearchResultInfoList
& results_ref
= *results
.get();
708 ConvertSearchResultInfoListToEntryDefinitionList(
712 base::Bind(&FileManagerPrivateSearchDriveFunction::OnEntryDefinitionList
,
715 base::Passed(&results
)));
718 void FileManagerPrivateSearchDriveFunction::OnEntryDefinitionList(
719 const GURL
& next_link
,
720 scoped_ptr
<SearchResultInfoList
> search_result_info_list
,
721 scoped_ptr
<EntryDefinitionList
> entry_definition_list
) {
722 DCHECK_EQ(search_result_info_list
->size(), entry_definition_list
->size());
723 base::ListValue
* entries
= new base::ListValue();
725 // Convert Drive files to something File API stack can understand.
726 for (EntryDefinitionList::const_iterator it
= entry_definition_list
->begin();
727 it
!= entry_definition_list
->end();
729 base::DictionaryValue
* entry
= new base::DictionaryValue();
730 entry
->SetString("fileSystemName", it
->file_system_name
);
731 entry
->SetString("fileSystemRoot", it
->file_system_root_url
);
732 entry
->SetString("fileFullPath", "/" + it
->full_path
.AsUTF8Unsafe());
733 entry
->SetBoolean("fileIsDirectory", it
->is_directory
);
734 entries
->Append(entry
);
737 base::DictionaryValue
* result
= new base::DictionaryValue();
738 result
->Set("entries", entries
);
739 result
->SetString("nextFeed", next_link
.spec());
745 bool FileManagerPrivateSearchDriveMetadataFunction::RunAsync() {
746 using api::file_manager_private::SearchDriveMetadata::Params
;
747 const scoped_ptr
<Params
> params(Params::Create(*args_
));
748 EXTENSION_FUNCTION_VALIDATE(params
);
750 drive::EventLogger
* logger
= file_manager::util::GetLogger(GetProfile());
752 logger
->Log(logging::LOG_INFO
,
753 "%s[%d] called. (types: '%s', maxResults: '%d')", name(),
754 request_id(), api::file_manager_private::ToString(
755 params
->search_params
.types
).c_str(),
756 params
->search_params
.max_results
);
758 set_log_on_completion(true);
760 drive::FileSystemInterface
* const file_system
=
761 drive::util::GetFileSystemByProfile(GetProfile());
763 // |file_system| is NULL if Drive is disabled.
768 switch (params
->search_params
.types
) {
769 case api::file_manager_private::SEARCH_TYPE_EXCLUDE_DIRECTORIES
:
770 options
= drive::SEARCH_METADATA_EXCLUDE_DIRECTORIES
;
772 case api::file_manager_private::SEARCH_TYPE_SHARED_WITH_ME
:
773 options
= drive::SEARCH_METADATA_SHARED_WITH_ME
;
775 case api::file_manager_private::SEARCH_TYPE_OFFLINE
:
776 options
= drive::SEARCH_METADATA_OFFLINE
;
778 case api::file_manager_private::SEARCH_TYPE_ALL
:
779 options
= drive::SEARCH_METADATA_ALL
;
781 case api::file_manager_private::SEARCH_TYPE_NONE
:
784 DCHECK_NE(options
, -1);
786 file_system
->SearchMetadata(
787 params
->search_params
.query
,
789 params
->search_params
.max_results
,
790 base::Bind(&FileManagerPrivateSearchDriveMetadataFunction::
791 OnSearchMetadata
, this));
795 void FileManagerPrivateSearchDriveMetadataFunction::OnSearchMetadata(
796 drive::FileError error
,
797 scoped_ptr
<drive::MetadataSearchResultVector
> results
) {
798 if (error
!= drive::FILE_ERROR_OK
) {
803 // Outlives the following conversion, since the pointer is bound to the
805 DCHECK(results
.get());
806 const drive::MetadataSearchResultVector
& results_ref
= *results
.get();
808 ConvertSearchResultInfoListToEntryDefinitionList(
813 &FileManagerPrivateSearchDriveMetadataFunction::OnEntryDefinitionList
,
815 base::Passed(&results
)));
818 void FileManagerPrivateSearchDriveMetadataFunction::OnEntryDefinitionList(
819 scoped_ptr
<drive::MetadataSearchResultVector
> search_result_info_list
,
820 scoped_ptr
<EntryDefinitionList
> entry_definition_list
) {
821 DCHECK_EQ(search_result_info_list
->size(), entry_definition_list
->size());
822 base::ListValue
* results_list
= new base::ListValue();
824 // Convert Drive files to something File API stack can understand. See
825 // file_browser_handler_custom_bindings.cc and
826 // file_manager_private_custom_bindings.js for how this is magically
827 // converted to a FileEntry.
828 for (size_t i
= 0; i
< entry_definition_list
->size(); ++i
) {
829 base::DictionaryValue
* result_dict
= new base::DictionaryValue();
832 base::DictionaryValue
* entry
= new base::DictionaryValue();
834 "fileSystemName", entry_definition_list
->at(i
).file_system_name
);
836 "fileSystemRoot", entry_definition_list
->at(i
).file_system_root_url
);
839 "/" + entry_definition_list
->at(i
).full_path
.AsUTF8Unsafe());
840 entry
->SetBoolean("fileIsDirectory",
841 entry_definition_list
->at(i
).is_directory
);
843 result_dict
->Set("entry", entry
);
844 result_dict
->SetString(
845 "highlightedBaseName",
846 search_result_info_list
->at(i
).highlighted_base_name
);
847 results_list
->Append(result_dict
);
850 SetResult(results_list
);
854 bool FileManagerPrivateGetDriveConnectionStateFunction::RunSync() {
855 api::file_manager_private::DriveConnectionState result
;
857 switch (drive::util::GetDriveConnectionStatus(GetProfile())) {
858 case drive::util::DRIVE_DISCONNECTED_NOSERVICE
:
859 result
.type
= kDriveConnectionTypeOffline
;
860 result
.reason
.reset(new std::string(kDriveConnectionReasonNoService
));
862 case drive::util::DRIVE_DISCONNECTED_NONETWORK
:
863 result
.type
= kDriveConnectionTypeOffline
;
864 result
.reason
.reset(new std::string(kDriveConnectionReasonNoNetwork
));
866 case drive::util::DRIVE_DISCONNECTED_NOTREADY
:
867 result
.type
= kDriveConnectionTypeOffline
;
868 result
.reason
.reset(new std::string(kDriveConnectionReasonNotReady
));
870 case drive::util::DRIVE_CONNECTED_METERED
:
871 result
.type
= kDriveConnectionTypeMetered
;
873 case drive::util::DRIVE_CONNECTED
:
874 result
.type
= kDriveConnectionTypeOnline
;
878 result
.has_cellular_network_access
=
879 chromeos::NetworkHandler::Get()
880 ->network_state_handler()
881 ->FirstNetworkByType(chromeos::NetworkTypePattern::Mobile());
882 results_
= api::file_manager_private::GetDriveConnectionState::Results::
885 drive::EventLogger
* logger
= file_manager::util::GetLogger(GetProfile());
887 logger
->Log(logging::LOG_INFO
, "%s succeeded.", name());
891 bool FileManagerPrivateRequestAccessTokenFunction::RunAsync() {
892 using extensions::api::file_manager_private::RequestAccessToken::Params
;
893 const scoped_ptr
<Params
> params(Params::Create(*args_
));
894 EXTENSION_FUNCTION_VALIDATE(params
);
896 drive::DriveServiceInterface
* const drive_service
=
897 drive::util::GetDriveServiceByProfile(GetProfile());
899 if (!drive_service
) {
900 // DriveService is not available.
901 SetResult(new base::StringValue(""));
906 // If refreshing is requested, then clear the token to refetch it.
908 drive_service
->ClearAccessToken();
910 // Retrieve the cached auth token (if available), otherwise the AuthService
911 // instance will try to refetch it.
912 drive_service
->RequestAccessToken(
913 base::Bind(&FileManagerPrivateRequestAccessTokenFunction::
914 OnAccessTokenFetched
, this));
918 void FileManagerPrivateRequestAccessTokenFunction::OnAccessTokenFetched(
919 google_apis::DriveApiErrorCode code
,
920 const std::string
& access_token
) {
921 SetResult(new base::StringValue(access_token
));
925 bool FileManagerPrivateInternalGetShareUrlFunction::RunAsync() {
926 using extensions::api::file_manager_private_internal::GetShareUrl::Params
;
927 const scoped_ptr
<Params
> params(Params::Create(*args_
));
928 EXTENSION_FUNCTION_VALIDATE(params
);
930 const base::FilePath path
= file_manager::util::GetLocalPathFromURL(
931 render_frame_host(), GetProfile(), GURL(params
->url
));
932 DCHECK(drive::util::IsUnderDriveMountPoint(path
));
934 const base::FilePath drive_path
= drive::util::ExtractDrivePath(path
);
936 drive::FileSystemInterface
* const file_system
=
937 drive::util::GetFileSystemByProfile(GetProfile());
939 // |file_system| is NULL if Drive is disabled.
943 file_system
->GetShareUrl(
945 GURL("chrome-extension://" + extension_id()), // embed origin
946 base::Bind(&FileManagerPrivateInternalGetShareUrlFunction::OnGetShareUrl
,
951 void FileManagerPrivateInternalGetShareUrlFunction::OnGetShareUrl(
952 drive::FileError error
,
953 const GURL
& share_url
) {
954 if (error
!= drive::FILE_ERROR_OK
) {
955 SetError("Share Url for this item is not available.");
960 SetResult(new base::StringValue(share_url
.spec()));
964 bool FileManagerPrivateInternalRequestDriveShareFunction::RunAsync() {
965 using extensions::api::file_manager_private_internal::RequestDriveShare::
967 const scoped_ptr
<Params
> params(Params::Create(*args_
));
968 EXTENSION_FUNCTION_VALIDATE(params
);
970 const base::FilePath path
= file_manager::util::GetLocalPathFromURL(
971 render_frame_host(), GetProfile(), GURL(params
->url
));
972 const base::FilePath drive_path
= drive::util::ExtractDrivePath(path
);
973 Profile
* const owner_profile
= drive::util::ExtractProfileFromPath(path
);
978 drive::FileSystemInterface
* const owner_file_system
=
979 drive::util::GetFileSystemByProfile(owner_profile
);
980 if (!owner_file_system
)
983 const user_manager::User
* const user
=
984 chromeos::ProfileHelper::Get()->GetUserByProfile(GetProfile());
985 if (!user
|| !user
->is_logged_in())
988 google_apis::drive::PermissionRole role
=
989 google_apis::drive::PERMISSION_ROLE_READER
;
990 switch (params
->share_type
) {
991 case api::file_manager_private::DRIVE_SHARE_TYPE_NONE
:
994 case api::file_manager_private::DRIVE_SHARE_TYPE_CAN_EDIT
:
995 role
= google_apis::drive::PERMISSION_ROLE_WRITER
;
997 case api::file_manager_private::DRIVE_SHARE_TYPE_CAN_COMMENT
:
998 role
= google_apis::drive::PERMISSION_ROLE_COMMENTER
;
1000 case api::file_manager_private::DRIVE_SHARE_TYPE_CAN_VIEW
:
1001 role
= google_apis::drive::PERMISSION_ROLE_READER
;
1005 // Share |drive_path| in |owner_file_system| to |user->email()|.
1006 owner_file_system
->AddPermission(
1007 drive_path
, user
->email(), role
,
1009 &FileManagerPrivateInternalRequestDriveShareFunction::OnAddPermission
,
1014 void FileManagerPrivateInternalRequestDriveShareFunction::OnAddPermission(
1015 drive::FileError error
) {
1016 SendResponse(error
== drive::FILE_ERROR_OK
);
1019 FileManagerPrivateInternalGetDownloadUrlFunction::
1020 FileManagerPrivateInternalGetDownloadUrlFunction() {}
1022 FileManagerPrivateInternalGetDownloadUrlFunction::
1023 ~FileManagerPrivateInternalGetDownloadUrlFunction() {}
1025 bool FileManagerPrivateInternalGetDownloadUrlFunction::RunAsync() {
1026 using extensions::api::file_manager_private_internal::GetShareUrl::Params
;
1027 const scoped_ptr
<Params
> params(Params::Create(*args_
));
1028 EXTENSION_FUNCTION_VALIDATE(params
);
1030 // Start getting the file info.
1031 drive::FileSystemInterface
* const file_system
=
1032 drive::util::GetFileSystemByProfile(GetProfile());
1034 // |file_system| is NULL if Drive is disabled or not mounted.
1035 SetError("Drive is disabled or not mounted.");
1036 SetResult(new base::StringValue("")); // Intentionally returns a blank.
1040 const base::FilePath path
= file_manager::util::GetLocalPathFromURL(
1041 render_frame_host(), GetProfile(), GURL(params
->url
));
1042 if (!drive::util::IsUnderDriveMountPoint(path
)) {
1043 SetError("The given file is not in Drive.");
1044 SetResult(new base::StringValue("")); // Intentionally returns a blank.
1047 base::FilePath file_path
= drive::util::ExtractDrivePath(path
);
1049 file_system
->GetResourceEntry(
1052 &FileManagerPrivateInternalGetDownloadUrlFunction::OnGetResourceEntry
,
1057 void FileManagerPrivateInternalGetDownloadUrlFunction::OnGetResourceEntry(
1058 drive::FileError error
,
1059 scoped_ptr
<drive::ResourceEntry
> entry
) {
1060 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
1062 if (error
!= drive::FILE_ERROR_OK
) {
1063 SetError("Download Url for this item is not available.");
1064 SetResult(new base::StringValue("")); // Intentionally returns a blank.
1065 SendResponse(false);
1069 DriveApiUrlGenerator
url_generator(
1070 (GURL(google_apis::DriveApiUrlGenerator::kBaseUrlForProduction
)),
1071 (GURL(google_apis::DriveApiUrlGenerator::kBaseDownloadUrlForProduction
)));
1072 download_url_
= url_generator
.GenerateDownloadFileUrl(entry
->resource_id());
1074 ProfileOAuth2TokenService
* oauth2_token_service
=
1075 ProfileOAuth2TokenServiceFactory::GetForProfile(GetProfile());
1076 SigninManagerBase
* signin_manager
=
1077 SigninManagerFactory::GetForProfile(GetProfile());
1078 const std::string
& account_id
= signin_manager
->GetAuthenticatedAccountId();
1079 std::vector
<std::string
> scopes
;
1080 scopes
.push_back("https://www.googleapis.com/auth/drive.readonly");
1082 auth_service_
.reset(
1083 new google_apis::AuthService(oauth2_token_service
,
1085 GetProfile()->GetRequestContext(),
1087 auth_service_
->StartAuthentication(base::Bind(
1088 &FileManagerPrivateInternalGetDownloadUrlFunction::OnTokenFetched
, this));
1091 void FileManagerPrivateInternalGetDownloadUrlFunction::OnTokenFetched(
1092 google_apis::DriveApiErrorCode code
,
1093 const std::string
& access_token
) {
1094 if (code
!= google_apis::HTTP_SUCCESS
) {
1095 SetError("Not able to fetch the token.");
1096 SetResult(new base::StringValue("")); // Intentionally returns a blank.
1097 SendResponse(false);
1101 const std::string url
=
1102 download_url_
.Resolve("?access_token=" + access_token
).spec();
1103 SetResult(new base::StringValue(url
));
1108 } // namespace extensions