OLD | NEW |
(Empty) | |
| 1 // Copyright 2016 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 <EarlGrey/EarlGrey.h> |
| 6 #import <UIKit/UIKit.h> |
| 7 #import <XCTest/XCTest.h> |
| 8 |
| 9 #include "base/ios/ios_util.h" |
| 10 #include "base/strings/sys_string_conversions.h" |
| 11 #include "components/content_settings/core/browser/host_content_settings_map.h" |
| 12 #include "ios/chrome/browser/browser_state/chrome_browser_state.h" |
| 13 #include "ios/chrome/browser/content_settings/host_content_settings_map_factory.
h" |
| 14 #import "ios/chrome/browser/ui/settings/settings_collection_view_controller.h" |
| 15 #import "ios/chrome/browser/ui/tools_menu/tools_menu_view_controller.h" |
| 16 #import "ios/chrome/browser/ui/tools_menu/tools_popup_controller.h" |
| 17 #include "ios/chrome/grit/ios_strings.h" |
| 18 #import "ios/chrome/test/app/chrome_test_util.h" |
| 19 #import "ios/chrome/test/app/navigation_test_util.h" |
| 20 #import "ios/chrome/test/app/web_view_interaction_test_util.h" |
| 21 #import "ios/chrome/test/earl_grey/accessibility_util.h" |
| 22 #import "ios/chrome/test/earl_grey/chrome_actions.h" |
| 23 #import "ios/chrome/test/earl_grey/chrome_assertions.h" |
| 24 #import "ios/chrome/test/earl_grey/chrome_earl_grey.h" |
| 25 #import "ios/chrome/test/earl_grey/chrome_earl_grey_ui.h" |
| 26 #import "ios/chrome/test/earl_grey/chrome_matchers.h" |
| 27 #import "ios/chrome/test/earl_grey/chrome_test_case.h" |
| 28 #import "ios/web/public/test/http_server.h" |
| 29 #import "ios/web/public/test/http_server_util.h" |
| 30 #import "ios/web/public/test/web_view_interaction_test_util.h" |
| 31 #include "ui/base/l10n/l10n_util_mac.h" |
| 32 #include "url/gurl.h" |
| 33 |
| 34 namespace { |
| 35 |
| 36 // URLs used in the tests. |
| 37 const char* kBlockPopupsUrl = "http://blockpopups"; |
| 38 const char* kOpenedWindowUrl = "http://openedwindow"; |
| 39 |
| 40 // JavaScript to open a new window after a short delay. |
| 41 NSString* kBlockPopupsResponseTemplate = |
| 42 @"<input type=\"button\" onclick=\"setTimeout(function() {" |
| 43 "window.open('%@')}, 1)\" " |
| 44 "id=\"openWindow\" " |
| 45 "value=\"openWindow\">"; |
| 46 const std::string kOpenedWindowResponse = "Opened window"; |
| 47 |
| 48 // Opens the block popups settings page. Must be called from the NTP. |
| 49 void OpenBlockPopupsSettings() { |
| 50 const CGFloat scroll_displacement = 50.0; |
| 51 id<GREYMatcher> tools_menu_table_view_matcher = |
| 52 grey_accessibilityID(kToolsMenuTableViewId); |
| 53 id<GREYMatcher> settings_button_matcher = |
| 54 grey_accessibilityID(kToolsMenuSettingsId); |
| 55 id<GREYMatcher> content_settings_button_matcher = |
| 56 chrome_test_util::buttonWithAccessibilityLabelId( |
| 57 IDS_IOS_CONTENT_SETTINGS_TITLE); |
| 58 id<GREYMatcher> settings_collection_view_matcher = |
| 59 grey_accessibilityID(kSettingsCollectionViewId); |
| 60 id<GREYMatcher> block_popups_button_matcher = |
| 61 chrome_test_util::buttonWithAccessibilityLabelId(IDS_IOS_BLOCK_POPUPS); |
| 62 |
| 63 [ChromeEarlGreyUI openToolsMenu]; |
| 64 [[[EarlGrey selectElementWithMatcher:settings_button_matcher] |
| 65 usingSearchAction:grey_scrollInDirection(kGREYDirectionDown, |
| 66 scroll_displacement) |
| 67 onElementWithMatcher:tools_menu_table_view_matcher] |
| 68 performAction:grey_tap()]; |
| 69 |
| 70 [[[EarlGrey selectElementWithMatcher:content_settings_button_matcher] |
| 71 usingSearchAction:grey_scrollInDirection(kGREYDirectionDown, |
| 72 scroll_displacement) |
| 73 onElementWithMatcher:settings_collection_view_matcher] |
| 74 performAction:grey_tap()]; |
| 75 |
| 76 [[EarlGrey selectElementWithMatcher:block_popups_button_matcher] |
| 77 performAction:grey_tap()]; |
| 78 } |
| 79 |
| 80 // Exits out of settings. Must be called from the block popups settings page. |
| 81 void CloseSettings() { |
| 82 [[EarlGrey |
| 83 selectElementWithMatcher:grey_allOf( |
| 84 grey_accessibilityID(@"back_bar_button"), |
| 85 grey_accessibilityTrait( |
| 86 UIAccessibilityTraitButton), |
| 87 nil)] performAction:grey_tap()]; |
| 88 [[EarlGrey |
| 89 selectElementWithMatcher:grey_allOf( |
| 90 grey_accessibilityID(@"back_bar_button"), |
| 91 grey_accessibilityTrait( |
| 92 UIAccessibilityTraitButton), |
| 93 nil)] performAction:grey_tap()]; |
| 94 [[EarlGrey |
| 95 selectElementWithMatcher:chrome_test_util::buttonWithAccessibilityLabelId( |
| 96 IDS_IOS_NAVIGATION_BAR_DONE_BUTTON)] |
| 97 performAction:grey_tap()]; |
| 98 } |
| 99 |
| 100 // ScopedBlockPopupsPref modifies the block popups preference and resets the |
| 101 // preference to its original value when this object goes out of scope. |
| 102 class ScopedBlockPopupsPref { |
| 103 public: |
| 104 ScopedBlockPopupsPref(ContentSetting setting) { |
| 105 original_setting_ = GetPrefValue(); |
| 106 SetPrefValue(setting); |
| 107 } |
| 108 ~ScopedBlockPopupsPref() { SetPrefValue(original_setting_); } |
| 109 |
| 110 private: |
| 111 // Gets the current value of the preference. |
| 112 ContentSetting GetPrefValue() { |
| 113 ContentSetting popupSetting = |
| 114 ios::HostContentSettingsMapFactory::GetForBrowserState( |
| 115 chrome_test_util::GetOriginalBrowserState()) |
| 116 ->GetDefaultContentSetting(CONTENT_SETTINGS_TYPE_POPUPS, NULL); |
| 117 return popupSetting; |
| 118 } |
| 119 |
| 120 // Sets the preference to the given value. |
| 121 void SetPrefValue(ContentSetting setting) { |
| 122 DCHECK(setting == CONTENT_SETTING_BLOCK || |
| 123 setting == CONTENT_SETTING_ALLOW); |
| 124 ios::ChromeBrowserState* state = |
| 125 chrome_test_util::GetOriginalBrowserState(); |
| 126 ios::HostContentSettingsMapFactory::GetForBrowserState(state) |
| 127 ->SetDefaultContentSetting(CONTENT_SETTINGS_TYPE_POPUPS, setting); |
| 128 } |
| 129 |
| 130 // Saves the original pref setting so that it can be restored when the scoper |
| 131 // is destroyed. |
| 132 ContentSetting original_setting_; |
| 133 |
| 134 DISALLOW_COPY_AND_ASSIGN(ScopedBlockPopupsPref); |
| 135 }; |
| 136 |
| 137 // ScopedBlockPopupsException adds an exception to the block popups exception |
| 138 // list for as long as this object is in scope. |
| 139 class ScopedBlockPopupsException { |
| 140 public: |
| 141 ScopedBlockPopupsException(const std::string& pattern) : pattern_(pattern) { |
| 142 SetException(pattern_, CONTENT_SETTING_ALLOW); |
| 143 } |
| 144 ~ScopedBlockPopupsException() { |
| 145 SetException(pattern_, CONTENT_SETTING_DEFAULT); |
| 146 } |
| 147 |
| 148 private: |
| 149 // Adds an exception for the given |pattern|. If |setting| is |
| 150 // CONTENT_SETTING_DEFAULT, removes the existing exception instead. |
| 151 void SetException(const std::string& pattern, ContentSetting setting) { |
| 152 ios::ChromeBrowserState* browserState = |
| 153 chrome_test_util::GetOriginalBrowserState(); |
| 154 |
| 155 ContentSettingsPattern exception_pattern = |
| 156 ContentSettingsPattern::FromString(pattern); |
| 157 ios::HostContentSettingsMapFactory::GetForBrowserState(browserState) |
| 158 ->SetContentSettingCustomScope( |
| 159 exception_pattern, ContentSettingsPattern::Wildcard(), |
| 160 CONTENT_SETTINGS_TYPE_POPUPS, std::string(), setting); |
| 161 } |
| 162 |
| 163 // The exception pattern that this object is managing. |
| 164 std::string pattern_; |
| 165 |
| 166 DISALLOW_COPY_AND_ASSIGN(ScopedBlockPopupsException); |
| 167 }; |
| 168 } // namespace |
| 169 |
| 170 // Block Popups tests for Chrome. |
| 171 @interface BlockPopupsTestCase : ChromeTestCase |
| 172 @end |
| 173 |
| 174 @implementation BlockPopupsTestCase |
| 175 |
| 176 // Opens the block popups settings page and verifies that accessibility is set |
| 177 // up properly. |
| 178 - (void)testAccessibilityOfBlockPopupSettings { |
| 179 OpenBlockPopupsSettings(); |
| 180 [[EarlGrey |
| 181 selectElementWithMatcher:grey_accessibilityID( |
| 182 @"block_popups_settings_view_controller")] |
| 183 assertWithMatcher:grey_notNil()]; |
| 184 chrome_test_util::VerifyAccessibilityForCurrentScreen(); |
| 185 CloseSettings(); |
| 186 } |
| 187 |
| 188 // Tests that popups are opened in new tabs when the preference is set to ALLOW. |
| 189 - (void)testPopupsAllowed { |
| 190 std::map<GURL, std::string> responses; |
| 191 const GURL blockPopupsURL = web::test::HttpServer::MakeUrl(kBlockPopupsUrl); |
| 192 const GURL openedWindowURL = web::test::HttpServer::MakeUrl(kOpenedWindowUrl); |
| 193 NSString* openedWindowURLString = |
| 194 base::SysUTF8ToNSString(openedWindowURL.spec()); |
| 195 responses[blockPopupsURL] = base::SysNSStringToUTF8([NSString |
| 196 stringWithFormat:kBlockPopupsResponseTemplate, openedWindowURLString]); |
| 197 responses[openedWindowURL] = kOpenedWindowResponse; |
| 198 web::test::SetUpSimpleHttpServer(responses); |
| 199 |
| 200 ScopedBlockPopupsPref prefSetter(CONTENT_SETTING_ALLOW); |
| 201 [ChromeEarlGrey loadURL:blockPopupsURL]; |
| 202 chrome_test_util::AssertMainTabCount(1U); |
| 203 |
| 204 // Tap the "Open Window" link and make sure the popup opened in a new tab. |
| 205 chrome_test_util::TapWebViewElementWithId("openWindow"); |
| 206 chrome_test_util::AssertMainTabCount(2U); |
| 207 |
| 208 // No infobar should be displayed. |
| 209 [[EarlGrey selectElementWithMatcher:chrome_test_util:: |
| 210 staticTextWithAccessibilityLabel( |
| 211 @"Pop-ups blocked (1)")] |
| 212 assertWithMatcher:grey_notVisible()]; |
| 213 } |
| 214 |
| 215 // Tests that popups are prevented from opening and an infobar is displayed when |
| 216 // the preference is set to BLOCK. |
| 217 - (void)testPopupsBlocked { |
| 218 std::map<GURL, std::string> responses; |
| 219 const GURL blockPopupsURL = web::test::HttpServer::MakeUrl(kBlockPopupsUrl); |
| 220 const GURL openedWindowURL = web::test::HttpServer::MakeUrl(kOpenedWindowUrl); |
| 221 NSString* openedWindowURLString = |
| 222 base::SysUTF8ToNSString(openedWindowURL.spec()); |
| 223 responses[blockPopupsURL] = base::SysNSStringToUTF8([NSString |
| 224 stringWithFormat:kBlockPopupsResponseTemplate, openedWindowURLString]); |
| 225 responses[openedWindowURL] = kOpenedWindowResponse; |
| 226 web::test::SetUpSimpleHttpServer(responses); |
| 227 |
| 228 ScopedBlockPopupsPref prefSetter(CONTENT_SETTING_BLOCK); |
| 229 [ChromeEarlGrey loadURL:blockPopupsURL]; |
| 230 chrome_test_util::AssertMainTabCount(1U); |
| 231 |
| 232 // Tap the "Open Window" link, then make sure the popup was blocked and an |
| 233 // infobar was displayed. The window.open() call is run via async JS, so the |
| 234 // infobar may not open immediately. |
| 235 chrome_test_util::TapWebViewElementWithId("openWindow"); |
| 236 [[GREYCondition |
| 237 conditionWithName:@"Wait for blocked popups infobar to show" |
| 238 block:^BOOL { |
| 239 NSError* error = nil; |
| 240 [[EarlGrey |
| 241 selectElementWithMatcher: |
| 242 chrome_test_util::staticTextWithAccessibilityLabel( |
| 243 @"Pop-ups blocked (1)")] |
| 244 assertWithMatcher:grey_sufficientlyVisible() |
| 245 error:&error]; |
| 246 return error == nil; |
| 247 }] waitWithTimeout:4.0]; |
| 248 chrome_test_util::AssertMainTabCount(1U); |
| 249 } |
| 250 |
| 251 // Tests that the "exceptions" section on the settings page is hidden and |
| 252 // revealed properly when the preference switch is toggled. |
| 253 - (void)testSettingsPageWithExceptions { |
| 254 std::string allowedPattern = "[*.]example.com"; |
| 255 ScopedBlockPopupsPref prefSetter(CONTENT_SETTING_BLOCK); |
| 256 ScopedBlockPopupsException exceptionSetter(allowedPattern); |
| 257 |
| 258 OpenBlockPopupsSettings(); |
| 259 |
| 260 // Make sure that the "example.com" exception is listed. |
| 261 [[EarlGrey selectElementWithMatcher:grey_text(base::SysUTF8ToNSString( |
| 262 allowedPattern))] |
| 263 assertWithMatcher:grey_sufficientlyVisible()]; |
| 264 |
| 265 // Toggle the switch off via the UI and make sure the exceptions are not |
| 266 // visible. |
| 267 [[EarlGrey |
| 268 selectElementWithMatcher:chrome_test_util::collectionViewSwitchCell( |
| 269 @"blockPopupsContentView_switch", YES)] |
| 270 performAction:chrome_test_util::turnCollectionViewSwitchOn(NO)]; |
| 271 [[EarlGrey selectElementWithMatcher:grey_text(base::SysUTF8ToNSString( |
| 272 allowedPattern))] |
| 273 assertWithMatcher:grey_notVisible()]; |
| 274 [[EarlGrey |
| 275 selectElementWithMatcher:grey_accessibilityLabel(l10n_util::GetNSString( |
| 276 IDS_IOS_NAVIGATION_BAR_EDIT_BUTTON))] |
| 277 assertWithMatcher:grey_notVisible()]; |
| 278 [[EarlGrey |
| 279 selectElementWithMatcher:grey_accessibilityLabel(l10n_util::GetNSString( |
| 280 IDS_IOS_NAVIGATION_BAR_DONE_BUTTON))] |
| 281 assertWithMatcher:grey_sufficientlyVisible()]; |
| 282 |
| 283 // Toggle the switch back on via the UI and make sure the exceptions are now |
| 284 // visible. |
| 285 [[EarlGrey |
| 286 selectElementWithMatcher:chrome_test_util::collectionViewSwitchCell( |
| 287 @"blockPopupsContentView_switch", NO)] |
| 288 performAction:chrome_test_util::turnCollectionViewSwitchOn(YES)]; |
| 289 [[EarlGrey selectElementWithMatcher:grey_text(base::SysUTF8ToNSString( |
| 290 allowedPattern))] |
| 291 assertWithMatcher:grey_sufficientlyVisible()]; |
| 292 [[EarlGrey |
| 293 selectElementWithMatcher:grey_accessibilityLabel(l10n_util::GetNSString( |
| 294 IDS_IOS_NAVIGATION_BAR_EDIT_BUTTON))] |
| 295 assertWithMatcher:grey_sufficientlyVisible()]; |
| 296 |
| 297 CloseSettings(); |
| 298 } |
| 299 |
| 300 @end |
OLD | NEW |