summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/app_modal_dialog_queue.cc5
-rw-r--r--chrome/browser/automation/automation_provider.cc37
-rw-r--r--chrome/browser/automation/automation_provider.h2
-rw-r--r--chrome/browser/browser_list.cc17
-rw-r--r--chrome/browser/browser_list.h32
-rw-r--r--chrome/test/automation/automation.vsprops2
-rw-r--r--chrome/test/automation/automation_messages_internal.h15
-rw-r--r--chrome/test/automation/automation_proxy.cc49
-rw-r--r--chrome/test/automation/automation_proxy.h9
-rw-r--r--chrome/test/automation/automation_proxy_uitest.cc88
10 files changed, 203 insertions, 53 deletions
diff --git a/chrome/browser/app_modal_dialog_queue.cc b/chrome/browser/app_modal_dialog_queue.cc
index b0736bc..0bcceb0 100644
--- a/chrome/browser/app_modal_dialog_queue.cc
+++ b/chrome/browser/app_modal_dialog_queue.cc
@@ -24,7 +24,7 @@ void AppModalDialogQueue::AddDialog(views::AppModalDialogDelegate* dialog) {
// static
void AppModalDialogQueue::ShowNextDialog() {
app_modal_dialog_queue_->pop();
- BrowserList::SetIsShowingAppModalDialog(false);
+ BrowserList::SetShowingAppModalDialog(NULL);
if (!app_modal_dialog_queue_->empty()) {
ShowModalDialog(app_modal_dialog_queue_->front());
} else {
@@ -43,6 +43,7 @@ void AppModalDialogQueue::ActivateModalDialog() {
void AppModalDialogQueue::ShowModalDialog(
views::AppModalDialogDelegate* dialog) {
dialog->ShowModalDialog();
- BrowserList::SetIsShowingAppModalDialog(true);
+ BrowserList::SetShowingAppModalDialog(dialog);
}
+
diff --git a/chrome/browser/automation/automation_provider.cc b/chrome/browser/automation/automation_provider.cc
index 146883b..c1d4a15 100644
--- a/chrome/browser/automation/automation_provider.cc
+++ b/chrome/browser/automation/automation_provider.cc
@@ -30,6 +30,8 @@
#include "chrome/common/chrome_paths.h"
#include "chrome/common/pref_service.h"
#include "chrome/test/automation/automation_messages.h"
+#include "chrome/views/app_modal_dialog_delegate.h"
+#include "chrome/views/window.h"
#include "net/base/cookie_monster.h"
#include "net/url_request/url_request_filter.h"
@@ -811,6 +813,8 @@ void AutomationProvider::OnMessageReceived(const IPC::Message& message) {
SetIntPreference)
IPC_MESSAGE_HANDLER(AutomationMsg_ShowingAppModalDialogRequest,
GetShowingAppModalDialog)
+ IPC_MESSAGE_HANDLER(AutomationMsg_ClickAppModalDialogButtonRequest,
+ ClickAppModalDialogButton)
IPC_END_MESSAGE_MAP()
}
@@ -1074,9 +1078,38 @@ void AutomationProvider::GetBrowserWindowCount(const IPC::Message& message) {
}
void AutomationProvider::GetShowingAppModalDialog(const IPC::Message& message) {
+ views::AppModalDialogDelegate* dialog_delegate =
+ BrowserList::GetShowingAppModalDialog();
Send(new AutomationMsg_ShowingAppModalDialogResponse(
- message.routing_id(),
- static_cast<bool>(BrowserList::IsShowingAppModalDialog())));
+ message.routing_id(), dialog_delegate != NULL,
+ dialog_delegate ? dialog_delegate->GetDialogButtons() :
+ views::DialogDelegate::DIALOGBUTTON_NONE));
+}
+
+void AutomationProvider::ClickAppModalDialogButton(const IPC::Message& message,
+ int button) {
+ bool success = false;
+
+ views::AppModalDialogDelegate* dialog_delegate =
+ BrowserList::GetShowingAppModalDialog();
+ if (dialog_delegate &&
+ (dialog_delegate->GetDialogButtons() & button) == button) {
+ views::DialogClientView* client_view =
+ dialog_delegate->window()->client_view()->AsDialogClientView();
+ if ((button & views::DialogDelegate::DIALOGBUTTON_OK) ==
+ views::DialogDelegate::DIALOGBUTTON_OK) {
+ client_view->AcceptWindow();
+ success = true;
+ }
+ if ((button & views::DialogDelegate::DIALOGBUTTON_CANCEL) ==
+ views::DialogDelegate::DIALOGBUTTON_CANCEL) {
+ DCHECK(!success) << "invalid param, OK and CANCEL specified";
+ client_view->CancelWindow();
+ success = true;
+ }
+ }
+ Send(new AutomationMsg_ClickAppModalDialogButtonResponse(
+ message.routing_id(), success));
}
void AutomationProvider::GetBrowserWindow(const IPC::Message& message,
diff --git a/chrome/browser/automation/automation_provider.h b/chrome/browser/automation/automation_provider.h
index 401e0b5..b0e21d3 100644
--- a/chrome/browser/automation/automation_provider.h
+++ b/chrome/browser/automation/automation_provider.h
@@ -106,6 +106,8 @@ class AutomationProvider : public base::RefCounted<AutomationProvider>,
int handle);
void GetBrowserWindowCount(const IPC::Message& message);
void GetShowingAppModalDialog(const IPC::Message& message);
+ void ClickAppModalDialogButton(const IPC::Message& message,
+ int button);
void GetBrowserWindow(const IPC::Message& message, int index);
void GetLastActiveBrowserWindow(const IPC::Message& message);
void GetActiveWindow(const IPC::Message& message);
diff --git a/chrome/browser/browser_list.cc b/chrome/browser/browser_list.cc
index 67d6a56..2665daa 100644
--- a/chrome/browser/browser_list.cc
+++ b/chrome/browser/browser_list.cc
@@ -176,18 +176,23 @@ bool BrowserList::HasBrowserWithProfile(Profile* profile) {
}
// static
-bool BrowserList::is_app_modal_ = false;
+views::AppModalDialogDelegate* BrowserList::app_modal_dialog_ = NULL;
// static
-void BrowserList::SetIsShowingAppModalDialog(bool is_app_modal) {
- // If we are already modal, we can't go modal again.
- DCHECK(!(is_app_modal_ && is_app_modal));
- is_app_modal_ = is_app_modal;
+void BrowserList::SetShowingAppModalDialog(
+ views::AppModalDialogDelegate* dialog) {
+ DCHECK(!(app_modal_dialog_ && dialog));
+ app_modal_dialog_ = dialog;
+}
+
+// static
+views::AppModalDialogDelegate* BrowserList::GetShowingAppModalDialog() {
+ return app_modal_dialog_;
}
// static
bool BrowserList::IsShowingAppModalDialog() {
- return is_app_modal_;
+ return app_modal_dialog_ != NULL;
}
// static
diff --git a/chrome/browser/browser_list.h b/chrome/browser/browser_list.h
index ef9a16f..f9d76c3 100644
--- a/chrome/browser/browser_list.h
+++ b/chrome/browser/browser_list.h
@@ -11,6 +11,7 @@
#include "chrome/browser/browser.h"
namespace views {
+class AppModalDialogDelegate;
class Window;
};
class WebContents;
@@ -76,30 +77,9 @@ class BrowserList {
// Returns true if there is at least one Browser with the specified profile.
static bool HasBrowserWithProfile(Profile* profile);
- // Set whether the last active browser should be modal or not, if
- // |is_app_modal| is true, the last active browser window will be activated
- // and brought to the front whenever the user attempts to activate any other
- // browser window. If |is_app_modal| is false all window activation works as
- // normal. SetIsShowingAppModalDialog should not be called with |is_app_modal|
- // set to true if the last active browser is already modal.
- //
- // TODO(devint): http://b/issue?id=1123402 Application modal dialogs aren't
- // selected, just the last active browser. Therefore, to properly use this
- // function we have to set the modal dialog as a child of a browser,
- // activate that browser window, call SetIsShowingAppModalDialog(true), and
- // implement the modal dialog as window modal to its parent. This still isn't
- // perfect,however, because it just assures that the browser is activated, and
- // the dialog will be on top of that browser, but inactive. It will activate
- // if the users attempts to interact with its parent window (the browser).
- // Ideally we should activate the modal dialog, not just its parent browser.
- //
- // There is probably a less clunky way overall to implement application
- // modality. Currently, if IsShowingAppModalDialog returns true, we handle
- // messages right before the browser activates, and activate whatever
- // GetLastActive() returns instead of whatever was trying to be activated.
- // It'd be better if we could use built in OS modality handling to deal with
- // this, but Windows only supports system modal or parent window modal.
- static void SetIsShowingAppModalDialog(bool is_app_modal);
+ // Sets the passed dialog delegate as the currently showing dialog.
+ static void SetShowingAppModalDialog(views::AppModalDialogDelegate* dialog);
+ static views::AppModalDialogDelegate* GetShowingAppModalDialog();
// True if the last active browser is application modal, false otherwise. See
// SetIsShowingAppModalDialog for more details.
@@ -153,8 +133,8 @@ class BrowserList {
typedef std::vector<views::Window*> DependentWindowList;
static DependentWindowList dependent_windows_;
- // True if last_active_ is app modal, false otherwise.
- static bool is_app_modal_;
+ // Set to the currently showing modal dialog delegate if any, NULL otherwise.
+ static views::AppModalDialogDelegate* app_modal_dialog_;
};
diff --git a/chrome/test/automation/automation.vsprops b/chrome/test/automation/automation.vsprops
index 4cc3b79..23a5fc4 100644
--- a/chrome/test/automation/automation.vsprops
+++ b/chrome/test/automation/automation.vsprops
@@ -3,7 +3,7 @@
ProjectType="Visual C++"
Version="8.00"
Name="automation"
- InheritedPropertySheets="$(SolutionDir)..\build\common.vsprops;$(SolutionDir)..\skia\using_skia.vsprops"
+ InheritedPropertySheets="$(SolutionDir)..\build\common.vsprops;$(SolutionDir)..\skia\using_skia.vsprops;$(SolutionDir)third_party\wtl\using_wtl.vsprops"
>
<Tool
Name="VCCLCompilerTool"
diff --git a/chrome/test/automation/automation_messages_internal.h b/chrome/test/automation/automation_messages_internal.h
index b71457d..165b606 100644
--- a/chrome/test/automation/automation_messages_internal.h
+++ b/chrome/test/automation/automation_messages_internal.h
@@ -802,14 +802,23 @@ IPC_BEGIN_MESSAGES(Automation, 0)
bool /* success */)
// Queries whether an app modal dialog is currently being shown. (i.e. a
- // javascript alert).
+ // javascript alert) and which buttons it contains.
IPC_MESSAGE_ROUTED0(AutomationMsg_ShowingAppModalDialogRequest)
- IPC_MESSAGE_ROUTED1(AutomationMsg_ShowingAppModalDialogResponse,
- bool /* showing dialog */)
+ IPC_MESSAGE_ROUTED2(AutomationMsg_ShowingAppModalDialogResponse,
+ bool /* showing dialog */,
+ int /* view::DelegateDialog::DialogButton */)
// Returns the ordinal and the number of matches found as a response to
// a AutomationMsg_FindRequest.
IPC_MESSAGE_ROUTED2(AutomationMsg_FindInPageResponse2,
int /* active_ordinal */,
int /* matches_found */)
+
+ // This message triggers the specified button for the currently showing
+ // modal dialog.
+ IPC_MESSAGE_ROUTED1(AutomationMsg_ClickAppModalDialogButtonRequest,
+ int /* view::DelegateDialog::DialogButton */)
+ IPC_MESSAGE_ROUTED1(AutomationMsg_ClickAppModalDialogButtonResponse,
+ bool /* success */)
+
IPC_END_MESSAGES(Automation)
diff --git a/chrome/test/automation/automation_proxy.cc b/chrome/test/automation/automation_proxy.cc
index 348ce0f..60806b5 100644
--- a/chrome/test/automation/automation_proxy.cc
+++ b/chrome/test/automation/automation_proxy.cc
@@ -15,6 +15,7 @@
#include "chrome/test/automation/browser_proxy.h"
#include "chrome/test/automation/tab_proxy.h"
#include "chrome/test/automation/window_proxy.h"
+#include "chrome/views/dialog_delegate.h"
using base::TimeDelta;
using base::TimeTicks;
@@ -302,32 +303,56 @@ bool AutomationProxy::WaitForWindowCountToBecome(int count,
return false;
}
-bool AutomationProxy::GetShowingAppModalDialog(bool* showing_app_modal_dialog) {
- if (!showing_app_modal_dialog) {
+bool AutomationProxy::GetShowingAppModalDialog(
+ bool* showing_app_modal_dialog,
+ views::DialogDelegate::DialogButton* button) {
+ if (!showing_app_modal_dialog || !button) {
NOTREACHED();
return false;
}
IPC::Message* response = NULL;
bool is_timeout = true;
- bool succeeded = SendAndWaitForResponseWithTimeout(
- new AutomationMsg_ShowingAppModalDialogRequest(0), &response,
- AutomationMsg_ShowingAppModalDialogResponse::ID,
- kMaxCommandExecutionTime, &is_timeout);
- if (!succeeded)
+ if (!SendAndWaitForResponseWithTimeout(
+ new AutomationMsg_ShowingAppModalDialogRequest(0), &response,
+ AutomationMsg_ShowingAppModalDialogResponse::ID,
+ kMaxCommandExecutionTime, &is_timeout)) {
return false;
+ }
+ scoped_ptr<IPC::Message> response_deleter(response); // Delete on exit.
if (is_timeout) {
DLOG(ERROR) << "ShowingAppModalDialog did not complete in a timely fashion";
return false;
}
void* iter = NULL;
- if (!response->ReadBool(&iter, showing_app_modal_dialog)) {
- succeeded = false;
+ int button_int = 0;
+ if (!response->ReadBool(&iter, showing_app_modal_dialog) ||
+ !response->ReadInt(&iter, &button_int))
+ return false;
+
+ *button = static_cast<views::DialogDelegate::DialogButton>(button_int);
+ return true;
+}
+
+bool AutomationProxy::ClickAppModalDialogButton(
+ views::DialogDelegate::DialogButton button) {
+ IPC::Message* response = NULL;
+ bool is_timeout = true;
+ if (!SendAndWaitForResponseWithTimeout(
+ new AutomationMsg_ClickAppModalDialogButtonRequest(0, button),
+ &response,
+ AutomationMsg_ClickAppModalDialogButtonResponse::ID,
+ kMaxCommandExecutionTime, &is_timeout)) {
+ return false;
}
- delete response;
+ bool succeeded = false;
+ void* iter = NULL;
+ if (!response->ReadBool(&iter, &succeeded))
+ return false;
+
return succeeded;
}
@@ -336,7 +361,9 @@ bool AutomationProxy::WaitForAppModalDialog(int wait_timeout) {
const TimeDelta timeout = TimeDelta::FromMilliseconds(wait_timeout);
while (TimeTicks::Now() - start < timeout) {
bool dialog_shown = false;
- bool succeeded = GetShowingAppModalDialog(&dialog_shown);
+ views::DialogDelegate::DialogButton button =
+ views::DialogDelegate::DIALOGBUTTON_NONE;
+ bool succeeded = GetShowingAppModalDialog(&dialog_shown, &button);
if (!succeeded) {
// Try again next round, but log it.
DLOG(ERROR) << "GetShowingAppModalDialog returned false";
diff --git a/chrome/test/automation/automation_proxy.h b/chrome/test/automation/automation_proxy.h
index 5621b011..0c147fa 100644
--- a/chrome/test/automation/automation_proxy.h
+++ b/chrome/test/automation/automation_proxy.h
@@ -14,6 +14,7 @@
#include "chrome/common/ipc_message.h"
#include "chrome/test/automation/automation_handle_tracker.h"
#include "chrome/test/automation/automation_messages.h"
+#include "chrome/views/dialog_delegate.h"
class AutomationRequest;
class BrowserProxy;
@@ -109,8 +110,12 @@ class AutomationProxy : public IPC::Channel::Listener,
bool WaitForWindowCountToBecome(int target_count, int wait_timeout);
// Returns whether an app modal dialog window is showing right now (i.e., a
- // javascript alert).
- bool GetShowingAppModalDialog(bool* showing_app_modal_dialog);
+ // javascript alert), and what buttons it contains.
+ bool GetShowingAppModalDialog(bool* showing_app_modal_dialog,
+ views::DialogDelegate::DialogButton* button);
+
+ // Simulates a click on a dialog button.
+ bool ClickAppModalDialogButton(views::DialogDelegate::DialogButton button);
// Block the thread until a modal dialog is displayed. Returns true on
// success.
diff --git a/chrome/test/automation/automation_proxy_uitest.cc b/chrome/test/automation/automation_proxy_uitest.cc
index aa24354..ece5fd8 100644
--- a/chrome/test/automation/automation_proxy_uitest.cc
+++ b/chrome/test/automation/automation_proxy_uitest.cc
@@ -17,12 +17,14 @@
#include "chrome/test/automation/tab_proxy.h"
#include "chrome/test/automation/window_proxy.h"
#include "chrome/test/ui/ui_test.h"
+#include "chrome/views/dialog_delegate.h"
#include "chrome/views/event.h"
#include "net/base/net_util.h"
class AutomationProxyTest : public UITest {
protected:
AutomationProxyTest() {
+ dom_automation_enabled_ = true;
CommandLine::AppendSwitchWithValue(&launch_arguments_,
switches::kLang,
L"en-us");
@@ -818,3 +820,89 @@ TEST_F(AutomationProxyVisibleTest, AutocompleteMatchesTest) {
EXPECT_TRUE(edit->GetAutocompleteMatches(&matches));
EXPECT_FALSE(matches.empty());
}
+
+TEST_F(AutomationProxyTest, AppModalDialogTest) {
+ scoped_ptr<BrowserProxy> browser(automation()->GetBrowserWindow(0));
+ ASSERT_TRUE(browser.get());
+ scoped_ptr<TabProxy> tab(browser->GetTab(0));
+ tab.reset(browser->GetTab(0));
+ ASSERT_TRUE(tab.get());
+
+ bool modal_dialog_showing = false;
+ views::DialogDelegate::DialogButton button =
+ views::DialogDelegate::DIALOGBUTTON_NONE;
+ EXPECT_TRUE(automation()->GetShowingAppModalDialog(&modal_dialog_showing,
+ &button));
+ EXPECT_FALSE(modal_dialog_showing);
+ EXPECT_EQ(views::DialogDelegate::DIALOGBUTTON_NONE, button);
+
+ // Show a simple alert.
+ std::string content =
+ "data:text/html,<html><head><script>function onload() {"
+ "setTimeout(\"alert('hello');\", 1000); }</script></head>"
+ "<body onload='onload()'></body></html>";
+ tab->NavigateToURL(GURL(content));
+ EXPECT_TRUE(automation()->WaitForAppModalDialog(3000));
+ EXPECT_TRUE(automation()->GetShowingAppModalDialog(&modal_dialog_showing,
+ &button));
+ EXPECT_TRUE(modal_dialog_showing);
+ EXPECT_EQ(views::DialogDelegate::DIALOGBUTTON_OK, button);
+
+ // Test that clicking missing button fails graciously and does not close the
+ // dialog.
+ EXPECT_FALSE(automation()->ClickAppModalDialogButton(
+ views::DialogDelegate::DIALOGBUTTON_CANCEL));
+ EXPECT_TRUE(automation()->GetShowingAppModalDialog(&modal_dialog_showing,
+ &button));
+ EXPECT_TRUE(modal_dialog_showing);
+
+ // Now click OK, that should close the dialog.
+ EXPECT_TRUE(automation()->ClickAppModalDialogButton(
+ views::DialogDelegate::DIALOGBUTTON_OK));
+ EXPECT_TRUE(automation()->GetShowingAppModalDialog(&modal_dialog_showing,
+ &button));
+ EXPECT_FALSE(modal_dialog_showing);
+
+ // Show a confirm dialog.
+ content =
+ "data:text/html,<html><head><script>var result = -1; function onload() {"
+ "setTimeout(\"result = confirm('hello') ? 0 : 1;\", 1000);} </script>"
+ "</head><body onload='onload()'></body></html>";
+ tab->NavigateToURL(GURL(content));
+ EXPECT_TRUE(automation()->WaitForAppModalDialog(3000));
+ EXPECT_TRUE(automation()->GetShowingAppModalDialog(&modal_dialog_showing,
+ &button));
+ EXPECT_TRUE(modal_dialog_showing);
+ EXPECT_EQ(views::DialogDelegate::DIALOGBUTTON_OK |
+ views::DialogDelegate::DIALOGBUTTON_CANCEL, button);
+
+ // Click OK.
+ EXPECT_TRUE(automation()->ClickAppModalDialogButton(
+ views::DialogDelegate::DIALOGBUTTON_OK));
+ EXPECT_TRUE(automation()->GetShowingAppModalDialog(&modal_dialog_showing,
+ &button));
+ EXPECT_FALSE(modal_dialog_showing);
+ int result = -1;
+ EXPECT_TRUE(tab->ExecuteAndExtractInt(
+ L"", L"window.domAutomationController.send(result);", &result));
+ EXPECT_EQ(0, result);
+
+ // Try again.
+ tab->NavigateToURL(GURL(content));
+ EXPECT_TRUE(automation()->WaitForAppModalDialog(3000));
+ EXPECT_TRUE(automation()->GetShowingAppModalDialog(&modal_dialog_showing,
+ &button));
+ EXPECT_TRUE(modal_dialog_showing);
+ EXPECT_EQ(views::DialogDelegate::DIALOGBUTTON_OK |
+ views::DialogDelegate::DIALOGBUTTON_CANCEL, button);
+
+ // Click Cancel this time.
+ EXPECT_TRUE(automation()->ClickAppModalDialogButton(
+ views::DialogDelegate::DIALOGBUTTON_CANCEL));
+ EXPECT_TRUE(automation()->GetShowingAppModalDialog(&modal_dialog_showing,
+ &button));
+ EXPECT_FALSE(modal_dialog_showing);
+ EXPECT_TRUE(tab->ExecuteAndExtractInt(
+ L"", L"window.domAutomationController.send(result);", &result));
+ EXPECT_EQ(1, result);
+} \ No newline at end of file