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 "ios/chrome/browser/ui/settings/utils/content_setting_backed_boolean.h" |
| 6 |
| 7 #include "base/ios/weak_nsobject.h" |
| 8 #include "base/scoped_observer.h" |
| 9 #include "components/content_settings/core/browser/content_settings_details.h" |
| 10 #include "components/content_settings/core/browser/content_settings_observer.h" |
| 11 #include "components/content_settings/core/browser/host_content_settings_map.h" |
| 12 #include "components/content_settings/core/common/content_settings.h" |
| 13 #include "components/content_settings/core/common/content_settings_types.h" |
| 14 |
| 15 @interface ContentSettingBackedBoolean () |
| 16 |
| 17 // The ID of the setting in |settingsMap|. |
| 18 @property(nonatomic, readonly) ContentSettingsType settingID; |
| 19 |
| 20 // Whether the boolean value reflects the state of the preference that backs it, |
| 21 // or its negation. |
| 22 @property(nonatomic, assign, getter=isInverted) BOOL inverted; |
| 23 |
| 24 // Whether this object is the one modifying the content setting. Used to filter |
| 25 // out changes notifications. |
| 26 @property(nonatomic, assign) BOOL isModifyingContentSetting; |
| 27 |
| 28 @end |
| 29 |
| 30 namespace { |
| 31 |
| 32 typedef ScopedObserver<HostContentSettingsMap, content_settings::Observer> |
| 33 ContentSettingsObserver; |
| 34 |
| 35 class ContentSettingsObserverBridge : public content_settings::Observer { |
| 36 public: |
| 37 explicit ContentSettingsObserverBridge(ContentSettingBackedBoolean* setting); |
| 38 ~ContentSettingsObserverBridge() override; |
| 39 |
| 40 // content_settings::Observer implementation. |
| 41 void OnContentSettingChanged(const ContentSettingsPattern& primary_pattern, |
| 42 const ContentSettingsPattern& secondary_pattern, |
| 43 ContentSettingsType content_type, |
| 44 std::string resource_identifier) override; |
| 45 |
| 46 private: |
| 47 ContentSettingBackedBoolean* setting_; // weak |
| 48 }; |
| 49 |
| 50 ContentSettingsObserverBridge::ContentSettingsObserverBridge( |
| 51 ContentSettingBackedBoolean* setting) |
| 52 : setting_(setting) {} |
| 53 |
| 54 ContentSettingsObserverBridge::~ContentSettingsObserverBridge() {} |
| 55 |
| 56 void ContentSettingsObserverBridge::OnContentSettingChanged( |
| 57 const ContentSettingsPattern& primary_pattern, |
| 58 const ContentSettingsPattern& secondary_pattern, |
| 59 ContentSettingsType content_type, |
| 60 std::string resource_identifier) { |
| 61 // Ignore when it's the ContentSettingBackedBoolean that is changing the |
| 62 // content setting. |
| 63 if (setting_.isModifyingContentSetting) { |
| 64 return; |
| 65 } |
| 66 const ContentSettingsDetails settings_details( |
| 67 primary_pattern, secondary_pattern, content_type, resource_identifier); |
| 68 ContentSettingsType settingID = settings_details.type(); |
| 69 // Unfortunately, because the ContentSettingsPolicyProvider doesn't publish |
| 70 // the specific content setting on policy updates, we must refresh on every |
| 71 // CONTENT_SETTINGS_TYPE_DEFAULT notification. |
| 72 if (settingID != CONTENT_SETTINGS_TYPE_DEFAULT && |
| 73 settingID != setting_.settingID) { |
| 74 return; |
| 75 } |
| 76 // Notify the BooleanObserver. |
| 77 [setting_.observer booleanDidChange:setting_]; |
| 78 } |
| 79 |
| 80 } // namespace |
| 81 |
| 82 @implementation ContentSettingBackedBoolean { |
| 83 ContentSettingsType settingID_; |
| 84 scoped_refptr<HostContentSettingsMap> settingsMap_; |
| 85 std::unique_ptr<ContentSettingsObserverBridge> adaptor_; |
| 86 std::unique_ptr<ContentSettingsObserver> content_settings_observer_; |
| 87 } |
| 88 |
| 89 @synthesize settingID = settingID_; |
| 90 @synthesize observer = observer_; |
| 91 @synthesize inverted = inverted_; |
| 92 @synthesize isModifyingContentSetting = isModifyingContentSetting_; |
| 93 |
| 94 - (id)initWithHostContentSettingsMap:(HostContentSettingsMap*)settingsMap |
| 95 settingID:(ContentSettingsType)settingID |
| 96 inverted:(BOOL)inverted { |
| 97 self = [super init]; |
| 98 if (self) { |
| 99 settingID_ = settingID; |
| 100 settingsMap_ = settingsMap; |
| 101 inverted_ = inverted; |
| 102 // Listen for changes to the content setting. |
| 103 adaptor_.reset(new ContentSettingsObserverBridge(self)); |
| 104 content_settings_observer_.reset( |
| 105 new ContentSettingsObserver(adaptor_.get())); |
| 106 content_settings_observer_->Add(settingsMap); |
| 107 } |
| 108 return self; |
| 109 } |
| 110 |
| 111 - (BOOL)value { |
| 112 ContentSetting setting = |
| 113 settingsMap_->GetDefaultContentSetting(settingID_, NULL); |
| 114 return self.inverted ^ (setting == CONTENT_SETTING_ALLOW); |
| 115 } |
| 116 |
| 117 - (void)setValue:(BOOL)value { |
| 118 ContentSetting setting = |
| 119 (self.inverted ^ value) ? CONTENT_SETTING_ALLOW : CONTENT_SETTING_BLOCK; |
| 120 self.isModifyingContentSetting = YES; |
| 121 settingsMap_->SetDefaultContentSetting(settingID_, setting); |
| 122 self.isModifyingContentSetting = NO; |
| 123 } |
| 124 |
| 125 @end |
OLD | NEW |