Upstream version 6.35.121.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / chromeos / extensions / file_manager / private_api_drive.cc
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.
4
5 #include "chrome/browser/chromeos/extensions/file_manager/private_api_drive.h"
6
7 #include "chrome/browser/browser_process.h"
8 #include "chrome/browser/chromeos/drive/drive_integration_service.h"
9 #include "chrome/browser/chromeos/extensions/file_manager/private_api_util.h"
10 #include "chrome/browser/chromeos/file_manager/file_tasks.h"
11 #include "chrome/browser/chromeos/file_manager/fileapi_util.h"
12 #include "chrome/browser/chromeos/file_manager/url_util.h"
13 #include "chrome/browser/chromeos/fileapi/file_system_backend.h"
14 #include "chrome/browser/chromeos/login/user_manager.h"
15 #include "chrome/browser/drive/drive_app_registry.h"
16 #include "chrome/browser/drive/event_logger.h"
17 #include "chrome/browser/profiles/profile.h"
18 #include "chrome/browser/profiles/profile_manager.h"
19 #include "chrome/common/extensions/api/file_browser_private.h"
20 #include "content/public/browser/browser_thread.h"
21 #include "webkit/common/fileapi/file_system_info.h"
22 #include "webkit/common/fileapi/file_system_util.h"
23
24 using content::BrowserThread;
25
26 using file_manager::util::EntryDefinition;
27 using file_manager::util::EntryDefinitionCallback;
28 using file_manager::util::EntryDefinitionList;
29 using file_manager::util::EntryDefinitionListCallback;
30 using file_manager::util::FileDefinition;
31 using file_manager::util::FileDefinitionList;
32
33 namespace extensions {
34 namespace {
35
36 // List of connection types of drive.
37 // Keep this in sync with the DriveConnectionType in common/js/util.js.
38 const char kDriveConnectionTypeOffline[] = "offline";
39 const char kDriveConnectionTypeMetered[] = "metered";
40 const char kDriveConnectionTypeOnline[] = "online";
41
42 // List of reasons of kDriveConnectionType*.
43 // Keep this in sync with the DriveConnectionReason in common/js/util.js.
44 const char kDriveConnectionReasonNotReady[] = "not_ready";
45 const char kDriveConnectionReasonNoNetwork[] = "no_network";
46 const char kDriveConnectionReasonNoService[] = "no_service";
47
48 // Copies properties from |entry_proto| to |properties|. |shared_with_me| is
49 // given from the running profile.
50 void FillDriveEntryPropertiesValue(
51     const drive::ResourceEntry& entry_proto,
52     bool shared_with_me,
53     api::file_browser_private::DriveEntryProperties* properties) {
54   properties->shared_with_me.reset(new bool(shared_with_me));
55   properties->shared.reset(new bool(entry_proto.shared()));
56
57   if (!entry_proto.has_file_specific_info())
58     return;
59
60   const drive::FileSpecificInfo& file_specific_info =
61       entry_proto.file_specific_info();
62
63   properties->thumbnail_url.reset(
64       new std::string("https://www.googledrive.com/thumb/" +
65           entry_proto.resource_id() + "?width=500&height=500"));
66   if (file_specific_info.has_image_width()) {
67     properties->image_width.reset(
68         new int(file_specific_info.image_width()));
69   }
70   if (file_specific_info.has_image_height()) {
71     properties->image_height.reset(
72         new int(file_specific_info.image_height()));
73   }
74   if (file_specific_info.has_image_rotation()) {
75     properties->image_rotation.reset(
76         new int(file_specific_info.image_rotation()));
77   }
78   properties->is_hosted.reset(
79       new bool(file_specific_info.is_hosted_document()));
80   properties->content_mime_type.reset(
81       new std::string(file_specific_info.content_mime_type()));
82 }
83
84 // Creates entry definition list for (metadata) search result info list.
85 template <class T>
86 void ConvertSearchResultInfoListToEntryDefinitionList(
87     Profile* profile,
88     const std::string& extension_id,
89     const std::vector<T>& search_result_info_list,
90     const EntryDefinitionListCallback& callback) {
91   FileDefinitionList file_definition_list;
92
93   for (size_t i = 0; i < search_result_info_list.size(); ++i) {
94     FileDefinition file_definition;
95     file_definition.virtual_path =
96         file_manager::util::ConvertDrivePathToRelativeFileSystemPath(
97             profile, extension_id, search_result_info_list.at(i).path);
98     file_definition.is_directory = search_result_info_list.at(i).is_directory;
99     file_definition_list.push_back(file_definition);
100   }
101
102   file_manager::util::ConvertFileDefinitionListToEntryDefinitionList(
103       profile,
104       extension_id,
105       file_definition_list,  // Safe, since copied internally.
106       callback);
107 }
108
109 }  // namespace
110
111 FileBrowserPrivateGetDriveEntryPropertiesFunction::
112     FileBrowserPrivateGetDriveEntryPropertiesFunction()
113     : properties_(
114           new extensions::api::file_browser_private::DriveEntryProperties) {}
115
116 FileBrowserPrivateGetDriveEntryPropertiesFunction::
117     ~FileBrowserPrivateGetDriveEntryPropertiesFunction() {
118 }
119
120 bool FileBrowserPrivateGetDriveEntryPropertiesFunction::RunImpl() {
121   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
122
123   using extensions::api::file_browser_private::GetDriveEntryProperties::Params;
124   const scoped_ptr<Params> params(Params::Create(*args_));
125   EXTENSION_FUNCTION_VALIDATE(params);
126
127   const GURL file_url = GURL(params->file_url);
128   const base::FilePath local_path = file_manager::util::GetLocalPathFromURL(
129       render_view_host(), GetProfile(), file_url);
130   file_path_ = drive::util::ExtractDrivePath(local_path);
131   file_owner_profile_ = drive::util::ExtractProfileFromPath(local_path);
132
133   // Owner not found.
134   if (!file_owner_profile_) {
135     CompleteGetFileProperties(drive::FILE_ERROR_FAILED);
136     return true;
137   }
138
139   // Start getting the file info.
140   drive::FileSystemInterface* const file_system =
141       drive::util::GetFileSystemByProfile(file_owner_profile_);
142   if (!file_system) {
143     // |file_system| is NULL if Drive is disabled or not mounted.
144     CompleteGetFileProperties(drive::FILE_ERROR_FAILED);
145     return true;
146   }
147
148   file_system->GetResourceEntry(
149       file_path_,
150       base::Bind(
151           &FileBrowserPrivateGetDriveEntryPropertiesFunction::OnGetFileInfo,
152           this));
153   return true;
154 }
155
156 void FileBrowserPrivateGetDriveEntryPropertiesFunction::OnGetFileInfo(
157     drive::FileError error,
158     scoped_ptr<drive::ResourceEntry> entry) {
159   if (error != drive::FILE_ERROR_OK) {
160     CompleteGetFileProperties(error);
161     return;
162   }
163   DCHECK(entry);
164   owner_resource_entry_.swap(entry);
165
166   if (GetProfile()->IsSameProfile(file_owner_profile_)) {
167     StartParseFileInfo(owner_resource_entry_->shared_with_me());
168     return;
169   }
170
171   // If the running profile does not own the file, obtain the shared_with_me
172   // flag from the running profile's value.
173   drive::FileSystemInterface* const file_system =
174       drive::util::GetFileSystemByProfile(GetProfile());
175   if (!file_system) {
176     CompleteGetFileProperties(drive::FILE_ERROR_FAILED);
177     return;
178   }
179   file_system->GetPathFromResourceId(
180       owner_resource_entry_->resource_id(),
181       base::Bind(
182           &FileBrowserPrivateGetDriveEntryPropertiesFunction::OnGetRunningPath,
183           this));
184 }
185
186 void FileBrowserPrivateGetDriveEntryPropertiesFunction::OnGetRunningPath(
187     drive::FileError error,
188     const base::FilePath& file_path) {
189   if (error != drive::FILE_ERROR_OK) {
190     // The running profile does not know the file.
191     StartParseFileInfo(false);
192     return;
193   }
194
195   drive::FileSystemInterface* const file_system =
196       drive::util::GetFileSystemByProfile(GetProfile());
197   if (!file_system) {
198     // The drive is disable for the running profile.
199     StartParseFileInfo(false);
200     return;
201   }
202   file_system->GetResourceEntry(
203       file_path,
204       base::Bind(
205           &FileBrowserPrivateGetDriveEntryPropertiesFunction::OnGetShareInfo,
206           this));
207 }
208
209 void FileBrowserPrivateGetDriveEntryPropertiesFunction::OnGetShareInfo(
210     drive::FileError error,
211     scoped_ptr<drive::ResourceEntry> entry) {
212   if (error != drive::FILE_ERROR_OK) {
213     CompleteGetFileProperties(error);
214     return;
215   }
216   DCHECK(entry);
217   StartParseFileInfo(entry->shared_with_me());
218 }
219
220 void FileBrowserPrivateGetDriveEntryPropertiesFunction::StartParseFileInfo(
221     bool shared_with_me) {
222   if (!g_browser_process->profile_manager()->IsValidProfile(
223           file_owner_profile_)) {
224     CompleteGetFileProperties(drive::FILE_ERROR_FAILED);
225     return;
226   }
227
228   FillDriveEntryPropertiesValue(
229       *owner_resource_entry_, shared_with_me, properties_.get());
230
231   drive::FileSystemInterface* const file_system =
232       drive::util::GetFileSystemByProfile(file_owner_profile_);
233   drive::DriveAppRegistry* const app_registry =
234       drive::util::GetDriveAppRegistryByProfile(file_owner_profile_);
235   if (!file_system || !app_registry) {
236     // |file_system| or |app_registry| is NULL if Drive is disabled.
237     CompleteGetFileProperties(drive::FILE_ERROR_FAILED);
238     return;
239   }
240
241   // The properties meaningful for directories are already filled in
242   // FillDriveEntryPropertiesValue().
243   if (!owner_resource_entry_->has_file_specific_info()) {
244     CompleteGetFileProperties(drive::FILE_ERROR_OK);
245     return;
246   }
247
248   const drive::FileSpecificInfo& file_specific_info =
249       owner_resource_entry_->file_specific_info();
250
251   // Get drive WebApps that can accept this file. We just need to extract the
252   // doc icon for the drive app, which is set as default.
253   std::vector<drive::DriveAppInfo> drive_apps;
254   app_registry->GetAppsForFile(file_path_.Extension(),
255                                file_specific_info.content_mime_type(),
256                                &drive_apps);
257   if (!drive_apps.empty()) {
258     std::string default_task_id =
259         file_manager::file_tasks::GetDefaultTaskIdFromPrefs(
260             *file_owner_profile_->GetPrefs(),
261             file_specific_info.content_mime_type(),
262             file_path_.Extension());
263     file_manager::file_tasks::TaskDescriptor default_task;
264     file_manager::file_tasks::ParseTaskID(default_task_id, &default_task);
265     DCHECK(default_task_id.empty() || !default_task.app_id.empty());
266     for (size_t i = 0; i < drive_apps.size(); ++i) {
267       const drive::DriveAppInfo& app_info = drive_apps[i];
268       if (default_task.app_id == app_info.app_id) {
269         // The drive app is set as default. Files.app should use the doc icon.
270         const GURL doc_icon =
271             drive::util::FindPreferredIcon(app_info.document_icons,
272                                            drive::util::kPreferredIconSize);
273         properties_->custom_icon_url.reset(new std::string(doc_icon.spec()));
274       }
275     }
276   }
277
278   file_system->GetCacheEntry(
279       file_path_,
280       base::Bind(&FileBrowserPrivateGetDriveEntryPropertiesFunction::
281                      CacheStateReceived, this));
282 }
283
284 void FileBrowserPrivateGetDriveEntryPropertiesFunction::CacheStateReceived(
285     bool /* success */,
286     const drive::FileCacheEntry& cache_entry) {
287   // In case of an error (i.e. success is false), cache_entry.is_*() all
288   // returns false.
289   properties_->is_pinned.reset(new bool(cache_entry.is_pinned()));
290   properties_->is_present.reset(new bool(cache_entry.is_present()));
291
292   CompleteGetFileProperties(drive::FILE_ERROR_OK);
293 }
294
295 void FileBrowserPrivateGetDriveEntryPropertiesFunction::
296     CompleteGetFileProperties(drive::FileError error) {
297   results_ = extensions::api::file_browser_private::GetDriveEntryProperties::
298       Results::Create(*properties_);
299   SendResponse(true);
300 }
301
302 bool FileBrowserPrivatePinDriveFileFunction::RunImpl() {
303   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
304
305   using extensions::api::file_browser_private::PinDriveFile::Params;
306   const scoped_ptr<Params> params(Params::Create(*args_));
307   EXTENSION_FUNCTION_VALIDATE(params);
308
309   drive::FileSystemInterface* const file_system =
310       drive::util::GetFileSystemByProfile(GetProfile());
311   if (!file_system)  // |file_system| is NULL if Drive is disabled.
312     return false;
313
314   const base::FilePath drive_path =
315       drive::util::ExtractDrivePath(file_manager::util::GetLocalPathFromURL(
316           render_view_host(), GetProfile(), GURL(params->file_url)));
317   if (params->pin) {
318     file_system->Pin(drive_path,
319                      base::Bind(&FileBrowserPrivatePinDriveFileFunction::
320                                     OnPinStateSet, this));
321   } else {
322     file_system->Unpin(drive_path,
323                        base::Bind(&FileBrowserPrivatePinDriveFileFunction::
324                                       OnPinStateSet, this));
325   }
326   return true;
327 }
328
329 void FileBrowserPrivatePinDriveFileFunction::
330     OnPinStateSet(drive::FileError error) {
331   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
332
333   if (error == drive::FILE_ERROR_OK) {
334     SendResponse(true);
335   } else {
336     SetError(drive::FileErrorToString(error));
337     SendResponse(false);
338   }
339 }
340
341 FileBrowserPrivateGetDriveFilesFunction::
342     FileBrowserPrivateGetDriveFilesFunction() {
343 }
344
345 FileBrowserPrivateGetDriveFilesFunction::
346     ~FileBrowserPrivateGetDriveFilesFunction() {
347 }
348
349 bool FileBrowserPrivateGetDriveFilesFunction::RunImpl() {
350   using extensions::api::file_browser_private::GetDriveFiles::Params;
351   const scoped_ptr<Params> params(Params::Create(*args_));
352   EXTENSION_FUNCTION_VALIDATE(params);
353
354   // Convert the list of strings to a list of GURLs.
355   for (size_t i = 0; i < params->file_urls.size(); ++i) {
356     const base::FilePath path = file_manager::util::GetLocalPathFromURL(
357         render_view_host(), GetProfile(), GURL(params->file_urls[i]));
358     DCHECK(drive::util::IsUnderDriveMountPoint(path));
359     base::FilePath drive_path = drive::util::ExtractDrivePath(path);
360     remaining_drive_paths_.push(drive_path);
361   }
362
363   GetFileOrSendResponse();
364   return true;
365 }
366
367 void FileBrowserPrivateGetDriveFilesFunction::GetFileOrSendResponse() {
368   // Send the response if all files are obtained.
369   if (remaining_drive_paths_.empty()) {
370     results_ = extensions::api::file_browser_private::
371         GetDriveFiles::Results::Create(local_paths_);
372     SendResponse(true);
373     return;
374   }
375
376   // Get the file on the top of the queue.
377   base::FilePath drive_path = remaining_drive_paths_.front();
378
379   drive::FileSystemInterface* file_system =
380       drive::util::GetFileSystemByProfile(GetProfile());
381   if (!file_system) {
382     // |file_system| is NULL if Drive is disabled or not mounted.
383     OnFileReady(drive::FILE_ERROR_FAILED, drive_path,
384                 scoped_ptr<drive::ResourceEntry>());
385     return;
386   }
387
388   file_system->GetFile(
389       drive_path,
390       base::Bind(&FileBrowserPrivateGetDriveFilesFunction::OnFileReady, this));
391 }
392
393
394 void FileBrowserPrivateGetDriveFilesFunction::OnFileReady(
395     drive::FileError error,
396     const base::FilePath& local_path,
397     scoped_ptr<drive::ResourceEntry> entry) {
398   base::FilePath drive_path = remaining_drive_paths_.front();
399
400   if (error == drive::FILE_ERROR_OK) {
401     local_paths_.push_back(local_path.AsUTF8Unsafe());
402     DVLOG(1) << "Got " << drive_path.value() << " as " << local_path.value();
403   } else {
404     local_paths_.push_back("");
405     DVLOG(1) << "Failed to get " << drive_path.value()
406              << " with error code: " << error;
407   }
408
409   remaining_drive_paths_.pop();
410
411   // Start getting the next file.
412   GetFileOrSendResponse();
413 }
414
415 bool FileBrowserPrivateCancelFileTransfersFunction::RunImpl() {
416   using extensions::api::file_browser_private::CancelFileTransfers::Params;
417   const scoped_ptr<Params> params(Params::Create(*args_));
418   EXTENSION_FUNCTION_VALIDATE(params);
419
420   drive::DriveIntegrationService* integration_service =
421       drive::DriveIntegrationServiceFactory::FindForProfile(GetProfile());
422   if (!integration_service || !integration_service->IsMounted())
423     return false;
424
425   // Create the mapping from file path to job ID.
426   drive::JobListInterface* job_list = integration_service->job_list();
427   DCHECK(job_list);
428   std::vector<drive::JobInfo> jobs = job_list->GetJobInfoList();
429
430   typedef std::map<base::FilePath, std::vector<drive::JobID> > PathToIdMap;
431   PathToIdMap path_to_id_map;
432   for (size_t i = 0; i < jobs.size(); ++i) {
433     if (drive::IsActiveFileTransferJobInfo(jobs[i]))
434       path_to_id_map[jobs[i].file_path].push_back(jobs[i].job_id);
435   }
436
437   // Cancel by Job ID.
438   std::vector<linked_ptr<api::file_browser_private::
439                          FileTransferCancelStatus> > responses;
440   for (size_t i = 0; i < params->file_urls.size(); ++i) {
441     base::FilePath file_path = file_manager::util::GetLocalPathFromURL(
442         render_view_host(), GetProfile(), GURL(params->file_urls[i]));
443     if (file_path.empty())
444       continue;
445
446     DCHECK(drive::util::IsUnderDriveMountPoint(file_path));
447     file_path = drive::util::ExtractDrivePath(file_path);
448
449     // Cancel all the jobs for the file.
450     PathToIdMap::iterator it = path_to_id_map.find(file_path);
451     if (it != path_to_id_map.end()) {
452       for (size_t i = 0; i < it->second.size(); ++i)
453         job_list->CancelJob(it->second[i]);
454     }
455     linked_ptr<api::file_browser_private::FileTransferCancelStatus> result(
456         new api::file_browser_private::FileTransferCancelStatus);
457     result->canceled = it != path_to_id_map.end();
458     // TODO(kinaba): simplify cancelFileTransfer() to take single URL each time,
459     // and eliminate this field; it is just returning a copy of the argument.
460     result->file_url = params->file_urls[i];
461     responses.push_back(result);
462   }
463   results_ = api::file_browser_private::CancelFileTransfers::Results::Create(
464       responses);
465   SendResponse(true);
466   return true;
467 }
468
469 bool FileBrowserPrivateSearchDriveFunction::RunImpl() {
470   using extensions::api::file_browser_private::SearchDrive::Params;
471   const scoped_ptr<Params> params(Params::Create(*args_));
472   EXTENSION_FUNCTION_VALIDATE(params);
473
474   drive::FileSystemInterface* const file_system =
475       drive::util::GetFileSystemByProfile(GetProfile());
476   if (!file_system) {
477     // |file_system| is NULL if Drive is disabled.
478     return false;
479   }
480
481   file_system->Search(
482       params->search_params.query, GURL(params->search_params.next_feed),
483       base::Bind(&FileBrowserPrivateSearchDriveFunction::OnSearch, this));
484   return true;
485 }
486
487 void FileBrowserPrivateSearchDriveFunction::OnSearch(
488     drive::FileError error,
489     const GURL& next_link,
490     scoped_ptr<SearchResultInfoList> results) {
491   if (error != drive::FILE_ERROR_OK) {
492     SendResponse(false);
493     return;
494   }
495
496   // Outlives the following conversion, since the pointer is bound to the
497   // callback.
498   DCHECK(results.get());
499   const SearchResultInfoList& results_ref = *results.get();
500
501   ConvertSearchResultInfoListToEntryDefinitionList(
502       GetProfile(),
503       extension_->id(),
504       results_ref,
505       base::Bind(&FileBrowserPrivateSearchDriveFunction::OnEntryDefinitionList,
506                  this,
507                  next_link,
508                  base::Passed(&results)));
509 }
510
511 void FileBrowserPrivateSearchDriveFunction::OnEntryDefinitionList(
512     const GURL& next_link,
513     scoped_ptr<SearchResultInfoList> search_result_info_list,
514     scoped_ptr<EntryDefinitionList> entry_definition_list) {
515   DCHECK_EQ(search_result_info_list->size(), entry_definition_list->size());
516   base::ListValue* entries = new base::ListValue();
517
518   // Convert Drive files to something File API stack can understand.
519   for (EntryDefinitionList::const_iterator it = entry_definition_list->begin();
520        it != entry_definition_list->end();
521        ++it) {
522     base::DictionaryValue* entry = new base::DictionaryValue();
523     entry->SetString("fileSystemName", it->file_system_name);
524     entry->SetString("fileSystemRoot", it->file_system_root_url);
525     entry->SetString("fileFullPath", "/" + it->full_path.AsUTF8Unsafe());
526     entry->SetBoolean("fileIsDirectory", it->is_directory);
527     entries->Append(entry);
528   }
529
530   base::DictionaryValue* result = new base::DictionaryValue();
531   result->Set("entries", entries);
532   result->SetString("nextFeed", next_link.spec());
533
534   SetResult(result);
535   SendResponse(true);
536 }
537
538 bool FileBrowserPrivateSearchDriveMetadataFunction::RunImpl() {
539   using api::file_browser_private::SearchDriveMetadata::Params;
540   const scoped_ptr<Params> params(Params::Create(*args_));
541   EXTENSION_FUNCTION_VALIDATE(params);
542
543   drive::EventLogger* logger = file_manager::util::GetLogger(GetProfile());
544   if (logger) {
545     logger->Log(logging::LOG_INFO,
546                 "%s[%d] called. (types: '%s', maxResults: '%d')",
547                 name().c_str(),
548                 request_id(),
549                 api::file_browser_private::ToString(
550                     params->search_params.types).c_str(),
551                 params->search_params.max_results);
552   }
553   set_log_on_completion(true);
554
555   drive::FileSystemInterface* const file_system =
556       drive::util::GetFileSystemByProfile(GetProfile());
557   if (!file_system) {
558     // |file_system| is NULL if Drive is disabled.
559     return false;
560   }
561
562   int options = -1;
563   switch (params->search_params.types) {
564     case api::file_browser_private::SEARCH_TYPE_EXCLUDE_DIRECTORIES:
565       options = drive::SEARCH_METADATA_EXCLUDE_DIRECTORIES;
566       break;
567     case api::file_browser_private::SEARCH_TYPE_SHARED_WITH_ME:
568       options = drive::SEARCH_METADATA_SHARED_WITH_ME;
569       break;
570     case api::file_browser_private::SEARCH_TYPE_OFFLINE:
571       options = drive::SEARCH_METADATA_OFFLINE;
572       break;
573     case api::file_browser_private::SEARCH_TYPE_ALL:
574       options = drive::SEARCH_METADATA_ALL;
575       break;
576     case api::file_browser_private::SEARCH_TYPE_NONE:
577       break;
578   }
579   DCHECK_NE(options, -1);
580
581   file_system->SearchMetadata(
582       params->search_params.query,
583       options,
584       params->search_params.max_results,
585       base::Bind(&FileBrowserPrivateSearchDriveMetadataFunction::
586                      OnSearchMetadata, this));
587   return true;
588 }
589
590 void FileBrowserPrivateSearchDriveMetadataFunction::OnSearchMetadata(
591     drive::FileError error,
592     scoped_ptr<drive::MetadataSearchResultVector> results) {
593   if (error != drive::FILE_ERROR_OK) {
594     SendResponse(false);
595     return;
596   }
597
598   // Outlives the following conversion, since the pointer is bound to the
599   // callback.
600   DCHECK(results.get());
601   const drive::MetadataSearchResultVector& results_ref = *results.get();
602
603   ConvertSearchResultInfoListToEntryDefinitionList(
604       GetProfile(),
605       extension_->id(),
606       results_ref,
607       base::Bind(
608           &FileBrowserPrivateSearchDriveMetadataFunction::OnEntryDefinitionList,
609           this,
610           base::Passed(&results)));
611 }
612
613 void FileBrowserPrivateSearchDriveMetadataFunction::OnEntryDefinitionList(
614     scoped_ptr<drive::MetadataSearchResultVector> search_result_info_list,
615     scoped_ptr<EntryDefinitionList> entry_definition_list) {
616   DCHECK_EQ(search_result_info_list->size(), entry_definition_list->size());
617   base::ListValue* results_list = new base::ListValue();
618
619   // Convert Drive files to something File API stack can understand.  See
620   // file_browser_handler_custom_bindings.cc and
621   // file_browser_private_custom_bindings.js for how this is magically
622   // converted to a FileEntry.
623   for (size_t i = 0; i < entry_definition_list->size(); ++i) {
624     base::DictionaryValue* result_dict = new base::DictionaryValue();
625
626     // FileEntry fields.
627     base::DictionaryValue* entry = new base::DictionaryValue();
628     entry->SetString(
629         "fileSystemName", entry_definition_list->at(i).file_system_name);
630     entry->SetString(
631         "fileSystemRoot", entry_definition_list->at(i).file_system_root_url);
632     entry->SetString(
633         "fileFullPath",
634         "/" + entry_definition_list->at(i).full_path.AsUTF8Unsafe());
635     entry->SetBoolean("fileIsDirectory",
636                       entry_definition_list->at(i).is_directory);
637
638     result_dict->Set("entry", entry);
639     result_dict->SetString(
640         "highlightedBaseName",
641         search_result_info_list->at(i).highlighted_base_name);
642     results_list->Append(result_dict);
643   }
644
645   SetResult(results_list);
646   SendResponse(true);
647 }
648
649 bool FileBrowserPrivateGetDriveConnectionStateFunction::RunImpl() {
650   api::file_browser_private::DriveConnectionState result;
651
652   switch (drive::util::GetDriveConnectionStatus(GetProfile())) {
653     case drive::util::DRIVE_DISCONNECTED_NOSERVICE:
654       result.type = kDriveConnectionTypeOffline;
655       result.reason.reset(new std::string(kDriveConnectionReasonNoService));
656       break;
657     case drive::util::DRIVE_DISCONNECTED_NONETWORK:
658       result.type = kDriveConnectionTypeOffline;
659       result.reason.reset(new std::string(kDriveConnectionReasonNoNetwork));
660       break;
661     case drive::util::DRIVE_DISCONNECTED_NOTREADY:
662       result.type = kDriveConnectionTypeOffline;
663       result.reason.reset(new std::string(kDriveConnectionReasonNotReady));
664       break;
665     case drive::util::DRIVE_CONNECTED_METERED:
666       result.type = kDriveConnectionTypeMetered;
667       break;
668     case drive::util::DRIVE_CONNECTED:
669       result.type = kDriveConnectionTypeOnline;
670       break;
671   }
672
673   results_ = api::file_browser_private::GetDriveConnectionState::Results::
674       Create(result);
675
676   drive::EventLogger* logger = file_manager::util::GetLogger(GetProfile());
677   if (logger)
678     logger->Log(logging::LOG_INFO, "%s succeeded.", name().c_str());
679   return true;
680 }
681
682 bool FileBrowserPrivateRequestAccessTokenFunction::RunImpl() {
683   using extensions::api::file_browser_private::RequestAccessToken::Params;
684   const scoped_ptr<Params> params(Params::Create(*args_));
685   EXTENSION_FUNCTION_VALIDATE(params);
686
687   drive::DriveServiceInterface* const drive_service =
688       drive::util::GetDriveServiceByProfile(GetProfile());
689
690   if (!drive_service) {
691     // DriveService is not available.
692     SetResult(new base::StringValue(""));
693     SendResponse(true);
694     return true;
695   }
696
697   // If refreshing is requested, then clear the token to refetch it.
698   if (params->refresh)
699     drive_service->ClearAccessToken();
700
701   // Retrieve the cached auth token (if available), otherwise the AuthService
702   // instance will try to refetch it.
703   drive_service->RequestAccessToken(
704       base::Bind(&FileBrowserPrivateRequestAccessTokenFunction::
705                       OnAccessTokenFetched, this));
706   return true;
707 }
708
709 void FileBrowserPrivateRequestAccessTokenFunction::OnAccessTokenFetched(
710     google_apis::GDataErrorCode code,
711     const std::string& access_token) {
712   SetResult(new base::StringValue(access_token));
713   SendResponse(true);
714 }
715
716 bool FileBrowserPrivateGetShareUrlFunction::RunImpl() {
717   using extensions::api::file_browser_private::GetShareUrl::Params;
718   const scoped_ptr<Params> params(Params::Create(*args_));
719   EXTENSION_FUNCTION_VALIDATE(params);
720
721   const base::FilePath path = file_manager::util::GetLocalPathFromURL(
722       render_view_host(), GetProfile(), GURL(params->url));
723   DCHECK(drive::util::IsUnderDriveMountPoint(path));
724
725   const base::FilePath drive_path = drive::util::ExtractDrivePath(path);
726
727   drive::FileSystemInterface* const file_system =
728       drive::util::GetFileSystemByProfile(GetProfile());
729   if (!file_system) {
730     // |file_system| is NULL if Drive is disabled.
731     return false;
732   }
733
734   file_system->GetShareUrl(
735       drive_path,
736       file_manager::util::GetFileManagerBaseUrl(),  // embed origin
737       base::Bind(&FileBrowserPrivateGetShareUrlFunction::OnGetShareUrl, this));
738   return true;
739 }
740
741 void FileBrowserPrivateGetShareUrlFunction::OnGetShareUrl(
742     drive::FileError error,
743     const GURL& share_url) {
744   if (error != drive::FILE_ERROR_OK) {
745     SetError("Share Url for this item is not available.");
746     SendResponse(false);
747     return;
748   }
749
750   SetResult(new base::StringValue(share_url.spec()));
751   SendResponse(true);
752 }
753
754 bool FileBrowserPrivateRequestDriveShareFunction::RunImpl() {
755   using extensions::api::file_browser_private::RequestDriveShare::Params;
756   const scoped_ptr<Params> params(Params::Create(*args_));
757   EXTENSION_FUNCTION_VALIDATE(params);
758
759   const base::FilePath path = file_manager::util::GetLocalPathFromURL(
760       render_view_host(), GetProfile(), GURL(params->url));
761   const base::FilePath drive_path = drive::util::ExtractDrivePath(path);
762   Profile* const owner_profile = drive::util::ExtractProfileFromPath(path);
763
764   if (!owner_profile)
765     return false;
766
767   drive::FileSystemInterface* const owner_file_system =
768       drive::util::GetFileSystemByProfile(owner_profile);
769   if (!owner_file_system)
770     return false;
771
772   const chromeos::User* const user =
773       chromeos::UserManager::Get()->GetUserByProfile(GetProfile());
774   if (!user || !user->is_logged_in())
775     return false;
776
777   google_apis::drive::PermissionRole role =
778       google_apis::drive::PERMISSION_ROLE_READER;
779   switch (params->share_type) {
780     case api::file_browser_private::DRIVE_SHARE_TYPE_NONE:
781       NOTREACHED();
782       return false;
783     case api::file_browser_private::DRIVE_SHARE_TYPE_CAN_EDIT:
784       role = google_apis::drive::PERMISSION_ROLE_WRITER;
785       break;
786     case api::file_browser_private::DRIVE_SHARE_TYPE_CAN_COMMENT:
787       role = google_apis::drive::PERMISSION_ROLE_COMMENTER;
788       break;
789     case api::file_browser_private::DRIVE_SHARE_TYPE_CAN_VIEW:
790       role = google_apis::drive::PERMISSION_ROLE_READER;
791       break;
792   }
793
794   // Share |drive_path| in |owner_file_system| to |user->email()|.
795   owner_file_system->AddPermission(
796       drive_path,
797       user->email(),
798       role,
799       base::Bind(&FileBrowserPrivateRequestDriveShareFunction::OnAddPermission,
800                  this));
801   return true;
802 }
803
804 void FileBrowserPrivateRequestDriveShareFunction::OnAddPermission(
805     drive::FileError error) {
806   SendResponse(error == drive::FILE_ERROR_OK);
807 }
808
809 }  // namespace extensions