Add ManagePasswordsDecoration and unit tests.

This CL also moves the common decoration grit ID computation
logic up into ManagePasswordsIcon.

BUG=328847

Review URL: https://codereview.chromium.org/419263002

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@287562 0039d316-1c4b-4281-b951-d872f2087c98
parent 0dbf1202
......@@ -28,6 +28,7 @@ class GeneratedCreditCardDecoration;
class KeywordHintDecoration;
class LocationBarDecoration;
class LocationIconDecoration;
class ManagePasswordsDecoration;
class MicSearchDecoration;
class OriginChipDecoration;
class PageActionDecoration;
......@@ -64,7 +65,7 @@ class LocationBarViewMac : public LocationBar,
virtual void FocusLocation(bool select_all) OVERRIDE;
virtual void FocusSearch() OVERRIDE;
virtual void UpdateContentSettingsIcons() OVERRIDE;
virtual void UpdateManagePasswordsIconAndBubble() OVERRIDE {};
virtual void UpdateManagePasswordsIconAndBubble() OVERRIDE;
virtual void UpdatePageActions() OVERRIDE;
virtual void InvalidatePageActions() OVERRIDE;
virtual void UpdateOpenPDFInReaderPrompt() OVERRIDE;
......@@ -266,6 +267,9 @@ class LocationBarViewMac : public LocationBar,
// The left-hand-side origin chip.
scoped_ptr<OriginChipDecoration> origin_chip_decoration_;
// The right-hand-side button to manage passwords associated with a page.
scoped_ptr<ManagePasswordsDecoration> manage_passwords_decoration_;
Browser* browser_;
// Used to register for notifications received by NotificationObserver.
......
......@@ -42,6 +42,7 @@
#import "chrome/browser/ui/cocoa/location_bar/generated_credit_card_decoration.h"
#import "chrome/browser/ui/cocoa/location_bar/keyword_hint_decoration.h"
#import "chrome/browser/ui/cocoa/location_bar/location_icon_decoration.h"
#import "chrome/browser/ui/cocoa/location_bar/manage_passwords_decoration.h"
#import "chrome/browser/ui/cocoa/location_bar/mic_search_decoration.h"
#import "chrome/browser/ui/cocoa/location_bar/origin_chip_decoration.h"
#import "chrome/browser/ui/cocoa/location_bar/page_action_decoration.h"
......@@ -54,6 +55,7 @@
#include "chrome/browser/ui/content_settings/content_setting_bubble_model.h"
#include "chrome/browser/ui/content_settings/content_setting_image_model.h"
#import "chrome/browser/ui/omnibox/omnibox_popup_model.h"
#include "chrome/browser/ui/passwords/manage_passwords_ui_controller.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/browser/ui/toolbar/toolbar_model.h"
#include "chrome/browser/ui/zoom/zoom_controller.h"
......@@ -132,9 +134,10 @@ LocationBarViewMac::LocationBarViewMac(AutocompleteTextField* field,
generated_credit_card_decoration_(
new GeneratedCreditCardDecoration(this)),
search_button_decoration_(new SearchButtonDecoration(this)),
manage_passwords_decoration_(
new ManagePasswordsDecoration(command_updater)),
browser_(browser),
weak_ptr_factory_(this) {
for (size_t i = 0; i < CONTENT_SETTINGS_NUM_TYPES; ++i) {
DCHECK_EQ(i, content_setting_decorations_.size());
ContentSettingsType type = static_cast<ContentSettingsType>(i);
......@@ -215,6 +218,14 @@ void LocationBarViewMac::UpdateContentSettingsIcons() {
OnDecorationsChanged();
}
void LocationBarViewMac::UpdateManagePasswordsIconAndBubble() {
WebContents* web_contents = GetWebContents();
if (!web_contents)
return;
ManagePasswordsUIController::FromWebContents(web_contents)
->UpdateIconAndBubbleState(manage_passwords_decoration_->icon());
}
void LocationBarViewMac::UpdatePageActions() {
size_t count_before = page_action_decorations_.size();
RefreshPageActionDecorations();
......@@ -407,6 +418,7 @@ void LocationBarViewMac::Layout() {
[cell addRightDecoration:translate_decoration_.get()];
[cell addRightDecoration:zoom_decoration_.get()];
[cell addRightDecoration:generated_credit_card_decoration_.get()];
[cell addRightDecoration:manage_passwords_decoration_.get()];
// Note that display order is right to left.
for (size_t i = 0; i < page_action_decorations_.size(); ++i) {
......
// Copyright 2014 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_BROWSER_UI_COCOA_LOCATION_BAR_MANAGE_PASSWORDS_DECORATION_H_
#define CHROME_BROWSER_UI_COCOA_LOCATION_BAR_MANAGE_PASSWORDS_DECORATION_H_
#import <Cocoa/Cocoa.h>
#include "base/compiler_specific.h"
#include "base/memory/scoped_ptr.h"
#include "chrome/browser/ui/cocoa/location_bar/image_decoration.h"
#include "chrome/browser/ui/passwords/manage_passwords_icon.h"
class CommandUpdater;
class ManagePasswordsDecoration;
// Cocoa implementation of ManagePasswordsIcon that delegates to
// ManagePasswordsDecoration.
class ManagePasswordsIconCocoa : public ManagePasswordsIcon {
public:
ManagePasswordsIconCocoa(ManagePasswordsDecoration* decoration);
virtual ~ManagePasswordsIconCocoa();
virtual void UpdateVisibleUI() OVERRIDE;
int icon_id() { return icon_id_; }
int tooltip_text_id() { return tooltip_text_id_; }
private:
ManagePasswordsDecoration* decoration_; // weak, owns us
};
// Manage passwords icon on the right side of the field. This appears when
// password management is available on the current page.
class ManagePasswordsDecoration : public ImageDecoration {
public:
explicit ManagePasswordsDecoration(CommandUpdater* command_updater);
virtual ~ManagePasswordsDecoration();
// Implement |LocationBarDecoration|
virtual bool AcceptsMousePress() OVERRIDE;
virtual bool OnMousePressed(NSRect frame, NSPoint location) OVERRIDE;
virtual NSString* GetToolTip() OVERRIDE;
virtual NSPoint GetBubblePointInFrame(NSRect frame) OVERRIDE;
// Updates the decoration according to icon state changes.
void UpdateVisibleUI();
// Accessor for the platform-independent interface.
ManagePasswordsIconCocoa* icon() { return icon_.get(); }
private:
// Shows the manage passwords bubble.
CommandUpdater* command_updater_; // Weak, owned by Browser.
// The platform-independent interface.
scoped_ptr<ManagePasswordsIconCocoa> icon_;
DISALLOW_COPY_AND_ASSIGN(ManagePasswordsDecoration);
};
#endif // CHROME_BROWSER_UI_COCOA_LOCATION_BAR_MANAGE_PASSWORDS_DECORATION_H_
// Copyright 2014 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.
#import "chrome/browser/ui/cocoa/location_bar/manage_passwords_decoration.h"
#include "chrome/app/chrome_command_ids.h"
#include "chrome/browser/command_updater.h"
#include "chrome/browser/ui/cocoa/omnibox/omnibox_view_mac.h"
#include "ui/base/l10n/l10n_util_mac.h"
// ManagePasswordsIconCocoa
ManagePasswordsIconCocoa::ManagePasswordsIconCocoa(
ManagePasswordsDecoration* decoration)
: decoration_(decoration) {
}
ManagePasswordsIconCocoa::~ManagePasswordsIconCocoa() {
}
void ManagePasswordsIconCocoa::UpdateVisibleUI() {
decoration_->UpdateVisibleUI();
}
// ManagePasswordsDecoration
ManagePasswordsDecoration::ManagePasswordsDecoration(
CommandUpdater* command_updater)
: command_updater_(command_updater),
icon_(new ManagePasswordsIconCocoa(this)) {
UpdateVisibleUI();
}
ManagePasswordsDecoration::~ManagePasswordsDecoration() {}
NSPoint ManagePasswordsDecoration::GetBubblePointInFrame(NSRect frame) {
const NSRect draw_frame = GetDrawRectInFrame(frame);
return NSMakePoint(NSMidX(draw_frame), NSMaxY(draw_frame));
}
bool ManagePasswordsDecoration::AcceptsMousePress() {
return true;
}
bool ManagePasswordsDecoration::OnMousePressed(NSRect frame, NSPoint location) {
command_updater_->ExecuteCommand(IDC_MANAGE_PASSWORDS_FOR_PAGE);
return true;
}
NSString* ManagePasswordsDecoration::GetToolTip() {
return icon_->tooltip_text_id()
? l10n_util::GetNSStringWithFixup(icon_->tooltip_text_id())
: nil;
}
void ManagePasswordsDecoration::UpdateVisibleUI() {
if (icon_->state() == password_manager::ui::INACTIVE_STATE) {
SetVisible(false);
SetImage(nil);
// TODO(dconnelly): Hide the bubble once it is implemented.
return;
}
SetVisible(true);
SetImage(OmniboxViewMac::ImageForResource(icon_->icon_id()));
}
// Copyright 2014 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.
#import <Cocoa/Cocoa.h>
#include "base/strings/utf_string_conversions.h"
#include "chrome/app/chrome_command_ids.h"
#include "chrome/browser/command_updater.h"
#include "chrome/browser/command_updater_delegate.h"
#include "chrome/browser/ui/cocoa/cocoa_test_helper.h"
#include "chrome/browser/ui/cocoa/location_bar/manage_passwords_decoration.h"
#include "chrome/browser/ui/cocoa/omnibox/omnibox_view_mac.h"
#include "components/password_manager/core/common/password_manager_ui.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/gtest_mac.h"
#include "ui/base/l10n/l10n_util_mac.h"
#include "ui/gfx/image/image.h"
namespace {
// A simple CommandUpdaterDelegate for testing whether the correct command
// was sent.
class TestCommandUpdaterDelegate : public CommandUpdaterDelegate {
public:
TestCommandUpdaterDelegate() : id_(0) {}
virtual void ExecuteCommandWithDisposition(
int id,
WindowOpenDisposition disposition) OVERRIDE {
id_ = id;
}
int id() { return id_; }
private:
int id_;
};
bool ImagesEqual(NSImage* left, NSImage* right) {
if (!left || !right)
return left == right;
gfx::Image leftImage([left copy]);
gfx::Image rightImage([right copy]);
return leftImage.As1xPNGBytes()->Equals(rightImage.As1xPNGBytes());
}
} // namespace
// Tests isolated functionality of the ManagedPasswordsDecoration.
class ManagePasswordsDecorationTest : public CocoaTest {
public:
ManagePasswordsDecorationTest()
: commandUpdater_(&commandDelegate_), decoration_(&commandUpdater_) {
commandUpdater_.UpdateCommandEnabled(IDC_MANAGE_PASSWORDS_FOR_PAGE, true);
}
protected:
TestCommandUpdaterDelegate* commandDelegate() { return &commandDelegate_; }
ManagePasswordsDecoration* decoration() { return &decoration_; }
private:
TestCommandUpdaterDelegate commandDelegate_;
CommandUpdater commandUpdater_;
ManagePasswordsDecoration decoration_;
};
TEST_F(ManagePasswordsDecorationTest, ExecutesManagePasswordsCommandOnClick) {
EXPECT_TRUE(decoration()->AcceptsMousePress());
EXPECT_TRUE(decoration()->OnMousePressed(NSRect(), NSPoint()));
EXPECT_EQ(IDC_MANAGE_PASSWORDS_FOR_PAGE, commandDelegate()->id());
}
// Parameter object for ManagePasswordsDecorationStateTests.
struct ManagePasswordsTestCase {
// Inputs
password_manager::ui::State state;
bool active;
// Outputs
bool visible;
int image;
int toolTip;
};
// Tests that setting different combinations of password_manager::ui::State
// and the Active property of the decoration result in the correct visibility,
// decoration icon, and tooltip.
class ManagePasswordsDecorationStateTest
: public ManagePasswordsDecorationTest,
public ::testing::WithParamInterface<ManagePasswordsTestCase> {};
TEST_P(ManagePasswordsDecorationStateTest, TestState) {
decoration()->icon()->SetState(GetParam().state);
decoration()->icon()->SetActive(GetParam().active);
EXPECT_EQ(GetParam().visible, decoration()->IsVisible());
EXPECT_TRUE(ImagesEqual(
GetParam().image ? OmniboxViewMac::ImageForResource(GetParam().image)
: nil,
decoration()->GetImage()));
EXPECT_NSEQ(GetParam().toolTip
? l10n_util::GetNSStringWithFixup(GetParam().toolTip)
: nil,
decoration()->GetToolTip());
}
ManagePasswordsTestCase managerInactiveOnPageAndEnabledTests[] = {
{.state = password_manager::ui::INACTIVE_STATE,
.active = true,
.visible = false,
.image = 0,
.toolTip = 0},
{.state = password_manager::ui::INACTIVE_STATE,
.active = false,
.visible = false,
.image = 0,
.toolTip = 0}};
INSTANTIATE_TEST_CASE_P(
ManagerInactiveOnPage,
ManagePasswordsDecorationStateTest,
::testing::ValuesIn(managerInactiveOnPageAndEnabledTests));
ManagePasswordsTestCase managerActiveOnPageAndEnabledTests[] = {
{.state = password_manager::ui::MANAGE_STATE,
.active = true,
.visible = true,
.image = IDR_SAVE_PASSWORD_ACTIVE,
.toolTip = IDS_PASSWORD_MANAGER_TOOLTIP_MANAGE},
{.state = password_manager::ui::MANAGE_STATE,
.active = false,
.visible = true,
.image = IDR_SAVE_PASSWORD_INACTIVE,
.toolTip = IDS_PASSWORD_MANAGER_TOOLTIP_MANAGE}};
INSTANTIATE_TEST_CASE_P(
ManagerActiveOnPageAndEnabled,
ManagePasswordsDecorationStateTest,
::testing::ValuesIn(managerActiveOnPageAndEnabledTests));
ManagePasswordsTestCase managerActiveOnPageAndBlacklistedTests[] = {
{.state = password_manager::ui::BLACKLIST_STATE,
.active = true,
.visible = true,
.image = IDR_SAVE_PASSWORD_DISABLED_ACTIVE,
.toolTip = IDS_PASSWORD_MANAGER_TOOLTIP_MANAGE},
{.state = password_manager::ui::BLACKLIST_STATE,
.active = false,
.visible = true,
.image = IDR_SAVE_PASSWORD_DISABLED_INACTIVE,
.toolTip = IDS_PASSWORD_MANAGER_TOOLTIP_MANAGE}};
INSTANTIATE_TEST_CASE_P(
ManagerActiveOnPageAndBlacklisted,
ManagePasswordsDecorationStateTest,
::testing::ValuesIn(managerActiveOnPageAndBlacklistedTests));
ManagePasswordsTestCase managerActiveOnPageAndPendingTests[] = {
{.state = password_manager::ui::PENDING_PASSWORD_AND_BUBBLE_STATE,
.active = true,
.visible = true,
.image = IDR_SAVE_PASSWORD_ACTIVE,
.toolTip = IDS_PASSWORD_MANAGER_TOOLTIP_SAVE},
{.state = password_manager::ui::PENDING_PASSWORD_AND_BUBBLE_STATE,
.active = false,
.visible = true,
.image = IDR_SAVE_PASSWORD_INACTIVE,
.toolTip = IDS_PASSWORD_MANAGER_TOOLTIP_SAVE},
{.state = password_manager::ui::PENDING_PASSWORD_STATE,
.active = true,
.visible = true,
.image = IDR_SAVE_PASSWORD_ACTIVE,
.toolTip = IDS_PASSWORD_MANAGER_TOOLTIP_SAVE},
{.state = password_manager::ui::PENDING_PASSWORD_STATE,
.active = false,
.visible = true,
.image = IDR_SAVE_PASSWORD_INACTIVE,
.toolTip = IDS_PASSWORD_MANAGER_TOOLTIP_SAVE}};
INSTANTIATE_TEST_CASE_P(
ManagerActiveOnPageAndPending,
ManagePasswordsDecorationStateTest,
::testing::ValuesIn(managerActiveOnPageAndPendingTests));
......@@ -4,8 +4,13 @@
#include "chrome/browser/ui/passwords/manage_passwords_icon.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
ManagePasswordsIcon::ManagePasswordsIcon()
: state_(password_manager::ui::INACTIVE_STATE),
: icon_id_(0),
tooltip_text_id_(0),
state_(password_manager::ui::INACTIVE_STATE),
active_(false) {
}
......@@ -16,6 +21,7 @@ void ManagePasswordsIcon::SetActive(bool active) {
if (active_ == active)
return;
active_ = active;
UpdateIDs();
UpdateVisibleUI();
}
......@@ -23,5 +29,28 @@ void ManagePasswordsIcon::SetState(password_manager::ui::State state) {
if (state_ == state)
return;
state_ = state;
UpdateIDs();
UpdateVisibleUI();
}
void ManagePasswordsIcon::UpdateIDs() {
// If the icon is inactive: clear out its image and tooltip and exit early.
if (state() == password_manager::ui::INACTIVE_STATE) {
icon_id_ = 0;
tooltip_text_id_ = 0;
return;
}
// Otherwise, start with the correct values for MANAGE_STATE, and adjust
// things accordingly if we're either in BLACKLIST_STATE or PENDING_STATE.
// TODO(dconnelly): Figure out how to share the resources with Android.
#if !defined(OS_ANDROID)
icon_id_ = active() ? IDR_SAVE_PASSWORD_ACTIVE : IDR_SAVE_PASSWORD_INACTIVE;
tooltip_text_id_ = IDS_PASSWORD_MANAGER_TOOLTIP_MANAGE;
if (state() == password_manager::ui::BLACKLIST_STATE)
icon_id_ = active() ? IDR_SAVE_PASSWORD_DISABLED_ACTIVE
: IDR_SAVE_PASSWORD_DISABLED_INACTIVE;
else if (password_manager::ui::IsPendingState(state()))
tooltip_text_id_ = IDS_PASSWORD_MANAGER_TOOLTIP_SAVE;
#endif
}
......@@ -21,6 +21,10 @@ class ManagePasswordsIcon {
bool active() const { return active_; }
protected:
// The ID of the icon and text resources that are currently displayed.
int icon_id_;
int tooltip_text_id_;
ManagePasswordsIcon();
~ManagePasswordsIcon();
......@@ -29,6 +33,9 @@ class ManagePasswordsIcon {
virtual void UpdateVisibleUI() = 0;
private:
// Updates the resource IDs in response to state changes.
void UpdateIDs();
password_manager::ui::State state_;
bool active_;
......
......@@ -10,15 +10,11 @@
#include "chrome/browser/ui/view_ids.h"
#include "chrome/browser/ui/views/passwords/manage_passwords_bubble_view.h"
#include "components/password_manager/core/common/password_manager_ui.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
ManagePasswordsIconView::ManagePasswordsIconView(CommandUpdater* updater)
: BubbleIconView(updater, IDC_MANAGE_PASSWORDS_FOR_PAGE),
icon_id_(0),
tooltip_text_id_(0) {
: BubbleIconView(updater, IDC_MANAGE_PASSWORDS_FOR_PAGE) {
set_id(VIEW_ID_MANAGE_PASSWORDS_ICON_BUTTON);
SetAccessibilityFocusable(true);
UpdateVisibleUI();
......@@ -27,28 +23,13 @@ ManagePasswordsIconView::ManagePasswordsIconView(CommandUpdater* updater)
ManagePasswordsIconView::~ManagePasswordsIconView() {}
void ManagePasswordsIconView::UpdateVisibleUI() {
// If the icon is inactive: clear out it's image and tooltip, hide the icon,
// close any active bubble, and exit early.
if (state() == password_manager::ui::INACTIVE_STATE) {
icon_id_ = 0;
tooltip_text_id_ = 0;
SetVisible(false);
if (ManagePasswordsBubbleView::IsShowing())
ManagePasswordsBubbleView::CloseBubble();
return;
}
// Otherwise, start with the correct values for MANAGE_STATE, and adjust
// things accordingly if we're either in BLACKLIST_STATE or PENDING_STATE.
icon_id_ = active() ? IDR_SAVE_PASSWORD_ACTIVE : IDR_SAVE_PASSWORD_INACTIVE;
tooltip_text_id_ = IDS_PASSWORD_MANAGER_TOOLTIP_MANAGE;
if (state() == password_manager::ui::BLACKLIST_STATE)
icon_id_ = active() ? IDR_SAVE_PASSWORD_DISABLED_ACTIVE
: IDR_SAVE_PASSWORD_DISABLED_INACTIVE;
else if (password_manager::ui::IsPendingState(state()))
tooltip_text_id_ = IDS_PASSWORD_MANAGER_TOOLTIP_SAVE;
SetVisible(true);
SetImage(ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(icon_id_));
SetTooltipText(l10n_util::GetStringUTF16(tooltip_text_id_));
......
......@@ -36,9 +36,6 @@ class ManagePasswordsIconView : public ManagePasswordsIcon,
virtual void UpdateVisibleUI() OVERRIDE;
private:
// The ID of the icon and text resources that are currently displayed.
int icon_id_;
int tooltip_text_id_;
DISALLOW_COPY_AND_ASSIGN(ManagePasswordsIconView);
};
......
......@@ -557,6 +557,8 @@
'browser/ui/cocoa/location_bar/location_bar_view_mac.mm',
'browser/ui/cocoa/location_bar/location_icon_decoration.h',
'browser/ui/cocoa/location_bar/location_icon_decoration.mm',
'browser/ui/cocoa/location_bar/manage_passwords_decoration.h',
'browser/ui/cocoa/location_bar/manage_passwords_decoration.mm',
'browser/ui/cocoa/location_bar/mic_search_decoration.h',
'browser/ui/cocoa/location_bar/mic_search_decoration.mm',
'browser/ui/cocoa/location_bar/origin_chip_decoration.h',
......
......@@ -1608,6 +1608,7 @@
'browser/ui/cocoa/location_bar/ev_bubble_decoration_unittest.mm',
'browser/ui/cocoa/location_bar/image_decoration_unittest.mm',
'browser/ui/cocoa/location_bar/keyword_hint_decoration_unittest.mm',
'browser/ui/cocoa/location_bar/manage_passwords_decoration_unittest.mm',
'browser/ui/cocoa/location_bar/selected_keyword_decoration_unittest.mm',
'browser/ui/cocoa/media_picker/desktop_media_picker_controller_unittest.mm',
'browser/ui/cocoa/menu_button_unittest.mm',
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment