Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 #include "components/policy/core/common/policy_loader_ios.h" | 5 #include "components/policy/core/common/policy_loader_ios.h" |
| 6 | 6 |
| 7 #import <Foundation/Foundation.h> | 7 #import <Foundation/Foundation.h> |
| 8 #import <UIKit/UIKit.h> | 8 #import <UIKit/UIKit.h> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| 11 #include "base/location.h" | 11 #include "base/location.h" |
| 12 #include "base/logging.h" | 12 #include "base/logging.h" |
| 13 #include "base/mac/scoped_nsobject.h" | |
| 13 #include "base/sequenced_task_runner.h" | 14 #include "base/sequenced_task_runner.h" |
| 14 #include "components/policy/core/common/mac_util.h" | 15 #include "components/policy/core/common/mac_util.h" |
| 15 #include "components/policy/core/common/policy_bundle.h" | 16 #include "components/policy/core/common/policy_bundle.h" |
| 16 #include "components/policy/core/common/policy_map.h" | 17 #include "components/policy/core/common/policy_map.h" |
| 17 #include "components/policy/core/common/policy_namespace.h" | 18 #include "components/policy/core/common/policy_namespace.h" |
| 18 #include "policy/policy_constants.h" | 19 #include "policy/policy_constants.h" |
| 19 | 20 |
| 20 // This policy loader loads a managed app configuration from the NSUserDefaults. | 21 // This policy loader loads a managed app configuration from the NSUserDefaults. |
| 21 // For example code from Apple see: | 22 // For example code from Apple see: |
| 22 // https://developer.apple.com/library/ios/samplecode/sc2279/Introduction/Intro. html | 23 // https://developer.apple.com/library/ios/samplecode/sc2279/Introduction/Intro. html |
| 23 // For an introduction to the API see session 301 from WWDC 2013, | 24 // For an introduction to the API see session 301 from WWDC 2013, |
| 24 // "Extending Your Apps for Enterprise and Education Use": | 25 // "Extending Your Apps for Enterprise and Education Use": |
| 25 // https://developer.apple.com/videos/wwdc/2013/?id=301 | 26 // https://developer.apple.com/videos/wwdc/2013/?id=301 |
| 26 | 27 |
| 27 namespace { | 28 namespace { |
| 28 | 29 |
| 29 // Key in the NSUserDefaults that contains the managed app configuration. | 30 // Key in the NSUserDefaults that contains the managed app configuration. |
| 30 NSString* const kConfigurationKey = @"com.apple.configuration.managed"; | 31 NSString* const kConfigurationKey = @"com.apple.configuration.managed"; |
| 31 | 32 |
| 32 // Key in the managed app configuration that contains the Chrome policy. | 33 // Key in the managed app configuration that contains the Chrome policy. |
| 33 NSString* const kChromePolicyKey = @"ChromePolicy"; | 34 NSString* const kChromePolicyKey = @"ChromePolicy"; |
| 34 | 35 |
| 36 // Key in the managed app configuration that contains the encoded Chrome policy. | |
| 37 // This is a serialized Property List, encoded in base 64. | |
| 38 NSString* const kEncodedChromePolicyKey = @"EncodedChromePolicy"; | |
| 39 | |
| 35 } // namespace | 40 } // namespace |
| 36 | 41 |
| 37 // Helper that observes notifications for NSUserDefaults and triggers an update | 42 // Helper that observes notifications for NSUserDefaults and triggers an update |
| 38 // at the loader on the right thread. | 43 // at the loader on the right thread. |
| 39 @interface PolicyNotificationObserver : NSObject { | 44 @interface PolicyNotificationObserver : NSObject { |
| 40 base::Closure callback_; | 45 base::Closure callback_; |
| 41 scoped_refptr<base::SequencedTaskRunner> taskRunner_; | 46 scoped_refptr<base::SequencedTaskRunner> taskRunner_; |
| 42 } | 47 } |
| 43 | 48 |
| 44 // Designated initializer. |callback| will be posted to |taskRunner| whenever | 49 // Designated initializer. |callback| will be posted to |taskRunner| whenever |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 100 notification_observer_.reset( | 105 notification_observer_.reset( |
| 101 [[PolicyNotificationObserver alloc] initWithCallback:callback | 106 [[PolicyNotificationObserver alloc] initWithCallback:callback |
| 102 taskRunner:task_runner()]); | 107 taskRunner:task_runner()]); |
| 103 } | 108 } |
| 104 | 109 |
| 105 scoped_ptr<PolicyBundle> PolicyLoaderIOS::Load() { | 110 scoped_ptr<PolicyBundle> PolicyLoaderIOS::Load() { |
| 106 scoped_ptr<PolicyBundle> bundle(new PolicyBundle()); | 111 scoped_ptr<PolicyBundle> bundle(new PolicyBundle()); |
| 107 NSDictionary* configuration = [[NSUserDefaults standardUserDefaults] | 112 NSDictionary* configuration = [[NSUserDefaults standardUserDefaults] |
| 108 dictionaryForKey:kConfigurationKey]; | 113 dictionaryForKey:kConfigurationKey]; |
| 109 id chromePolicy = configuration[kChromePolicyKey]; | 114 id chromePolicy = configuration[kChromePolicyKey]; |
| 115 id encodedChromePolicy = configuration[kEncodedChromePolicyKey]; | |
|
dconnelly
2014/03/27 13:14:19
I think a warning on !(chromePolicy ^ encodedChrom
Joao da Silva
2014/03/27 14:05:08
Added a warning on chromePolicy && encodedChromePo
| |
| 116 | |
| 110 if (chromePolicy && [chromePolicy isKindOfClass:[NSDictionary class]]) { | 117 if (chromePolicy && [chromePolicy isKindOfClass:[NSDictionary class]]) { |
| 111 // NSDictionary is toll-free bridged to CFDictionaryRef, which is a | 118 LoadNSDictionaryToPolicyBundle(chromePolicy, bundle.get()); |
| 112 // CFPropertyListRef. | 119 } else if (encodedChromePolicy && |
| 113 scoped_ptr<base::Value> value = | 120 [encodedChromePolicy isKindOfClass:[NSString class]]) { |
| 114 PropertyToValue(static_cast<CFPropertyListRef>(chromePolicy)); | 121 base::scoped_nsobject<NSData> data( |
| 115 base::DictionaryValue* dict = NULL; | 122 [[NSData alloc] initWithBase64EncodedString:encodedChromePolicy |
| 116 if (value && value->GetAsDictionary(&dict)) { | 123 options:0]); |
| 117 PolicyMap& map = bundle->Get(PolicyNamespace(POLICY_DOMAIN_CHROME, "")); | 124 if (!data) { |
| 118 map.LoadFrom(dict, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE); | 125 NSLog(@"Invalid Base64 encoding of EncodedChromePolicy"); |
| 126 } else { | |
| 127 NSError* error = nil; | |
| 128 NSDictionary* properties = [NSPropertyListSerialization | |
| 129 propertyListWithData:data.get() | |
| 130 options:NSPropertyListImmutable | |
| 131 format:NULL | |
| 132 error:&error]; | |
| 133 if (!properties || error) { | |
| 134 NSLog(@"Invalid property list in EncodedChromePolicy: %@", error); | |
|
dconnelly
2014/03/27 13:14:19
Does !properties imply !!error? If not, maybe a di
Joao da Silva
2014/03/27 14:05:08
Done.
| |
| 135 } else if (![properties isKindOfClass:[NSDictionary class]]) { | |
| 136 NSLog(@"Invalid property list in EncodedChromePolicy: expected an " | |
| 137 "NSDictionary but found %@", [properties class]); | |
| 138 } else { | |
| 139 LoadNSDictionaryToPolicyBundle(properties, bundle.get()); | |
| 140 } | |
| 119 } | 141 } |
| 120 } | 142 } |
| 121 | 143 |
| 122 return bundle.Pass(); | 144 return bundle.Pass(); |
| 123 } | 145 } |
| 124 | 146 |
| 125 base::Time PolicyLoaderIOS::LastModificationTime() { | 147 base::Time PolicyLoaderIOS::LastModificationTime() { |
| 126 return last_notification_time_; | 148 return last_notification_time_; |
| 127 } | 149 } |
| 128 | 150 |
| 129 void PolicyLoaderIOS::UserDefaultsChanged() { | 151 void PolicyLoaderIOS::UserDefaultsChanged() { |
| 130 // The base class coalesces multiple Reload() calls into a single Load() if | 152 // The base class coalesces multiple Reload() calls into a single Load() if |
| 131 // the LastModificationTime() has a small delta between Reload() calls. | 153 // the LastModificationTime() has a small delta between Reload() calls. |
| 132 // This coalesces the multiple notifications sent during startup into a single | 154 // This coalesces the multiple notifications sent during startup into a single |
| 133 // Load() call. | 155 // Load() call. |
| 134 last_notification_time_ = base::Time::Now(); | 156 last_notification_time_ = base::Time::Now(); |
| 135 Reload(false); | 157 Reload(false); |
| 136 } | 158 } |
| 137 | 159 |
| 160 // static | |
| 161 void PolicyLoaderIOS::LoadNSDictionaryToPolicyBundle(NSDictionary* dictionary, | |
| 162 PolicyBundle* bundle) { | |
| 163 // NSDictionary is toll-free bridged to CFDictionaryRef, which is a | |
| 164 // CFPropertyListRef. | |
| 165 scoped_ptr<base::Value> value = | |
| 166 PropertyToValue(static_cast<CFPropertyListRef>(dictionary)); | |
| 167 base::DictionaryValue* dict = NULL; | |
| 168 if (value && value->GetAsDictionary(&dict)) { | |
| 169 PolicyMap& map = bundle->Get(PolicyNamespace(POLICY_DOMAIN_CHROME, "")); | |
| 170 map.LoadFrom(dict, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE); | |
| 171 } | |
| 172 } | |
| 173 | |
| 138 } // namespace policy | 174 } // namespace policy |
| OLD | NEW |