Index: ios/chrome/browser/ui/settings/block_popups_egtest.mm |
diff --git a/ios/chrome/browser/ui/settings/block_popups_egtest.mm b/ios/chrome/browser/ui/settings/block_popups_egtest.mm |
new file mode 100644 |
index 0000000000000000000000000000000000000000..c566ecc912f0f4593011b7e72ec346ce1aa6e287 |
--- /dev/null |
+++ b/ios/chrome/browser/ui/settings/block_popups_egtest.mm |
@@ -0,0 +1,300 @@ |
+// Copyright 2016 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 <EarlGrey/EarlGrey.h> |
+#import <UIKit/UIKit.h> |
+#import <XCTest/XCTest.h> |
+ |
+#include "base/ios/ios_util.h" |
+#include "base/strings/sys_string_conversions.h" |
+#include "components/content_settings/core/browser/host_content_settings_map.h" |
+#include "ios/chrome/browser/browser_state/chrome_browser_state.h" |
+#include "ios/chrome/browser/content_settings/host_content_settings_map_factory.h" |
+#import "ios/chrome/browser/ui/settings/settings_collection_view_controller.h" |
+#import "ios/chrome/browser/ui/tools_menu/tools_menu_view_controller.h" |
+#import "ios/chrome/browser/ui/tools_menu/tools_popup_controller.h" |
+#include "ios/chrome/grit/ios_strings.h" |
+#import "ios/chrome/test/app/chrome_test_util.h" |
+#import "ios/chrome/test/app/navigation_test_util.h" |
+#import "ios/chrome/test/app/web_view_interaction_test_util.h" |
+#import "ios/chrome/test/earl_grey/accessibility_util.h" |
+#import "ios/chrome/test/earl_grey/chrome_actions.h" |
+#import "ios/chrome/test/earl_grey/chrome_assertions.h" |
+#import "ios/chrome/test/earl_grey/chrome_earl_grey.h" |
+#import "ios/chrome/test/earl_grey/chrome_earl_grey_ui.h" |
+#import "ios/chrome/test/earl_grey/chrome_matchers.h" |
+#import "ios/chrome/test/earl_grey/chrome_test_case.h" |
+#import "ios/web/public/test/http_server.h" |
+#import "ios/web/public/test/http_server_util.h" |
+#import "ios/web/public/test/web_view_interaction_test_util.h" |
+#include "ui/base/l10n/l10n_util_mac.h" |
+#include "url/gurl.h" |
+ |
+namespace { |
+ |
+// URLs used in the tests. |
+const char* kBlockPopupsUrl = "http://blockpopups"; |
+const char* kOpenedWindowUrl = "http://openedwindow"; |
+ |
+// JavaScript to open a new window after a short delay. |
+NSString* kBlockPopupsResponseTemplate = |
+ @"<input type=\"button\" onclick=\"setTimeout(function() {" |
+ "window.open('%@')}, 1)\" " |
+ "id=\"openWindow\" " |
+ "value=\"openWindow\">"; |
+const std::string kOpenedWindowResponse = "Opened window"; |
+ |
+// Opens the block popups settings page. Must be called from the NTP. |
+void OpenBlockPopupsSettings() { |
+ const CGFloat scroll_displacement = 50.0; |
+ id<GREYMatcher> tools_menu_table_view_matcher = |
+ grey_accessibilityID(kToolsMenuTableViewId); |
+ id<GREYMatcher> settings_button_matcher = |
+ grey_accessibilityID(kToolsMenuSettingsId); |
+ id<GREYMatcher> content_settings_button_matcher = |
+ chrome_test_util::buttonWithAccessibilityLabelId( |
+ IDS_IOS_CONTENT_SETTINGS_TITLE); |
+ id<GREYMatcher> settings_collection_view_matcher = |
+ grey_accessibilityID(kSettingsCollectionViewId); |
+ id<GREYMatcher> block_popups_button_matcher = |
+ chrome_test_util::buttonWithAccessibilityLabelId(IDS_IOS_BLOCK_POPUPS); |
+ |
+ [ChromeEarlGreyUI openToolsMenu]; |
+ [[[EarlGrey selectElementWithMatcher:settings_button_matcher] |
+ usingSearchAction:grey_scrollInDirection(kGREYDirectionDown, |
+ scroll_displacement) |
+ onElementWithMatcher:tools_menu_table_view_matcher] |
+ performAction:grey_tap()]; |
+ |
+ [[[EarlGrey selectElementWithMatcher:content_settings_button_matcher] |
+ usingSearchAction:grey_scrollInDirection(kGREYDirectionDown, |
+ scroll_displacement) |
+ onElementWithMatcher:settings_collection_view_matcher] |
+ performAction:grey_tap()]; |
+ |
+ [[EarlGrey selectElementWithMatcher:block_popups_button_matcher] |
+ performAction:grey_tap()]; |
+} |
+ |
+// Exits out of settings. Must be called from the block popups settings page. |
+void CloseSettings() { |
+ [[EarlGrey |
+ selectElementWithMatcher:grey_allOf( |
+ grey_accessibilityID(@"back_bar_button"), |
+ grey_accessibilityTrait( |
+ UIAccessibilityTraitButton), |
+ nil)] performAction:grey_tap()]; |
+ [[EarlGrey |
+ selectElementWithMatcher:grey_allOf( |
+ grey_accessibilityID(@"back_bar_button"), |
+ grey_accessibilityTrait( |
+ UIAccessibilityTraitButton), |
+ nil)] performAction:grey_tap()]; |
+ [[EarlGrey |
+ selectElementWithMatcher:chrome_test_util::buttonWithAccessibilityLabelId( |
+ IDS_IOS_NAVIGATION_BAR_DONE_BUTTON)] |
+ performAction:grey_tap()]; |
+} |
+ |
+// ScopedBlockPopupsPref modifies the block popups preference and resets the |
+// preference to its original value when this object goes out of scope. |
+class ScopedBlockPopupsPref { |
+ public: |
+ ScopedBlockPopupsPref(ContentSetting setting) { |
+ original_setting_ = GetPrefValue(); |
+ SetPrefValue(setting); |
+ } |
+ ~ScopedBlockPopupsPref() { SetPrefValue(original_setting_); } |
+ |
+ private: |
+ // Gets the current value of the preference. |
+ ContentSetting GetPrefValue() { |
+ ContentSetting popupSetting = |
+ ios::HostContentSettingsMapFactory::GetForBrowserState( |
+ chrome_test_util::GetOriginalBrowserState()) |
+ ->GetDefaultContentSetting(CONTENT_SETTINGS_TYPE_POPUPS, NULL); |
+ return popupSetting; |
+ } |
+ |
+ // Sets the preference to the given value. |
+ void SetPrefValue(ContentSetting setting) { |
+ DCHECK(setting == CONTENT_SETTING_BLOCK || |
+ setting == CONTENT_SETTING_ALLOW); |
+ ios::ChromeBrowserState* state = |
+ chrome_test_util::GetOriginalBrowserState(); |
+ ios::HostContentSettingsMapFactory::GetForBrowserState(state) |
+ ->SetDefaultContentSetting(CONTENT_SETTINGS_TYPE_POPUPS, setting); |
+ } |
+ |
+ // Saves the original pref setting so that it can be restored when the scoper |
+ // is destroyed. |
+ ContentSetting original_setting_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(ScopedBlockPopupsPref); |
+}; |
+ |
+// ScopedBlockPopupsException adds an exception to the block popups exception |
+// list for as long as this object is in scope. |
+class ScopedBlockPopupsException { |
+ public: |
+ ScopedBlockPopupsException(const std::string& pattern) : pattern_(pattern) { |
+ SetException(pattern_, CONTENT_SETTING_ALLOW); |
+ } |
+ ~ScopedBlockPopupsException() { |
+ SetException(pattern_, CONTENT_SETTING_DEFAULT); |
+ } |
+ |
+ private: |
+ // Adds an exception for the given |pattern|. If |setting| is |
+ // CONTENT_SETTING_DEFAULT, removes the existing exception instead. |
+ void SetException(const std::string& pattern, ContentSetting setting) { |
+ ios::ChromeBrowserState* browserState = |
+ chrome_test_util::GetOriginalBrowserState(); |
+ |
+ ContentSettingsPattern exception_pattern = |
+ ContentSettingsPattern::FromString(pattern); |
+ ios::HostContentSettingsMapFactory::GetForBrowserState(browserState) |
+ ->SetContentSettingCustomScope( |
+ exception_pattern, ContentSettingsPattern::Wildcard(), |
+ CONTENT_SETTINGS_TYPE_POPUPS, std::string(), setting); |
+ } |
+ |
+ // The exception pattern that this object is managing. |
+ std::string pattern_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(ScopedBlockPopupsException); |
+}; |
+} // namespace |
+ |
+// Block Popups tests for Chrome. |
+@interface BlockPopupsTestCase : ChromeTestCase |
+@end |
+ |
+@implementation BlockPopupsTestCase |
+ |
+// Opens the block popups settings page and verifies that accessibility is set |
+// up properly. |
+- (void)testAccessibilityOfBlockPopupSettings { |
+ OpenBlockPopupsSettings(); |
+ [[EarlGrey |
+ selectElementWithMatcher:grey_accessibilityID( |
+ @"block_popups_settings_view_controller")] |
+ assertWithMatcher:grey_notNil()]; |
+ chrome_test_util::VerifyAccessibilityForCurrentScreen(); |
+ CloseSettings(); |
+} |
+ |
+// Tests that popups are opened in new tabs when the preference is set to ALLOW. |
+- (void)testPopupsAllowed { |
+ std::map<GURL, std::string> responses; |
+ const GURL blockPopupsURL = web::test::HttpServer::MakeUrl(kBlockPopupsUrl); |
+ const GURL openedWindowURL = web::test::HttpServer::MakeUrl(kOpenedWindowUrl); |
+ NSString* openedWindowURLString = |
+ base::SysUTF8ToNSString(openedWindowURL.spec()); |
+ responses[blockPopupsURL] = base::SysNSStringToUTF8([NSString |
+ stringWithFormat:kBlockPopupsResponseTemplate, openedWindowURLString]); |
+ responses[openedWindowURL] = kOpenedWindowResponse; |
+ web::test::SetUpSimpleHttpServer(responses); |
+ |
+ ScopedBlockPopupsPref prefSetter(CONTENT_SETTING_ALLOW); |
+ [ChromeEarlGrey loadURL:blockPopupsURL]; |
+ chrome_test_util::AssertMainTabCount(1U); |
+ |
+ // Tap the "Open Window" link and make sure the popup opened in a new tab. |
+ chrome_test_util::TapWebViewElementWithId("openWindow"); |
+ chrome_test_util::AssertMainTabCount(2U); |
+ |
+ // No infobar should be displayed. |
+ [[EarlGrey selectElementWithMatcher:chrome_test_util:: |
+ staticTextWithAccessibilityLabel( |
+ @"Pop-ups blocked (1)")] |
+ assertWithMatcher:grey_notVisible()]; |
+} |
+ |
+// Tests that popups are prevented from opening and an infobar is displayed when |
+// the preference is set to BLOCK. |
+- (void)testPopupsBlocked { |
+ std::map<GURL, std::string> responses; |
+ const GURL blockPopupsURL = web::test::HttpServer::MakeUrl(kBlockPopupsUrl); |
+ const GURL openedWindowURL = web::test::HttpServer::MakeUrl(kOpenedWindowUrl); |
+ NSString* openedWindowURLString = |
+ base::SysUTF8ToNSString(openedWindowURL.spec()); |
+ responses[blockPopupsURL] = base::SysNSStringToUTF8([NSString |
+ stringWithFormat:kBlockPopupsResponseTemplate, openedWindowURLString]); |
+ responses[openedWindowURL] = kOpenedWindowResponse; |
+ web::test::SetUpSimpleHttpServer(responses); |
+ |
+ ScopedBlockPopupsPref prefSetter(CONTENT_SETTING_BLOCK); |
+ [ChromeEarlGrey loadURL:blockPopupsURL]; |
+ chrome_test_util::AssertMainTabCount(1U); |
+ |
+ // Tap the "Open Window" link, then make sure the popup was blocked and an |
+ // infobar was displayed. The window.open() call is run via async JS, so the |
+ // infobar may not open immediately. |
+ chrome_test_util::TapWebViewElementWithId("openWindow"); |
+ [[GREYCondition |
+ conditionWithName:@"Wait for blocked popups infobar to show" |
+ block:^BOOL { |
+ NSError* error = nil; |
+ [[EarlGrey |
+ selectElementWithMatcher: |
+ chrome_test_util::staticTextWithAccessibilityLabel( |
+ @"Pop-ups blocked (1)")] |
+ assertWithMatcher:grey_sufficientlyVisible() |
+ error:&error]; |
+ return error == nil; |
+ }] waitWithTimeout:4.0]; |
+ chrome_test_util::AssertMainTabCount(1U); |
+} |
+ |
+// Tests that the "exceptions" section on the settings page is hidden and |
+// revealed properly when the preference switch is toggled. |
+- (void)testSettingsPageWithExceptions { |
+ std::string allowedPattern = "[*.]example.com"; |
+ ScopedBlockPopupsPref prefSetter(CONTENT_SETTING_BLOCK); |
+ ScopedBlockPopupsException exceptionSetter(allowedPattern); |
+ |
+ OpenBlockPopupsSettings(); |
+ |
+ // Make sure that the "example.com" exception is listed. |
+ [[EarlGrey selectElementWithMatcher:grey_text(base::SysUTF8ToNSString( |
+ allowedPattern))] |
+ assertWithMatcher:grey_sufficientlyVisible()]; |
+ |
+ // Toggle the switch off via the UI and make sure the exceptions are not |
+ // visible. |
+ [[EarlGrey |
+ selectElementWithMatcher:chrome_test_util::collectionViewSwitchCell( |
+ @"blockPopupsContentView_switch", YES)] |
+ performAction:chrome_test_util::turnCollectionViewSwitchOn(NO)]; |
+ [[EarlGrey selectElementWithMatcher:grey_text(base::SysUTF8ToNSString( |
+ allowedPattern))] |
+ assertWithMatcher:grey_notVisible()]; |
+ [[EarlGrey |
+ selectElementWithMatcher:grey_accessibilityLabel(l10n_util::GetNSString( |
+ IDS_IOS_NAVIGATION_BAR_EDIT_BUTTON))] |
+ assertWithMatcher:grey_notVisible()]; |
+ [[EarlGrey |
+ selectElementWithMatcher:grey_accessibilityLabel(l10n_util::GetNSString( |
+ IDS_IOS_NAVIGATION_BAR_DONE_BUTTON))] |
+ assertWithMatcher:grey_sufficientlyVisible()]; |
+ |
+ // Toggle the switch back on via the UI and make sure the exceptions are now |
+ // visible. |
+ [[EarlGrey |
+ selectElementWithMatcher:chrome_test_util::collectionViewSwitchCell( |
+ @"blockPopupsContentView_switch", NO)] |
+ performAction:chrome_test_util::turnCollectionViewSwitchOn(YES)]; |
+ [[EarlGrey selectElementWithMatcher:grey_text(base::SysUTF8ToNSString( |
+ allowedPattern))] |
+ assertWithMatcher:grey_sufficientlyVisible()]; |
+ [[EarlGrey |
+ selectElementWithMatcher:grey_accessibilityLabel(l10n_util::GetNSString( |
+ IDS_IOS_NAVIGATION_BAR_EDIT_BUTTON))] |
+ assertWithMatcher:grey_sufficientlyVisible()]; |
+ |
+ CloseSettings(); |
+} |
+ |
+@end |