// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/chromeos/extensions/file_manager/file_manager_util.h"

#include "ash/shell.h"
#include "base/bind.h"
#include "base/command_line.h"
#include "base/json/json_writer.h"
#include "base/logging.h"
#include "base/metrics/histogram.h"
#include "base/path_service.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/threading/sequenced_worker_pool.h"
#include "base/values.h"
#include "chrome/browser/chromeos/drive/drive.pb.h"
#include "chrome/browser/chromeos/drive/drive_integration_service.h"
#include "chrome/browser/chromeos/drive/file_system.h"
#include "chrome/browser/chromeos/drive/file_system_util.h"
#include "chrome/browser/chromeos/extensions/file_manager/file_browser_handlers.h"
#include "chrome/browser/chromeos/extensions/file_manager/file_tasks.h"
#include "chrome/browser/chromeos/extensions/file_manager/fileapi_util.h"
#include "chrome/browser/chromeos/media/media_player.h"
#include "chrome/browser/extensions/api/file_handlers/app_file_handler_util.h"
#include "chrome/browser/extensions/crx_installer.h"
#include "chrome/browser/extensions/extension_install_prompt.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_system.h"
#include "chrome/browser/google_apis/task_util.h"
#include "chrome/browser/plugins/plugin_prefs.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/browser_iterator.h"
#include "chrome/browser/ui/browser_tabstrip.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/extensions/application_launch.h"
#include "chrome/browser/ui/host_desktop.h"
#include "chrome/browser/ui/simple_message_box.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/extensions/api/file_browser_handlers/file_browser_handler.h"
#include "chrome/common/url_constants.h"
#include "chromeos/chromeos_switches.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/plugin_service.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/browser/user_metrics.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/pepper_plugin_info.h"
#include "content/public/common/webplugininfo.h"
#include "grit/generated_resources.h"
#include "net/base/escape.h"
#include "net/base/mime_util.h"
#include "net/base/net_util.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/gfx/screen.h"
#include "webkit/browser/fileapi/file_system_backend.h"
#include "webkit/browser/fileapi/file_system_context.h"
#include "webkit/browser/fileapi/file_system_operation_runner.h"
#include "webkit/browser/fileapi/file_system_url.h"
#include "webkit/common/fileapi/file_system_util.h"

using base::DictionaryValue;
using base::ListValue;
using content::BrowserContext;
using content::BrowserThread;
using content::PluginService;
using content::UserMetricsAction;
using extensions::app_file_handler_util::FindFileHandlersForFiles;
using extensions::app_file_handler_util::PathAndMimeTypeSet;
using extensions::Extension;
using fileapi::FileSystemURL;

const char kFileBrowserDomain[] = "hhaomjibdihmijegdhdafkllkbggdgoj";

const char kFileBrowserGalleryTaskId[] = "gallery";
const char kFileBrowserMountArchiveTaskId[] = "mount-archive";
const char kFileBrowserWatchTaskId[] = "watch";
const char kFileBrowserPlayTaskId[] = "play";

const char kVideoPlayerAppName[] = "videoplayer";

namespace file_manager {
namespace util {
namespace {

const char kCRXExtension[] = ".crx";
const char kPdfExtension[] = ".pdf";
const char kSwfExtension[] = ".swf";
// List of file extension we can open in tab.
const char* kBrowserSupportedExtensions[] = {
#if defined(GOOGLE_CHROME_BUILD)
    ".pdf", ".swf",
#endif
    ".bmp", ".jpg", ".jpeg", ".png", ".webp", ".gif", ".txt", ".html", ".htm",
    ".mhtml", ".mht", ".svg"
};

// Returns a file manager URL for the given |path|.
GURL GetFileManagerUrl(const char* path) {
  return GURL(std::string("chrome-extension://") + kFileBrowserDomain + path);
}

bool IsSupportedBrowserExtension(const char* file_extension) {
  for (size_t i = 0; i < arraysize(kBrowserSupportedExtensions); i++) {
    if (base::strcasecmp(file_extension, kBrowserSupportedExtensions[i]) == 0) {
      return true;
    }
  }
  return false;
}

bool IsCRXFile(const char* file_extension) {
  return base::strcasecmp(file_extension, kCRXExtension) == 0;
}

bool IsPepperPluginEnabled(Profile* profile,
                           const base::FilePath& plugin_path) {
  content::PepperPluginInfo* pepper_info =
      PluginService::GetInstance()->GetRegisteredPpapiPluginInfo(plugin_path);
  if (!pepper_info)
    return false;

  scoped_refptr<PluginPrefs> plugin_prefs = PluginPrefs::GetForProfile(profile);
  if (!plugin_prefs.get())
    return false;

  return plugin_prefs->IsPluginEnabled(pepper_info->ToWebPluginInfo());
}

bool IsPdfPluginEnabled(Profile* profile) {
  base::FilePath plugin_path;
  PathService::Get(chrome::FILE_PDF_PLUGIN, &plugin_path);
  return IsPepperPluginEnabled(profile, plugin_path);
}

bool IsFlashPluginEnabled(Profile* profile) {
  base::FilePath plugin_path(
      CommandLine::ForCurrentProcess()->GetSwitchValueNative(
          switches::kPpapiFlashPath));
  if (plugin_path.empty())
    PathService::Get(chrome::FILE_PEPPER_FLASH_PLUGIN, &plugin_path);
  return IsPepperPluginEnabled(profile, plugin_path);
}

// Convert numeric dialog type to a string.
std::string GetDialogTypeAsString(
    ui::SelectFileDialog::Type dialog_type) {
  std::string type_str;
  switch (dialog_type) {
    case ui::SelectFileDialog::SELECT_NONE:
      type_str = "full-page";
      break;

    case ui::SelectFileDialog::SELECT_FOLDER:
      type_str = "folder";
      break;

    case ui::SelectFileDialog::SELECT_UPLOAD_FOLDER:
      type_str = "upload-folder";
      break;

    case ui::SelectFileDialog::SELECT_SAVEAS_FILE:
      type_str = "saveas-file";
      break;

    case ui::SelectFileDialog::SELECT_OPEN_FILE:
      type_str = "open-file";
      break;

    case ui::SelectFileDialog::SELECT_OPEN_MULTI_FILE:
      type_str = "open-multi-file";
      break;

    default:
      NOTREACHED();
  }

  return type_str;
}

void OpenNewTab(Profile* profile, const GURL& url) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  Browser* browser = chrome::FindOrCreateTabbedBrowser(
      profile ? profile : ProfileManager::GetDefaultProfileOrOffTheRecord(),
      chrome::HOST_DESKTOP_TYPE_ASH);
  chrome::AddSelectedTabWithURL(browser, url, content::PAGE_TRANSITION_LINK);
  // If the current browser is not tabbed then the new tab will be created
  // in a different browser. Make sure it is visible.
  browser->window()->Show();
}

// Shows a warning message box saying that the file could not be opened.
void ShowWarningMessageBox(Profile* profile, const base::FilePath& path) {
  // TODO: if FindOrCreateTabbedBrowser creates a new browser the returned
  // browser is leaked.
  Browser* browser =
      chrome::FindOrCreateTabbedBrowser(profile,
                                        chrome::HOST_DESKTOP_TYPE_ASH);
  chrome::ShowMessageBox(
      browser->window()->GetNativeWindow(),
      l10n_util::GetStringFUTF16(
          IDS_FILE_BROWSER_ERROR_VIEWING_FILE_TITLE,
          UTF8ToUTF16(path.BaseName().value())),
      l10n_util::GetStringUTF16(IDS_FILE_BROWSER_ERROR_VIEWING_FILE),
      chrome::MESSAGE_BOX_TYPE_WARNING);
}

void InstallCRX(Browser* browser, const base::FilePath& path) {
  ExtensionService* service =
      extensions::ExtensionSystem::Get(browser->profile())->extension_service();
  CHECK(service);

  scoped_refptr<extensions::CrxInstaller> installer(
      extensions::CrxInstaller::Create(
          service,
          scoped_ptr<ExtensionInstallPrompt>(new ExtensionInstallPrompt(
              browser->profile(), NULL, NULL))));
  installer->set_error_on_unsupported_requirements(true);
  installer->set_is_gallery_install(false);
  installer->set_allow_silent_install(false);
  installer->InstallCrx(path);
}

// Called when a crx file on Drive was downloaded.
void OnCRXDownloadCallback(Browser* browser,
                           drive::FileError error,
                           const base::FilePath& file,
                           scoped_ptr<drive::ResourceEntry> entry) {
  if (error != drive::FILE_ERROR_OK)
    return;
  InstallCRX(browser, file);
}

// Grants file system access to the file browser.
bool GrantFileSystemAccessToFileBrowser(Profile* profile) {
  // File browser always runs in the site for its extension id, so that is the
  // site for which file access permissions should be granted.
  GURL site = extensions::ExtensionSystem::Get(profile)->extension_service()->
      GetSiteForExtensionId(kFileBrowserDomain);
  fileapi::ExternalFileSystemBackend* backend =
      BrowserContext::GetStoragePartitionForSite(profile, site)->
          GetFileSystemContext()->external_backend();
  if (!backend)
    return false;
  backend->GrantFullAccessToExtension(GetFileBrowserUrl().host());
  return true;
}

// Executes handler specified with |task| for |url|.
void ExecuteHandler(Profile* profile,
                    const file_tasks::TaskDescriptor& task,
                    const GURL& url) {
  // If File Browser has not been open yet then it did not request access
  // to the file system. Do it now.
  if (!GrantFileSystemAccessToFileBrowser(profile))
    return;

  fileapi::FileSystemContext* file_system_context =
      fileapi_util::GetFileSystemContextForExtensionId(
          profile, kFileBrowserDomain);

  // We are executing the task on behalf of File Browser extension.
  const GURL source_url = GetFileBrowserUrl();
  std::vector<FileSystemURL> urls;
  urls.push_back(file_system_context->CrackURL(url));

  file_tasks::ExecuteFileTask(
      profile,
      source_url,
      kFileBrowserDomain,
      0, // no tab id
      task,
      urls,
      file_tasks::FileTaskFinishedCallback());
}

void OpenFileBrowserImpl(const base::FilePath& path,
                         const std::string& action_id) {
  content::RecordAction(UserMetricsAction("ShowFileBrowserFullTab"));
  Profile* profile = ProfileManager::GetDefaultProfileOrOffTheRecord();

  GURL url;
  if (!ConvertFileToFileSystemUrl(profile, path, kFileBrowserDomain, &url))
    return;

  file_tasks::TaskDescriptor task(kFileBrowserDomain,
                                  file_tasks::kFileBrowserHandlerTaskType,
                                  action_id);
  ExecuteHandler(profile, task, url);
}

Browser* GetBrowserForUrl(GURL target_url) {
  for (chrome::BrowserIterator it; !it.done(); it.Next()) {
    Browser* browser = *it;
    TabStripModel* tab_strip = browser->tab_strip_model();
    for (int idx = 0; idx < tab_strip->count(); idx++) {
      content::WebContents* web_contents = tab_strip->GetWebContentsAt(idx);
      const GURL& url = web_contents->GetLastCommittedURL();
      if (url == target_url)
        return browser;
    }
  }
  return NULL;
}

bool ExecuteDefaultAppHandler(Profile* profile,
                              const base::FilePath& path,
                              const GURL& url,
                              const std::string& mime_type,
                              const std::string& default_task_id) {
  ExtensionService* service = profile->GetExtensionService();
  if (!service)
    return false;

  PathAndMimeTypeSet files;
  files.insert(std::make_pair(path, mime_type));
  const extensions::FileHandlerInfo* first_handler = NULL;
  const extensions::Extension* extension_for_first_handler = NULL;

  // If we find the default handler, we execute it immediately, but otherwise,
  // we remember the first handler, and if there was no default handler, simply
  // execute the first one.
  for (ExtensionSet::const_iterator iter = service->extensions()->begin();
       iter != service->extensions()->end();
       ++iter) {
    const Extension* extension = iter->get();

    // We don't support using hosted apps to open files.
    if (!extension->is_platform_app())
      continue;

    // We only support apps that specify "incognito: split" if in incognito
    // mode.
    if (profile->IsOffTheRecord() &&
        !service->IsIncognitoEnabled(extension->id()))
      continue;

    typedef std::vector<const extensions::FileHandlerInfo*> FileHandlerList;
    FileHandlerList file_handlers = FindFileHandlersForFiles(*extension, files);
    for (FileHandlerList::iterator i = file_handlers.begin();
         i != file_handlers.end(); ++i) {
      const extensions::FileHandlerInfo* handler = *i;
      std::string task_id = file_tasks::MakeTaskID(
          extension->id(),
          file_tasks::kFileHandlerTaskType,
          handler->id);
      if (task_id == default_task_id) {
        file_tasks::TaskDescriptor task(extension->id(),
                                        file_tasks::kFileHandlerTaskType,
                                        handler->id);
        ExecuteHandler(profile, task, url);
        return true;

      } else if (!first_handler) {
        first_handler = handler;
        extension_for_first_handler = extension;
      }
    }
  }
  if (first_handler) {
    file_tasks::TaskDescriptor task(extension_for_first_handler->id(),
                                    file_tasks::kFileHandlerTaskType,
                                    first_handler->id);
    ExecuteHandler(profile, task, url);
    return true;
  }
  return false;
}

bool ExecuteExtensionHandler(Profile* profile,
                             const base::FilePath& path,
                             const FileBrowserHandler& handler,
                             const GURL& url) {
  std::string extension_id = handler.extension_id();
  std::string action_id = handler.id();
  Browser* browser = chrome::FindLastActiveWithProfile(profile,
      chrome::HOST_DESKTOP_TYPE_ASH);

  // If there is no browsers for the profile, bail out. Return true so warning
  // about file type not being supported is not displayed.
  if (!browser)
    return true;

  if (extension_id == kFileBrowserDomain) {
    if (action_id == kFileBrowserGalleryTaskId ||
        action_id == kFileBrowserMountArchiveTaskId ||
        action_id == kFileBrowserPlayTaskId ||
        action_id == kFileBrowserWatchTaskId) {
      file_tasks::TaskDescriptor task(extension_id,
                                      file_tasks::kFileBrowserHandlerTaskType,
                                      action_id);
      ExecuteHandler(profile, task, url);
      return true;
    }
    return ExecuteBuiltinHandler(browser, path);
  }

  file_tasks::TaskDescriptor task(extension_id,
                                  file_tasks::kFileBrowserHandlerTaskType,
                                  action_id);
  ExecuteHandler(profile, task, url);
  return true;
}

bool ExecuteDefaultHandler(Profile* profile, const base::FilePath& path) {
  GURL url;
  if (!ConvertFileToFileSystemUrl(profile, path, kFileBrowserDomain, &url))
    return false;

  std::string mime_type = GetMimeTypeForPath(path);
  std::string default_task_id = file_tasks::GetDefaultTaskIdFromPrefs(
      profile, mime_type, path.Extension());

  // We choose the file handler from the following in decreasing priority or
  // fail if none support the file type:
  // 1. default extension
  // 2. default app
  // 3. a fallback handler (e.g. opening in the browser)
  // 4. non-default app
  // 5. non-default extension
  // Note that there can be at most one of default extension and default app.
  const FileBrowserHandler* handler =
      file_browser_handlers::FindFileBrowserHandlerForURLAndPath(
          profile, url, path);
  if (!handler) {
    return ExecuteDefaultAppHandler(
        profile, path, url, mime_type, default_task_id);
  }

  std::string handler_task_id = file_tasks::MakeTaskID(
        handler->extension_id(),
        file_tasks::kFileBrowserHandlerTaskType,
        handler->id());
  if (handler_task_id != default_task_id &&
      !file_browser_handlers::IsFallbackFileBrowserHandler(handler) &&
      ExecuteDefaultAppHandler(
          profile, path, url, mime_type, default_task_id)) {
    return true;
  }
  return ExecuteExtensionHandler(profile, path, *handler, url);
}

// Reads the alternate URL from a GDoc file. When it fails, returns a file URL
// for |file_path| as fallback.
// Note that an alternate url is a URL to open a hosted document.
GURL ReadUrlFromGDocOnBlockingPool(const base::FilePath& file_path) {
  GURL url = drive::util::ReadUrlFromGDocFile(file_path);
  if (url.is_empty())
    url = net::FilePathToFileURL(file_path);
  return url;
}

// Used to implement ViewItem().
void ContinueViewItem(Profile* profile,
                      const base::FilePath& path,
                      base::PlatformFileError error) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));

  if (error == base::PLATFORM_FILE_OK) {
    // A directory exists at |path|. Open it with FileBrowser.
    OpenFileBrowserImpl(path, "open");
  } else {
    if (!ExecuteDefaultHandler(profile, path))
      ShowWarningMessageBox(profile, path);
  }
}

// Used to implement CheckIfDirectoryExists().
void CheckIfDirectoryExistsOnIOThread(
    scoped_refptr<fileapi::FileSystemContext> file_system_context,
    const GURL& url,
    const fileapi::FileSystemOperationRunner::StatusCallback& callback) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));

  fileapi::FileSystemURL file_system_url = file_system_context->CrackURL(url);
  file_system_context->operation_runner()->DirectoryExists(
      file_system_url, callback);
}

// Checks if a directory exists at |url|.
void CheckIfDirectoryExists(
    scoped_refptr<fileapi::FileSystemContext> file_system_context,
    const GURL& url,
    const fileapi::FileSystemOperationRunner::StatusCallback& callback) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));

  BrowserThread::PostTask(
      BrowserThread::IO, FROM_HERE,
      base::Bind(&CheckIfDirectoryExistsOnIOThread,
                 file_system_context,
                 url,
                 google_apis::CreateRelayCallback(callback)));
}

}  // namespace

GURL GetFileBrowserExtensionUrl() {
  return GetFileManagerUrl("/");
}

GURL GetFileBrowserUrl() {
  return GetFileManagerUrl("/main.html");
}

GURL GetMediaPlayerUrl() {
  return GetFileManagerUrl("/mediaplayer.html");
}

GURL GetActionChoiceUrl(const base::FilePath& virtual_path,
                        bool advanced_mode) {
  std::string url = GetFileManagerUrl("/action_choice.html").spec();
  if (advanced_mode)
    url += "?advanced-mode";
  url += "#/" + net::EscapeUrlEncodedData(virtual_path.value(),
                                          false);  // Space to %20 instead of +.
  return GURL(url);
}

GURL ConvertRelativePathToFileSystemUrl(const base::FilePath& relative_path,
                                        const std::string& extension_id) {
  GURL base_url = fileapi::GetFileSystemRootURI(
      Extension::GetBaseURLFromExtensionId(extension_id),
      fileapi::kFileSystemTypeExternal);
  return GURL(base_url.spec() +
              net::EscapeUrlEncodedData(relative_path.AsUTF8Unsafe(),
                                        false));  // Space to %20 instead of +.
}

bool ConvertFileToFileSystemUrl(Profile* profile,
                                const base::FilePath& full_file_path,
                                const std::string& extension_id,
                                GURL* url) {
  base::FilePath relative_path;
  if (!ConvertFileToRelativeFileSystemPath(profile, extension_id,
           full_file_path, &relative_path)) {
    return false;
  }
  *url = ConvertRelativePathToFileSystemUrl(relative_path, extension_id);
  return true;
}

bool ConvertFileToRelativeFileSystemPath(
    Profile* profile,
    const std::string& extension_id,
    const base::FilePath& full_file_path,
    base::FilePath* virtual_path) {
  ExtensionService* service =
      extensions::ExtensionSystem::Get(profile)->extension_service();
  // May be NULL during unit_tests.
  if (!service)
    return false;

  // File browser APIs are meant to be used only from extension context, so the
  // extension's site is the one in whose file system context the virtual path
  // should be found.
  GURL site = service->GetSiteForExtensionId(extension_id);
  fileapi::ExternalFileSystemBackend* backend =
      BrowserContext::GetStoragePartitionForSite(profile, site)->
          GetFileSystemContext()->external_backend();
  if (!backend)
    return false;

  // Find if this file path is managed by the external backend.
  if (!backend->GetVirtualPath(full_file_path, virtual_path))
    return false;

  return true;
}

GURL GetFileBrowserUrlWithParams(
    ui::SelectFileDialog::Type type,
    const string16& title,
    const base::FilePath& default_virtual_path,
    const ui::SelectFileDialog::FileTypeInfo* file_types,
    int file_type_index,
    const base::FilePath::StringType& default_extension) {
  DictionaryValue arg_value;
  arg_value.SetString("type", GetDialogTypeAsString(type));
  arg_value.SetString("title", title);
  arg_value.SetString("defaultPath", default_virtual_path.value());
  arg_value.SetString("defaultExtension", default_extension);

  if (file_types) {
    ListValue* types_list = new ListValue();
    for (size_t i = 0; i < file_types->extensions.size(); ++i) {
      ListValue* extensions_list = new ListValue();
      for (size_t j = 0; j < file_types->extensions[i].size(); ++j) {
        extensions_list->Append(
            new base::StringValue(file_types->extensions[i][j]));
      }

      DictionaryValue* dict = new DictionaryValue();
      dict->Set("extensions", extensions_list);

      if (i < file_types->extension_description_overrides.size()) {
        string16 desc = file_types->extension_description_overrides[i];
        dict->SetString("description", desc);
      }

      // file_type_index is 1-based. 0 means no selection at all.
      dict->SetBoolean("selected",
                       (static_cast<size_t>(file_type_index) == (i + 1)));

      types_list->Set(i, dict);
    }
    arg_value.Set("typeList", types_list);

    arg_value.SetBoolean("includeAllFiles", file_types->include_all_files);
  }

  // If the caller cannot handle Drive path, the file chooser dialog need to
  // return resolved local native paths to the selected files.
  arg_value.SetBoolean("shouldReturnLocalPath",
                       !file_types || !file_types->support_drive);

  std::string json_args;
  base::JSONWriter::Write(&arg_value, &json_args);

  // kChromeUIFileManagerURL could not be used since query parameters are not
  // supported for it.
  std::string url = GetFileBrowserUrl().spec() + '?' +
      net::EscapeUrlEncodedData(json_args,
                                false);  // Space to %20 instead of +.
  return GURL(url);
}

string16 GetTitleFromType(ui::SelectFileDialog::Type dialog_type) {
  string16 title;
  switch (dialog_type) {
    case ui::SelectFileDialog::SELECT_NONE:
      // Full page file manager doesn't need a title.
      break;

    case ui::SelectFileDialog::SELECT_FOLDER:
      title = l10n_util::GetStringUTF16(
          IDS_FILE_BROWSER_SELECT_FOLDER_TITLE);
      break;

    case ui::SelectFileDialog::SELECT_UPLOAD_FOLDER:
      title = l10n_util::GetStringUTF16(
          IDS_FILE_BROWSER_SELECT_UPLOAD_FOLDER_TITLE);
      break;

    case ui::SelectFileDialog::SELECT_SAVEAS_FILE:
      title = l10n_util::GetStringUTF16(
          IDS_FILE_BROWSER_SELECT_SAVEAS_FILE_TITLE);
      break;

    case ui::SelectFileDialog::SELECT_OPEN_FILE:
      title = l10n_util::GetStringUTF16(
          IDS_FILE_BROWSER_SELECT_OPEN_FILE_TITLE);
      break;

    case ui::SelectFileDialog::SELECT_OPEN_MULTI_FILE:
      title = l10n_util::GetStringUTF16(
          IDS_FILE_BROWSER_SELECT_OPEN_MULTI_FILE_TITLE);
      break;

    default:
      NOTREACHED();
  }

  return title;
}

void ViewRemovableDrive(const base::FilePath& path) {
  OpenFileBrowserImpl(path, "auto-open");
}

void OpenActionChoiceDialog(const base::FilePath& path, bool advanced_mode) {
  const int kDialogWidth = 394;
  // TODO(dgozman): remove 50, which is a title height once popup window
  // will have no title.
  const int kDialogHeight = 316 + 50;

  Profile* profile = ProfileManager::GetDefaultProfileOrOffTheRecord();

  base::FilePath virtual_path;
  if (!ConvertFileToRelativeFileSystemPath(profile, kFileBrowserDomain, path,
                                           &virtual_path))
    return;
  GURL dialog_url = GetActionChoiceUrl(virtual_path, advanced_mode);

  const gfx::Size screen = ash::Shell::GetScreen()->GetPrimaryDisplay().size();
  const gfx::Rect bounds((screen.width() - kDialogWidth) / 2,
                         (screen.height() - kDialogHeight) / 2,
                         kDialogWidth,
                         kDialogHeight);

  Browser* browser = GetBrowserForUrl(dialog_url);

  if (browser) {
    browser->window()->Show();
    return;
  }

  ExtensionService* service = extensions::ExtensionSystem::Get(
    profile ? profile : ProfileManager::GetDefaultProfileOrOffTheRecord())->
        extension_service();
  if (!service)
    return;

  const extensions::Extension* extension =
      service->GetExtensionById(kFileBrowserDomain, false);
  if (!extension)
    return;

  chrome::AppLaunchParams params(profile, extension,
                                 extension_misc::LAUNCH_WINDOW,
                                 NEW_FOREGROUND_TAB);
  params.override_url = dialog_url;
  params.override_bounds = bounds;
  chrome::OpenApplication(params);
}

void ViewItem(const base::FilePath& path) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));

  Profile* profile = ProfileManager::GetDefaultProfileOrOffTheRecord();
  GURL url;
  if (!ConvertFileToFileSystemUrl(profile, path, kFileBrowserDomain, &url) ||
      !GrantFileSystemAccessToFileBrowser(profile)) {
    ShowWarningMessageBox(profile, path);
    return;
  }

  scoped_refptr<fileapi::FileSystemContext> file_system_context =
      fileapi_util::GetFileSystemContextForExtensionId(
          profile, kFileBrowserDomain);

  CheckIfDirectoryExists(file_system_context, url,
                         base::Bind(&ContinueViewItem, profile, path));
}

void ShowFileInFolder(const base::FilePath& path) {
  // This action changes the selection so we do not reuse existing tabs.
  OpenFileBrowserImpl(path, "select");
}

bool ExecuteBuiltinHandler(Browser* browser, const base::FilePath& path) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));

  Profile* profile = browser->profile();
  std::string file_extension = path.Extension();
  // For things supported natively by the browser, we should open it
  // in a tab.
  if (IsSupportedBrowserExtension(file_extension.data()) ||
      ShouldBeOpenedWithPlugin(profile, file_extension.data())) {
    GURL page_url = net::FilePathToFileURL(path);
    // Override drive resource to point to internal handler instead of file URL.
    if (drive::util::IsUnderDriveMountPoint(path)) {
      page_url = drive::util::FilePathToDriveURL(
          drive::util::ExtractDrivePath(path));
    }
    OpenNewTab(profile, page_url);
    return true;
  }

  if (drive::util::HasGDocFileExtension(path)) {
    if (drive::util::IsUnderDriveMountPoint(path)) {
      // The file is on Google Docs. Open with drive URL.
      GURL url = drive::util::FilePathToDriveURL(
          drive::util::ExtractDrivePath(path));
      OpenNewTab(profile, url);
    } else {
      // The file is local (downloaded from an attachment or otherwise copied).
      // Parse the file to extract the Docs url and open this url.
      base::PostTaskAndReplyWithResult(
          BrowserThread::GetBlockingPool(),
          FROM_HERE,
          base::Bind(&ReadUrlFromGDocOnBlockingPool, path),
          base::Bind(&OpenNewTab, static_cast<Profile*>(NULL)));
    }
    return true;
  }

  if (IsCRXFile(file_extension.data())) {
    if (drive::util::IsUnderDriveMountPoint(path)) {
      drive::DriveIntegrationService* integration_service =
          drive::DriveIntegrationServiceFactory::GetForProfile(profile);
      if (!integration_service)
        return false;
      integration_service->file_system()->GetFileByPath(
          drive::util::ExtractDrivePath(path),
          base::Bind(&OnCRXDownloadCallback, browser));
    } else {
      InstallCRX(browser, path);
    }
    return true;
  }

  // Failed to open the file of unknown type.
  LOG(WARNING) << "Unknown file type: " << path.value();
  return false;
}

// If a bundled plugin is enabled, we should open pdf/swf files in a tab.
bool ShouldBeOpenedWithPlugin(Profile* profile, const char* file_extension) {
  if (LowerCaseEqualsASCII(file_extension, kPdfExtension))
    return IsPdfPluginEnabled(profile);
  if (LowerCaseEqualsASCII(file_extension, kSwfExtension))
    return IsFlashPluginEnabled(profile);
  return false;
}

std::string GetMimeTypeForPath(const base::FilePath& file_path) {
  const base::FilePath::StringType file_extension =
      StringToLowerASCII(file_path.Extension());

  // TODO(thorogood): Rearchitect this call so it can run on the File thread;
  // GetMimeTypeFromFile requires this on Linux. Right now, we use
  // Chrome-level knowledge only.
  std::string mime_type;
  if (file_extension.empty() ||
      !net::GetWellKnownMimeTypeFromExtension(file_extension.substr(1),
                                              &mime_type)) {
    // If the file doesn't have an extension or its mime-type cannot be
    // determined, then indicate that it has the empty mime-type. This will
    // only be matched if the Web Intents accepts "*" or "*/*".
    return "";
  } else {
    return mime_type;
  }
}

}  // namespace util
}  // namespace file_manager
