• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
3// found in the LICENSE file.
4
5#include "base/memory/scoped_nsobject.h"
6#include "base/string_util.h"
7#include "base/string_number_conversions.h"
8#include "base/sys_string_conversions.h"
9#include "base/utf_string_conversions.h"
10#include "chrome/browser/page_info_model.h"
11#import "chrome/browser/ui/cocoa/hyperlink_button_cell.h"
12#import "chrome/browser/ui/cocoa/page_info_bubble_controller.h"
13#include "chrome/browser/ui/cocoa/browser_test_helper.h"
14#import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
15#include "grit/generated_resources.h"
16#include "ui/base/l10n/l10n_util.h"
17
18namespace {
19
20class FakeModel : public PageInfoModel {
21 public:
22  FakeModel() : PageInfoModel() {}
23
24  void AddSection(SectionStateIcon icon_id,
25                  const string16& headline,
26                  const string16& description,
27                  SectionInfoType type) {
28    sections_.push_back(SectionInfo(
29        icon_id, headline, description, type));
30  }
31};
32
33class FakeBridge : public PageInfoModel::PageInfoModelObserver {
34 public:
35  void ModelChanged() {}
36};
37
38class PageInfoBubbleControllerTest : public CocoaTest {
39 public:
40  PageInfoBubbleControllerTest() {
41    controller_ = nil;
42    model_ = new FakeModel();
43  }
44
45  virtual void TearDown() {
46    [controller_ close];
47    CocoaTest::TearDown();
48  }
49
50  void CreateBubble() {
51    // The controller cleans up after itself when the window closes.
52    controller_ =
53        [[PageInfoBubbleController alloc] initWithPageInfoModel:model_
54                                                  modelObserver:NULL
55                                                   parentWindow:test_window()];
56    window_ = [controller_ window];
57    [controller_ showWindow:nil];
58  }
59
60  // Checks the controller's window for the requisite subviews in the given
61  // numbers.
62  void CheckWindow(int text_count,
63                   int image_count,
64                   int spacer_count,
65                   int button_count) {
66    // All windows have the help center link and a spacer for it.
67    int link_count = 1;
68    ++spacer_count;
69
70    // The window's only immediate child is an invisible view that has a flipped
71    // coordinate origin. It is into this that all views get placed.
72    NSArray* windowSubviews = [[window_ contentView] subviews];
73    EXPECT_EQ(1U, [windowSubviews count]);
74    NSArray* subviews = [[windowSubviews lastObject] subviews];
75
76    for (NSView* view in subviews) {
77      if ([view isKindOfClass:[NSTextField class]]) {
78        --text_count;
79      } else if ([view isKindOfClass:[NSImageView class]]) {
80        --image_count;
81      } else if ([view isKindOfClass:[NSBox class]]) {
82        --spacer_count;
83      } else if ([view isKindOfClass:[NSButton class]]) {
84        NSButton* button = static_cast<NSButton*>(view);
85        // Every window should have a single link button to the help page.
86        if ([[button cell] isKindOfClass:[HyperlinkButtonCell class]]) {
87          --link_count;
88          CheckButton(button, @selector(showHelpPage:));
89        } else {
90          --button_count;
91          CheckButton(button, @selector(showCertWindow:));
92        }
93      } else {
94        ADD_FAILURE() << "Unknown subview: " << [[view description] UTF8String];
95      }
96    }
97    EXPECT_EQ(0, text_count);
98    EXPECT_EQ(0, image_count);
99    EXPECT_EQ(0, spacer_count);
100    EXPECT_EQ(0, button_count);
101    EXPECT_EQ(0, link_count);
102    EXPECT_EQ([window_ delegate], controller_);
103  }
104
105  // Checks that a button is hooked up correctly.
106  void CheckButton(NSButton* button, SEL action) {
107    EXPECT_EQ(action, [button action]);
108    EXPECT_EQ(controller_, [button target]);
109    EXPECT_TRUE([button stringValue]);
110  }
111
112  BrowserTestHelper helper_;
113
114  PageInfoBubbleController* controller_;  // Weak, owns self.
115  FakeModel* model_;  // Weak, owned by controller.
116  NSWindow* window_;  // Weak, owned by controller.
117};
118
119
120TEST_F(PageInfoBubbleControllerTest, NoHistoryNoSecurity) {
121  model_->AddSection(PageInfoModel::ICON_STATE_ERROR,
122      string16(),
123      l10n_util::GetStringUTF16(IDS_PAGE_INFO_SECURITY_TAB_UNKNOWN_PARTY),
124      PageInfoModel::SECTION_INFO_IDENTITY);
125  model_->AddSection(PageInfoModel::ICON_STATE_ERROR,
126      string16(),
127      l10n_util::GetStringFUTF16(
128          IDS_PAGE_INFO_SECURITY_TAB_NOT_ENCRYPTED_CONNECTION_TEXT,
129          ASCIIToUTF16("google.com")),
130      PageInfoModel::SECTION_INFO_CONNECTION);
131
132  CreateBubble();
133  CheckWindow(/*text=*/2, /*image=*/2, /*spacer=*/1, /*button=*/0);
134}
135
136
137TEST_F(PageInfoBubbleControllerTest, HistoryNoSecurity) {
138  model_->AddSection(PageInfoModel::ICON_STATE_ERROR,
139      string16(),
140      l10n_util::GetStringUTF16(IDS_PAGE_INFO_SECURITY_TAB_UNKNOWN_PARTY),
141      PageInfoModel::SECTION_INFO_IDENTITY);
142  model_->AddSection(PageInfoModel::ICON_STATE_ERROR,
143      string16(),
144      l10n_util::GetStringFUTF16(
145          IDS_PAGE_INFO_SECURITY_TAB_NOT_ENCRYPTED_CONNECTION_TEXT,
146          ASCIIToUTF16("google.com")),
147      PageInfoModel::SECTION_INFO_CONNECTION);
148
149  // In practice, the history information comes later because it's queried
150  // asynchronously, so replicate the double-build here.
151  CreateBubble();
152
153  model_->AddSection(PageInfoModel::ICON_STATE_ERROR,
154      l10n_util::GetStringUTF16(IDS_PAGE_INFO_SITE_INFO_TITLE),
155      l10n_util::GetStringUTF16(
156          IDS_PAGE_INFO_SECURITY_TAB_FIRST_VISITED_TODAY),
157      PageInfoModel::SECTION_INFO_FIRST_VISIT);
158
159  [controller_ performLayout];
160
161  CheckWindow(/*text=*/4, /*image=*/3, /*spacer=*/2, /*button=*/0);
162}
163
164
165TEST_F(PageInfoBubbleControllerTest, NoHistoryMixedSecurity) {
166  model_->AddSection(PageInfoModel::ICON_STATE_OK,
167      string16(),
168      l10n_util::GetStringFUTF16(
169          IDS_PAGE_INFO_SECURITY_TAB_SECURE_IDENTITY,
170          ASCIIToUTF16("Goat Security Systems")),
171      PageInfoModel::SECTION_INFO_IDENTITY);
172
173  // This string is super long and the text should overflow the default clip
174  // region (kImageSize).
175  string16 description = l10n_util::GetStringFUTF16(
176      IDS_PAGE_INFO_SECURITY_TAB_ENCRYPTED_SENTENCE_LINK,
177      l10n_util::GetStringFUTF16(
178          IDS_PAGE_INFO_SECURITY_TAB_ENCRYPTED_CONNECTION_TEXT,
179          ASCIIToUTF16("chrome.google.com"),
180          base::IntToString16(1024)),
181      l10n_util::GetStringUTF16(
182          IDS_PAGE_INFO_SECURITY_TAB_ENCRYPTED_INSECURE_CONTENT_WARNING));
183
184  model_->AddSection(PageInfoModel::ICON_STATE_OK,
185      string16(),
186      description,
187      PageInfoModel::SECTION_INFO_CONNECTION);
188
189  CreateBubble();
190  [controller_ setCertID:1];
191  [controller_ performLayout];
192
193  CheckWindow(/*text=*/2, /*image=*/2, /*spacer=*/1, /*button=*/1);
194
195  // Look for the over-sized box.
196  NSString* targetDesc = base::SysUTF16ToNSString(description);
197  NSArray* subviews = [[window_ contentView] subviews];
198  for (NSView* subview in subviews) {
199    if ([subview isKindOfClass:[NSTextField class]]) {
200      NSTextField* desc = static_cast<NSTextField*>(subview);
201      if ([[desc stringValue] isEqualToString:targetDesc]) {
202        // Typical box frame is ~55px, make sure this is extra large.
203        EXPECT_LT(75, NSHeight([desc frame]));
204      }
205    }
206  }
207}
208
209}  // namespace
210