Upstream version 7.35.144.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / cocoa / website_settings_bubble_controller_unittest.mm
1 // Copyright (c) 2012 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 #import "chrome/browser/ui/cocoa/website_settings_bubble_controller.h"
6
7 #include "base/strings/utf_string_conversions.h"
8 #include "chrome/browser/ui/cocoa/cocoa_test_helper.h"
9 #include "testing/gtest_mac.h"
10
11 @interface WebsiteSettingsBubbleController (ExposedForTesting)
12 - (NSSegmentedControl*)segmentedControl;
13 - (NSTabView*)tabView;
14 - (NSView*)permissionsView;
15 - (NSView*)connectionTabContentView;
16 - (NSImageView*)identityStatusIcon;
17 - (NSTextField*)identityStatusDescriptionField;
18 - (NSImageView*)connectionStatusIcon;
19 - (NSTextField*)connectionStatusDescriptionField;
20 - (NSTextField*)firstVisitDescriptionField;
21 - (NSButton*)helpButton;
22 @end
23
24 @implementation WebsiteSettingsBubbleController (ExposedForTesting)
25 - (NSSegmentedControl*)segmentedControl {
26   return segmentedControl_.get();
27 }
28 - (NSTabView*)tabView {
29   return tabView_.get();
30 }
31 - (NSView*)permissionsView {
32   return permissionsView_;
33 }
34
35 - (NSView*)connectionTabContentView {
36   return connectionTabContentView_;
37 }
38
39 - (NSImageView*)identityStatusIcon {
40   return identityStatusIcon_;
41 }
42
43 - (NSTextField*)identityStatusDescriptionField {
44   return identityStatusDescriptionField_;
45 }
46
47 - (NSImageView*)connectionStatusIcon {
48   return connectionStatusIcon_;
49 }
50
51 - (NSTextField*)connectionStatusDescriptionField {
52   return connectionStatusDescriptionField_;
53 }
54
55 - (NSTextField*)firstVisitDescriptionField {
56   return firstVisitDescriptionField_;
57 }
58
59 - (NSButton*)helpButton {
60   return helpButton_;
61 }
62 @end
63
64 @interface WebsiteSettingsBubbleControllerForTesting
65     : WebsiteSettingsBubbleController {
66  @private
67   CGFloat defaultWindowWidth_;
68 }
69 @end
70
71 @implementation WebsiteSettingsBubbleControllerForTesting
72 - (void)setDefaultWindowWidth:(CGFloat)width {
73   defaultWindowWidth_ = width;
74 }
75 - (CGFloat)defaultWindowWidth {
76   // If |defaultWindowWidth_| is 0, use the superclass implementation.
77   return defaultWindowWidth_ ?
78       defaultWindowWidth_ : [super defaultWindowWidth];
79 }
80 @end
81
82 namespace {
83
84 // Indices of the menu items in the permission menu.
85 enum PermissionMenuIndices {
86   kMenuIndexContentSettingAllow = 0,
87   kMenuIndexContentSettingBlock,
88   kMenuIndexContentSettingDefault
89 };
90
91 const ContentSettingsType kTestPermissionTypes[] = {
92   // NOTE: FULLSCREEN does not support "Always block", so it must appear as
93   // one of the first three permissions.
94   CONTENT_SETTINGS_TYPE_FULLSCREEN,
95   CONTENT_SETTINGS_TYPE_IMAGES,
96   CONTENT_SETTINGS_TYPE_JAVASCRIPT,
97   CONTENT_SETTINGS_TYPE_PLUGINS,
98   CONTENT_SETTINGS_TYPE_POPUPS,
99   CONTENT_SETTINGS_TYPE_GEOLOCATION,
100   CONTENT_SETTINGS_TYPE_NOTIFICATIONS,
101   CONTENT_SETTINGS_TYPE_MOUSELOCK,
102   CONTENT_SETTINGS_TYPE_MEDIASTREAM,
103 };
104
105 const ContentSetting kTestSettings[] = {
106   CONTENT_SETTING_DEFAULT,
107   CONTENT_SETTING_DEFAULT,
108   CONTENT_SETTING_DEFAULT,
109   CONTENT_SETTING_ALLOW,
110   CONTENT_SETTING_BLOCK,
111   CONTENT_SETTING_ALLOW,
112   CONTENT_SETTING_BLOCK,
113   CONTENT_SETTING_ALLOW,
114   CONTENT_SETTING_BLOCK,
115 };
116
117 const ContentSetting kTestDefaultSettings[] = {
118   CONTENT_SETTING_ALLOW,
119   CONTENT_SETTING_BLOCK,
120   CONTENT_SETTING_ASK
121 };
122
123 const content_settings::SettingSource kTestSettingSources[] = {
124   content_settings::SETTING_SOURCE_USER,
125   content_settings::SETTING_SOURCE_USER,
126   content_settings::SETTING_SOURCE_USER,
127   content_settings::SETTING_SOURCE_USER,
128   content_settings::SETTING_SOURCE_USER,
129   content_settings::SETTING_SOURCE_POLICY,
130   content_settings::SETTING_SOURCE_POLICY,
131   content_settings::SETTING_SOURCE_EXTENSION,
132   content_settings::SETTING_SOURCE_EXTENSION,
133 };
134
135 class WebsiteSettingsBubbleControllerTest : public CocoaTest {
136  public:
137   WebsiteSettingsBubbleControllerTest() {
138     controller_ = nil;
139   }
140
141   virtual void TearDown() {
142     [controller_ close];
143     CocoaTest::TearDown();
144   }
145
146  protected:
147   WebsiteSettingsUIBridge* bridge_;  // Weak, owned by controller.
148
149   enum MatchType {
150     TEXT_EQUAL = 0,
151     TEXT_NOT_EQUAL
152   };
153
154   // Creates a new website settings bubble, with the given default width.
155   // If |default_width| is 0, the *default* default width will be used.
156   void CreateBubbleWithWidth(CGFloat default_width) {
157     bridge_ = new WebsiteSettingsUIBridge();
158
159     // The controller cleans up after itself when the window closes.
160     controller_ = [WebsiteSettingsBubbleControllerForTesting alloc];
161     [controller_ setDefaultWindowWidth:default_width];
162     [controller_ initWithParentWindow:test_window()
163                  websiteSettingsUIBridge:bridge_
164                  webContents:nil
165                  isInternalPage:NO];
166     window_ = [controller_ window];
167     [controller_ showWindow:nil];
168   }
169
170   void CreateBubble() {
171     CreateBubbleWithWidth(0.0);
172   }
173
174   // Return a pointer to the first NSTextField found that either matches, or
175   // doesn't match, the given text.
176   NSTextField* FindTextField(MatchType match_type, NSString* text) {
177     // The window's only immediate child is an invisible view that has a flipped
178     // coordinate origin. It is into this that all views get placed.
179     NSArray* window_subviews = [[window_ contentView] subviews];
180     EXPECT_EQ(1U, [window_subviews count]);
181     NSArray* subviews = [[window_subviews lastObject] subviews];
182
183     // Expect 4 views: the identity, identity status, the segmented control
184     // (which implements the tab strip), and the tab view.
185     EXPECT_EQ(4U, [subviews count]);
186
187     bool desired_result = match_type == TEXT_EQUAL;
188
189     for (NSView* view in subviews) {
190       if ([view isKindOfClass:[NSTextField class]]) {
191         NSTextField* text_field = static_cast<NSTextField*>(view);
192         if ([[text_field stringValue] isEqual:text] == desired_result)
193           return text_field;
194       }
195     }
196     return nil;
197   }
198
199   NSMutableArray* FindAllSubviewsOfClass(NSView* parent_view, Class a_class) {
200     NSMutableArray* views = [NSMutableArray array];
201     for (NSView* view in [parent_view subviews]) {
202       if ([view isKindOfClass:a_class])
203         [views addObject:view];
204     }
205     return views;
206   }
207
208   // Sets up the dialog with some test permission settings.
209   void SetTestPermissions() {
210     // Create a list of 5 different permissions, corresponding to all the
211     // possible settings:
212     // - [allow, block, ask] by default
213     // - [block, allow] * [by user, by policy, by extension]
214     PermissionInfoList list;
215     WebsiteSettingsUI::PermissionInfo info;
216     for (size_t i = 0; i < arraysize(kTestPermissionTypes); ++i) {
217       info.type = kTestPermissionTypes[i];
218       info.setting = kTestSettings[i];
219       if (info.setting == CONTENT_SETTING_DEFAULT)
220         info.default_setting = kTestDefaultSettings[i];
221       info.source = kTestSettingSources[i];
222       list.push_back(info);
223     }
224     bridge_->SetPermissionInfo(list);
225   }
226
227   WebsiteSettingsBubbleControllerForTesting* controller_;  // Weak, owns self.
228   NSWindow* window_;  // Weak, owned by controller.
229 };
230
231 TEST_F(WebsiteSettingsBubbleControllerTest, BasicIdentity) {
232   WebsiteSettingsUI::IdentityInfo info;
233   info.site_identity = std::string("nhl.com");
234   info.identity_status = WebsiteSettings::SITE_IDENTITY_STATUS_UNKNOWN;
235
236   CreateBubble();
237
238   // Test setting the site identity.
239   bridge_->SetIdentityInfo(const_cast<WebsiteSettingsUI::IdentityInfo&>(info));
240   NSTextField* identity_field = FindTextField(TEXT_EQUAL, @"nhl.com");
241   ASSERT_TRUE(identity_field != nil);
242
243   // Test changing the site identity, and ensure that the UI is updated.
244   info.site_identity = std::string("google.com");
245   bridge_->SetIdentityInfo(const_cast<WebsiteSettingsUI::IdentityInfo&>(info));
246   EXPECT_EQ(identity_field, FindTextField(TEXT_EQUAL, @"google.com"));
247
248   // Find the identity status field.
249   NSTextField* identity_status_field =
250       FindTextField(TEXT_NOT_EQUAL, @"google.com");
251   ASSERT_NE(identity_field, identity_status_field);
252
253   // Ensure the text of the identity status field changes when the status does.
254   NSString* status = [identity_status_field stringValue];
255   info.identity_status = WebsiteSettings::SITE_IDENTITY_STATUS_CERT;
256   bridge_->SetIdentityInfo(const_cast<WebsiteSettingsUI::IdentityInfo&>(info));
257   EXPECT_NSNE(status, [identity_status_field stringValue]);
258 }
259
260 TEST_F(WebsiteSettingsBubbleControllerTest, SetIdentityInfo) {
261   WebsiteSettingsUI::IdentityInfo info;
262   info.site_identity = std::string("nhl.com");
263   info.identity_status = WebsiteSettings::SITE_IDENTITY_STATUS_UNKNOWN;
264   info.identity_status_description = std::string("Identity1");
265   info.connection_status = WebsiteSettings::SITE_CONNECTION_STATUS_UNKNOWN;
266   info.connection_status_description = std::string("Connection1");
267   info.cert_id = 0;
268
269   CreateBubble();
270
271   // Set the identity, and test that the description fields on the Connection
272   // tab are set properly.
273   bridge_->SetIdentityInfo(const_cast<WebsiteSettingsUI::IdentityInfo&>(info));
274   EXPECT_NSEQ(@"Identity1",
275               [[controller_ identityStatusDescriptionField] stringValue]);
276   EXPECT_NSEQ(@"Connection1",
277               [[controller_ connectionStatusDescriptionField] stringValue]);
278
279   // Check the contents of the images, and make sure they change after the
280   // status changes.
281
282   NSImage* identity_icon = [[controller_ identityStatusIcon] image];
283   NSImage* connection_icon = [[controller_ connectionStatusIcon] image];
284   // Icons should be the same when they are both unknown.
285   EXPECT_EQ(identity_icon, connection_icon);
286
287   // Ensure that the link button for certificate info is not there -- the
288   // help link button should be the first one found.
289   NSMutableArray* buttons = FindAllSubviewsOfClass(
290       [controller_ connectionTabContentView], [NSButton class]);
291   ASSERT_EQ(1U, [buttons count]);
292   EXPECT_NSEQ([controller_ helpButton], [buttons objectAtIndex:0]);
293
294   // Check that it has a target and action linked up.
295   NSButton* link_button = static_cast<NSButton*>([buttons objectAtIndex:0]);
296   EXPECT_NSEQ(controller_, [link_button target]);
297   EXPECT_TRUE([link_button action] == @selector(showHelpPage:));
298
299   info.identity_status = WebsiteSettings::SITE_IDENTITY_STATUS_CERT;
300   info.connection_status = WebsiteSettings::SITE_CONNECTION_STATUS_ENCRYPTED;
301   info.cert_id = 1;
302   bridge_->SetIdentityInfo(const_cast<WebsiteSettingsUI::IdentityInfo&>(info));
303
304   EXPECT_NE(identity_icon, [[controller_ identityStatusIcon] image]);
305   EXPECT_NE(connection_icon, [[controller_ connectionStatusIcon] image]);
306
307   // The certificate info button should be there now.
308   buttons = FindAllSubviewsOfClass(
309       [controller_ connectionTabContentView], [NSButton class]);
310   ASSERT_EQ(2U, [buttons count]);
311   EXPECT_NSNE([controller_ helpButton], [buttons objectAtIndex:1]);
312
313   // Check that it has a target and action linked up.
314   link_button = static_cast<NSButton*>([buttons objectAtIndex:1]);
315   EXPECT_NSEQ(controller_, [link_button target]);
316   EXPECT_TRUE([link_button action] == @selector(showCertificateInfo:));
317 }
318
319 TEST_F(WebsiteSettingsBubbleControllerTest, SetFirstVisit) {
320   CreateBubble();
321   bridge_->SetFirstVisit(base::ASCIIToUTF16("Yesterday"));
322   EXPECT_NSEQ(@"Yesterday",
323               [[controller_ firstVisitDescriptionField] stringValue]);
324 }
325
326 TEST_F(WebsiteSettingsBubbleControllerTest, SetPermissionInfo) {
327   CreateBubble();
328   SetTestPermissions();
329
330   // There should be three subviews per permission (an icon, a label and a
331   // select box), plus a text label for the Permission section.
332   NSArray* subviews = [[controller_ permissionsView] subviews];
333   EXPECT_EQ(arraysize(kTestPermissionTypes) * 3 + 1, [subviews count]);
334
335   // Ensure that there is a distinct label for each permission.
336   NSMutableSet* labels = [NSMutableSet set];
337   for (NSView* view in subviews) {
338     if ([view isKindOfClass:[NSTextField class]])
339       [labels addObject:[static_cast<NSTextField*>(view) stringValue]];
340   }
341   // The section header ("Permissions") will also be found, hence the +1.
342   EXPECT_EQ(arraysize(kTestPermissionTypes) + 1, [labels count]);
343
344   // Ensure that the button labels are distinct, and look for the correct
345   // number of disabled buttons.
346   int disabled_count = 0;
347   [labels removeAllObjects];
348   for (NSView* view in subviews) {
349     if ([view isKindOfClass:[NSPopUpButton class]]) {
350       NSPopUpButton* button = static_cast<NSPopUpButton*>(view);
351       [labels addObject:[[button selectedCell] title]];
352
353       if (![button isEnabled])
354         ++disabled_count;
355     }
356   }
357   EXPECT_EQ(arraysize(kTestPermissionTypes), [labels count]);
358
359   // 4 of the buttons should be disabled -- the ones that have a setting source
360   // of SETTING_SOURCE_POLICY or SETTING_SOURCE_EXTENSION.
361   EXPECT_EQ(4, disabled_count);
362 }
363
364 TEST_F(WebsiteSettingsBubbleControllerTest, SetSelectedTab) {
365   CreateBubble();
366   NSSegmentedControl* segmentedControl = [controller_ segmentedControl];
367   NSTabView* tabView = [controller_ tabView];
368
369   // Test whether SetSelectedTab properly changes both the segmented control
370   // (which implements the tabs) as well as the visible tab contents.
371   // NOTE: This implicitly (and deliberately) tests that the tabs appear in a
372   // specific order: Permissions, Connection.
373   EXPECT_EQ(0, [segmentedControl selectedSegment]);
374   EXPECT_EQ(0, [tabView indexOfTabViewItem:[tabView selectedTabViewItem]]);
375   bridge_->SetSelectedTab(WebsiteSettingsUI::TAB_ID_CONNECTION);
376   EXPECT_EQ(1, [segmentedControl selectedSegment]);
377   EXPECT_EQ(1, [tabView indexOfTabViewItem:[tabView selectedTabViewItem]]);
378 }
379
380 TEST_F(WebsiteSettingsBubbleControllerTest, WindowWidth) {
381   // Try creating a window that is obviously too small.
382   CreateBubbleWithWidth(30.0);
383   SetTestPermissions();
384
385   CGFloat window_width = NSWidth([[controller_ window] frame]);
386
387   // Check the window was made bigger to fit the content.
388   EXPECT_LT(30.0, window_width);
389
390   // Check that the window is wider than the right edge of all the permission
391   // popup buttons.
392   for (NSView* view in [[controller_ permissionsView] subviews]) {
393     if ([view isKindOfClass:[NSPopUpButton class]]) {
394       NSPopUpButton* button = static_cast<NSPopUpButton*>(view);
395       EXPECT_LT(NSMaxX([button frame]), window_width);
396     }
397   }
398 }
399
400 }  // namespace