| 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/ui/views/select_file_dialog_extension.h" | 5 #include "chrome/browser/ui/views/select_file_dialog_extension.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/callback.h" | 8 #include "base/callback.h" |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/memory/ref_counted.h" | 10 #include "base/memory/ref_counted.h" |
| 11 #include "base/memory/singleton.h" | 11 #include "base/memory/singleton.h" |
| 12 #include "base/message_loop.h" | 12 #include "base/message_loop.h" |
| 13 #include "chrome/browser/browser_process.h" |
| 13 #include "chrome/browser/chromeos/extensions/file_browser_private_api.h" | 14 #include "chrome/browser/chromeos/extensions/file_browser_private_api.h" |
| 14 #include "chrome/browser/chromeos/extensions/file_manager_util.h" | 15 #include "chrome/browser/chromeos/extensions/file_manager_util.h" |
| 15 #include "chrome/browser/extensions/extension_host.h" | 16 #include "chrome/browser/extensions/extension_host.h" |
| 16 #include "chrome/browser/extensions/extension_service.h" | 17 #include "chrome/browser/extensions/extension_service.h" |
| 18 #include "chrome/browser/extensions/shell_window_registry.h" |
| 19 #include "chrome/browser/profiles/profile_manager.h" |
| 17 #include "chrome/browser/sessions/restore_tab_helper.h" | 20 #include "chrome/browser/sessions/restore_tab_helper.h" |
| 21 #include "chrome/browser/ui/base_window.h" |
| 18 #include "chrome/browser/ui/browser.h" | 22 #include "chrome/browser/ui/browser.h" |
| 19 #include "chrome/browser/ui/browser_finder.h" | 23 #include "chrome/browser/ui/browser_finder.h" |
| 20 #include "chrome/browser/ui/browser_list.h" | 24 #include "chrome/browser/ui/browser_list.h" |
| 21 #include "chrome/browser/ui/browser_window.h" | 25 #include "chrome/browser/ui/browser_window.h" |
| 26 #include "chrome/browser/ui/extensions/shell_window.h" |
| 22 #include "chrome/browser/ui/tab_contents/tab_contents.h" | 27 #include "chrome/browser/ui/tab_contents/tab_contents.h" |
| 23 #include "chrome/browser/ui/views/extensions/extension_dialog.h" | 28 #include "chrome/browser/ui/views/extensions/extension_dialog.h" |
| 24 #include "content/public/browser/browser_thread.h" | 29 #include "content/public/browser/browser_thread.h" |
| 25 #include "content/public/common/selected_file_info.h" | 30 #include "content/public/common/selected_file_info.h" |
| 26 | 31 |
| 27 using content::BrowserThread; | 32 using content::BrowserThread; |
| 28 | 33 |
| 29 namespace { | 34 namespace { |
| 30 | 35 |
| 31 const int kFileManagerWidth = 954; // pixels | 36 const int kFileManagerWidth = 954; // pixels |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 89 // static | 94 // static |
| 90 SelectFileDialogExtension* SelectFileDialogExtension::Create( | 95 SelectFileDialogExtension* SelectFileDialogExtension::Create( |
| 91 Listener* listener) { | 96 Listener* listener) { |
| 92 return new SelectFileDialogExtension(listener); | 97 return new SelectFileDialogExtension(listener); |
| 93 } | 98 } |
| 94 | 99 |
| 95 SelectFileDialogExtension::SelectFileDialogExtension(Listener* listener) | 100 SelectFileDialogExtension::SelectFileDialogExtension(Listener* listener) |
| 96 : SelectFileDialog(listener), | 101 : SelectFileDialog(listener), |
| 97 has_multiple_file_type_choices_(false), | 102 has_multiple_file_type_choices_(false), |
| 98 tab_id_(0), | 103 tab_id_(0), |
| 99 owner_browser_(NULL), | 104 profile_(NULL), |
| 100 owner_window_(NULL), | 105 owner_window_(NULL), |
| 101 selection_type_(CANCEL), | 106 selection_type_(CANCEL), |
| 102 selection_index_(0), | 107 selection_index_(0), |
| 103 params_(NULL) { | 108 params_(NULL) { |
| 104 } | 109 } |
| 105 | 110 |
| 106 SelectFileDialogExtension::~SelectFileDialogExtension() { | 111 SelectFileDialogExtension::~SelectFileDialogExtension() { |
| 107 if (extension_dialog_) | 112 if (extension_dialog_) |
| 108 extension_dialog_->ObserverDestroyed(); | 113 extension_dialog_->ObserverDestroyed(); |
| 109 } | 114 } |
| 110 | 115 |
| 111 bool SelectFileDialogExtension::IsRunning( | 116 bool SelectFileDialogExtension::IsRunning( |
| 112 gfx::NativeWindow owner_window) const { | 117 gfx::NativeWindow owner_window) const { |
| 113 return owner_window_ == owner_window; | 118 return owner_window_ == owner_window; |
| 114 } | 119 } |
| 115 | 120 |
| 116 void SelectFileDialogExtension::ListenerDestroyed() { | 121 void SelectFileDialogExtension::ListenerDestroyed() { |
| 117 listener_ = NULL; | 122 listener_ = NULL; |
| 118 params_ = NULL; | 123 params_ = NULL; |
| 119 PendingDialog::GetInstance()->Remove(tab_id_); | 124 PendingDialog::GetInstance()->Remove(tab_id_); |
| 120 } | 125 } |
| 121 | 126 |
| 122 void SelectFileDialogExtension::ExtensionDialogClosing( | 127 void SelectFileDialogExtension::ExtensionDialogClosing( |
| 123 ExtensionDialog* dialog) { | 128 ExtensionDialog* dialog) { |
| 124 owner_browser_ = NULL; | 129 profile_ = NULL; |
| 125 owner_window_ = NULL; | 130 owner_window_ = NULL; |
| 126 // Release our reference to the dialog to allow it to close. | 131 // Release our reference to the dialog to allow it to close. |
| 127 extension_dialog_ = NULL; | 132 extension_dialog_ = NULL; |
| 128 PendingDialog::GetInstance()->Remove(tab_id_); | 133 PendingDialog::GetInstance()->Remove(tab_id_); |
| 129 // Actually invoke the appropriate callback on our listener. | 134 // Actually invoke the appropriate callback on our listener. |
| 130 NotifyListener(); | 135 NotifyListener(); |
| 131 } | 136 } |
| 132 | 137 |
| 133 void SelectFileDialogExtension::ExtensionTerminated( | 138 void SelectFileDialogExtension::ExtensionTerminated( |
| 134 ExtensionDialog* dialog) { | 139 ExtensionDialog* dialog) { |
| 135 // The extension would have been unloaded because of the termination, | 140 // The extension would have been unloaded because of the termination, |
| 136 // reload it. | 141 // reload it. |
| 137 std::string extension_id = dialog->host()->extension()->id(); | 142 std::string extension_id = dialog->host()->extension()->id(); |
| 138 // Reload the extension after a bit; the extension may not have been unloaded | 143 // Reload the extension after a bit; the extension may not have been unloaded |
| 139 // yet. We don't want to try to reload the extension only to have the Unload | 144 // yet. We don't want to try to reload the extension only to have the Unload |
| 140 // code execute after us and re-unload the extension. | 145 // code execute after us and re-unload the extension. |
| 141 // | 146 // |
| 142 // TODO(rkc): This is ugly. The ideal solution is that we shouldn't need to | 147 // TODO(rkc): This is ugly. The ideal solution is that we shouldn't need to |
| 143 // reload the extension at all - when we try to open the extension the next | 148 // reload the extension at all - when we try to open the extension the next |
| 144 // time, the extension subsystem would automatically reload it for us. At | 149 // time, the extension subsystem would automatically reload it for us. At |
| 145 // this time though this is broken because of some faulty wiring in | 150 // this time though this is broken because of some faulty wiring in |
| 146 // ExtensionProcessManager::CreateViewHost. Once that is fixed, remove this. | 151 // ExtensionProcessManager::CreateViewHost. Once that is fixed, remove this. |
| 147 if (owner_browser_) { | 152 if (profile_) { |
| 148 MessageLoop::current()->PostTask(FROM_HERE, | 153 MessageLoop::current()->PostTask(FROM_HERE, |
| 149 base::Bind(&ExtensionService::ReloadExtension, | 154 base::Bind(&ExtensionService::ReloadExtension, |
| 150 base::Unretained(owner_browser_->profile()->GetExtensionService()), | 155 base::Unretained(profile_->GetExtensionService()), |
| 151 extension_id)); | 156 extension_id)); |
| 152 } | 157 } |
| 153 | 158 |
| 154 dialog->Close(); | 159 dialog->Close(); |
| 155 } | 160 } |
| 156 | 161 |
| 157 // static | 162 // static |
| 158 void SelectFileDialogExtension::OnFileSelected( | 163 void SelectFileDialogExtension::OnFileSelected( |
| 159 int32 tab_id, | 164 int32 tab_id, |
| 160 const content::SelectedFileInfo& file, | 165 const content::SelectedFileInfo& file, |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 239 const FilePath& default_path, | 244 const FilePath& default_path, |
| 240 const FileTypeInfo* file_types, | 245 const FileTypeInfo* file_types, |
| 241 int file_type_index, | 246 int file_type_index, |
| 242 const FilePath::StringType& default_extension, | 247 const FilePath::StringType& default_extension, |
| 243 gfx::NativeWindow owner_window, | 248 gfx::NativeWindow owner_window, |
| 244 void* params) { | 249 void* params) { |
| 245 if (owner_window_) { | 250 if (owner_window_) { |
| 246 LOG(ERROR) << "File dialog already in use!"; | 251 LOG(ERROR) << "File dialog already in use!"; |
| 247 return; | 252 return; |
| 248 } | 253 } |
| 249 // Extension background pages may not supply an owner_window. | 254 |
| 250 owner_browser_ = (owner_window ? | 255 // The base window to associate the dialog with. |
| 256 BaseWindow* base_window = NULL; |
| 257 |
| 258 // The tab contents to associate the dialog with. |
| 259 const TabContents* tab = NULL; |
| 260 |
| 261 // First try to find a Browser using the supplied owner_window. If no owner |
| 262 // window has been supplied, this is running from a background page and should |
| 263 // be associated with the last active browser. |
| 264 Browser* owner_browser = (owner_window ? |
| 251 browser::FindBrowserWithWindow(owner_window) : | 265 browser::FindBrowserWithWindow(owner_window) : |
| 252 BrowserList::GetLastActive()); | 266 BrowserList::GetLastActive()); |
| 253 if (!owner_browser_) { | 267 if (owner_browser) { |
| 254 NOTREACHED() << "Can't find owning browser"; | 268 base_window = owner_browser->window(); |
| 269 tab = owner_browser->GetActiveTabContents(); |
| 270 profile_ = tab->profile(); |
| 271 } else if (owner_window) { |
| 272 // If an owner_window was supplied but we couldn't find a browser, this |
| 273 // could be for a shell window. |
| 274 // TODO(benwells): Find a better way to get a shell window from a native |
| 275 // window. |
| 276 std::vector<Profile*> profiles = |
| 277 g_browser_process->profile_manager()->GetLoadedProfiles(); |
| 278 for (std::vector<Profile*>::const_iterator iter = profiles.begin(); |
| 279 iter < profiles.end(); iter++) { |
| 280 ShellWindowRegistry* registry = ShellWindowRegistry::Get(*iter); |
| 281 DCHECK(registry); |
| 282 ShellWindow* shell_window = registry->GetShellWindowForNativeWindow( |
| 283 owner_window); |
| 284 if (shell_window) { |
| 285 base_window = shell_window; |
| 286 tab = shell_window->tab_contents(); |
| 287 profile_ = *iter; |
| 288 break; |
| 289 } |
| 290 } |
| 291 } |
| 292 |
| 293 if (!base_window) { |
| 294 NOTREACHED() << "Can't find owning window."; |
| 255 return; | 295 return; |
| 256 } | 296 } |
| 257 | 297 DCHECK(profile_); |
| 258 TabContents* tab = owner_browser_->GetActiveTabContents(); | |
| 259 | 298 |
| 260 // Check if we have another dialog opened in the tab. It's unlikely, but | 299 // Check if we have another dialog opened in the tab. It's unlikely, but |
| 261 // possible. | 300 // possible. If there is no tab contents use a tab_id of 0. A dialog without |
| 301 // an associated tab contents will be shown fully screen; only one at a time |
| 302 // is allowed in this state. |
| 262 int32 tab_id = tab ? tab->restore_tab_helper()->session_id().id() : 0; | 303 int32 tab_id = tab ? tab->restore_tab_helper()->session_id().id() : 0; |
| 263 if (PendingExists(tab_id)) { | 304 if (PendingExists(tab_id)) { |
| 264 DLOG(WARNING) << "Pending dialog exists with id " << tab_id; | 305 DLOG(WARNING) << "Pending dialog exists with id " << tab_id; |
| 265 return; | 306 return; |
| 266 } | 307 } |
| 267 | 308 |
| 268 FilePath virtual_path; | 309 FilePath virtual_path; |
| 269 if (!file_manager_util::ConvertFileToRelativeFileSystemPath( | 310 if (!file_manager_util::ConvertFileToRelativeFileSystemPath( |
| 270 owner_browser_->profile(), default_path, &virtual_path)) { | 311 profile_, default_path, &virtual_path)) { |
| 271 virtual_path = default_path.BaseName(); | 312 virtual_path = default_path.BaseName(); |
| 272 } | 313 } |
| 273 | 314 |
| 274 has_multiple_file_type_choices_ = | 315 has_multiple_file_type_choices_ = |
| 275 file_types ? file_types->extensions.size() > 1 : true; | 316 file_types ? file_types->extensions.size() > 1 : true; |
| 276 | 317 |
| 277 GURL file_browser_url = file_manager_util::GetFileBrowserUrlWithParams( | 318 GURL file_browser_url = file_manager_util::GetFileBrowserUrlWithParams( |
| 278 type, title, virtual_path, file_types, file_type_index, | 319 type, title, virtual_path, file_types, file_type_index, |
| 279 default_extension); | 320 default_extension); |
| 280 | 321 |
| 281 ExtensionDialog* dialog = ExtensionDialog::Show(file_browser_url, | 322 ExtensionDialog* dialog = ExtensionDialog::Show(file_browser_url, |
| 282 owner_browser_, tab->web_contents(), | 323 base_window, profile_, tab->web_contents(), |
| 283 kFileManagerWidth, kFileManagerHeight, | 324 kFileManagerWidth, kFileManagerHeight, |
| 284 #if defined(USE_AURA) | 325 #if defined(USE_AURA) |
| 285 file_manager_util::GetTitleFromType(type), | 326 file_manager_util::GetTitleFromType(type), |
| 286 #else | 327 #else |
| 287 // HTML-based header used. | 328 // HTML-based header used. |
| 288 string16(), | 329 string16(), |
| 289 #endif | 330 #endif |
| 290 this /* ExtensionDialog::Observer */); | 331 this /* ExtensionDialog::Observer */); |
| 291 if (!dialog) { | 332 if (!dialog) { |
| 292 LOG(ERROR) << "Unable to create extension dialog"; | 333 LOG(ERROR) << "Unable to create extension dialog"; |
| 293 return; | 334 return; |
| 294 } | 335 } |
| 295 | 336 |
| 296 // Connect our listener to FileDialogFunction's per-tab callbacks. | 337 // Connect our listener to FileDialogFunction's per-tab callbacks. |
| 297 AddPending(tab_id); | 338 AddPending(tab_id); |
| 298 | 339 |
| 299 extension_dialog_ = dialog; | 340 extension_dialog_ = dialog; |
| 300 params_ = params; | 341 params_ = params; |
| 301 tab_id_ = tab_id; | 342 tab_id_ = tab_id; |
| 302 owner_window_ = owner_window; | 343 owner_window_ = owner_window; |
| 303 } | 344 } |
| OLD | NEW |