OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/ui/views/select_file_dialog_extension.h" | 5 #include "chrome/browser/ui/views/select_file_dialog_extension.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 #include "base/memory/ref_counted.h" | 8 #include "base/memory/ref_counted.h" |
9 #include "base/memory/singleton.h" | 9 #include "base/memory/singleton.h" |
10 #include "chrome/browser/extensions/extension_file_browser_private_api.h" | 10 #include "chrome/browser/extensions/extension_file_browser_private_api.h" |
(...skipping 16 matching lines...) Expand all Loading... |
27 const int kFileManagerWidth = 720; // pixels | 27 const int kFileManagerWidth = 720; // pixels |
28 const int kFileManagerHeight = 580; // pixels | 28 const int kFileManagerHeight = 580; // pixels |
29 | 29 |
30 // Holds references to file manager dialogs that have callbacks pending | 30 // Holds references to file manager dialogs that have callbacks pending |
31 // to their listeners. | 31 // to their listeners. |
32 class PendingDialog { | 32 class PendingDialog { |
33 public: | 33 public: |
34 static PendingDialog* GetInstance(); | 34 static PendingDialog* GetInstance(); |
35 void Add(int32 tab_id, scoped_refptr<SelectFileDialogExtension> dialog); | 35 void Add(int32 tab_id, scoped_refptr<SelectFileDialogExtension> dialog); |
36 void Remove(int32 tab_id); | 36 void Remove(int32 tab_id); |
37 // Returns scoped_refptr because in some cases, when the listener receives | |
38 // the callback, it deletes itself and the reference to the dialog, and | |
39 // otherwise we end up calling Close on a deleted dialog. | |
40 scoped_refptr<SelectFileDialogExtension> Find(int32 tab_id); | 37 scoped_refptr<SelectFileDialogExtension> Find(int32 tab_id); |
41 | 38 |
42 private: | 39 private: |
43 friend struct DefaultSingletonTraits<PendingDialog>; | 40 friend struct DefaultSingletonTraits<PendingDialog>; |
44 typedef std::map<int32, scoped_refptr<SelectFileDialogExtension> > Map; | 41 typedef std::map<int32, scoped_refptr<SelectFileDialogExtension> > Map; |
45 Map map_; | 42 Map map_; |
46 }; | 43 }; |
47 | 44 |
48 // static | 45 // static |
49 PendingDialog* PendingDialog::GetInstance() { | 46 PendingDialog* PendingDialog::GetInstance() { |
50 return Singleton<PendingDialog>::get(); | 47 return Singleton<PendingDialog>::get(); |
51 } | 48 } |
52 | 49 |
53 void PendingDialog::Add(int32 tab_id, | 50 void PendingDialog::Add(int32 tab_id, |
54 scoped_refptr<SelectFileDialogExtension> dialog) { | 51 scoped_refptr<SelectFileDialogExtension> dialog) { |
55 DCHECK(dialog); | 52 DCHECK(dialog); |
56 if (map_.find(tab_id) == map_.end()) | 53 if (map_.find(tab_id) == map_.end()) |
57 map_.insert(std::make_pair(tab_id, dialog)); | 54 map_.insert(std::make_pair(tab_id, dialog)); |
58 else | 55 else |
59 LOG(WARNING) << "Duplicate pending dialog " << tab_id; | 56 DLOG(WARNING) << "Duplicate pending dialog " << tab_id; |
60 } | 57 } |
61 | 58 |
62 void PendingDialog::Remove(int32 tab_id) { | 59 void PendingDialog::Remove(int32 tab_id) { |
63 map_.erase(tab_id); | 60 map_.erase(tab_id); |
64 } | 61 } |
65 | 62 |
66 scoped_refptr<SelectFileDialogExtension> PendingDialog::Find(int32 tab_id) { | 63 scoped_refptr<SelectFileDialogExtension> PendingDialog::Find(int32 tab_id) { |
67 Map::const_iterator it = map_.find(tab_id); | 64 Map::const_iterator it = map_.find(tab_id); |
68 if (it == map_.end()) { | 65 if (it == map_.end()) |
69 LOG(WARNING) << "Pending dialog not found " << tab_id; | |
70 return NULL; | 66 return NULL; |
71 } | |
72 return it->second; | 67 return it->second; |
73 } | 68 } |
74 | 69 |
75 } // namespace | 70 } // namespace |
76 | 71 |
77 // Linking this implementation of SelectFileDialog::Create into the target | 72 // Linking this implementation of SelectFileDialog::Create into the target |
78 // selects FileManagerDialog as the dialog of choice. | 73 // selects FileManagerDialog as the dialog of choice. |
79 // TODO(jamescook): Move this into a new file shell_dialogs_chromeos.cc | 74 // TODO(jamescook): Move this into a new file shell_dialogs_chromeos.cc |
80 // TODO(jamescook): Change all instances of SelectFileDialog::Create to return | 75 // TODO(jamescook): Change all instances of SelectFileDialog::Create to return |
81 // scoped_refptr<SelectFileDialog> as object is ref-counted. | 76 // scoped_refptr<SelectFileDialog> as object is ref-counted. |
82 // static | 77 // static |
83 SelectFileDialog* SelectFileDialog::Create(Listener* listener) { | 78 SelectFileDialog* SelectFileDialog::Create(Listener* listener) { |
84 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 79 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
85 return SelectFileDialogExtension::Create(listener); | 80 return SelectFileDialogExtension::Create(listener); |
86 } | 81 } |
87 | 82 |
88 ///////////////////////////////////////////////////////////////////////////// | 83 ///////////////////////////////////////////////////////////////////////////// |
89 | 84 |
90 // static | 85 // static |
91 SelectFileDialogExtension* SelectFileDialogExtension::Create( | 86 SelectFileDialogExtension* SelectFileDialogExtension::Create( |
92 Listener* listener) { | 87 Listener* listener) { |
93 return new SelectFileDialogExtension(listener); | 88 return new SelectFileDialogExtension(listener); |
94 } | 89 } |
95 | 90 |
96 SelectFileDialogExtension::SelectFileDialogExtension(Listener* listener) | 91 SelectFileDialogExtension::SelectFileDialogExtension(Listener* listener) |
97 : SelectFileDialog(listener), | 92 : SelectFileDialog(listener), |
98 has_multiple_file_type_choices_(false), | 93 has_multiple_file_type_choices_(false), |
99 params_(NULL), | |
100 tab_id_(0), | 94 tab_id_(0), |
101 owner_window_(0) { | 95 owner_window_(0), |
| 96 selection_type_(CANCEL), |
| 97 selection_index_(0), |
| 98 params_(NULL) { |
102 } | 99 } |
103 | 100 |
104 SelectFileDialogExtension::~SelectFileDialogExtension() { | 101 SelectFileDialogExtension::~SelectFileDialogExtension() { |
105 if (extension_dialog_) | 102 if (extension_dialog_) |
106 extension_dialog_->ObserverDestroyed(); | 103 extension_dialog_->ObserverDestroyed(); |
107 } | 104 } |
108 | 105 |
109 bool SelectFileDialogExtension::IsRunning( | 106 bool SelectFileDialogExtension::IsRunning( |
110 gfx::NativeWindow owner_window) const { | 107 gfx::NativeWindow owner_window) const { |
111 return owner_window_ == owner_window; | 108 return owner_window_ == owner_window; |
112 } | 109 } |
113 | 110 |
114 void SelectFileDialogExtension::ListenerDestroyed() { | 111 void SelectFileDialogExtension::ListenerDestroyed() { |
115 listener_ = NULL; | 112 listener_ = NULL; |
116 params_ = NULL; | 113 params_ = NULL; |
117 PendingDialog::GetInstance()->Remove(tab_id_); | 114 PendingDialog::GetInstance()->Remove(tab_id_); |
118 } | 115 } |
119 | 116 |
120 void SelectFileDialogExtension::ExtensionDialogIsClosing( | 117 void SelectFileDialogExtension::ExtensionDialogClosing( |
121 ExtensionDialog* dialog) { | 118 ExtensionDialog* dialog) { |
122 owner_window_ = NULL; | 119 owner_window_ = NULL; |
123 // Release our reference to the dialog to allow it to close. | 120 // Release our reference to the dialog to allow it to close. |
124 extension_dialog_ = NULL; | 121 extension_dialog_ = NULL; |
125 PendingDialog::GetInstance()->Remove(tab_id_); | 122 PendingDialog::GetInstance()->Remove(tab_id_); |
126 } | 123 // Actually invoke the appropriate callback on our listener. |
127 | 124 NotifyListener(); |
128 void SelectFileDialogExtension::Close() { | |
129 if (extension_dialog_) | |
130 extension_dialog_->Close(); | |
131 PendingDialog::GetInstance()->Remove(tab_id_); | |
132 } | 125 } |
133 | 126 |
134 // static | 127 // static |
135 void SelectFileDialogExtension::OnFileSelected( | 128 void SelectFileDialogExtension::OnFileSelected( |
136 int32 tab_id, const FilePath& path, int index) { | 129 int32 tab_id, const FilePath& path, int index) { |
137 scoped_refptr<SelectFileDialogExtension> dialog = | 130 scoped_refptr<SelectFileDialogExtension> dialog = |
138 PendingDialog::GetInstance()->Find(tab_id); | 131 PendingDialog::GetInstance()->Find(tab_id); |
139 if (dialog) { | 132 if (!dialog) |
140 DCHECK(dialog->listener_); | 133 return; |
141 dialog->listener_->FileSelected(path, index, dialog->params_); | 134 dialog->selection_type_ = SINGLE_FILE; |
142 dialog->Close(); | 135 dialog->selection_files_.clear(); |
143 } | 136 dialog->selection_files_.push_back(path); |
| 137 dialog->selection_index_ = index; |
144 } | 138 } |
145 | 139 |
146 // static | 140 // static |
147 void SelectFileDialogExtension::OnMultiFilesSelected( | 141 void SelectFileDialogExtension::OnMultiFilesSelected( |
148 int32 tab_id, const std::vector<FilePath>& files) { | 142 int32 tab_id, const std::vector<FilePath>& files) { |
149 scoped_refptr<SelectFileDialogExtension> dialog = | 143 scoped_refptr<SelectFileDialogExtension> dialog = |
150 PendingDialog::GetInstance()->Find(tab_id); | 144 PendingDialog::GetInstance()->Find(tab_id); |
151 if (dialog) { | 145 if (!dialog) |
152 DCHECK(dialog->listener_); | 146 return; |
153 dialog->listener_->MultiFilesSelected(files, dialog->params_); | 147 dialog->selection_type_ = MULTIPLE_FILES; |
154 dialog->Close(); | 148 dialog->selection_files_ = files; |
155 } | 149 dialog->selection_index_ = 0; |
156 } | 150 } |
157 | 151 |
158 // static | 152 // static |
159 void SelectFileDialogExtension::OnFileSelectionCanceled(int32 tab_id) { | 153 void SelectFileDialogExtension::OnFileSelectionCanceled(int32 tab_id) { |
160 scoped_refptr<SelectFileDialogExtension> dialog = | 154 scoped_refptr<SelectFileDialogExtension> dialog = |
161 PendingDialog::GetInstance()->Find(tab_id); | 155 PendingDialog::GetInstance()->Find(tab_id); |
162 if (dialog) { | 156 if (!dialog) |
163 DCHECK(dialog->listener_); | 157 return; |
164 dialog->listener_->FileSelectionCanceled(dialog->params_); | 158 dialog->selection_type_ = CANCEL; |
165 dialog->Close(); | 159 dialog->selection_files_.clear(); |
166 } | 160 dialog->selection_index_ = 0; |
167 } | 161 } |
168 | 162 |
169 RenderViewHost* SelectFileDialogExtension::GetRenderViewHost() { | 163 RenderViewHost* SelectFileDialogExtension::GetRenderViewHost() { |
170 if (extension_dialog_) | 164 if (extension_dialog_) |
171 return extension_dialog_->host()->render_view_host(); | 165 return extension_dialog_->host()->render_view_host(); |
172 return NULL; | 166 return NULL; |
173 } | 167 } |
174 | 168 |
| 169 void SelectFileDialogExtension::NotifyListener() { |
| 170 if (!listener_) |
| 171 return; |
| 172 switch (selection_type_) { |
| 173 case CANCEL: |
| 174 listener_->FileSelectionCanceled(params_); |
| 175 break; |
| 176 case SINGLE_FILE: |
| 177 listener_->FileSelected(selection_files_[0], selection_index_, params_); |
| 178 break; |
| 179 case MULTIPLE_FILES: |
| 180 listener_->MultiFilesSelected(selection_files_, params_); |
| 181 break; |
| 182 default: |
| 183 NOTREACHED(); |
| 184 break; |
| 185 } |
| 186 } |
| 187 |
175 void SelectFileDialogExtension::AddPending(int32 tab_id) { | 188 void SelectFileDialogExtension::AddPending(int32 tab_id) { |
176 PendingDialog::GetInstance()->Add(tab_id, this); | 189 PendingDialog::GetInstance()->Add(tab_id, this); |
177 } | 190 } |
178 | 191 |
179 // static | 192 // static |
180 bool SelectFileDialogExtension::PendingExists(int32 tab_id) { | 193 bool SelectFileDialogExtension::PendingExists(int32 tab_id) { |
181 return PendingDialog::GetInstance()->Find(tab_id) != NULL; | 194 return PendingDialog::GetInstance()->Find(tab_id) != NULL; |
182 } | 195 } |
183 | 196 |
184 bool SelectFileDialogExtension::HasMultipleFileTypeChoicesImpl() { | 197 bool SelectFileDialogExtension::HasMultipleFileTypeChoicesImpl() { |
(...skipping 20 matching lines...) Expand all Loading... |
205 if (!owner_browser) { | 218 if (!owner_browser) { |
206 NOTREACHED() << "Can't find owning browser"; | 219 NOTREACHED() << "Can't find owning browser"; |
207 return; | 220 return; |
208 } | 221 } |
209 | 222 |
210 TabContentsWrapper* tab = owner_browser->GetSelectedTabContentsWrapper(); | 223 TabContentsWrapper* tab = owner_browser->GetSelectedTabContentsWrapper(); |
211 | 224 |
212 // Check if we have another dialog opened in the tab. It's unlikely, but | 225 // Check if we have another dialog opened in the tab. It's unlikely, but |
213 // possible. | 226 // possible. |
214 int32 tab_id = tab ? tab->restore_tab_helper()->session_id().id() : 0; | 227 int32 tab_id = tab ? tab->restore_tab_helper()->session_id().id() : 0; |
215 if (PendingExists(tab_id)) | 228 if (PendingExists(tab_id)) { |
| 229 DLOG(WARNING) << "Pending dialog exists with id " << tab_id; |
216 return; | 230 return; |
| 231 } |
217 | 232 |
218 FilePath virtual_path; | 233 FilePath virtual_path; |
219 if (!file_manager_util::ConvertFileToRelativeFileSystemPath( | 234 if (!file_manager_util::ConvertFileToRelativeFileSystemPath( |
220 owner_browser->profile(), default_path, &virtual_path)) { | 235 owner_browser->profile(), default_path, &virtual_path)) { |
221 virtual_path = default_path.BaseName(); | 236 virtual_path = default_path.BaseName(); |
222 } | 237 } |
223 | 238 |
224 has_multiple_file_type_choices_ = | 239 has_multiple_file_type_choices_ = |
225 file_types ? file_types->extensions.size() > 1 : true; | 240 file_types ? file_types->extensions.size() > 1 : true; |
226 | 241 |
(...skipping 11 matching lines...) Expand all Loading... |
238 } | 253 } |
239 | 254 |
240 // Connect our listener to FileDialogFunction's per-tab callbacks. | 255 // Connect our listener to FileDialogFunction's per-tab callbacks. |
241 AddPending(tab_id); | 256 AddPending(tab_id); |
242 | 257 |
243 extension_dialog_ = dialog; | 258 extension_dialog_ = dialog; |
244 params_ = params; | 259 params_ = params; |
245 tab_id_ = tab_id; | 260 tab_id_ = tab_id; |
246 owner_window_ = owner_window; | 261 owner_window_ = owner_window; |
247 } | 262 } |
OLD | NEW |