OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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/file_select_helper.h" | 5 #include "chrome/browser/file_select_helper.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 | 8 |
9 #include "base/file_util.h" | 9 #include "base/file_util.h" |
10 #include "base/string_split.h" | 10 #include "base/string_split.h" |
11 #include "base/string_util.h" | 11 #include "base/string_util.h" |
12 #include "base/utf_string_conversions.h" | 12 #include "base/utf_string_conversions.h" |
13 #include "net/base/mime_util.h" | 13 #include "net/base/mime_util.h" |
14 #include "chrome/browser/platform_util.h" | 14 #include "chrome/browser/platform_util.h" |
15 #include "chrome/browser/profiles/profile.h" | 15 #include "chrome/browser/profiles/profile.h" |
16 #include "chrome/common/notification_details.h" | 16 #include "chrome/common/notification_details.h" |
17 #include "chrome/common/notification_source.h" | 17 #include "chrome/common/notification_source.h" |
18 #include "chrome/common/render_messages_params.h" | 18 #include "chrome/common/render_messages_params.h" |
19 #include "content/browser/renderer_host/render_view_host.h" | 19 #include "content/browser/renderer_host/render_view_host.h" |
20 #include "content/browser/renderer_host/render_widget_host_view.h" | 20 #include "content/browser/renderer_host/render_widget_host_view.h" |
21 #include "grit/generated_resources.h" | 21 #include "grit/generated_resources.h" |
22 #include "ui/base/l10n/l10n_util.h" | 22 #include "ui/base/l10n/l10n_util.h" |
23 | 23 |
| 24 namespace { |
| 25 |
| 26 // There is only one file-selection happening at any given time, |
| 27 // so we allocate an enumeration ID for that purpose. All IDs from |
| 28 // the renderer must start at 0 and increase. |
| 29 static const int kFileSelectEnumerationId = -1; |
| 30 |
| 31 } |
| 32 |
24 FileSelectHelper::FileSelectHelper(Profile* profile) | 33 FileSelectHelper::FileSelectHelper(Profile* profile) |
25 : profile_(profile), | 34 : profile_(profile), |
26 render_view_host_(NULL), | 35 render_view_host_(NULL), |
27 select_file_dialog_(), | 36 select_file_dialog_(), |
28 dialog_type_(SelectFileDialog::SELECT_OPEN_FILE) { | 37 dialog_type_(SelectFileDialog::SELECT_OPEN_FILE) { |
29 } | 38 } |
30 | 39 |
31 FileSelectHelper::~FileSelectHelper() { | 40 FileSelectHelper::~FileSelectHelper() { |
32 // There may be pending file dialogs, we need to tell them that we've gone | 41 // There may be pending file dialogs, we need to tell them that we've gone |
33 // away so they don't try and call back to us. | 42 // away so they don't try and call back to us. |
34 if (select_file_dialog_.get()) | 43 if (select_file_dialog_.get()) |
35 select_file_dialog_->ListenerDestroyed(); | 44 select_file_dialog_->ListenerDestroyed(); |
36 | 45 |
37 // Stop any pending directory enumeration and prevent a callback. | 46 // Stop any pending directory enumeration, prevent a callback, and free |
38 if (directory_lister_.get()) { | 47 // allocated memory. |
39 directory_lister_->set_delegate(NULL); | 48 std::map<int, ActiveDirectoryEnumeration*>::iterator iter; |
40 directory_lister_->Cancel(); | 49 for (iter = directory_enumerations_.begin(); |
| 50 iter != directory_enumerations_.end(); |
| 51 ++iter) { |
| 52 if (iter->second->lister_.get()) { |
| 53 iter->second->lister_->set_delegate(NULL); |
| 54 iter->second->lister_->Cancel(); |
| 55 } |
| 56 delete iter->second; |
41 } | 57 } |
42 } | 58 } |
43 | 59 |
44 void FileSelectHelper::FileSelected(const FilePath& path, | 60 void FileSelectHelper::FileSelected(const FilePath& path, |
45 int index, void* params) { | 61 int index, void* params) { |
46 if (!render_view_host_) | 62 if (!render_view_host_) |
47 return; | 63 return; |
48 | 64 |
49 profile_->set_last_selected_directory(path.DirName()); | 65 profile_->set_last_selected_directory(path.DirName()); |
50 | 66 |
51 if (dialog_type_ == SelectFileDialog::SELECT_FOLDER) { | 67 if (dialog_type_ == SelectFileDialog::SELECT_FOLDER) { |
52 DirectorySelected(path); | 68 StartNewEnumeration(path, kFileSelectEnumerationId, render_view_host_); |
53 return; | 69 return; |
54 } | 70 } |
55 | 71 |
56 std::vector<FilePath> files; | 72 std::vector<FilePath> files; |
57 files.push_back(path); | 73 files.push_back(path); |
58 render_view_host_->FilesSelectedInChooser(files); | 74 render_view_host_->FilesSelectedInChooser(files); |
59 // We are done with this showing of the dialog. | 75 // We are done with this showing of the dialog. |
60 render_view_host_ = NULL; | 76 render_view_host_ = NULL; |
61 } | 77 } |
62 | 78 |
(...skipping 14 matching lines...) Expand all Loading... |
77 return; | 93 return; |
78 | 94 |
79 // If the user cancels choosing a file to upload we pass back an | 95 // If the user cancels choosing a file to upload we pass back an |
80 // empty vector. | 96 // empty vector. |
81 render_view_host_->FilesSelectedInChooser(std::vector<FilePath>()); | 97 render_view_host_->FilesSelectedInChooser(std::vector<FilePath>()); |
82 | 98 |
83 // We are done with this showing of the dialog. | 99 // We are done with this showing of the dialog. |
84 render_view_host_ = NULL; | 100 render_view_host_ = NULL; |
85 } | 101 } |
86 | 102 |
87 void FileSelectHelper::DirectorySelected(const FilePath& path) { | 103 void FileSelectHelper::StartNewEnumeration(const FilePath& path, |
88 directory_lister_ = new net::DirectoryLister(path, | 104 int request_id, |
89 true, | 105 RenderViewHost* render_view_host) { |
90 net::DirectoryLister::NO_SORT, | 106 scoped_ptr<ActiveDirectoryEnumeration> entry(new ActiveDirectoryEnumeration); |
91 this); | 107 entry->rvh_ = render_view_host; |
92 if (!directory_lister_->Start()) | 108 entry->delegate_.reset(new DirectoryListerDispatchDelegate(this, request_id)); |
93 FileSelectionCanceled(NULL); | 109 entry->lister_ = new net::DirectoryLister(path, |
| 110 true, |
| 111 net::DirectoryLister::NO_SORT, |
| 112 entry->delegate_.get()); |
| 113 if (!entry->lister_->Start()) { |
| 114 if (request_id == kFileSelectEnumerationId) |
| 115 FileSelectionCanceled(NULL); |
| 116 else |
| 117 render_view_host->DirectoryEnumerationFinished(request_id, |
| 118 entry->results_); |
| 119 } else { |
| 120 directory_enumerations_[request_id] = entry.release(); |
| 121 } |
94 } | 122 } |
95 | 123 |
96 void FileSelectHelper::OnListFile( | 124 void FileSelectHelper::OnListFile( |
| 125 int id, |
97 const net::DirectoryLister::DirectoryListerData& data) { | 126 const net::DirectoryLister::DirectoryListerData& data) { |
| 127 ActiveDirectoryEnumeration* entry = directory_enumerations_[id]; |
| 128 |
98 // Directory upload returns directories via a "." file, so that | 129 // Directory upload returns directories via a "." file, so that |
99 // empty directories are included. This util call just checks | 130 // empty directories are included. This util call just checks |
100 // the flags in the structure; there's no file I/O going on. | 131 // the flags in the structure; there's no file I/O going on. |
101 if (file_util::FileEnumerator::IsDirectory(data.info)) | 132 if (file_util::FileEnumerator::IsDirectory(data.info)) |
102 directory_lister_results_.push_back( | 133 entry->results_.push_back(data.path.Append(FILE_PATH_LITERAL("."))); |
103 data.path.Append(FILE_PATH_LITERAL("."))); | |
104 else | 134 else |
105 directory_lister_results_.push_back(data.path); | 135 entry->results_.push_back(data.path); |
106 } | 136 } |
107 | 137 |
108 void FileSelectHelper::OnListDone(int error) { | 138 void FileSelectHelper::OnListDone(int id, int error) { |
109 if (!render_view_host_) | 139 // This entry needs to be cleaned up when this function is done. |
| 140 scoped_ptr<ActiveDirectoryEnumeration> entry(directory_enumerations_[id]); |
| 141 directory_enumerations_.erase(id); |
| 142 if (!entry->rvh_) |
110 return; | 143 return; |
111 | |
112 if (error) { | 144 if (error) { |
113 FileSelectionCanceled(NULL); | 145 FileSelectionCanceled(NULL); |
114 return; | 146 return; |
115 } | 147 } |
116 | 148 if (id == kFileSelectEnumerationId) |
117 render_view_host_->FilesSelectedInChooser(directory_lister_results_); | 149 entry->rvh_->FilesSelectedInChooser(entry->results_); |
118 render_view_host_ = NULL; | 150 else |
119 directory_lister_ = NULL; | 151 entry->rvh_->DirectoryEnumerationFinished(id, entry->results_); |
120 directory_lister_results_.clear(); | |
121 } | 152 } |
122 | 153 |
123 SelectFileDialog::FileTypeInfo* FileSelectHelper::GetFileTypesFromAcceptType( | 154 SelectFileDialog::FileTypeInfo* FileSelectHelper::GetFileTypesFromAcceptType( |
124 const string16& accept_types) { | 155 const string16& accept_types) { |
125 if (accept_types.empty()) | 156 if (accept_types.empty()) |
126 return NULL; | 157 return NULL; |
127 | 158 |
128 // Split the accept-type string on commas. | 159 // Split the accept-type string on commas. |
129 std::vector<string16> mime_types; | 160 std::vector<string16> mime_types; |
130 base::SplitStringUsingSubstr(accept_types, ASCIIToUTF16(","), &mime_types); | 161 base::SplitStringUsingSubstr(accept_types, ASCIIToUTF16(","), &mime_types); |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
231 select_file_dialog_->SelectFile(dialog_type_, | 262 select_file_dialog_->SelectFile(dialog_type_, |
232 params.title, | 263 params.title, |
233 default_file_name, | 264 default_file_name, |
234 file_types.get(), | 265 file_types.get(), |
235 file_types.get() ? 1 : 0, // 1-based index. | 266 file_types.get() ? 1 : 0, // 1-based index. |
236 FILE_PATH_LITERAL(""), | 267 FILE_PATH_LITERAL(""), |
237 owning_window, | 268 owning_window, |
238 NULL); | 269 NULL); |
239 } | 270 } |
240 | 271 |
| 272 void FileSelectHelper::EnumerateDirectory(int request_id, |
| 273 RenderViewHost* render_view_host, |
| 274 const FilePath& path) { |
| 275 DCHECK_NE(kFileSelectEnumerationId, request_id); |
| 276 StartNewEnumeration(path, request_id, render_view_host); |
| 277 } |
| 278 |
241 void FileSelectHelper::Observe(NotificationType type, | 279 void FileSelectHelper::Observe(NotificationType type, |
242 const NotificationSource& source, | 280 const NotificationSource& source, |
243 const NotificationDetails& details) { | 281 const NotificationDetails& details) { |
244 DCHECK(type == NotificationType::RENDER_WIDGET_HOST_DESTROYED); | 282 DCHECK(type == NotificationType::RENDER_WIDGET_HOST_DESTROYED); |
245 DCHECK(Details<RenderViewHost>(details).ptr() == render_view_host_); | 283 DCHECK(Details<RenderViewHost>(details).ptr() == render_view_host_); |
246 render_view_host_ = NULL; | 284 render_view_host_ = NULL; |
247 } | 285 } |
OLD | NEW |