| 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 |