1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188
|
// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/extensions/api/file_system/chrome_file_system_delegate.h"
#include <string>
#include <utility>
#include "apps/saved_files_service.h"
#include "base/check.h"
#include "base/functional/bind.h"
#include "base/functional/callback.h"
#include "base/notreached.h"
#include "base/path_service.h"
#include "chrome/browser/download/chrome_download_manager_delegate.h"
#include "chrome/browser/download/download_core_service.h"
#include "chrome/browser/download/download_core_service_factory.h"
#include "chrome/browser/download/download_prefs.h"
#include "chrome/browser/extensions/api/file_system/file_entry_picker.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/apps/directory_access_confirmation_dialog.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/grit/generated_resources.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/web_contents.h"
#include "extensions/browser/api/file_system/saved_files_service_interface.h"
#include "extensions/browser/app_window/app_window.h"
#include "extensions/browser/app_window/app_window_registry.h"
#include "extensions/common/extension.h"
#include "storage/common/file_system/file_system_util.h"
#if BUILDFLAG(IS_MAC)
#include <CoreFoundation/CoreFoundation.h>
#include "base/apple/foundation_util.h"
#endif
#if BUILDFLAG(IS_CHROMEOS)
#include "extensions/browser/event_router.h"
#endif // BUILDFLAG(IS_CHROMEOS)
namespace extensions {
namespace file_system = api::file_system;
#if BUILDFLAG(IS_CHROMEOS)
namespace file_system_api {
const char kConsentImpossible[] =
"Impossible to ask for user consent as there is no app window visible.";
const char kNotSupportedOnNonKioskSessionError[] =
"Operation only supported for kiosk apps running in a kiosk session.";
const char kRequiresFileSystemWriteError[] =
"Operation requires fileSystem.write permission";
const char kSecurityError[] = "Security error.";
const char kVolumeNotFoundError[] = "Volume not found.";
// Returns error message, or null if none.
const char* ConsentResultToError(ConsentProvider::Consent result) {
switch (result) {
case ConsentProvider::CONSENT_REJECTED:
return kSecurityError;
case ConsentProvider::CONSENT_IMPOSSIBLE:
return kConsentImpossible;
case ConsentProvider::CONSENT_GRANTED:
return nullptr;
}
NOTREACHED();
}
} // namespace file_system_api
#endif // BUILDFLAG(IS_CHROMEOS)
/******** ChromeFileSystemDelegate ********/
ChromeFileSystemDelegate::ChromeFileSystemDelegate() = default;
ChromeFileSystemDelegate::~ChromeFileSystemDelegate() = default;
base::FilePath ChromeFileSystemDelegate::GetDefaultDirectory() {
base::FilePath documents_dir;
base::PathService::Get(chrome::DIR_USER_DOCUMENTS, &documents_dir);
return documents_dir;
}
base::FilePath ChromeFileSystemDelegate::GetManagedSaveAsDirectory(
content::BrowserContext* browser_context,
const Extension& extension) {
if (extension.id() != extension_misc::kPdfExtensionId)
return base::FilePath();
ChromeDownloadManagerDelegate* download_manager =
DownloadCoreServiceFactory::GetForBrowserContext(browser_context)
->GetDownloadManagerDelegate();
DownloadPrefs* download_prefs = download_manager->download_prefs();
if (!download_prefs->IsDownloadPathManaged())
return base::FilePath();
return download_prefs->DownloadPath();
}
bool ChromeFileSystemDelegate::ShowSelectFileDialog(
scoped_refptr<ExtensionFunction> extension_function,
ui::SelectFileDialog::Type type,
const base::FilePath& default_path,
const ui::SelectFileDialog::FileTypeInfo* file_types,
FileSystemDelegate::FilesSelectedCallback files_selected_callback,
base::OnceClosure file_selection_canceled_callback) {
const Extension* extension = extension_function->extension();
content::WebContents* web_contents =
extension_function->GetSenderWebContents();
if (!web_contents)
return false;
// TODO(asargent/benwells) - As a short term remediation for
// crbug.com/179010 we're adding the ability for a allowlisted extension to
// use this API since chrome.fileBrowserHandler.selectFile is ChromeOS-only.
// Eventually we'd like a better solution and likely this code will go back
// to being platform-app only.
// Make sure there is an app window associated with the web contents, so that
// platform apps cannot open the file picker from a background page.
// TODO(michaelpg): As a workaround for https://crbug.com/736930, allow this
// to work from a background page for non-platform apps (which, in practice,
// is restricted to allowlisted extensions).
if (extension->is_platform_app() &&
!AppWindowRegistry::Get(extension_function->browser_context())
->GetAppWindowForWebContents(web_contents)) {
return false;
}
// The file picker will hold a reference to the ExtensionFunction
// instance, preventing its destruction (and subsequent sending of the
// function response) until the user has selected a file or cancelled the
// picker. At that point, the picker will delete itself, which will also free
// the function instance.
new FileEntryPicker(web_contents, default_path, *file_types, type,
std::move(files_selected_callback),
std::move(file_selection_canceled_callback));
return true;
}
void ChromeFileSystemDelegate::ConfirmSensitiveDirectoryAccess(
bool has_write_permission,
const std::u16string& app_name,
content::WebContents* web_contents,
base::OnceClosure on_accept,
base::OnceClosure on_cancel) {
CreateDirectoryAccessConfirmationDialog(has_write_permission, app_name,
web_contents, std::move(on_accept),
std::move(on_cancel));
}
int ChromeFileSystemDelegate::GetDescriptionIdForAcceptType(
const std::string& accept_type) {
if (accept_type == "image/*")
return IDS_IMAGE_FILES;
if (accept_type == "audio/*")
return IDS_AUDIO_FILES;
if (accept_type == "video/*")
return IDS_VIDEO_FILES;
return 0;
}
#if BUILDFLAG(IS_CHROMEOS)
void ChromeFileSystemDelegate::RequestFileSystem(
content::BrowserContext* browser_context,
scoped_refptr<ExtensionFunction> requester,
ConsentProvider* consent_provider,
const Extension& extension,
std::string volume_id,
bool writable,
FileSystemCallback success_callback,
ErrorCallback error_callback) {}
void ChromeFileSystemDelegate::GetVolumeList(
content::BrowserContext* browser_context,
VolumeListCallback success_callback,
ErrorCallback error_callback) {}
#endif // BUILDFLAG(IS_CHROMEOS)
SavedFilesServiceInterface* ChromeFileSystemDelegate::GetSavedFilesService(
content::BrowserContext* browser_context) {
return apps::SavedFilesService::Get(browser_context);
}
} // namespace extensions
|