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