1 // Copyright (c) 2011 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 #include "chrome/browser/extensions/file_manager_util.h" 5 6 #include "base/json/json_writer.h" 7 #include "base/logging.h" 8 #include "base/string_util.h" 9 #include "base/utf_string_conversions.h" 10 #include "base/values.h" 11 #include "chrome/browser/metrics/user_metrics.h" 12 #include "chrome/browser/platform_util.h" 13 #include "chrome/browser/profiles/profile.h" 14 #include "chrome/browser/ui/browser.h" 15 #include "chrome/browser/ui/browser_list.h" 16 #include "chrome/browser/ui/webui/mediaplayer_ui.h" 17 #include "content/browser/browser_thread.h" 18 #include "grit/generated_resources.h" 19 #include "third_party/libjingle/source/talk/base/urlencode.h" 20 #include "ui/base/l10n/l10n_util.h" 21 #include "webkit/fileapi/file_system_context.h" 22 #include "webkit/fileapi/file_system_mount_point_provider.h" 23 #include "webkit/fileapi/file_system_util.h" 24 25 // This is the "well known" url for the file manager extension from 26 // browser/resources/file_manager. In the future we may provide a way to swap 27 // out this file manager for an aftermarket part, but not yet. 28 const char kBaseFileBrowserUrl[] = 29 "chrome-extension://hhaomjibdihmijegdhdafkllkbggdgoj/main.html"; 30 // List of file extension we can open in tab. 31 const char* kBrowserSupportedExtensions[] = { 32 ".jpg", ".jpeg", ".png", ".webp", ".gif", ".pdf", ".txt", ".html", ".htm" 33 }; 34 // List of file extension that can be handled with the media player. 35 const char* kAVExtensions[] = { 36 ".webm", ".mp4", ".m4v", ".mov", ".ogm", ".ogv", ".ogx", 37 ".mp3", ".m4a", ".ogg", ".oga", ".wav", 38 /* TODO(zelidrag): Add unsupported ones as we enable them: 39 ".3gp", ".mkv", ".avi", ".divx", ".xvid", ".wmv", ".asf", ".mpeg", ".mpg", 40 ".wma", ".aiff", 41 */ 42 }; 43 44 bool IsSupportedBrowserExtension(const char* ext) { 45 for (size_t i = 0; i < arraysize(kBrowserSupportedExtensions); i++) { 46 if (base::strcasecmp(ext, kBrowserSupportedExtensions[i]) == 0) { 47 return true; 48 } 49 } 50 return false; 51 } 52 53 bool IsSupportedAVExtension(const char* ext) { 54 for (size_t i = 0; i < arraysize(kAVExtensions); i++) { 55 if (base::strcasecmp(ext, kAVExtensions[i]) == 0) { 56 return true; 57 } 58 } 59 return false; 60 } 61 62 // static 63 GURL FileManagerUtil::GetFileBrowserUrl() { 64 return GURL(kBaseFileBrowserUrl); 65 } 66 67 // static 68 bool FileManagerUtil::ConvertFileToFileSystemUrl( 69 Profile* profile, const FilePath& full_file_path, const GURL& origin_url, 70 GURL* url) { 71 fileapi::FileSystemPathManager* path_manager = 72 profile->GetFileSystemContext()->path_manager(); 73 fileapi::ExternalFileSystemMountPointProvider* provider = 74 path_manager->external_provider(); 75 if (!provider) 76 return false; 77 78 // Find if this file path is managed by the external provider. 79 std::vector<FilePath> root_dirs = provider->GetRootDirectories(); 80 for (std::vector<FilePath>::iterator iter = root_dirs.begin(); 81 iter != root_dirs.end(); 82 ++iter) { 83 FilePath path; 84 std::vector<FilePath::StringType> components; 85 const FilePath& root_path = *iter; 86 root_path.GetComponents(&components); 87 if (!components.size()) { 88 NOTREACHED(); 89 continue; 90 } 91 if (root_path.AppendRelativePath(full_file_path, &path)) { 92 GURL base_url = fileapi::GetFileSystemRootURI(origin_url, 93 fileapi::kFileSystemTypeExternal); 94 std::string final_url = base_url.spec(); 95 FilePath relative_path(components[components.size() - 1]); 96 *url = GURL(base_url.spec() + relative_path.Append(path).value()); 97 return true; 98 } 99 } 100 return false; 101 } 102 103 // static 104 GURL FileManagerUtil::GetFileBrowserUrlWithParams( 105 SelectFileDialog::Type type, 106 const string16& title, 107 const FilePath& default_path, 108 const SelectFileDialog::FileTypeInfo* file_types, 109 int file_type_index, 110 const FilePath::StringType& default_extension) { 111 std::string json = GetArgumentsJson(type, title, default_path, file_types, 112 file_type_index, default_extension); 113 return GURL(FileManagerUtil::GetFileBrowserUrl().spec() + "?" + 114 UrlEncodeStringWithoutEncodingSpaceAsPlus(json)); 115 116 } 117 // static 118 void FileManagerUtil::ShowFullTabUrl(Profile* profile, 119 const FilePath& default_path) { 120 std::string json = GetArgumentsJson(SelectFileDialog::SELECT_NONE, string16(), 121 default_path, NULL, 0, FilePath::StringType()); 122 GURL url(std::string(kBaseFileBrowserUrl) + "?" + 123 UrlEncodeStringWithoutEncodingSpaceAsPlus(json)); 124 Browser* browser = BrowserList::GetLastActive(); 125 if (!browser) 126 return; 127 128 UserMetrics::RecordAction(UserMetricsAction("ShowFileBrowserFullTab"), 129 profile); 130 browser->ShowSingletonTab(GURL(url)); 131 } 132 133 134 void FileManagerUtil::ViewItem(const FilePath& full_path, bool enqueue) { 135 std::string ext = full_path.Extension(); 136 // For things supported natively by the browser, we should open it 137 // in a tab. 138 if (IsSupportedBrowserExtension(ext.data())) { 139 std::string path; 140 path = "file://"; 141 path.append(full_path.value()); 142 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { 143 bool result = BrowserThread::PostTask( 144 BrowserThread::UI, FROM_HERE, 145 NewRunnableFunction(&ViewItem, full_path, enqueue)); 146 DCHECK(result); 147 return; 148 } 149 Browser* browser = BrowserList::GetLastActive(); 150 if (browser) 151 browser->AddSelectedTabWithURL(GURL(path), PageTransition::LINK); 152 return; 153 } 154 if (IsSupportedAVExtension(ext.data())) { 155 Browser* browser = BrowserList::GetLastActive(); 156 if (!browser) 157 return; 158 MediaPlayer* mediaplayer = MediaPlayer::GetInstance(); 159 if (enqueue) 160 mediaplayer->EnqueueMediaFile(browser->profile(), full_path, NULL); 161 else 162 mediaplayer->ForcePlayMediaFile(browser->profile(), full_path, NULL); 163 return; 164 } 165 166 // Unknown file type. Show an error message. 167 BrowserThread::PostTask( 168 BrowserThread::UI, FROM_HERE, 169 NewRunnableFunction( 170 &platform_util::SimpleErrorBox, 171 static_cast<gfx::NativeWindow>(NULL), 172 l10n_util::GetStringUTF16(IDS_FILEBROWSER_ERROR_TITLE), 173 l10n_util::GetStringFUTF16(IDS_FILEBROWSER_ERROR_UNKNOWN_FILE_TYPE, 174 UTF8ToUTF16(full_path.BaseName().value())) 175 )); 176 } 177 178 // static 179 std::string FileManagerUtil::GetArgumentsJson( 180 SelectFileDialog::Type type, 181 const string16& title, 182 const FilePath& default_path, 183 const SelectFileDialog::FileTypeInfo* file_types, 184 int file_type_index, 185 const FilePath::StringType& default_extension) { 186 DictionaryValue arg_value; 187 arg_value.SetString("type", GetDialogTypeAsString(type)); 188 arg_value.SetString("title", title); 189 // TODO(zelidrag): Convert local system path into virtual path for File API. 190 arg_value.SetString("defaultPath", default_path.value()); 191 arg_value.SetString("defaultExtension", default_extension); 192 193 ListValue* types_list = new ListValue(); 194 195 if (file_types) { 196 for (size_t i = 0; i < file_types->extensions.size(); ++i) { 197 ListValue* extensions_list = new ListValue(); 198 for (size_t j = 0; j < file_types->extensions[i].size(); ++j) { 199 extensions_list->Set( 200 i, Value::CreateStringValue(file_types->extensions[i][j])); 201 } 202 203 DictionaryValue* dict = new DictionaryValue(); 204 dict->Set("extensions", extensions_list); 205 206 if (i < file_types->extension_description_overrides.size()) { 207 string16 desc = file_types->extension_description_overrides[i]; 208 dict->SetString("description", desc); 209 } 210 211 dict->SetBoolean("selected", 212 (static_cast<size_t>(file_type_index) == i)); 213 214 types_list->Set(i, dict); 215 } 216 } 217 218 std::string rv; 219 base::JSONWriter::Write(&arg_value, false, &rv); 220 221 return rv; 222 } 223 224 // static 225 std::string FileManagerUtil::GetDialogTypeAsString( 226 SelectFileDialog::Type dialog_type) { 227 std::string type_str; 228 switch (dialog_type) { 229 case SelectFileDialog::SELECT_NONE: 230 type_str = "full-page"; 231 break; 232 233 case SelectFileDialog::SELECT_FOLDER: 234 type_str = "folder"; 235 break; 236 237 case SelectFileDialog::SELECT_SAVEAS_FILE: 238 type_str = "saveas-file"; 239 break; 240 241 case SelectFileDialog::SELECT_OPEN_FILE: 242 type_str = "open-file"; 243 break; 244 245 case SelectFileDialog::SELECT_OPEN_MULTI_FILE: 246 type_str = "open-multi-file"; 247 break; 248 249 default: 250 NOTREACHED(); 251 } 252 253 return type_str; 254 } 255