summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authorjamescook@chromium.org <jamescook@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-09-02 05:52:39 +0000
committerjamescook@chromium.org <jamescook@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-09-02 05:52:39 +0000
commit000b534024e7abd56628af5522d6e136a0fe2375 (patch)
treec324aaf418be52c008c59fdbbed4acf6073813d7 /chrome
parented83c869d753a929179a2d3926fb6fca0dbdcb8d (diff)
downloadchromium_src-000b534024e7abd56628af5522d6e136a0fe2375.zip
chromium_src-000b534024e7abd56628af5522d6e136a0fe2375.tar.gz
chromium_src-000b534024e7abd56628af5522d6e136a0fe2375.tar.bz2
CrOS - Fix file picker to route callbacks using TabContents
Previously, when the user clicked open/save/cancel in the CrOS file picker, it would route that callback data to the frontmost tab. Sometimes other tabs can switch to frontmost, however. Use set_associated_tab_contents() to inform the extension function implementions of the tab to which to route the callbacks. This also adds a test from tbarzic for the referenced bug. BUG=chromium-os:18956 TEST=browser_tests FileManagerDialogTest.*, also verify you can open the file picker and open/save/cancel under normal conditions Review URL: http://codereview.chromium.org/7830024 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@99327 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r--chrome/browser/extensions/extension_file_browser_private_api.cc26
-rw-r--r--chrome/browser/ui/views/extensions/extension_dialog.cc5
-rw-r--r--chrome/browser/ui/views/extensions/extension_dialog.h3
-rw-r--r--chrome/browser/ui/views/file_manager_dialog.cc13
-rw-r--r--chrome/browser/ui/views/file_manager_dialog_browsertest.cc60
5 files changed, 86 insertions, 21 deletions
diff --git a/chrome/browser/extensions/extension_file_browser_private_api.cc b/chrome/browser/extensions/extension_file_browser_private_api.cc
index 2cd65da..206d5bf 100644
--- a/chrome/browser/extensions/extension_file_browser_private_api.cc
+++ b/chrome/browser/extensions/extension_file_browser_private_api.cc
@@ -907,23 +907,21 @@ FileBrowserFunction::~FileBrowserFunction() {
}
int32 FileBrowserFunction::GetTabId() const {
- int32 tab_id = 0;
if (!dispatcher()) {
- NOTREACHED();
- return tab_id;
+ LOG(WARNING) << "No dispatcher";
+ return 0;
}
-
- // TODO(jamescook): This is going to fail when we switch to tab-modal
- // dialogs. Figure out a way to find which SelectFileDialog::Listener
- // to call from inside these extension FileBrowserFunctions.
- Browser* browser =
- const_cast<FileBrowserFunction*>(this)->GetCurrentBrowser();
- if (browser) {
- TabContents* contents = browser->GetSelectedTabContents();
- if (contents)
- tab_id = ExtensionTabUtil::GetTabId(contents);
+ if (!dispatcher()->delegate()) {
+ LOG(WARNING) << "No delegate";
+ return 0;
+ }
+ TabContents* tab_contents =
+ dispatcher()->delegate()->GetAssociatedTabContents();
+ if (!tab_contents) {
+ LOG(WARNING) << "No associated tab contents";
+ return 0;
}
- return tab_id;
+ return ExtensionTabUtil::GetTabId(tab_contents);
}
// GetFileSystemRootPathOnFileThread can only be called from the file thread,
diff --git a/chrome/browser/ui/views/extensions/extension_dialog.cc b/chrome/browser/ui/views/extensions/extension_dialog.cc
index aadb4c5..d263eb2 100644
--- a/chrome/browser/ui/views/extensions/extension_dialog.cc
+++ b/chrome/browser/ui/views/extensions/extension_dialog.cc
@@ -54,6 +54,7 @@ ExtensionDialog::~ExtensionDialog() {
ExtensionDialog* ExtensionDialog::Show(
const GURL& url,
Browser* browser,
+ TabContents* tab_contents,
int width,
int height,
ExtensionDialogObserver* observer) {
@@ -64,7 +65,9 @@ ExtensionDialog* ExtensionDialog::Show(
if (!manager)
return NULL;
ExtensionHost* host = manager->CreateDialogHost(url, browser);
- DCHECK(host);
+ if (!host)
+ return NULL;
+ host->set_associated_tab_contents(tab_contents);
return new ExtensionDialog(browser, host, width, height, observer);
}
diff --git a/chrome/browser/ui/views/extensions/extension_dialog.h b/chrome/browser/ui/views/extensions/extension_dialog.h
index 741b2c4..654aad1 100644
--- a/chrome/browser/ui/views/extensions/extension_dialog.h
+++ b/chrome/browser/ui/views/extensions/extension_dialog.h
@@ -17,6 +17,7 @@ class ExtensionDialogObserver;
class ExtensionHost;
class GURL;
class Profile;
+class TabContents;
namespace views {
class View;
@@ -35,8 +36,10 @@ class ExtensionDialog : public views::WidgetDelegate,
// Create and show a dialog with |url| centered over the browser window.
// |browser| is the browser to which the pop-up will be attached.
+ // |tab_contents| is the tab that spawned the dialog.
// |width| and |height| are the size of the dialog in pixels.
static ExtensionDialog* Show(const GURL& url, Browser* browser,
+ TabContents* tab_contents,
int width,
int height,
ExtensionDialogObserver* observer);
diff --git a/chrome/browser/ui/views/file_manager_dialog.cc b/chrome/browser/ui/views/file_manager_dialog.cc
index 322ee87..e7f1564 100644
--- a/chrome/browser/ui/views/file_manager_dialog.cc
+++ b/chrome/browser/ui/views/file_manager_dialog.cc
@@ -182,18 +182,19 @@ void FileManagerDialog::SelectFileImpl(
virtual_path = FilePath();
}
+ // Connect our listener to FileDialogFunction's per-tab callbacks.
+ TabContentsWrapper* tab = owner_browser->GetSelectedTabContentsWrapper();
+ int32 tab_id = (tab ? tab->restore_tab_helper()->session_id().id() : 0);
+ PendingDialog::Add(tab_id, this);
+
GURL file_browser_url = FileManagerUtil::GetFileBrowserUrlWithParams(
type, title, virtual_path, file_types, file_type_index,
default_extension);
extension_dialog_ = ExtensionDialog::Show(file_browser_url,
- owner_browser, kFileManagerWidth, kFileManagerHeight,
+ owner_browser, tab->tab_contents(),
+ kFileManagerWidth, kFileManagerHeight,
this /* ExtensionDialog::Observer */);
- // Connect our listener to FileDialogFunction's per-tab callbacks.
- TabContentsWrapper* tab = owner_browser->GetSelectedTabContentsWrapper();
- int32 tab_id = (tab ? tab->restore_tab_helper()->session_id().id() : 0);
- PendingDialog::Add(tab_id, this);
-
params_ = params;
tab_id_ = tab_id;
owner_window_ = owner_window;
diff --git a/chrome/browser/ui/views/file_manager_dialog_browsertest.cc b/chrome/browser/ui/views/file_manager_dialog_browsertest.cc
index 882fc19..0a75797 100644
--- a/chrome/browser/ui/views/file_manager_dialog_browsertest.cc
+++ b/chrome/browser/ui/views/file_manager_dialog_browsertest.cc
@@ -16,6 +16,7 @@
#include "chrome/browser/extensions/extension_test_message_listener.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_navigator.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/shell_dialogs.h" // SelectFileDialog
#include "chrome/common/chrome_paths.h"
@@ -296,3 +297,62 @@ IN_PROC_BROWSER_TEST_F(FileManagerDialogTest, SelectFileAndSave) {
ASSERT_EQ(test_file, listener_->path());
ASSERT_EQ(this, listener_->params());
}
+
+IN_PROC_BROWSER_TEST_F(FileManagerDialogTest, OpenSingletonTabAndCancel) {
+ // Add tmp mount point even though this test won't use it directly.
+ // We need this to make sure that at least one top-level directory exists
+ // in the file browser.
+ FilePath tmp_dir("/tmp");
+ AddMountPoint(tmp_dir);
+
+ // Spawn a dialog to open a file. The dialog will signal that it is ready
+ // via chrome.test.sendMessage() in the extension JavaScript.
+ ExtensionTestMessageListener init_listener("worker-initialized",
+ false /* will_reply */);
+ gfx::NativeWindow owning_window = browser()->window()->GetNativeHandle();
+ dialog_->SelectFile(SelectFileDialog::SELECT_OPEN_FILE,
+ string16() /* title */,
+ FilePath() /* default_path */,
+ NULL /* file_types */,
+ 0 /* file_type_index */,
+ FILE_PATH_LITERAL("") /* default_extension */,
+ NULL /* source_contents */,
+ owning_window,
+ this /* params */);
+ LOG(INFO) << "Waiting for JavaScript ready message.";
+ ASSERT_TRUE(init_listener.WaitUntilSatisfied());
+
+ // Dialog should be running now.
+ ASSERT_TRUE(dialog_->IsRunning(owning_window));
+
+ // Open a singleton tab in background.
+ browser::NavigateParams p(browser(), GURL("www.google.com"),
+ PageTransition::LINK);
+ p.window_action = browser::NavigateParams::SHOW_WINDOW;
+ p.disposition = SINGLETON_TAB;
+ browser::Navigate(&p);
+
+ // Inject JavaScript to click the cancel button and wait for notification
+ // that the window has closed.
+ ui_test_utils::WindowedNotificationObserver host_destroyed(
+ content::NOTIFICATION_RENDER_WIDGET_HOST_DESTROYED,
+ NotificationService::AllSources());
+ RenderViewHost* host = dialog_->GetRenderViewHost();
+ string16 main_frame;
+ string16 script = ASCIIToUTF16(
+ "console.log(\'Test JavaScript injected.\');"
+ "document.querySelector(\'.cancel\').click();");
+ // The file selection handler closes the dialog and does not return control
+ // to JavaScript, so do not wait for return values.
+ host->ExecuteJavascriptInWebFrame(main_frame, script);
+ LOG(INFO) << "Waiting for window close notification.";
+ host_destroyed.Wait();
+
+ // Dialog no longer believes it is running.
+ ASSERT_FALSE(dialog_->IsRunning(owning_window));
+
+ // Listener should have been informed of the cancellation.
+ ASSERT_FALSE(listener_->file_selected());
+ ASSERT_TRUE(listener_->canceled());
+ ASSERT_EQ(this, listener_->params());
+}