Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(97)

Side by Side Diff: chrome/browser/ui/views/select_file_dialog_extension.cc

Issue 10584026: Allow ChromeOS file selection dialog to be shown from shell windows. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Cleanup Created 8 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/browser/ui/views/select_file_dialog_extension.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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 }
OLDNEW
« no previous file with comments | « chrome/browser/ui/views/select_file_dialog_extension.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698