1ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// Use of this source code is governed by a BSD-style license that can be
3ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// found in the LICENSE file.
4ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "chrome/browser/chromeos/file_manager/file_browser_handlers.h"
6ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
71320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include <algorithm>
81320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include <set>
91320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
10ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "base/bind.h"
111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h"
12ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "base/i18n/case_conversion.h"
13ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "base/strings/utf_string_conversions.h"
14ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "chrome/browser/chromeos/drive/file_system_util.h"
1558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "chrome/browser/chromeos/file_manager/app_id.h"
1658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "chrome/browser/chromeos/file_manager/fileapi_util.h"
1758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "chrome/browser/chromeos/file_manager/open_with_browser.h"
18ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "chrome/browser/chromeos/fileapi/file_system_backend.h"
19ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "chrome/browser/extensions/extension_service.h"
208bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "chrome/browser/extensions/extension_util.h"
21ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "chrome/browser/profiles/profile.h"
223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "chrome/browser/ui/browser_finder.h"
23ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "chrome/common/extensions/api/file_browser_handlers/file_browser_handler.h"
241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "chrome/common/extensions/api/file_manager_private.h"
25ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "content/public/browser/browser_thread.h"
26ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "content/public/browser/child_process_security_policy.h"
27ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "content/public/browser/render_process_host.h"
28ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "content/public/browser/site_instance.h"
29ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "content/public/browser/web_contents.h"
30f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/browser/event_router.h"
3123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "extensions/browser/extension_host.h"
325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/browser/extension_system.h"
33116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "extensions/browser/extension_util.h"
341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "extensions/browser/lazy_background_task_queue.h"
355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/common/extension_set.h"
36f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/manifest_handlers/background_info.h"
37ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "net/base/escape.h"
381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "storage/browser/fileapi/file_system_context.h"
391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "storage/browser/fileapi/file_system_url.h"
401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "storage/common/fileapi/file_system_info.h"
411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "storage/common/fileapi/file_system_util.h"
42ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
43ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochusing content::BrowserThread;
44ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochusing content::ChildProcessSecurityPolicy;
45ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochusing content::SiteInstance;
46ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochusing content::WebContents;
47ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochusing extensions::Extension;
4803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)using storage::FileSystemURL;
49a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)using file_manager::util::EntryDefinition;
50a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)using file_manager::util::EntryDefinitionList;
51a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)using file_manager::util::FileDefinition;
52a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)using file_manager::util::FileDefinitionList;
53ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
54ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochnamespace file_manager {
55ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochnamespace file_browser_handlers {
56ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochnamespace {
57ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
58ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// Returns process id of the process the extension is running in.
59ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochint ExtractProcessFromExtensionId(Profile* profile,
60ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                  const std::string& extension_id) {
61ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  GURL extension_url =
62ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      Extension::GetBaseURLFromExtensionId(extension_id);
63f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  extensions::ProcessManager* manager =
64ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    extensions::ExtensionSystem::Get(profile)->process_manager();
65ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
66ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  SiteInstance* site_instance = manager->GetSiteInstanceForURL(extension_url);
67ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (!site_instance || !site_instance->HasProcess())
68ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return -1;
69ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  content::RenderProcessHost* process = site_instance->GetProcess();
70ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
71ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  return process->GetID();
72ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
73ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
74ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// Finds a file browser handler that matches |action_id|. Returns NULL if not
75ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// found.
76ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochconst FileBrowserHandler* FindFileBrowserHandlerForActionId(
77ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const Extension* extension,
78ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const std::string& action_id) {
79ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  FileBrowserHandler::List* handler_list =
80ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      FileBrowserHandler::GetHandlers(extension);
81ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  for (FileBrowserHandler::List::const_iterator handler_iter =
82ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch           handler_list->begin();
83ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch       handler_iter != handler_list->end();
84ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch       ++handler_iter) {
85ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    if (handler_iter->get()->id() == action_id)
86ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      return handler_iter->get();
87ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
88ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  return NULL;
89ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
90ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
91ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochstd::string EscapedUtf8ToLower(const std::string& str) {
925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::string16 utf16 = base::UTF8ToUTF16(
93ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      net::UnescapeURLComponent(str, net::UnescapeRule::NORMAL));
94ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  return net::EscapeUrlEncodedData(
955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::UTF16ToUTF8(base::i18n::ToLower(utf16)),
96ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      false /* do not replace space with plus */);
97ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
98ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
99ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// Finds file browser handlers that can handle the |selected_file_url|.
100ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben MurdochFileBrowserHandlerList FindFileBrowserHandlersForURL(
101ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    Profile* profile,
102ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const GURL& selected_file_url) {
103ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  ExtensionService* service =
104ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      extensions::ExtensionSystem::Get(profile)->extension_service();
105ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // In unit-tests, we may not have an ExtensionService.
106ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (!service)
107ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return FileBrowserHandlerList();
108ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
109ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // We need case-insensitive matching, and pattern in the handler is already
110ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // in lower case.
111ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  const GURL lowercase_url(EscapedUtf8ToLower(selected_file_url.spec()));
112ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
113ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  FileBrowserHandlerList results;
1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (extensions::ExtensionSet::const_iterator iter =
1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)           service->extensions()->begin();
1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       iter != service->extensions()->end(); ++iter) {
117ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const Extension* extension = iter->get();
118ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    if (profile->IsOffTheRecord() &&
1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        !extensions::util::IsIncognitoEnabled(extension->id(), profile))
120ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      continue;
121116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (extensions::util::IsEphemeralApp(extension->id(), profile))
122116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      continue;
123ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
124ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    FileBrowserHandler::List* handler_list =
125ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        FileBrowserHandler::GetHandlers(extension);
126ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    if (!handler_list)
127ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      continue;
128ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    for (FileBrowserHandler::List::const_iterator handler_iter =
129ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch             handler_list->begin();
130ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch         handler_iter != handler_list->end();
131ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch         ++handler_iter) {
132ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      const FileBrowserHandler* handler = handler_iter->get();
133ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      if (!handler->MatchesURL(lowercase_url))
134ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        continue;
135ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
136ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      results.push_back(handler_iter->get());
137ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    }
138ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
139ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  return results;
140ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
141ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
142ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// This class is used to execute a file browser handler task. Here's how this
143ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// works:
144ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch//
145ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// 1) Open the "external" file system
146ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// 2) Set up permissions for the target files on the external file system.
147ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// 3) Raise onExecute event with the action ID and entries of the target
148ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch//    files. The event will launch the file browser handler if not active.
149ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// 4) In the file browser handler, onExecute event is handled and executes the
150ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch//    task in JavaScript.
151ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch//
152ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// That said, the class itself does not execute a task. The task will be
153ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// executed in JavaScript.
154ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochclass FileBrowserHandlerExecutor {
155ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch public:
156ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  FileBrowserHandlerExecutor(Profile* profile,
157ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                             const Extension* extension,
158ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                             const std::string& action_id);
159ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
160ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // Executes the task for each file. |done| will be run with the result.
161ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  void Execute(const std::vector<FileSystemURL>& file_urls,
162ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch               const file_tasks::FileTaskFinishedCallback& done);
163ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
164ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch private:
165ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // This object is responsible to delete itself.
166ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  virtual ~FileBrowserHandlerExecutor();
167ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
168ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // Checks legitimacy of file url and grants file RO access permissions from
169ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // handler (target) extension and its renderer process.
170a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  static scoped_ptr<FileDefinitionList> SetupFileAccessPermissions(
17103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      scoped_refptr<storage::FileSystemContext> file_system_context_handler,
172ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      const scoped_refptr<const Extension>& handler_extension,
173ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      const std::vector<FileSystemURL>& file_urls);
174ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
175ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  void ExecuteDoneOnUIThread(bool success);
176a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  void ExecuteAfterSetupFileAccess(scoped_ptr<FileDefinitionList> file_list);
177a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  void ExecuteFileActionsOnUIThread(
178a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      scoped_ptr<FileDefinitionList> file_definition_list,
179a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      scoped_ptr<EntryDefinitionList> entry_definition_list);
180a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  void SetupPermissionsAndDispatchEvent(
181a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      scoped_ptr<FileDefinitionList> file_definition_list,
182a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      scoped_ptr<EntryDefinitionList> entry_definition_list,
183a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      int handler_pid_in,
184a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      extensions::ExtensionHost* host);
185ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
186ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // Registers file permissions from |handler_host_permissions_| with
187ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // ChildProcessSecurityPolicy for process with id |handler_pid|.
188ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  void SetupHandlerHostFileAccessPermissions(
189a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      FileDefinitionList* file_definition_list,
190ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      const Extension* extension,
191ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      int handler_pid);
192ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
193ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  Profile* profile_;
194ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  scoped_refptr<const Extension> extension_;
195ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  const std::string action_id_;
196ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  file_tasks::FileTaskFinishedCallback done_;
197ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  base::WeakPtrFactory<FileBrowserHandlerExecutor> weak_ptr_factory_;
198ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
199ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  DISALLOW_COPY_AND_ASSIGN(FileBrowserHandlerExecutor);
200ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch};
201ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
202ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// static
203a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)scoped_ptr<FileDefinitionList>
204ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben MurdochFileBrowserHandlerExecutor::SetupFileAccessPermissions(
20503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    scoped_refptr<storage::FileSystemContext> file_system_context_handler,
206ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const scoped_refptr<const Extension>& handler_extension,
207ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const std::vector<FileSystemURL>& file_urls) {
208f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
209ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  DCHECK(handler_extension.get());
210ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
21103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  storage::ExternalFileSystemBackend* backend =
212ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      file_system_context_handler->external_backend();
213ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
214a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  scoped_ptr<FileDefinitionList> file_definition_list(new FileDefinitionList);
215ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  for (size_t i = 0; i < file_urls.size(); ++i) {
216ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const FileSystemURL& url = file_urls[i];
217ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
218ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // Check if this file system entry exists first.
2195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::File::Info file_info;
220ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
221ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    base::FilePath local_path = url.path();
222ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    base::FilePath virtual_path = url.virtual_path();
223ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
22403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    const bool is_drive_file = url.type() == storage::kFileSystemTypeDrive;
225ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    DCHECK(!is_drive_file || drive::util::IsUnderDriveMountPoint(local_path));
226ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
2275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    const bool is_native_file =
22803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        url.type() == storage::kFileSystemTypeNativeLocal ||
22903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        url.type() == storage::kFileSystemTypeRestrictedNativeLocal;
2305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
2315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    // If the file is from a physical volume, actual file must be found.
2325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    if (is_native_file) {
233ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      if (!base::PathExists(local_path) ||
234a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)          base::IsLink(local_path) ||
235a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)          !base::GetFileInfo(local_path, &file_info)) {
236ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        continue;
237ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      }
238ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    }
239ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
240ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // Grant access to this particular file to target extension. This will
241ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // ensure that the target extension can access only this FS entry and
242ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // prevent from traversing FS hierarchy upward.
2435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    backend->GrantFileAccessToExtension(handler_extension->id(), virtual_path);
244ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
245ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // Output values.
246a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    FileDefinition file_definition;
247a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    file_definition.virtual_path = virtual_path;
248a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    file_definition.is_directory = file_info.is_directory;
249a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    file_definition.absolute_path = local_path;
250a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    file_definition_list->push_back(file_definition);
251ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
252a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
253a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return file_definition_list.Pass();
254ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
255ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
256ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben MurdochFileBrowserHandlerExecutor::FileBrowserHandlerExecutor(
257ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    Profile* profile,
258ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const Extension* extension,
259ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const std::string& action_id)
260ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    : profile_(profile),
261ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      extension_(extension),
262ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      action_id_(action_id),
263ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      weak_ptr_factory_(this) {
264ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
265ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
266ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben MurdochFileBrowserHandlerExecutor::~FileBrowserHandlerExecutor() {}
267ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
268ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid FileBrowserHandlerExecutor::Execute(
269ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const std::vector<FileSystemURL>& file_urls,
270ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const file_tasks::FileTaskFinishedCallback& done) {
271ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  done_ = done;
272ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
273ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // Get file system context for the extension to which onExecute event will be
274ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // sent. The file access permissions will be granted to the extension in the
275ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // file system context for the files in |file_urls|.
27603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  scoped_refptr<storage::FileSystemContext> file_system_context(
27703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      util::GetFileSystemContextForExtensionId(profile_, extension_->id()));
2784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
279ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  BrowserThread::PostTaskAndReplyWithResult(
280ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      BrowserThread::FILE,
281ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      FROM_HERE,
282ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      base::Bind(&SetupFileAccessPermissions,
283ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                 file_system_context,
284ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                 extension_,
285ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                 file_urls),
286a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      base::Bind(&FileBrowserHandlerExecutor::ExecuteAfterSetupFileAccess,
2874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                 weak_ptr_factory_.GetWeakPtr()));
288ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
289ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
290a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void FileBrowserHandlerExecutor::ExecuteAfterSetupFileAccess(
291a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    scoped_ptr<FileDefinitionList> file_definition_list) {
292a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Outlives the conversion process, since bound to the callback.
293a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  const FileDefinitionList& file_definition_list_ref =
294a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      *file_definition_list.get();
295a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  file_manager::util::ConvertFileDefinitionListToEntryDefinitionList(
296a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      profile_,
297a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      extension_->id(),
298a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      file_definition_list_ref,
299a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      base::Bind(&FileBrowserHandlerExecutor::ExecuteFileActionsOnUIThread,
300a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                 weak_ptr_factory_.GetWeakPtr(),
301a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                 base::Passed(&file_definition_list)));
302a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
303a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
304ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid FileBrowserHandlerExecutor::ExecuteDoneOnUIThread(bool success) {
305f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DCHECK_CURRENTLY_ON(BrowserThread::UI);
306ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (!done_.is_null())
3075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    done_.Run(
3085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        success
3091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            ? extensions::api::file_manager_private::TASK_RESULT_MESSAGE_SENT
3101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            : extensions::api::file_manager_private::TASK_RESULT_FAILED);
311ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  delete this;
312ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
313ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
314ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid FileBrowserHandlerExecutor::ExecuteFileActionsOnUIThread(
315a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    scoped_ptr<FileDefinitionList> file_definition_list,
316a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    scoped_ptr<EntryDefinitionList> entry_definition_list) {
317f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DCHECK_CURRENTLY_ON(BrowserThread::UI);
318ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
319a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (file_definition_list->empty() || entry_definition_list->empty()) {
320ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    ExecuteDoneOnUIThread(false);
321ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return;
322ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
323ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
324ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  int handler_pid = ExtractProcessFromExtensionId(profile_, extension_->id());
325ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (handler_pid <= 0 &&
326ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      !extensions::BackgroundInfo::HasLazyBackgroundPage(extension_.get())) {
327ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    ExecuteDoneOnUIThread(false);
328ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return;
329ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
330ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
331ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (handler_pid > 0) {
332a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    SetupPermissionsAndDispatchEvent(file_definition_list.Pass(),
333a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                     entry_definition_list.Pass(),
334a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                     handler_pid,
335a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                     NULL);
336ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  } else {
337ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // We have to wake the handler background page before we proceed.
338ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    extensions::LazyBackgroundTaskQueue* queue =
339ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        extensions::ExtensionSystem::Get(profile_)->
340ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        lazy_background_task_queue();
341ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    if (!queue->ShouldEnqueueTask(profile_, extension_.get())) {
342ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      ExecuteDoneOnUIThread(false);
343ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      return;
344ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    }
345ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    queue->AddPendingTask(
346a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        profile_,
347a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        extension_->id(),
348ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        base::Bind(
349ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch            &FileBrowserHandlerExecutor::SetupPermissionsAndDispatchEvent,
350ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch            weak_ptr_factory_.GetWeakPtr(),
351a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            base::Passed(file_definition_list.Pass()),
352a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            base::Passed(entry_definition_list.Pass()),
353a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            handler_pid));
354ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
355ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
356ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
357ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid FileBrowserHandlerExecutor::SetupPermissionsAndDispatchEvent(
358a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    scoped_ptr<FileDefinitionList> file_definition_list,
359a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    scoped_ptr<EntryDefinitionList> entry_definition_list,
360ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    int handler_pid_in,
361ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    extensions::ExtensionHost* host) {
362ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  int handler_pid = host ? host->render_process_host()->GetID() :
363ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      handler_pid_in;
364ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
365ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (handler_pid <= 0) {
366ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    ExecuteDoneOnUIThread(false);
367ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return;
368ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
369ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
3700529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  extensions::EventRouter* router = extensions::EventRouter::Get(profile_);
3710529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (!router) {
372ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    ExecuteDoneOnUIThread(false);
373ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return;
374ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
375ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
376ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  SetupHandlerHostFileAccessPermissions(
377a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      file_definition_list.get(), extension_.get(), handler_pid);
378ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
3795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<base::ListValue> event_args(new base::ListValue());
380ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  event_args->Append(new base::StringValue(action_id_));
3815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::DictionaryValue* details = new base::DictionaryValue();
382ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  event_args->Append(details);
383ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // Get file definitions. These will be replaced with Entry instances by
384ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // dispatchEvent() method from event_binding.js.
3855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::ListValue* file_entries = new base::ListValue();
386ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  details->Set("entries", file_entries);
387a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
388a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  for (EntryDefinitionList::const_iterator iter =
389a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)           entry_definition_list->begin();
390a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)       iter != entry_definition_list->end();
391ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch       ++iter) {
3925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::DictionaryValue* file_def = new base::DictionaryValue();
393ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    file_entries->Append(file_def);
394a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    file_def->SetString("fileSystemName", iter->file_system_name);
395a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    file_def->SetString("fileSystemRoot", iter->file_system_root_url);
3965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    file_def->SetString("fileFullPath",
397a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                        "/" + iter->full_path.AsUTF8Unsafe());
398ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    file_def->SetBoolean("fileIsDirectory", iter->is_directory);
399ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
400ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
401ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  scoped_ptr<extensions::Event> event(new extensions::Event(
402ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      "fileBrowserHandler.onExecute", event_args.Pass()));
403f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  event->restrict_to_browser_context = profile_;
4040529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  router->DispatchEventToExtension(extension_->id(), event.Pass());
405ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
406ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  ExecuteDoneOnUIThread(true);
407ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
408ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
409ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid FileBrowserHandlerExecutor::SetupHandlerHostFileAccessPermissions(
410a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    FileDefinitionList* file_definition_list,
411ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const Extension* extension,
412ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    int handler_pid) {
4131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  const FileBrowserHandler* action =
4141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      FindFileBrowserHandlerForActionId(extension_.get(), action_id_);
415a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  for (FileDefinitionList::const_iterator iter = file_definition_list->begin();
416a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)       iter != file_definition_list->end();
417ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch       ++iter) {
418ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    if (!action)
419ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      continue;
420ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    if (action->CanRead()) {
421ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      content::ChildProcessSecurityPolicy::GetInstance()->GrantReadFile(
422ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch          handler_pid, iter->absolute_path);
423ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    }
424ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    if (action->CanWrite()) {
425ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      content::ChildProcessSecurityPolicy::GetInstance()->
426ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch          GrantCreateReadWriteFile(handler_pid, iter->absolute_path);
427ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    }
428ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
429ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
430ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
4313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// Returns true if |extension_id| and |action_id| indicate that the file
4323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// currently being handled should be opened with the browser. This function
4333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// is used to handle certain action IDs of the file manager.
4343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)bool ShouldBeOpenedWithBrowser(const std::string& extension_id,
4353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                               const std::string& action_id) {
4363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return (extension_id == kFileManagerAppId &&
4373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          (action_id == "view-pdf" ||
4383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)           action_id == "view-swf" ||
4393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)           action_id == "view-in-browser" ||
4403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)           action_id == "open-hosted-generic" ||
4413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)           action_id == "open-hosted-gdoc" ||
4423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)           action_id == "open-hosted-gsheet" ||
4433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)           action_id == "open-hosted-gslides"));
4443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
4453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
446424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// Opens the files specified by |file_urls| with the browser for |profile|.
447424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// Returns true on success. It's a failure if no files are opened.
4483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)bool OpenFilesWithBrowser(Profile* profile,
4493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                          const std::vector<FileSystemURL>& file_urls) {
4503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  int num_opened = 0;
4513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  for (size_t i = 0; i < file_urls.size(); ++i) {
4523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const FileSystemURL& file_url = file_urls[i];
4533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    if (chromeos::FileSystemBackend::CanHandleURL(file_url)) {
4541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      num_opened += util::OpenFileWithBrowser(profile, file_url) ? 1 : 0;
4553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    }
4563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
4573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return num_opened > 0;
4583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
4593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
460ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}  // namespace
461ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
462ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochbool ExecuteFileBrowserHandler(
463ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    Profile* profile,
464ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const Extension* extension,
465ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const std::string& action_id,
466ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const std::vector<FileSystemURL>& file_urls,
467ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const file_tasks::FileTaskFinishedCallback& done) {
468ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // Forbid calling undeclared handlers.
469ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (!FindFileBrowserHandlerForActionId(extension, action_id))
470ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return false;
471ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
4723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Some action IDs of the file manager's file browser handlers require the
4733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // files to be directly opened with the browser.
4743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (ShouldBeOpenedWithBrowser(extension->id(), action_id)) {
4755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const bool result = OpenFilesWithBrowser(profile, file_urls);
476f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (result && !done.is_null())
4771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      done.Run(extensions::api::file_manager_private::TASK_RESULT_OPENED);
4785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return result;
4793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
4803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
481ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // The executor object will be self deleted on completion.
482ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  (new FileBrowserHandlerExecutor(
483a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      profile, extension, action_id))->Execute(file_urls, done);
484ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  return true;
485ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
486ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
48758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)FileBrowserHandlerList FindFileBrowserHandlers(
488ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    Profile* profile,
489ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const std::vector<GURL>& file_list) {
490ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  FileBrowserHandlerList common_handlers;
491ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  for (std::vector<GURL>::const_iterator it = file_list.begin();
492ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch       it != file_list.end(); ++it) {
493ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    FileBrowserHandlerList handlers =
494ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        FindFileBrowserHandlersForURL(profile, *it);
495ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // If there is nothing to do for one file, the intersection of handlers
496ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // for all files will be empty at the end, so no need to check further.
497ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    if (handlers.empty())
498ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      return FileBrowserHandlerList();
499ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
500ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // For the very first file, just copy all the elements.
501ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    if (it == file_list.begin()) {
502ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      common_handlers = handlers;
503ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    } else {
504ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      // For all additional files, find intersection between the accumulated and
505ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      // file specific set.
506ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      FileBrowserHandlerList intersection;
507a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      std::set<const FileBrowserHandler*> common_handler_set(
508a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)          common_handlers.begin(), common_handlers.end());
509a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
510a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      for (FileBrowserHandlerList::const_iterator itr = handlers.begin();
511a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)           itr != handlers.end(); ++itr) {
512a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        if (ContainsKey(common_handler_set, *itr))
513a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)          intersection.push_back(*itr);
514a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      }
515a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
516a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      std::swap(common_handlers, intersection);
517ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      if (common_handlers.empty())
518ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        return FileBrowserHandlerList();
519ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    }
520ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
521ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
522ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  return common_handlers;
523ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
524ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
525ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}  // namespace file_browser_handlers
526ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}  // namespace file_manager
527