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 |