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