OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #import "ios/chrome/browser/ui/settings/block_popups_collection_view_controller.
h" | 5 #import "ios/chrome/browser/ui/settings/block_popups_collection_view_controller.
h" |
6 | 6 |
7 #import "base/ios/weak_nsobject.h" | |
8 #include "base/logging.h" | 7 #include "base/logging.h" |
9 #import "base/mac/foundation_util.h" | 8 #import "base/mac/foundation_util.h" |
10 #import "base/mac/scoped_nsobject.h" | |
11 #include "base/strings/sys_string_conversions.h" | 9 #include "base/strings/sys_string_conversions.h" |
12 #include "base/values.h" | 10 #include "base/values.h" |
13 #include "components/content_settings/core/browser/host_content_settings_map.h" | 11 #include "components/content_settings/core/browser/host_content_settings_map.h" |
14 #include "components/content_settings/core/common/content_settings_pattern.h" | 12 #include "components/content_settings/core/common/content_settings_pattern.h" |
15 #include "ios/chrome/browser/browser_state/chrome_browser_state.h" | 13 #include "ios/chrome/browser/browser_state/chrome_browser_state.h" |
16 #include "ios/chrome/browser/content_settings/host_content_settings_map_factory.
h" | 14 #include "ios/chrome/browser/content_settings/host_content_settings_map_factory.
h" |
17 #import "ios/chrome/browser/ui/collection_view/cells/collection_view_switch_item
.h" | 15 #import "ios/chrome/browser/ui/collection_view/cells/collection_view_switch_item
.h" |
18 #import "ios/chrome/browser/ui/collection_view/cells/collection_view_text_item.h
" | 16 #import "ios/chrome/browser/ui/collection_view/cells/collection_view_text_item.h
" |
19 #import "ios/chrome/browser/ui/collection_view/collection_view_model.h" | 17 #import "ios/chrome/browser/ui/collection_view/collection_view_model.h" |
20 #import "ios/chrome/browser/ui/settings/settings_navigation_controller.h" | 18 #import "ios/chrome/browser/ui/settings/settings_navigation_controller.h" |
21 #import "ios/chrome/browser/ui/settings/utils/content_setting_backed_boolean.h" | 19 #import "ios/chrome/browser/ui/settings/utils/content_setting_backed_boolean.h" |
22 #include "ios/chrome/grit/ios_strings.h" | 20 #include "ios/chrome/grit/ios_strings.h" |
23 #import "ios/third_party/material_components_ios/src/components/Palettes/src/Mat
erialPalettes.h" | 21 #import "ios/third_party/material_components_ios/src/components/Palettes/src/Mat
erialPalettes.h" |
24 #include "ui/base/l10n/l10n_util.h" | 22 #include "ui/base/l10n/l10n_util.h" |
25 #include "ui/base/l10n/l10n_util_mac.h" | 23 #include "ui/base/l10n/l10n_util_mac.h" |
26 | 24 |
| 25 #if !defined(__has_feature) || !__has_feature(objc_arc) |
| 26 #error "This file requires ARC support." |
| 27 #endif |
| 28 |
27 namespace { | 29 namespace { |
28 | 30 |
29 typedef NS_ENUM(NSInteger, SectionIdentifier) { | 31 typedef NS_ENUM(NSInteger, SectionIdentifier) { |
30 SectionIdentifierMainSwitch = kSectionIdentifierEnumZero, | 32 SectionIdentifierMainSwitch = kSectionIdentifierEnumZero, |
31 SectionIdentifierExceptions, | 33 SectionIdentifierExceptions, |
32 }; | 34 }; |
33 | 35 |
34 typedef NS_ENUM(NSInteger, ItemType) { | 36 typedef NS_ENUM(NSInteger, ItemType) { |
35 ItemTypeMainSwitch = kItemTypeEnumZero, | 37 ItemTypeMainSwitch = kItemTypeEnumZero, |
36 ItemTypeHeader, | 38 ItemTypeHeader, |
37 ItemTypeException, | 39 ItemTypeException, |
38 }; | 40 }; |
39 | 41 |
40 } // namespace | 42 } // namespace |
41 | 43 |
42 @interface BlockPopupsCollectionViewController ()<BooleanObserver> { | 44 @interface BlockPopupsCollectionViewController ()<BooleanObserver> { |
43 ios::ChromeBrowserState* _browserState; // weak | 45 ios::ChromeBrowserState* _browserState; // weak |
44 | 46 |
45 // List of url patterns that are allowed to display popups. | 47 // List of url patterns that are allowed to display popups. |
46 base::ListValue _exceptions; | 48 base::ListValue _exceptions; |
47 | 49 |
48 // The observable boolean that binds to the "Disable Popups" setting state. | 50 // The observable boolean that binds to the "Disable Popups" setting state. |
49 base::scoped_nsobject<ContentSettingBackedBoolean> _disablePopupsSetting; | 51 ContentSettingBackedBoolean* _disablePopupsSetting; |
50 | 52 |
51 // The item related to the switch for the "Disable Popups" setting. | 53 // The item related to the switch for the "Disable Popups" setting. |
52 base::scoped_nsobject<CollectionViewSwitchItem> _blockPopupsItem; | 54 CollectionViewSwitchItem* _blockPopupsItem; |
53 } | 55 } |
54 | 56 |
55 // Fetch the urls that can display popups and add them to |_exceptions|. | 57 // Fetch the urls that can display popups and add them to |_exceptions|. |
56 - (void)populateExceptionsList; | 58 - (void)populateExceptionsList; |
57 | 59 |
58 // Returns YES if popups are currently blocked by default, NO otherwise. | 60 // Returns YES if popups are currently blocked by default, NO otherwise. |
59 - (BOOL)popupsCurrentlyBlocked; | 61 - (BOOL)popupsCurrentlyBlocked; |
60 | 62 |
61 @end | 63 @end |
62 | 64 |
63 @implementation BlockPopupsCollectionViewController | 65 @implementation BlockPopupsCollectionViewController |
64 | 66 |
65 - (instancetype)initWithBrowserState:(ios::ChromeBrowserState*)browserState { | 67 - (instancetype)initWithBrowserState:(ios::ChromeBrowserState*)browserState { |
66 DCHECK(browserState); | 68 DCHECK(browserState); |
67 self = [super initWithStyle:CollectionViewControllerStyleAppBar]; | 69 self = [super initWithStyle:CollectionViewControllerStyleAppBar]; |
68 if (self) { | 70 if (self) { |
69 _browserState = browserState; | 71 _browserState = browserState; |
70 HostContentSettingsMap* settingsMap = | 72 HostContentSettingsMap* settingsMap = |
71 ios::HostContentSettingsMapFactory::GetForBrowserState(_browserState); | 73 ios::HostContentSettingsMapFactory::GetForBrowserState(_browserState); |
72 _disablePopupsSetting.reset([[ContentSettingBackedBoolean alloc] | 74 _disablePopupsSetting = [[ContentSettingBackedBoolean alloc] |
73 initWithHostContentSettingsMap:settingsMap | 75 initWithHostContentSettingsMap:settingsMap |
74 settingID:CONTENT_SETTINGS_TYPE_POPUPS | 76 settingID:CONTENT_SETTINGS_TYPE_POPUPS |
75 inverted:YES]); | 77 inverted:YES]; |
76 [_disablePopupsSetting setObserver:self]; | 78 [_disablePopupsSetting setObserver:self]; |
77 self.title = l10n_util::GetNSString(IDS_IOS_BLOCK_POPUPS); | 79 self.title = l10n_util::GetNSString(IDS_IOS_BLOCK_POPUPS); |
78 self.collectionViewAccessibilityIdentifier = | 80 self.collectionViewAccessibilityIdentifier = |
79 @"block_popups_settings_view_controller"; | 81 @"block_popups_settings_view_controller"; |
80 | 82 |
81 [self populateExceptionsList]; | 83 [self populateExceptionsList]; |
82 [self updateEditButton]; | 84 [self updateEditButton]; |
83 [self loadModel]; | 85 [self loadModel]; |
84 } | 86 } |
85 return self; | 87 return self; |
86 } | 88 } |
87 | 89 |
88 - (void)dealloc { | 90 - (void)dealloc { |
89 [_disablePopupsSetting setObserver:nil]; | 91 [_disablePopupsSetting setObserver:nil]; |
90 [super dealloc]; | |
91 } | 92 } |
92 | 93 |
93 #pragma mark - SettingsRootCollectionViewController | 94 #pragma mark - SettingsRootCollectionViewController |
94 | 95 |
95 - (void)loadModel { | 96 - (void)loadModel { |
96 [super loadModel]; | 97 [super loadModel]; |
97 | 98 |
98 CollectionViewModel* model = self.collectionViewModel; | 99 CollectionViewModel* model = self.collectionViewModel; |
99 | 100 |
100 // Block popups switch. | 101 // Block popups switch. |
101 [model addSectionWithIdentifier:SectionIdentifierMainSwitch]; | 102 [model addSectionWithIdentifier:SectionIdentifierMainSwitch]; |
102 | 103 |
103 _blockPopupsItem.reset( | 104 _blockPopupsItem = |
104 [[CollectionViewSwitchItem alloc] initWithType:ItemTypeMainSwitch]); | 105 [[CollectionViewSwitchItem alloc] initWithType:ItemTypeMainSwitch]; |
105 _blockPopupsItem.get().text = l10n_util::GetNSString(IDS_IOS_BLOCK_POPUPS); | 106 _blockPopupsItem.text = l10n_util::GetNSString(IDS_IOS_BLOCK_POPUPS); |
106 _blockPopupsItem.get().on = [_disablePopupsSetting value]; | 107 _blockPopupsItem.on = [_disablePopupsSetting value]; |
107 _blockPopupsItem.get().accessibilityIdentifier = | 108 _blockPopupsItem.accessibilityIdentifier = @"blockPopupsContentView_switch"; |
108 @"blockPopupsContentView_switch"; | |
109 [model addItem:_blockPopupsItem | 109 [model addItem:_blockPopupsItem |
110 toSectionWithIdentifier:SectionIdentifierMainSwitch]; | 110 toSectionWithIdentifier:SectionIdentifierMainSwitch]; |
111 | 111 |
112 if ([self popupsCurrentlyBlocked] && _exceptions.GetSize()) { | 112 if ([self popupsCurrentlyBlocked] && _exceptions.GetSize()) { |
113 [self populateExceptionsItems]; | 113 [self populateExceptionsItems]; |
114 } | 114 } |
115 } | 115 } |
116 | 116 |
117 - (BOOL)shouldShowEditButton { | 117 - (BOOL)shouldShowEditButton { |
118 return [self popupsCurrentlyBlocked]; | 118 return [self popupsCurrentlyBlocked]; |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
180 } | 180 } |
181 | 181 |
182 - (void)collectionView:(UICollectionView*)collectionView | 182 - (void)collectionView:(UICollectionView*)collectionView |
183 didDeleteItemsAtIndexPaths:(NSArray*)indexPaths { | 183 didDeleteItemsAtIndexPaths:(NSArray*)indexPaths { |
184 // The only editable section is the block popups exceptions section. | 184 // The only editable section is the block popups exceptions section. |
185 if ([self.collectionViewModel | 185 if ([self.collectionViewModel |
186 hasSectionForSectionIdentifier:SectionIdentifierExceptions]) { | 186 hasSectionForSectionIdentifier:SectionIdentifierExceptions]) { |
187 NSInteger exceptionsSectionIndex = [self.collectionViewModel | 187 NSInteger exceptionsSectionIndex = [self.collectionViewModel |
188 sectionForSectionIdentifier:SectionIdentifierExceptions]; | 188 sectionForSectionIdentifier:SectionIdentifierExceptions]; |
189 if ([collectionView numberOfItemsInSection:exceptionsSectionIndex] == 0) { | 189 if ([collectionView numberOfItemsInSection:exceptionsSectionIndex] == 0) { |
190 base::WeakNSObject<BlockPopupsCollectionViewController> weakSelf(self); | 190 __weak BlockPopupsCollectionViewController* weakSelf = self; |
191 [self.collectionView performBatchUpdates:^{ | 191 [self.collectionView performBatchUpdates:^{ |
192 base::scoped_nsobject<BlockPopupsCollectionViewController> strongSelf( | 192 BlockPopupsCollectionViewController* strongSelf = weakSelf; |
193 [weakSelf retain]); | |
194 if (!strongSelf) { | 193 if (!strongSelf) { |
195 return; | 194 return; |
196 } | 195 } |
197 NSInteger section = [strongSelf.get().collectionViewModel | 196 NSInteger section = [strongSelf.collectionViewModel |
198 sectionForSectionIdentifier:SectionIdentifierExceptions]; | 197 sectionForSectionIdentifier:SectionIdentifierExceptions]; |
199 [strongSelf.get().collectionViewModel | 198 [strongSelf.collectionViewModel |
200 removeSectionWithIdentifier:SectionIdentifierExceptions]; | 199 removeSectionWithIdentifier:SectionIdentifierExceptions]; |
201 [strongSelf.get().collectionView | 200 [strongSelf.collectionView |
202 deleteSections:[NSIndexSet indexSetWithIndex:section]]; | 201 deleteSections:[NSIndexSet indexSetWithIndex:section]]; |
203 } | 202 } |
204 completion:nil]; | 203 completion:nil]; |
205 } | 204 } |
206 } | 205 } |
207 } | 206 } |
208 | 207 |
209 #pragma mark MDCCollectionViewStylingDelegate | 208 #pragma mark MDCCollectionViewStylingDelegate |
210 | 209 |
211 - (BOOL)collectionView:(UICollectionView*)collectionView | 210 - (BOOL)collectionView:(UICollectionView*)collectionView |
212 hidesInkViewAtIndexPath:(NSIndexPath*)indexPath { | 211 hidesInkViewAtIndexPath:(NSIndexPath*)indexPath { |
213 NSInteger type = [self.collectionViewModel itemTypeForIndexPath:indexPath]; | 212 NSInteger type = [self.collectionViewModel itemTypeForIndexPath:indexPath]; |
214 switch (type) { | 213 switch (type) { |
215 case ItemTypeMainSwitch: | 214 case ItemTypeMainSwitch: |
216 return YES; | 215 return YES; |
217 default: | 216 default: |
218 return NO; | 217 return NO; |
219 } | 218 } |
220 } | 219 } |
221 | 220 |
222 #pragma mark - BooleanObserver | 221 #pragma mark - BooleanObserver |
223 | 222 |
224 - (void)booleanDidChange:(id<ObservableBoolean>)observableBoolean { | 223 - (void)booleanDidChange:(id<ObservableBoolean>)observableBoolean { |
225 DCHECK_EQ(observableBoolean, _disablePopupsSetting.get()); | 224 DCHECK_EQ(observableBoolean, _disablePopupsSetting); |
226 | 225 |
227 // Update the item. | 226 // Update the item. |
228 _blockPopupsItem.get().on = [_disablePopupsSetting value]; | 227 _blockPopupsItem.on = [_disablePopupsSetting value]; |
229 | 228 |
230 // Update the cell. | 229 // Update the cell. |
231 [self reconfigureCellsForItems:@[ _blockPopupsItem ] | 230 [self reconfigureCellsForItems:@[ _blockPopupsItem ] |
232 inSectionWithIdentifier:SectionIdentifierMainSwitch]; | 231 inSectionWithIdentifier:SectionIdentifierMainSwitch]; |
233 | 232 |
234 // Update the rest of the UI. | 233 // Update the rest of the UI. |
235 [self.editor setEditing:NO]; | 234 [self.editor setEditing:NO]; |
236 [self updateEditButton]; | 235 [self updateEditButton]; |
237 [self layoutSections:[_disablePopupsSetting value]]; | 236 [self layoutSections:[_disablePopupsSetting value]]; |
238 } | 237 } |
239 | 238 |
240 #pragma mark - Actions | 239 #pragma mark - Actions |
241 | 240 |
242 - (void)blockPopupsSwitchChanged:(UISwitch*)switchView { | 241 - (void)blockPopupsSwitchChanged:(UISwitch*)switchView { |
243 // Update the setting. | 242 // Update the setting. |
244 [_disablePopupsSetting setValue:switchView.on]; | 243 [_disablePopupsSetting setValue:switchView.on]; |
245 | 244 |
246 // Update the item. | 245 // Update the item. |
247 _blockPopupsItem.get().on = [_disablePopupsSetting value]; | 246 _blockPopupsItem.on = [_disablePopupsSetting value]; |
248 | 247 |
249 // Update the rest of the UI. | 248 // Update the rest of the UI. |
250 [self.editor setEditing:NO]; | 249 [self.editor setEditing:NO]; |
251 [self updateEditButton]; | 250 [self updateEditButton]; |
252 [self layoutSections:switchView.on]; | 251 [self layoutSections:switchView.on]; |
253 } | 252 } |
254 | 253 |
255 #pragma mark - Private | 254 #pragma mark - Private |
256 | 255 |
257 - (BOOL)popupsCurrentlyBlocked { | 256 - (BOOL)popupsCurrentlyBlocked { |
(...skipping 29 matching lines...) Expand all Loading... |
287 LOG(ERROR) << "Secondary content settings patterns are not " | 286 LOG(ERROR) << "Secondary content settings patterns are not " |
288 << "supported by the content settings UI"; | 287 << "supported by the content settings UI"; |
289 } | 288 } |
290 } | 289 } |
291 } | 290 } |
292 | 291 |
293 - (void)populateExceptionsItems { | 292 - (void)populateExceptionsItems { |
294 CollectionViewModel* model = self.collectionViewModel; | 293 CollectionViewModel* model = self.collectionViewModel; |
295 [model addSectionWithIdentifier:SectionIdentifierExceptions]; | 294 [model addSectionWithIdentifier:SectionIdentifierExceptions]; |
296 | 295 |
297 CollectionViewTextItem* header = [ | 296 CollectionViewTextItem* header = |
298 [[CollectionViewTextItem alloc] initWithType:ItemTypeHeader] autorelease]; | 297 [[CollectionViewTextItem alloc] initWithType:ItemTypeHeader]; |
299 header.text = l10n_util::GetNSString(IDS_IOS_POPUPS_ALLOWED); | 298 header.text = l10n_util::GetNSString(IDS_IOS_POPUPS_ALLOWED); |
300 header.textColor = [[MDCPalette greyPalette] tint500]; | 299 header.textColor = [[MDCPalette greyPalette] tint500]; |
301 [model setHeader:header forSectionWithIdentifier:SectionIdentifierExceptions]; | 300 [model setHeader:header forSectionWithIdentifier:SectionIdentifierExceptions]; |
302 | 301 |
303 for (size_t i = 0; i < _exceptions.GetSize(); ++i) { | 302 for (size_t i = 0; i < _exceptions.GetSize(); ++i) { |
304 std::string allowed_url; | 303 std::string allowed_url; |
305 _exceptions.GetString(i, &allowed_url); | 304 _exceptions.GetString(i, &allowed_url); |
306 CollectionViewTextItem* item = [[[CollectionViewTextItem alloc] | 305 CollectionViewTextItem* item = |
307 initWithType:ItemTypeException] autorelease]; | 306 [[CollectionViewTextItem alloc] initWithType:ItemTypeException]; |
308 item.text = base::SysUTF8ToNSString(allowed_url); | 307 item.text = base::SysUTF8ToNSString(allowed_url); |
309 [model addItem:item toSectionWithIdentifier:SectionIdentifierExceptions]; | 308 [model addItem:item toSectionWithIdentifier:SectionIdentifierExceptions]; |
310 } | 309 } |
311 } | 310 } |
312 | 311 |
313 - (void)layoutSections:(BOOL)blockPopupsIsOn { | 312 - (void)layoutSections:(BOOL)blockPopupsIsOn { |
314 BOOL hasExceptions = _exceptions.GetSize(); | 313 BOOL hasExceptions = _exceptions.GetSize(); |
315 BOOL exceptionsListShown = [self.collectionViewModel | 314 BOOL exceptionsListShown = [self.collectionViewModel |
316 hasSectionForSectionIdentifier:SectionIdentifierExceptions]; | 315 hasSectionForSectionIdentifier:SectionIdentifierExceptions]; |
317 | 316 |
318 if (blockPopupsIsOn && !exceptionsListShown && hasExceptions) { | 317 if (blockPopupsIsOn && !exceptionsListShown && hasExceptions) { |
319 // Animate in the list of exceptions. Animation looks much better if the | 318 // Animate in the list of exceptions. Animation looks much better if the |
320 // section is added at once, rather than row-by-row as each object is added. | 319 // section is added at once, rather than row-by-row as each object is added. |
321 base::WeakNSObject<BlockPopupsCollectionViewController> weakSelf(self); | 320 __weak BlockPopupsCollectionViewController* weakSelf = self; |
322 [self.collectionView performBatchUpdates:^{ | 321 [self.collectionView performBatchUpdates:^{ |
323 base::scoped_nsobject<BlockPopupsCollectionViewController> strongSelf( | 322 BlockPopupsCollectionViewController* strongSelf = weakSelf; |
324 [weakSelf retain]); | |
325 if (!strongSelf) | 323 if (!strongSelf) |
326 return; | 324 return; |
327 [strongSelf populateExceptionsItems]; | 325 [strongSelf populateExceptionsItems]; |
328 NSUInteger index = [[strongSelf collectionViewModel] | 326 NSUInteger index = [[strongSelf collectionViewModel] |
329 sectionForSectionIdentifier:SectionIdentifierExceptions]; | 327 sectionForSectionIdentifier:SectionIdentifierExceptions]; |
330 [[strongSelf collectionView] | 328 [[strongSelf collectionView] |
331 insertSections:[NSIndexSet indexSetWithIndex:index]]; | 329 insertSections:[NSIndexSet indexSetWithIndex:index]]; |
332 } | 330 } |
333 completion:nil]; | 331 completion:nil]; |
334 } else if (!blockPopupsIsOn && exceptionsListShown) { | 332 } else if (!blockPopupsIsOn && exceptionsListShown) { |
335 // Make sure the exception section is not shown. | 333 // Make sure the exception section is not shown. |
336 base::WeakNSObject<BlockPopupsCollectionViewController> weakSelf(self); | 334 __weak BlockPopupsCollectionViewController* weakSelf = self; |
337 [self.collectionView performBatchUpdates:^{ | 335 [self.collectionView performBatchUpdates:^{ |
338 base::scoped_nsobject<BlockPopupsCollectionViewController> strongSelf( | 336 BlockPopupsCollectionViewController* strongSelf = weakSelf; |
339 [weakSelf retain]); | |
340 if (!strongSelf) | 337 if (!strongSelf) |
341 return; | 338 return; |
342 NSUInteger index = [[strongSelf collectionViewModel] | 339 NSUInteger index = [[strongSelf collectionViewModel] |
343 sectionForSectionIdentifier:SectionIdentifierExceptions]; | 340 sectionForSectionIdentifier:SectionIdentifierExceptions]; |
344 [[strongSelf collectionViewModel] | 341 [[strongSelf collectionViewModel] |
345 removeSectionWithIdentifier:SectionIdentifierExceptions]; | 342 removeSectionWithIdentifier:SectionIdentifierExceptions]; |
346 [[strongSelf collectionView] | 343 [[strongSelf collectionView] |
347 deleteSections:[NSIndexSet indexSetWithIndex:index]]; | 344 deleteSections:[NSIndexSet indexSetWithIndex:index]]; |
348 } | 345 } |
349 completion:nil]; | 346 completion:nil]; |
350 } | 347 } |
351 } | 348 } |
352 | 349 |
353 @end | 350 @end |
OLD | NEW |