Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / chromeos / extensions / file_manager / private_api_drive.cc
index 139ca7e..f087837 100644 (file)
@@ -4,21 +4,47 @@
 
 #include "chrome/browser/chromeos/extensions/file_manager/private_api_drive.h"
 
+#include "base/command_line.h"
+#include "chrome/browser/browser_process.h"
 #include "chrome/browser/chromeos/drive/drive_integration_service.h"
-#include "chrome/browser/chromeos/drive/logging.h"
 #include "chrome/browser/chromeos/extensions/file_manager/private_api_util.h"
 #include "chrome/browser/chromeos/file_manager/file_tasks.h"
+#include "chrome/browser/chromeos/file_manager/fileapi_util.h"
 #include "chrome/browser/chromeos/file_manager/url_util.h"
+#include "chrome/browser/chromeos/file_system_provider/mount_path_util.h"
+#include "chrome/browser/chromeos/file_system_provider/provided_file_system_interface.h"
+#include "chrome/browser/chromeos/fileapi/external_file_url_util.h"
 #include "chrome/browser/chromeos/fileapi/file_system_backend.h"
+#include "chrome/browser/chromeos/profiles/profile_helper.h"
 #include "chrome/browser/drive/drive_app_registry.h"
+#include "chrome/browser/drive/event_logger.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/common/extensions/api/file_browser_private.h"
+#include "chrome/browser/profiles/profile_manager.h"
+#include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
+#include "chrome/browser/signin/signin_manager_factory.h"
+#include "chromeos/chromeos_switches.h"
+#include "chromeos/network/network_handler.h"
+#include "chromeos/network/network_state_handler.h"
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/signin_manager.h"
 #include "content/public/browser/browser_thread.h"
-#include "webkit/common/fileapi/file_system_info.h"
-#include "webkit/common/fileapi/file_system_util.h"
+#include "google_apis/drive/auth_service.h"
+#include "storage/common/fileapi/file_system_info.h"
+#include "storage/common/fileapi/file_system_util.h"
 
 using content::BrowserThread;
 
+using chromeos::file_system_provider::EntryMetadata;
+using chromeos::file_system_provider::ProvidedFileSystemInterface;
+using chromeos::file_system_provider::util::FileSystemURLParser;
+using extensions::api::file_manager_private::EntryProperties;
+using file_manager::util::EntryDefinition;
+using file_manager::util::EntryDefinitionCallback;
+using file_manager::util::EntryDefinitionList;
+using file_manager::util::EntryDefinitionListCallback;
+using file_manager::util::FileDefinition;
+using file_manager::util::FileDefinitionList;
+
 namespace extensions {
 namespace {
 
@@ -34,22 +60,30 @@ const char kDriveConnectionReasonNotReady[] = "not_ready";
 const char kDriveConnectionReasonNoNetwork[] = "no_network";
 const char kDriveConnectionReasonNoService[] = "no_service";
 
-// Copies properties from |entry_proto| to |properties|.
-void FillDriveEntryPropertiesValue(
-    const drive::ResourceEntry& entry_proto,
-    api::file_browser_private::DriveEntryProperties* properties) {
-  properties->shared_with_me.reset(new bool(entry_proto.shared_with_me()));
+// Copies properties from |entry_proto| to |properties|. |shared_with_me| is
+// given from the running profile.
+void FillEntryPropertiesValueForDrive(const drive::ResourceEntry& entry_proto,
+                                      bool shared_with_me,
+                                      EntryProperties* properties) {
+  properties->shared_with_me.reset(new bool(shared_with_me));
   properties->shared.reset(new bool(entry_proto.shared()));
 
+  const drive::PlatformFileInfoProto& file_info = entry_proto.file_info();
+  properties->file_size.reset(new double(file_info.size()));
+  properties->last_modified_time.reset(new double(
+      base::Time::FromInternalValue(file_info.last_modified()).ToJsTime()));
+
   if (!entry_proto.has_file_specific_info())
     return;
 
   const drive::FileSpecificInfo& file_specific_info =
       entry_proto.file_specific_info();
 
-  properties->thumbnail_url.reset(
-      new std::string("https://www.googledrive.com/thumb/" +
-          entry_proto.resource_id() + "?width=500&height=500"));
+  if (!entry_proto.resource_id().empty()) {
+    properties->thumbnail_url.reset(
+        new std::string("https://www.googledrive.com/thumb/" +
+                        entry_proto.resource_id() + "?width=500&height=500"));
+  }
   if (file_specific_info.has_image_width()) {
     properties->image_width.reset(
         new int(file_specific_info.image_width()));
@@ -66,137 +100,429 @@ void FillDriveEntryPropertiesValue(
       new bool(file_specific_info.is_hosted_document()));
   properties->content_mime_type.reset(
       new std::string(file_specific_info.content_mime_type()));
-}
 
-}  // namespace
+  properties->is_pinned.reset(
+      new bool(file_specific_info.cache_state().is_pinned()));
+  properties->is_present.reset(
+      new bool(file_specific_info.cache_state().is_present()));
+
+  if (file_specific_info.cache_state().is_present()) {
+    properties->is_available_offline.reset(new bool(true));
+  } else if (file_specific_info.is_hosted_document() &&
+             file_specific_info.has_document_extension()) {
+    const std::string file_extension = file_specific_info.document_extension();
+    // What's available offline? See the 'Web' column at:
+    // http://support.google.com/drive/answer/1628467
+    properties->is_available_offline.reset(
+        new bool(file_extension == ".gdoc" || file_extension == ".gdraw" ||
+                 file_extension == ".gsheet" || file_extension == ".gslides"));
+  } else {
+    properties->is_available_offline.reset(new bool(false));
+  }
 
-FileBrowserPrivateGetDriveEntryPropertiesFunction::
-    FileBrowserPrivateGetDriveEntryPropertiesFunction() {
+  properties->is_available_when_metered.reset(
+      new bool(file_specific_info.cache_state().is_present() ||
+               file_specific_info.is_hosted_document()));
 }
 
-FileBrowserPrivateGetDriveEntryPropertiesFunction::
-    ~FileBrowserPrivateGetDriveEntryPropertiesFunction() {
+// Creates entry definition list for (metadata) search result info list.
+template <class T>
+void ConvertSearchResultInfoListToEntryDefinitionList(
+    Profile* profile,
+    const std::string& extension_id,
+    const std::vector<T>& search_result_info_list,
+    const EntryDefinitionListCallback& callback) {
+  FileDefinitionList file_definition_list;
+
+  for (size_t i = 0; i < search_result_info_list.size(); ++i) {
+    FileDefinition file_definition;
+    file_definition.virtual_path =
+        file_manager::util::ConvertDrivePathToRelativeFileSystemPath(
+            profile, extension_id, search_result_info_list.at(i).path);
+    file_definition.is_directory = search_result_info_list.at(i).is_directory;
+    file_definition_list.push_back(file_definition);
+  }
+
+  file_manager::util::ConvertFileDefinitionListToEntryDefinitionList(
+      profile,
+      extension_id,
+      file_definition_list,  // Safe, since copied internally.
+      callback);
 }
 
-bool FileBrowserPrivateGetDriveEntryPropertiesFunction::RunImpl() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+class SingleEntryPropertiesGetterForDrive {
+ public:
+  typedef base::Callback<void(scoped_ptr<EntryProperties> properties,
+                              base::File::Error error)> ResultCallback;
 
-  using extensions::api::file_browser_private::GetDriveEntryProperties::Params;
-  const scoped_ptr<Params> params(Params::Create(*args_));
-  EXTENSION_FUNCTION_VALIDATE(params);
+  // Creates an instance and starts the process.
+  static void Start(const base::FilePath local_path,
+                    Profile* const profile,
+                    const ResultCallback& callback) {
+    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
-  const GURL file_url = GURL(params->file_url);
-  file_path_ =
-      drive::util::ExtractDrivePath(file_manager::util::GetLocalPathFromURL(
-          render_view_host(), GetProfile(), file_url));
+    SingleEntryPropertiesGetterForDrive* instance =
+        new SingleEntryPropertiesGetterForDrive(local_path, profile, callback);
+    instance->StartProcess();
 
-  properties_.reset(new extensions::api::file_browser_private::
-                    DriveEntryProperties);
+    // The instance will be destroyed by itself.
+  }
 
-  // Start getting the file info.
-  drive::FileSystemInterface* file_system =
-      drive::util::GetFileSystemByProfile(GetProfile());
-  if (!file_system) {
-    // |file_system| is NULL if Drive is disabled or not mounted.
-    CompleteGetFileProperties(drive::FILE_ERROR_FAILED);
-    return true;
+  virtual ~SingleEntryPropertiesGetterForDrive() {}
+
+ private:
+  SingleEntryPropertiesGetterForDrive(const base::FilePath local_path,
+                                      Profile* const profile,
+                                      const ResultCallback& callback)
+      : callback_(callback),
+        local_path_(local_path),
+        running_profile_(profile),
+        properties_(new EntryProperties),
+        file_owner_profile_(NULL),
+        weak_ptr_factory_(this) {
+    DCHECK(!callback_.is_null());
+    DCHECK(profile);
   }
 
-  file_system->GetResourceEntry(
-      file_path_,
-      base::Bind(&FileBrowserPrivateGetDriveEntryPropertiesFunction::
-                     OnGetFileInfo, this));
-  return true;
-}
+  void StartProcess() {
+    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
-void FileBrowserPrivateGetDriveEntryPropertiesFunction::OnGetFileInfo(
-    drive::FileError error,
-    scoped_ptr<drive::ResourceEntry> entry) {
-  DCHECK(properties_);
+    file_path_ = drive::util::ExtractDrivePath(local_path_);
+    file_owner_profile_ = drive::util::ExtractProfileFromPath(local_path_);
 
-  if (error != drive::FILE_ERROR_OK) {
-    CompleteGetFileProperties(error);
-    return;
+    if (!file_owner_profile_ ||
+        !g_browser_process->profile_manager()->IsValidProfile(
+            file_owner_profile_)) {
+      CompleteGetEntryProperties(drive::FILE_ERROR_FAILED);
+      return;
+    }
+
+    // Start getting the file info.
+    drive::FileSystemInterface* const file_system =
+        drive::util::GetFileSystemByProfile(file_owner_profile_);
+    if (!file_system) {
+      // |file_system| is NULL if Drive is disabled or not mounted.
+      CompleteGetEntryProperties(drive::FILE_ERROR_FAILED);
+      return;
+    }
+
+    file_system->GetResourceEntry(
+        file_path_,
+        base::Bind(&SingleEntryPropertiesGetterForDrive::OnGetFileInfo,
+                   weak_ptr_factory_.GetWeakPtr()));
   }
-  DCHECK(entry);
 
-  FillDriveEntryPropertiesValue(*entry, properties_.get());
+  void OnGetFileInfo(drive::FileError error,
+                     scoped_ptr<drive::ResourceEntry> entry) {
+    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
-  drive::FileSystemInterface* file_system =
-      drive::util::GetFileSystemByProfile(GetProfile());
-  drive::DriveAppRegistry* app_registry =
-      drive::util::GetDriveAppRegistryByProfile(GetProfile());
-  if (!file_system || !app_registry) {
-    // |file_system| or |app_registry| is NULL if Drive is disabled.
-    CompleteGetFileProperties(drive::FILE_ERROR_FAILED);
-    return;
+    if (error != drive::FILE_ERROR_OK) {
+      CompleteGetEntryProperties(error);
+      return;
+    }
+
+    DCHECK(entry);
+    owner_resource_entry_.swap(entry);
+
+    if (running_profile_->IsSameProfile(file_owner_profile_)) {
+      StartParseFileInfo(owner_resource_entry_->shared_with_me());
+      return;
+    }
+
+    // If the running profile does not own the file, obtain the shared_with_me
+    // flag from the running profile's value.
+    drive::FileSystemInterface* const file_system =
+        drive::util::GetFileSystemByProfile(running_profile_);
+    if (!file_system) {
+      CompleteGetEntryProperties(drive::FILE_ERROR_FAILED);
+      return;
+    }
+    file_system->GetPathFromResourceId(
+        owner_resource_entry_->resource_id(),
+        base::Bind(&SingleEntryPropertiesGetterForDrive::OnGetRunningPath,
+                   weak_ptr_factory_.GetWeakPtr()));
   }
 
-  // The properties meaningful for directories are already filled in
-  // FillDriveEntryPropertiesValue().
-  if (entry.get() && !entry->has_file_specific_info()) {
-    CompleteGetFileProperties(error);
-    return;
+  void OnGetRunningPath(drive::FileError error,
+                        const base::FilePath& file_path) {
+    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+    if (error != drive::FILE_ERROR_OK) {
+      // The running profile does not know the file.
+      StartParseFileInfo(false);
+      return;
+    }
+
+    drive::FileSystemInterface* const file_system =
+        drive::util::GetFileSystemByProfile(running_profile_);
+    if (!file_system) {
+      // The drive is disable for the running profile.
+      StartParseFileInfo(false);
+      return;
+    }
+
+    file_system->GetResourceEntry(
+        file_path,
+        base::Bind(&SingleEntryPropertiesGetterForDrive::OnGetShareInfo,
+                   weak_ptr_factory_.GetWeakPtr()));
   }
 
-  const drive::FileSpecificInfo& file_specific_info =
-      entry->file_specific_info();
-
-  // Get drive WebApps that can accept this file. We just need to extract the
-  // doc icon for the drive app, which is set as default.
-  std::vector<drive::DriveAppInfo> drive_apps;
-  app_registry->GetAppsForFile(file_path_.Extension(),
-                               file_specific_info.content_mime_type(),
-                               &drive_apps);
-  if (!drive_apps.empty()) {
-    std::string default_task_id =
-        file_manager::file_tasks::GetDefaultTaskIdFromPrefs(
-            *GetProfile()->GetPrefs(),
-            file_specific_info.content_mime_type(),
-            file_path_.Extension());
-    file_manager::file_tasks::TaskDescriptor default_task;
-    file_manager::file_tasks::ParseTaskID(default_task_id, &default_task);
-    DCHECK(default_task_id.empty() || !default_task.app_id.empty());
-    for (size_t i = 0; i < drive_apps.size(); ++i) {
-      const drive::DriveAppInfo& app_info = drive_apps[i];
-      if (default_task.app_id == app_info.app_id) {
-        // The drive app is set as default. Files.app should use the doc icon.
-        const GURL doc_icon =
-            drive::util::FindPreferredIcon(app_info.document_icons,
-                                           drive::util::kPreferredIconSize);
-        properties_->custom_icon_url.reset(new std::string(doc_icon.spec()));
+  void OnGetShareInfo(drive::FileError error,
+                      scoped_ptr<drive::ResourceEntry> entry) {
+    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+    if (error != drive::FILE_ERROR_OK) {
+      CompleteGetEntryProperties(error);
+      return;
+    }
+
+    DCHECK(entry.get());
+    StartParseFileInfo(entry->shared_with_me());
+  }
+
+  void StartParseFileInfo(bool shared_with_me) {
+    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+    FillEntryPropertiesValueForDrive(
+        *owner_resource_entry_, shared_with_me, properties_.get());
+
+    drive::FileSystemInterface* const file_system =
+        drive::util::GetFileSystemByProfile(file_owner_profile_);
+    drive::DriveAppRegistry* const app_registry =
+        drive::util::GetDriveAppRegistryByProfile(file_owner_profile_);
+    if (!file_system || !app_registry) {
+      // |file_system| or |app_registry| is NULL if Drive is disabled.
+      CompleteGetEntryProperties(drive::FILE_ERROR_FAILED);
+      return;
+    }
+
+    // The properties meaningful for directories are already filled in
+    // FillEntryPropertiesValueForDrive().
+    if (!owner_resource_entry_->has_file_specific_info()) {
+      CompleteGetEntryProperties(drive::FILE_ERROR_OK);
+      return;
+    }
+
+    const drive::FileSpecificInfo& file_specific_info =
+        owner_resource_entry_->file_specific_info();
+
+    // Get drive WebApps that can accept this file. We just need to extract the
+    // doc icon for the drive app, which is set as default.
+    std::vector<drive::DriveAppInfo> drive_apps;
+    app_registry->GetAppsForFile(file_path_.Extension(),
+                                 file_specific_info.content_mime_type(),
+                                 &drive_apps);
+    if (!drive_apps.empty()) {
+      std::string default_task_id =
+          file_manager::file_tasks::GetDefaultTaskIdFromPrefs(
+              *file_owner_profile_->GetPrefs(),
+              file_specific_info.content_mime_type(),
+              file_path_.Extension());
+      file_manager::file_tasks::TaskDescriptor default_task;
+      file_manager::file_tasks::ParseTaskID(default_task_id, &default_task);
+      DCHECK(default_task_id.empty() || !default_task.app_id.empty());
+      for (size_t i = 0; i < drive_apps.size(); ++i) {
+        const drive::DriveAppInfo& app_info = drive_apps[i];
+        if (default_task.app_id == app_info.app_id) {
+          // The drive app is set as default. Files.app should use the doc icon.
+          const GURL doc_icon = drive::util::FindPreferredIcon(
+              app_info.document_icons, drive::util::kPreferredIconSize);
+          properties_->custom_icon_url.reset(new std::string(doc_icon.spec()));
+        }
       }
     }
+
+    CompleteGetEntryProperties(drive::FILE_ERROR_OK);
+  }
+
+  void CompleteGetEntryProperties(drive::FileError error) {
+    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+    DCHECK(!callback_.is_null());
+
+    callback_.Run(properties_.Pass(), drive::FileErrorToBaseFileError(error));
+    BrowserThread::DeleteSoon(BrowserThread::UI, FROM_HERE, this);
+  }
+
+  // Given parameters.
+  const ResultCallback callback_;
+  const base::FilePath local_path_;
+  Profile* const running_profile_;
+
+  // Values used in the process.
+  scoped_ptr<EntryProperties> properties_;
+  Profile* file_owner_profile_;
+  base::FilePath file_path_;
+  scoped_ptr<drive::ResourceEntry> owner_resource_entry_;
+
+  base::WeakPtrFactory<SingleEntryPropertiesGetterForDrive> weak_ptr_factory_;
+};  // class SingleEntryPropertiesGetterForDrive
+
+class SingleEntryPropertiesGetterForFileSystemProvider {
+ public:
+  typedef base::Callback<void(scoped_ptr<EntryProperties> properties,
+                              base::File::Error error)> ResultCallback;
+
+  // Creates an instance and starts the process.
+  static void Start(const storage::FileSystemURL file_system_url,
+                    const ResultCallback& callback) {
+    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+    SingleEntryPropertiesGetterForFileSystemProvider* instance =
+        new SingleEntryPropertiesGetterForFileSystemProvider(file_system_url,
+                                                             callback);
+    instance->StartProcess();
+
+    // The instance will be destroyed by itself.
+  }
+
+  virtual ~SingleEntryPropertiesGetterForFileSystemProvider() {}
+
+ private:
+  SingleEntryPropertiesGetterForFileSystemProvider(
+      const storage::FileSystemURL& file_system_url,
+      const ResultCallback& callback)
+      : callback_(callback),
+        file_system_url_(file_system_url),
+        properties_(new EntryProperties),
+        weak_ptr_factory_(this) {
+    DCHECK(!callback_.is_null());
+  }
+
+  void StartProcess() {
+    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+    FileSystemURLParser parser(file_system_url_);
+    if (!parser.Parse()) {
+      CompleteGetEntryProperties(base::File::FILE_ERROR_NOT_FOUND);
+      return;
+    }
+
+    parser.file_system()->GetMetadata(
+        parser.file_path(),
+        ProvidedFileSystemInterface::METADATA_FIELD_THUMBNAIL,
+        base::Bind(&SingleEntryPropertiesGetterForFileSystemProvider::
+                       OnGetMetadataCompleted,
+                   weak_ptr_factory_.GetWeakPtr()));
+  }
+
+  void OnGetMetadataCompleted(scoped_ptr<EntryMetadata> metadata,
+                              base::File::Error result) {
+    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+    if (result != base::File::FILE_OK) {
+      CompleteGetEntryProperties(result);
+      return;
+    }
+
+    properties_->file_size.reset(new double(metadata->size));
+    properties_->last_modified_time.reset(
+        new double(metadata->modification_time.ToJsTime()));
+
+    if (!metadata->thumbnail.empty())
+      properties_->thumbnail_url.reset(new std::string(metadata->thumbnail));
+
+    CompleteGetEntryProperties(base::File::FILE_OK);
+  }
+
+  void CompleteGetEntryProperties(base::File::Error result) {
+    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+    DCHECK(!callback_.is_null());
+
+    callback_.Run(properties_.Pass(), result);
+    BrowserThread::DeleteSoon(BrowserThread::UI, FROM_HERE, this);
   }
 
-  file_system->GetCacheEntry(
-      file_path_,
-      base::Bind(&FileBrowserPrivateGetDriveEntryPropertiesFunction::
-                     CacheStateReceived, this));
+  // Given parameters.
+  const ResultCallback callback_;
+  const storage::FileSystemURL file_system_url_;
+
+  // Values used in the process.
+  scoped_ptr<EntryProperties> properties_;
+
+  base::WeakPtrFactory<SingleEntryPropertiesGetterForFileSystemProvider>
+      weak_ptr_factory_;
+};  // class SingleEntryPropertiesGetterForDrive
+
+}  // namespace
+
+FileManagerPrivateGetEntryPropertiesFunction::
+    FileManagerPrivateGetEntryPropertiesFunction()
+    : processed_count_(0) {
+}
+
+FileManagerPrivateGetEntryPropertiesFunction::
+    ~FileManagerPrivateGetEntryPropertiesFunction() {
 }
 
-void FileBrowserPrivateGetDriveEntryPropertiesFunction::CacheStateReceived(
-    bool /* success */,
-    const drive::FileCacheEntry& cache_entry) {
-  // In case of an error (i.e. success is false), cache_entry.is_*() all
-  // returns false.
-  properties_->is_pinned.reset(new bool(cache_entry.is_pinned()));
-  properties_->is_present.reset(new bool(cache_entry.is_present()));
+bool FileManagerPrivateGetEntryPropertiesFunction::RunAsync() {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+  using api::file_manager_private::GetEntryProperties::Params;
+  const scoped_ptr<Params> params(Params::Create(*args_));
+  EXTENSION_FUNCTION_VALIDATE(params);
+
+  scoped_refptr<storage::FileSystemContext> file_system_context =
+      file_manager::util::GetFileSystemContextForRenderViewHost(
+          GetProfile(), render_view_host());
+
+  properties_list_.resize(params->file_urls.size());
+  for (size_t i = 0; i < params->file_urls.size(); i++) {
+    const GURL url = GURL(params->file_urls[i]);
+    const storage::FileSystemURL file_system_url =
+        file_system_context->CrackURL(url);
+    switch (file_system_url.type()) {
+      case storage::kFileSystemTypeDrive:
+        SingleEntryPropertiesGetterForDrive::Start(
+            file_system_url.path(), GetProfile(),
+            base::Bind(&FileManagerPrivateGetEntryPropertiesFunction::
+                           CompleteGetEntryProperties,
+                       this, i, file_system_url));
+        break;
+      case storage::kFileSystemTypeProvided:
+        SingleEntryPropertiesGetterForFileSystemProvider::Start(
+            file_system_url,
+            base::Bind(&FileManagerPrivateGetEntryPropertiesFunction::
+                           CompleteGetEntryProperties,
+                       this, i, file_system_url));
+        break;
+      default:
+        LOG(ERROR) << "Not supported file system type.";
+        CompleteGetEntryProperties(i, file_system_url,
+                                   make_scoped_ptr(new EntryProperties),
+                                   base::File::FILE_ERROR_INVALID_OPERATION);
+    }
+  }
 
-  CompleteGetFileProperties(drive::FILE_ERROR_OK);
+  return true;
 }
 
-void FileBrowserPrivateGetDriveEntryPropertiesFunction::
-    CompleteGetFileProperties(drive::FileError error) {
-  results_ = extensions::api::file_browser_private::GetDriveEntryProperties::
-      Results::Create(*properties_);
+void FileManagerPrivateGetEntryPropertiesFunction::CompleteGetEntryProperties(
+    size_t index,
+    const storage::FileSystemURL& url,
+    scoped_ptr<EntryProperties> properties,
+    base::File::Error error) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK(0 <= processed_count_ && processed_count_ < properties_list_.size());
+
+  properties_list_[index] = make_linked_ptr(properties.release());
+  if (error == base::File::FILE_OK) {
+    properties_list_[index]->external_file_url.reset(
+        new std::string(chromeos::FileSystemURLToExternalFileURL(url).spec()));
+  }
+
+  processed_count_++;
+  if (processed_count_ < properties_list_.size())
+    return;
+
+  results_ = extensions::api::file_manager_private::GetEntryProperties::
+      Results::Create(properties_list_);
   SendResponse(true);
 }
 
-bool FileBrowserPrivatePinDriveFileFunction::RunImpl() {
+bool FileManagerPrivatePinDriveFileFunction::RunAsync() {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
-  using extensions::api::file_browser_private::PinDriveFile::Params;
+  using extensions::api::file_manager_private::PinDriveFile::Params;
   const scoped_ptr<Params> params(Params::Create(*args_));
   EXTENSION_FUNCTION_VALIDATE(params);
 
@@ -210,110 +536,30 @@ bool FileBrowserPrivatePinDriveFileFunction::RunImpl() {
           render_view_host(), GetProfile(), GURL(params->file_url)));
   if (params->pin) {
     file_system->Pin(drive_path,
-                     base::Bind(&FileBrowserPrivatePinDriveFileFunction::
+                     base::Bind(&FileManagerPrivatePinDriveFileFunction::
                                     OnPinStateSet, this));
   } else {
     file_system->Unpin(drive_path,
-                       base::Bind(&FileBrowserPrivatePinDriveFileFunction::
+                       base::Bind(&FileManagerPrivatePinDriveFileFunction::
                                       OnPinStateSet, this));
   }
   return true;
 }
 
-void FileBrowserPrivatePinDriveFileFunction::
+void FileManagerPrivatePinDriveFileFunction::
     OnPinStateSet(drive::FileError error) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
   if (error == drive::FILE_ERROR_OK) {
     SendResponse(true);
   } else {
-    error_ = drive::FileErrorToString(error);
+    SetError(drive::FileErrorToString(error));
     SendResponse(false);
   }
 }
 
-FileBrowserPrivateGetDriveFilesFunction::
-    FileBrowserPrivateGetDriveFilesFunction() {
-}
-
-FileBrowserPrivateGetDriveFilesFunction::
-    ~FileBrowserPrivateGetDriveFilesFunction() {
-}
-
-bool FileBrowserPrivateGetDriveFilesFunction::RunImpl() {
-  using extensions::api::file_browser_private::GetDriveFiles::Params;
-  const scoped_ptr<Params> params(Params::Create(*args_));
-  EXTENSION_FUNCTION_VALIDATE(params);
-
-  // Convert the list of strings to a list of GURLs.
-  for (size_t i = 0; i < params->file_urls.size(); ++i) {
-    const base::FilePath path = file_manager::util::GetLocalPathFromURL(
-        render_view_host(), GetProfile(), GURL(params->file_urls[i]));
-    DCHECK(drive::util::IsUnderDriveMountPoint(path));
-    base::FilePath drive_path = drive::util::ExtractDrivePath(path);
-    remaining_drive_paths_.push(drive_path);
-  }
-
-  GetFileOrSendResponse();
-  return true;
-}
-
-void FileBrowserPrivateGetDriveFilesFunction::GetFileOrSendResponse() {
-  // Send the response if all files are obtained.
-  if (remaining_drive_paths_.empty()) {
-    results_ = extensions::api::file_browser_private::
-        GetDriveFiles::Results::Create(local_paths_);
-    SendResponse(true);
-    return;
-  }
-
-  // Get the file on the top of the queue.
-  base::FilePath drive_path = remaining_drive_paths_.front();
-
-  drive::FileSystemInterface* file_system =
-      drive::util::GetFileSystemByProfile(GetProfile());
-  if (!file_system) {
-    // |file_system| is NULL if Drive is disabled or not mounted.
-    OnFileReady(drive::FILE_ERROR_FAILED, drive_path,
-                scoped_ptr<drive::ResourceEntry>());
-    return;
-  }
-
-  file_system->GetFile(
-      drive_path,
-      base::Bind(&FileBrowserPrivateGetDriveFilesFunction::OnFileReady, this));
-}
-
-
-void FileBrowserPrivateGetDriveFilesFunction::OnFileReady(
-    drive::FileError error,
-    const base::FilePath& local_path,
-    scoped_ptr<drive::ResourceEntry> entry) {
-  base::FilePath drive_path = remaining_drive_paths_.front();
-
-  if (error == drive::FILE_ERROR_OK) {
-    local_paths_.push_back(local_path.AsUTF8Unsafe());
-    DVLOG(1) << "Got " << drive_path.value() << " as " << local_path.value();
-
-    // TODO(benchan): If the file is a hosted document, a temporary JSON file
-    // is created to represent the document. The JSON file is not cached and
-    // should be deleted after use. We need to somehow communicate with
-    // file_manager.js to manage the lifetime of the temporary file.
-    // See crosbug.com/28058.
-  } else {
-    local_paths_.push_back("");
-    DVLOG(1) << "Failed to get " << drive_path.value()
-             << " with error code: " << error;
-  }
-
-  remaining_drive_paths_.pop();
-
-  // Start getting the next file.
-  GetFileOrSendResponse();
-}
-
-bool FileBrowserPrivateCancelFileTransfersFunction::RunImpl() {
-  using extensions::api::file_browser_private::CancelFileTransfers::Params;
+bool FileManagerPrivateCancelFileTransfersFunction::RunAsync() {
+  using extensions::api::file_manager_private::CancelFileTransfers::Params;
   const scoped_ptr<Params> params(Params::Create(*args_));
   EXTENSION_FUNCTION_VALIDATE(params);
 
@@ -322,52 +568,49 @@ bool FileBrowserPrivateCancelFileTransfersFunction::RunImpl() {
   if (!integration_service || !integration_service->IsMounted())
     return false;
 
-  // Create the mapping from file path to job ID.
   drive::JobListInterface* job_list = integration_service->job_list();
   DCHECK(job_list);
   std::vector<drive::JobInfo> jobs = job_list->GetJobInfoList();
 
-  typedef std::map<base::FilePath, std::vector<drive::JobID> > PathToIdMap;
-  PathToIdMap path_to_id_map;
-  for (size_t i = 0; i < jobs.size(); ++i) {
-    if (drive::IsActiveFileTransferJobInfo(jobs[i]))
-      path_to_id_map[jobs[i].file_path].push_back(jobs[i].job_id);
-  }
-
-  // Cancel by Job ID.
-  std::vector<linked_ptr<api::file_browser_private::
-                         FileTransferCancelStatus> > responses;
-  for (size_t i = 0; i < params->file_urls.size(); ++i) {
-    base::FilePath file_path = file_manager::util::GetLocalPathFromURL(
-        render_view_host(), GetProfile(), GURL(params->file_urls[i]));
-    if (file_path.empty())
-      continue;
-
-    DCHECK(drive::util::IsUnderDriveMountPoint(file_path));
-    file_path = drive::util::ExtractDrivePath(file_path);
-
-    // Cancel all the jobs for the file.
-    PathToIdMap::iterator it = path_to_id_map.find(file_path);
-    if (it != path_to_id_map.end()) {
-      for (size_t i = 0; i < it->second.size(); ++i)
-        job_list->CancelJob(it->second[i]);
+  // If file_urls are empty, cancel all jobs.
+  if (!params->file_urls.get()) {
+    for (size_t i = 0; i < jobs.size(); ++i) {
+      if (drive::IsActiveFileTransferJobInfo(jobs[i]))
+        job_list->CancelJob(jobs[i].job_id);
+    }
+  } else {
+    // Create the mapping from file path to job ID.
+    std::vector<std::string> file_urls(*params->file_urls.get());
+    typedef std::map<base::FilePath, std::vector<drive::JobID> > PathToIdMap;
+    PathToIdMap path_to_id_map;
+    for (size_t i = 0; i < jobs.size(); ++i) {
+      if (drive::IsActiveFileTransferJobInfo(jobs[i]))
+        path_to_id_map[jobs[i].file_path].push_back(jobs[i].job_id);
+    }
+
+    for (size_t i = 0; i < file_urls.size(); ++i) {
+      base::FilePath file_path = file_manager::util::GetLocalPathFromURL(
+          render_view_host(), GetProfile(), GURL(file_urls[i]));
+      if (file_path.empty())
+        continue;
+
+      file_path = drive::util::ExtractDrivePath(file_path);
+      DCHECK(file_path.empty());
+
+      // Cancel all the jobs for the file.
+      PathToIdMap::iterator it = path_to_id_map.find(file_path);
+      if (it != path_to_id_map.end()) {
+        for (size_t i = 0; i < it->second.size(); ++i)
+          job_list->CancelJob(it->second[i]);
+      }
     }
-    linked_ptr<api::file_browser_private::FileTransferCancelStatus> result(
-        new api::file_browser_private::FileTransferCancelStatus);
-    result->canceled = it != path_to_id_map.end();
-    // TODO(kinaba): simplify cancelFileTransfer() to take single URL each time,
-    // and eliminate this field; it is just returning a copy of the argument.
-    result->file_url = params->file_urls[i];
-    responses.push_back(result);
-  }
-  results_ = api::file_browser_private::CancelFileTransfers::Results::Create(
-      responses);
+  }
   SendResponse(true);
   return true;
 }
 
-bool FileBrowserPrivateSearchDriveFunction::RunImpl() {
-  using extensions::api::file_browser_private::SearchDrive::Params;
+bool FileManagerPrivateSearchDriveFunction::RunAsync() {
+  using extensions::api::file_manager_private::SearchDrive::Params;
   const scoped_ptr<Params> params(Params::Create(*args_));
   EXTENSION_FUNCTION_VALIDATE(params);
 
@@ -380,32 +623,50 @@ bool FileBrowserPrivateSearchDriveFunction::RunImpl() {
 
   file_system->Search(
       params->search_params.query, GURL(params->search_params.next_feed),
-      base::Bind(&FileBrowserPrivateSearchDriveFunction::OnSearch, this));
+      base::Bind(&FileManagerPrivateSearchDriveFunction::OnSearch, this));
   return true;
 }
 
-void FileBrowserPrivateSearchDriveFunction::OnSearch(
+void FileManagerPrivateSearchDriveFunction::OnSearch(
     drive::FileError error,
     const GURL& next_link,
-    scoped_ptr<std::vector<drive::SearchResultInfo> > results) {
+    scoped_ptr<SearchResultInfoList> results) {
   if (error != drive::FILE_ERROR_OK) {
     SendResponse(false);
     return;
   }
 
+  // Outlives the following conversion, since the pointer is bound to the
+  // callback.
   DCHECK(results.get());
+  const SearchResultInfoList& results_ref = *results.get();
+
+  ConvertSearchResultInfoListToEntryDefinitionList(
+      GetProfile(),
+      extension_->id(),
+      results_ref,
+      base::Bind(&FileManagerPrivateSearchDriveFunction::OnEntryDefinitionList,
+                 this,
+                 next_link,
+                 base::Passed(&results)));
+}
 
+void FileManagerPrivateSearchDriveFunction::OnEntryDefinitionList(
+    const GURL& next_link,
+    scoped_ptr<SearchResultInfoList> search_result_info_list,
+    scoped_ptr<EntryDefinitionList> entry_definition_list) {
+  DCHECK_EQ(search_result_info_list->size(), entry_definition_list->size());
   base::ListValue* entries = new base::ListValue();
 
   // Convert Drive files to something File API stack can understand.
-  fileapi::FileSystemInfo info =
-      fileapi::GetFileSystemInfoForChromeOS(source_url_.GetOrigin());
-  for (size_t i = 0; i < results->size(); ++i) {
+  for (EntryDefinitionList::const_iterator it = entry_definition_list->begin();
+       it != entry_definition_list->end();
+       ++it) {
     base::DictionaryValue* entry = new base::DictionaryValue();
-    entry->SetString("fileSystemName", info.name);
-    entry->SetString("fileSystemRoot", info.root_url.spec());
-    entry->SetString("fileFullPath", "/" + results->at(i).path.value());
-    entry->SetBoolean("fileIsDirectory", results->at(i).is_directory);
+    entry->SetString("fileSystemName", it->file_system_name);
+    entry->SetString("fileSystemRoot", it->file_system_root_url);
+    entry->SetString("fileFullPath", "/" + it->full_path.AsUTF8Unsafe());
+    entry->SetBoolean("fileIsDirectory", it->is_directory);
     entries->Append(entry);
   }
 
@@ -417,18 +678,21 @@ void FileBrowserPrivateSearchDriveFunction::OnSearch(
   SendResponse(true);
 }
 
-bool FileBrowserPrivateSearchDriveMetadataFunction::RunImpl() {
-  using api::file_browser_private::SearchDriveMetadata::Params;
+bool FileManagerPrivateSearchDriveMetadataFunction::RunAsync() {
+  using api::file_manager_private::SearchDriveMetadata::Params;
   const scoped_ptr<Params> params(Params::Create(*args_));
   EXTENSION_FUNCTION_VALIDATE(params);
 
-  drive::util::Log(logging::LOG_INFO,
-                   "%s[%d] called. (types: '%s', maxResults: '%d')",
-                   name().c_str(),
-                   request_id(),
-                   api::file_browser_private::ToString(
-                       params->search_params.types).c_str(),
-                   params->search_params.max_results);
+  drive::EventLogger* logger = file_manager::util::GetLogger(GetProfile());
+  if (logger) {
+    logger->Log(logging::LOG_INFO,
+                "%s[%d] called. (types: '%s', maxResults: '%d')",
+                name().c_str(),
+                request_id(),
+                api::file_manager_private::ToString(
+                    params->search_params.types).c_str(),
+                params->search_params.max_results);
+  }
   set_log_on_completion(true);
 
   drive::FileSystemInterface* const file_system =
@@ -440,19 +704,19 @@ bool FileBrowserPrivateSearchDriveMetadataFunction::RunImpl() {
 
   int options = -1;
   switch (params->search_params.types) {
-    case api::file_browser_private::SEARCH_TYPE_EXCLUDE_DIRECTORIES:
+    case api::file_manager_private::SEARCH_TYPE_EXCLUDE_DIRECTORIES:
       options = drive::SEARCH_METADATA_EXCLUDE_DIRECTORIES;
       break;
-    case api::file_browser_private::SEARCH_TYPE_SHARED_WITH_ME:
+    case api::file_manager_private::SEARCH_TYPE_SHARED_WITH_ME:
       options = drive::SEARCH_METADATA_SHARED_WITH_ME;
       break;
-    case api::file_browser_private::SEARCH_TYPE_OFFLINE:
+    case api::file_manager_private::SEARCH_TYPE_OFFLINE:
       options = drive::SEARCH_METADATA_OFFLINE;
       break;
-    case api::file_browser_private::SEARCH_TYPE_ALL:
+    case api::file_manager_private::SEARCH_TYPE_ALL:
       options = drive::SEARCH_METADATA_ALL;
       break;
-    case api::file_browser_private::SEARCH_TYPE_NONE:
+    case api::file_manager_private::SEARCH_TYPE_NONE:
       break;
   }
   DCHECK_NE(options, -1);
@@ -461,12 +725,12 @@ bool FileBrowserPrivateSearchDriveMetadataFunction::RunImpl() {
       params->search_params.query,
       options,
       params->search_params.max_results,
-      base::Bind(&FileBrowserPrivateSearchDriveMetadataFunction::
+      base::Bind(&FileManagerPrivateSearchDriveMetadataFunction::
                      OnSearchMetadata, this));
   return true;
 }
 
-void FileBrowserPrivateSearchDriveMetadataFunction::OnSearchMetadata(
+void FileManagerPrivateSearchDriveMetadataFunction::OnSearchMetadata(
     drive::FileError error,
     scoped_ptr<drive::MetadataSearchResultVector> results) {
   if (error != drive::FILE_ERROR_OK) {
@@ -474,30 +738,50 @@ void FileBrowserPrivateSearchDriveMetadataFunction::OnSearchMetadata(
     return;
   }
 
+  // Outlives the following conversion, since the pointer is bound to the
+  // callback.
   DCHECK(results.get());
+  const drive::MetadataSearchResultVector& results_ref = *results.get();
+
+  ConvertSearchResultInfoListToEntryDefinitionList(
+      GetProfile(),
+      extension_->id(),
+      results_ref,
+      base::Bind(
+          &FileManagerPrivateSearchDriveMetadataFunction::OnEntryDefinitionList,
+          this,
+          base::Passed(&results)));
+}
 
+void FileManagerPrivateSearchDriveMetadataFunction::OnEntryDefinitionList(
+    scoped_ptr<drive::MetadataSearchResultVector> search_result_info_list,
+    scoped_ptr<EntryDefinitionList> entry_definition_list) {
+  DCHECK_EQ(search_result_info_list->size(), entry_definition_list->size());
   base::ListValue* results_list = new base::ListValue();
 
   // Convert Drive files to something File API stack can understand.  See
   // file_browser_handler_custom_bindings.cc and
-  // file_browser_private_custom_bindings.js for how this is magically
+  // file_manager_private_custom_bindings.js for how this is magically
   // converted to a FileEntry.
-  fileapi::FileSystemInfo info =
-      fileapi::GetFileSystemInfoForChromeOS(source_url_.GetOrigin());
-  for (size_t i = 0; i < results->size(); ++i) {
+  for (size_t i = 0; i < entry_definition_list->size(); ++i) {
     base::DictionaryValue* result_dict = new base::DictionaryValue();
 
     // FileEntry fields.
     base::DictionaryValue* entry = new base::DictionaryValue();
-    entry->SetString("fileSystemName", info.name);
-    entry->SetString("fileSystemRoot", info.root_url.spec());
-    entry->SetString("fileFullPath", "/" + results->at(i).path.value());
+    entry->SetString(
+        "fileSystemName", entry_definition_list->at(i).file_system_name);
+    entry->SetString(
+        "fileSystemRoot", entry_definition_list->at(i).file_system_root_url);
+    entry->SetString(
+        "fileFullPath",
+        "/" + entry_definition_list->at(i).full_path.AsUTF8Unsafe());
     entry->SetBoolean("fileIsDirectory",
-                      results->at(i).entry.file_info().is_directory());
+                      entry_definition_list->at(i).is_directory);
 
     result_dict->Set("entry", entry);
-    result_dict->SetString("highlightedBaseName",
-                           results->at(i).highlighted_base_name);
+    result_dict->SetString(
+        "highlightedBaseName",
+        search_result_info_list->at(i).highlighted_base_name);
     results_list->Append(result_dict);
   }
 
@@ -505,8 +789,8 @@ void FileBrowserPrivateSearchDriveMetadataFunction::OnSearchMetadata(
   SendResponse(true);
 }
 
-bool FileBrowserPrivateGetDriveConnectionStateFunction::RunImpl() {
-  api::file_browser_private::DriveConnectionState result;
+bool FileManagerPrivateGetDriveConnectionStateFunction::RunSync() {
+  api::file_manager_private::DriveConnectionState result;
 
   switch (drive::util::GetDriveConnectionStatus(GetProfile())) {
     case drive::util::DRIVE_DISCONNECTED_NOSERVICE:
@@ -529,15 +813,21 @@ bool FileBrowserPrivateGetDriveConnectionStateFunction::RunImpl() {
       break;
   }
 
-  results_ = api::file_browser_private::GetDriveConnectionState::Results::
+  result.has_cellular_network_access =
+      chromeos::NetworkHandler::Get()
+          ->network_state_handler()
+          ->FirstNetworkByType(chromeos::NetworkTypePattern::Mobile());
+  results_ = api::file_manager_private::GetDriveConnectionState::Results::
       Create(result);
 
-  drive::util::Log(logging::LOG_INFO, "%s succeeded.", name().c_str());
+  drive::EventLogger* logger = file_manager::util::GetLogger(GetProfile());
+  if (logger)
+    logger->Log(logging::LOG_INFO, "%s succeeded.", name().c_str());
   return true;
 }
 
-bool FileBrowserPrivateRequestAccessTokenFunction::RunImpl() {
-  using extensions::api::file_browser_private::RequestAccessToken::Params;
+bool FileManagerPrivateRequestAccessTokenFunction::RunAsync() {
+  using extensions::api::file_manager_private::RequestAccessToken::Params;
   const scoped_ptr<Params> params(Params::Create(*args_));
   EXTENSION_FUNCTION_VALIDATE(params);
 
@@ -558,20 +848,20 @@ bool FileBrowserPrivateRequestAccessTokenFunction::RunImpl() {
   // Retrieve the cached auth token (if available), otherwise the AuthService
   // instance will try to refetch it.
   drive_service->RequestAccessToken(
-      base::Bind(&FileBrowserPrivateRequestAccessTokenFunction::
+      base::Bind(&FileManagerPrivateRequestAccessTokenFunction::
                       OnAccessTokenFetched, this));
   return true;
 }
 
-void FileBrowserPrivateRequestAccessTokenFunction::OnAccessTokenFetched(
+void FileManagerPrivateRequestAccessTokenFunction::OnAccessTokenFetched(
     google_apis::GDataErrorCode code,
     const std::string& access_token) {
   SetResult(new base::StringValue(access_token));
   SendResponse(true);
 }
 
-bool FileBrowserPrivateGetShareUrlFunction::RunImpl() {
-  using extensions::api::file_browser_private::GetShareUrl::Params;
+bool FileManagerPrivateGetShareUrlFunction::RunAsync() {
+  using extensions::api::file_manager_private::GetShareUrl::Params;
   const scoped_ptr<Params> params(Params::Create(*args_));
   EXTENSION_FUNCTION_VALIDATE(params);
 
@@ -590,16 +880,16 @@ bool FileBrowserPrivateGetShareUrlFunction::RunImpl() {
 
   file_system->GetShareUrl(
       drive_path,
-      file_manager::util::GetFileManagerBaseUrl(),  // embed origin
-      base::Bind(&FileBrowserPrivateGetShareUrlFunction::OnGetShareUrl, this));
+      GURL("chrome-extension://" + extension_id()),  // embed origin
+      base::Bind(&FileManagerPrivateGetShareUrlFunction::OnGetShareUrl, this));
   return true;
 }
 
-void FileBrowserPrivateGetShareUrlFunction::OnGetShareUrl(
+void FileManagerPrivateGetShareUrlFunction::OnGetShareUrl(
     drive::FileError error,
     const GURL& share_url) {
   if (error != drive::FILE_ERROR_OK) {
-    error_ = "Share Url for this item is not available.";
+    SetError("Share Url for this item is not available.");
     SendResponse(false);
     return;
   }
@@ -608,4 +898,147 @@ void FileBrowserPrivateGetShareUrlFunction::OnGetShareUrl(
   SendResponse(true);
 }
 
+bool FileManagerPrivateRequestDriveShareFunction::RunAsync() {
+  using extensions::api::file_manager_private::RequestDriveShare::Params;
+  const scoped_ptr<Params> params(Params::Create(*args_));
+  EXTENSION_FUNCTION_VALIDATE(params);
+
+  const base::FilePath path = file_manager::util::GetLocalPathFromURL(
+      render_view_host(), GetProfile(), GURL(params->url));
+  const base::FilePath drive_path = drive::util::ExtractDrivePath(path);
+  Profile* const owner_profile = drive::util::ExtractProfileFromPath(path);
+
+  if (!owner_profile)
+    return false;
+
+  drive::FileSystemInterface* const owner_file_system =
+      drive::util::GetFileSystemByProfile(owner_profile);
+  if (!owner_file_system)
+    return false;
+
+  const user_manager::User* const user =
+      chromeos::ProfileHelper::Get()->GetUserByProfile(GetProfile());
+  if (!user || !user->is_logged_in())
+    return false;
+
+  google_apis::drive::PermissionRole role =
+      google_apis::drive::PERMISSION_ROLE_READER;
+  switch (params->share_type) {
+    case api::file_manager_private::DRIVE_SHARE_TYPE_NONE:
+      NOTREACHED();
+      return false;
+    case api::file_manager_private::DRIVE_SHARE_TYPE_CAN_EDIT:
+      role = google_apis::drive::PERMISSION_ROLE_WRITER;
+      break;
+    case api::file_manager_private::DRIVE_SHARE_TYPE_CAN_COMMENT:
+      role = google_apis::drive::PERMISSION_ROLE_COMMENTER;
+      break;
+    case api::file_manager_private::DRIVE_SHARE_TYPE_CAN_VIEW:
+      role = google_apis::drive::PERMISSION_ROLE_READER;
+      break;
+  }
+
+  // Share |drive_path| in |owner_file_system| to |user->email()|.
+  owner_file_system->AddPermission(
+      drive_path,
+      user->email(),
+      role,
+      base::Bind(&FileManagerPrivateRequestDriveShareFunction::OnAddPermission,
+                 this));
+  return true;
+}
+
+void FileManagerPrivateRequestDriveShareFunction::OnAddPermission(
+    drive::FileError error) {
+  SendResponse(error == drive::FILE_ERROR_OK);
+}
+
+FileManagerPrivateGetDownloadUrlFunction::
+    FileManagerPrivateGetDownloadUrlFunction() {
+}
+
+FileManagerPrivateGetDownloadUrlFunction::
+    ~FileManagerPrivateGetDownloadUrlFunction() {
+}
+
+bool FileManagerPrivateGetDownloadUrlFunction::RunAsync() {
+  using extensions::api::file_manager_private::GetShareUrl::Params;
+  const scoped_ptr<Params> params(Params::Create(*args_));
+  EXTENSION_FUNCTION_VALIDATE(params);
+
+  // Start getting the file info.
+  drive::FileSystemInterface* const file_system =
+      drive::util::GetFileSystemByProfile(GetProfile());
+  if (!file_system) {
+    // |file_system| is NULL if Drive is disabled or not mounted.
+    SetError("Drive is disabled or not mounted.");
+    SetResult(new base::StringValue(""));  // Intentionally returns a blank.
+    return false;
+  }
+
+  const base::FilePath path = file_manager::util::GetLocalPathFromURL(
+      render_view_host(), GetProfile(), GURL(params->url));
+  if (!drive::util::IsUnderDriveMountPoint(path)) {
+    SetError("The given file is not in Drive.");
+    SetResult(new base::StringValue(""));  // Intentionally returns a blank.
+    return false;
+  }
+  base::FilePath file_path = drive::util::ExtractDrivePath(path);
+
+  file_system->GetResourceEntry(
+      file_path,
+      base::Bind(&FileManagerPrivateGetDownloadUrlFunction::OnGetResourceEntry,
+                 this));
+  return true;
+}
+
+void FileManagerPrivateGetDownloadUrlFunction::OnGetResourceEntry(
+    drive::FileError error,
+    scoped_ptr<drive::ResourceEntry> entry) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+  if (error != drive::FILE_ERROR_OK) {
+    SetError("Download Url for this item is not available.");
+    SetResult(new base::StringValue(""));  // Intentionally returns a blank.
+    SendResponse(false);
+    return;
+  }
+
+  download_url_ =
+      google_apis::DriveApiUrlGenerator::kBaseDownloadUrlForProduction +
+      entry->resource_id();
+
+  ProfileOAuth2TokenService* oauth2_token_service =
+      ProfileOAuth2TokenServiceFactory::GetForProfile(GetProfile());
+  SigninManagerBase* signin_manager =
+      SigninManagerFactory::GetForProfile(GetProfile());
+  const std::string& account_id = signin_manager->GetAuthenticatedAccountId();
+  std::vector<std::string> scopes;
+  scopes.push_back("https://www.googleapis.com/auth/drive.readonly");
+
+  auth_service_.reset(
+      new google_apis::AuthService(oauth2_token_service,
+                                   account_id,
+                                   GetProfile()->GetRequestContext(),
+                                   scopes));
+  auth_service_->StartAuthentication(base::Bind(
+      &FileManagerPrivateGetDownloadUrlFunction::OnTokenFetched, this));
+}
+
+void FileManagerPrivateGetDownloadUrlFunction::OnTokenFetched(
+    google_apis::GDataErrorCode code,
+    const std::string& access_token) {
+  if (code != google_apis::HTTP_SUCCESS) {
+    SetError("Not able to fetch the token.");
+    SetResult(new base::StringValue(""));  // Intentionally returns a blank.
+    SendResponse(false);
+    return;
+  }
+
+  const std::string url = download_url_ + "?access_token=" + access_token;
+  SetResult(new base::StringValue(url));
+
+  SendResponse(true);
+}
+
 }  // namespace extensions