1a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
2a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// found in the LICENSE file.
4a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
5a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "components/policy/core/common/mac_util.h"
6a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
7a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include <string>
8a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
9a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/mac/foundation_util.h"
10a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/strings/sys_string_conversions.h"
11a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/values.h"
12a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
13a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)using base::mac::CFCast;
14a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
15a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)namespace policy {
16a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
17a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)namespace {
18a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
19a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Callback function for CFDictionaryApplyFunction. |key| and |value| are an
20a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// entry of the CFDictionary that should be converted into an equivalent entry
21a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// in the DictionaryValue in |context|.
22a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void DictionaryEntryToValue(const void* key, const void* value, void* context) {
23a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (CFStringRef cf_key = CFCast<CFStringRef>(key)) {
24a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    scoped_ptr<base::Value> converted =
25a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        PropertyToValue(static_cast<CFPropertyListRef>(value));
26a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (converted) {
27a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      const std::string string = base::SysCFStringRefToUTF8(cf_key);
28a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      static_cast<base::DictionaryValue*>(context)->Set(
29a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          string, converted.release());
30a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    }
31a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
32a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
33a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
34a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Callback function for CFArrayApplyFunction. |value| is an entry of the
35a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// CFArray that should be converted into an equivalent entry in the ListValue
36a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// in |context|.
37a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void ArrayEntryToValue(const void* value, void* context) {
38a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  scoped_ptr<base::Value> converted =
39a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      PropertyToValue(static_cast<CFPropertyListRef>(value));
40a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (converted)
41a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    static_cast<base::ListValue *>(context)->Append(converted.release());
42a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
43a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
44a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}  // namespace
45a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
46a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)scoped_ptr<base::Value> PropertyToValue(CFPropertyListRef property) {
47a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (CFCast<CFNullRef>(property))
48a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return scoped_ptr<base::Value>(base::Value::CreateNullValue());
49a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
50a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (CFBooleanRef boolean = CFCast<CFBooleanRef>(property)) {
51116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return scoped_ptr<base::Value>(new base::FundamentalValue(
52116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        static_cast<bool>(CFBooleanGetValue(boolean))));
53a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
54a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
55a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (CFNumberRef number = CFCast<CFNumberRef>(property)) {
56a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // CFNumberGetValue() converts values implicitly when the conversion is not
57a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // lossy. Check the type before trying to convert.
58a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (CFNumberIsFloatType(number)) {
59a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      double double_value = 0.0;
60a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      if (CFNumberGetValue(number, kCFNumberDoubleType, &double_value)) {
61a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        return scoped_ptr<base::Value>(
625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            new base::FundamentalValue(double_value));
63a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      }
64a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    } else {
65a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      int int_value = 0;
66a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      if (CFNumberGetValue(number, kCFNumberIntType, &int_value)) {
67116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        return scoped_ptr<base::Value>(new base::FundamentalValue(int_value));
68a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      }
69a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    }
70a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
71a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
72a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (CFStringRef string = CFCast<CFStringRef>(property)) {
73a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return scoped_ptr<base::Value>(
745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        new base::StringValue(base::SysCFStringRefToUTF8(string)));
75a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
76a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
77a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (CFDictionaryRef dict = CFCast<CFDictionaryRef>(property)) {
78a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    scoped_ptr<base::DictionaryValue> dict_value(new base::DictionaryValue());
79a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    CFDictionaryApplyFunction(dict, DictionaryEntryToValue, dict_value.get());
80a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return dict_value.PassAs<base::Value>();
81a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
82a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
83a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (CFArrayRef array = CFCast<CFArrayRef>(property)) {
84a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    scoped_ptr<base::ListValue> list_value(new base::ListValue());
85a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    CFArrayApplyFunction(array,
86a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                         CFRangeMake(0, CFArrayGetCount(array)),
87a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                         ArrayEntryToValue,
88a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                         list_value.get());
89a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return list_value.PassAs<base::Value>();
90a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
91a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
92a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return scoped_ptr<base::Value>();
93a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
94a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
95a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}  // namespace policy
96