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/file_select_helper.h" | 5 #include "chrome/browser/file_select_helper.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/file_util.h" | 10 #include "base/file_util.h" |
11 #include "base/platform_file.h" | 11 #include "base/platform_file.h" |
12 #include "base/string_split.h" | 12 #include "base/string_split.h" |
13 #include "base/string_util.h" | 13 #include "base/string_util.h" |
14 #include "base/utf_string_conversions.h" | 14 #include "base/utf_string_conversions.h" |
15 #include "chrome/browser/platform_util.h" | 15 #include "chrome/browser/platform_util.h" |
16 #include "chrome/browser/profiles/profile.h" | 16 #include "chrome/browser/profiles/profile.h" |
17 #include "chrome/browser/ui/browser.h" | 17 #include "chrome/browser/ui/browser.h" |
18 #include "chrome/browser/ui/browser_list.h" | 18 #include "chrome/browser/ui/browser_list.h" |
19 #include "content/public/browser/notification_details.h" | 19 #include "content/public/browser/notification_details.h" |
20 #include "content/public/browser/notification_source.h" | 20 #include "content/public/browser/notification_source.h" |
21 #include "content/public/browser/notification_types.h" | 21 #include "content/public/browser/notification_types.h" |
22 #include "content/public/browser/render_view_host.h" | 22 #include "content/public/browser/render_view_host.h" |
23 #include "content/public/browser/render_widget_host_view.h" | 23 #include "content/public/browser/render_widget_host_view.h" |
| 24 #include "content/public/browser/web_contents.h" |
24 #include "content/public/common/file_chooser_params.h" | 25 #include "content/public/common/file_chooser_params.h" |
25 #include "content/public/common/selected_file_info.h" | 26 #include "content/public/common/selected_file_info.h" |
26 #include "grit/generated_resources.h" | 27 #include "grit/generated_resources.h" |
27 #include "net/base/mime_util.h" | 28 #include "net/base/mime_util.h" |
28 #include "ui/base/l10n/l10n_util.h" | 29 #include "ui/base/l10n/l10n_util.h" |
29 | 30 |
30 using content::BrowserThread; | 31 using content::BrowserThread; |
| 32 using content::FileChooserParams; |
31 using content::RenderViewHost; | 33 using content::RenderViewHost; |
32 using content::RenderWidgetHost; | 34 using content::RenderWidgetHost; |
33 using content::WebContents; | 35 using content::WebContents; |
34 | 36 |
35 namespace { | 37 namespace { |
36 | 38 |
37 // There is only one file-selection happening at any given time, | 39 // There is only one file-selection happening at any given time, |
38 // so we allocate an enumeration ID for that purpose. All IDs from | 40 // so we allocate an enumeration ID for that purpose. All IDs from |
39 // the renderer must start at 0 and increase. | 41 // the renderer must start at 0 and increase. |
40 const int kFileSelectEnumerationId = -1; | 42 const int kFileSelectEnumerationId = -1; |
(...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
293 description_id = IDS_CUSTOM_FILES; | 295 description_id = IDS_CUSTOM_FILES; |
294 | 296 |
295 if (description_id) { | 297 if (description_id) { |
296 file_type->extension_description_overrides.push_back( | 298 file_type->extension_description_overrides.push_back( |
297 l10n_util::GetStringUTF16(description_id)); | 299 l10n_util::GetStringUTF16(description_id)); |
298 } | 300 } |
299 | 301 |
300 return file_type.release(); | 302 return file_type.release(); |
301 } | 303 } |
302 | 304 |
303 void FileSelectHelper::RunFileChooser( | 305 // static |
304 RenderViewHost* render_view_host, | 306 void FileSelectHelper::RunFileChooser(content::WebContents* tab, |
305 content::WebContents* web_contents, | 307 const FileChooserParams& params) { |
306 const content::FileChooserParams& params) { | 308 Profile* profile = Profile::FromBrowserContext(tab->GetBrowserContext()); |
| 309 // FileSelectHelper will keep itself alive until it sends the result message. |
| 310 scoped_refptr<FileSelectHelper> file_select_helper( |
| 311 new FileSelectHelper(profile)); |
| 312 file_select_helper->RunFileChooser(tab->GetRenderViewHost(), tab, params); |
| 313 } |
| 314 |
| 315 // static |
| 316 void FileSelectHelper::EnumerateDirectory(content::WebContents* tab, |
| 317 int request_id, |
| 318 const FilePath& path) { |
| 319 Profile* profile = Profile::FromBrowserContext(tab->GetBrowserContext()); |
| 320 // FileSelectHelper will keep itself alive until it sends the result message. |
| 321 scoped_refptr<FileSelectHelper> file_select_helper( |
| 322 new FileSelectHelper(profile)); |
| 323 file_select_helper->EnumerateDirectory( |
| 324 request_id, tab->GetRenderViewHost(), path); |
| 325 } |
| 326 |
| 327 void FileSelectHelper::RunFileChooser(RenderViewHost* render_view_host, |
| 328 content::WebContents* web_contents, |
| 329 const FileChooserParams& params) { |
307 DCHECK(!render_view_host_); | 330 DCHECK(!render_view_host_); |
308 DCHECK(!web_contents_); | 331 DCHECK(!web_contents_); |
309 render_view_host_ = render_view_host; | 332 render_view_host_ = render_view_host; |
310 web_contents_ = web_contents; | 333 web_contents_ = web_contents; |
311 notification_registrar_.RemoveAll(); | 334 notification_registrar_.RemoveAll(); |
312 notification_registrar_.Add( | 335 notification_registrar_.Add( |
313 this, content::NOTIFICATION_RENDER_WIDGET_HOST_DESTROYED, | 336 this, content::NOTIFICATION_RENDER_WIDGET_HOST_DESTROYED, |
314 content::Source<RenderWidgetHost>(render_view_host_)); | 337 content::Source<RenderWidgetHost>(render_view_host_)); |
315 notification_registrar_.Add( | 338 notification_registrar_.Add( |
316 this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED, | 339 this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED, |
317 content::Source<WebContents>(web_contents_)); | 340 content::Source<WebContents>(web_contents_)); |
318 | 341 |
319 BrowserThread::PostTask( | 342 BrowserThread::PostTask( |
320 BrowserThread::FILE, FROM_HERE, | 343 BrowserThread::FILE, FROM_HERE, |
321 base::Bind(&FileSelectHelper::RunFileChooserOnFileThread, this, params)); | 344 base::Bind(&FileSelectHelper::RunFileChooserOnFileThread, this, params)); |
322 | 345 |
323 // Because this class returns notifications to the RenderViewHost, it is | 346 // Because this class returns notifications to the RenderViewHost, it is |
324 // difficult for callers to know how long to keep a reference to this | 347 // difficult for callers to know how long to keep a reference to this |
325 // instance. We AddRef() here to keep the instance alive after we return | 348 // instance. We AddRef() here to keep the instance alive after we return |
326 // to the caller, until the last callback is received from the file dialog. | 349 // to the caller, until the last callback is received from the file dialog. |
327 // At that point, we must call RunFileChooserEnd(). | 350 // At that point, we must call RunFileChooserEnd(). |
328 AddRef(); | 351 AddRef(); |
329 } | 352 } |
330 | 353 |
331 void FileSelectHelper::RunFileChooserOnFileThread( | 354 void FileSelectHelper::RunFileChooserOnFileThread( |
332 const content::FileChooserParams& params) { | 355 const FileChooserParams& params) { |
333 select_file_types_.reset( | 356 select_file_types_.reset( |
334 GetFileTypesFromAcceptType(params.accept_types)); | 357 GetFileTypesFromAcceptType(params.accept_types)); |
335 | 358 |
336 BrowserThread::PostTask( | 359 BrowserThread::PostTask( |
337 BrowserThread::UI, FROM_HERE, | 360 BrowserThread::UI, FROM_HERE, |
338 base::Bind(&FileSelectHelper::RunFileChooserOnUIThread, this, params)); | 361 base::Bind(&FileSelectHelper::RunFileChooserOnUIThread, this, params)); |
339 } | 362 } |
340 | 363 |
341 void FileSelectHelper::RunFileChooserOnUIThread( | 364 void FileSelectHelper::RunFileChooserOnUIThread( |
342 const content::FileChooserParams& params) { | 365 const FileChooserParams& params) { |
343 if (!render_view_host_ || !web_contents_) { | 366 if (!render_view_host_ || !web_contents_) { |
344 // If the renderer was destroyed before we started, just cancel the | 367 // If the renderer was destroyed before we started, just cancel the |
345 // operation. | 368 // operation. |
346 RunFileChooserEnd(); | 369 RunFileChooserEnd(); |
347 return; | 370 return; |
348 } | 371 } |
349 | 372 |
350 if (!select_file_dialog_.get()) | 373 if (!select_file_dialog_.get()) |
351 select_file_dialog_ = SelectFileDialog::Create(this); | 374 select_file_dialog_ = SelectFileDialog::Create(this); |
352 | 375 |
353 switch (params.mode) { | 376 switch (params.mode) { |
354 case content::FileChooserParams::Open: | 377 case FileChooserParams::Open: |
355 dialog_type_ = SelectFileDialog::SELECT_OPEN_FILE; | 378 dialog_type_ = SelectFileDialog::SELECT_OPEN_FILE; |
356 break; | 379 break; |
357 case content::FileChooserParams::OpenMultiple: | 380 case FileChooserParams::OpenMultiple: |
358 dialog_type_ = SelectFileDialog::SELECT_OPEN_MULTI_FILE; | 381 dialog_type_ = SelectFileDialog::SELECT_OPEN_MULTI_FILE; |
359 break; | 382 break; |
360 case content::FileChooserParams::OpenFolder: | 383 case FileChooserParams::OpenFolder: |
361 dialog_type_ = SelectFileDialog::SELECT_FOLDER; | 384 dialog_type_ = SelectFileDialog::SELECT_FOLDER; |
362 break; | 385 break; |
363 case content::FileChooserParams::Save: | 386 case FileChooserParams::Save: |
364 dialog_type_ = SelectFileDialog::SELECT_SAVEAS_FILE; | 387 dialog_type_ = SelectFileDialog::SELECT_SAVEAS_FILE; |
365 break; | 388 break; |
366 default: | 389 default: |
367 dialog_type_ = SelectFileDialog::SELECT_OPEN_FILE; // Prevent warning. | 390 dialog_type_ = SelectFileDialog::SELECT_OPEN_FILE; // Prevent warning. |
368 NOTREACHED(); | 391 NOTREACHED(); |
369 } | 392 } |
370 FilePath default_file_name = params.default_file_name; | 393 FilePath default_file_name = params.default_file_name; |
371 if (default_file_name.empty()) | 394 if (default_file_name.empty()) |
372 default_file_name = profile_->last_selected_directory(); | 395 default_file_name = profile_->last_selected_directory(); |
373 | 396 |
(...skipping 19 matching lines...) Expand all Loading... |
393 // in RunFileChooser(). | 416 // in RunFileChooser(). |
394 void FileSelectHelper::RunFileChooserEnd() { | 417 void FileSelectHelper::RunFileChooserEnd() { |
395 render_view_host_ = NULL; | 418 render_view_host_ = NULL; |
396 web_contents_ = NULL; | 419 web_contents_ = NULL; |
397 Release(); | 420 Release(); |
398 } | 421 } |
399 | 422 |
400 void FileSelectHelper::EnumerateDirectory(int request_id, | 423 void FileSelectHelper::EnumerateDirectory(int request_id, |
401 RenderViewHost* render_view_host, | 424 RenderViewHost* render_view_host, |
402 const FilePath& path) { | 425 const FilePath& path) { |
403 DCHECK_NE(kFileSelectEnumerationId, request_id); | |
404 | 426 |
405 // Because this class returns notifications to the RenderViewHost, it is | 427 // Because this class returns notifications to the RenderViewHost, it is |
406 // difficult for callers to know how long to keep a reference to this | 428 // difficult for callers to know how long to keep a reference to this |
407 // instance. We AddRef() here to keep the instance alive after we return | 429 // instance. We AddRef() here to keep the instance alive after we return |
408 // to the caller, until the last callback is received from the enumeration | 430 // to the caller, until the last callback is received from the enumeration |
409 // code. At that point, we must call EnumerateDirectoryEnd(). | 431 // code. At that point, we must call EnumerateDirectoryEnd(). |
410 AddRef(); | 432 AddRef(); |
411 StartNewEnumeration(path, request_id, render_view_host); | 433 StartNewEnumeration(path, request_id, render_view_host); |
412 } | 434 } |
413 | 435 |
(...skipping 18 matching lines...) Expand all Loading... |
432 case content::NOTIFICATION_WEB_CONTENTS_DESTROYED: { | 454 case content::NOTIFICATION_WEB_CONTENTS_DESTROYED: { |
433 DCHECK(content::Source<WebContents>(source).ptr() == web_contents_); | 455 DCHECK(content::Source<WebContents>(source).ptr() == web_contents_); |
434 web_contents_ = NULL; | 456 web_contents_ = NULL; |
435 break; | 457 break; |
436 } | 458 } |
437 | 459 |
438 default: | 460 default: |
439 NOTREACHED(); | 461 NOTREACHED(); |
440 } | 462 } |
441 } | 463 } |
OLD | NEW |