1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Use of this source code is governed by a BSD-style license that can be
3ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// found in the LICENSE file.
4ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
5ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/extensions/extension_file_browser_private_api.h"
6ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
7ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/base64.h"
8ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/command_line.h"
9ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/json/json_writer.h"
10ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/logging.h"
11ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/singleton.h"
12ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/stringprintf.h"
13ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/string_util.h"
14ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/task.h"
15ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/time.h"
16ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/values.h"
17ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/profiles/profile.h"
18ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/extensions/extension_event_router.h"
19ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/extensions/extension_function_dispatcher.h"
20ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/extensions/extension_process_manager.h"
21ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/extensions/extension_service.h"
22ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/extensions/extension_tabs_module.h"
23ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/extensions/file_manager_util.h"
24ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/prefs/pref_service.h"
25ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/prefs/scoped_user_pref_update.h"
26ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/ui/browser.h"
27ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/ui/views/html_dialog_view.h"
28ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/ui/webui/extension_icon_source.h"
29ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/common/chrome_switches.h"
30ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/common/extensions/extension.h"
31ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/common/extensions/file_browser_handler.h"
32ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/common/pref_names.h"
33ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/browser/browser_thread.h"
34ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/browser/child_process_security_policy.h"
35ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/browser/renderer_host/render_process_host.h"
36ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/browser/renderer_host/render_view_host.h"
37ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/browser/tab_contents/tab_contents.h"
38ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "googleurl/src/gurl.h"
39ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "grit/generated_resources.h"
40ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "webkit/fileapi/file_system_context.h"
41ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "webkit/fileapi/file_system_mount_point_provider.h"
42ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "webkit/fileapi/file_system_operation.h"
43ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "webkit/fileapi/file_system_operation_context.h"
44ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "webkit/fileapi/file_system_path_manager.h"
45ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "webkit/fileapi/file_system_types.h"
46ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "webkit/fileapi/file_system_util.h"
47ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "webkit/fileapi/file_system_file_util.h"
48ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "webkit/fileapi/local_file_system_file_util.h"
49ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "ui/base/l10n/l10n_util.h"
50ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
51ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Error messages.
52ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenconst char kFileError[] = "File error %d";
53ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenconst char kInvalidFileUrl[] = "Invalid file URL";
54ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
55ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Internal task ids.
56ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenconst char kEnqueueTaskId[] = "enqueue";
57ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
58ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenconst int kReadOnlyFilePermissions = base::PLATFORM_FILE_OPEN |
59ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                     base::PLATFORM_FILE_READ |
60ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                     base::PLATFORM_FILE_EXCLUSIVE_READ |
61ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                     base::PLATFORM_FILE_ASYNC;
62ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
63ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenconst int kReadWriteFilePermissions = base::PLATFORM_FILE_OPEN |
64ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                      base::PLATFORM_FILE_CREATE |
65ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                      base::PLATFORM_FILE_OPEN_ALWAYS |
66ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                      base::PLATFORM_FILE_CREATE_ALWAYS |
67ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                      base::PLATFORM_FILE_READ |
68ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                      base::PLATFORM_FILE_WRITE |
69ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                      base::PLATFORM_FILE_EXCLUSIVE_READ |
70ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                      base::PLATFORM_FILE_EXCLUSIVE_WRITE |
71ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                      base::PLATFORM_FILE_ASYNC |
72ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                      base::PLATFORM_FILE_TRUNCATE |
73ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                      base::PLATFORM_FILE_WRITE_ATTRIBUTES;
74ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
75ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsentypedef std::pair<int, const FileBrowserHandler* > LastUsedHandler;
76ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsentypedef std::vector<LastUsedHandler> LastUsedHandlerList;
77ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
78ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsentypedef std::vector<const FileBrowserHandler*> ActionList;
79ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
80ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
81ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Breaks down task_id that is used between getFileTasks() and executeTask() on
82ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// its building blocks. task_id field the following structure:
83ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen//     <extension-id>|<task-action-id>
84ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Currently, the only supported task-type is of 'context'.
85ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool CrackTaskIdentifier(const std::string& task_id,
86ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                         std::string* target_extension_id,
87ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                         std::string* action_id) {
88ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  std::vector<std::string> result;
89ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  int count = Tokenize(task_id, std::string("|"), &result);
90ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (count != 2)
91ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return false;
92ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  *target_extension_id = result[0];
93ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  *action_id = result[1];
94ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return true;
95ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
96ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
97ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenstd::string MakeTaskID(const char* extension_id,
98ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                       const char*  action_id) {
99ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return base::StringPrintf("%s|%s", extension_id, action_id);
100ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
101ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
102ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool GetFileBrowserHandlers(Profile* profile,
103ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                           const GURL& selected_file_url,
104ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                           ActionList* results) {
105ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ExtensionService* service = profile->GetExtensionService();
106ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!service)
107ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return false;  // In unit-tests, we may not have an ExtensionService.
108ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
109ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  for (ExtensionList::const_iterator iter = service->extensions()->begin();
110ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen       iter != service->extensions()->end();
111ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen       ++iter) {
112ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const Extension* extension = iter->get();
113ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (!extension->file_browser_handlers())
114ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      continue;
115ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
116ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    for (Extension::FileBrowserHandlerList::const_iterator action_iter =
117ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen             extension->file_browser_handlers()->begin();
118ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        action_iter != extension->file_browser_handlers()->end();
119ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        ++action_iter) {
120ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      const FileBrowserHandler* action = action_iter->get();
121ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      if (!action->MatchesURL(selected_file_url))
122ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        continue;
123ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
124ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      results->push_back(action_iter->get());
125ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
126ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
127ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return true;
128ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
129ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
130ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool SortByLastUsedTimestampDesc(const LastUsedHandler& a,
131ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                 const LastUsedHandler& b) {
132ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return a.first > b.first;
133ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
134ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
135ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// TODO(zelidrag): Wire this with ICU to make this sort I18N happy.
136ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool SortByTaskName(const LastUsedHandler& a, const LastUsedHandler& b) {
137ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return base::strcasecmp(a.second->title().data(),
138ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                          b.second->title().data()) > 0;
139ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
140ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
141ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Given the list of selected files, returns array of context menu tasks
142ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// that are shared
143ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool FindCommonTasks(Profile* profile,
144ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                     ListValue* files_list,
145ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                     LastUsedHandlerList* named_action_list) {
146ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  named_action_list->clear();
147ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ActionList common_tasks;
148ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  for (size_t i = 0; i < files_list->GetSize(); ++i) {
149ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    std::string file_url;
150ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (!files_list->GetString(i, &file_url))
151ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      return false;
152ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
153ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    ActionList file_actions;
154ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (!GetFileBrowserHandlers(profile, GURL(file_url), &file_actions))
155ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      return false;
156ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // If there is nothing to do for one file, the intersection of tasks for all
157ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // files will be empty at the end.
158ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (!file_actions.size()) {
159ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      common_tasks.clear();
160ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      return true;
161ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
162ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // For the very first file, just copy elements.
163ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (i == 0) {
164ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      common_tasks.insert(common_tasks.begin(),
165ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                          file_actions.begin(),
166ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                          file_actions.end());
167ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      std::sort(common_tasks.begin(), common_tasks.end());
168ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    } else if (common_tasks.size()) {
169ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      // For all additional files, find intersection between the accumulated
170ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      // and file specific set.
171ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      std::sort(file_actions.begin(), file_actions.end());
172ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      ActionList intersection(common_tasks.size());
173ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      ActionList::iterator intersection_end =
174ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          std::set_intersection(common_tasks.begin(),
175ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                common_tasks.end(),
176ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                file_actions.begin(),
177ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                file_actions.end(),
178ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                intersection.begin());
179ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      common_tasks.clear();
180ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      common_tasks.insert(common_tasks.begin(),
181ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                          intersection.begin(),
182ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                          intersection_end);
183ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      std::sort(common_tasks.begin(), common_tasks.end());
184ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
185ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
186ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
187ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  const DictionaryValue* prefs_tasks =
188ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      profile->GetPrefs()->GetDictionary(prefs::kLastUsedFileBrowserHandlers);
189ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  for (ActionList::const_iterator iter = common_tasks.begin();
190ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen       iter != common_tasks.end(); ++iter) {
191ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // Get timestamp of when this task was used last time.
192ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    int last_used_timestamp = 0;
193ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    prefs_tasks->GetInteger(MakeTaskID((*iter)->extension_id().data(),
194ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                       (*iter)->id().data()),
195ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                             &last_used_timestamp);
196ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    named_action_list->push_back(LastUsedHandler(last_used_timestamp, *iter));
197ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
198ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Sort by the last used descending.
199ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  std::sort(named_action_list->begin(), named_action_list->end(),
200ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen            SortByLastUsedTimestampDesc);
201ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (named_action_list->size() > 1) {
202ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // Sort the rest by name.
203ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    std::sort(named_action_list->begin() + 1, named_action_list->end(),
204ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen              SortByTaskName);
205ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
206ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return true;
207ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
208ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
209ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Update file handler usage stats.
210ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid UpdateFileHandlerUsageStats(Profile* profile, const std::string& task_id) {
211ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!profile || !profile->GetPrefs())
212ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return;
213ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DictionaryPrefUpdate prefs_usage_update(profile->GetPrefs(),
214ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      prefs::kLastUsedFileBrowserHandlers);
215ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  prefs_usage_update->SetWithoutPathExpansion(task_id,
216ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      new FundamentalValue(
217ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          static_cast<int>(base::Time::Now().ToInternalValue()/
218ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                           base::Time::kMicrosecondsPerSecond)));
219ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
220ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
221ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
222ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenclass LocalFileSystemCallbackDispatcher
223ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    : public fileapi::FileSystemCallbackDispatcher {
224ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen public:
225ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  explicit LocalFileSystemCallbackDispatcher(
226ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      RequestLocalFileSystemFunction* function,
227ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      Profile* profile,
228ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      int child_id,
229ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      scoped_refptr<const Extension> extension)
230ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      : function_(function),
231ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        profile_(profile),
232ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        child_id_(child_id),
233ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        extension_(extension)  {
234ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    DCHECK(function_);
235ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
236ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
237ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // fileapi::FileSystemCallbackDispatcher overrides.
238ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  virtual void DidSucceed() OVERRIDE {
239ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    NOTREACHED();
240ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
241ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
242ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  virtual void DidGetLocalPath(const FilePath& local_path) {
243ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    NOTREACHED();
244ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
245ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
246ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  virtual void DidReadMetadata(const base::PlatformFileInfo& info,
247ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                               const FilePath& unused) OVERRIDE {
248ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    NOTREACHED();
249ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
250ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
251ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  virtual void DidReadDirectory(
252ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      const std::vector<base::FileUtilProxy::Entry>& entries,
253ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      bool has_more) OVERRIDE {
254ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    NOTREACHED();
255ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
256ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
257ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  virtual void DidWrite(int64 bytes, bool complete) OVERRIDE {
258ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    NOTREACHED();
259ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
260ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
261ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  virtual void DidOpenFileSystem(const std::string& name,
262ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                 const GURL& root_path) OVERRIDE {
263ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
264ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // Set up file permission access.
265ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (!SetupFileSystemAccessPermissions()) {
266ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      DidFail(base::PLATFORM_FILE_ERROR_SECURITY);
267ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      return;
268ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
269ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
270ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    BrowserThread::PostTask(
271ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        BrowserThread::UI, FROM_HERE,
272ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        NewRunnableMethod(function_,
273ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen            &RequestLocalFileSystemFunction::RespondSuccessOnUIThread,
274ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen            name,
275ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen            root_path));
276ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
277ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
278ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  virtual void DidFail(base::PlatformFileError error_code) OVERRIDE {
279ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    BrowserThread::PostTask(
280ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        BrowserThread::UI, FROM_HERE,
281ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        NewRunnableMethod(function_,
282ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen            &RequestLocalFileSystemFunction::RespondFailedOnUIThread,
283ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen            error_code));
284ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
285ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
286ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen private:
287ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
288ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Grants file system access permissions to file browser component.
289ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  bool SetupFileSystemAccessPermissions() {
290ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (!extension_.get())
291ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      return false;
292ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
293ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // Make sure that only component extension can access the entire
294ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // local file system.
295ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (extension_->location() != Extension::COMPONENT
296ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#ifndef NDEBUG
297ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      && !CommandLine::ForCurrentProcess()->HasSwitch(
298ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          switches::kExposePrivateExtensionApi)
299ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#endif
300ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        ) {
301ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      NOTREACHED() << "Private method access by non-component extension "
302ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                   << extension_->id();
303ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      return false;
304ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
305ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
306ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    fileapi::FileSystemPathManager* path_manager =
307ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        profile_->GetFileSystemContext()->path_manager();
308ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    fileapi::ExternalFileSystemMountPointProvider* provider =
309ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        path_manager->external_provider();
310ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (!provider)
311ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      return false;
312ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
313ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // Grant full access to File API from this component extension.
314ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    provider->GrantFullAccessToExtension(extension_->id());
315ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
316ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // Grant R/W file permissions to the renderer hosting component
317ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // extension for all paths exposed by our local file system provider.
318ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    std::vector<FilePath> root_dirs = provider->GetRootDirectories();
319ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    for (std::vector<FilePath>::iterator iter = root_dirs.begin();
320ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen         iter != root_dirs.end();
321ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen         ++iter) {
322ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      ChildProcessSecurityPolicy::GetInstance()->GrantPermissionsForFile(
323ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          child_id_, *iter, kReadWriteFilePermissions);
324ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
325ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return true;
326ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
327ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
328ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  RequestLocalFileSystemFunction* function_;
329ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  Profile* profile_;
330ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Renderer process id.
331ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  int child_id_;
332ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Extension source URL.
333ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  scoped_refptr<const Extension> extension_;
334ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DISALLOW_COPY_AND_ASSIGN(LocalFileSystemCallbackDispatcher);
335ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen};
336ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
337ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid RequestLocalFileSystemFunction::RequestOnFileThread(
338ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const GURL& source_url, int child_id) {
339ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  fileapi::FileSystemOperation* operation =
340ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      new fileapi::FileSystemOperation(
341ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          new LocalFileSystemCallbackDispatcher(
342ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen              this,
343ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen              profile(),
344ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen              child_id,
345ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen              GetExtension()),
346ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE),
347ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          profile()->GetFileSystemContext(),
348ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          NULL);
349ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  GURL origin_url = source_url.GetOrigin();
350ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  operation->OpenFileSystem(origin_url, fileapi::kFileSystemTypeExternal,
351ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                            false);     // create
352ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
353ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
354ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool RequestLocalFileSystemFunction::RunImpl() {
355ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!dispatcher() || !dispatcher()->render_view_host() ||
356ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      !dispatcher()->render_view_host()->process())
357ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return false;
358ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
359ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  BrowserThread::PostTask(
360ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      BrowserThread::FILE, FROM_HERE,
361ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      NewRunnableMethod(this,
362ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          &RequestLocalFileSystemFunction::RequestOnFileThread,
363ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          source_url_,
364ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          dispatcher()->render_view_host()->process()->id()));
365ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Will finish asynchronously.
366ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return true;
367ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
368ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
369ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid RequestLocalFileSystemFunction::RespondSuccessOnUIThread(
370ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const std::string& name, const GURL& root_path) {
371ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
372ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  result_.reset(new DictionaryValue());
373ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DictionaryValue* dict = reinterpret_cast<DictionaryValue*>(result_.get());
374ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  dict->SetString("name", name);
375ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  dict->SetString("path", root_path.spec());
376ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  dict->SetInteger("error", base::PLATFORM_FILE_OK);
377ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  SendResponse(true);
378ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
379ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
380ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid RequestLocalFileSystemFunction::RespondFailedOnUIThread(
381ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    base::PlatformFileError error_code) {
382ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
383ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  error_ = base::StringPrintf(kFileError, static_cast<int>(error_code));
384ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  SendResponse(false);
385ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
386ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
387ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool GetFileTasksFileBrowserFunction::RunImpl() {
388ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ListValue* files_list = NULL;
389ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!args_->GetList(0, &files_list))
390ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return false;
391ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
392ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ListValue* result_list = new ListValue();
393ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  result_.reset(result_list);
394ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
395ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  LastUsedHandlerList common_tasks;
396ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!FindCommonTasks(profile_, files_list, &common_tasks))
397ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return false;
398ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
399ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ExtensionService* service = profile_->GetExtensionService();
400ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  for (LastUsedHandlerList::const_iterator iter = common_tasks.begin();
401ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen       iter != common_tasks.end();
402ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen       ++iter) {
403ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const std::string extension_id = iter->second->extension_id();
404ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const Extension* extension = service->GetExtensionById(extension_id, false);
405ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    CHECK(extension);
406ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    DictionaryValue* task = new DictionaryValue();
407ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    task->SetString("taskId", MakeTaskID(extension_id.data(),
408ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                         iter->second->id().data()));
409ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    task->SetString("title", iter->second->title());
410ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // TODO(zelidrag): Figure out how to expose icon URL that task defined in
411ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // manifest instead of the default extension icon.
412ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    GURL icon =
413ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        ExtensionIconSource::GetIconURL(extension,
414ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                        Extension::EXTENSION_ICON_BITTY,
415ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                        ExtensionIconSet::MATCH_BIGGER,
416ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                        false);     // grayscale
417ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    task->SetString("iconUrl", icon.spec());
418ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    result_list->Append(task);
419ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
420ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
421ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // TODO(zelidrag, serya): Add intent content tasks to result_list once we
422ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // implement that API.
423ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  SendResponse(true);
424ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return true;
425ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
426ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
427ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenclass ExecuteTasksFileSystemCallbackDispatcher
428ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    : public fileapi::FileSystemCallbackDispatcher {
429ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen public:
430ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  explicit ExecuteTasksFileSystemCallbackDispatcher(
431ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      ExecuteTasksFileBrowserFunction* function,
432ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      Profile* profile,
433ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      int child_id,
434ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      const GURL& source_url,
435ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      scoped_refptr<const Extension> extension,
436ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      const std::string task_id,
437ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      const std::vector<GURL>& file_urls)
438ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      : function_(function),
439ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        profile_(profile),
440ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        source_url_(source_url),
441ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        extension_(extension),
442ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        task_id_(task_id),
443ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        origin_file_urls_(file_urls) {
444ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    DCHECK(function_);
445ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
446ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
447ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // fileapi::FileSystemCallbackDispatcher overrides.
448ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  virtual void DidSucceed() OVERRIDE {
449ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    NOTREACHED();
450ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
451ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
452ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  virtual void DidGetLocalPath(const FilePath& local_path) {
453ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    NOTREACHED();
454ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
455ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
456ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  virtual void DidReadMetadata(const base::PlatformFileInfo& info,
457ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                               const FilePath& unused) OVERRIDE {
458ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    NOTREACHED();
459ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
460ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
461ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  virtual void DidReadDirectory(
462ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      const std::vector<base::FileUtilProxy::Entry>& entries,
463ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      bool has_more) OVERRIDE {
464ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    NOTREACHED();
465ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
466ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
467ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  virtual void DidWrite(int64 bytes, bool complete) OVERRIDE {
468ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    NOTREACHED();
469ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
470ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
471ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  virtual void DidOpenFileSystem(const std::string& file_system_name,
472ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                 const GURL& file_system_root) OVERRIDE {
473ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
474ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    ExecuteTasksFileBrowserFunction::FileDefinitionList file_list;
475ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    for (std::vector<GURL>::iterator iter = origin_file_urls_.begin();
476ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen         iter != origin_file_urls_.end();
477ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen         ++iter) {
478ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      // Set up file permission access.
479ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      ExecuteTasksFileBrowserFunction::FileDefinition file;
480ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      if (!SetupFileAccessPermissions(*iter, &file.target_file_url,
481ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                      &file.virtual_path, &file.is_directory)) {
482ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        continue;
483ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      }
484ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      file_list.push_back(file);
485ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
486ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (file_list.empty()) {
487ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      BrowserThread::PostTask(
488ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          BrowserThread::UI, FROM_HERE,
489ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          NewRunnableMethod(function_,
490ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen              &ExecuteTasksFileBrowserFunction::ExecuteFailedOnUIThread));
491ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      return;
492ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
493ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
494ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    BrowserThread::PostTask(
495ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        BrowserThread::UI, FROM_HERE,
496ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        NewRunnableMethod(function_,
497ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen            &ExecuteTasksFileBrowserFunction::ExecuteFileActionsOnUIThread,
498ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen            task_id_,
499ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen            file_system_name,
500ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen            file_system_root,
501ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen            file_list));
502ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
503ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
504ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  virtual void DidFail(base::PlatformFileError error_code) OVERRIDE {
505ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    LOG(WARNING) << "Local file system cant be resolved";
506ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    BrowserThread::PostTask(
507ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        BrowserThread::UI, FROM_HERE,
508ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        NewRunnableMethod(function_,
509ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen            &ExecuteTasksFileBrowserFunction::ExecuteFailedOnUIThread));
510ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
511ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
512ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen private:
513ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Checks legitimacy of file url and grants file RO access permissions from
514ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // handler (target) extension and its renderer process.
515ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  bool SetupFileAccessPermissions(const GURL& origin_file_url,
516ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen     GURL* target_file_url, FilePath* file_path, bool* is_directory) {
517ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
518ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (!extension_.get())
519ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      return false;
520ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
521ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    GURL file_origin_url;
522ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    FilePath virtual_path;
523ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    fileapi::FileSystemType type;
524ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (!CrackFileSystemURL(origin_file_url, &file_origin_url, &type,
525ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                            &virtual_path)) {
526ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      return false;
527ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
528ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
529ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (type != fileapi::kFileSystemTypeExternal)
530ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      return false;
531ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
532ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    fileapi::FileSystemPathManager* path_manager =
533ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        profile_->GetFileSystemContext()->path_manager();
534ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (!path_manager->IsAccessAllowed(file_origin_url,
535ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                       type,
536ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                       virtual_path)) {
537ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      return false;
538ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
539ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
540ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // Make sure this url really being used by the right caller extension.
541ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (source_url_.GetOrigin() != file_origin_url) {
542ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      DidFail(base::PLATFORM_FILE_ERROR_SECURITY);
543ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      return false;
544ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
545ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
546ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    FilePath root_path =
547ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        path_manager->ValidateFileSystemRootAndGetPathOnFileThread(
548ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          file_origin_url,
549ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          fileapi::kFileSystemTypeExternal,
550ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          virtual_path,
551ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          false);     // create
552ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    FilePath final_file_path = root_path.Append(virtual_path);
553ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
554ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // Check if this file system entry exists first.
555ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    base::PlatformFileInfo file_info;
556ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    FilePath platform_path;
557ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    fileapi::FileSystemOperationContext file_system_operation_context(
558ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        profile_->GetFileSystemContext(),
559ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        fileapi::LocalFileSystemFileUtil::GetInstance());
560ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (base::PLATFORM_FILE_OK !=
561ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen            fileapi::FileSystemFileUtil::GetInstance()->GetFileInfo(
562ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                &file_system_operation_context, final_file_path, &file_info,
563ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                &platform_path)) {
564ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      return false;
565ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
566ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
567ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    fileapi::ExternalFileSystemMountPointProvider* external_provider =
568ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        path_manager->external_provider();
569ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (!external_provider)
570ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      return false;
571ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
572ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // TODO(zelidrag): Let's just prevent all symlinks for now. We don't want a
573ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // USB drive content to point to something in the rest of the file system.
574ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // Ideally, we should permit symlinks within the boundary of the same
575ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // virtual mount point.
576ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (file_info.is_symbolic_link)
577ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      return false;
578ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
579ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // Get task details.
580ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    std::string target_extension_id;
581ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    std::string action_id;
582ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (!CrackTaskIdentifier(task_id_, &target_extension_id,
583ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                             &action_id)) {
584ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      return false;
585ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
586ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
587ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // TODO(zelidrag): Add explicit R/W + R/O permissions for non-component
588ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // extensions.
589ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
590ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // Get target extension's process.
591ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    RenderProcessHost* target_host =
592ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        profile_->GetExtensionProcessManager()->GetExtensionProcess(
593ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen            target_extension_id);
594ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (!target_host)
595ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      return false;
596ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
597ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // Grant R/O access permission to non-component extension and R/W to
598ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // component extensions.
599ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    ChildProcessSecurityPolicy::GetInstance()->GrantPermissionsForFile(
600ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        target_host->id(), final_file_path,
601ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        extension_->location() != Extension::COMPONENT ?
602ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen            kReadOnlyFilePermissions : kReadWriteFilePermissions);
603ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
604ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // Grant access to this particular file to target extension. This will
605ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // ensure that the target extension can access only this FS entry and
606ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // prevent from traversing FS hierarchy upward.
607ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    external_provider->GrantFileAccessToExtension(target_extension_id,
608ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                                  virtual_path);
609ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
610ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // Output values.
611ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    GURL target_origin_url(Extension::GetBaseURLFromExtensionId(
612ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        target_extension_id));
613ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    GURL base_url = fileapi::GetFileSystemRootURI(target_origin_url,
614ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        fileapi::kFileSystemTypeExternal);
615ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    *target_file_url = GURL(base_url.spec() + virtual_path.value());
616ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    FilePath root(FILE_PATH_LITERAL("/"));
617ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    *file_path = root.Append(virtual_path);
618ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    *is_directory = file_info.is_directory;
619ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return true;
620ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
621ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
622ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ExecuteTasksFileBrowserFunction* function_;
623ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  Profile* profile_;
624ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Extension source URL.
625ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  GURL source_url_;
626ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  scoped_refptr<const Extension> extension_;
627ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  std::string task_id_;
628ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  std::vector<GURL> origin_file_urls_;
629ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DISALLOW_COPY_AND_ASSIGN(ExecuteTasksFileSystemCallbackDispatcher);
630ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen};
631ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
632ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool ExecuteTasksFileBrowserFunction::RunImpl() {
633ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // First param is task id that was to the extension with getFileTasks call.
634ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  std::string task_id;
635ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!args_->GetString(0, &task_id) || !task_id.size())
636ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return false;
637ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
638ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // The second param is the list of files that need to be executed with this
639ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // task.
640ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ListValue* files_list = NULL;
641ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!args_->GetList(1, &files_list))
642ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return false;
643ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
644ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!files_list->GetSize())
645ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return true;
646ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
647ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return InitiateFileTaskExecution(task_id, files_list);
648ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
649ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
650ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool ExecuteTasksFileBrowserFunction::InitiateFileTaskExecution(
651ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const std::string& task_id, ListValue* files_list) {
652ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  std::vector<GURL> file_urls;
653ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  for (size_t i = 0; i < files_list->GetSize(); i++) {
654ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    std::string origin_file_url;
655ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (!files_list->GetString(i, &origin_file_url)) {
656ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      error_ = kInvalidFileUrl;
657ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      return false;
658ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
659ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    file_urls.push_back(GURL(origin_file_url));
660ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
661ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Get local file system instance on file thread.
662ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  BrowserThread::PostTask(
663ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      BrowserThread::FILE, FROM_HERE,
664ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      NewRunnableMethod(this,
665ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          &ExecuteTasksFileBrowserFunction::RequestFileEntryOnFileThread,
666ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          source_url_,
667ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          task_id,
668ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          file_urls));
669ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  result_.reset(new FundamentalValue(true));
670ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return true;
671ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
672ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
673ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid ExecuteTasksFileBrowserFunction::RequestFileEntryOnFileThread(
674ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const GURL& source_url, const std::string& task_id,
675ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const std::vector<GURL>& file_urls) {
676ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
677ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  fileapi::FileSystemOperation* operation =
678ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      new fileapi::FileSystemOperation(
679ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          new ExecuteTasksFileSystemCallbackDispatcher(
680ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen              this,
681ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen              profile(),
682ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen              dispatcher()->render_view_host()->process()->id(),
683ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen              source_url,
684ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen              GetExtension(),
685ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen              task_id,
686ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen              file_urls),
687ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE),
688ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          profile()->GetFileSystemContext(),
689ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          NULL);
690ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  GURL origin_url = source_url.GetOrigin();
691ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  operation->OpenFileSystem(origin_url, fileapi::kFileSystemTypeExternal,
692ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                            false);     // create
693ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
694ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
695ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid ExecuteTasksFileBrowserFunction::ExecuteFailedOnUIThread() {
696ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  SendResponse(false);
697ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
698ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
699ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
700ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid ExecuteTasksFileBrowserFunction::ExecuteFileActionsOnUIThread(
701ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const std::string& task_id,
702ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const std::string& file_system_name,
703ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const GURL& file_system_root,
704ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const FileDefinitionList& file_list) {
705ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
706ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ExtensionService* service = profile_->GetExtensionService();
707ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!service)
708ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return;
709ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Get task details.
710ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  std::string handler_extension_id;
711ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  std::string action_id;
712ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!CrackTaskIdentifier(task_id, &handler_extension_id,
713ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                           &action_id)) {
714ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    LOG(WARNING) << "Invalid task " << task_id;
715ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    SendResponse(false);
716ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return;
717ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
718ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
719ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  const Extension* extension = service->GetExtensionById(handler_extension_id,
720ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                                         false);
721ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!extension) {
722ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    SendResponse(false);
723ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return;
724ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
725ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
726ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ExtensionEventRouter* event_router = profile_->GetExtensionEventRouter();
727ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!event_router) {
728ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    SendResponse(false);
729ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return;
730ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
731ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
732ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  scoped_ptr<ListValue> event_args(new ListValue());
733ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  event_args->Append(Value::CreateStringValue(action_id));
734ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DictionaryValue* details = new DictionaryValue();
735ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  event_args->Append(details);
736ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Get file definitions. These will be replaced with Entry instances by
737ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // chromeHidden.Event.dispatchJSON() method from even_binding.js.
738ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ListValue* files_urls = new ListValue();
739ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  details->Set("entries", files_urls);
740ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  for (FileDefinitionList::const_iterator iter = file_list.begin();
741ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen       iter != file_list.end();
742ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen       ++iter) {
743ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    DictionaryValue* file_def = new DictionaryValue();
744ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    files_urls->Append(file_def);
745ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    file_def->SetString("fileSystemName", file_system_name);
746ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    file_def->SetString("fileSystemRoot", file_system_root.spec());
747ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    file_def->SetString("fileFullPath", iter->virtual_path.value());
748ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    file_def->SetBoolean("fileIsDirectory", iter->is_directory);
749ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
750ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Get tab id.
751ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  Browser* browser = GetCurrentBrowser();
752ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (browser) {
753ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    TabContents* contents = browser->GetSelectedTabContents();
754ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (contents)
755ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      details->SetInteger("tab_id", ExtensionTabUtil::GetTabId(contents));
756ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
757ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
758ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  UpdateFileHandlerUsageStats(profile_, task_id);
759ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
760ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  std::string json_args;
761ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  base::JSONWriter::Write(event_args.get(), false, &json_args);
762ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  event_router->DispatchEventToExtension(
763ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      handler_extension_id, std::string("fileBrowserHandler.onExecute"),
764ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      json_args, profile_,
765ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      GURL());
766ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  SendResponse(true);
767ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
768ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
769ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenFileDialogFunction::FileDialogFunction() {
770ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
771ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
772ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenFileDialogFunction::~FileDialogFunction() {
773ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
774ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
775ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// static
776ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenFileDialogFunction::Callback
777ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenFileDialogFunction::Callback::null_(NULL, NULL, NULL);
778ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
779ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// static
780ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenFileDialogFunction::Callback::Map FileDialogFunction::Callback::map_;
781ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
782ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// static
783ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid FileDialogFunction::Callback::Add(int32 tab_id,
784ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                     SelectFileDialog::Listener* listener,
785ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                     HtmlDialogView* dialog,
786ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                     void* params) {
787ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (map_.find(tab_id) == map_.end()) {
788ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    map_.insert(std::make_pair(tab_id, Callback(listener, dialog, params)));
789ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  } else {
790ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    DLOG_ASSERT("FileDialogFunction::AddCallback tab_id already present");
791ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
792ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
793ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
794ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// static
795ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid FileDialogFunction::Callback::Remove(int32 tab_id) {
796ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  map_.erase(tab_id);
797ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
798ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
799ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// static
800ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenconst FileDialogFunction::Callback&
801ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenFileDialogFunction::Callback::Find(int32 tab_id) {
802ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  Callback::Map::const_iterator it = map_.find(tab_id);
803ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return (it == map_.end()) ? null_ : it->second;
804ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
805ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
806ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
807ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenint32 FileDialogFunction::GetTabId() const {
808ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return dispatcher()->delegate()->associated_tab_contents()->
809ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    controller().session_id().id();
810ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
811ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
812ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenconst FileDialogFunction::Callback& FileDialogFunction::GetCallback() const {
813ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!dispatcher() || !dispatcher()->delegate() ||
814ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      !dispatcher()->delegate()->associated_tab_contents()) {
815ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return Callback::null();
816ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
817ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return Callback::Find(GetTabId());
818ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
819ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
820ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid FileDialogFunction::CloseDialog(HtmlDialogView* dialog) {
821ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DCHECK(dialog);
822ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  TabContents* contents = dispatcher()->delegate()->associated_tab_contents();
823ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (contents)
824ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    dialog->CloseContents(contents);
825ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
826ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
827ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// GetFileSystemRootPathOnFileThread can only be called from the file thread,
828ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// so here we are. This function takes a vector of virtual paths, converts
829ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// them to local paths and calls GetLocalPathsResponseOnUIThread with the
830ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// result vector, on the UI thread.
831ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid FileDialogFunction::GetLocalPathsOnFileThread(const UrlList& file_urls,
832ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                                   const std::string& task_id) {
833ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
834ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  FilePathList selected_files;
835ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
836ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // FilePath(virtual_path) doesn't work on win, so limit this to ChromeOS.
837ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#if defined(OS_CHROMEOS)
838ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  GURL origin_url = source_url().GetOrigin();
839ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  fileapi::FileSystemPathManager* path_manager =
840ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      profile()->GetFileSystemContext()->path_manager();
841ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
842ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  size_t len = file_urls.size();
843ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  selected_files.reserve(len);
844ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  for (size_t i = 0; i < len; ++i) {
845ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const GURL& file_url = file_urls[i];
846ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    GURL file_origin_url;
847ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    FilePath virtual_path;
848ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    fileapi::FileSystemType type;
849ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (!CrackFileSystemURL(file_url, &file_origin_url, &type,
850ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                            &virtual_path)) {
851ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      continue;
852ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
853ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (type != fileapi::kFileSystemTypeExternal) {
854ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      NOTREACHED();
855ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      continue;
856ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
857ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    FilePath root = path_manager->ValidateFileSystemRootAndGetPathOnFileThread(
858ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        origin_url,
859ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        fileapi::kFileSystemTypeExternal,
860ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        FilePath(virtual_path),
861ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        false);
862ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (!root.empty()) {
863ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      selected_files.push_back(root.Append(virtual_path));
864ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    } else {
865ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      LOG(WARNING) << "GetLocalPathsOnFileThread failed "
866ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                   << file_url.spec();
867ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
868ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
869ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#endif
870ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
871ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!selected_files.empty()) {
872ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    BrowserThread::PostTask(
873ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        BrowserThread::UI, FROM_HERE,
874ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        NewRunnableMethod(this,
875ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen            &FileDialogFunction::GetLocalPathsResponseOnUIThread,
876ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen            selected_files, task_id));
877ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
878ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
879ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
880ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool SelectFileFunction::RunImpl() {
881ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (args_->GetSize() != 2) {
882ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return false;
883ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
884ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  std::string file_url;
885ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  args_->GetString(0, &file_url);
886ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  UrlList file_paths;
887ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  file_paths.push_back(GURL(file_url));
888ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
889ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  BrowserThread::PostTask(
890ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      BrowserThread::FILE, FROM_HERE,
891ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      NewRunnableMethod(this,
892ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          &SelectFileFunction::GetLocalPathsOnFileThread,
893ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          file_paths, std::string()));
894ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
895ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return true;
896ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
897ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
898ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid SelectFileFunction::GetLocalPathsResponseOnUIThread(
899ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const FilePathList& files, const std::string& task_id) {
900ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
901ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (files.size() != 1) {
902ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    SendResponse(false);
903ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return;
904ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
905ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  int index;
906ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  args_->GetInteger(1, &index);
907ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  const Callback& callback = GetCallback();
908ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DCHECK(!callback.IsNull());
909ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!callback.IsNull()) {
910ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // Must do this before callback, as the callback may delete listeners
911ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // waiting for window close.
912ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    CloseDialog(callback.dialog());
913ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    callback.listener()->FileSelected(files[0],
914ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                      index,
915ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                      callback.params());
916ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
917ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  SendResponse(true);
918ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
919ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
920ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
921ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenViewFilesFunction::ViewFilesFunction() {
922ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
923ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
924ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenViewFilesFunction::~ViewFilesFunction() {
925ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
926ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
927ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool ViewFilesFunction::RunImpl() {
928ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (args_->GetSize() < 1) {
929ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return false;
930ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
931ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
932ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ListValue* path_list = NULL;
933ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  args_->GetList(0, &path_list);
934ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DCHECK(path_list);
935ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
936ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  std::string internal_task_id;
937ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  args_->GetString(1, &internal_task_id);
938ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
939ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  std::string virtual_path;
940ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  size_t len = path_list->GetSize();
941ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  UrlList file_urls;
942ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  file_urls.reserve(len);
943ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  for (size_t i = 0; i < len; ++i) {
944ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    path_list->GetString(i, &virtual_path);
945ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    file_urls.push_back(GURL(virtual_path));
946ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
947ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
948ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  BrowserThread::PostTask(
949ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      BrowserThread::FILE, FROM_HERE,
950ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      NewRunnableMethod(this,
951ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          &ViewFilesFunction::GetLocalPathsOnFileThread,
952ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          file_urls, internal_task_id));
953ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
954ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return true;
955ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
956ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
957ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid ViewFilesFunction::GetLocalPathsResponseOnUIThread(
958ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const FilePathList& files, const std::string& internal_task_id) {
959ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
960ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  for (FilePathList::const_iterator iter = files.begin();
961ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen       iter != files.end();
962ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen       ++iter) {
963ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    FileManagerUtil::ViewItem(*iter, internal_task_id == kEnqueueTaskId);
964ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
965ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  UpdateFileHandlerUsageStats(profile_, internal_task_id);
966ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  SendResponse(true);
967ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
968ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
969ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenSelectFilesFunction::SelectFilesFunction() {
970ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
971ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
972ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenSelectFilesFunction::~SelectFilesFunction() {
973ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
974ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
975ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool SelectFilesFunction::RunImpl() {
976ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (args_->GetSize() != 1) {
977ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return false;
978ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
979ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
980ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ListValue* path_list = NULL;
981ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  args_->GetList(0, &path_list);
982ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DCHECK(path_list);
983ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
984ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  std::string virtual_path;
985ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  size_t len = path_list->GetSize();
986ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  UrlList file_urls;
987ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  file_urls.reserve(len);
988ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  for (size_t i = 0; i < len; ++i) {
989ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    path_list->GetString(i, &virtual_path);
990ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    file_urls.push_back(GURL(virtual_path));
991ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
992ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
993ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  BrowserThread::PostTask(
994ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      BrowserThread::FILE, FROM_HERE,
995ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      NewRunnableMethod(this,
996ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          &SelectFilesFunction::GetLocalPathsOnFileThread,
997ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          file_urls, std::string()));
998ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
999ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return true;
1000ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
1001ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
1002ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid SelectFilesFunction::GetLocalPathsResponseOnUIThread(
1003ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const FilePathList& files, const std::string& internal_task_id) {
1004ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1005ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
1006ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  const Callback& callback = GetCallback();
1007ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DCHECK(!callback.IsNull());
1008ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!callback.IsNull()) {
1009ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // Must do this before callback, as the callback may delete listeners
1010ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // waiting for window close.
1011ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    CloseDialog(callback.dialog());
1012ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    callback.listener()->MultiFilesSelected(files, callback.params());
1013ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
1014ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  SendResponse(true);
1015ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
1016ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
1017ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool CancelFileDialogFunction::RunImpl() {
1018ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  const Callback& callback = GetCallback();
1019ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DCHECK(!callback.IsNull());
1020ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!callback.IsNull()) {
1021ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // Must do this before callback, as the callback may delete listeners
1022ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // waiting for window close.
1023ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    CloseDialog(callback.dialog());
1024ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    callback.listener()->FileSelectionCanceled(callback.params());
1025ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
1026ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  SendResponse(true);
1027ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return true;
1028ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
1029ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
1030ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool FileDialogStringsFunction::RunImpl() {
1031ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  result_.reset(new DictionaryValue());
1032ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DictionaryValue* dict = reinterpret_cast<DictionaryValue*>(result_.get());
1033ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
1034ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#define SET_STRING(ns, id) \
1035ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  dict->SetString(#id, l10n_util::GetStringUTF16(ns##_##id))
1036ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
1037ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  SET_STRING(IDS, LOCALE_FMT_DATE_SHORT);
1038ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  SET_STRING(IDS, LOCALE_MONTHS_SHORT);
1039ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  SET_STRING(IDS, LOCALE_DAYS_SHORT);
1040ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
1041ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  SET_STRING(IDS_FILE_BROWSER, BODY_FONT_FAMILY);
1042ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  SET_STRING(IDS_FILE_BROWSER, BODY_FONT_SIZE);
1043ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
1044ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  SET_STRING(IDS_FILE_BROWSER, ROOT_DIRECTORY_LABEL);
1045ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  SET_STRING(IDS_FILE_BROWSER, DOWNLOADS_DIRECTORY_LABEL);
1046ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  SET_STRING(IDS_FILE_BROWSER, MEDIA_DIRECTORY_LABEL);
1047ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  SET_STRING(IDS_FILE_BROWSER, NAME_COLUMN_LABEL);
1048ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  SET_STRING(IDS_FILE_BROWSER, SIZE_COLUMN_LABEL);
1049ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  SET_STRING(IDS_FILE_BROWSER, DATE_COLUMN_LABEL);
1050ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  SET_STRING(IDS_FILE_BROWSER, PREVIEW_COLUMN_LABEL);
1051ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
1052ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  SET_STRING(IDS_FILE_BROWSER, ERROR_CREATING_FOLDER);
1053ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  SET_STRING(IDS_FILE_BROWSER, ERROR_INVALID_FOLDER_CHARACTER);
1054ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  SET_STRING(IDS_FILE_BROWSER, ERROR_INVALID_FILE_CHARACTER);
1055ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  SET_STRING(IDS_FILE_BROWSER, NEW_FOLDER_PROMPT);
1056ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  SET_STRING(IDS_FILE_BROWSER, NEW_FOLDER_BUTTON_LABEL);
1057ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  SET_STRING(IDS_FILE_BROWSER, FILENAME_LABEL);
1058ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
1059ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  SET_STRING(IDS_FILE_BROWSER, EJECT_BUTTON);
1060ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  SET_STRING(IDS_FILE_BROWSER, IMAGE_DIMENSIONS);
1061ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  SET_STRING(IDS_FILE_BROWSER, VOLUME_LABEL);
1062ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  SET_STRING(IDS_FILE_BROWSER, READ_ONLY);
1063ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
1064ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  SET_STRING(IDS_FILE_BROWSER, ERROR_RENAMING);
1065ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  SET_STRING(IDS_FILE_BROWSER, RENAME_PROMPT);
1066ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  SET_STRING(IDS_FILE_BROWSER, RENAME_BUTTON_LABEL);
1067ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
1068ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  SET_STRING(IDS_FILE_BROWSER, ERROR_DELETING);
1069ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  SET_STRING(IDS_FILE_BROWSER, DELETE_BUTTON_LABEL);
1070ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
1071ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  SET_STRING(IDS_FILE_BROWSER, ERROR_MOVING);
1072ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  SET_STRING(IDS_FILE_BROWSER, MOVE_BUTTON_LABEL);
1073ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
1074ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  SET_STRING(IDS_FILE_BROWSER, ERROR_PASTING);
1075ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  SET_STRING(IDS_FILE_BROWSER, PASTE_BUTTON_LABEL);
1076ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
1077ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  SET_STRING(IDS_FILE_BROWSER, COPY_BUTTON_LABEL);
1078ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  SET_STRING(IDS_FILE_BROWSER, CUT_BUTTON_LABEL);
1079ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
1080ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  SET_STRING(IDS_FILE_BROWSER, DEVICE_TYPE_FLASH);
1081ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  SET_STRING(IDS_FILE_BROWSER, DEVICE_TYPE_HDD);
1082ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  SET_STRING(IDS_FILE_BROWSER, DEVICE_TYPE_OPTICAL);
1083ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  SET_STRING(IDS_FILE_BROWSER, DEVICE_TYPE_UNDEFINED);
1084ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
1085ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  SET_STRING(IDS_FILE_BROWSER, CANCEL_LABEL);
1086ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  SET_STRING(IDS_FILE_BROWSER, OPEN_LABEL);
1087ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  SET_STRING(IDS_FILE_BROWSER, SAVE_LABEL);
1088ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
1089ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  SET_STRING(IDS_FILE_BROWSER, SELECT_FOLDER_TITLE);
1090ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  SET_STRING(IDS_FILE_BROWSER, SELECT_OPEN_FILE_TITLE);
1091ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  SET_STRING(IDS_FILE_BROWSER, SELECT_OPEN_MULTI_FILE_TITLE);
1092ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  SET_STRING(IDS_FILE_BROWSER, SELECT_SAVEAS_FILE_TITLE);
1093ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
1094ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  SET_STRING(IDS_FILE_BROWSER, COMPUTING_SELECTION);
1095ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  SET_STRING(IDS_FILE_BROWSER, NOTHING_SELECTED);
1096ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  SET_STRING(IDS_FILE_BROWSER, ONE_FILE_SELECTED);
1097ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  SET_STRING(IDS_FILE_BROWSER, MANY_FILES_SELECTED);
1098ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
1099ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // FILEBROWSER, without the underscore, is from the old school codebase.
1100ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // TODO(rginda): Move these into IDS_FILE_BROWSER post M12.
1101ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  SET_STRING(IDS_FILEBROWSER, CONFIRM_DELETE);
1102ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
1103ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  SET_STRING(IDS_FILEBROWSER, ENQUEUE);
1104ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#undef SET_STRING
1105ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
1106ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // TODO(serya): Create a new string in .grd file for this one in M13.
1107ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  dict->SetString("PREVIEW_IMAGE",
1108ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      l10n_util::GetStringUTF16(IDS_CERT_MANAGER_VIEW_CERT_BUTTON));
1109ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  dict->SetString("PLAY_MEDIA",
1110ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      l10n_util::GetStringUTF16(IDS_CONTENT_CONTEXT_PLAY));
1111ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
1112ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return true;
1113ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
1114