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