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]; |
| 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 |
113 scoped_ptr<base::Value> value = | 120 if (encodedChromePolicy) |
114 PropertyToValue(static_cast<CFPropertyListRef>(chromePolicy)); | 121 NSLog(@"Ignoring EncodedChromePolicy because ChromePolicy is present."); |
115 base::DictionaryValue* dict = NULL; | 122 } else if (encodedChromePolicy && |
116 if (value && value->GetAsDictionary(&dict)) { | 123 [encodedChromePolicy isKindOfClass:[NSString class]]) { |
117 PolicyMap& map = bundle->Get(PolicyNamespace(POLICY_DOMAIN_CHROME, "")); | 124 base::scoped_nsobject<NSData> data( |
118 map.LoadFrom(dict, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE); | 125 [[NSData alloc] initWithBase64EncodedString:encodedChromePolicy |
| 126 options:0]); |
| 127 if (!data) { |
| 128 NSLog(@"Invalid Base64 encoding of EncodedChromePolicy"); |
| 129 } else { |
| 130 NSError* error = nil; |
| 131 NSDictionary* properties = [NSPropertyListSerialization |
| 132 propertyListWithData:data.get() |
| 133 options:NSPropertyListImmutable |
| 134 format:NULL |
| 135 error:&error]; |
| 136 if (error) { |
| 137 NSLog(@"Invalid property list in EncodedChromePolicy: %@", error); |
| 138 } else if (!properties) { |
| 139 NSLog(@"Failed to deserialize a valid Property List"); |
| 140 } else if (![properties isKindOfClass:[NSDictionary class]]) { |
| 141 NSLog(@"Invalid property list in EncodedChromePolicy: expected an " |
| 142 "NSDictionary but found %@", [properties class]); |
| 143 } else { |
| 144 LoadNSDictionaryToPolicyBundle(properties, bundle.get()); |
| 145 } |
119 } | 146 } |
120 } | 147 } |
121 | 148 |
122 return bundle.Pass(); | 149 return bundle.Pass(); |
123 } | 150 } |
124 | 151 |
125 base::Time PolicyLoaderIOS::LastModificationTime() { | 152 base::Time PolicyLoaderIOS::LastModificationTime() { |
126 return last_notification_time_; | 153 return last_notification_time_; |
127 } | 154 } |
128 | 155 |
129 void PolicyLoaderIOS::UserDefaultsChanged() { | 156 void PolicyLoaderIOS::UserDefaultsChanged() { |
130 // The base class coalesces multiple Reload() calls into a single Load() if | 157 // The base class coalesces multiple Reload() calls into a single Load() if |
131 // the LastModificationTime() has a small delta between Reload() calls. | 158 // the LastModificationTime() has a small delta between Reload() calls. |
132 // This coalesces the multiple notifications sent during startup into a single | 159 // This coalesces the multiple notifications sent during startup into a single |
133 // Load() call. | 160 // Load() call. |
134 last_notification_time_ = base::Time::Now(); | 161 last_notification_time_ = base::Time::Now(); |
135 Reload(false); | 162 Reload(false); |
136 } | 163 } |
137 | 164 |
| 165 // static |
| 166 void PolicyLoaderIOS::LoadNSDictionaryToPolicyBundle(NSDictionary* dictionary, |
| 167 PolicyBundle* bundle) { |
| 168 // NSDictionary is toll-free bridged to CFDictionaryRef, which is a |
| 169 // CFPropertyListRef. |
| 170 scoped_ptr<base::Value> value = |
| 171 PropertyToValue(static_cast<CFPropertyListRef>(dictionary)); |
| 172 base::DictionaryValue* dict = NULL; |
| 173 if (value && value->GetAsDictionary(&dict)) { |
| 174 PolicyMap& map = bundle->Get(PolicyNamespace(POLICY_DOMAIN_CHROME, "")); |
| 175 map.LoadFrom(dict, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE); |
| 176 } |
| 177 } |
| 178 |
138 } // namespace policy | 179 } // namespace policy |
OLD | NEW |