Home | History | Annotate | Download | only in extensions
      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