summaryrefslogtreecommitdiffstats
path: root/chrome_frame
diff options
context:
space:
mode:
authorerikwright@chromium.org <erikwright@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-01-24 19:27:32 +0000
committererikwright@chromium.org <erikwright@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-01-24 19:27:32 +0000
commit28efc58634459b8fc65ee1a5cb00a4351e7179b9 (patch)
tree587568b6b0845d11b2238ebb30671d467cf34c81 /chrome_frame
parent3b17959e51578bb2fba9f22100a199c436e31d5d (diff)
downloadchromium_src-28efc58634459b8fc65ee1a5cb00a4351e7179b9.zip
chromium_src-28efc58634459b8fc65ee1a5cb00a4351e7179b9.tar.gz
chromium_src-28efc58634459b8fc65ee1a5cb00a4351e7179b9.tar.bz2
Update the Ready Mode UI in response to feedback from UI leads, Chrome Frame team.
BUG=None TEST=chrome_frame_unittests --gtest_filter=Ready* Review URL: http://codereview.chromium.org/6314016 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@72366 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome_frame')
-rw-r--r--chrome_frame/chrome_frame.gyp1
-rw-r--r--chrome_frame/ready_mode/internal/ready_prompt_content.cc17
-rw-r--r--chrome_frame/ready_mode/internal/ready_prompt_content.h9
-rw-r--r--chrome_frame/ready_mode/internal/ready_prompt_window.cc62
-rw-r--r--chrome_frame/ready_mode/internal/ready_prompt_window.h37
-rw-r--r--chrome_frame/ready_mode/internal/url_launcher.h20
-rw-r--r--chrome_frame/ready_mode/ready_mode.cc35
-rw-r--r--chrome_frame/test/ready_mode_unittest.cc33
8 files changed, 168 insertions, 46 deletions
diff --git a/chrome_frame/chrome_frame.gyp b/chrome_frame/chrome_frame.gyp
index a50096f..e1596c8 100644
--- a/chrome_frame/chrome_frame.gyp
+++ b/chrome_frame/chrome_frame.gyp
@@ -872,6 +872,7 @@
'ready_mode/internal/ready_prompt_window.h',
'ready_mode/internal/registry_ready_mode_state.cc',
'ready_mode/internal/registry_ready_mode_state.h',
+ 'ready_mode/internal/url_launcher.h',
'ready_mode/ready_mode.cc',
'ready_mode/ready_mode.h',
'register_bho.rgs',
diff --git a/chrome_frame/ready_mode/internal/ready_prompt_content.cc b/chrome_frame/ready_mode/internal/ready_prompt_content.cc
index 4764e63..52ab70f 100644
--- a/chrome_frame/ready_mode/internal/ready_prompt_content.cc
+++ b/chrome_frame/ready_mode/internal/ready_prompt_content.cc
@@ -4,15 +4,15 @@
#include "chrome_frame/ready_mode/internal/ready_prompt_content.h"
-#include <atlbase.h>
-#include <atlwin.h>
-
#include "base/logging.h"
#include "chrome_frame/ready_mode/internal/ready_mode_state.h"
#include "chrome_frame/ready_mode/internal/ready_prompt_window.h"
+#include "chrome_frame/ready_mode/internal/url_launcher.h"
-ReadyPromptContent::ReadyPromptContent(ReadyModeState* ready_mode_state)
- : ready_mode_state_(ready_mode_state) {
+ReadyPromptContent::ReadyPromptContent(ReadyModeState* ready_mode_state,
+ UrlLauncher* url_launcher)
+ : ready_mode_state_(ready_mode_state),
+ url_launcher_(url_launcher) {
}
ReadyPromptContent::~ReadyPromptContent() {
@@ -26,10 +26,11 @@ ReadyPromptContent::~ReadyPromptContent() {
bool ReadyPromptContent::InstallInFrame(Frame* frame) {
DCHECK(window_ == NULL);
DCHECK(ready_mode_state_ != NULL);
+ DCHECK(url_launcher_ != NULL);
- // The window owns itself upon call to Initialize.
- ReadyPromptWindow* new_window_ = new ReadyPromptWindow();
- window_ = new_window_->Initialize(frame, ready_mode_state_.release());
+ // Pass ownership of our ready_mode_state_ and url_launcher_ to the window.
+ window_ = ReadyPromptWindow::CreateInstance(
+ frame, ready_mode_state_.release(), url_launcher_.release());
return window_ != NULL;
}
diff --git a/chrome_frame/ready_mode/internal/ready_prompt_content.h b/chrome_frame/ready_mode/internal/ready_prompt_content.h
index bb8692e..5a1f670 100644
--- a/chrome_frame/ready_mode/internal/ready_prompt_content.h
+++ b/chrome_frame/ready_mode/internal/ready_prompt_content.h
@@ -13,14 +13,18 @@
class ReadyModeState;
class ReadyPromptWindow;
+class UrlLauncher;
// Encapsulates the Ready Mode prompt inviting users to permanently activate
// Chrome Frame, temporarily disable Ready Mode, or permanently disable Ready
// Mode.
class ReadyPromptContent : public InfobarContent {
public:
- explicit ReadyPromptContent(ReadyModeState* ready_mode_state);
- ~ReadyPromptContent();
+ // Takes ownership of the ReadyModeState and UrlLauncher instances, which
+ // will be freed upon destruction of the ReadyPromptContent.
+ ReadyPromptContent(ReadyModeState* ready_mode_state,
+ UrlLauncher* url_launcher);
+ virtual ~ReadyPromptContent();
// InfobarContent implementation
virtual bool InstallInFrame(Frame* frame);
@@ -30,6 +34,7 @@ class ReadyPromptContent : public InfobarContent {
private:
base::WeakPtr<ReadyPromptWindow> window_;
scoped_ptr<ReadyModeState> ready_mode_state_;
+ scoped_ptr<UrlLauncher> url_launcher_;
DISALLOW_COPY_AND_ASSIGN(ReadyPromptContent);
}; // class ReadyPromptContent
diff --git a/chrome_frame/ready_mode/internal/ready_prompt_window.cc b/chrome_frame/ready_mode/internal/ready_prompt_window.cc
index b05fbce..ddb51a9 100644
--- a/chrome_frame/ready_mode/internal/ready_prompt_window.cc
+++ b/chrome_frame/ready_mode/internal/ready_prompt_window.cc
@@ -4,33 +4,63 @@
#include "chrome_frame/ready_mode/internal/ready_prompt_window.h"
+#include <atlctrls.h>
+#include <Shellapi.h> // Must appear before atlctrlx.h
+
+// These seem to be required by atlctrlx?
+template<class A>
+A min(A const& a, A const& b) { return a < b ? a : b; }
+
+template<class A>
+A max(A const& a, A const& b) { return a > b ? a : b; }
+
+#include <atlctrlx.h>
+
#include "base/compiler_specific.h"
+#include "base/win/scoped_bstr.h"
+#include "base/win/scoped_comptr.h"
#include "chrome_frame/ready_mode/internal/ready_mode_state.h"
+#include "chrome_frame/ready_mode/internal/url_launcher.h"
+#include "chrome_frame/simple_resource_loader.h"
+#include "grit/chromium_strings.h"
-ReadyPromptWindow::ReadyPromptWindow()
- : frame_(NULL),
+ReadyPromptWindow::ReadyPromptWindow(
+ InfobarContent::Frame* frame, ReadyModeState* ready_mode_state,
+ UrlLauncher* url_launcher)
+ : frame_(frame),
+ ready_mode_state_(ready_mode_state),
+ url_launcher_(url_launcher),
weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
}
+ReadyPromptWindow::~ReadyPromptWindow() {
+}
-base::WeakPtr<ReadyPromptWindow> ReadyPromptWindow::Initialize(
- InfobarContent::Frame* frame, ReadyModeState* ready_mode_state) {
+base::WeakPtr<ReadyPromptWindow> ReadyPromptWindow::CreateInstance(
+ InfobarContent::Frame* frame, ReadyModeState* ready_mode_state,
+ UrlLauncher* url_launcher) {
DCHECK(frame != NULL);
- DCHECK(frame_ == NULL);
DCHECK(ready_mode_state != NULL);
- DCHECK(ready_mode_state_ == NULL);
+ DCHECK(url_launcher != NULL);
- frame_ = frame;
- ready_mode_state_.reset(ready_mode_state);
+ base::WeakPtr<ReadyPromptWindow> instance((new ReadyPromptWindow(
+ frame, ready_mode_state, url_launcher))->weak_ptr_factory_.GetWeakPtr());
- DCHECK(!IsWindow());
+ DCHECK(!instance->IsWindow());
- if (Create(frame->GetFrameWindow()) == NULL) {
+ if (instance->Create(frame->GetFrameWindow()) == NULL) {
DPLOG(ERROR) << "Failed to create HWND for ReadyPromptWindow.";
- delete this;
return base::WeakPtr<ReadyPromptWindow>();
}
- return weak_ptr_factory_.GetWeakPtr();
+ // Subclass the "Learn more." text to make it behave like a link. Clicks are
+ // routed to OnLearnMore().
+ CWindow rte = instance->GetDlgItem(IDC_PROMPT_LINK);
+ instance->link_.reset(new CHyperLink());
+ instance->link_->SubclassWindow(rte);
+ instance->link_->SetHyperLinkExtendedStyle(HLINK_NOTIFYBUTTON,
+ HLINK_NOTIFYBUTTON);
+
+ return instance;
}
void ReadyPromptWindow::OnDestroy() {
@@ -69,6 +99,14 @@ LRESULT ReadyPromptWindow::OnNo(WORD /*wNotifyCode*/,
return 0;
}
+LRESULT ReadyPromptWindow::OnLearnMore(WORD /*wParam*/,
+ LPNMHDR /*lParam*/,
+ BOOL& /*bHandled*/) {
+ url_launcher_->LaunchUrl(SimpleResourceLoader::Get(
+ IDS_CHROME_FRAME_READY_MODE_LEARN_MORE_URL));
+ return 0;
+}
+
void ReadyPromptWindow::OnFinalMessage(HWND) {
delete this;
}
diff --git a/chrome_frame/ready_mode/internal/ready_prompt_window.h b/chrome_frame/ready_mode/internal/ready_prompt_window.h
index 2d931a3..5dc87ae 100644
--- a/chrome_frame/ready_mode/internal/ready_prompt_window.h
+++ b/chrome_frame/ready_mode/internal/ready_prompt_window.h
@@ -14,11 +14,17 @@
#include "base/weak_ptr.h"
#include "base/scoped_ptr.h"
+#include "base/win/scoped_comptr.h"
#include "chrome_frame/infobars/infobar_content.h"
#include "chrome_frame/resource.h"
#include "grit/generated_resources.h"
class ReadyModeState;
+class UrlLauncher;
+
+namespace WTL {
+class CHyperLink;
+} // namespace WTL
// Implements a dialog with text and buttons inviting the user to permanently
// activate the product or temporarily/permanently disable Ready Mode.
@@ -28,39 +34,49 @@ class ReadyPromptWindow
public:
enum { IDD = IDD_CHROME_FRAME_READY_PROMPT };
- ReadyPromptWindow();
- ~ReadyPromptWindow() {}
-
- // Initializes the dialog for display in the provided frame. The
+ // Creates and initializes a dialog for display in the provided frame. The
// ReadyModeState will be invoked to capture the user's response, if any.
+ // The UrlLauncher may be used to launch a new tab containing a
+ // knowledge-base article about Ready Mode.
//
// Upon success, takes ownership of itself (to be deleted upon WM_DESTROY) and
// returns a weak pointer to this dialog. Upon failure, returns a null weak
// pointer and deletes self.
//
- // In either case, takes ownership of the ReadyModeState, but not the frame.
- base::WeakPtr<ReadyPromptWindow> Initialize(InfobarContent::Frame* frame,
- ReadyModeState* ready_mode_state);
+ // In either case, takes ownership of the ReadyModeState and UrlLauncher, but
+ // not the frame.
+ static base::WeakPtr<ReadyPromptWindow> CreateInstance(
+ InfobarContent::Frame* frame,
+ ReadyModeState* ready_mode_state,
+ UrlLauncher* url_launcher);
BEGIN_MSG_MAP(InfobarWindow)
MSG_WM_INITDIALOG(OnInitDialog)
MSG_WM_DESTROY(OnDestroy)
+ NOTIFY_HANDLER(IDC_PROMPT_LINK, NM_CLICK, OnLearnMore)
COMMAND_HANDLER(IDACTIVATE, BN_CLICKED, OnYes)
- COMMAND_HANDLER(IDLATER, BN_CLICKED, OnRemindMeLater)
COMMAND_HANDLER(IDNEVER, BN_CLICKED, OnNo)
CHAIN_MSG_MAP(CDialogResize<ReadyPromptWindow>)
END_MSG_MAP()
BEGIN_DLGRESIZE_MAP(InfobarWindow)
DLGRESIZE_CONTROL(IDACTIVATE, DLSZ_CENTER_Y | DLSZ_MOVE_X)
- DLGRESIZE_CONTROL(IDLATER, DLSZ_CENTER_Y | DLSZ_MOVE_X)
DLGRESIZE_CONTROL(IDNEVER, DLSZ_CENTER_Y | DLSZ_MOVE_X)
DLGRESIZE_CONTROL(IDC_PROMPT_MESSAGE, DLSZ_SIZE_Y | DLSZ_SIZE_X)
+ DLGRESIZE_CONTROL(IDC_PROMPT_LINK, DLSZ_CENTER_Y | DLSZ_MOVE_X)
END_DLGRESIZE_MAP()
virtual void OnFinalMessage(HWND);
private:
+ // Call CreateInstance() to get an initialized ReadyPromptWindow.
+ ReadyPromptWindow(InfobarContent::Frame* frame,
+ ReadyModeState* ready_mode_state,
+ UrlLauncher* url_launcher);
+
+ // The ReadyPromptWindow manages its own destruction.
+ virtual ~ReadyPromptWindow();
+
// Event handlers.
void OnDestroy();
BOOL OnInitDialog(CWindow wndFocus, LPARAM lInitParam);
@@ -72,6 +88,7 @@ class ReadyPromptWindow
WORD wID,
HWND hWndCtl,
BOOL& bHandled);
+ LRESULT OnLearnMore(WORD wParam, LPNMHDR lParam, BOOL& bHandled); // NOLINT
LRESULT OnNo(WORD wNotifyCode,
WORD wID,
HWND hWndCtl,
@@ -79,6 +96,8 @@ class ReadyPromptWindow
InfobarContent::Frame* frame_; // Not owned by this instance
scoped_ptr<ReadyModeState> ready_mode_state_;
+ scoped_ptr<WTL::CHyperLink> link_;
+ scoped_ptr<UrlLauncher> url_launcher_;
base::WeakPtrFactory<ReadyPromptWindow> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(ReadyPromptWindow);
diff --git a/chrome_frame/ready_mode/internal/url_launcher.h b/chrome_frame/ready_mode/internal/url_launcher.h
new file mode 100644
index 0000000..ea3711c
--- /dev/null
+++ b/chrome_frame/ready_mode/internal/url_launcher.h
@@ -0,0 +1,20 @@
+// Copyright (c) 2010 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.
+
+#ifndef CHROME_FRAME_READY_MODE_INTERNAL_URL_LAUNCHER_H_
+#define CHROME_FRAME_READY_MODE_INTERNAL_URL_LAUNCHER_H_
+#pragma once
+
+// Implements the launching of a new browser window/tab. The
+// ReadyPromptContent invokes this, in response to user action, to display
+// documentation about Ready Mode.
+class UrlLauncher {
+ public:
+ virtual ~UrlLauncher() {}
+
+ // Displays the specified URL in a new window or tab.
+ virtual void LaunchUrl(const std::wstring& url) = 0;
+}; // class UrlHelper
+
+#endif // CHROME_FRAME_READY_MODE_INTERNAL_URL_LAUNCHER_H_
diff --git a/chrome_frame/ready_mode/ready_mode.cc b/chrome_frame/ready_mode/ready_mode.cc
index 82b5d23..51df76f 100644
--- a/chrome_frame/ready_mode/ready_mode.cc
+++ b/chrome_frame/ready_mode/ready_mode.cc
@@ -21,6 +21,7 @@
#include "chrome_frame/ready_mode/internal/ready_mode_web_browser_adapter.h"
#include "chrome_frame/ready_mode/internal/ready_prompt_content.h"
#include "chrome_frame/ready_mode/internal/registry_ready_mode_state.h"
+#include "chrome_frame/ready_mode/internal/url_launcher.h"
#include "chrome_frame/utils.h"
namespace {
@@ -90,6 +91,33 @@ class BrowserObserver : public ReadyModeWebBrowserAdapter::Observer {
DISALLOW_COPY_AND_ASSIGN(BrowserObserver);
}; // class BrowserObserver
+// Implements launching of a URL in an instance of IWebBrowser2.
+class UrlLauncherImpl : public UrlLauncher {
+ public:
+ explicit UrlLauncherImpl(IWebBrowser2* web_browser);
+
+ // UrlLauncher implementation
+ void LaunchUrl(const std::wstring& url);
+
+ private:
+ base::win::ScopedComPtr<IWebBrowser2> web_browser_;
+}; // class UrlLaucherImpl
+
+UrlLauncherImpl::UrlLauncherImpl(IWebBrowser2* web_browser) {
+ DCHECK(web_browser);
+ web_browser_ = web_browser;
+}
+
+void UrlLauncherImpl::LaunchUrl(const std::wstring& url) {
+ VARIANT flags = { VT_I4 };
+ V_I4(&flags) = navOpenInNewWindow;
+ base::win::ScopedBstr location(url.c_str());
+
+ HRESULT hr = web_browser_->Navigate(location, &flags, NULL, NULL, NULL);
+ DLOG_IF(ERROR, FAILED(hr)) << "Failed to invoke Navigate on IWebBrowser2. "
+ << "Error: " << hr;
+}
+
StateObserver::StateObserver(
const base::WeakPtr<BrowserObserver>& ready_mode_ui)
: ready_mode_ui_(ready_mode_ui) {
@@ -200,9 +228,12 @@ void BrowserObserver::ShowPrompt() {
base::TimeDelta::FromMinutes(kTemporaryDeclineDurationMinutes),
ready_mode_state_observer.release()));
+ // Owned by infobar_content
+ scoped_ptr<UrlLauncher> url_launcher(new UrlLauncherImpl(web_browser_));
+
// Owned by infobar_manager
- scoped_ptr<InfobarContent> infobar_content(
- new ReadyPromptContent(ready_mode_state.release()));
+ scoped_ptr<InfobarContent> infobar_content(new ReadyPromptContent(
+ ready_mode_state.release(), url_launcher.release()));
infobar_manager->Show(infobar_content.release(), TOP_INFOBAR);
}
diff --git a/chrome_frame/test/ready_mode_unittest.cc b/chrome_frame/test/ready_mode_unittest.cc
index a462ff2..e404269b 100644
--- a/chrome_frame/test/ready_mode_unittest.cc
+++ b/chrome_frame/test/ready_mode_unittest.cc
@@ -18,6 +18,7 @@
#include "chrome_frame/ready_mode/internal/ready_prompt_content.h"
#include "chrome_frame/ready_mode/internal/ready_prompt_window.h"
#include "chrome_frame/ready_mode/internal/registry_ready_mode_state.h"
+#include "chrome_frame/ready_mode/internal/url_launcher.h"
#include "chrome_frame/simple_resource_loader.h"
#include "chrome_frame/test/chrome_frame_test_utils.h"
@@ -97,6 +98,12 @@ class MockReadyModeState : public ReadyModeState {
MOCK_METHOD0(AcceptChromeFrame, void(void));
}; // class MockReadyModeState
+class MockUrlLauncher : public UrlLauncher {
+ public:
+ // UrlLauncher implementation
+ MOCK_METHOD1(LaunchUrl, void(const std::wstring& url));
+}; // class MockUrlLauncher
+
} // namespace
class ReadyPromptTest : public testing::Test {
@@ -126,8 +133,10 @@ class ReadyPromptWindowTest : public ReadyPromptTest {
// owned by ReadyPromptWindow
state_ = new MockReadyModeState();
- ready_prompt_window_ = (new ReadyPromptWindow())->Initialize(&frame_,
- state_);
+ url_launcher_ = new MockUrlLauncher();
+
+ ready_prompt_window_ = ReadyPromptWindow::CreateInstance(
+ &frame_, state_, url_launcher_);
ASSERT_TRUE(ready_prompt_window_ != NULL);
RECT position = {0, 0, 800, 39};
@@ -137,6 +146,7 @@ class ReadyPromptWindowTest : public ReadyPromptTest {
protected:
MockReadyModeState* state_;
+ MockUrlLauncher* url_launcher_;
base::WeakPtr<ReadyPromptWindow> ready_prompt_window_;
}; // class ReadyPromptWindowTest
@@ -212,7 +222,10 @@ class ReadyPromptWindowButtonTest : public ReadyPromptWindowTest {
TEST_F(ReadyPromptTest, ReadyPromptContentTest) {
// owned by ReadyPromptContent
MockReadyModeState* state = new MockReadyModeState();
- scoped_ptr<ReadyPromptContent> content_(new ReadyPromptContent(state));
+ MockUrlLauncher* url_launcher = new MockUrlLauncher();
+
+ scoped_ptr<ReadyPromptContent> content_(new ReadyPromptContent(state,
+ url_launcher));
content_->InstallInFrame(&frame_);
@@ -255,21 +268,15 @@ TEST_F(ReadyPromptWindowTest, Destroy) {
ready_prompt_window_->DestroyWindow();
}
-TEST_F(ReadyPromptWindowButtonTest, ClickYes) {
+TEST_F(ReadyPromptWindowButtonTest, ClickEnable) {
EXPECT_CALL(*state_, AcceptChromeFrame());
- ASSERT_TRUE(ClickOnCaption(L"&Yes"));
- RunUntilCloseInfobar();
-}
-
-TEST_F(ReadyPromptWindowButtonTest, ClickRemindMeLater) {
- EXPECT_CALL(*state_, TemporarilyDeclineChromeFrame());
- ASSERT_TRUE(ClickOnCaption(L"Remind me &Later"));
+ ASSERT_TRUE(ClickOnCaption(L"Enable"));
RunUntilCloseInfobar();
}
-TEST_F(ReadyPromptWindowButtonTest, ClickNo) {
+TEST_F(ReadyPromptWindowButtonTest, ClickIgnore) {
EXPECT_CALL(*state_, PermanentlyDeclineChromeFrame());
- ASSERT_TRUE(ClickOnCaption(L"&No"));
+ ASSERT_TRUE(ClickOnCaption(L"Ignore"));
RunUntilCloseInfobar();
}