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(¶ms))); 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(¶ms))); 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(¶ms))); 199 } 200 201 } // namespace util 202 } // namespace file_manager 203