1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 23345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Use of this source code is governed by a BSD-style license that can be 33345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// found in the LICENSE file. 43345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 53345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "chrome/browser/file_select_helper.h" 63345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include <string> 821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 93345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/file_util.h" 103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/string_split.h" 113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/string_util.h" 123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/utf_string_conversions.h" 133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "chrome/browser/platform_util.h" 1421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/profiles/profile.h" 15ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/browser/child_process_security_policy.h" 16ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/browser/renderer_host/render_process_host.h" 17dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/renderer_host/render_view_host.h" 18dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/renderer_host/render_widget_host_view.h" 19ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/browser/tab_contents/tab_contents.h" 20ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/ui/browser.h" 21ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/ui/browser_list.h" 22ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/common/notification_details.h" 23ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/common/notification_source.h" 24ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/common/view_messages.h" 253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "grit/generated_resources.h" 26ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "net/base/mime_util.h" 2772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/l10n/l10n_util.h" 283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 29ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsennamespace { 30ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 31ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// There is only one file-selection happening at any given time, 32ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// so we allocate an enumeration ID for that purpose. All IDs from 33ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// the renderer must start at 0 and increase. 34ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenstatic const int kFileSelectEnumerationId = -1; 35ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 36ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 37ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenstruct FileSelectHelper::ActiveDirectoryEnumeration { 38ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ActiveDirectoryEnumeration() {} 39ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 40ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen scoped_ptr<DirectoryListerDispatchDelegate> delegate_; 41ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen scoped_refptr<net::DirectoryLister> lister_; 42ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen RenderViewHost* rvh_; 43ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::vector<FilePath> results_; 44ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}; 45ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 463345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickFileSelectHelper::FileSelectHelper(Profile* profile) 473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick : profile_(profile), 483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick render_view_host_(NULL), 493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick select_file_dialog_(), 503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick dialog_type_(SelectFileDialog::SELECT_OPEN_FILE) { 513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 533345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickFileSelectHelper::~FileSelectHelper() { 543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // There may be pending file dialogs, we need to tell them that we've gone 553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // away so they don't try and call back to us. 563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (select_file_dialog_.get()) 573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick select_file_dialog_->ListenerDestroyed(); 583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 59ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Stop any pending directory enumeration, prevent a callback, and free 60ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // allocated memory. 61ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::map<int, ActiveDirectoryEnumeration*>::iterator iter; 62ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (iter = directory_enumerations_.begin(); 63ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen iter != directory_enumerations_.end(); 64ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ++iter) { 65ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (iter->second->lister_.get()) { 66ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen iter->second->lister_->set_delegate(NULL); 67ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen iter->second->lister_->Cancel(); 68ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 69ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen delete iter->second; 703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid FileSelectHelper::FileSelected(const FilePath& path, 743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick int index, void* params) { 753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!render_view_host_) 763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return; 773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick profile_->set_last_selected_directory(path.DirName()); 793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (dialog_type_ == SelectFileDialog::SELECT_FOLDER) { 81ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen StartNewEnumeration(path, kFileSelectEnumerationId, render_view_host_); 823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return; 833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick std::vector<FilePath> files; 863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick files.push_back(path); 873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick render_view_host_->FilesSelectedInChooser(files); 883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // We are done with this showing of the dialog. 893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick render_view_host_ = NULL; 903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid FileSelectHelper::MultiFilesSelected(const std::vector<FilePath>& files, 933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick void* params) { 943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!files.empty()) 953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick profile_->set_last_selected_directory(files[0].DirName()); 963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!render_view_host_) 973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return; 983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick render_view_host_->FilesSelectedInChooser(files); 1003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // We are done with this showing of the dialog. 1013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick render_view_host_ = NULL; 1023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 1033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid FileSelectHelper::FileSelectionCanceled(void* params) { 1053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!render_view_host_) 1063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return; 1073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // If the user cancels choosing a file to upload we pass back an 1093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // empty vector. 1103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick render_view_host_->FilesSelectedInChooser(std::vector<FilePath>()); 1113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // We are done with this showing of the dialog. 1133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick render_view_host_ = NULL; 1143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 1153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 116ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid FileSelectHelper::StartNewEnumeration(const FilePath& path, 117ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int request_id, 118ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen RenderViewHost* render_view_host) { 119ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen scoped_ptr<ActiveDirectoryEnumeration> entry(new ActiveDirectoryEnumeration); 120ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen entry->rvh_ = render_view_host; 121ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen entry->delegate_.reset(new DirectoryListerDispatchDelegate(this, request_id)); 122ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen entry->lister_ = new net::DirectoryLister(path, 123ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen true, 124ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen net::DirectoryLister::NO_SORT, 125ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen entry->delegate_.get()); 126ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!entry->lister_->Start()) { 127ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (request_id == kFileSelectEnumerationId) 128ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen FileSelectionCanceled(NULL); 129ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen else 130ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen render_view_host->DirectoryEnumerationFinished(request_id, 131ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen entry->results_); 132ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } else { 133ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen directory_enumerations_[request_id] = entry.release(); 134ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 1353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 1363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid FileSelectHelper::OnListFile( 138ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int id, 1393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const net::DirectoryLister::DirectoryListerData& data) { 140ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ActiveDirectoryEnumeration* entry = directory_enumerations_[id]; 141ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 14272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Directory upload returns directories via a "." file, so that 14372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // empty directories are included. This util call just checks 1443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // the flags in the structure; there's no file I/O going on. 1453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (file_util::FileEnumerator::IsDirectory(data.info)) 146ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen entry->results_.push_back(data.path.Append(FILE_PATH_LITERAL("."))); 14772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen else 148ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen entry->results_.push_back(data.path); 1493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 1503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 151ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid FileSelectHelper::OnListDone(int id, int error) { 152ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // This entry needs to be cleaned up when this function is done. 153ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen scoped_ptr<ActiveDirectoryEnumeration> entry(directory_enumerations_[id]); 154ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen directory_enumerations_.erase(id); 155ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!entry->rvh_) 1563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return; 1573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (error) { 1583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick FileSelectionCanceled(NULL); 1593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return; 1603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 161ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (id == kFileSelectEnumerationId) 162ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen entry->rvh_->FilesSelectedInChooser(entry->results_); 163ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen else 164ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen entry->rvh_->DirectoryEnumerationFinished(id, entry->results_); 1653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 1663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1673345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickSelectFileDialog::FileTypeInfo* FileSelectHelper::GetFileTypesFromAcceptType( 1683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const string16& accept_types) { 1693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (accept_types.empty()) 1703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return NULL; 1713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Split the accept-type string on commas. 1733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick std::vector<string16> mime_types; 1743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick base::SplitStringUsingSubstr(accept_types, ASCIIToUTF16(","), &mime_types); 1753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (mime_types.empty()) 1763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return NULL; 1773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Create FileTypeInfo and pre-allocate for the first extension list. 1793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick scoped_ptr<SelectFileDialog::FileTypeInfo> file_type( 1803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick new SelectFileDialog::FileTypeInfo()); 1813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick file_type->include_all_files = true; 1823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick file_type->extensions.resize(1); 1833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick std::vector<FilePath::StringType>* extensions = &file_type->extensions.back(); 1843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Find the correspondinge extensions. 1863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick int valid_type_count = 0; 1873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick int description_id = 0; 1883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick for (size_t i = 0; i < mime_types.size(); ++i) { 1893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick string16 mime_type = mime_types[i]; 1903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick std::string ascii_mime_type = StringToLowerASCII(UTF16ToASCII(mime_type)); 1913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick TrimWhitespace(ascii_mime_type, TRIM_ALL, &ascii_mime_type); 1933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (ascii_mime_type.empty()) 1943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick continue; 1953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick size_t old_extension_size = extensions->size(); 1973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (ascii_mime_type == "image/*") { 1983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick description_id = IDS_IMAGE_FILES; 1993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick net::GetImageExtensions(extensions); 2003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } else if (ascii_mime_type == "audio/*") { 2013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick description_id = IDS_AUDIO_FILES; 2023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick net::GetAudioExtensions(extensions); 2033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } else if (ascii_mime_type == "video/*") { 2043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick description_id = IDS_VIDEO_FILES; 2053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick net::GetVideoExtensions(extensions); 2063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } else { 2073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick net::GetExtensionsForMimeType(ascii_mime_type, extensions); 2083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 2093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 2103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (extensions->size() > old_extension_size) 2113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick valid_type_count++; 2123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 2133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 214201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // If no valid extension is added, bail out. 215201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch if (valid_type_count == 0) 216201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch return NULL; 217201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 2183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Use a generic description "Custom Files" if either of the following is 2193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // true: 2203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // 1) There're multiple types specified, like "audio/*,video/*" 2213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // 2) There're multiple extensions for a MIME type without parameter, like 2223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // "ehtml,shtml,htm,html" for "text/html". On Windows, the select file 2233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // dialog uses the first extension in the list to form the description, 2243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // like "EHTML Files". This is not what we want. 2253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (valid_type_count > 1 || 2263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick (valid_type_count == 1 && description_id == 0 && extensions->size() > 1)) 2273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick description_id = IDS_CUSTOM_FILES; 2283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 2293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (description_id) { 2303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick file_type->extension_description_overrides.push_back( 2313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick l10n_util::GetStringUTF16(description_id)); 2323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 2333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 2343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return file_type.release(); 2353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 2363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 2373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid FileSelectHelper::RunFileChooser( 2383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick RenderViewHost* render_view_host, 239ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen TabContents* tab_contents, 240ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const ViewHostMsg_RunFileChooser_Params& params) { 2413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DCHECK(!render_view_host_); 2423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick render_view_host_ = render_view_host; 2433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick notification_registrar_.RemoveAll(); 2443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick notification_registrar_.Add(this, 2453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick NotificationType::RENDER_WIDGET_HOST_DESTROYED, 2463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick Source<RenderViewHost>(render_view_host)); 2473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 2483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!select_file_dialog_.get()) 2493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick select_file_dialog_ = SelectFileDialog::Create(this); 2503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 2513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick switch (params.mode) { 252ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen case ViewHostMsg_RunFileChooser_Mode::Open: 2533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick dialog_type_ = SelectFileDialog::SELECT_OPEN_FILE; 2543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick break; 255ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen case ViewHostMsg_RunFileChooser_Mode::OpenMultiple: 2563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick dialog_type_ = SelectFileDialog::SELECT_OPEN_MULTI_FILE; 2573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick break; 258ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen case ViewHostMsg_RunFileChooser_Mode::OpenFolder: 2593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick dialog_type_ = SelectFileDialog::SELECT_FOLDER; 2603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick break; 261ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen case ViewHostMsg_RunFileChooser_Mode::Save: 2623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick dialog_type_ = SelectFileDialog::SELECT_SAVEAS_FILE; 2633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick break; 2643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick default: 2653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick dialog_type_ = SelectFileDialog::SELECT_OPEN_FILE; // Prevent warning. 2663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick NOTREACHED(); 2673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 2683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick scoped_ptr<SelectFileDialog::FileTypeInfo> file_types( 2693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick GetFileTypesFromAcceptType(params.accept_types)); 2703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick FilePath default_file_name = params.default_file_name; 2713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (default_file_name.empty()) 2723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick default_file_name = profile_->last_selected_directory(); 2733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 2743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick gfx::NativeWindow owning_window = 2753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick platform_util::GetTopLevel(render_view_host_->view()->GetNativeView()); 276ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 2773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick select_file_dialog_->SelectFile(dialog_type_, 2783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick params.title, 2793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick default_file_name, 2803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick file_types.get(), 281201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch file_types.get() ? 1 : 0, // 1-based index. 2823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick FILE_PATH_LITERAL(""), 283ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen tab_contents, 2843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick owning_window, 2853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick NULL); 2863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 2873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 288ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid FileSelectHelper::EnumerateDirectory(int request_id, 289ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen RenderViewHost* render_view_host, 290ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const FilePath& path) { 291ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK_NE(kFileSelectEnumerationId, request_id); 292ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen StartNewEnumeration(path, request_id, render_view_host); 293ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 294ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 2953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid FileSelectHelper::Observe(NotificationType type, 2963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const NotificationSource& source, 2973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const NotificationDetails& details) { 2983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DCHECK(type == NotificationType::RENDER_WIDGET_HOST_DESTROYED); 2993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DCHECK(Details<RenderViewHost>(details).ptr() == render_view_host_); 3003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick render_view_host_ = NULL; 3013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 302ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 303ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenFileSelectObserver::FileSelectObserver(TabContents* tab_contents) 304ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen : TabContentsObserver(tab_contents) { 305ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 306ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 307ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenFileSelectObserver::~FileSelectObserver() { 308ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 309ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 310ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool FileSelectObserver::OnMessageReceived(const IPC::Message& message) { 311ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen bool handled = true; 312ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen IPC_BEGIN_MESSAGE_MAP(FileSelectObserver, message) 313ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen IPC_MESSAGE_HANDLER(ViewHostMsg_RunFileChooser, OnRunFileChooser) 314ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen IPC_MESSAGE_HANDLER(ViewHostMsg_EnumerateDirectory, OnEnumerateDirectory) 315ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen IPC_MESSAGE_UNHANDLED(handled = false) 316ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen IPC_END_MESSAGE_MAP() 317ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 318ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return handled; 319ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 320ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 321ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid FileSelectObserver::OnRunFileChooser( 322ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const ViewHostMsg_RunFileChooser_Params& params) { 323ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!file_select_helper_.get()) 324ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen file_select_helper_.reset(new FileSelectHelper(tab_contents()->profile())); 325ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen file_select_helper_->RunFileChooser(tab_contents()->render_view_host(), 326ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen tab_contents(), 327ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen params); 328ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 329ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 330ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid FileSelectObserver::OnEnumerateDirectory(int request_id, 331ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const FilePath& path) { 332ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ChildProcessSecurityPolicy* policy = 333ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ChildProcessSecurityPolicy::GetInstance(); 334ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!policy->CanReadDirectory( 335ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen tab_contents()->render_view_host()->process()->id(), 336ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen path)) { 337ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return; 338ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 339ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 340ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!file_select_helper_.get()) 341ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen file_select_helper_.reset(new FileSelectHelper(tab_contents()->profile())); 342ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen file_select_helper_->EnumerateDirectory(request_id, 343ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen tab_contents()->render_view_host(), 344ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen path); 345ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 346