| Index: ios/chrome/browser/ui/settings/utils/content_setting_backed_boolean.mm
|
| diff --git a/ios/chrome/browser/ui/settings/utils/content_setting_backed_boolean.mm b/ios/chrome/browser/ui/settings/utils/content_setting_backed_boolean.mm
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..0e17a5fbd72ded62a21bbe9cabbe03c2d54cefb9
|
| --- /dev/null
|
| +++ b/ios/chrome/browser/ui/settings/utils/content_setting_backed_boolean.mm
|
| @@ -0,0 +1,125 @@
|
| +// 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 "ios/chrome/browser/ui/settings/utils/content_setting_backed_boolean.h"
|
| +
|
| +#include "base/ios/weak_nsobject.h"
|
| +#include "base/scoped_observer.h"
|
| +#include "components/content_settings/core/browser/content_settings_details.h"
|
| +#include "components/content_settings/core/browser/content_settings_observer.h"
|
| +#include "components/content_settings/core/browser/host_content_settings_map.h"
|
| +#include "components/content_settings/core/common/content_settings.h"
|
| +#include "components/content_settings/core/common/content_settings_types.h"
|
| +
|
| +@interface ContentSettingBackedBoolean ()
|
| +
|
| +// The ID of the setting in |settingsMap|.
|
| +@property(nonatomic, readonly) ContentSettingsType settingID;
|
| +
|
| +// Whether the boolean value reflects the state of the preference that backs it,
|
| +// or its negation.
|
| +@property(nonatomic, assign, getter=isInverted) BOOL inverted;
|
| +
|
| +// Whether this object is the one modifying the content setting. Used to filter
|
| +// out changes notifications.
|
| +@property(nonatomic, assign) BOOL isModifyingContentSetting;
|
| +
|
| +@end
|
| +
|
| +namespace {
|
| +
|
| +typedef ScopedObserver<HostContentSettingsMap, content_settings::Observer>
|
| + ContentSettingsObserver;
|
| +
|
| +class ContentSettingsObserverBridge : public content_settings::Observer {
|
| + public:
|
| + explicit ContentSettingsObserverBridge(ContentSettingBackedBoolean* setting);
|
| + ~ContentSettingsObserverBridge() override;
|
| +
|
| + // content_settings::Observer implementation.
|
| + void OnContentSettingChanged(const ContentSettingsPattern& primary_pattern,
|
| + const ContentSettingsPattern& secondary_pattern,
|
| + ContentSettingsType content_type,
|
| + std::string resource_identifier) override;
|
| +
|
| + private:
|
| + ContentSettingBackedBoolean* setting_; // weak
|
| +};
|
| +
|
| +ContentSettingsObserverBridge::ContentSettingsObserverBridge(
|
| + ContentSettingBackedBoolean* setting)
|
| + : setting_(setting) {}
|
| +
|
| +ContentSettingsObserverBridge::~ContentSettingsObserverBridge() {}
|
| +
|
| +void ContentSettingsObserverBridge::OnContentSettingChanged(
|
| + const ContentSettingsPattern& primary_pattern,
|
| + const ContentSettingsPattern& secondary_pattern,
|
| + ContentSettingsType content_type,
|
| + std::string resource_identifier) {
|
| + // Ignore when it's the ContentSettingBackedBoolean that is changing the
|
| + // content setting.
|
| + if (setting_.isModifyingContentSetting) {
|
| + return;
|
| + }
|
| + const ContentSettingsDetails settings_details(
|
| + primary_pattern, secondary_pattern, content_type, resource_identifier);
|
| + ContentSettingsType settingID = settings_details.type();
|
| + // Unfortunately, because the ContentSettingsPolicyProvider doesn't publish
|
| + // the specific content setting on policy updates, we must refresh on every
|
| + // CONTENT_SETTINGS_TYPE_DEFAULT notification.
|
| + if (settingID != CONTENT_SETTINGS_TYPE_DEFAULT &&
|
| + settingID != setting_.settingID) {
|
| + return;
|
| + }
|
| + // Notify the BooleanObserver.
|
| + [setting_.observer booleanDidChange:setting_];
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +@implementation ContentSettingBackedBoolean {
|
| + ContentSettingsType settingID_;
|
| + scoped_refptr<HostContentSettingsMap> settingsMap_;
|
| + std::unique_ptr<ContentSettingsObserverBridge> adaptor_;
|
| + std::unique_ptr<ContentSettingsObserver> content_settings_observer_;
|
| +}
|
| +
|
| +@synthesize settingID = settingID_;
|
| +@synthesize observer = observer_;
|
| +@synthesize inverted = inverted_;
|
| +@synthesize isModifyingContentSetting = isModifyingContentSetting_;
|
| +
|
| +- (id)initWithHostContentSettingsMap:(HostContentSettingsMap*)settingsMap
|
| + settingID:(ContentSettingsType)settingID
|
| + inverted:(BOOL)inverted {
|
| + self = [super init];
|
| + if (self) {
|
| + settingID_ = settingID;
|
| + settingsMap_ = settingsMap;
|
| + inverted_ = inverted;
|
| + // Listen for changes to the content setting.
|
| + adaptor_.reset(new ContentSettingsObserverBridge(self));
|
| + content_settings_observer_.reset(
|
| + new ContentSettingsObserver(adaptor_.get()));
|
| + content_settings_observer_->Add(settingsMap);
|
| + }
|
| + return self;
|
| +}
|
| +
|
| +- (BOOL)value {
|
| + ContentSetting setting =
|
| + settingsMap_->GetDefaultContentSetting(settingID_, NULL);
|
| + return self.inverted ^ (setting == CONTENT_SETTING_ALLOW);
|
| +}
|
| +
|
| +- (void)setValue:(BOOL)value {
|
| + ContentSetting setting =
|
| + (self.inverted ^ value) ? CONTENT_SETTING_ALLOW : CONTENT_SETTING_BLOCK;
|
| + self.isModifyingContentSetting = YES;
|
| + settingsMap_->SetDefaultContentSetting(settingID_, setting);
|
| + self.isModifyingContentSetting = NO;
|
| +}
|
| +
|
| +@end
|
|
|