| OLD | NEW |
| 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 "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/file_path.h" | 8 #include "base/file_path.h" |
| 9 #include "base/file_util.h" | 9 #include "base/file_util.h" |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| (...skipping 20 matching lines...) Expand all Loading... |
| 31 | 31 |
| 32 using fileapi::IsolatedContext; | 32 using fileapi::IsolatedContext; |
| 33 | 33 |
| 34 const char kInvalidParameters[] = "Invalid parameters"; | 34 const char kInvalidParameters[] = "Invalid parameters"; |
| 35 const char kSecurityError[] = "Security error"; | 35 const char kSecurityError[] = "Security error"; |
| 36 const char kInvalidCallingPage[] = "Invalid calling page"; | 36 const char kInvalidCallingPage[] = "Invalid calling page"; |
| 37 const char kUserCancelled[] = "User cancelled"; | 37 const char kUserCancelled[] = "User cancelled"; |
| 38 const char kWritableFileError[] = "Invalid file for writing"; | 38 const char kWritableFileError[] = "Invalid file for writing"; |
| 39 const char kRequiresFileSystemWriteError[] = | 39 const char kRequiresFileSystemWriteError[] = |
| 40 "Operation requires fileSystemWrite permission"; | 40 "Operation requires fileSystemWrite permission"; |
| 41 const char kUnknownChooseFileType[] = "Unknown type"; | 41 const char kUnknownChooseEntryType[] = "Unknown type"; |
| 42 | 42 |
| 43 const char kOpenFileOption[] = "openFile"; | 43 const char kOpenFileOption[] = "openFile"; |
| 44 const char kOpenWritableFileOption[] ="openWritableFile"; | 44 const char kOpenWritableFileOption[] ="openWritableFile"; |
| 45 const char kSaveFileOption[] = "saveFile"; | 45 const char kSaveFileOption[] = "saveFile"; |
| 46 | 46 |
| 47 namespace file_system = extensions::api::file_system; | 47 namespace file_system = extensions::api::file_system; |
| 48 namespace ChooseFile = file_system::ChooseFile; | 48 namespace ChooseEntry = file_system::ChooseEntry; |
| 49 | 49 |
| 50 namespace { | 50 namespace { |
| 51 | 51 |
| 52 struct RewritePair { | 52 struct RewritePair { |
| 53 int path_key; | 53 int path_key; |
| 54 const char* output; | 54 const char* output; |
| 55 }; | 55 }; |
| 56 | 56 |
| 57 const RewritePair g_rewrite_pairs[] = { | 57 const RewritePair g_rewrite_pairs[] = { |
| 58 #if defined(OS_WIN) | 58 #if defined(OS_WIN) |
| (...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 273 dict->SetString("baseName", registered_name); | 273 dict->SetString("baseName", registered_name); |
| 274 SendResponse(true); | 274 SendResponse(true); |
| 275 } | 275 } |
| 276 | 276 |
| 277 void FileSystemEntryFunction::HandleWritableFileError() { | 277 void FileSystemEntryFunction::HandleWritableFileError() { |
| 278 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 278 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| 279 error_ = kWritableFileError; | 279 error_ = kWritableFileError; |
| 280 SendResponse(false); | 280 SendResponse(false); |
| 281 } | 281 } |
| 282 | 282 |
| 283 bool FileSystemGetWritableFileEntryFunction::RunImpl() { | 283 bool FileSystemGetWritableEntryFunction::RunImpl() { |
| 284 std::string filesystem_name; | 284 std::string filesystem_name; |
| 285 std::string filesystem_path; | 285 std::string filesystem_path; |
| 286 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &filesystem_name)); | 286 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &filesystem_name)); |
| 287 EXTENSION_FUNCTION_VALIDATE(args_->GetString(1, &filesystem_path)); | 287 EXTENSION_FUNCTION_VALIDATE(args_->GetString(1, &filesystem_path)); |
| 288 | 288 |
| 289 if (!HasFileSystemWritePermission()) { | 289 if (!HasFileSystemWritePermission()) { |
| 290 error_ = kRequiresFileSystemWriteError; | 290 error_ = kRequiresFileSystemWriteError; |
| 291 return false; | 291 return false; |
| 292 } | 292 } |
| 293 | 293 |
| 294 FilePath path; | 294 FilePath path; |
| 295 if (!GetFilePathOfFileEntry(filesystem_name, filesystem_path, | 295 if (!GetFilePathOfFileEntry(filesystem_name, filesystem_path, |
| 296 render_view_host_, &path, &error_)) | 296 render_view_host_, &path, &error_)) |
| 297 return false; | 297 return false; |
| 298 | 298 |
| 299 content::BrowserThread::PostTask(content::BrowserThread::FILE, FROM_HERE, | 299 content::BrowserThread::PostTask(content::BrowserThread::FILE, FROM_HERE, |
| 300 base::Bind(&FileSystemGetWritableFileEntryFunction::CheckWritableFile, | 300 base::Bind(&FileSystemGetWritableEntryFunction::CheckWritableFile, |
| 301 this, path)); | 301 this, path)); |
| 302 return true; | 302 return true; |
| 303 } | 303 } |
| 304 | 304 |
| 305 bool FileSystemIsWritableFileEntryFunction::RunImpl() { | 305 bool FileSystemIsWritableEntryFunction::RunImpl() { |
| 306 std::string filesystem_name; | 306 std::string filesystem_name; |
| 307 std::string filesystem_path; | 307 std::string filesystem_path; |
| 308 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &filesystem_name)); | 308 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &filesystem_name)); |
| 309 EXTENSION_FUNCTION_VALIDATE(args_->GetString(1, &filesystem_path)); | 309 EXTENSION_FUNCTION_VALIDATE(args_->GetString(1, &filesystem_path)); |
| 310 | 310 |
| 311 std::string filesystem_id; | 311 std::string filesystem_id; |
| 312 if (!fileapi::CrackIsolatedFileSystemName(filesystem_name, &filesystem_id)) { | 312 if (!fileapi::CrackIsolatedFileSystemName(filesystem_name, &filesystem_id)) { |
| 313 error_ = kInvalidParameters; | 313 error_ = kInvalidParameters; |
| 314 return false; | 314 return false; |
| 315 } | 315 } |
| 316 | 316 |
| 317 content::ChildProcessSecurityPolicy* policy = | 317 content::ChildProcessSecurityPolicy* policy = |
| 318 content::ChildProcessSecurityPolicy::GetInstance(); | 318 content::ChildProcessSecurityPolicy::GetInstance(); |
| 319 int renderer_id = render_view_host_->GetProcess()->GetID(); | 319 int renderer_id = render_view_host_->GetProcess()->GetID(); |
| 320 bool is_writable = policy->CanReadWriteFileSystem(renderer_id, | 320 bool is_writable = policy->CanReadWriteFileSystem(renderer_id, |
| 321 filesystem_id); | 321 filesystem_id); |
| 322 | 322 |
| 323 SetResult(base::Value::CreateBooleanValue(is_writable)); | 323 SetResult(base::Value::CreateBooleanValue(is_writable)); |
| 324 return true; | 324 return true; |
| 325 } | 325 } |
| 326 | 326 |
| 327 // Handles showing a dialog to the user to ask for the filename for a file to | 327 // Handles showing a dialog to the user to ask for the filename for a file to |
| 328 // save or open. | 328 // save or open. |
| 329 class FileSystemChooseFileFunction::FilePicker | 329 class FileSystemChooseEntryFunction::FilePicker |
| 330 : public ui::SelectFileDialog::Listener { | 330 : public ui::SelectFileDialog::Listener { |
| 331 public: | 331 public: |
| 332 FilePicker(FileSystemChooseFileFunction* function, | 332 FilePicker(FileSystemChooseEntryFunction* function, |
| 333 content::WebContents* web_contents, | 333 content::WebContents* web_contents, |
| 334 const FilePath& suggested_name, | 334 const FilePath& suggested_name, |
| 335 const ui::SelectFileDialog::FileTypeInfo& file_type_info, | 335 const ui::SelectFileDialog::FileTypeInfo& file_type_info, |
| 336 ui::SelectFileDialog::Type picker_type, | 336 ui::SelectFileDialog::Type picker_type, |
| 337 EntryType entry_type) | 337 EntryType entry_type) |
| 338 : suggested_name_(suggested_name), | 338 : suggested_name_(suggested_name), |
| 339 entry_type_(entry_type), | 339 entry_type_(entry_type), |
| 340 function_(function) { | 340 function_(function) { |
| 341 select_file_dialog_ = ui::SelectFileDialog::Create( | 341 select_file_dialog_ = ui::SelectFileDialog::Create( |
| 342 this, new ChromeSelectFilePolicy(web_contents)); | 342 this, new ChromeSelectFilePolicy(web_contents)); |
| 343 gfx::NativeWindow owning_window = web_contents ? | 343 gfx::NativeWindow owning_window = web_contents ? |
| 344 platform_util::GetTopLevel(web_contents->GetNativeView()) : NULL; | 344 platform_util::GetTopLevel(web_contents->GetNativeView()) : NULL; |
| 345 | 345 |
| 346 if (g_skip_picker_for_test) { | 346 if (g_skip_picker_for_test) { |
| 347 if (g_path_to_be_picked_for_test) { | 347 if (g_path_to_be_picked_for_test) { |
| 348 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, | 348 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, |
| 349 base::Bind( | 349 base::Bind( |
| 350 &FileSystemChooseFileFunction::FilePicker::FileSelected, | 350 &FileSystemChooseEntryFunction::FilePicker::FileSelected, |
| 351 base::Unretained(this), *g_path_to_be_picked_for_test, 1, | 351 base::Unretained(this), *g_path_to_be_picked_for_test, 1, |
| 352 static_cast<void*>(NULL))); | 352 static_cast<void*>(NULL))); |
| 353 } else { | 353 } else { |
| 354 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, | 354 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, |
| 355 base::Bind( | 355 base::Bind( |
| 356 &FileSystemChooseFileFunction::FilePicker:: | 356 &FileSystemChooseEntryFunction::FilePicker:: |
| 357 FileSelectionCanceled, | 357 FileSelectionCanceled, |
| 358 base::Unretained(this), static_cast<void*>(NULL))); | 358 base::Unretained(this), static_cast<void*>(NULL))); |
| 359 } | 359 } |
| 360 return; | 360 return; |
| 361 } | 361 } |
| 362 | 362 |
| 363 select_file_dialog_->SelectFile(picker_type, | 363 select_file_dialog_->SelectFile(picker_type, |
| 364 string16(), | 364 string16(), |
| 365 suggested_name, | 365 suggested_name, |
| 366 &file_type_info, 0, FILE_PATH_LITERAL(""), | 366 &file_type_info, 0, FILE_PATH_LITERAL(""), |
| (...skipping 14 matching lines...) Expand all Loading... |
| 381 virtual void FileSelectionCanceled(void* params) OVERRIDE { | 381 virtual void FileSelectionCanceled(void* params) OVERRIDE { |
| 382 function_->FileSelectionCanceled(); | 382 function_->FileSelectionCanceled(); |
| 383 delete this; | 383 delete this; |
| 384 } | 384 } |
| 385 | 385 |
| 386 FilePath suggested_name_; | 386 FilePath suggested_name_; |
| 387 | 387 |
| 388 EntryType entry_type_; | 388 EntryType entry_type_; |
| 389 | 389 |
| 390 scoped_refptr<ui::SelectFileDialog> select_file_dialog_; | 390 scoped_refptr<ui::SelectFileDialog> select_file_dialog_; |
| 391 scoped_refptr<FileSystemChooseFileFunction> function_; | 391 scoped_refptr<FileSystemChooseEntryFunction> function_; |
| 392 | 392 |
| 393 DISALLOW_COPY_AND_ASSIGN(FilePicker); | 393 DISALLOW_COPY_AND_ASSIGN(FilePicker); |
| 394 }; | 394 }; |
| 395 | 395 |
| 396 bool FileSystemChooseFileFunction::ShowPicker( | 396 bool FileSystemChooseEntryFunction::ShowPicker( |
| 397 const FilePath& suggested_name, | 397 const FilePath& suggested_name, |
| 398 const ui::SelectFileDialog::FileTypeInfo& file_type_info, | 398 const ui::SelectFileDialog::FileTypeInfo& file_type_info, |
| 399 ui::SelectFileDialog::Type picker_type, | 399 ui::SelectFileDialog::Type picker_type, |
| 400 EntryType entry_type) { | 400 EntryType entry_type) { |
| 401 ShellWindowRegistry* registry = ShellWindowRegistry::Get(profile()); | 401 ShellWindowRegistry* registry = ShellWindowRegistry::Get(profile()); |
| 402 DCHECK(registry); | 402 DCHECK(registry); |
| 403 ShellWindow* shell_window = registry->GetShellWindowForRenderViewHost( | 403 ShellWindow* shell_window = registry->GetShellWindowForRenderViewHost( |
| 404 render_view_host()); | 404 render_view_host()); |
| 405 if (!shell_window) { | 405 if (!shell_window) { |
| 406 error_ = kInvalidCallingPage; | 406 error_ = kInvalidCallingPage; |
| 407 return false; | 407 return false; |
| 408 } | 408 } |
| 409 | 409 |
| 410 // The file picker will hold a reference to this function instance, preventing | 410 // The file picker will hold a reference to this function instance, preventing |
| 411 // its destruction (and subsequent sending of the function response) until the | 411 // its destruction (and subsequent sending of the function response) until the |
| 412 // user has selected a file or cancelled the picker. At that point, the picker | 412 // user has selected a file or cancelled the picker. At that point, the picker |
| 413 // will delete itself, which will also free the function instance. | 413 // will delete itself, which will also free the function instance. |
| 414 new FilePicker(this, shell_window->web_contents(), suggested_name, | 414 new FilePicker(this, shell_window->web_contents(), suggested_name, |
| 415 file_type_info, picker_type, entry_type); | 415 file_type_info, picker_type, entry_type); |
| 416 return true; | 416 return true; |
| 417 } | 417 } |
| 418 | 418 |
| 419 // static | 419 // static |
| 420 void FileSystemChooseFileFunction::SkipPickerAndAlwaysSelectPathForTest( | 420 void FileSystemChooseEntryFunction::SkipPickerAndAlwaysSelectPathForTest( |
| 421 FilePath* path) { | 421 FilePath* path) { |
| 422 g_skip_picker_for_test = true; | 422 g_skip_picker_for_test = true; |
| 423 g_path_to_be_picked_for_test = path; | 423 g_path_to_be_picked_for_test = path; |
| 424 } | 424 } |
| 425 | 425 |
| 426 // static | 426 // static |
| 427 void FileSystemChooseFileFunction::SkipPickerAndAlwaysCancelForTest() { | 427 void FileSystemChooseEntryFunction::SkipPickerAndAlwaysCancelForTest() { |
| 428 g_skip_picker_for_test = true; | 428 g_skip_picker_for_test = true; |
| 429 g_path_to_be_picked_for_test = NULL; | 429 g_path_to_be_picked_for_test = NULL; |
| 430 } | 430 } |
| 431 | 431 |
| 432 // static | 432 // static |
| 433 void FileSystemChooseFileFunction::StopSkippingPickerForTest() { | 433 void FileSystemChooseEntryFunction::StopSkippingPickerForTest() { |
| 434 g_skip_picker_for_test = false; | 434 g_skip_picker_for_test = false; |
| 435 } | 435 } |
| 436 | 436 |
| 437 void FileSystemChooseFileFunction::FileSelected(const FilePath& path, | 437 void FileSystemChooseEntryFunction::FileSelected(const FilePath& path, |
| 438 EntryType entry_type) { | 438 EntryType entry_type) { |
| 439 if (entry_type == WRITABLE) { | 439 if (entry_type == WRITABLE) { |
| 440 content::BrowserThread::PostTask(content::BrowserThread::FILE, FROM_HERE, | 440 content::BrowserThread::PostTask(content::BrowserThread::FILE, FROM_HERE, |
| 441 base::Bind(&FileSystemChooseFileFunction::CheckWritableFile, | 441 base::Bind(&FileSystemChooseEntryFunction::CheckWritableFile, |
| 442 this, path)); | 442 this, path)); |
| 443 return; | 443 return; |
| 444 } | 444 } |
| 445 | 445 |
| 446 // Don't need to check the file, it's for reading. | 446 // Don't need to check the file, it's for reading. |
| 447 RegisterFileSystemAndSendResponse(path, READ_ONLY); | 447 RegisterFileSystemAndSendResponse(path, READ_ONLY); |
| 448 } | 448 } |
| 449 | 449 |
| 450 void FileSystemChooseFileFunction::FileSelectionCanceled() { | 450 void FileSystemChooseEntryFunction::FileSelectionCanceled() { |
| 451 error_ = kUserCancelled; | 451 error_ = kUserCancelled; |
| 452 SendResponse(false); | 452 SendResponse(false); |
| 453 } | 453 } |
| 454 | 454 |
| 455 void FileSystemChooseFileFunction::BuildFileTypeInfo( | 455 void FileSystemChooseEntryFunction::BuildFileTypeInfo( |
| 456 ui::SelectFileDialog::FileTypeInfo* file_type_info, | 456 ui::SelectFileDialog::FileTypeInfo* file_type_info, |
| 457 const FilePath::StringType& suggested_extension, | 457 const FilePath::StringType& suggested_extension, |
| 458 const AcceptOptions* accepts, | 458 const AcceptOptions* accepts, |
| 459 const bool* acceptsAllTypes) { | 459 const bool* acceptsAllTypes) { |
| 460 file_type_info->include_all_files = true; | 460 file_type_info->include_all_files = true; |
| 461 if (acceptsAllTypes) | 461 if (acceptsAllTypes) |
| 462 file_type_info->include_all_files = *acceptsAllTypes; | 462 file_type_info->include_all_files = *acceptsAllTypes; |
| 463 | 463 |
| 464 bool need_suggestion = !file_type_info->include_all_files && | 464 bool need_suggestion = !file_type_info->include_all_files && |
| 465 !suggested_extension.empty(); | 465 !suggested_extension.empty(); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 485 } | 485 } |
| 486 } | 486 } |
| 487 } | 487 } |
| 488 | 488 |
| 489 // If there's nothing in our accepted extension list or we couldn't find the | 489 // If there's nothing in our accepted extension list or we couldn't find the |
| 490 // suggested extension required, then default to accepting all types. | 490 // suggested extension required, then default to accepting all types. |
| 491 if (file_type_info->extensions.empty() || need_suggestion) | 491 if (file_type_info->extensions.empty() || need_suggestion) |
| 492 file_type_info->include_all_files = true; | 492 file_type_info->include_all_files = true; |
| 493 } | 493 } |
| 494 | 494 |
| 495 void FileSystemChooseFileFunction::BuildSuggestion( | 495 void FileSystemChooseEntryFunction::BuildSuggestion( |
| 496 const std::string *opt_name, | 496 const std::string *opt_name, |
| 497 FilePath* suggested_name, | 497 FilePath* suggested_name, |
| 498 FilePath::StringType* suggested_extension) { | 498 FilePath::StringType* suggested_extension) { |
| 499 if (opt_name) { | 499 if (opt_name) { |
| 500 *suggested_name = FilePath::FromUTF8Unsafe(*opt_name); | 500 *suggested_name = FilePath::FromUTF8Unsafe(*opt_name); |
| 501 | 501 |
| 502 // Don't allow any path components; shorten to the base name. This should | 502 // Don't allow any path components; shorten to the base name. This should |
| 503 // result in a relative path, but in some cases may not. Clear the | 503 // result in a relative path, but in some cases may not. Clear the |
| 504 // suggestion for safety if this is the case. | 504 // suggestion for safety if this is the case. |
| 505 *suggested_name = suggested_name->BaseName(); | 505 *suggested_name = suggested_name->BaseName(); |
| 506 if (suggested_name->IsAbsolute()) | 506 if (suggested_name->IsAbsolute()) |
| 507 *suggested_name = FilePath(); | 507 *suggested_name = FilePath(); |
| 508 | 508 |
| 509 *suggested_extension = suggested_name->Extension(); | 509 *suggested_extension = suggested_name->Extension(); |
| 510 if (!suggested_extension->empty()) | 510 if (!suggested_extension->empty()) |
| 511 suggested_extension->erase(suggested_extension->begin()); // drop the . | 511 suggested_extension->erase(suggested_extension->begin()); // drop the . |
| 512 } | 512 } |
| 513 } | 513 } |
| 514 | 514 |
| 515 bool FileSystemChooseFileFunction::RunImpl() { | 515 bool FileSystemChooseEntryFunction::RunImpl() { |
| 516 scoped_ptr<ChooseFile::Params> params(ChooseFile::Params::Create(*args_)); | 516 scoped_ptr<ChooseEntry::Params> params(ChooseEntry::Params::Create(*args_)); |
| 517 EXTENSION_FUNCTION_VALIDATE(params.get()); | 517 EXTENSION_FUNCTION_VALIDATE(params.get()); |
| 518 | 518 |
| 519 FilePath suggested_name; | 519 FilePath suggested_name; |
| 520 ui::SelectFileDialog::FileTypeInfo file_type_info; | 520 ui::SelectFileDialog::FileTypeInfo file_type_info; |
| 521 EntryType entry_type = READ_ONLY; | 521 EntryType entry_type = READ_ONLY; |
| 522 ui::SelectFileDialog::Type picker_type = | 522 ui::SelectFileDialog::Type picker_type = |
| 523 ui::SelectFileDialog::SELECT_OPEN_FILE; | 523 ui::SelectFileDialog::SELECT_OPEN_FILE; |
| 524 | 524 |
| 525 file_system::ChooseFileOptions* options = params->options.get(); | 525 file_system::ChooseEntryOptions* options = params->options.get(); |
| 526 if (options) { | 526 if (options) { |
| 527 if (options->type.get()) { | 527 if (options->type.get()) { |
| 528 if (*options->type == kOpenWritableFileOption) { | 528 if (*options->type == kOpenWritableFileOption) { |
| 529 entry_type = WRITABLE; | 529 entry_type = WRITABLE; |
| 530 } else if (*options->type == kSaveFileOption) { | 530 } else if (*options->type == kSaveFileOption) { |
| 531 entry_type = WRITABLE; | 531 entry_type = WRITABLE; |
| 532 picker_type = ui::SelectFileDialog::SELECT_SAVEAS_FILE; | 532 picker_type = ui::SelectFileDialog::SELECT_SAVEAS_FILE; |
| 533 } else if (*options->type != kOpenFileOption) { | 533 } else if (*options->type != kOpenFileOption) { |
| 534 error_ = kUnknownChooseFileType; | 534 error_ = kUnknownChooseEntryType; |
| 535 return false; | 535 return false; |
| 536 } | 536 } |
| 537 } | 537 } |
| 538 | 538 |
| 539 FilePath::StringType suggested_extension; | 539 FilePath::StringType suggested_extension; |
| 540 BuildSuggestion(options->suggested_name.get(), &suggested_name, | 540 BuildSuggestion(options->suggested_name.get(), &suggested_name, |
| 541 &suggested_extension); | 541 &suggested_extension); |
| 542 | 542 |
| 543 BuildFileTypeInfo(&file_type_info, suggested_extension, | 543 BuildFileTypeInfo(&file_type_info, suggested_extension, |
| 544 options->accepts.get(), options->accepts_all_types.get()); | 544 options->accepts.get(), options->accepts_all_types.get()); |
| 545 } | 545 } |
| 546 | 546 |
| 547 if (entry_type == WRITABLE && !HasFileSystemWritePermission()) { | 547 if (entry_type == WRITABLE && !HasFileSystemWritePermission()) { |
| 548 error_ = kRequiresFileSystemWriteError; | 548 error_ = kRequiresFileSystemWriteError; |
| 549 return false; | 549 return false; |
| 550 } | 550 } |
| 551 | 551 |
| 552 return ShowPicker(suggested_name, file_type_info, picker_type, entry_type); | 552 return ShowPicker(suggested_name, file_type_info, picker_type, entry_type); |
| 553 } | 553 } |
| 554 | 554 |
| 555 } // namespace extensions | 555 } // namespace extensions |
| OLD | NEW |