// 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/file_manager/file_tasks.h"

#include <stddef.h>

#include <map>

#include "apps/launcher.h"
#include "base/bind.h"
#include "base/macros.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/string_split.h"
#include "base/strings/stringprintf.h"
#include "chrome/browser/chromeos/drive/file_system_util.h"
#include "chrome/browser/chromeos/drive/file_task_executor.h"
#include "chrome/browser/chromeos/file_manager/app_id.h"
#include "chrome/browser/chromeos/file_manager/arc_file_tasks.h"
#include "chrome/browser/chromeos/file_manager/file_browser_handlers.h"
#include "chrome/browser/chromeos/file_manager/fileapi_util.h"
#include "chrome/browser/chromeos/file_manager/open_util.h"
#include "chrome/browser/extensions/extension_tab_util.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/extensions/application_launch.h"
#include "chrome/browser/ui/webui/extensions/extension_icon_source.h"
#include "chrome/common/extensions/api/file_browser_handlers/file_browser_handler.h"
#include "chrome/common/extensions/api/file_manager_private.h"
#include "chrome/common/extensions/extension_constants.h"
#include "chrome/common/pref_names.h"
#include "chromeos/chromeos_switches.h"
#include "components/drive/drive_api_util.h"
#include "components/drive/drive_app_registry.h"
#include "components/prefs/pref_service.h"
#include "components/prefs/scoped_user_pref_update.h"
#include "extensions/browser/api/file_handlers/mime_util.h"
#include "extensions/browser/entry_info.h"
#include "extensions/browser/extension_host.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/extension_system.h"
#include "extensions/browser/extension_util.h"
#include "extensions/common/constants.h"
#include "extensions/common/extension_set.h"
#include "storage/browser/fileapi/file_system_url.h"
#include "third_party/WebKit/common/mime_util/mime_util.h"

using extensions::Extension;
using extensions::api::file_manager_private::Verb;
using extensions::app_file_handler_util::FindFileHandlersForEntries;
using storage::FileSystemURL;

namespace file_manager {
namespace file_tasks {

namespace {

// The values "file" and "app" are confusing, but cannot be changed easily as
// these are used in default task IDs stored in preferences.
const char kFileBrowserHandlerTaskType[] = "file";
const char kFileHandlerTaskType[] = "app";
const char kDriveAppTaskType[] = "drive";
const char kArcAppTaskType[] = "arc";

// Drive apps always use the action ID.
const char kDriveAppActionID[] = "open-with";

// Converts a TaskType to a string.
std::string TaskTypeToString(TaskType task_type) {
  switch (task_type) {
    case TASK_TYPE_FILE_BROWSER_HANDLER:
      return kFileBrowserHandlerTaskType;
    case TASK_TYPE_FILE_HANDLER:
      return kFileHandlerTaskType;
    case TASK_TYPE_DRIVE_APP:
      return kDriveAppTaskType;
    case TASK_TYPE_ARC_APP:
      return kArcAppTaskType;
    case TASK_TYPE_UNKNOWN:
    case NUM_TASK_TYPE:
      break;
  }
  NOTREACHED();
  return "";
}

// Converts a string to a TaskType. Returns TASK_TYPE_UNKNOWN on error.
TaskType StringToTaskType(const std::string& str) {
  if (str == kFileBrowserHandlerTaskType)
    return TASK_TYPE_FILE_BROWSER_HANDLER;
  if (str == kFileHandlerTaskType)
    return TASK_TYPE_FILE_HANDLER;
  if (str == kDriveAppTaskType)
    return TASK_TYPE_DRIVE_APP;
  if (str == kArcAppTaskType)
    return TASK_TYPE_ARC_APP;
  return TASK_TYPE_UNKNOWN;
}

// Legacy Drive task extension prefix, used by CrackTaskID.
const char kDriveTaskExtensionPrefix[] = "drive-app:";
const size_t kDriveTaskExtensionPrefixLength =
    arraysize(kDriveTaskExtensionPrefix) - 1;

// Returns true if path_mime_set contains a Google document.
bool ContainsGoogleDocument(const std::vector<extensions::EntryInfo>& entries) {
  for (const auto& it : entries) {
    if (drive::util::HasHostedDocumentExtension(it.path))
      return true;
  }
  return false;
}

// Leaves tasks handled by the file manger itself as is and removes all others.
void KeepOnlyFileManagerInternalTasks(std::vector<FullTaskDescriptor>* tasks) {
  std::vector<FullTaskDescriptor> filtered;
  for (size_t i = 0; i < tasks->size(); ++i) {
    if ((*tasks)[i].task_descriptor().app_id == kFileManagerAppId)
      filtered.push_back((*tasks)[i]);
  }
  tasks->swap(filtered);
}

// Returns true if the given task is a handler by built-in apps like the Files
// app itself or QuickOffice etc. They are used as the initial default app.
bool IsFallbackFileHandler(const file_tasks::TaskDescriptor& task) {
  if (task.task_type != file_tasks::TASK_TYPE_FILE_BROWSER_HANDLER &&
      task.task_type != file_tasks::TASK_TYPE_FILE_HANDLER)
    return false;

  const char* const kBuiltInApps[] = {
      kFileManagerAppId, kVideoPlayerAppId, kGalleryAppId, kTextEditorAppId,
  };

  for (size_t i = 0; i < arraysize(kBuiltInApps); ++i) {
    if (task.app_id == kBuiltInApps[i])
      return true;
  }
  return false;
}

// Gets the profile in which a file task owned by |extension| should be
// launched - for example, it makes sure that a file task is not handled in OTR
// profile for platform apps (outside a guest session).
Profile* GetProfileForExtensionTask(Profile* profile,
                                    const extensions::Extension& extension) {
  // In guest profile, all available task handlers are in OTR profile.
  if (profile->IsGuestSession()) {
    DCHECK(profile->IsOffTheRecord());
    return profile;
  }

  // Outside guest sessions, if the task is handled by a platform app, launch
  // the handler in the original profile.
  if (extension.is_platform_app())
    return profile->GetOriginalProfile();
  return profile;
}

void ExecuteByArcAfterMimeTypesCollected(
    Profile* profile,
    const TaskDescriptor& task,
    const std::vector<FileSystemURL>& file_urls,
    const FileTaskFinishedCallback& done,
    extensions::app_file_handler_util::MimeTypeCollector* mime_collector,
    std::unique_ptr<std::vector<std::string>> mime_types) {
  if (ExecuteArcTask(profile, task, file_urls, *mime_types)) {
    done.Run(extensions::api::file_manager_private::TASK_RESULT_MESSAGE_SENT);
  } else {
    done.Run(extensions::api::file_manager_private::TASK_RESULT_FAILED);
  }
}

void PostProcessFoundTasks(
    Profile* profile,
    const std::vector<extensions::EntryInfo>& entries,
    const FindTasksCallback& callback,
    std::unique_ptr<std::vector<FullTaskDescriptor>> result_list) {
  // Google documents can only be handled by internal handlers.
  if (ContainsGoogleDocument(entries))
    KeepOnlyFileManagerInternalTasks(result_list.get());
  ChooseAndSetDefaultTask(*profile->GetPrefs(), entries, result_list.get());
  callback.Run(std::move(result_list));
}

}  // namespace

FullTaskDescriptor::FullTaskDescriptor(const TaskDescriptor& task_descriptor,
                                       const std::string& task_title,
                                       const Verb task_verb,
                                       const GURL& icon_url,
                                       bool is_default,
                                       bool is_generic_file_handler)
    : task_descriptor_(task_descriptor),
      task_title_(task_title),
      task_verb_(task_verb),
      icon_url_(icon_url),
      is_default_(is_default),
      is_generic_file_handler_(is_generic_file_handler) {}

FullTaskDescriptor::~FullTaskDescriptor() {}

FullTaskDescriptor::FullTaskDescriptor(const FullTaskDescriptor& other) =
    default;

void UpdateDefaultTask(PrefService* pref_service,
                       const std::string& task_id,
                       const std::set<std::string>& suffixes,
                       const std::set<std::string>& mime_types) {
  if (!pref_service)
    return;

  if (!mime_types.empty()) {
    DictionaryPrefUpdate mime_type_pref(pref_service,
                                        prefs::kDefaultTasksByMimeType);
    for (std::set<std::string>::const_iterator iter = mime_types.begin();
        iter != mime_types.end(); ++iter) {
      mime_type_pref->SetWithoutPathExpansion(
          *iter, std::make_unique<base::Value>(task_id));
    }
  }

  if (!suffixes.empty()) {
    DictionaryPrefUpdate mime_type_pref(pref_service,
                                        prefs::kDefaultTasksBySuffix);
    for (std::set<std::string>::const_iterator iter = suffixes.begin();
        iter != suffixes.end(); ++iter) {
      // Suffixes are case insensitive.
      std::string lower_suffix = base::ToLowerASCII(*iter);
      mime_type_pref->SetWithoutPathExpansion(
          lower_suffix, std::make_unique<base::Value>(task_id));
    }
  }
}

std::string GetDefaultTaskIdFromPrefs(const PrefService& pref_service,
                                      const std::string& mime_type,
                                      const std::string& suffix) {
  VLOG(1) << "Looking for default for MIME type: " << mime_type
      << " and suffix: " << suffix;
  std::string task_id;
  if (!mime_type.empty()) {
    const base::DictionaryValue* mime_task_prefs =
        pref_service.GetDictionary(prefs::kDefaultTasksByMimeType);
    DCHECK(mime_task_prefs);
    LOG_IF(ERROR, !mime_task_prefs) << "Unable to open MIME type prefs";
    if (mime_task_prefs &&
        mime_task_prefs->GetStringWithoutPathExpansion(mime_type, &task_id)) {
      VLOG(1) << "Found MIME default handler: " << task_id;
      return task_id;
    }
  }

  const base::DictionaryValue* suffix_task_prefs =
      pref_service.GetDictionary(prefs::kDefaultTasksBySuffix);
  DCHECK(suffix_task_prefs);
  LOG_IF(ERROR, !suffix_task_prefs) << "Unable to open suffix prefs";
  std::string lower_suffix = base::ToLowerASCII(suffix);
  if (suffix_task_prefs)
    suffix_task_prefs->GetStringWithoutPathExpansion(lower_suffix, &task_id);
  VLOG_IF(1, !task_id.empty()) << "Found suffix default handler: " << task_id;
  return task_id;
}

std::string MakeTaskID(const std::string& app_id,
                       TaskType task_type,
                       const std::string& action_id) {
  return base::StringPrintf("%s|%s|%s",
                            app_id.c_str(),
                            TaskTypeToString(task_type).c_str(),
                            action_id.c_str());
}

std::string TaskDescriptorToId(const TaskDescriptor& task_descriptor) {
  return MakeTaskID(task_descriptor.app_id,
                    task_descriptor.task_type,
                    task_descriptor.action_id);
}

bool ParseTaskID(const std::string& task_id, TaskDescriptor* task) {
  DCHECK(task);

  std::vector<std::string> result = base::SplitString(
      task_id, "|", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY);

  // Parse a legacy task ID that only contain two parts. Drive tasks are
  // identified by a prefix "drive-app:" on the extension ID. The legacy task
  // IDs can be stored in preferences.
  if (result.size() == 2) {
    if (base::StartsWith(result[0], kDriveTaskExtensionPrefix,
                         base::CompareCase::SENSITIVE)) {
      task->task_type = TASK_TYPE_DRIVE_APP;
      task->app_id = result[0].substr(kDriveTaskExtensionPrefixLength);
    } else {
      task->task_type = TASK_TYPE_FILE_BROWSER_HANDLER;
      task->app_id = result[0];
    }

    task->action_id = result[1];

    return true;
  }

  if (result.size() != 3)
    return false;

  TaskType task_type = StringToTaskType(result[1]);
  if (task_type == TASK_TYPE_UNKNOWN)
    return false;

  task->app_id = result[0];
  task->task_type = task_type;
  task->action_id = result[2];

  return true;
}

bool ExecuteFileTask(Profile* profile,
                     const GURL& source_url,
                     const TaskDescriptor& task,
                     const std::vector<FileSystemURL>& file_urls,
                     const FileTaskFinishedCallback& done) {
  UMA_HISTOGRAM_ENUMERATION("FileBrowser.ViewingTaskType", task.task_type,
                            NUM_TASK_TYPE);

  // ARC apps needs mime types for launching. Retrieve them first.
  if (task.task_type == TASK_TYPE_ARC_APP) {
    extensions::app_file_handler_util::MimeTypeCollector* mime_collector =
        new extensions::app_file_handler_util::MimeTypeCollector(profile);
    mime_collector->CollectForURLs(
        file_urls,
        base::Bind(&ExecuteByArcAfterMimeTypesCollected, profile, task,
                   file_urls, done, base::Owned(mime_collector)));
    return true;
  }

  // drive::FileTaskExecutor is responsible to handle drive tasks.
  if (task.task_type == TASK_TYPE_DRIVE_APP) {
    DCHECK_EQ(kDriveAppActionID, task.action_id);
    drive::FileTaskExecutor* executor =
        new drive::FileTaskExecutor(profile, task.app_id);
    executor->Execute(file_urls, done);
    return true;
  }

  // Get the extension.
  const Extension* extension = extensions::ExtensionRegistry::Get(
      profile)->enabled_extensions().GetByID(task.app_id);
  if (!extension)
    return false;

  Profile* extension_task_profile =
      GetProfileForExtensionTask(profile, *extension);

  // Execute the task.
  if (task.task_type == TASK_TYPE_FILE_BROWSER_HANDLER) {
    return file_browser_handlers::ExecuteFileBrowserHandler(
        extension_task_profile, extension, task.action_id, file_urls, done);
  } else if (task.task_type == TASK_TYPE_FILE_HANDLER) {
    std::vector<base::FilePath> paths;
    for (size_t i = 0; i != file_urls.size(); ++i)
      paths.push_back(file_urls[i].path());
    apps::LaunchPlatformAppWithFileHandler(extension_task_profile, extension,
                                           task.action_id, paths);
    if (!done.is_null())
      done.Run(extensions::api::file_manager_private::TASK_RESULT_MESSAGE_SENT);
    return true;
  }
  NOTREACHED();
  return false;
}

void FindDriveAppTasks(const drive::DriveAppRegistry& drive_app_registry,
                       const std::vector<extensions::EntryInfo>& entries,
                       std::vector<FullTaskDescriptor>* result_list) {
  DCHECK(result_list);

  bool is_first = true;
  typedef std::map<std::string, drive::DriveAppInfo> DriveAppInfoMap;
  DriveAppInfoMap drive_app_map;

  for (std::vector<extensions::EntryInfo>::const_iterator it = entries.begin();
       it != entries.end(); ++it) {
    const base::FilePath& file_path = it->path;
    const std::string& mime_type = it->mime_type;
    // Return immediately if a file not on Drive is found, as Drive app tasks
    // work only if all files are on Drive.
    if (!drive::util::IsUnderDriveMountPoint(file_path))
      return;

    std::vector<drive::DriveAppInfo> app_info_list;
    drive_app_registry.GetAppsForFile(file_path.Extension(),
                                      mime_type,
                                      &app_info_list);

    if (is_first) {
      // For the first file, we store all the info.
      for (size_t j = 0; j < app_info_list.size(); ++j)
        drive_app_map[app_info_list[j].app_id] = app_info_list[j];
    } else {
      // For remaining files, take the intersection with the current
      // result, based on the app id.
      std::set<std::string> app_id_set;
      for (size_t j = 0; j < app_info_list.size(); ++j)
        app_id_set.insert(app_info_list[j].app_id);
      for (DriveAppInfoMap::iterator iter = drive_app_map.begin();
           iter != drive_app_map.end();) {
        if (app_id_set.count(iter->first) == 0) {
          drive_app_map.erase(iter++);
        } else {
          ++iter;
        }
      }
    }

    is_first = false;
  }

  for (DriveAppInfoMap::const_iterator iter = drive_app_map.begin();
       iter != drive_app_map.end(); ++iter) {
    const drive::DriveAppInfo& app_info = iter->second;
    TaskDescriptor descriptor(app_info.app_id,
                              TASK_TYPE_DRIVE_APP,
                              kDriveAppActionID);
    GURL icon_url = drive::util::FindPreferredIcon(
        app_info.app_icons,
        drive::util::kPreferredIconSize);

    result_list->push_back(FullTaskDescriptor(
        descriptor, app_info.app_name, Verb::VERB_OPEN_WITH, icon_url,
        false /* is_default */, false /* is_generic_file_handler */));
  }
}

bool IsGoodMatchFileHandler(
    const extensions::FileHandlerInfo& file_handler_info,
    const std::vector<extensions::EntryInfo>& entries) {
  if (file_handler_info.extensions.count("*") > 0 ||
      file_handler_info.types.count("*") > 0 ||
      file_handler_info.types.count("*/*") > 0)
    return false;

  // If text/* file handler matches with unsupported text mime type, we don't
  // regard it as good match.
  if (file_handler_info.types.count("text/*")) {
    for (const auto& entry : entries) {
      if (blink::IsUnsupportedTextMimeType(entry.mime_type))
        return false;
    }
  }

  // We consider it a good match if no directories are selected.
  for (const auto& entry : entries) {
    if (entry.is_directory)
      return false;
  }
  return true;
}

void FindFileHandlerTasks(Profile* profile,
                          const std::vector<extensions::EntryInfo>& entries,
                          std::vector<FullTaskDescriptor>* result_list) {
  DCHECK(!entries.empty());
  DCHECK(result_list);

  const extensions::ExtensionSet& enabled_extensions =
      extensions::ExtensionRegistry::Get(profile)->enabled_extensions();

  for (extensions::ExtensionSet::const_iterator iter =
           enabled_extensions.begin();
       iter != enabled_extensions.end();
       ++iter) {
    const Extension* extension = iter->get();

    // Check that the extension can be launched via an event. This includes all
    // platform apps plus whitelisted extensions.
    if (!CanLaunchViaEvent(extension))
      continue;

    if (profile->IsOffTheRecord() &&
        !extensions::util::IsIncognitoEnabled(extension->id(), profile))
      continue;

    typedef std::vector<const extensions::FileHandlerInfo*> FileHandlerList;
    FileHandlerList file_handlers =
        FindFileHandlersForEntries(*extension, entries);
    if (file_handlers.empty())
      continue;

    // If the new ZIP unpacker is disabled, then hide its handlers, so we don't
    // show both the legacy one and the new one in Files app for ZIP files.
    if (extension->id() == extension_misc::kZIPUnpackerExtensionId &&
        base::CommandLine::ForCurrentProcess()->HasSwitch(
            chromeos::switches::kDisableNewZIPUnpacker)) {
      continue;
    }

    // A map which has as key a handler verb, and as value a pair of the
    // handler with which to open the given entries and a boolean marking
    // if the handler is a good match.
    std::map<std::string, std::pair<const extensions::FileHandlerInfo*, bool>>
        handlers_for_entries;
    // Show the first good matching handler of each verb supporting the given
    // entries that corresponds to the app. If there doesn't exist such handler,
    // show the first matching handler of the verb.
    for (const extensions::FileHandlerInfo* handler : file_handlers) {
      bool good_match = IsGoodMatchFileHandler(*handler, entries);
      auto it = handlers_for_entries.find(handler->verb);
      if (it == handlers_for_entries.end() ||
          (!it->second.second /* existing handler not a good match */ &&
           good_match)) {
        handlers_for_entries[handler->verb] =
            std::make_pair(handler, good_match);
      }
    }

    for (const auto& entry : handlers_for_entries) {
      const extensions::FileHandlerInfo* handler = entry.second.first;
      std::string task_id = file_tasks::MakeTaskID(
          extension->id(), file_tasks::TASK_TYPE_FILE_HANDLER, handler->id);

      GURL best_icon = extensions::ExtensionIconSource::GetIconURL(
          extension, drive::util::kPreferredIconSize,
          ExtensionIconSet::MATCH_BIGGER,
          false);  // grayscale

      // If file handler doesn't match as good match, regards it as generic file
      // handler.
      const bool is_generic_file_handler =
          !IsGoodMatchFileHandler(*handler, entries);
      Verb verb;
      if (handler->verb == extensions::file_handler_verbs::kAddTo) {
        verb = Verb::VERB_ADD_TO;
      } else if (handler->verb == extensions::file_handler_verbs::kPackWith) {
        verb = Verb::VERB_PACK_WITH;
      } else if (handler->verb == extensions::file_handler_verbs::kShareWith) {
        verb = Verb::VERB_SHARE_WITH;
      } else {
        // Only kOpenWith is a valid remaining verb. Invalid verbs should fall
        // back to it.
        DCHECK(handler->verb == extensions::file_handler_verbs::kOpenWith);
        verb = Verb::VERB_OPEN_WITH;
      }

      result_list->push_back(FullTaskDescriptor(
          TaskDescriptor(extension->id(), file_tasks::TASK_TYPE_FILE_HANDLER,
                         handler->id),
          extension->name(), verb, best_icon, false /* is_default */,
          is_generic_file_handler));
    }
  }
}

void FindFileBrowserHandlerTasks(
    Profile* profile,
    const std::vector<GURL>& file_urls,
    std::vector<FullTaskDescriptor>* result_list) {
  DCHECK(!file_urls.empty());
  DCHECK(result_list);

  file_browser_handlers::FileBrowserHandlerList common_tasks =
      file_browser_handlers::FindFileBrowserHandlers(profile, file_urls);
  if (common_tasks.empty())
    return;

  const extensions::ExtensionSet& enabled_extensions =
      extensions::ExtensionRegistry::Get(profile)->enabled_extensions();
  for (file_browser_handlers::FileBrowserHandlerList::const_iterator iter =
           common_tasks.begin();
       iter != common_tasks.end();
       ++iter) {
    const FileBrowserHandler* handler = *iter;
    const std::string extension_id = handler->extension_id();
    const Extension* extension = enabled_extensions.GetByID(extension_id);
    DCHECK(extension);

    // TODO(zelidrag): Figure out how to expose icon URL that task defined in
    // manifest instead of the default extension icon.
    const GURL icon_url = extensions::ExtensionIconSource::GetIconURL(
        extension, extension_misc::EXTENSION_ICON_SMALL,
        ExtensionIconSet::MATCH_BIGGER,
        false);  // grayscale

    result_list->push_back(FullTaskDescriptor(
        TaskDescriptor(extension_id, file_tasks::TASK_TYPE_FILE_BROWSER_HANDLER,
                       handler->id()),
        handler->title(), Verb::VERB_NONE /* no verb for FileBrowserHandler */,
        icon_url, false /* is_default */, false /* is_generic_file_handler */));
  }
}

void FindExtensionAndAppTasks(
    Profile* profile,
    const std::vector<extensions::EntryInfo>& entries,
    const std::vector<GURL>& file_urls,
    const FindTasksCallback& callback,
    std::unique_ptr<std::vector<FullTaskDescriptor>> result_list) {
  // 3. Continues from FindAllTypesOfTasks. Find and append file handler tasks.
  FindFileHandlerTasks(profile, entries, result_list.get());

  // 4. Find and append file browser handler tasks. We know there aren't
  // duplicates because "file_browser_handlers" and "file_handlers" shouldn't
  // be used in the same manifest.json.
  FindFileBrowserHandlerTasks(profile, file_urls, result_list.get());

  // Done. Apply post-filtering and callback.
  PostProcessFoundTasks(profile, entries, callback, std::move(result_list));
}

void FindAllTypesOfTasks(Profile* profile,
                         const drive::DriveAppRegistry* drive_app_registry,
                         const std::vector<extensions::EntryInfo>& entries,
                         const std::vector<GURL>& file_urls,
                         const FindTasksCallback& callback) {
  DCHECK(profile);
  std::unique_ptr<std::vector<FullTaskDescriptor>> result_list(
      new std::vector<FullTaskDescriptor>);

  // 1. Find Drive app tasks, if the drive app registry is present.
  if (drive_app_registry)
    FindDriveAppTasks(*drive_app_registry, entries, result_list.get());

  // 2. Find and append ARC handler tasks.
  FindArcTasks(profile, entries, std::move(result_list),
               base::Bind(&FindExtensionAndAppTasks, profile, entries,
                          file_urls, callback));
}

void ChooseAndSetDefaultTask(const PrefService& pref_service,
                             const std::vector<extensions::EntryInfo>& entries,
                             std::vector<FullTaskDescriptor>* tasks) {
  // Collect the task IDs of default tasks from the preferences into a set.
  std::set<std::string> default_task_ids;
  for (std::vector<extensions::EntryInfo>::const_iterator it = entries.begin();
       it != entries.end(); ++it) {
    const base::FilePath& file_path = it->path;
    const std::string& mime_type = it->mime_type;
    std::string task_id = file_tasks::GetDefaultTaskIdFromPrefs(
        pref_service, mime_type, file_path.Extension());
    default_task_ids.insert(task_id);
  }

  // Go through all the tasks from the beginning and see if there is any
  // default task. If found, pick and set it as default and return.
  for (size_t i = 0; i < tasks->size(); ++i) {
    FullTaskDescriptor* task = &tasks->at(i);
    DCHECK(!task->is_default());
    const std::string task_id = TaskDescriptorToId(task->task_descriptor());
    if (base::ContainsKey(default_task_ids, task_id)) {
      task->set_is_default(true);
      return;
    }
  }

  // No default tasks found. If there is any fallback file browser handler,
  // make it as default task, so it's selected by default.
  for (size_t i = 0; i < tasks->size(); ++i) {
    FullTaskDescriptor* task = &tasks->at(i);
    DCHECK(!task->is_default());
    if (IsFallbackFileHandler(task->task_descriptor())) {
      task->set_is_default(true);
      return;
    }
  }
}

}  // namespace file_tasks
}  // namespace file_manager
