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 |