Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(439)

Side by Side Diff: chrome/browser/extensions/api/file_system/file_system_api.cc

Issue 2924943003: Break ConsentProvider classes into own file (Closed)
Patch Set: rebase Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/extensions/api/file_system/file_system_api.h" 5 #include "chrome/browser/extensions/api/file_system/file_system_api.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 8
9 #include <memory> 9 #include <memory>
10 #include <set> 10 #include <set>
11 #include <utility> 11 #include <utility>
12 #include <vector> 12 #include <vector>
13 13
14 #include "apps/saved_files_service.h" 14 #include "apps/saved_files_service.h"
15 #include "base/bind.h" 15 #include "base/bind.h"
16 #include "base/files/file_path.h" 16 #include "base/files/file_path.h"
17 #include "base/files/file_util.h" 17 #include "base/files/file_util.h"
18 #include "base/logging.h"
19 #include "base/macros.h" 18 #include "base/macros.h"
20 #include "base/memory/ptr_util.h" 19 #include "base/memory/ptr_util.h"
21 #include "base/path_service.h" 20 #include "base/path_service.h"
22 #include "base/strings/string_util.h" 21 #include "base/strings/string_util.h"
23 #include "base/strings/stringprintf.h" 22 #include "base/strings/stringprintf.h"
24 #include "base/strings/sys_string_conversions.h" 23 #include "base/strings/sys_string_conversions.h"
25 #include "base/strings/utf_string_conversions.h" 24 #include "base/strings/utf_string_conversions.h"
26 #include "base/task_scheduler/post_task.h" 25 #include "base/task_scheduler/post_task.h"
27 #include "base/value_conversions.h" 26 #include "base/value_conversions.h"
28 #include "base/values.h" 27 #include "base/values.h"
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
61 #include "ui/shell_dialogs/select_file_dialog.h" 60 #include "ui/shell_dialogs/select_file_dialog.h"
62 #include "ui/shell_dialogs/selected_file_info.h" 61 #include "ui/shell_dialogs/selected_file_info.h"
63 62
64 #if defined(OS_MACOSX) 63 #if defined(OS_MACOSX)
65 #include <CoreFoundation/CoreFoundation.h> 64 #include <CoreFoundation/CoreFoundation.h>
66 #include "base/mac/foundation_util.h" 65 #include "base/mac/foundation_util.h"
67 #endif 66 #endif
68 67
69 #if defined(OS_CHROMEOS) 68 #if defined(OS_CHROMEOS)
70 #include "base/strings/string16.h" 69 #include "base/strings/string16.h"
71 #include "base/threading/thread_task_runner_handle.h"
72 #include "chrome/browser/chromeos/app_mode/kiosk_app_manager.h"
73 #include "chrome/browser/chromeos/file_manager/app_id.h"
74 #include "chrome/browser/chromeos/file_manager/filesystem_api_util.h" 70 #include "chrome/browser/chromeos/file_manager/filesystem_api_util.h"
75 #include "chrome/browser/chromeos/file_manager/volume_manager.h" 71 #include "chrome/browser/chromeos/file_manager/volume_manager.h"
76 #include "chrome/browser/extensions/api/file_system/request_file_system_notifica tion.h"
77 #include "chrome/browser/ui/simple_message_box.h"
78 #include "chrome/browser/ui/views/extensions/request_file_system_dialog_view.h"
79 #include "components/user_manager/user_manager.h"
80 #include "extensions/browser/event_router.h" 72 #include "extensions/browser/event_router.h"
81 #include "extensions/browser/extension_registry.h" 73 #include "extensions/browser/extension_registry.h"
82 #include "extensions/common/constants.h" 74 #include "extensions/common/constants.h"
83 #include "extensions/common/manifest_handlers/kiosk_mode_info.h"
84 #include "url/url_constants.h" 75 #include "url/url_constants.h"
85 #endif 76 #endif
86 77
87 using apps::SavedFileEntry; 78 using apps::SavedFileEntry;
88 using apps::SavedFilesService; 79 using apps::SavedFilesService;
89 using storage::IsolatedContext; 80 using storage::IsolatedContext;
90 81
91 const char kInvalidCallingPage[] = "Invalid calling page. This function can't " 82 const char kInvalidCallingPage[] = "Invalid calling page. This function can't "
92 "be called from a background page."; 83 "be called from a background page.";
93 const char kUserCancelled[] = "User cancelled"; 84 const char kUserCancelled[] = "User cancelled";
94 const char kWritableFileErrorFormat[] = "Error opening %s"; 85 const char kWritableFileErrorFormat[] = "Error opening %s";
95 const char kRequiresFileSystemWriteError[] = 86 const char kRequiresFileSystemWriteError[] =
96 "Operation requires fileSystem.write permission"; 87 "Operation requires fileSystem.write permission";
97 const char kRequiresFileSystemDirectoryError[] = 88 const char kRequiresFileSystemDirectoryError[] =
98 "Operation requires fileSystem.directory permission"; 89 "Operation requires fileSystem.directory permission";
99 const char kMultipleUnsupportedError[] = 90 const char kMultipleUnsupportedError[] =
100 "acceptsMultiple: true is only supported for 'openFile'"; 91 "acceptsMultiple: true is only supported for 'openFile'";
101 const char kUnknownIdError[] = "Unknown id"; 92 const char kUnknownIdError[] = "Unknown id";
102 93
103 #if !defined(OS_CHROMEOS) 94 #if !defined(OS_CHROMEOS)
104 const char kNotSupportedOnCurrentPlatformError[] = 95 const char kNotSupportedOnCurrentPlatformError[] =
105 "Operation not supported on the current platform."; 96 "Operation not supported on the current platform.";
106 #else 97 #else
107 const char kNotSupportedOnNonKioskSessionError[] = 98 const char kNotSupportedOnNonKioskSessionError[] =
108 "Operation only supported for kiosk apps running in a kiosk session."; 99 "Operation only supported for kiosk apps running in a kiosk session.";
109 const char kVolumeNotFoundError[] = "Volume not found."; 100 const char kVolumeNotFoundError[] = "Volume not found.";
110 const char kSecurityError[] = "Security error."; 101 const char kSecurityError[] = "Security error.";
111 const char kConsentImpossible[] = 102 const char kConsentImpossible[] =
112 "Impossible to ask for user consent as there is no app window visible."; 103 "Impossible to ask for user consent as there is no app window visible.";
113
114 // List of whitelisted component apps and extensions by their ids for
115 // chrome.fileSystem.requestFileSystem.
116 const char* const kRequestFileSystemComponentWhitelist[] = {
117 file_manager::kFileManagerAppId,
118 file_manager::kVideoPlayerAppId,
119 file_manager::kGalleryAppId,
120 file_manager::kAudioPlayerAppId,
121 file_manager::kImageLoaderExtensionId,
122 // TODO(mtomasz): Remove this extension id, and add it only for tests.
123 "pkplfbidichfdicaijlchgnapepdginl" // Testing extensions.
124 };
125 #endif 104 #endif
126 105
127 namespace extensions { 106 namespace extensions {
128 107
129 namespace file_system = api::file_system; 108 namespace file_system = api::file_system;
130 namespace ChooseEntry = file_system::ChooseEntry; 109 namespace ChooseEntry = file_system::ChooseEntry;
131 110
132 namespace { 111 namespace {
133 112
134 bool g_skip_picker_for_test = false; 113 bool g_skip_picker_for_test = false;
135 bool g_use_suggested_path_for_test = false; 114 bool g_use_suggested_path_for_test = false;
136 base::FilePath* g_path_to_be_picked_for_test; 115 base::FilePath* g_path_to_be_picked_for_test;
137 std::vector<base::FilePath>* g_paths_to_be_picked_for_test; 116 std::vector<base::FilePath>* g_paths_to_be_picked_for_test;
138 bool g_skip_directory_confirmation_for_test = false; 117 bool g_skip_directory_confirmation_for_test = false;
139 bool g_allow_directory_access_for_test = false; 118 bool g_allow_directory_access_for_test = false;
140 119
141 #if defined(OS_CHROMEOS)
142 ui::DialogButton g_auto_dialog_button_for_test = ui::DIALOG_BUTTON_NONE;
143 #endif
144
145 // Expand the mime-types and extensions provided in an AcceptOption, returning 120 // Expand the mime-types and extensions provided in an AcceptOption, returning
146 // them within the passed extension vector. Returns false if no valid types 121 // them within the passed extension vector. Returns false if no valid types
147 // were found. 122 // were found.
148 bool GetFileTypesFromAcceptOption( 123 bool GetFileTypesFromAcceptOption(
149 const file_system::AcceptOption& accept_option, 124 const file_system::AcceptOption& accept_option,
150 std::vector<base::FilePath::StringType>* extensions, 125 std::vector<base::FilePath::StringType>* extensions,
151 base::string16* description) { 126 base::string16* description) {
152 std::set<base::FilePath::StringType> extension_set; 127 std::set<base::FilePath::StringType> extension_set;
153 int description_id = 0; 128 int description_id = 0;
154 129
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
240 content::WebContents::FromRenderFrameHost(render_frame_host); 215 content::WebContents::FromRenderFrameHost(render_frame_host);
241 // Check if there is an app window associated with the web contents; if not, 216 // Check if there is an app window associated with the web contents; if not,
242 // return null. 217 // return null.
243 return AppWindowRegistry::Get(profile) 218 return AppWindowRegistry::Get(profile)
244 ->GetAppWindowForWebContents(web_contents) 219 ->GetAppWindowForWebContents(web_contents)
245 ? web_contents 220 ? web_contents
246 : nullptr; 221 : nullptr;
247 } 222 }
248 223
249 #if defined(OS_CHROMEOS) 224 #if defined(OS_CHROMEOS)
250 // Gets a WebContents instance handle for a current window of a platform app
251 // with |app_id|. If not found, then returns NULL.
252 content::WebContents* GetWebContentsForAppId(Profile* profile,
253 const std::string& app_id) {
254 AppWindowRegistry* const registry = AppWindowRegistry::Get(profile);
255 DCHECK(registry);
256 AppWindow* const app_window = registry->GetCurrentAppWindowForApp(app_id);
257 return app_window ? app_window->web_contents() : nullptr;
258 }
259
260 // Fills a list of volumes mounted in the system. 225 // Fills a list of volumes mounted in the system.
261 void FillVolumeList(Profile* profile, 226 void FillVolumeList(Profile* profile,
262 std::vector<api::file_system::Volume>* result) { 227 std::vector<api::file_system::Volume>* result) {
263 file_manager::VolumeManager* const volume_manager = 228 file_manager::VolumeManager* const volume_manager =
264 file_manager::VolumeManager::Get(profile); 229 file_manager::VolumeManager::Get(profile);
265 DCHECK(volume_manager); 230 DCHECK(volume_manager);
266 231
267 const auto& volume_list = volume_manager->GetVolumeList(); 232 const auto& volume_list = volume_manager->GetVolumeList();
268 // Convert volume_list to result_volume_list. 233 // Convert volume_list to result_volume_list.
269 for (const auto& volume : volume_list) { 234 for (const auto& volume : volume_list) {
270 api::file_system::Volume result_volume; 235 api::file_system::Volume result_volume;
271 result_volume.volume_id = volume->volume_id(); 236 result_volume.volume_id = volume->volume_id();
272 result_volume.writable = !volume->is_read_only(); 237 result_volume.writable = !volume->is_read_only();
273 result->push_back(std::move(result_volume)); 238 result->push_back(std::move(result_volume));
274 } 239 }
275 } 240 }
276
277 // Converts the clicked button to a consent result and passes it via the
278 // |callback|.
279 void DialogResultToConsent(
280 const file_system_api::ConsentProvider::ConsentCallback& callback,
281 ui::DialogButton button) {
282 switch (button) {
283 case ui::DIALOG_BUTTON_NONE:
284 callback.Run(file_system_api::ConsentProvider::CONSENT_IMPOSSIBLE);
285 break;
286 case ui::DIALOG_BUTTON_OK:
287 callback.Run(file_system_api::ConsentProvider::CONSENT_GRANTED);
288 break;
289 case ui::DIALOG_BUTTON_CANCEL:
290 callback.Run(file_system_api::ConsentProvider::CONSENT_REJECTED);
291 break;
292 }
293 }
294 #endif 241 #endif
295 242
296 } // namespace 243 } // namespace
297 244
298 namespace file_system_api { 245 namespace file_system_api {
299 246
300 base::FilePath GetLastChooseEntryDirectory(const ExtensionPrefs* prefs, 247 base::FilePath GetLastChooseEntryDirectory(const ExtensionPrefs* prefs,
301 const std::string& extension_id) { 248 const std::string& extension_id) {
302 base::FilePath path; 249 base::FilePath path;
303 std::string string_path; 250 std::string string_path;
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
335 if (!consent_provider.IsGrantable(*extension.get())) 282 if (!consent_provider.IsGrantable(*extension.get()))
336 continue; 283 continue;
337 event_router->DispatchEventToExtension( 284 event_router->DispatchEventToExtension(
338 extension->id(), 285 extension->id(),
339 base::MakeUnique<Event>( 286 base::MakeUnique<Event>(
340 events::FILE_SYSTEM_ON_VOLUME_LIST_CHANGED, 287 events::FILE_SYSTEM_ON_VOLUME_LIST_CHANGED,
341 api::file_system::OnVolumeListChanged::kEventName, 288 api::file_system::OnVolumeListChanged::kEventName,
342 api::file_system::OnVolumeListChanged::Create(event_args))); 289 api::file_system::OnVolumeListChanged::Create(event_args)));
343 } 290 }
344 } 291 }
345
346 ConsentProvider::ConsentProvider(DelegateInterface* delegate)
347 : delegate_(delegate) {
348 DCHECK(delegate_);
349 }
350
351 ConsentProvider::~ConsentProvider() {
352 }
353
354 void ConsentProvider::RequestConsent(
355 const Extension& extension,
356 const base::WeakPtr<file_manager::Volume>& volume,
357 bool writable,
358 const ConsentCallback& callback) {
359 DCHECK(IsGrantable(extension));
360
361 // If a whitelisted component, then no need to ask or inform the user.
362 if (extension.location() == Manifest::COMPONENT &&
363 delegate_->IsWhitelistedComponent(extension)) {
364 base::ThreadTaskRunnerHandle::Get()->PostTask(
365 FROM_HERE, base::Bind(callback, CONSENT_GRANTED));
366 return;
367 }
368
369 // If auto-launched kiosk app, then no need to ask user either, but show the
370 // notification.
371 if (delegate_->IsAutoLaunched(extension)) {
372 delegate_->ShowNotification(extension, volume, writable);
373 base::ThreadTaskRunnerHandle::Get()->PostTask(
374 FROM_HERE, base::Bind(callback, CONSENT_GRANTED));
375 return;
376 }
377
378 // If it's a kiosk app running in manual-launch kiosk session, then show
379 // the confirmation dialog.
380 if (KioskModeInfo::IsKioskOnly(&extension) &&
381 user_manager::UserManager::Get()->IsLoggedInAsKioskApp()) {
382 delegate_->ShowDialog(extension, volume, writable,
383 base::Bind(&DialogResultToConsent, callback));
384 return;
385 }
386
387 NOTREACHED() << "Cannot request consent for non-grantable extensions.";
388 }
389
390 bool ConsentProvider::IsGrantable(const Extension& extension) {
391 const bool is_whitelisted_component =
392 delegate_->IsWhitelistedComponent(extension);
393
394 const bool is_running_in_kiosk_session =
395 KioskModeInfo::IsKioskOnly(&extension) &&
396 user_manager::UserManager::Get()->IsLoggedInAsKioskApp();
397
398 return is_whitelisted_component || is_running_in_kiosk_session;
399 }
400
401 ConsentProviderDelegate::ConsentProviderDelegate(Profile* profile,
402 content::RenderFrameHost* host)
403 : profile_(profile), host_(host) {
404 DCHECK(profile_);
405 }
406
407 ConsentProviderDelegate::~ConsentProviderDelegate() {
408 }
409
410 // static
411 void ConsentProviderDelegate::SetAutoDialogButtonForTest(
412 ui::DialogButton button) {
413 g_auto_dialog_button_for_test = button;
414 }
415
416 void ConsentProviderDelegate::ShowDialog(
417 const Extension& extension,
418 const base::WeakPtr<file_manager::Volume>& volume,
419 bool writable,
420 const file_system_api::ConsentProvider::ShowDialogCallback& callback) {
421 DCHECK(host_);
422 content::WebContents* const foreground_contents =
423 GetWebContentsForRenderFrameHost(profile_, host_);
424 // If there is no web contents handle, then the method is most probably
425 // executed from a background page. Find an app window to host the dialog.
426 content::WebContents* const web_contents =
427 foreground_contents ? foreground_contents
428 : GetWebContentsForAppId(profile_, extension.id());
429 if (!web_contents) {
430 base::ThreadTaskRunnerHandle::Get()->PostTask(
431 FROM_HERE, base::Bind(callback, ui::DIALOG_BUTTON_NONE));
432 return;
433 }
434
435 // Short circuit the user consent dialog for tests. This is far from a pretty
436 // code design.
437 if (g_auto_dialog_button_for_test != ui::DIALOG_BUTTON_NONE) {
438 base::ThreadTaskRunnerHandle::Get()->PostTask(
439 FROM_HERE,
440 base::Bind(callback, g_auto_dialog_button_for_test /* result */));
441 return;
442 }
443
444 // If the volume is gone, then cancel the dialog.
445 if (!volume.get()) {
446 base::ThreadTaskRunnerHandle::Get()->PostTask(
447 FROM_HERE, base::Bind(callback, ui::DIALOG_BUTTON_CANCEL));
448 return;
449 }
450
451 RequestFileSystemDialogView::ShowDialog(
452 web_contents, extension.name(),
453 (volume->volume_label().empty() ? volume->volume_id()
454 : volume->volume_label()),
455 writable, callback);
456 }
457
458 void ConsentProviderDelegate::ShowNotification(
459 const Extension& extension,
460 const base::WeakPtr<file_manager::Volume>& volume,
461 bool writable) {
462 RequestFileSystemNotification::ShowAutoGrantedNotification(
463 profile_, extension, volume, writable);
464 }
465
466 bool ConsentProviderDelegate::IsAutoLaunched(const Extension& extension) {
467 chromeos::KioskAppManager::App app_info;
468 return chromeos::KioskAppManager::Get()->GetApp(extension.id(), &app_info) &&
469 app_info.was_auto_launched_with_zero_delay;
470 }
471
472 bool ConsentProviderDelegate::IsWhitelistedComponent(
473 const Extension& extension) {
474 for (auto* whitelisted_id : kRequestFileSystemComponentWhitelist) {
475 if (extension.id().compare(whitelisted_id) == 0)
476 return true;
477 }
478 return false;
479 }
480
481 #endif 292 #endif
482 293
483 } // namespace file_system_api 294 } // namespace file_system_api
484 295
485 #if defined(OS_CHROMEOS) 296 #if defined(OS_CHROMEOS)
486 using file_system_api::ConsentProvider; 297 using file_system_api::ConsentProvider;
487 #endif 298 #endif
488 299
489 ExtensionFunction::ResponseAction FileSystemGetDisplayPathFunction::Run() { 300 ExtensionFunction::ResponseAction FileSystemGetDisplayPathFunction::Run() {
490 std::string filesystem_name; 301 std::string filesystem_name;
(...skipping 948 matching lines...) Expand 10 before | Expand all | Expand 10 after
1439 return RespondNow(Error(kNotSupportedOnNonKioskSessionError)); 1250 return RespondNow(Error(kNotSupportedOnNonKioskSessionError));
1440 std::vector<api::file_system::Volume> result_volume_list; 1251 std::vector<api::file_system::Volume> result_volume_list;
1441 FillVolumeList(chrome_details_.GetProfile(), &result_volume_list); 1252 FillVolumeList(chrome_details_.GetProfile(), &result_volume_list);
1442 1253
1443 return RespondNow(ArgumentList( 1254 return RespondNow(ArgumentList(
1444 api::file_system::GetVolumeList::Results::Create(result_volume_list))); 1255 api::file_system::GetVolumeList::Results::Create(result_volume_list)));
1445 } 1256 }
1446 #endif 1257 #endif
1447 1258
1448 } // namespace extensions 1259 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698