Home | History | Annotate | Download | only in file_manager
      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_util.h"
      6 
      7 #include "base/files/file_path.h"
      8 #include "chrome/browser/chromeos/drive/drive.pb.h"
      9 #include "chrome/browser/chromeos/drive/drive_integration_service.h"
     10 #include "chrome/browser/chromeos/drive/file_errors.h"
     11 #include "chrome/browser/chromeos/drive/file_system_util.h"
     12 #include "chrome/browser/chromeos/extensions/file_manager/fileapi_util.h"
     13 #include "chrome/browser/chromeos/fileapi/file_system_backend.h"
     14 #include "chrome/browser/extensions/extension_function_dispatcher.h"
     15 #include "chrome/browser/extensions/extension_tab_util.h"
     16 #include "chrome/browser/profiles/profile.h"
     17 #include "content/public/browser/browser_context.h"
     18 #include "content/public/browser/browser_thread.h"
     19 #include "content/public/browser/render_view_host.h"
     20 #include "content/public/browser/storage_partition.h"
     21 #include "content/public/browser/web_contents.h"
     22 #include "ui/shell_dialogs/selected_file_info.h"
     23 #include "webkit/browser/fileapi/file_system_context.h"
     24 #include "webkit/browser/fileapi/file_system_url.h"
     25 
     26 using content::BrowserThread;
     27 using google_apis::InstalledApp;
     28 
     29 namespace file_manager {
     30 namespace util {
     31 namespace {
     32 
     33 // The struct is used for GetSelectedFileInfo().
     34 struct GetSelectedFileInfoParams {
     35   GetSelectedFileInfoLocalPathOption local_path_option;
     36   GetSelectedFileInfoCallback callback;
     37   std::vector<base::FilePath> file_paths;
     38   std::vector<ui::SelectedFileInfo> selected_files;
     39 };
     40 
     41 // Forward declarations of helper functions for GetSelectedFileInfo().
     42 void ContinueGetSelectedFileInfo(Profile* profile,
     43                                  scoped_ptr<GetSelectedFileInfoParams> params,
     44                                  drive::FileError error,
     45                                  const base::FilePath& local_file_path,
     46                                  scoped_ptr<drive::ResourceEntry> entry);
     47 
     48 // Part of GetSelectedFileInfo().
     49 void GetSelectedFileInfoInternal(Profile* profile,
     50                                  scoped_ptr<GetSelectedFileInfoParams> params) {
     51   DCHECK(profile);
     52   drive::DriveIntegrationService* integration_service =
     53       drive::DriveIntegrationServiceFactory::GetForProfile(profile);
     54 
     55   for (size_t i = params->selected_files.size();
     56        i < params->file_paths.size(); ++i) {
     57     const base::FilePath& file_path = params->file_paths[i];
     58 
     59     if (!drive::util::IsUnderDriveMountPoint(file_path)) {
     60       params->selected_files.push_back(
     61           ui::SelectedFileInfo(file_path, base::FilePath()));
     62     } else {
     63       // |integration_service| is NULL if Drive is disabled.
     64       if (!integration_service) {
     65         ContinueGetSelectedFileInfo(profile,
     66                                     params.Pass(),
     67                                     drive::FILE_ERROR_FAILED,
     68                                     base::FilePath(),
     69                                     scoped_ptr<drive::ResourceEntry>());
     70         return;
     71       }
     72       // When the caller of the select file dialog wants local file paths,
     73       // we should retrieve Drive files onto the local cache.
     74       switch (params->local_path_option) {
     75         case NO_LOCAL_PATH_RESOLUTION:
     76           params->selected_files.push_back(
     77               ui::SelectedFileInfo(file_path, base::FilePath()));
     78           break;
     79         case NEED_LOCAL_PATH_FOR_OPENING:
     80           integration_service->file_system()->GetFileByPath(
     81               drive::util::ExtractDrivePath(file_path),
     82               base::Bind(&ContinueGetSelectedFileInfo,
     83                          profile,
     84                          base::Passed(&params)));
     85           return;  // Remaining work is done in ContinueGetSelectedFileInfo.
     86         case NEED_LOCAL_PATH_FOR_SAVING:
     87           integration_service->file_system()->GetFileByPathForSaving(
     88               drive::util::ExtractDrivePath(file_path),
     89               base::Bind(&ContinueGetSelectedFileInfo,
     90                          profile,
     91                          base::Passed(&params)));
     92           return;  // Remaining work is done in ContinueGetSelectedFileInfo.
     93       }
     94    }
     95   }
     96   params->callback.Run(params->selected_files);
     97 }
     98 
     99 // Part of GetSelectedFileInfo().
    100 void ContinueGetSelectedFileInfo(Profile* profile,
    101                                  scoped_ptr<GetSelectedFileInfoParams> params,
    102                                  drive::FileError error,
    103                                  const base::FilePath& local_file_path,
    104                                  scoped_ptr<drive::ResourceEntry> entry) {
    105   DCHECK(profile);
    106 
    107   const int index = params->selected_files.size();
    108   const base::FilePath& file_path = params->file_paths[index];
    109   base::FilePath local_path;
    110   if (error == drive::FILE_ERROR_OK) {
    111     local_path = local_file_path;
    112   } else {
    113     DLOG(ERROR) << "Failed to get " << file_path.value()
    114                 << " with error code: " << error;
    115   }
    116   params->selected_files.push_back(ui::SelectedFileInfo(file_path, local_path));
    117   GetSelectedFileInfoInternal(profile, params.Pass());
    118 }
    119 
    120 }  // namespace
    121 
    122 int32 GetTabId(ExtensionFunctionDispatcher* dispatcher) {
    123   if (!dispatcher) {
    124     LOG(WARNING) << "No dispatcher";
    125     return 0;
    126   }
    127   if (!dispatcher->delegate()) {
    128     LOG(WARNING) << "No delegate";
    129     return 0;
    130   }
    131   content::WebContents* web_contents =
    132       dispatcher->delegate()->GetAssociatedWebContents();
    133   if (!web_contents) {
    134     LOG(WARNING) << "No associated tab contents";
    135     return 0;
    136   }
    137   return ExtensionTabUtil::GetTabId(web_contents);
    138 }
    139 
    140 GURL FindPreferredIcon(const InstalledApp::IconList& icons,
    141                        int preferred_size) {
    142   GURL result;
    143   if (icons.empty())
    144     return result;
    145   result = icons.rbegin()->second;
    146   for (InstalledApp::IconList::const_reverse_iterator iter = icons.rbegin();
    147        iter != icons.rend() && iter->first >= preferred_size; ++iter) {
    148     result = iter->second;
    149   }
    150   return result;
    151 }
    152 
    153 base::FilePath GetLocalPathFromURL(
    154     content::RenderViewHost* render_view_host,
    155     Profile* profile,
    156     const GURL& url) {
    157   DCHECK(render_view_host);
    158   DCHECK(profile);
    159 
    160   scoped_refptr<fileapi::FileSystemContext> file_system_context =
    161       fileapi_util::GetFileSystemContextForRenderViewHost(
    162           profile, render_view_host);
    163 
    164   const fileapi::FileSystemURL filesystem_url(
    165       file_system_context->CrackURL(url));
    166   base::FilePath path;
    167   if (!chromeos::FileSystemBackend::CanHandleURL(filesystem_url))
    168     return base::FilePath();
    169   return filesystem_url.path();
    170 }
    171 
    172 void GetSelectedFileInfo(content::RenderViewHost* render_view_host,
    173                          Profile* profile,
    174                          const std::vector<GURL>& file_urls,
    175                          GetSelectedFileInfoLocalPathOption local_path_option,
    176                          GetSelectedFileInfoCallback callback) {
    177   DCHECK(render_view_host);
    178   DCHECK(profile);
    179 
    180   scoped_ptr<GetSelectedFileInfoParams> params(new GetSelectedFileInfoParams);
    181   params->local_path_option = local_path_option;
    182   params->callback = callback;
    183 
    184   for (size_t i = 0; i < file_urls.size(); ++i) {
    185     const GURL& file_url = file_urls[i];
    186     const base::FilePath path = GetLocalPathFromURL(
    187         render_view_host, profile, file_url);
    188     if (!path.empty()) {
    189       DVLOG(1) << "Selected: file path: " << path.value();
    190       params->file_paths.push_back(path);
    191     }
    192   }
    193 
    194   BrowserThread::PostTask(
    195       BrowserThread::UI, FROM_HERE,
    196       base::Bind(&GetSelectedFileInfoInternal,
    197                  profile,
    198                  base::Passed(&params)));
    199 }
    200 
    201 }  // namespace util
    202 }  // namespace file_manager
    203