ozone: evdev: Sync caps lock LED state to evdev
[chromium-blink-merge.git] / chrome / browser / chromeos / extensions / file_manager / private_api_drive.cc
blobe97e59bb41b91393c5a0831158a746a40312d638
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"
7 #include <map>
8 #include <set>
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"
38 #include "url/gurl.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 {
56 namespace {
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,
73 bool shared_with_me,
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())
84 return;
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)),
92 (GURL(
93 google_apis::DriveApiUrlGenerator::kBaseDownloadUrlForProduction)));
94 properties->thumbnail_url.reset(new std::string(
95 url_generator.GetThumbnailUrl(entry_proto.resource_id(),
96 500 /* width */,
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"));
131 } else {
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.
141 template <class T>
142 void ConvertSearchResultInfoListToEntryDefinitionList(
143 Profile* profile,
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(
159 profile,
160 extension_id,
161 file_definition_list, // Safe, since copied internally.
162 callback);
165 class SingleEntryPropertiesGetterForDrive {
166 public:
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,
179 callback);
180 instance->StartProcess();
182 // The instance will be destroyed by itself.
185 virtual ~SingleEntryPropertiesGetterForDrive() {}
187 private:
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());
200 DCHECK(profile);
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);
213 return;
216 // Start getting the file info.
217 drive::FileSystemInterface* const file_system =
218 drive::util::GetFileSystemByProfile(file_owner_profile_);
219 if (!file_system) {
220 // |file_system| is NULL if Drive is disabled or not mounted.
221 CompleteGetEntryProperties(drive::FILE_ERROR_FAILED);
222 return;
225 file_system->GetResourceEntry(
226 file_path_,
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);
237 return;
240 DCHECK(entry);
241 owner_resource_entry_.swap(entry);
243 if (running_profile_->IsSameProfile(file_owner_profile_)) {
244 StartParseFileInfo(owner_resource_entry_->shared_with_me());
245 return;
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_);
252 if (!file_system) {
253 CompleteGetEntryProperties(drive::FILE_ERROR_FAILED);
254 return;
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);
269 return;
272 drive::FileSystemInterface* const file_system =
273 drive::util::GetFileSystemByProfile(running_profile_);
274 if (!file_system) {
275 // The drive is disable for the running profile.
276 StartParseFileInfo(false);
277 return;
280 file_system->GetResourceEntry(
281 file_path,
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);
292 return;
295 DCHECK(entry.get());
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);
312 return;
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);
319 return;
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(),
330 &drive_apps);
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);
362 // Given parameters.
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 {
377 public:
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,
389 names, callback);
390 instance->StartProcess();
392 // The instance will be destroyed by itself.
395 virtual ~SingleEntryPropertiesGetterForFileSystemProvider() {}
397 private:
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),
404 names_(names),
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);
416 return;
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.
423 if (names_.find(
424 api::file_manager_private::ENTRY_PROPERTY_NAME_THUMBNAILURL) !=
425 names_.end())
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);
441 return;
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);
462 // Given parameters.
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>
471 weak_ptr_factory_;
472 }; // class SingleEntryPropertiesGetterForDrive
474 } // namespace
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));
510 break;
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));
517 break;
518 default:
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);
528 return true;
531 void FileManagerPrivateGetEntryPropertiesFunction::CompleteGetEntryProperties(
532 size_t index,
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()));
545 processed_count_++;
546 if (processed_count_ < properties_list_.size())
547 return;
549 results_ = extensions::api::file_manager_private::GetEntryProperties::
550 Results::Create(properties_list_);
551 SendResponse(true);
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.
564 return false;
566 const base::FilePath drive_path =
567 drive::util::ExtractDrivePath(file_manager::util::GetLocalPathFromURL(
568 render_view_host(), GetProfile(), GURL(params->file_url)));
569 if (params->pin) {
570 file_system->Pin(drive_path,
571 base::Bind(&FileManagerPrivatePinDriveFileFunction::
572 OnPinStateSet, this));
573 } else {
574 file_system->Unpin(drive_path,
575 base::Bind(&FileManagerPrivatePinDriveFileFunction::
576 OnPinStateSet, this));
578 return true;
581 void FileManagerPrivatePinDriveFileFunction::
582 OnPinStateSet(drive::FileError error) {
583 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
585 if (error == drive::FILE_ERROR_OK) {
586 SendResponse(true);
587 } else {
588 SetError(drive::FileErrorToString(error));
589 SendResponse(false);
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())
601 return false;
603 drive::JobListInterface* job_list = integration_service->job_list();
604 DCHECK(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);
613 } else {
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())
627 continue;
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]);
640 SendResponse(true);
641 return true;
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());
651 if (!file_system) {
652 // |file_system| is NULL if Drive is disabled.
653 return false;
656 file_system->Search(
657 params->search_params.query, GURL(params->search_params.next_feed),
658 base::Bind(&FileManagerPrivateSearchDriveFunction::OnSearch, this));
659 return true;
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) {
667 SendResponse(false);
668 return;
671 // Outlives the following conversion, since the pointer is bound to the
672 // callback.
673 DCHECK(results.get());
674 const SearchResultInfoList& results_ref = *results.get();
676 ConvertSearchResultInfoListToEntryDefinitionList(
677 GetProfile(),
678 extension_->id(),
679 results_ref,
680 base::Bind(&FileManagerPrivateSearchDriveFunction::OnEntryDefinitionList,
681 this,
682 next_link,
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();
696 ++it) {
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());
709 SetResult(result);
710 SendResponse(true);
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());
719 if (logger) {
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());
730 if (!file_system) {
731 // |file_system| is NULL if Drive is disabled.
732 return false;
735 int options = -1;
736 switch (params->search_params.types) {
737 case api::file_manager_private::SEARCH_TYPE_EXCLUDE_DIRECTORIES:
738 options = drive::SEARCH_METADATA_EXCLUDE_DIRECTORIES;
739 break;
740 case api::file_manager_private::SEARCH_TYPE_SHARED_WITH_ME:
741 options = drive::SEARCH_METADATA_SHARED_WITH_ME;
742 break;
743 case api::file_manager_private::SEARCH_TYPE_OFFLINE:
744 options = drive::SEARCH_METADATA_OFFLINE;
745 break;
746 case api::file_manager_private::SEARCH_TYPE_ALL:
747 options = drive::SEARCH_METADATA_ALL;
748 break;
749 case api::file_manager_private::SEARCH_TYPE_NONE:
750 break;
752 DCHECK_NE(options, -1);
754 file_system->SearchMetadata(
755 params->search_params.query,
756 options,
757 params->search_params.max_results,
758 base::Bind(&FileManagerPrivateSearchDriveMetadataFunction::
759 OnSearchMetadata, this));
760 return true;
763 void FileManagerPrivateSearchDriveMetadataFunction::OnSearchMetadata(
764 drive::FileError error,
765 scoped_ptr<drive::MetadataSearchResultVector> results) {
766 if (error != drive::FILE_ERROR_OK) {
767 SendResponse(false);
768 return;
771 // Outlives the following conversion, since the pointer is bound to the
772 // callback.
773 DCHECK(results.get());
774 const drive::MetadataSearchResultVector& results_ref = *results.get();
776 ConvertSearchResultInfoListToEntryDefinitionList(
777 GetProfile(),
778 extension_->id(),
779 results_ref,
780 base::Bind(
781 &FileManagerPrivateSearchDriveMetadataFunction::OnEntryDefinitionList,
782 this,
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();
799 // FileEntry fields.
800 base::DictionaryValue* entry = new base::DictionaryValue();
801 entry->SetString(
802 "fileSystemName", entry_definition_list->at(i).file_system_name);
803 entry->SetString(
804 "fileSystemRoot", entry_definition_list->at(i).file_system_root_url);
805 entry->SetString(
806 "fileFullPath",
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);
819 SendResponse(true);
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));
829 break;
830 case drive::util::DRIVE_DISCONNECTED_NONETWORK:
831 result.type = kDriveConnectionTypeOffline;
832 result.reason.reset(new std::string(kDriveConnectionReasonNoNetwork));
833 break;
834 case drive::util::DRIVE_DISCONNECTED_NOTREADY:
835 result.type = kDriveConnectionTypeOffline;
836 result.reason.reset(new std::string(kDriveConnectionReasonNotReady));
837 break;
838 case drive::util::DRIVE_CONNECTED_METERED:
839 result.type = kDriveConnectionTypeMetered;
840 break;
841 case drive::util::DRIVE_CONNECTED:
842 result.type = kDriveConnectionTypeOnline;
843 break;
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::
851 Create(result);
853 drive::EventLogger* logger = file_manager::util::GetLogger(GetProfile());
854 if (logger)
855 logger->Log(logging::LOG_INFO, "%s succeeded.", name());
856 return true;
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(""));
870 SendResponse(true);
871 return true;
874 // If refreshing is requested, then clear the token to refetch it.
875 if (params->refresh)
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));
883 return true;
886 void FileManagerPrivateRequestAccessTokenFunction::OnAccessTokenFetched(
887 google_apis::DriveApiErrorCode code,
888 const std::string& access_token) {
889 SetResult(new base::StringValue(access_token));
890 SendResponse(true);
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());
906 if (!file_system) {
907 // |file_system| is NULL if Drive is disabled.
908 return false;
911 file_system->GetShareUrl(
912 drive_path,
913 GURL("chrome-extension://" + extension_id()), // embed origin
914 base::Bind(&FileManagerPrivateGetShareUrlFunction::OnGetShareUrl, this));
915 return true;
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.");
923 SendResponse(false);
924 return;
927 SetResult(new base::StringValue(share_url.spec()));
928 SendResponse(true);
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);
941 if (!owner_profile)
942 return false;
944 drive::FileSystemInterface* const owner_file_system =
945 drive::util::GetFileSystemByProfile(owner_profile);
946 if (!owner_file_system)
947 return false;
949 const user_manager::User* const user =
950 chromeos::ProfileHelper::Get()->GetUserByProfile(GetProfile());
951 if (!user || !user->is_logged_in())
952 return false;
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:
958 NOTREACHED();
959 return false;
960 case api::file_manager_private::DRIVE_SHARE_TYPE_CAN_EDIT:
961 role = google_apis::drive::PERMISSION_ROLE_WRITER;
962 break;
963 case api::file_manager_private::DRIVE_SHARE_TYPE_CAN_COMMENT:
964 role = google_apis::drive::PERMISSION_ROLE_COMMENTER;
965 break;
966 case api::file_manager_private::DRIVE_SHARE_TYPE_CAN_VIEW:
967 role = google_apis::drive::PERMISSION_ROLE_READER;
968 break;
971 // Share |drive_path| in |owner_file_system| to |user->email()|.
972 owner_file_system->AddPermission(
973 drive_path,
974 user->email(),
975 role,
976 base::Bind(&FileManagerPrivateRequestDriveShareFunction::OnAddPermission,
977 this));
978 return true;
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());
1002 if (!file_system) {
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.
1006 return false;
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.
1014 return false;
1016 base::FilePath file_path = drive::util::ExtractDrivePath(path);
1018 file_system->GetResourceEntry(
1019 file_path,
1020 base::Bind(&FileManagerPrivateGetDownloadUrlFunction::OnGetResourceEntry,
1021 this));
1022 return true;
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);
1034 return;
1037 download_url_ =
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,
1051 account_id,
1052 GetProfile()->GetRequestContext(),
1053 scopes));
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);
1065 return;
1068 const std::string url = download_url_ + "?access_token=" + access_token;
1069 SetResult(new base::StringValue(url));
1071 SendResponse(true);
1074 } // namespace extensions