Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/file_manager_dialog.h" | 5 #include "chrome/browser/ui/views/file_manager_dialog.h" |
| 6 | 6 |
| 7 #include "base/file_util.h" | 7 #include "base/file_util.h" |
| 8 #include "base/logging.h" | 8 #include "base/logging.h" |
| 9 #include "base/memory/scoped_ptr.h" | 9 #include "base/memory/scoped_ptr.h" |
| 10 #include "base/path_service.h" | 10 #include "base/path_service.h" |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 59 bool file_selected_; | 59 bool file_selected_; |
| 60 bool canceled_; | 60 bool canceled_; |
| 61 FilePath path_; | 61 FilePath path_; |
| 62 void* params_; | 62 void* params_; |
| 63 | 63 |
| 64 DISALLOW_COPY_AND_ASSIGN(MockSelectFileDialogListener); | 64 DISALLOW_COPY_AND_ASSIGN(MockSelectFileDialogListener); |
| 65 }; | 65 }; |
| 66 | 66 |
| 67 class FileManagerDialogBrowserTest : public ExtensionBrowserTest { | 67 class FileManagerDialogBrowserTest : public ExtensionBrowserTest { |
| 68 public: | 68 public: |
| 69 enum DialogButtonType { | |
| 70 DIALOG_BTN_OK, | |
| 71 DIALOG_BTN_CANCEL | |
| 72 }; | |
| 73 | |
| 69 virtual void SetUp() OVERRIDE { | 74 virtual void SetUp() OVERRIDE { |
| 70 // Create the dialog wrapper object, but don't show it yet. | 75 // Create the dialog wrapper object, but don't show it yet. |
| 71 listener_.reset(new MockSelectFileDialogListener()); | 76 listener_.reset(new MockSelectFileDialogListener()); |
| 72 dialog_ = new FileManagerDialog(listener_.get()); | 77 dialog_ = new FileManagerDialog(listener_.get()); |
| 78 | |
| 73 // Must run after our setup because it actually runs the test. | 79 // Must run after our setup because it actually runs the test. |
| 74 ExtensionBrowserTest::SetUp(); | 80 ExtensionBrowserTest::SetUp(); |
| 75 } | 81 } |
| 76 | 82 |
| 77 virtual void TearDown() OVERRIDE { | 83 virtual void TearDown() OVERRIDE { |
| 78 ExtensionBrowserTest::TearDown(); | 84 ExtensionBrowserTest::TearDown(); |
| 79 // Delete the dialog first, as it holds a pointer to the listener. | 85 // Delete the dialog first, as it holds a pointer to the listener. |
| 80 dialog_ = NULL; | 86 dialog_ = NULL; |
| 81 listener_.reset(); | 87 listener_.reset(); |
| 88 | |
| 89 second_dialog_ = NULL; | |
| 90 second_listener_.reset(); | |
| 82 } | 91 } |
| 83 | 92 |
| 84 // Creates a file system mount point for a directory. | 93 // Creates a file system mount point for a directory. |
| 85 void AddMountPoint(const FilePath& path) { | 94 void AddMountPoint(const FilePath& path) { |
| 86 fileapi::FileSystemPathManager* path_manager = | 95 fileapi::FileSystemPathManager* path_manager = |
| 87 browser()->profile()->GetFileSystemContext()->path_manager(); | 96 browser()->profile()->GetFileSystemContext()->path_manager(); |
| 88 fileapi::ExternalFileSystemMountPointProvider* provider = | 97 fileapi::ExternalFileSystemMountPointProvider* provider = |
| 89 path_manager->external_provider(); | 98 path_manager->external_provider(); |
| 90 provider->AddMountPoint(path); | 99 provider->AddMountPoint(path); |
| 91 } | 100 } |
| 92 | 101 |
| 102 void OpenDialog(SelectFileDialog::Type dialog_type, | |
| 103 const FilePath& file_path, | |
| 104 const gfx::NativeWindow& owning_window, | |
| 105 const std::string& additional_message) { | |
| 106 // Spawn a dialog to open a file. The dialog will signal that it is ready | |
| 107 // via chrome.test.sendMessage() in the extension JavaScript. | |
| 108 ExtensionTestMessageListener init_listener("worker-initialized", | |
| 109 false /* will_reply */); | |
| 110 | |
| 111 scoped_ptr<ExtensionTestMessageListener> additional_listener; | |
| 112 if (!additional_message.empty()) { | |
| 113 additional_listener.reset( | |
| 114 new ExtensionTestMessageListener(additional_message, false)); | |
| 115 } | |
| 116 | |
| 117 dialog_->SelectFile(dialog_type, | |
| 118 string16() /* title */, | |
|
achuithb
2011/11/10 23:30:03
Do you like this commenting style? Have you consid
tbarzic
2011/11/11 03:26:24
Usually not, but when commenting function args I p
| |
| 119 file_path, | |
| 120 NULL /* file_types */, | |
| 121 0 /* file_type_index */, | |
| 122 FILE_PATH_LITERAL("") /* default_extension */, | |
| 123 NULL /* source_contents */, | |
| 124 owning_window, | |
| 125 this /* params */); | |
| 126 | |
| 127 LOG(INFO) << "Waiting for JavaScript ready message."; | |
|
achuithb
2011/11/10 23:30:03
Is this logging necessary?
tbarzic
2011/11/11 03:26:24
not necessary, but useful
| |
| 128 ASSERT_TRUE(init_listener.WaitUntilSatisfied()); | |
| 129 | |
| 130 if (additional_listener.get()) { | |
| 131 LOG(INFO) << "Waiting for JavaScript " << additional_message | |
| 132 << " message."; | |
| 133 ASSERT_TRUE(additional_listener->WaitUntilSatisfied()); | |
| 134 } | |
| 135 | |
| 136 // Dialog should be running now. | |
| 137 ASSERT_TRUE(dialog_->IsRunning(owning_window)); | |
| 138 } | |
| 139 | |
| 140 void TryOpeningSecondDialog(const gfx::NativeWindow& owning_window) { | |
| 141 second_listener_.reset(new MockSelectFileDialogListener()); | |
| 142 second_dialog_ = new FileManagerDialog(second_listener_.get()); | |
| 143 | |
| 144 // At the moment we don't really care about dialog type, but we have to put | |
| 145 // some dialog type. | |
|
James Cook
2011/11/10 23:17:18
nit: remove extra space at start of comment
tbarzic
2011/11/11 03:26:24
Done.
| |
| 146 second_dialog_->SelectFile(SelectFileDialog::SELECT_OPEN_FILE, | |
| 147 string16() /* title */, | |
| 148 FilePath() /* default_path */, | |
| 149 NULL /* file_types */, | |
| 150 0 /* file_type_index */, | |
| 151 FILE_PATH_LITERAL("") /* default_extension */, | |
| 152 NULL /* source_contents */, | |
| 153 owning_window, | |
| 154 this /* params */); | |
| 155 | |
| 156 | |
| 157 } | |
| 158 | |
| 159 void CloseDialog(DialogButtonType button_type, | |
| 160 const gfx::NativeWindow& owning_window) { | |
| 161 // Inject JavaScript to click the cancel button and wait for notification | |
| 162 // that the window has closed. | |
| 163 ui_test_utils::WindowedNotificationObserver host_destroyed( | |
| 164 content::NOTIFICATION_RENDER_WIDGET_HOST_DESTROYED, | |
| 165 content::NotificationService::AllSources()); | |
| 166 RenderViewHost* host = dialog_->GetRenderViewHost(); | |
| 167 string16 main_frame; | |
| 168 std::string button_class = | |
| 169 (button_type == DIALOG_BTN_OK) ? ".ok" : ".cancel"; | |
| 170 string16 script = ASCIIToUTF16( | |
| 171 "console.log(\'Test JavaScript injected.\');" | |
| 172 "document.querySelector(\'" + button_class + "\').click();"); | |
| 173 // The file selection handler closes the dialog and does not return control | |
| 174 // to JavaScript, so do not wait for return values. | |
| 175 host->ExecuteJavascriptInWebFrame(main_frame, script); | |
| 176 LOG(INFO) << "Waiting for window close notification."; | |
| 177 host_destroyed.Wait(); | |
| 178 | |
| 179 // Dialog no longer believes it is running. | |
| 180 ASSERT_FALSE(dialog_->IsRunning(owning_window)); | |
| 181 } | |
| 182 | |
| 93 scoped_ptr<MockSelectFileDialogListener> listener_; | 183 scoped_ptr<MockSelectFileDialogListener> listener_; |
| 94 scoped_refptr<FileManagerDialog> dialog_; | 184 scoped_refptr<FileManagerDialog> dialog_; |
| 185 | |
| 186 scoped_ptr<MockSelectFileDialogListener> second_listener_; | |
| 187 scoped_refptr<FileManagerDialog> second_dialog_; | |
| 95 }; | 188 }; |
| 96 | 189 |
| 97 IN_PROC_BROWSER_TEST_F(FileManagerDialogBrowserTest, CreateAndDestroy) { | 190 IN_PROC_BROWSER_TEST_F(FileManagerDialogBrowserTest, CreateAndDestroy) { |
| 98 // Browser window must be up for us to test dialog window parent. | 191 // Browser window must be up for us to test dialog window parent. |
| 99 gfx::NativeWindow native_window = browser()->window()->GetNativeHandle(); | 192 gfx::NativeWindow native_window = browser()->window()->GetNativeHandle(); |
| 100 ASSERT_TRUE(native_window != NULL); | 193 ASSERT_TRUE(native_window != NULL); |
| 101 | 194 |
| 102 // Before we call SelectFile, dialog is not running/visible. | 195 // Before we call SelectFile, dialog is not running/visible. |
| 103 ASSERT_FALSE(dialog_->IsRunning(native_window)); | 196 ASSERT_FALSE(dialog_->IsRunning(native_window)); |
| 104 } | 197 } |
| 105 | 198 |
| 106 IN_PROC_BROWSER_TEST_F(FileManagerDialogBrowserTest, DestroyListener) { | 199 IN_PROC_BROWSER_TEST_F(FileManagerDialogBrowserTest, DestroyListener) { |
| 107 // Some users of SelectFileDialog destroy their listener before cleaning | 200 // Some users of SelectFileDialog destroy their listener before cleaning |
| 108 // up the dialog. Make sure we don't crash. | 201 // up the dialog. Make sure we don't crash. |
| 109 dialog_->ListenerDestroyed(); | 202 dialog_->ListenerDestroyed(); |
| 110 listener_.reset(); | 203 listener_.reset(); |
| 111 } | 204 } |
| 112 | 205 |
| 113 // TODO(jamescook): Add a test for selecting a file for an <input type='file'/> | 206 // TODO(jamescook): Add a test for selecting a file for an <input type='file'/> |
| 114 // page element, as that uses different memory management pathways. | 207 // page element, as that uses different memory management pathways. |
| 115 // crbug.com/98791 | 208 // crbug.com/98791 |
| 116 IN_PROC_BROWSER_TEST_F(FileManagerDialogBrowserTest, SelectFileAndCancel) { | 209 IN_PROC_BROWSER_TEST_F(FileManagerDialogBrowserTest, SelectFileAndCancel) { |
| 117 // Add tmp mount point even though this test won't use it directly. | 210 // Add tmp mount point even though this test won't use it directly. |
| 118 // We need this to make sure that at least one top-level directory exists | 211 // We need this to make sure that at least one top-level directory exists |
| 119 // in the file browser. | 212 // in the file browser. |
| 120 FilePath tmp_dir("/tmp"); | 213 FilePath tmp_dir("/tmp"); |
| 121 AddMountPoint(tmp_dir); | 214 AddMountPoint(tmp_dir); |
| 122 | 215 |
| 123 // Spawn a dialog to open a file. The dialog will signal that it is ready | |
| 124 // via chrome.test.sendMessage() in the extension JavaScript. | |
| 125 ExtensionTestMessageListener init_listener("worker-initialized", | |
| 126 false /* will_reply */); | |
| 127 gfx::NativeWindow owning_window = browser()->window()->GetNativeHandle(); | 216 gfx::NativeWindow owning_window = browser()->window()->GetNativeHandle(); |
| 128 dialog_->SelectFile(SelectFileDialog::SELECT_OPEN_FILE, | |
| 129 string16() /* title */, | |
| 130 FilePath() /* default_path */, | |
| 131 NULL /* file_types */, | |
| 132 0 /* file_type_index */, | |
| 133 FILE_PATH_LITERAL("") /* default_extension */, | |
| 134 NULL /* source_contents */, | |
| 135 owning_window, | |
| 136 this /* params */); | |
| 137 LOG(INFO) << "Waiting for JavaScript ready message."; | |
| 138 ASSERT_TRUE(init_listener.WaitUntilSatisfied()); | |
| 139 | 217 |
| 140 // Dialog should be running now. | 218 // FilePath() for default path. |
| 141 ASSERT_TRUE(dialog_->IsRunning(owning_window)); | 219 OpenDialog(SelectFileDialog::SELECT_OPEN_FILE, FilePath(), owning_window, ""); |
| 142 | 220 |
| 143 // Inject JavaScript to click the cancel button and wait for notification | 221 // Press cancel button. |
| 144 // that the window has closed. | 222 CloseDialog(DIALOG_BTN_CANCEL, owning_window); |
| 145 ui_test_utils::WindowedNotificationObserver host_destroyed( | |
| 146 content::NOTIFICATION_RENDER_WIDGET_HOST_DESTROYED, | |
| 147 content::NotificationService::AllSources()); | |
| 148 RenderViewHost* host = dialog_->GetRenderViewHost(); | |
| 149 string16 main_frame; | |
| 150 string16 script = ASCIIToUTF16( | |
| 151 "console.log(\'Test JavaScript injected.\');" | |
| 152 "document.querySelector(\'.cancel\').click();"); | |
| 153 // The file selection handler closes the dialog and does not return control | |
| 154 // to JavaScript, so do not wait for return values. | |
| 155 host->ExecuteJavascriptInWebFrame(main_frame, script); | |
| 156 LOG(INFO) << "Waiting for window close notification."; | |
| 157 host_destroyed.Wait(); | |
| 158 | |
| 159 // Dialog no longer believes it is running. | |
| 160 ASSERT_FALSE(dialog_->IsRunning(owning_window)); | |
| 161 | 223 |
| 162 // Listener should have been informed of the cancellation. | 224 // Listener should have been informed of the cancellation. |
| 163 ASSERT_FALSE(listener_->file_selected()); | 225 ASSERT_FALSE(listener_->file_selected()); |
| 164 ASSERT_TRUE(listener_->canceled()); | 226 ASSERT_TRUE(listener_->canceled()); |
| 165 ASSERT_EQ(this, listener_->params()); | 227 ASSERT_EQ(this, listener_->params()); |
| 166 } | 228 } |
| 167 | 229 |
| 168 IN_PROC_BROWSER_TEST_F(FileManagerDialogBrowserTest, SelectFileAndOpen) { | 230 IN_PROC_BROWSER_TEST_F(FileManagerDialogBrowserTest, SelectFileAndOpen) { |
| 169 // Allow the tmp directory to be mounted. We explicitly use /tmp because | 231 // Allow the tmp directory to be mounted. We explicitly use /tmp because |
| 170 // it it whitelisted for file system access on Chrome OS. | 232 // it it whitelisted for file system access on Chrome OS. |
| 171 FilePath tmp_dir("/tmp"); | 233 FilePath tmp_dir("/tmp"); |
| 172 AddMountPoint(tmp_dir); | 234 AddMountPoint(tmp_dir); |
| 173 | 235 |
| 174 // Create a directory with a single file in it. ScopedTempDir will delete | 236 // Create a directory with a single file in it. ScopedTempDir will delete |
| 175 // itself and our temp file when it goes out of scope. | 237 // itself and our temp file when it goes out of scope. |
| 176 ScopedTempDir scoped_temp_dir; | 238 ScopedTempDir scoped_temp_dir; |
| 177 ASSERT_TRUE(scoped_temp_dir.CreateUniqueTempDirUnderPath(tmp_dir)); | 239 ASSERT_TRUE(scoped_temp_dir.CreateUniqueTempDirUnderPath(tmp_dir)); |
| 178 FilePath temp_dir = scoped_temp_dir.path(); | 240 FilePath temp_dir = scoped_temp_dir.path(); |
| 179 FilePath test_file = temp_dir.AppendASCII("file_manager_test.html"); | 241 FilePath test_file = temp_dir.AppendASCII("file_manager_test.html"); |
| 180 | 242 |
| 181 // Create an empty file to give us something to select. | 243 // Create an empty file to give us something to select. |
| 182 FILE* fp = file_util::OpenFile(test_file, "w"); | 244 FILE* fp = file_util::OpenFile(test_file, "w"); |
| 183 ASSERT_TRUE(fp != NULL); | 245 ASSERT_TRUE(fp != NULL); |
| 184 ASSERT_TRUE(file_util::CloseFile(fp)); | 246 ASSERT_TRUE(file_util::CloseFile(fp)); |
| 185 | 247 |
| 248 gfx::NativeWindow owning_window = browser()->window()->GetNativeHandle(); | |
| 249 | |
| 186 // Spawn a dialog to open a file. Provide the path to the file so the dialog | 250 // Spawn a dialog to open a file. Provide the path to the file so the dialog |
| 187 // will automatically select it. Ensure that the OK button is enabled by | 251 // will automatically select it. Ensure that the OK button is enabled by |
| 188 // waiting for chrome.test.sendMessage('selection-change-complete'). | 252 // waiting for chrome.test.sendMessage('selection-change-complete'). |
| 189 // The extension starts a Web Worker to read file metadata, so it may send | 253 // The extension starts a Web Worker to read file metadata, so it may send |
| 190 // 'selection-change-complete' before 'worker-initialized'. This is OK. | 254 // 'selection-change-complete' before 'worker-initialized'. This is OK. |
| 191 ExtensionTestMessageListener init_listener("worker-initialized", | 255 OpenDialog(SelectFileDialog::SELECT_OPEN_FILE, test_file, owning_window, |
| 192 false /* will_reply */); | 256 "selection-change-complete"); |
| 193 ExtensionTestMessageListener selection_listener("selection-change-complete", | |
| 194 false /* will_reply */); | |
| 195 gfx::NativeWindow owning_window = browser()->window()->GetNativeHandle(); | |
| 196 dialog_->SelectFile(SelectFileDialog::SELECT_OPEN_FILE, | |
| 197 string16() /* title */, | |
| 198 test_file, | |
| 199 NULL /* file_types */, | |
| 200 0 /* file_type_index */, | |
| 201 FILE_PATH_LITERAL("") /* default_extension */, | |
| 202 NULL /* source_contents */, | |
| 203 owning_window, | |
| 204 this /* params */); | |
| 205 LOG(INFO) << "Waiting for JavaScript initialized message."; | |
| 206 ASSERT_TRUE(init_listener.WaitUntilSatisfied()); | |
| 207 LOG(INFO) << "Waiting for JavaScript selection-change-complete message."; | |
| 208 ASSERT_TRUE(selection_listener.WaitUntilSatisfied()); | |
| 209 | 257 |
| 210 // Dialog should be running now. | 258 // Click open button. |
| 211 ASSERT_TRUE(dialog_->IsRunning(owning_window)); | 259 CloseDialog(DIALOG_BTN_OK, owning_window); |
| 212 | |
| 213 // Inject JavaScript to click the open button and wait for notification | |
| 214 // that the window has closed. | |
| 215 ui_test_utils::WindowedNotificationObserver host_destroyed( | |
| 216 content::NOTIFICATION_RENDER_WIDGET_HOST_DESTROYED, | |
| 217 content::NotificationService::AllSources()); | |
| 218 RenderViewHost* host = dialog_->GetRenderViewHost(); | |
| 219 string16 main_frame; | |
| 220 string16 script = ASCIIToUTF16( | |
| 221 "console.log(\'Test JavaScript injected.\');" | |
| 222 "document.querySelector('.ok').click();"); | |
| 223 // The file selection handler closes the dialog and does not return control | |
| 224 // to JavaScript, so do not wait for return values. | |
| 225 host->ExecuteJavascriptInWebFrame(main_frame, script); | |
| 226 LOG(INFO) << "Waiting for window close notification."; | |
| 227 host_destroyed.Wait(); | |
| 228 | |
| 229 // Dialog no longer believes it is running. | |
| 230 ASSERT_FALSE(dialog_->IsRunning(owning_window)); | |
| 231 | 260 |
| 232 // Listener should have been informed that the file was opened. | 261 // Listener should have been informed that the file was opened. |
| 233 ASSERT_TRUE(listener_->file_selected()); | 262 ASSERT_TRUE(listener_->file_selected()); |
| 234 ASSERT_FALSE(listener_->canceled()); | 263 ASSERT_FALSE(listener_->canceled()); |
| 235 ASSERT_EQ(test_file, listener_->path()); | 264 ASSERT_EQ(test_file, listener_->path()); |
| 236 ASSERT_EQ(this, listener_->params()); | 265 ASSERT_EQ(this, listener_->params()); |
| 237 } | 266 } |
| 238 | 267 |
| 239 IN_PROC_BROWSER_TEST_F(FileManagerDialogBrowserTest, SelectFileAndSave) { | 268 IN_PROC_BROWSER_TEST_F(FileManagerDialogBrowserTest, SelectFileAndSave) { |
| 240 // Allow the tmp directory to be mounted. We explicitly use /tmp because | 269 // Allow the tmp directory to be mounted. We explicitly use /tmp because |
| 241 // it it whitelisted for file system access on Chrome OS. | 270 // it it whitelisted for file system access on Chrome OS. |
| 242 FilePath tmp_dir("/tmp"); | 271 FilePath tmp_dir("/tmp"); |
| 243 AddMountPoint(tmp_dir); | 272 AddMountPoint(tmp_dir); |
| 244 | 273 |
| 245 // Create a directory with a single file in it. ScopedTempDir will delete | 274 // Create a directory with a single file in it. ScopedTempDir will delete |
| 246 // itself and our temp file when it goes out of scope. | 275 // itself and our temp file when it goes out of scope. |
| 247 ScopedTempDir scoped_temp_dir; | 276 ScopedTempDir scoped_temp_dir; |
| 248 ASSERT_TRUE(scoped_temp_dir.CreateUniqueTempDirUnderPath(tmp_dir)); | 277 ASSERT_TRUE(scoped_temp_dir.CreateUniqueTempDirUnderPath(tmp_dir)); |
| 249 FilePath temp_dir = scoped_temp_dir.path(); | 278 FilePath temp_dir = scoped_temp_dir.path(); |
| 250 FilePath test_file = temp_dir.AppendASCII("file_manager_test.html"); | 279 FilePath test_file = temp_dir.AppendASCII("file_manager_test.html"); |
| 251 | 280 |
| 281 gfx::NativeWindow owning_window = browser()->window()->GetNativeHandle(); | |
| 282 | |
| 252 // Spawn a dialog to save a file, providing a suggested path. | 283 // Spawn a dialog to save a file, providing a suggested path. |
| 253 // Ensure "Save" button is enabled by waiting for notification from | 284 // Ensure "Save" button is enabled by waiting for notification from |
| 254 // chrome.test.sendMessage(). | 285 // chrome.test.sendMessage(). |
| 255 // The extension starts a Web Worker to read file metadata, so it may send | 286 // The extension starts a Web Worker to read file metadata, so it may send |
| 256 // 'directory-change-complete' before 'worker-initialized'. This is OK. | 287 // 'directory-change-complete' before 'worker-initialized'. This is OK. |
| 257 ExtensionTestMessageListener init_listener("worker-initialized", | 288 OpenDialog(SelectFileDialog::SELECT_SAVEAS_FILE, test_file, owning_window, |
| 258 false /* will_reply */); | 289 "directory-change-complete"); |
| 259 ExtensionTestMessageListener dir_change_listener("directory-change-complete", | |
| 260 false /* will_reply */); | |
| 261 gfx::NativeWindow owning_window = browser()->window()->GetNativeHandle(); | |
| 262 dialog_->SelectFile(SelectFileDialog::SELECT_SAVEAS_FILE, | |
| 263 string16() /* title */, | |
| 264 test_file, | |
| 265 NULL /* file_types */, | |
| 266 0 /* file_type_index */, | |
| 267 FILE_PATH_LITERAL("") /* default_extension */, | |
| 268 NULL /* source_contents */, | |
| 269 owning_window, | |
| 270 this /* params */); | |
| 271 LOG(INFO) << "Waiting for JavaScript initialized message."; | |
| 272 ASSERT_TRUE(init_listener.WaitUntilSatisfied()); | |
| 273 LOG(INFO) << "Waiting for JavaScript directory-change-complete message."; | |
| 274 ASSERT_TRUE(dir_change_listener.WaitUntilSatisfied()); | |
| 275 | 290 |
| 276 // Dialog should be running now. | 291 // Click save button. |
| 277 ASSERT_TRUE(dialog_->IsRunning(owning_window)); | 292 CloseDialog(DIALOG_BTN_OK, owning_window); |
| 278 | |
| 279 // Inject JavaScript to click the save button and wait for notification | |
| 280 // that the window has closed. | |
| 281 ui_test_utils::WindowedNotificationObserver host_destroyed( | |
| 282 content::NOTIFICATION_RENDER_WIDGET_HOST_DESTROYED, | |
| 283 content::NotificationService::AllSources()); | |
| 284 RenderViewHost* host = dialog_->GetRenderViewHost(); | |
| 285 string16 main_frame; | |
| 286 string16 script = ASCIIToUTF16( | |
| 287 "console.log(\'Test JavaScript injected.\');" | |
| 288 "document.querySelector('.ok').click();"); | |
| 289 // The file selection handler closes the dialog and does not return control | |
| 290 // to JavaScript, so do not wait for return values. | |
| 291 host->ExecuteJavascriptInWebFrame(main_frame, script); | |
| 292 LOG(INFO) << "Waiting for window close notification."; | |
| 293 host_destroyed.Wait(); | |
| 294 | |
| 295 // Dialog no longer believes it is running. | |
| 296 ASSERT_FALSE(dialog_->IsRunning(owning_window)); | |
| 297 | 293 |
| 298 // Listener should have been informed that the file was selected. | 294 // Listener should have been informed that the file was selected. |
| 299 ASSERT_TRUE(listener_->file_selected()); | 295 ASSERT_TRUE(listener_->file_selected()); |
| 300 ASSERT_FALSE(listener_->canceled()); | 296 ASSERT_FALSE(listener_->canceled()); |
| 301 ASSERT_EQ(test_file, listener_->path()); | 297 ASSERT_EQ(test_file, listener_->path()); |
| 302 ASSERT_EQ(this, listener_->params()); | 298 ASSERT_EQ(this, listener_->params()); |
| 303 } | 299 } |
| 304 | 300 |
| 305 IN_PROC_BROWSER_TEST_F(FileManagerDialogBrowserTest, | 301 IN_PROC_BROWSER_TEST_F(FileManagerDialogBrowserTest, |
| 306 OpenSingletonTabAndCancel) { | 302 OpenSingletonTabAndCancel) { |
| 307 // Add tmp mount point even though this test won't use it directly. | 303 // Add tmp mount point even though this test won't use it directly. |
| 308 // We need this to make sure that at least one top-level directory exists | 304 // We need this to make sure that at least one top-level directory exists |
| 309 // in the file browser. | 305 // in the file browser. |
| 310 FilePath tmp_dir("/tmp"); | 306 FilePath tmp_dir("/tmp"); |
| 311 AddMountPoint(tmp_dir); | 307 AddMountPoint(tmp_dir); |
| 312 | 308 |
| 313 // Spawn a dialog to open a file. The dialog will signal that it is ready | |
| 314 // via chrome.test.sendMessage() in the extension JavaScript. | |
| 315 ExtensionTestMessageListener init_listener("worker-initialized", | |
| 316 false /* will_reply */); | |
| 317 gfx::NativeWindow owning_window = browser()->window()->GetNativeHandle(); | 309 gfx::NativeWindow owning_window = browser()->window()->GetNativeHandle(); |
| 318 dialog_->SelectFile(SelectFileDialog::SELECT_OPEN_FILE, | |
| 319 string16() /* title */, | |
| 320 FilePath() /* default_path */, | |
| 321 NULL /* file_types */, | |
| 322 0 /* file_type_index */, | |
| 323 FILE_PATH_LITERAL("") /* default_extension */, | |
| 324 NULL /* source_contents */, | |
| 325 owning_window, | |
| 326 this /* params */); | |
| 327 LOG(INFO) << "Waiting for JavaScript ready message."; | |
| 328 ASSERT_TRUE(init_listener.WaitUntilSatisfied()); | |
| 329 | 310 |
| 330 // Dialog should be running now. | 311 OpenDialog(SelectFileDialog::SELECT_OPEN_FILE, FilePath(), owning_window, ""); |
| 331 ASSERT_TRUE(dialog_->IsRunning(owning_window)); | |
| 332 | 312 |
| 333 // Open a singleton tab in background. | 313 // Open a singleton tab in background. |
| 334 browser::NavigateParams p(browser(), GURL("www.google.com"), | 314 browser::NavigateParams p(browser(), GURL("www.google.com"), |
| 335 content::PAGE_TRANSITION_LINK); | 315 content::PAGE_TRANSITION_LINK); |
| 336 p.window_action = browser::NavigateParams::SHOW_WINDOW; | 316 p.window_action = browser::NavigateParams::SHOW_WINDOW; |
| 337 p.disposition = SINGLETON_TAB; | 317 p.disposition = SINGLETON_TAB; |
| 338 browser::Navigate(&p); | 318 browser::Navigate(&p); |
| 339 | 319 |
| 340 // Inject JavaScript to click the cancel button and wait for notification | 320 // Press cancel button. |
| 341 // that the window has closed. | 321 CloseDialog(DIALOG_BTN_CANCEL, owning_window); |
| 342 ui_test_utils::WindowedNotificationObserver host_destroyed( | |
| 343 content::NOTIFICATION_RENDER_WIDGET_HOST_DESTROYED, | |
| 344 content::NotificationService::AllSources()); | |
| 345 RenderViewHost* host = dialog_->GetRenderViewHost(); | |
| 346 string16 main_frame; | |
| 347 string16 script = ASCIIToUTF16( | |
| 348 "console.log(\'Test JavaScript injected.\');" | |
| 349 "document.querySelector(\'.cancel\').click();"); | |
| 350 // The file selection handler closes the dialog and does not return control | |
| 351 // to JavaScript, so do not wait for return values. | |
| 352 host->ExecuteJavascriptInWebFrame(main_frame, script); | |
| 353 LOG(INFO) << "Waiting for window close notification."; | |
| 354 host_destroyed.Wait(); | |
| 355 | |
| 356 // Dialog no longer believes it is running. | |
| 357 ASSERT_FALSE(dialog_->IsRunning(owning_window)); | |
| 358 | 322 |
| 359 // Listener should have been informed of the cancellation. | 323 // Listener should have been informed of the cancellation. |
| 360 ASSERT_FALSE(listener_->file_selected()); | 324 ASSERT_FALSE(listener_->file_selected()); |
| 325 ASSERT_TRUE(listener_->canceled()); | |
| 326 ASSERT_EQ(this, listener_->params()); | |
| 327 } | |
| 328 | |
| 329 IN_PROC_BROWSER_TEST_F(FileManagerDialogBrowserTest, OpenTwoDialogs) { | |
| 330 // Add tmp mount point even though this test won't use it directly. | |
| 331 // We need this to make sure that at least one top-level directory exists | |
| 332 // in the file browser. | |
| 333 FilePath tmp_dir("/tmp"); | |
| 334 AddMountPoint(tmp_dir); | |
| 335 | |
| 336 gfx::NativeWindow owning_window = browser()->window()->GetNativeHandle(); | |
| 337 | |
| 338 OpenDialog(SelectFileDialog::SELECT_OPEN_FILE, FilePath(), owning_window, ""); | |
| 339 | |
| 340 TryOpeningSecondDialog(owning_window); | |
| 341 | |
| 342 // Second dialog should not be running. | |
| 343 ASSERT_FALSE(second_dialog_->IsRunning(owning_window)); | |
| 344 | |
| 345 // Click cancel button. | |
| 346 CloseDialog(DIALOG_BTN_CANCEL, owning_window); | |
| 347 | |
| 348 // Listener should have been informed of the cancellation. | |
| 349 ASSERT_FALSE(listener_->file_selected()); | |
| 361 ASSERT_TRUE(listener_->canceled()); | 350 ASSERT_TRUE(listener_->canceled()); |
| 362 ASSERT_EQ(this, listener_->params()); | 351 ASSERT_EQ(this, listener_->params()); |
| 363 } | 352 } |
| OLD | NEW |