| 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/path_service.h" | 10 #include "base/path_service.h" |
| (...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 236 return true; | 236 return true; |
| 237 } | 237 } |
| 238 | 238 |
| 239 // Handles showing a dialog to the user to ask for the filename for a file to | 239 // Handles showing a dialog to the user to ask for the filename for a file to |
| 240 // save or open. | 240 // save or open. |
| 241 class FileSystemChooseFileFunction::FilePicker | 241 class FileSystemChooseFileFunction::FilePicker |
| 242 : public SelectFileDialog::Listener { | 242 : public SelectFileDialog::Listener { |
| 243 public: | 243 public: |
| 244 FilePicker(FileSystemChooseFileFunction* function, | 244 FilePicker(FileSystemChooseFileFunction* function, |
| 245 content::WebContents* web_contents, | 245 content::WebContents* web_contents, |
| 246 const FilePath& suggested_path, | 246 const FilePath& suggested_name, |
| 247 SelectFileDialog::Type picker_type, | 247 SelectFileDialog::Type picker_type, |
| 248 EntryType entry_type) | 248 EntryType entry_type) |
| 249 : suggested_path_(suggested_path), | 249 : suggested_name_(suggested_name), |
| 250 entry_type_(entry_type), | 250 entry_type_(entry_type), |
| 251 function_(function) { | 251 function_(function) { |
| 252 select_file_dialog_ = SelectFileDialog::Create( | 252 select_file_dialog_ = SelectFileDialog::Create( |
| 253 this, new ChromeSelectFilePolicy(web_contents)); | 253 this, new ChromeSelectFilePolicy(web_contents)); |
| 254 SelectFileDialog::FileTypeInfo file_type_info; | 254 SelectFileDialog::FileTypeInfo file_type_info; |
| 255 FilePath::StringType extension = suggested_path.Extension(); | 255 FilePath::StringType extension = suggested_name.Extension(); |
| 256 if (!extension.empty()) { | 256 if (!extension.empty()) { |
| 257 extension.erase(extension.begin()); // drop the . | 257 extension.erase(extension.begin()); // drop the . |
| 258 file_type_info.extensions.resize(1); | 258 file_type_info.extensions.resize(1); |
| 259 file_type_info.extensions[0].push_back(extension); | 259 file_type_info.extensions[0].push_back(extension); |
| 260 } | 260 } |
| 261 file_type_info.include_all_files = true; | 261 file_type_info.include_all_files = true; |
| 262 gfx::NativeWindow owning_window = web_contents ? | 262 gfx::NativeWindow owning_window = web_contents ? |
| 263 platform_util::GetTopLevel(web_contents->GetNativeView()) : NULL; | 263 platform_util::GetTopLevel(web_contents->GetNativeView()) : NULL; |
| 264 | 264 |
| 265 if (g_skip_picker_for_test) { | 265 if (g_skip_picker_for_test) { |
| 266 if (g_path_to_be_picked_for_test) { | 266 if (g_path_to_be_picked_for_test) { |
| 267 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, | 267 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, |
| 268 base::Bind( | 268 base::Bind( |
| 269 &FileSystemChooseFileFunction::FilePicker::FileSelected, | 269 &FileSystemChooseFileFunction::FilePicker::FileSelected, |
| 270 base::Unretained(this), *g_path_to_be_picked_for_test, 1, | 270 base::Unretained(this), *g_path_to_be_picked_for_test, 1, |
| 271 static_cast<void*>(NULL))); | 271 static_cast<void*>(NULL))); |
| 272 } else { | 272 } else { |
| 273 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, | 273 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, |
| 274 base::Bind( | 274 base::Bind( |
| 275 &FileSystemChooseFileFunction::FilePicker:: | 275 &FileSystemChooseFileFunction::FilePicker:: |
| 276 FileSelectionCanceled, | 276 FileSelectionCanceled, |
| 277 base::Unretained(this), static_cast<void*>(NULL))); | 277 base::Unretained(this), static_cast<void*>(NULL))); |
| 278 } | 278 } |
| 279 return; | 279 return; |
| 280 } | 280 } |
| 281 | 281 |
| 282 select_file_dialog_->SelectFile(picker_type, | 282 select_file_dialog_->SelectFile(picker_type, |
| 283 string16(), | 283 string16(), |
| 284 suggested_path, | 284 suggested_name, |
| 285 &file_type_info, 0, FILE_PATH_LITERAL(""), | 285 &file_type_info, 0, FILE_PATH_LITERAL(""), |
| 286 owning_window, NULL); | 286 owning_window, NULL); |
| 287 } | 287 } |
| 288 | 288 |
| 289 virtual ~FilePicker() {} | 289 virtual ~FilePicker() {} |
| 290 | 290 |
| 291 private: | 291 private: |
| 292 // SelectFileDialog::Listener implementation. | 292 // SelectFileDialog::Listener implementation. |
| 293 virtual void FileSelected(const FilePath& path, | 293 virtual void FileSelected(const FilePath& path, |
| 294 int index, | 294 int index, |
| 295 void* params) OVERRIDE { | 295 void* params) OVERRIDE { |
| 296 function_->FileSelected(path, entry_type_); | 296 function_->FileSelected(path, entry_type_); |
| 297 delete this; | 297 delete this; |
| 298 } | 298 } |
| 299 | 299 |
| 300 virtual void FileSelectionCanceled(void* params) OVERRIDE { | 300 virtual void FileSelectionCanceled(void* params) OVERRIDE { |
| 301 function_->FileSelectionCanceled(); | 301 function_->FileSelectionCanceled(); |
| 302 delete this; | 302 delete this; |
| 303 } | 303 } |
| 304 | 304 |
| 305 FilePath suggested_path_; | 305 FilePath suggested_name_; |
| 306 | 306 |
| 307 EntryType entry_type_; | 307 EntryType entry_type_; |
| 308 | 308 |
| 309 scoped_refptr<SelectFileDialog> select_file_dialog_; | 309 scoped_refptr<SelectFileDialog> select_file_dialog_; |
| 310 scoped_refptr<FileSystemChooseFileFunction> function_; | 310 scoped_refptr<FileSystemChooseFileFunction> function_; |
| 311 | 311 |
| 312 DISALLOW_COPY_AND_ASSIGN(FilePicker); | 312 DISALLOW_COPY_AND_ASSIGN(FilePicker); |
| 313 }; | 313 }; |
| 314 | 314 |
| 315 bool FileSystemChooseFileFunction::ShowPicker( | 315 bool FileSystemChooseFileFunction::ShowPicker( |
| 316 const FilePath& suggested_path, | 316 const FilePath& suggested_name, |
| 317 SelectFileDialog::Type picker_type, | 317 SelectFileDialog::Type picker_type, |
| 318 EntryType entry_type) { | 318 EntryType entry_type) { |
| 319 ShellWindowRegistry* registry = ShellWindowRegistry::Get(profile()); | 319 ShellWindowRegistry* registry = ShellWindowRegistry::Get(profile()); |
| 320 DCHECK(registry); | 320 DCHECK(registry); |
| 321 ShellWindow* shell_window = registry->GetShellWindowForRenderViewHost( | 321 ShellWindow* shell_window = registry->GetShellWindowForRenderViewHost( |
| 322 render_view_host()); | 322 render_view_host()); |
| 323 if (!shell_window) { | 323 if (!shell_window) { |
| 324 error_ = kInvalidCallingPage; | 324 error_ = kInvalidCallingPage; |
| 325 return false; | 325 return false; |
| 326 } | 326 } |
| 327 | 327 |
| 328 // The file picker will hold a reference to this function instance, preventing | 328 // The file picker will hold a reference to this function instance, preventing |
| 329 // its destruction (and subsequent sending of the function response) until the | 329 // its destruction (and subsequent sending of the function response) until the |
| 330 // user has selected a file or cancelled the picker. At that point, the picker | 330 // user has selected a file or cancelled the picker. At that point, the picker |
| 331 // will delete itself, which will also free the function instance. | 331 // will delete itself, which will also free the function instance. |
| 332 new FilePicker(this, shell_window->web_contents(), suggested_path, | 332 new FilePicker(this, shell_window->web_contents(), suggested_name, |
| 333 picker_type, entry_type); | 333 picker_type, entry_type); |
| 334 return true; | 334 return true; |
| 335 } | 335 } |
| 336 | 336 |
| 337 // static | 337 // static |
| 338 void FileSystemChooseFileFunction::SkipPickerAndAlwaysSelectPathForTest( | 338 void FileSystemChooseFileFunction::SkipPickerAndAlwaysSelectPathForTest( |
| 339 FilePath* path) { | 339 FilePath* path) { |
| 340 g_skip_picker_for_test = true; | 340 g_skip_picker_for_test = true; |
| 341 g_path_to_be_picked_for_test = path; | 341 g_path_to_be_picked_for_test = path; |
| 342 } | 342 } |
| (...skipping 24 matching lines...) Expand all Loading... |
| 367 | 367 |
| 368 void FileSystemChooseFileFunction::FileSelectionCanceled() { | 368 void FileSystemChooseFileFunction::FileSelectionCanceled() { |
| 369 error_ = kUserCancelled; | 369 error_ = kUserCancelled; |
| 370 SendResponse(false); | 370 SendResponse(false); |
| 371 } | 371 } |
| 372 | 372 |
| 373 bool FileSystemChooseFileFunction::RunImpl() { | 373 bool FileSystemChooseFileFunction::RunImpl() { |
| 374 scoped_ptr<ChooseFile::Params> params(ChooseFile::Params::Create(*args_)); | 374 scoped_ptr<ChooseFile::Params> params(ChooseFile::Params::Create(*args_)); |
| 375 EXTENSION_FUNCTION_VALIDATE(params.get()); | 375 EXTENSION_FUNCTION_VALIDATE(params.get()); |
| 376 | 376 |
| 377 FilePath suggested_name; |
| 377 EntryType entry_type = READ_ONLY; | 378 EntryType entry_type = READ_ONLY; |
| 378 SelectFileDialog::Type picker_type = SelectFileDialog::SELECT_OPEN_FILE; | 379 SelectFileDialog::Type picker_type = SelectFileDialog::SELECT_OPEN_FILE; |
| 380 |
| 379 file_system::ChooseFileOptions* options = params->options.get(); | 381 file_system::ChooseFileOptions* options = params->options.get(); |
| 380 if (options && options->type.get()) { | 382 if (options) { |
| 381 if (*options->type == kOpenWritableFileOption) { | 383 if (options->type.get()) { |
| 382 entry_type = WRITABLE; | 384 if (*options->type == kOpenWritableFileOption) { |
| 383 } else if (*options->type == kSaveFileOption) { | 385 entry_type = WRITABLE; |
| 384 entry_type = WRITABLE; | 386 } else if (*options->type == kSaveFileOption) { |
| 385 picker_type = SelectFileDialog::SELECT_SAVEAS_FILE; | 387 entry_type = WRITABLE; |
| 386 } else if (*options->type != kOpenFileOption) { | 388 picker_type = SelectFileDialog::SELECT_SAVEAS_FILE; |
| 387 error_ = kUnknownChooseFileType; | 389 } else if (*options->type != kOpenFileOption) { |
| 388 return false; | 390 error_ = kUnknownChooseFileType; |
| 391 return false; |
| 392 } |
| 393 } |
| 394 |
| 395 if (options->suggested_name.get()) { |
| 396 suggested_name = FilePath::FromUTF8Unsafe( |
| 397 *options->suggested_name.get()); |
| 398 |
| 399 // Don't allow any path components; shorten to the base name. This should |
| 400 // result in a relative path, but in some cases may not. Clear the |
| 401 // suggestion for safety if this is the case. |
| 402 suggested_name = suggested_name.BaseName(); |
| 403 if (suggested_name.IsAbsolute()) { |
| 404 suggested_name = FilePath(); |
| 405 } |
| 389 } | 406 } |
| 390 } | 407 } |
| 391 | 408 |
| 392 if (entry_type == WRITABLE && !HasFileSystemWritePermission()) { | 409 if (entry_type == WRITABLE && !HasFileSystemWritePermission()) { |
| 393 error_ = kRequiresFileSystemWriteError; | 410 error_ = kRequiresFileSystemWriteError; |
| 394 return false; | 411 return false; |
| 395 } | 412 } |
| 396 | 413 |
| 397 return ShowPicker(FilePath(), picker_type, entry_type); | 414 return ShowPicker(suggested_name, picker_type, entry_type); |
| 398 } | 415 } |
| 399 | 416 |
| 400 } // namespace extensions | 417 } // namespace extensions |
| OLD | NEW |