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/extensions/file_manager/private_api_util.h"
14 #include "chrome/browser/chromeos/file_manager/file_tasks.h"
15 #include "chrome/browser/chromeos/file_manager/fileapi_util.h"
16 #include "chrome/browser/chromeos/file_manager/url_util.h"
17 #include "chrome/browser/chromeos/file_system_provider/mount_path_util.h"
18 #include "chrome/browser/chromeos/file_system_provider/provided_file_system_interface.h"
19 #include "chrome/browser/chromeos/fileapi/external_file_url_util.h"
20 #include "chrome/browser/chromeos/fileapi/file_system_backend.h"
21 #include "chrome/browser/chromeos/profiles/profile_helper.h"
22 #include "chrome/browser/drive/drive_app_registry.h"
23 #include "chrome/browser/drive/event_logger.h"
24 #include "chrome/browser/profiles/profile.h"
25 #include "chrome/browser/profiles/profile_manager.h"
26 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
27 #include "chrome/browser/signin/signin_manager_factory.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/signin/core/browser/profile_oauth2_token_service.h"
32 #include "components/signin/core/browser/signin_manager.h"
33 #include "content/public/browser/browser_thread.h"
34 #include "google_apis/drive/auth_service.h"
35 #include "google_apis/drive/drive_api_url_generator.h"
36 #include "storage/common/fileapi/file_system_info.h"
37 #include "storage/common/fileapi/file_system_util.h"
40 using content::BrowserThread
;
42 using chromeos::file_system_provider::EntryMetadata
;
43 using chromeos::file_system_provider::ProvidedFileSystemInterface
;
44 using chromeos::file_system_provider::util::FileSystemURLParser
;
45 using extensions::api::file_manager_private::EntryProperties
;
46 using extensions::api::file_manager_private::EntryPropertyName
;
47 using file_manager::util::EntryDefinition
;
48 using file_manager::util::EntryDefinitionCallback
;
49 using file_manager::util::EntryDefinitionList
;
50 using file_manager::util::EntryDefinitionListCallback
;
51 using file_manager::util::FileDefinition
;
52 using file_manager::util::FileDefinitionList
;
53 using google_apis::DriveApiUrlGenerator
;
55 namespace extensions
{
58 // List of connection types of drive.
59 // Keep this in sync with the DriveConnectionType in common/js/util.js.
60 const char kDriveConnectionTypeOffline
[] = "offline";
61 const char kDriveConnectionTypeMetered
[] = "metered";
62 const char kDriveConnectionTypeOnline
[] = "online";
64 // List of reasons of kDriveConnectionType*.
65 // Keep this in sync with the DriveConnectionReason in common/js/util.js.
66 const char kDriveConnectionReasonNotReady
[] = "not_ready";
67 const char kDriveConnectionReasonNoNetwork
[] = "no_network";
68 const char kDriveConnectionReasonNoService
[] = "no_service";
70 // Copies properties from |entry_proto| to |properties|. |shared_with_me| is
71 // given from the running profile.
72 void FillEntryPropertiesValueForDrive(const drive::ResourceEntry
& entry_proto
,
74 EntryProperties
* properties
) {
75 properties
->shared_with_me
.reset(new bool(shared_with_me
));
76 properties
->shared
.reset(new bool(entry_proto
.shared()));
78 const drive::PlatformFileInfoProto
& file_info
= entry_proto
.file_info();
79 properties
->size
.reset(new double(file_info
.size()));
80 properties
->modification_time
.reset(new double(
81 base::Time::FromInternalValue(file_info
.last_modified()).ToJsTime()));
83 if (!entry_proto
.has_file_specific_info())
86 const drive::FileSpecificInfo
& file_specific_info
=
87 entry_proto
.file_specific_info();
89 if (!entry_proto
.resource_id().empty()) {
90 DriveApiUrlGenerator
url_generator(
91 (GURL(google_apis::DriveApiUrlGenerator::kBaseUrlForProduction
)),
93 google_apis::DriveApiUrlGenerator::kBaseDownloadUrlForProduction
)));
94 properties
->thumbnail_url
.reset(new std::string(
95 url_generator
.GetThumbnailUrl(entry_proto
.resource_id(),
97 500 /* height */).spec()));
99 if (file_specific_info
.has_image_width()) {
100 properties
->image_width
.reset(
101 new int(file_specific_info
.image_width()));
103 if (file_specific_info
.has_image_height()) {
104 properties
->image_height
.reset(
105 new int(file_specific_info
.image_height()));
107 if (file_specific_info
.has_image_rotation()) {
108 properties
->image_rotation
.reset(
109 new int(file_specific_info
.image_rotation()));
111 properties
->hosted
.reset(new bool(file_specific_info
.is_hosted_document()));
112 properties
->content_mime_type
.reset(
113 new std::string(file_specific_info
.content_mime_type()));
114 properties
->pinned
.reset(
115 new bool(file_specific_info
.cache_state().is_pinned()));
116 properties
->dirty
.reset(
117 new bool(file_specific_info
.cache_state().is_dirty()));
118 properties
->present
.reset(
119 new bool(file_specific_info
.cache_state().is_present()));
121 if (file_specific_info
.cache_state().is_present()) {
122 properties
->available_offline
.reset(new bool(true));
123 } else if (file_specific_info
.is_hosted_document() &&
124 file_specific_info
.has_document_extension()) {
125 const std::string file_extension
= file_specific_info
.document_extension();
126 // What's available offline? See the 'Web' column at:
127 // http://support.google.com/drive/answer/1628467
128 properties
->available_offline
.reset(
129 new bool(file_extension
== ".gdoc" || file_extension
== ".gdraw" ||
130 file_extension
== ".gsheet" || file_extension
== ".gslides"));
132 properties
->available_offline
.reset(new bool(false));
135 properties
->available_when_metered
.reset(
136 new bool(file_specific_info
.cache_state().is_present() ||
137 file_specific_info
.is_hosted_document()));
140 // Creates entry definition list for (metadata) search result info list.
142 void ConvertSearchResultInfoListToEntryDefinitionList(
144 const std::string
& extension_id
,
145 const std::vector
<T
>& search_result_info_list
,
146 const EntryDefinitionListCallback
& callback
) {
147 FileDefinitionList file_definition_list
;
149 for (size_t i
= 0; i
< search_result_info_list
.size(); ++i
) {
150 FileDefinition file_definition
;
151 file_definition
.virtual_path
=
152 file_manager::util::ConvertDrivePathToRelativeFileSystemPath(
153 profile
, extension_id
, search_result_info_list
.at(i
).path
);
154 file_definition
.is_directory
= search_result_info_list
.at(i
).is_directory
;
155 file_definition_list
.push_back(file_definition
);
158 file_manager::util::ConvertFileDefinitionListToEntryDefinitionList(
161 file_definition_list
, // Safe, since copied internally.
165 class SingleEntryPropertiesGetterForDrive
{
167 typedef base::Callback
<void(scoped_ptr
<EntryProperties
> properties
,
168 base::File::Error error
)> ResultCallback
;
170 // Creates an instance and starts the process.
171 static void Start(const base::FilePath local_path
,
172 const std::set
<EntryPropertyName
>& names
,
173 Profile
* const profile
,
174 const ResultCallback
& callback
) {
175 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
177 SingleEntryPropertiesGetterForDrive
* instance
=
178 new SingleEntryPropertiesGetterForDrive(local_path
, names
, profile
,
180 instance
->StartProcess();
182 // The instance will be destroyed by itself.
185 virtual ~SingleEntryPropertiesGetterForDrive() {}
188 SingleEntryPropertiesGetterForDrive(
189 const base::FilePath local_path
,
190 const std::set
<EntryPropertyName
>& /* names */,
191 Profile
* const profile
,
192 const ResultCallback
& callback
)
193 : callback_(callback
),
194 local_path_(local_path
),
195 running_profile_(profile
),
196 properties_(new EntryProperties
),
197 file_owner_profile_(NULL
),
198 weak_ptr_factory_(this) {
199 DCHECK(!callback_
.is_null());
203 void StartProcess() {
204 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
206 file_path_
= drive::util::ExtractDrivePath(local_path_
);
207 file_owner_profile_
= drive::util::ExtractProfileFromPath(local_path_
);
209 if (!file_owner_profile_
||
210 !g_browser_process
->profile_manager()->IsValidProfile(
211 file_owner_profile_
)) {
212 CompleteGetEntryProperties(drive::FILE_ERROR_FAILED
);
216 // Start getting the file info.
217 drive::FileSystemInterface
* const file_system
=
218 drive::util::GetFileSystemByProfile(file_owner_profile_
);
220 // |file_system| is NULL if Drive is disabled or not mounted.
221 CompleteGetEntryProperties(drive::FILE_ERROR_FAILED
);
225 file_system
->GetResourceEntry(
227 base::Bind(&SingleEntryPropertiesGetterForDrive::OnGetFileInfo
,
228 weak_ptr_factory_
.GetWeakPtr()));
231 void OnGetFileInfo(drive::FileError error
,
232 scoped_ptr
<drive::ResourceEntry
> entry
) {
233 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
235 if (error
!= drive::FILE_ERROR_OK
) {
236 CompleteGetEntryProperties(error
);
241 owner_resource_entry_
.swap(entry
);
243 if (running_profile_
->IsSameProfile(file_owner_profile_
)) {
244 StartParseFileInfo(owner_resource_entry_
->shared_with_me());
248 // If the running profile does not own the file, obtain the shared_with_me
249 // flag from the running profile's value.
250 drive::FileSystemInterface
* const file_system
=
251 drive::util::GetFileSystemByProfile(running_profile_
);
253 CompleteGetEntryProperties(drive::FILE_ERROR_FAILED
);
256 file_system
->GetPathFromResourceId(
257 owner_resource_entry_
->resource_id(),
258 base::Bind(&SingleEntryPropertiesGetterForDrive::OnGetRunningPath
,
259 weak_ptr_factory_
.GetWeakPtr()));
262 void OnGetRunningPath(drive::FileError error
,
263 const base::FilePath
& file_path
) {
264 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
266 if (error
!= drive::FILE_ERROR_OK
) {
267 // The running profile does not know the file.
268 StartParseFileInfo(false);
272 drive::FileSystemInterface
* const file_system
=
273 drive::util::GetFileSystemByProfile(running_profile_
);
275 // The drive is disable for the running profile.
276 StartParseFileInfo(false);
280 file_system
->GetResourceEntry(
282 base::Bind(&SingleEntryPropertiesGetterForDrive::OnGetShareInfo
,
283 weak_ptr_factory_
.GetWeakPtr()));
286 void OnGetShareInfo(drive::FileError error
,
287 scoped_ptr
<drive::ResourceEntry
> entry
) {
288 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
290 if (error
!= drive::FILE_ERROR_OK
) {
291 CompleteGetEntryProperties(error
);
296 StartParseFileInfo(entry
->shared_with_me());
299 void StartParseFileInfo(bool shared_with_me
) {
300 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
302 FillEntryPropertiesValueForDrive(
303 *owner_resource_entry_
, shared_with_me
, properties_
.get());
305 drive::FileSystemInterface
* const file_system
=
306 drive::util::GetFileSystemByProfile(file_owner_profile_
);
307 drive::DriveAppRegistry
* const app_registry
=
308 drive::util::GetDriveAppRegistryByProfile(file_owner_profile_
);
309 if (!file_system
|| !app_registry
) {
310 // |file_system| or |app_registry| is NULL if Drive is disabled.
311 CompleteGetEntryProperties(drive::FILE_ERROR_FAILED
);
315 // The properties meaningful for directories are already filled in
316 // FillEntryPropertiesValueForDrive().
317 if (!owner_resource_entry_
->has_file_specific_info()) {
318 CompleteGetEntryProperties(drive::FILE_ERROR_OK
);
322 const drive::FileSpecificInfo
& file_specific_info
=
323 owner_resource_entry_
->file_specific_info();
325 // Get drive WebApps that can accept this file. We just need to extract the
326 // doc icon for the drive app, which is set as default.
327 std::vector
<drive::DriveAppInfo
> drive_apps
;
328 app_registry
->GetAppsForFile(file_path_
.Extension(),
329 file_specific_info
.content_mime_type(),
331 if (!drive_apps
.empty()) {
332 std::string default_task_id
=
333 file_manager::file_tasks::GetDefaultTaskIdFromPrefs(
334 *file_owner_profile_
->GetPrefs(),
335 file_specific_info
.content_mime_type(),
336 file_path_
.Extension());
337 file_manager::file_tasks::TaskDescriptor default_task
;
338 file_manager::file_tasks::ParseTaskID(default_task_id
, &default_task
);
339 DCHECK(default_task_id
.empty() || !default_task
.app_id
.empty());
340 for (size_t i
= 0; i
< drive_apps
.size(); ++i
) {
341 const drive::DriveAppInfo
& app_info
= drive_apps
[i
];
342 if (default_task
.app_id
== app_info
.app_id
) {
343 // The drive app is set as default. Files.app should use the doc icon.
344 const GURL doc_icon
= drive::util::FindPreferredIcon(
345 app_info
.document_icons
, drive::util::kPreferredIconSize
);
346 properties_
->custom_icon_url
.reset(new std::string(doc_icon
.spec()));
351 CompleteGetEntryProperties(drive::FILE_ERROR_OK
);
354 void CompleteGetEntryProperties(drive::FileError error
) {
355 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
356 DCHECK(!callback_
.is_null());
358 callback_
.Run(properties_
.Pass(), drive::FileErrorToBaseFileError(error
));
359 BrowserThread::DeleteSoon(BrowserThread::UI
, FROM_HERE
, this);
363 const ResultCallback callback_
;
364 const base::FilePath local_path_
;
365 Profile
* const running_profile_
;
367 // Values used in the process.
368 scoped_ptr
<EntryProperties
> properties_
;
369 Profile
* file_owner_profile_
;
370 base::FilePath file_path_
;
371 scoped_ptr
<drive::ResourceEntry
> owner_resource_entry_
;
373 base::WeakPtrFactory
<SingleEntryPropertiesGetterForDrive
> weak_ptr_factory_
;
374 }; // class SingleEntryPropertiesGetterForDrive
376 class SingleEntryPropertiesGetterForFileSystemProvider
{
378 typedef base::Callback
<void(scoped_ptr
<EntryProperties
> properties
,
379 base::File::Error error
)> ResultCallback
;
381 // Creates an instance and starts the process.
382 static void Start(const storage::FileSystemURL file_system_url
,
383 const std::set
<EntryPropertyName
>& names
,
384 const ResultCallback
& callback
) {
385 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
387 SingleEntryPropertiesGetterForFileSystemProvider
* instance
=
388 new SingleEntryPropertiesGetterForFileSystemProvider(file_system_url
,
390 instance
->StartProcess();
392 // The instance will be destroyed by itself.
395 virtual ~SingleEntryPropertiesGetterForFileSystemProvider() {}
398 SingleEntryPropertiesGetterForFileSystemProvider(
399 const storage::FileSystemURL
& file_system_url
,
400 const std::set
<EntryPropertyName
>& names
,
401 const ResultCallback
& callback
)
402 : callback_(callback
),
403 file_system_url_(file_system_url
),
405 properties_(new EntryProperties
),
406 weak_ptr_factory_(this) {
407 DCHECK(!callback_
.is_null());
410 void StartProcess() {
411 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
413 FileSystemURLParser
parser(file_system_url_
);
414 if (!parser
.Parse()) {
415 CompleteGetEntryProperties(base::File::FILE_ERROR_NOT_FOUND
);
419 ProvidedFileSystemInterface::MetadataFieldMask field_mask
=
420 ProvidedFileSystemInterface::METADATA_FIELD_DEFAULT
;
421 // TODO(mtomasz): Add other fields. All of them should be requested on
422 // demand. crbug.com/413161.
424 api::file_manager_private::ENTRY_PROPERTY_NAME_THUMBNAILURL
) !=
426 field_mask
|= ProvidedFileSystemInterface::METADATA_FIELD_THUMBNAIL
;
428 parser
.file_system()->GetMetadata(
429 parser
.file_path(), field_mask
,
430 base::Bind(&SingleEntryPropertiesGetterForFileSystemProvider::
431 OnGetMetadataCompleted
,
432 weak_ptr_factory_
.GetWeakPtr()));
435 void OnGetMetadataCompleted(scoped_ptr
<EntryMetadata
> metadata
,
436 base::File::Error result
) {
437 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
439 if (result
!= base::File::FILE_OK
) {
440 CompleteGetEntryProperties(result
);
444 properties_
->size
.reset(new double(metadata
->size
));
445 properties_
->modification_time
.reset(
446 new double(metadata
->modification_time
.ToJsTime()));
448 if (!metadata
->thumbnail
.empty())
449 properties_
->thumbnail_url
.reset(new std::string(metadata
->thumbnail
));
451 CompleteGetEntryProperties(base::File::FILE_OK
);
454 void CompleteGetEntryProperties(base::File::Error result
) {
455 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
456 DCHECK(!callback_
.is_null());
458 callback_
.Run(properties_
.Pass(), result
);
459 BrowserThread::DeleteSoon(BrowserThread::UI
, FROM_HERE
, this);
463 const ResultCallback callback_
;
464 const storage::FileSystemURL file_system_url_
;
465 const std::set
<EntryPropertyName
> names_
;
467 // Values used in the process.
468 scoped_ptr
<EntryProperties
> properties_
;
470 base::WeakPtrFactory
<SingleEntryPropertiesGetterForFileSystemProvider
>
472 }; // class SingleEntryPropertiesGetterForDrive
476 FileManagerPrivateGetEntryPropertiesFunction::
477 FileManagerPrivateGetEntryPropertiesFunction()
478 : processed_count_(0) {
481 FileManagerPrivateGetEntryPropertiesFunction::
482 ~FileManagerPrivateGetEntryPropertiesFunction() {
485 bool FileManagerPrivateGetEntryPropertiesFunction::RunAsync() {
486 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
488 using api::file_manager_private::GetEntryProperties::Params
;
489 const scoped_ptr
<Params
> params(Params::Create(*args_
));
490 EXTENSION_FUNCTION_VALIDATE(params
);
492 scoped_refptr
<storage::FileSystemContext
> file_system_context
=
493 file_manager::util::GetFileSystemContextForRenderViewHost(
494 GetProfile(), render_view_host());
496 properties_list_
.resize(params
->file_urls
.size());
497 const std::set
<EntryPropertyName
> names_as_set(params
->names
.begin(),
498 params
->names
.end());
499 for (size_t i
= 0; i
< params
->file_urls
.size(); i
++) {
500 const GURL url
= GURL(params
->file_urls
[i
]);
501 const storage::FileSystemURL file_system_url
=
502 file_system_context
->CrackURL(url
);
503 switch (file_system_url
.type()) {
504 case storage::kFileSystemTypeDrive
:
505 SingleEntryPropertiesGetterForDrive::Start(
506 file_system_url
.path(), names_as_set
, GetProfile(),
507 base::Bind(&FileManagerPrivateGetEntryPropertiesFunction::
508 CompleteGetEntryProperties
,
509 this, i
, file_system_url
));
511 case storage::kFileSystemTypeProvided
:
512 SingleEntryPropertiesGetterForFileSystemProvider::Start(
513 file_system_url
, names_as_set
,
514 base::Bind(&FileManagerPrivateGetEntryPropertiesFunction::
515 CompleteGetEntryProperties
,
516 this, i
, file_system_url
));
519 // TODO(yawano) Change this to support other voluems (e.g. local) ,and
520 // integrate fileManagerPrivate.getMimeType to this method.
521 LOG(ERROR
) << "Not supported file system type.";
522 CompleteGetEntryProperties(i
, file_system_url
,
523 make_scoped_ptr(new EntryProperties
),
524 base::File::FILE_ERROR_INVALID_OPERATION
);
531 void FileManagerPrivateGetEntryPropertiesFunction::CompleteGetEntryProperties(
533 const storage::FileSystemURL
& url
,
534 scoped_ptr
<EntryProperties
> properties
,
535 base::File::Error error
) {
536 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
537 DCHECK(0 <= processed_count_
&& processed_count_
< properties_list_
.size());
539 properties_list_
[index
] = make_linked_ptr(properties
.release());
540 if (error
== base::File::FILE_OK
) {
541 properties_list_
[index
]->external_file_url
.reset(
542 new std::string(chromeos::FileSystemURLToExternalFileURL(url
).spec()));
546 if (processed_count_
< properties_list_
.size())
549 results_
= extensions::api::file_manager_private::GetEntryProperties::
550 Results::Create(properties_list_
);
554 bool FileManagerPrivatePinDriveFileFunction::RunAsync() {
555 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
557 using extensions::api::file_manager_private::PinDriveFile::Params
;
558 const scoped_ptr
<Params
> params(Params::Create(*args_
));
559 EXTENSION_FUNCTION_VALIDATE(params
);
561 drive::FileSystemInterface
* const file_system
=
562 drive::util::GetFileSystemByProfile(GetProfile());
563 if (!file_system
) // |file_system| is NULL if Drive is disabled.
566 const base::FilePath drive_path
=
567 drive::util::ExtractDrivePath(file_manager::util::GetLocalPathFromURL(
568 render_view_host(), GetProfile(), GURL(params
->file_url
)));
570 file_system
->Pin(drive_path
,
571 base::Bind(&FileManagerPrivatePinDriveFileFunction::
572 OnPinStateSet
, this));
574 file_system
->Unpin(drive_path
,
575 base::Bind(&FileManagerPrivatePinDriveFileFunction::
576 OnPinStateSet
, this));
581 void FileManagerPrivatePinDriveFileFunction::
582 OnPinStateSet(drive::FileError error
) {
583 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
585 if (error
== drive::FILE_ERROR_OK
) {
588 SetError(drive::FileErrorToString(error
));
593 bool FileManagerPrivateCancelFileTransfersFunction::RunAsync() {
594 using extensions::api::file_manager_private::CancelFileTransfers::Params
;
595 const scoped_ptr
<Params
> params(Params::Create(*args_
));
596 EXTENSION_FUNCTION_VALIDATE(params
);
598 drive::DriveIntegrationService
* integration_service
=
599 drive::DriveIntegrationServiceFactory::FindForProfile(GetProfile());
600 if (!integration_service
|| !integration_service
->IsMounted())
603 drive::JobListInterface
* job_list
= integration_service
->job_list();
605 std::vector
<drive::JobInfo
> jobs
= job_list
->GetJobInfoList();
607 // If file_urls are empty, cancel all jobs.
608 if (!params
->file_urls
.get()) {
609 for (size_t i
= 0; i
< jobs
.size(); ++i
) {
610 if (drive::IsActiveFileTransferJobInfo(jobs
[i
]))
611 job_list
->CancelJob(jobs
[i
].job_id
);
614 // Create the mapping from file path to job ID.
615 std::vector
<std::string
> file_urls(*params
->file_urls
.get());
616 typedef std::map
<base::FilePath
, std::vector
<drive::JobID
> > PathToIdMap
;
617 PathToIdMap path_to_id_map
;
618 for (size_t i
= 0; i
< jobs
.size(); ++i
) {
619 if (drive::IsActiveFileTransferJobInfo(jobs
[i
]))
620 path_to_id_map
[jobs
[i
].file_path
].push_back(jobs
[i
].job_id
);
623 for (size_t i
= 0; i
< file_urls
.size(); ++i
) {
624 base::FilePath file_path
= file_manager::util::GetLocalPathFromURL(
625 render_view_host(), GetProfile(), GURL(file_urls
[i
]));
626 if (file_path
.empty())
629 file_path
= drive::util::ExtractDrivePath(file_path
);
630 DCHECK(file_path
.empty());
632 // Cancel all the jobs for the file.
633 PathToIdMap::iterator it
= path_to_id_map
.find(file_path
);
634 if (it
!= path_to_id_map
.end()) {
635 for (size_t i
= 0; i
< it
->second
.size(); ++i
)
636 job_list
->CancelJob(it
->second
[i
]);
644 bool FileManagerPrivateSearchDriveFunction::RunAsync() {
645 using extensions::api::file_manager_private::SearchDrive::Params
;
646 const scoped_ptr
<Params
> params(Params::Create(*args_
));
647 EXTENSION_FUNCTION_VALIDATE(params
);
649 drive::FileSystemInterface
* const file_system
=
650 drive::util::GetFileSystemByProfile(GetProfile());
652 // |file_system| is NULL if Drive is disabled.
657 params
->search_params
.query
, GURL(params
->search_params
.next_feed
),
658 base::Bind(&FileManagerPrivateSearchDriveFunction::OnSearch
, this));
662 void FileManagerPrivateSearchDriveFunction::OnSearch(
663 drive::FileError error
,
664 const GURL
& next_link
,
665 scoped_ptr
<SearchResultInfoList
> results
) {
666 if (error
!= drive::FILE_ERROR_OK
) {
671 // Outlives the following conversion, since the pointer is bound to the
673 DCHECK(results
.get());
674 const SearchResultInfoList
& results_ref
= *results
.get();
676 ConvertSearchResultInfoListToEntryDefinitionList(
680 base::Bind(&FileManagerPrivateSearchDriveFunction::OnEntryDefinitionList
,
683 base::Passed(&results
)));
686 void FileManagerPrivateSearchDriveFunction::OnEntryDefinitionList(
687 const GURL
& next_link
,
688 scoped_ptr
<SearchResultInfoList
> search_result_info_list
,
689 scoped_ptr
<EntryDefinitionList
> entry_definition_list
) {
690 DCHECK_EQ(search_result_info_list
->size(), entry_definition_list
->size());
691 base::ListValue
* entries
= new base::ListValue();
693 // Convert Drive files to something File API stack can understand.
694 for (EntryDefinitionList::const_iterator it
= entry_definition_list
->begin();
695 it
!= entry_definition_list
->end();
697 base::DictionaryValue
* entry
= new base::DictionaryValue();
698 entry
->SetString("fileSystemName", it
->file_system_name
);
699 entry
->SetString("fileSystemRoot", it
->file_system_root_url
);
700 entry
->SetString("fileFullPath", "/" + it
->full_path
.AsUTF8Unsafe());
701 entry
->SetBoolean("fileIsDirectory", it
->is_directory
);
702 entries
->Append(entry
);
705 base::DictionaryValue
* result
= new base::DictionaryValue();
706 result
->Set("entries", entries
);
707 result
->SetString("nextFeed", next_link
.spec());
713 bool FileManagerPrivateSearchDriveMetadataFunction::RunAsync() {
714 using api::file_manager_private::SearchDriveMetadata::Params
;
715 const scoped_ptr
<Params
> params(Params::Create(*args_
));
716 EXTENSION_FUNCTION_VALIDATE(params
);
718 drive::EventLogger
* logger
= file_manager::util::GetLogger(GetProfile());
720 logger
->Log(logging::LOG_INFO
,
721 "%s[%d] called. (types: '%s', maxResults: '%d')", name(),
722 request_id(), api::file_manager_private::ToString(
723 params
->search_params
.types
).c_str(),
724 params
->search_params
.max_results
);
726 set_log_on_completion(true);
728 drive::FileSystemInterface
* const file_system
=
729 drive::util::GetFileSystemByProfile(GetProfile());
731 // |file_system| is NULL if Drive is disabled.
736 switch (params
->search_params
.types
) {
737 case api::file_manager_private::SEARCH_TYPE_EXCLUDE_DIRECTORIES
:
738 options
= drive::SEARCH_METADATA_EXCLUDE_DIRECTORIES
;
740 case api::file_manager_private::SEARCH_TYPE_SHARED_WITH_ME
:
741 options
= drive::SEARCH_METADATA_SHARED_WITH_ME
;
743 case api::file_manager_private::SEARCH_TYPE_OFFLINE
:
744 options
= drive::SEARCH_METADATA_OFFLINE
;
746 case api::file_manager_private::SEARCH_TYPE_ALL
:
747 options
= drive::SEARCH_METADATA_ALL
;
749 case api::file_manager_private::SEARCH_TYPE_NONE
:
752 DCHECK_NE(options
, -1);
754 file_system
->SearchMetadata(
755 params
->search_params
.query
,
757 params
->search_params
.max_results
,
758 base::Bind(&FileManagerPrivateSearchDriveMetadataFunction::
759 OnSearchMetadata
, this));
763 void FileManagerPrivateSearchDriveMetadataFunction::OnSearchMetadata(
764 drive::FileError error
,
765 scoped_ptr
<drive::MetadataSearchResultVector
> results
) {
766 if (error
!= drive::FILE_ERROR_OK
) {
771 // Outlives the following conversion, since the pointer is bound to the
773 DCHECK(results
.get());
774 const drive::MetadataSearchResultVector
& results_ref
= *results
.get();
776 ConvertSearchResultInfoListToEntryDefinitionList(
781 &FileManagerPrivateSearchDriveMetadataFunction::OnEntryDefinitionList
,
783 base::Passed(&results
)));
786 void FileManagerPrivateSearchDriveMetadataFunction::OnEntryDefinitionList(
787 scoped_ptr
<drive::MetadataSearchResultVector
> search_result_info_list
,
788 scoped_ptr
<EntryDefinitionList
> entry_definition_list
) {
789 DCHECK_EQ(search_result_info_list
->size(), entry_definition_list
->size());
790 base::ListValue
* results_list
= new base::ListValue();
792 // Convert Drive files to something File API stack can understand. See
793 // file_browser_handler_custom_bindings.cc and
794 // file_manager_private_custom_bindings.js for how this is magically
795 // converted to a FileEntry.
796 for (size_t i
= 0; i
< entry_definition_list
->size(); ++i
) {
797 base::DictionaryValue
* result_dict
= new base::DictionaryValue();
800 base::DictionaryValue
* entry
= new base::DictionaryValue();
802 "fileSystemName", entry_definition_list
->at(i
).file_system_name
);
804 "fileSystemRoot", entry_definition_list
->at(i
).file_system_root_url
);
807 "/" + entry_definition_list
->at(i
).full_path
.AsUTF8Unsafe());
808 entry
->SetBoolean("fileIsDirectory",
809 entry_definition_list
->at(i
).is_directory
);
811 result_dict
->Set("entry", entry
);
812 result_dict
->SetString(
813 "highlightedBaseName",
814 search_result_info_list
->at(i
).highlighted_base_name
);
815 results_list
->Append(result_dict
);
818 SetResult(results_list
);
822 bool FileManagerPrivateGetDriveConnectionStateFunction::RunSync() {
823 api::file_manager_private::DriveConnectionState result
;
825 switch (drive::util::GetDriveConnectionStatus(GetProfile())) {
826 case drive::util::DRIVE_DISCONNECTED_NOSERVICE
:
827 result
.type
= kDriveConnectionTypeOffline
;
828 result
.reason
.reset(new std::string(kDriveConnectionReasonNoService
));
830 case drive::util::DRIVE_DISCONNECTED_NONETWORK
:
831 result
.type
= kDriveConnectionTypeOffline
;
832 result
.reason
.reset(new std::string(kDriveConnectionReasonNoNetwork
));
834 case drive::util::DRIVE_DISCONNECTED_NOTREADY
:
835 result
.type
= kDriveConnectionTypeOffline
;
836 result
.reason
.reset(new std::string(kDriveConnectionReasonNotReady
));
838 case drive::util::DRIVE_CONNECTED_METERED
:
839 result
.type
= kDriveConnectionTypeMetered
;
841 case drive::util::DRIVE_CONNECTED
:
842 result
.type
= kDriveConnectionTypeOnline
;
846 result
.has_cellular_network_access
=
847 chromeos::NetworkHandler::Get()
848 ->network_state_handler()
849 ->FirstNetworkByType(chromeos::NetworkTypePattern::Mobile());
850 results_
= api::file_manager_private::GetDriveConnectionState::Results::
853 drive::EventLogger
* logger
= file_manager::util::GetLogger(GetProfile());
855 logger
->Log(logging::LOG_INFO
, "%s succeeded.", name());
859 bool FileManagerPrivateRequestAccessTokenFunction::RunAsync() {
860 using extensions::api::file_manager_private::RequestAccessToken::Params
;
861 const scoped_ptr
<Params
> params(Params::Create(*args_
));
862 EXTENSION_FUNCTION_VALIDATE(params
);
864 drive::DriveServiceInterface
* const drive_service
=
865 drive::util::GetDriveServiceByProfile(GetProfile());
867 if (!drive_service
) {
868 // DriveService is not available.
869 SetResult(new base::StringValue(""));
874 // If refreshing is requested, then clear the token to refetch it.
876 drive_service
->ClearAccessToken();
878 // Retrieve the cached auth token (if available), otherwise the AuthService
879 // instance will try to refetch it.
880 drive_service
->RequestAccessToken(
881 base::Bind(&FileManagerPrivateRequestAccessTokenFunction::
882 OnAccessTokenFetched
, this));
886 void FileManagerPrivateRequestAccessTokenFunction::OnAccessTokenFetched(
887 google_apis::DriveApiErrorCode code
,
888 const std::string
& access_token
) {
889 SetResult(new base::StringValue(access_token
));
893 bool FileManagerPrivateGetShareUrlFunction::RunAsync() {
894 using extensions::api::file_manager_private::GetShareUrl::Params
;
895 const scoped_ptr
<Params
> params(Params::Create(*args_
));
896 EXTENSION_FUNCTION_VALIDATE(params
);
898 const base::FilePath path
= file_manager::util::GetLocalPathFromURL(
899 render_view_host(), GetProfile(), GURL(params
->url
));
900 DCHECK(drive::util::IsUnderDriveMountPoint(path
));
902 const base::FilePath drive_path
= drive::util::ExtractDrivePath(path
);
904 drive::FileSystemInterface
* const file_system
=
905 drive::util::GetFileSystemByProfile(GetProfile());
907 // |file_system| is NULL if Drive is disabled.
911 file_system
->GetShareUrl(
913 GURL("chrome-extension://" + extension_id()), // embed origin
914 base::Bind(&FileManagerPrivateGetShareUrlFunction::OnGetShareUrl
, this));
918 void FileManagerPrivateGetShareUrlFunction::OnGetShareUrl(
919 drive::FileError error
,
920 const GURL
& share_url
) {
921 if (error
!= drive::FILE_ERROR_OK
) {
922 SetError("Share Url for this item is not available.");
927 SetResult(new base::StringValue(share_url
.spec()));
931 bool FileManagerPrivateRequestDriveShareFunction::RunAsync() {
932 using extensions::api::file_manager_private::RequestDriveShare::Params
;
933 const scoped_ptr
<Params
> params(Params::Create(*args_
));
934 EXTENSION_FUNCTION_VALIDATE(params
);
936 const base::FilePath path
= file_manager::util::GetLocalPathFromURL(
937 render_view_host(), GetProfile(), GURL(params
->url
));
938 const base::FilePath drive_path
= drive::util::ExtractDrivePath(path
);
939 Profile
* const owner_profile
= drive::util::ExtractProfileFromPath(path
);
944 drive::FileSystemInterface
* const owner_file_system
=
945 drive::util::GetFileSystemByProfile(owner_profile
);
946 if (!owner_file_system
)
949 const user_manager::User
* const user
=
950 chromeos::ProfileHelper::Get()->GetUserByProfile(GetProfile());
951 if (!user
|| !user
->is_logged_in())
954 google_apis::drive::PermissionRole role
=
955 google_apis::drive::PERMISSION_ROLE_READER
;
956 switch (params
->share_type
) {
957 case api::file_manager_private::DRIVE_SHARE_TYPE_NONE
:
960 case api::file_manager_private::DRIVE_SHARE_TYPE_CAN_EDIT
:
961 role
= google_apis::drive::PERMISSION_ROLE_WRITER
;
963 case api::file_manager_private::DRIVE_SHARE_TYPE_CAN_COMMENT
:
964 role
= google_apis::drive::PERMISSION_ROLE_COMMENTER
;
966 case api::file_manager_private::DRIVE_SHARE_TYPE_CAN_VIEW
:
967 role
= google_apis::drive::PERMISSION_ROLE_READER
;
971 // Share |drive_path| in |owner_file_system| to |user->email()|.
972 owner_file_system
->AddPermission(
976 base::Bind(&FileManagerPrivateRequestDriveShareFunction::OnAddPermission
,
981 void FileManagerPrivateRequestDriveShareFunction::OnAddPermission(
982 drive::FileError error
) {
983 SendResponse(error
== drive::FILE_ERROR_OK
);
986 FileManagerPrivateGetDownloadUrlFunction::
987 FileManagerPrivateGetDownloadUrlFunction() {
990 FileManagerPrivateGetDownloadUrlFunction::
991 ~FileManagerPrivateGetDownloadUrlFunction() {
994 bool FileManagerPrivateGetDownloadUrlFunction::RunAsync() {
995 using extensions::api::file_manager_private::GetShareUrl::Params
;
996 const scoped_ptr
<Params
> params(Params::Create(*args_
));
997 EXTENSION_FUNCTION_VALIDATE(params
);
999 // Start getting the file info.
1000 drive::FileSystemInterface
* const file_system
=
1001 drive::util::GetFileSystemByProfile(GetProfile());
1003 // |file_system| is NULL if Drive is disabled or not mounted.
1004 SetError("Drive is disabled or not mounted.");
1005 SetResult(new base::StringValue("")); // Intentionally returns a blank.
1009 const base::FilePath path
= file_manager::util::GetLocalPathFromURL(
1010 render_view_host(), GetProfile(), GURL(params
->url
));
1011 if (!drive::util::IsUnderDriveMountPoint(path
)) {
1012 SetError("The given file is not in Drive.");
1013 SetResult(new base::StringValue("")); // Intentionally returns a blank.
1016 base::FilePath file_path
= drive::util::ExtractDrivePath(path
);
1018 file_system
->GetResourceEntry(
1020 base::Bind(&FileManagerPrivateGetDownloadUrlFunction::OnGetResourceEntry
,
1025 void FileManagerPrivateGetDownloadUrlFunction::OnGetResourceEntry(
1026 drive::FileError error
,
1027 scoped_ptr
<drive::ResourceEntry
> entry
) {
1028 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
1030 if (error
!= drive::FILE_ERROR_OK
) {
1031 SetError("Download Url for this item is not available.");
1032 SetResult(new base::StringValue("")); // Intentionally returns a blank.
1033 SendResponse(false);
1038 google_apis::DriveApiUrlGenerator::kBaseDownloadUrlForProduction
+
1039 entry
->resource_id();
1041 ProfileOAuth2TokenService
* oauth2_token_service
=
1042 ProfileOAuth2TokenServiceFactory::GetForProfile(GetProfile());
1043 SigninManagerBase
* signin_manager
=
1044 SigninManagerFactory::GetForProfile(GetProfile());
1045 const std::string
& account_id
= signin_manager
->GetAuthenticatedAccountId();
1046 std::vector
<std::string
> scopes
;
1047 scopes
.push_back("https://www.googleapis.com/auth/drive.readonly");
1049 auth_service_
.reset(
1050 new google_apis::AuthService(oauth2_token_service
,
1052 GetProfile()->GetRequestContext(),
1054 auth_service_
->StartAuthentication(base::Bind(
1055 &FileManagerPrivateGetDownloadUrlFunction::OnTokenFetched
, this));
1058 void FileManagerPrivateGetDownloadUrlFunction::OnTokenFetched(
1059 google_apis::DriveApiErrorCode code
,
1060 const std::string
& access_token
) {
1061 if (code
!= google_apis::HTTP_SUCCESS
) {
1062 SetError("Not able to fetch the token.");
1063 SetResult(new base::StringValue("")); // Intentionally returns a blank.
1064 SendResponse(false);
1068 const std::string url
= download_url_
+ "?access_token=" + access_token
;
1069 SetResult(new base::StringValue(url
));
1074 } // namespace extensions