diff options
author | pastarmovj@chromium.org <pastarmovj@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-04-15 21:10:00 +0000 |
---|---|---|
committer | pastarmovj@chromium.org <pastarmovj@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-04-15 21:10:00 +0000 |
commit | d9898919b7f2e479c84caa3ec6f214f2e10bdddb (patch) | |
tree | 485ae6bc95b819467b87a3266b745acf688886da /chrome/browser | |
parent | 79d68c6ea3f0ee22789e04bcdcdf64841618f2c1 (diff) | |
download | chromium_src-d9898919b7f2e479c84caa3ec6f214f2e10bdddb.zip chromium_src-d9898919b7f2e479c84caa3ec6f214f2e10bdddb.tar.gz chromium_src-d9898919b7f2e479c84caa3ec6f214f2e10bdddb.tar.bz2 |
Policy to manage file selection dialogs.
Adds a policy to allow/disallow file selection dialogs from
wherever they can be launched (Save Link As, Import Bookmarks, etc.).
In case file selection dialogs are disallowed by policy a InfoBar informs
the user whenever he triggers a file selection dialog.
BUG=73174
TEST=Manually set the policy and check if the corresponding file selection are not shown and the InfoBar appears.
Review URL: http://codereview.chromium.org/6814011
Patch from Sandro Feuz <sfeuz@google.com>.
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@81804 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
31 files changed, 352 insertions, 112 deletions
diff --git a/chrome/browser/download/download_manager.cc b/chrome/browser/download/download_manager.cc index c7fba6c..ccedecf 100644 --- a/chrome/browser/download/download_manager.cc +++ b/chrome/browser/download/download_manager.cc @@ -446,7 +446,7 @@ void DownloadManager::OnPathExistenceAvailable(DownloadCreateInfo* info) { string16(), info->suggested_path, &file_type_info, 0, FILE_PATH_LITERAL(""), - owning_window, info); + contents, owning_window, info); FOR_EACH_OBSERVER(Observer, observers_, SelectFileDialogDisplayed(info->download_id)); } else { diff --git a/chrome/browser/download/save_package.cc b/chrome/browser/download/save_package.cc index 9285719..9c54006 100644 --- a/chrome/browser/download/save_package.cc +++ b/chrome/browser/download/save_package.cc @@ -1392,6 +1392,7 @@ void SavePackage::ContinueGetSaveInfo(const FilePath& suggested_path, &file_type_info, file_type_index, default_extension, + tab_contents(), platform_util::GetTopLevel( tab_contents()->GetNativeView()), NULL); diff --git a/chrome/browser/extensions/extension_bookmarks_module.cc b/chrome/browser/extensions/extension_bookmarks_module.cc index e240ea8..1777e79 100644 --- a/chrome/browser/extensions/extension_bookmarks_module.cc +++ b/chrome/browser/extensions/extension_bookmarks_module.cc @@ -855,12 +855,19 @@ void BookmarksIOFunction::ShowSelectFileDialog(SelectFileDialog::Type type, file_type_info.extensions.resize(1); file_type_info.extensions[0].push_back(FILE_PATH_LITERAL("html")); + TabContents* tab_contents = dispatcher()->delegate()-> + associated_tab_contents(); + + // |tab_contents| can be NULL (for background pages), which is fine. In such + // a case if file-selection dialogs are forbidden by policy, we will not + // show an InfoBar, which is better than letting one appear out of the blue. select_file_dialog_->SelectFile(type, string16(), default_path, &file_type_info, 0, FILE_PATH_LITERAL(""), + tab_contents, NULL, NULL); } diff --git a/chrome/browser/extensions/extension_host.cc b/chrome/browser/extensions/extension_host.cc index 017f9df..a930350 100644 --- a/chrome/browser/extensions/extension_host.cc +++ b/chrome/browser/extensions/extension_host.cc @@ -837,5 +837,6 @@ void ExtensionHost::OnRunFileChooser( const ViewHostMsg_RunFileChooser_Params& params) { if (file_select_helper_.get() == NULL) file_select_helper_.reset(new FileSelectHelper(profile())); - file_select_helper_->RunFileChooser(render_view_host_, params); + file_select_helper_->RunFileChooser(render_view_host_, + associated_tab_contents(), params); } diff --git a/chrome/browser/extensions/extensions_ui.cc b/chrome/browser/extensions/extensions_ui.cc index ed29460..0a4fc0a 100644 --- a/chrome/browser/extensions/extensions_ui.cc +++ b/chrome/browser/extensions/extensions_ui.cc @@ -603,7 +603,7 @@ void ExtensionsDOMHandler::HandleSelectFilePathMessage(const ListValue* args) { load_extension_dialog_ = SelectFileDialog::Create(this); load_extension_dialog_->SelectFile(type, select_title, FilePath(), &info, - file_type_index, FILE_PATH_LITERAL(""), + file_type_index, FILE_PATH_LITERAL(""), web_ui_->tab_contents(), web_ui_->tab_contents()->view()->GetTopLevelNativeWindow(), NULL); } diff --git a/chrome/browser/file_select_helper.cc b/chrome/browser/file_select_helper.cc index a4545ad..3ee8c5a 100644 --- a/chrome/browser/file_select_helper.cc +++ b/chrome/browser/file_select_helper.cc @@ -17,6 +17,8 @@ #include "content/browser/renderer_host/render_view_host.h" #include "content/browser/renderer_host/render_widget_host_view.h" #include "content/browser/tab_contents/tab_contents.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_list.h" #include "content/common/notification_details.h" #include "content/common/notification_source.h" #include "content/common/view_messages.h" @@ -234,6 +236,7 @@ SelectFileDialog::FileTypeInfo* FileSelectHelper::GetFileTypesFromAcceptType( void FileSelectHelper::RunFileChooser( RenderViewHost* render_view_host, + TabContents* tab_contents, const ViewHostMsg_RunFileChooser_Params& params) { DCHECK(!render_view_host_); render_view_host_ = render_view_host; @@ -270,12 +273,14 @@ void FileSelectHelper::RunFileChooser( gfx::NativeWindow owning_window = platform_util::GetTopLevel(render_view_host_->view()->GetNativeView()); + select_file_dialog_->SelectFile(dialog_type_, params.title, default_file_name, file_types.get(), file_types.get() ? 1 : 0, // 1-based index. FILE_PATH_LITERAL(""), + tab_contents, owning_window, NULL); } @@ -318,6 +323,7 @@ void FileSelectObserver::OnRunFileChooser( if (!file_select_helper_.get()) file_select_helper_.reset(new FileSelectHelper(tab_contents()->profile())); file_select_helper_->RunFileChooser(tab_contents()->render_view_host(), + tab_contents(), params); } diff --git a/chrome/browser/file_select_helper.h b/chrome/browser/file_select_helper.h index e5fc7fa..270c8aa 100644 --- a/chrome/browser/file_select_helper.h +++ b/chrome/browser/file_select_helper.h @@ -20,6 +20,10 @@ class Profile; class RenderViewHost; struct ViewHostMsg_RunFileChooser_Params; + +// This class handles file-selection requests coming from WebUI elements +// (via the ExtensionHost class). It implements both the initialisation +// and listener functions for file-selection dialogs. class FileSelectHelper : public SelectFileDialog::Listener, public NotificationObserver { @@ -29,6 +33,7 @@ class FileSelectHelper // Show the file chooser dialog. void RunFileChooser(RenderViewHost* render_view_host, + TabContents* tab_contents, const ViewHostMsg_RunFileChooser_Params& params); // Enumerates all the files in directory. diff --git a/chrome/browser/policy/configuration_policy_pref_store.cc b/chrome/browser/policy/configuration_policy_pref_store.cc index 58d1850..d73ac28 100644 --- a/chrome/browser/policy/configuration_policy_pref_store.cc +++ b/chrome/browser/policy/configuration_policy_pref_store.cc @@ -249,6 +249,8 @@ const ConfigurationPolicyPrefKeeper::PolicyToPreferenceMapEntry prefs::kPluginsAllowOutdated }, { Value::TYPE_BOOLEAN, kPolicyEditBookmarksEnabled, prefs::kEditBookmarksEnabled }, + { Value::TYPE_BOOLEAN, kPolicyAllowFileSelectionDialogs, + prefs::kAllowFileSelectionDialogs }, #if defined(OS_CHROMEOS) { Value::TYPE_BOOLEAN, kPolicyChromeOsLockOnIdleSuspend, @@ -956,6 +958,8 @@ ConfigurationPolicyPrefStore::GetChromePolicyDefinitionList() { key::kBookmarkBarEnabled }, { kPolicyEditBookmarksEnabled, Value::TYPE_BOOLEAN, key::kEditBookmarksEnabled }, + { kPolicyAllowFileSelectionDialogs, Value::TYPE_BOOLEAN, + key::kAllowFileSelectionDialogs }, #if defined(OS_CHROMEOS) { kPolicyChromeOsLockOnIdleSuspend, Value::TYPE_BOOLEAN, diff --git a/chrome/browser/policy/configuration_policy_pref_store_unittest.cc b/chrome/browser/policy/configuration_policy_pref_store_unittest.cc index 6c71089..ad6b451 100644 --- a/chrome/browser/policy/configuration_policy_pref_store_unittest.cc +++ b/chrome/browser/policy/configuration_policy_pref_store_unittest.cc @@ -211,7 +211,9 @@ INSTANTIATE_TEST_CASE_P( TypeAndName(kPolicyBookmarkBarEnabled, prefs::kEnableBookmarkBar), TypeAndName(kPolicyEditBookmarksEnabled, - prefs::kEditBookmarksEnabled))); + prefs::kEditBookmarksEnabled), + TypeAndName(kPolicyAllowFileSelectionDialogs, + prefs::kAllowFileSelectionDialogs))); #if defined(OS_CHROMEOS) INSTANTIATE_TEST_CASE_P( diff --git a/chrome/browser/policy/configuration_policy_provider_mac_unittest.cc b/chrome/browser/policy/configuration_policy_provider_mac_unittest.cc index 9494122..0a76502 100644 --- a/chrome/browser/policy/configuration_policy_provider_mac_unittest.cc +++ b/chrome/browser/policy/configuration_policy_provider_mac_unittest.cc @@ -333,6 +333,9 @@ INSTANTIATE_TEST_CASE_P( key::kBookmarkBarEnabled), PolicyTestParams::ForBooleanPolicy( kPolicyEditBookmarksEnabled, - key::kEditBookmarksEnabled))); + key::kEditBookmarksEnabled), + PolicyTestParams::ForBooleanPolicy( + kPolicyAllowFileSelectionDialogs, + key::kAllowFileSelectionDialogs))); } // namespace policy diff --git a/chrome/browser/policy/configuration_policy_provider_win_unittest.cc b/chrome/browser/policy/configuration_policy_provider_win_unittest.cc index 2763f15..facff3d 100644 --- a/chrome/browser/policy/configuration_policy_provider_win_unittest.cc +++ b/chrome/browser/policy/configuration_policy_provider_win_unittest.cc @@ -491,6 +491,9 @@ INSTANTIATE_TEST_CASE_P( key::kBookmarkBarEnabled), PolicyTestParams::ForBooleanPolicy( kPolicyEditBookmarksEnabled, - key::kEditBookmarksEnabled))); + key::kEditBookmarksEnabled), + PolicyTestParams::ForBooleanPolicy( + kPolicyAllowFileSelectionDialogs, + key::kAllowFileSelectionDialogs))); } // namespace policy diff --git a/chrome/browser/ui/browser.cc b/chrome/browser/ui/browser.cc index 9fea401..b4e9b6f 100644 --- a/chrome/browser/ui/browser.cc +++ b/chrome/browser/ui/browser.cc @@ -1790,6 +1790,7 @@ void Browser::OpenFile() { select_file_dialog_->SelectFile(SelectFileDialog::SELECT_OPEN_FILE, string16(), directory, NULL, 0, FILE_PATH_LITERAL(""), + GetSelectedTabContents(), parent_window, NULL); #endif } @@ -2053,6 +2054,7 @@ void Browser::RegisterPrefs(PrefService* prefs) { prefs->RegisterIntegerPref(prefs::kOptionsWindowLastTabIndex, 0); prefs->RegisterIntegerPref(prefs::kExtensionSidebarWidth, -1); prefs->RegisterIntegerPref(prefs::kMultipleProfilePrefMigration, 0); + prefs->RegisterBooleanPref(prefs::kAllowFileSelectionDialogs, true); // Educated guess: Chrome has a bundled Flash version supporting // clearing LSO data, Chromium hasn't. #if defined(GOOGLE_CHROME_BUILD) diff --git a/chrome/browser/ui/cocoa/shell_dialogs_mac.mm b/chrome/browser/ui/cocoa/shell_dialogs_mac.mm index 248c03e..687ca71 100644 --- a/chrome/browser/ui/cocoa/shell_dialogs_mac.mm +++ b/chrome/browser/ui/cocoa/shell_dialogs_mac.mm @@ -54,17 +54,6 @@ class SelectFileDialogImpl : public SelectFileDialog { virtual bool IsRunning(gfx::NativeWindow parent_window) const; virtual void ListenerDestroyed(); - // SelectFileDialog implementation. - // |params| is user data we pass back via the Listener interface. - virtual void SelectFile(Type type, - const string16& title, - const FilePath& default_path, - const FileTypeInfo* file_types, - int file_type_index, - const FilePath::StringType& default_extension, - gfx::NativeWindow owning_window, - void* params); - // Callback from ObjC bridge. void FileWasSelected(NSSavePanel* dialog, NSWindow* parent_window, @@ -80,14 +69,23 @@ class SelectFileDialogImpl : public SelectFileDialog { NSWindow* owning_window; }; + protected: + // SelectFileDialog implementation. + // |params| is user data we pass back via the Listener interface. + virtual void SelectFileImpl(Type type, + const string16& title, + const FilePath& default_path, + const FileTypeInfo* file_types, + int file_type_index, + const FilePath::StringType& default_extension, + gfx::NativeWindow owning_window, + void* params); + private: // Gets the accessory view for the save dialog. NSView* GetAccessoryView(const FileTypeInfo* file_types, int file_type_index); - // The listener to be notified of selection completion. - Listener* listener_; - // The bridge for results from Cocoa to return to us. scoped_nsobject<SelectFileDialogBridge> bridge_; @@ -109,7 +107,7 @@ SelectFileDialog* SelectFileDialog::Create(Listener* listener) { } SelectFileDialogImpl::SelectFileDialogImpl(Listener* listener) - : listener_(listener), + : SelectFileDialog(listener), bridge_([[SelectFileDialogBridge alloc] initWithSelectFileDialogImpl:this]) { } @@ -138,7 +136,7 @@ void SelectFileDialogImpl::ListenerDestroyed() { listener_ = NULL; } -void SelectFileDialogImpl::SelectFile( +void SelectFileDialogImpl::SelectFileImpl( Type type, const string16& title, const FilePath& default_path, diff --git a/chrome/browser/ui/gtk/certificate_dialogs.cc b/chrome/browser/ui/gtk/certificate_dialogs.cc index 6b6e19a..bd9cf29 100644 --- a/chrome/browser/ui/gtk/certificate_dialogs.cc +++ b/chrome/browser/ui/gtk/certificate_dialogs.cc @@ -73,7 +73,8 @@ std::string GetBase64String(net::X509Certificate::OSCertHandle cert) { class Exporter : public SelectFileDialog::Listener { public: - Exporter(gfx::NativeWindow parent, net::X509Certificate::OSCertHandle cert); + Exporter(TabContents* tab_contents, gfx::NativeWindow parent, + net::X509Certificate::OSCertHandle cert); ~Exporter(); // SelectFileDialog::Listener implemenation. @@ -87,7 +88,8 @@ class Exporter : public SelectFileDialog::Listener { net::X509Certificate::OSCertHandles cert_chain_list_; }; -Exporter::Exporter(gfx::NativeWindow parent, +Exporter::Exporter(TabContents* tab_contents, + gfx::NativeWindow parent, net::X509Certificate::OSCertHandle cert) : select_file_dialog_(SelectFileDialog::Create(this)) { x509_certificate_model::GetCertChainFromCert(cert, &cert_chain_list_); @@ -102,6 +104,7 @@ Exporter::Exporter(gfx::NativeWindow parent, ShowCertSelectFileDialog(select_file_dialog_.get(), SelectFileDialog::SELECT_SAVEAS_FILE, suggested_path, + tab_contents, parent, NULL); } @@ -153,6 +156,7 @@ void Exporter::FileSelectionCanceled(void* params) { void ShowCertSelectFileDialog(SelectFileDialog* select_file_dialog, SelectFileDialog::Type type, const FilePath& suggested_path, + TabContents* tab_contents, gfx::NativeWindow parent, void* params) { SelectFileDialog::FileTypeInfo file_type_info; @@ -178,11 +182,12 @@ void ShowCertSelectFileDialog(SelectFileDialog* select_file_dialog, select_file_dialog->SelectFile( type, string16(), suggested_path, &file_type_info, 1, - FILE_PATH_LITERAL("crt"), parent, - params); + FILE_PATH_LITERAL("crt"), tab_contents, + parent, params); } -void ShowCertExportDialog(gfx::NativeWindow parent, +void ShowCertExportDialog(TabContents* tab_contents, + gfx::NativeWindow parent, net::X509Certificate::OSCertHandle cert) { - new Exporter(parent, cert); + new Exporter(tab_contents, parent, cert); } diff --git a/chrome/browser/ui/gtk/certificate_dialogs.h b/chrome/browser/ui/gtk/certificate_dialogs.h index a13bfca..fbc6116 100644 --- a/chrome/browser/ui/gtk/certificate_dialogs.h +++ b/chrome/browser/ui/gtk/certificate_dialogs.h @@ -12,10 +12,12 @@ void ShowCertSelectFileDialog(SelectFileDialog* select_file_dialog, SelectFileDialog::Type type, const FilePath& suggested_path, + TabContents* tab_contents, gfx::NativeWindow parent, void* params); -void ShowCertExportDialog(gfx::NativeWindow parent, +void ShowCertExportDialog(TabContents* tab_contents, + gfx::NativeWindow parent, net::X509Certificate::OSCertHandle cert); #endif // CHROME_BROWSER_UI_GTK_CERTIFICATE_DIALOGS_H_ diff --git a/chrome/browser/ui/gtk/certificate_viewer.cc b/chrome/browser/ui/gtk/certificate_viewer.cc index 1a1a8fe..e062fec 100644 --- a/chrome/browser/ui/gtk/certificate_viewer.cc +++ b/chrome/browser/ui/gtk/certificate_viewer.cc @@ -697,7 +697,7 @@ void CertificateViewer::OnExportClicked(GtkButton *button, return; } - ShowCertExportDialog(GTK_WINDOW(viewer->dialog_), + ShowCertExportDialog(NULL, GTK_WINDOW(viewer->dialog_), viewer->cert_chain_list_[cert_index]); } diff --git a/chrome/browser/ui/gtk/dialogs_gtk.cc b/chrome/browser/ui/gtk/dialogs_gtk.cc index 7ddd63d..e208d23 100644 --- a/chrome/browser/ui/gtk/dialogs_gtk.cc +++ b/chrome/browser/ui/gtk/dialogs_gtk.cc @@ -38,16 +38,17 @@ class SelectFileDialogImpl : public SelectFileDialog { virtual bool IsRunning(gfx::NativeWindow parent_window) const; virtual void ListenerDestroyed(); + protected: // SelectFileDialog implementation. // |params| is user data we pass back via the Listener interface. - virtual void SelectFile(Type type, - const string16& title, - const FilePath& default_path, - const FileTypeInfo* file_types, - int file_type_index, - const FilePath::StringType& default_extension, - gfx::NativeWindow owning_window, - void* params); + virtual void SelectFileImpl(Type type, + const string16& title, + const FilePath& default_path, + const FileTypeInfo* file_types, + int file_type_index, + const FilePath::StringType& default_extension, + gfx::NativeWindow owning_window, + void* params); private: virtual ~SelectFileDialogImpl(); @@ -55,7 +56,6 @@ class SelectFileDialogImpl : public SelectFileDialog { // Add the filters from |file_types_| to |chooser|. void AddFilters(GtkFileChooser* chooser); - // Notifies the listener that a single file was chosen. void FileSelected(GtkWidget* dialog, const FilePath& path); // Notifies the listener that multiple files were chosen. @@ -125,9 +125,6 @@ class SelectFileDialogImpl : public SelectFileDialog { // Callback for when we update the preview for the selection. CHROMEGTK_CALLBACK_0(SelectFileDialogImpl, void, OnUpdatePreview); - // The listener to be notified of selection completion. - Listener* listener_; - // A map from dialog windows to the |params| user data associated with them. std::map<GtkWidget*, void*> params_map_; @@ -168,7 +165,7 @@ SelectFileDialog* SelectFileDialog::Create(Listener* listener) { } SelectFileDialogImpl::SelectFileDialogImpl(Listener* listener) - : listener_(listener), + : SelectFileDialog(listener), file_type_index_(0), type_(SELECT_NONE), preview_(NULL) { @@ -193,7 +190,7 @@ void SelectFileDialogImpl::ListenerDestroyed() { } // We ignore |default_extension|. -void SelectFileDialogImpl::SelectFile( +void SelectFileDialogImpl::SelectFileImpl( Type type, const string16& title, const FilePath& default_path, diff --git a/chrome/browser/ui/shell_dialogs.cc b/chrome/browser/ui/shell_dialogs.cc index 9b9bc6e..3e9593c 100644 --- a/chrome/browser/ui/shell_dialogs.cc +++ b/chrome/browser/ui/shell_dialogs.cc @@ -4,10 +4,79 @@ #include "chrome/browser/ui/shell_dialogs.h" +#include "base/logging.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/prefs/pref_service.h" +#include "chrome/browser/tab_contents/simple_alert_infobar_delegate.h" +#include "chrome/common/pref_names.h" +#include "content/browser/tab_contents/tab_contents.h" +#include "grit/generated_resources.h" +#include "ui/base/l10n/l10n_util.h" + SelectFileDialog::FileTypeInfo::FileTypeInfo() : include_all_files(false) {} SelectFileDialog::FileTypeInfo::~FileTypeInfo() {} -SelectFileDialog::SelectFileDialog() {} +SelectFileDialog::SelectFileDialog(Listener* listener) + : listener_(listener) { + DCHECK(listener_); +} SelectFileDialog::~SelectFileDialog() {} + +bool SelectFileDialog::CanOpenSelectFileDialog() { + DCHECK(g_browser_process); + + // local_state() can return NULL for tests. + if (!g_browser_process->local_state()) + return false; + + return !g_browser_process->local_state()->FindPreference( + prefs::kAllowFileSelectionDialogs) || + g_browser_process->local_state()->GetBoolean( + prefs::kAllowFileSelectionDialogs); +} + +void SelectFileDialog::SelectFile(Type type, + const string16& title, + const FilePath& default_path, + const FileTypeInfo* file_types, + int file_type_index, + const FilePath::StringType& default_extension, + TabContents* source_contents, + gfx::NativeWindow owning_window, + void* params) { + DCHECK(listener_); + + if (!CanOpenSelectFileDialog()) { + // Show the InfoBar saying that file-selection dialogs are disabled. + if (source_contents) { + source_contents->AddInfoBar(new SimpleAlertInfoBarDelegate( + source_contents, + NULL, + l10n_util::GetStringUTF16(IDS_FILE_SELECTION_DIALOG_INFOBAR), + true)); + } else { + LOG(WARNING) << "File-selection dialogs are disabled but no TabContents " + << "is given to display the InfoBar."; + } + + // Inform the listener that no file was selected. + // Post a task rather than calling FileSelectionCanceled directly to ensure + // that the listener is called asynchronously. + MessageLoop::current()->PostTask(FROM_HERE, + NewRunnableMethod( + this, + &SelectFileDialog::CancelFileSelection, + params)); + return; + } + // Call the platform specific implementation of the file selection dialog. + SelectFileImpl(type, title, default_path, file_types, file_type_index, + default_extension, owning_window, params); +} + +void SelectFileDialog::CancelFileSelection(void* params) { + if (listener_) + listener_->FileSelectionCanceled(params); +} diff --git a/chrome/browser/ui/shell_dialogs.h b/chrome/browser/ui/shell_dialogs.h index d77cdbc..c016f6f 100644 --- a/chrome/browser/ui/shell_dialogs.h +++ b/chrome/browser/ui/shell_dialogs.h @@ -14,6 +14,8 @@ #include "base/string16.h" #include "ui/gfx/native_widget_types.h" +class TabContents; + // This function is declared extern such that it is accessible for unit tests // in /chrome/browser/ui/views/shell_dialogs_win_unittest.cc extern std::wstring AppendExtensionIfNeeded(const std::wstring& filename, @@ -97,7 +99,11 @@ class SelectFileDialog bool include_all_files; }; - // Selects a file. This will start displaying the dialog box. This will also + // Selects a File. + // Before doing anything this function checks if FileBrowsing is forbidden + // by Policy. If so, it tries to show an InfoBar and behaves as though no File + // was selected (the user clicked `Cancel` immediately). + // Otherwise it will start displaying the dialog box. This will also // block the calling window until the dialog box is complete. The listener // associated with this object will be notified when the selection is // complete. @@ -114,28 +120,58 @@ class SelectFileDialog // |default_extension| is the default extension to add to the file if the // user doesn't type one. This should NOT include the '.'. On Windows, if // you specify this you must also specify |file_types|. + // |source_contents| is the TabContents the call is originating from, i.e. + // where the InfoBar should be shown in case file-selection dialogs are + // forbidden by policy, or NULL if no InfoBar should be shown. // |owning_window| is the window the dialog is modal to, or NULL for a // modeless dialog. // |params| is data from the calling context which will be passed through to // the listener. Can be NULL. // NOTE: only one instance of any shell dialog can be shown per owning_window // at a time (for obvious reasons). - virtual void SelectFile(Type type, - const string16& title, - const FilePath& default_path, - const FileTypeInfo* file_types, - int file_type_index, - const FilePath::StringType& default_extension, - gfx::NativeWindow owning_window, - void* params) = 0; + void SelectFile(Type type, + const string16& title, + const FilePath& default_path, + const FileTypeInfo* file_types, + int file_type_index, + const FilePath::StringType& default_extension, + TabContents* source_contents, + gfx::NativeWindow owning_window, + void* params); // browser_mode is true when running inside the browser. virtual void set_browser_mode(bool value) {} protected: friend class base::RefCountedThreadSafe<SelectFileDialog>; - SelectFileDialog(); + explicit SelectFileDialog(Listener* listener); virtual ~SelectFileDialog(); + + // Displays the actual file-selection dialog. + // This is overridden in the platform-specific descendants of FileSelectDialog + // and gets called from SelectFile after testing the + // AllowFileSelectionDialogs-Policy. + virtual void SelectFileImpl(Type type, + const string16& title, + const FilePath& default_path, + const FileTypeInfo* file_types, + int file_type_index, + const FilePath::StringType& default_extension, + gfx::NativeWindow owning_window, + void* params) = 0; + + // The listener to be notified of selection completion. + Listener* listener_; + + private: + // Tests if the file selection dialog can be displayed by + // testing if the AllowFileSelectionDialogs-Policy is + // either unset or set to true. + bool CanOpenSelectFileDialog(); + + // Informs the |listener_| that the file seleciton dialog was canceled. Moved + // to a function for being able to post it to the message loop. + void CancelFileSelection(void* params); }; #endif // CHROME_BROWSER_UI_SHELL_DIALOGS_H_ diff --git a/chrome/browser/ui/shell_dialogs_unittest.cc b/chrome/browser/ui/shell_dialogs_unittest.cc new file mode 100644 index 0000000..2269405 --- /dev/null +++ b/chrome/browser/ui/shell_dialogs_unittest.cc @@ -0,0 +1,95 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/file_path.h" +#include "base/file_util.h" +#include "base/string16.h" +#include "base/values.h" +#include "chrome/browser/prefs/pref_service.h" +#include "chrome/browser/prefs/browser_prefs.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/shell_dialogs.h" +#include "chrome/test/testing_browser_process_test.h" +#include "chrome/test/testing_pref_service.h" +#include "chrome/common/pref_names.h" +#include "testing/gtest/include/gtest/gtest.h" + +class FileSelectionUser : public SelectFileDialog::Listener { + public: + FileSelectionUser() + : file_selection_initialisation_in_progress(false) { + } + + ~FileSelectionUser() { + if (select_file_dialog_.get()) + select_file_dialog_->ListenerDestroyed(); + } + + void StartFileSelection() { + CHECK(!select_file_dialog_.get()); + select_file_dialog_ = SelectFileDialog::Create(this); + + const FilePath file_path; + const string16 title=string16(); + + file_selection_initialisation_in_progress = true; + select_file_dialog_->SelectFile(SelectFileDialog::SELECT_OPEN_FILE, + title, + file_path, + NULL, + 0, + FILE_PATH_LITERAL(""), + NULL, + NULL, + NULL); + file_selection_initialisation_in_progress = false; + } + + // SelectFileDialog::Listener implementation. + virtual void FileSelected(const FilePath& path, + int index, void* params){ + ASSERT_FALSE(file_selection_initialisation_in_progress); + } + virtual void MultiFilesSelected( + const std::vector<FilePath>& files, + void* params) { + ASSERT_FALSE(file_selection_initialisation_in_progress); + } + virtual void FileSelectionCanceled(void* params) { + ASSERT_FALSE(file_selection_initialisation_in_progress); + } + + private: + scoped_refptr<SelectFileDialog> select_file_dialog_; + + bool file_selection_initialisation_in_progress; +}; + +typedef TestingBrowserProcessTest FileSelectionDialogTest; + +// Tests if SelectFileDialog::SelectFile returns asynchronously with +// file-selection dialogs disabled by policy. +TEST_F(FileSelectionDialogTest, ExpectAsynchronousListenerCall) { + MessageLoopForUI message_loop; + BrowserThread ui_thread(BrowserThread::UI, &message_loop); + + TestingPrefService test_local_state; + browser::RegisterLocalState(&test_local_state); + static_cast<TestingBrowserProcess*>(g_browser_process)-> + SetPrefService(&test_local_state); + + FileSelectionUser* file_selection_user; + + // Disallow file-selection dialogs. + test_local_state.SetManagedPref( + prefs::kAllowFileSelectionDialogs, + Value::CreateBooleanValue(false)); + + file_selection_user = new FileSelectionUser(); + file_selection_user->StartFileSelection(); + delete file_selection_user; + + static_cast<TestingBrowserProcess*>(g_browser_process)-> + SetPrefService(NULL); +} diff --git a/chrome/browser/ui/views/file_manager_dialogs.cc b/chrome/browser/ui/views/file_manager_dialogs.cc index 48bf6b2..62214e4 100644 --- a/chrome/browser/ui/views/file_manager_dialogs.cc +++ b/chrome/browser/ui/views/file_manager_dialogs.cc @@ -66,16 +66,6 @@ class FileManagerDialog } // SelectFileDialog implementation. - - virtual void SelectFile(Type type, - const string16& title, - const FilePath& default_path, - const FileTypeInfo* file_types, - int file_type_index, - const FilePath::StringType& default_extension, - gfx::NativeWindow owning_window, - void* params); - virtual void set_browser_mode(bool value) { browser_mode_ = value; } @@ -133,10 +123,20 @@ class FileManagerDialog return true; } + protected: + // SelectFileDialog implementation. + virtual void SelectFileImpl(Type type, + const string16& title, + const FilePath& default_path, + const FileTypeInfo* file_types, + int file_type_index, + const FilePath::StringType& default_extension, + gfx::NativeWindow owning_window, + void* params); + private: virtual ~FileManagerDialog() {} - Listener* listener_; int32 tab_id_; // True when opening in browser, otherwise in OOBE/login mode. @@ -171,13 +171,13 @@ std::string FileManagerDialog::s_extension_base_url_ = "chrome-extension://hhaomjibdihmijegdhdafkllkbggdgoj/main.html"; FileManagerDialog::FileManagerDialog(Listener* listener) - : tab_id_(0), + : SelectFileDialog(listener), + tab_id_(0), browser_mode_(true), owner_window_(0) { - listener_ = listener; } -void FileManagerDialog::SelectFile( +void FileManagerDialog::SelectFileImpl( Type type, const string16& title, const FilePath& default_path, diff --git a/chrome/browser/ui/views/select_file_dialog.cc b/chrome/browser/ui/views/select_file_dialog.cc index 2590005..fba4762 100644 --- a/chrome/browser/ui/views/select_file_dialog.cc +++ b/chrome/browser/ui/views/select_file_dialog.cc @@ -43,21 +43,22 @@ class SelectFileDialogImpl : public SelectFileDialog { virtual bool IsRunning(gfx::NativeWindow parent_window) const; virtual void ListenerDestroyed(); - // SelectFileDialog implementation. - // |params| is user data we pass back via the Listener interface. - virtual void SelectFile(Type type, - const string16& title, - const FilePath& default_path, - const FileTypeInfo* file_types, - int file_type_index, - const FilePath::StringType& default_extension, - gfx::NativeWindow owning_window, - void* params); - virtual void set_browser_mode(bool value) { browser_mode_ = value; } + protected: + // SelectFileDialog implementation. + // |params| is user data we pass back via the Listener interface. + virtual void SelectFileImpl(Type type, + const string16& title, + const FilePath& default_path, + const FileTypeInfo* file_types, + int file_type_index, + const FilePath::StringType& default_extension, + gfx::NativeWindow owning_window, + void* params); + private: virtual ~SelectFileDialogImpl(); @@ -155,9 +156,6 @@ class SelectFileDialogImpl : public SelectFileDialog { // True when opening in browser, otherwise in OOBE/login mode. bool browser_mode_; - // The listener to be notified of selection completion. - Listener* listener_; - DISALLOW_COPY_AND_ASSIGN(SelectFileDialogImpl); }; @@ -169,8 +167,8 @@ SelectFileDialog* SelectFileDialog::Create(Listener* listener) { } SelectFileDialogImpl::SelectFileDialogImpl(Listener* listener) - : browser_mode_(true), - listener_(listener) { + : SelectFileDialog(listener), + browser_mode_(true) { } SelectFileDialogImpl::~SelectFileDialogImpl() { @@ -186,7 +184,7 @@ void SelectFileDialogImpl::ListenerDestroyed() { listener_ = NULL; } -void SelectFileDialogImpl::SelectFile( +void SelectFileDialogImpl::SelectFileImpl( Type type, const string16& title, const FilePath& default_path, @@ -271,8 +269,8 @@ void SelectFileDialogImpl::OnDialogClosed(FileBrowseDelegate* delegate, FilePath path( base::SysWideToNativeMB(base::SysUTF8ToWide(path_string))); #endif - listener_->FileSelected(path, kSaveCompletePageIndex, - delegate->params_); + listener_-> + FileSelected(path, kSaveCompletePageIndex, delegate->params_); notification_fired = true; } } else if (delegate->type_ == SELECT_OPEN_MULTI_FILE) { diff --git a/chrome/browser/ui/views/shell_dialogs_win.cc b/chrome/browser/ui/views/shell_dialogs_win.cc index f35a8bd..5eba0de4 100644 --- a/chrome/browser/ui/views/shell_dialogs_win.cc +++ b/chrome/browser/ui/views/shell_dialogs_win.cc @@ -535,18 +535,20 @@ class SelectFileDialogImpl : public SelectFileDialog, public: explicit SelectFileDialogImpl(Listener* listener); - // SelectFileDialog implementation: - virtual void SelectFile(Type type, - const string16& title, - const FilePath& default_path, - const FileTypeInfo* file_types, - int file_type_index, - const FilePath::StringType& default_extension, - gfx::NativeWindow owning_window, - void* params); virtual bool IsRunning(HWND owning_hwnd) const; virtual void ListenerDestroyed(); + protected: + // SelectFileDialog implementation: + virtual void SelectFileImpl(Type type, + const string16& title, + const FilePath& default_path, + const FileTypeInfo* file_types, + int file_type_index, + const FilePath::StringType& default_extension, + gfx::NativeWindow owning_window, + void* params); + private: virtual ~SelectFileDialogImpl(); @@ -630,21 +632,19 @@ class SelectFileDialogImpl : public SelectFileDialog, LPARAM parameter, LPARAM data); - // The listener to be notified of selection completion. - Listener* listener_; DISALLOW_COPY_AND_ASSIGN(SelectFileDialogImpl); }; SelectFileDialogImpl::SelectFileDialogImpl(Listener* listener) - : listener_(listener), + : SelectFileDialog(listener), BaseShellDialogImpl() { } SelectFileDialogImpl::~SelectFileDialogImpl() { } -void SelectFileDialogImpl::SelectFile( +void SelectFileDialogImpl::SelectFileImpl( Type type, const string16& title, const FilePath& default_path, diff --git a/chrome/browser/ui/views/user_data_dir_dialog.cc b/chrome/browser/ui/views/user_data_dir_dialog.cc index 20d5055f..996f442 100644 --- a/chrome/browser/ui/views/user_data_dir_dialog.cc +++ b/chrome/browser/ui/views/user_data_dir_dialog.cc @@ -74,8 +74,8 @@ bool UserDataDirDialog::Accept() { HWND owning_hwnd = GetAncestor(message_box_view_->GetWidget()->GetNativeView(), GA_ROOT); select_file_dialog_->SelectFile(SelectFileDialog::SELECT_FOLDER, - dialog_title, FilePath(), NULL, - 0, std::wstring(), owning_hwnd, NULL); + dialog_title, FilePath(), NULL, 0, + std::wstring(), NULL, owning_hwnd, NULL); return false; } diff --git a/chrome/browser/ui/webui/net_internals_ui.cc b/chrome/browser/ui/webui/net_internals_ui.cc index a28daa6..67ce3ac 100644 --- a/chrome/browser/ui/webui/net_internals_ui.cc +++ b/chrome/browser/ui/webui/net_internals_ui.cc @@ -508,7 +508,7 @@ void NetInternalsMessageHandler::OnLoadLogFile(const ListValue* list) { select_log_file_dialog_ = SelectFileDialog::Create(this); select_log_file_dialog_->SelectFile( SelectFileDialog::SELECT_OPEN_FILE, string16(), FilePath(), NULL, 0, - FILE_PATH_LITERAL(""), + FILE_PATH_LITERAL(""), web_ui_->tab_contents(), web_ui_->tab_contents()->view()->GetTopLevelNativeWindow(), NULL); } diff --git a/chrome/browser/ui/webui/options/advanced_options_handler.cc b/chrome/browser/ui/webui/options/advanced_options_handler.cc index 6628a42..9cb60a3 100644 --- a/chrome/browser/ui/webui/options/advanced_options_handler.cc +++ b/chrome/browser/ui/webui/options/advanced_options_handler.cc @@ -341,7 +341,7 @@ void AdvancedOptionsHandler::HandleSelectDownloadLocation( SelectFileDialog::SELECT_FOLDER, l10n_util::GetStringUTF16(IDS_OPTIONS_DOWNLOADLOCATION_BROWSE_TITLE), pref_service->GetFilePath(prefs::kDownloadDefaultDirectory), - NULL, 0, FILE_PATH_LITERAL(""), + NULL, 0, FILE_PATH_LITERAL(""), web_ui_->tab_contents(), web_ui_->tab_contents()->view()->GetTopLevelNativeWindow(), NULL); } diff --git a/chrome/browser/ui/webui/options/certificate_manager_handler.cc b/chrome/browser/ui/webui/options/certificate_manager_handler.cc index 180201b..9262326 100644 --- a/chrome/browser/ui/webui/options/certificate_manager_handler.cc +++ b/chrome/browser/ui/webui/options/certificate_manager_handler.cc @@ -515,8 +515,8 @@ void CertificateManagerHandler::ExportPersonal(const ListValue* args) { select_file_dialog_ = SelectFileDialog::Create(this); select_file_dialog_->SelectFile( SelectFileDialog::SELECT_SAVEAS_FILE, string16(), - FilePath(), &file_type_info, 1, - FILE_PATH_LITERAL("p12"), GetParentWindow(), + FilePath(), &file_type_info, 1, FILE_PATH_LITERAL("p12"), + web_ui_->tab_contents(), GetParentWindow(), reinterpret_cast<void*>(EXPORT_PERSONAL_FILE_SELECTED)); } @@ -603,8 +603,8 @@ void CertificateManagerHandler::StartImportPersonal(const ListValue* args) { select_file_dialog_ = SelectFileDialog::Create(this); select_file_dialog_->SelectFile( SelectFileDialog::SELECT_OPEN_FILE, string16(), - FilePath(), &file_type_info, 1, - FILE_PATH_LITERAL("p12"), GetParentWindow(), + FilePath(), &file_type_info, 1, FILE_PATH_LITERAL("p12"), + web_ui_->tab_contents(), GetParentWindow(), reinterpret_cast<void*>(IMPORT_PERSONAL_FILE_SELECTED)); } @@ -707,6 +707,7 @@ void CertificateManagerHandler::ImportServer(const ListValue* args) { select_file_dialog_.get(), SelectFileDialog::SELECT_OPEN_FILE, FilePath(), + web_ui_->tab_contents(), GetParentWindow(), reinterpret_cast<void*>(IMPORT_SERVER_FILE_SELECTED)); } @@ -761,6 +762,7 @@ void CertificateManagerHandler::ImportCA(const ListValue* args) { ShowCertSelectFileDialog(select_file_dialog_.get(), SelectFileDialog::SELECT_OPEN_FILE, FilePath(), + web_ui_->tab_contents(), GetParentWindow(), reinterpret_cast<void*>(IMPORT_CA_FILE_SELECTED)); } @@ -843,7 +845,8 @@ void CertificateManagerHandler::Export(const ListValue* args) { net::X509Certificate* cert = CallbackArgsToCert(args); if (!cert) return; - ShowCertExportDialog(GetParentWindow(), cert->os_cert_handle()); + ShowCertExportDialog(web_ui_->tab_contents(), GetParentWindow(), + cert->os_cert_handle()); } void CertificateManagerHandler::Delete(const ListValue* args) { diff --git a/chrome/browser/ui/webui/options/chromeos/change_picture_options_handler.cc b/chrome/browser/ui/webui/options/chromeos/change_picture_options_handler.cc index 1741ea9..93f6d74 100644 --- a/chrome/browser/ui/webui/options/chromeos/change_picture_options_handler.cc +++ b/chrome/browser/ui/webui/options/chromeos/change_picture_options_handler.cc @@ -94,6 +94,7 @@ void ChangePictureOptionsHandler::ChooseFile(const ListValue* args) { &file_type_info, 0, FILE_PATH_LITERAL(""), + web_ui_->tab_contents(), NULL, NULL); } diff --git a/chrome/browser/ui/webui/options/extension_settings_handler.cc b/chrome/browser/ui/webui/options/extension_settings_handler.cc index 1392671..68166e8 100644 --- a/chrome/browser/ui/webui/options/extension_settings_handler.cc +++ b/chrome/browser/ui/webui/options/extension_settings_handler.cc @@ -696,7 +696,7 @@ void ExtensionsDOMHandler::HandleSelectFilePathMessage(const ListValue* args) { load_extension_dialog_ = SelectFileDialog::Create(this); load_extension_dialog_->SelectFile(type, select_title, FilePath(), &info, - file_type_index, FILE_PATH_LITERAL(""), + file_type_index, FILE_PATH_LITERAL(""), web_ui_->tab_contents(), web_ui_->tab_contents()->view()->GetTopLevelNativeWindow(), NULL); } diff --git a/chrome/browser/ui/webui/options/personal_options_handler.cc b/chrome/browser/ui/webui/options/personal_options_handler.cc index eacf7ea..820ee74 100644 --- a/chrome/browser/ui/webui/options/personal_options_handler.cc +++ b/chrome/browser/ui/webui/options/personal_options_handler.cc @@ -438,7 +438,8 @@ void PersonalOptionsHandler::LoadAccountPicture(const ListValue* args) { chromeos::UserManager::Get()->logged_in_user(); std::string email = user.email(); if (!email.empty()) { - // int64 is either long or long long, but we need a certain format specifier. + // int64 is either long or long long, but we need a certain format + // specifier. long long timestamp = base::TimeTicks::Now().ToInternalValue(); StringValue image_url( StringPrintf("%s%s?id=%lld", diff --git a/chrome/browser/ui/webui/print_preview_handler.cc b/chrome/browser/ui/webui/print_preview_handler.cc index 9811baf..14b497b 100644 --- a/chrome/browser/ui/webui/print_preview_handler.cc +++ b/chrome/browser/ui/webui/print_preview_handler.cc @@ -255,6 +255,7 @@ void PrintPreviewHandler::SelectFile() { &file_type_info, 0, FILE_PATH_LITERAL(""), + web_ui_->tab_contents(), platform_util::GetTopLevel( web_ui_->tab_contents()->GetNativeView()), NULL); |