1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5#include "nsMacPreferencesReader.h"
6
7#include "js/JSON.h"
8#include "js/RootingAPI.h"
9#include "js/Value.h"
10#include "JSONWriter.h"
11
12NS_IMPL_ISUPPORTS(nsMacPreferencesReader, nsIMacPreferencesReader)
13
14using namespace mozilla;
15
16struct StringWriteFunc : public JSONWriteFunc {
17  nsAString& mString;
18  explicit StringWriteFunc(nsAString& aStr) : mString(aStr) {}
19  void Write(const Span<const char>& aStr) override {
20    mString.Append(NS_ConvertUTF8toUTF16(aStr.data(), aStr.size()));
21  }
22};
23
24static void EvaluateDict(JSONWriter* aWriter, NSDictionary<NSString*, id>* aDict);
25
26static void EvaluateArray(JSONWriter* aWriter, NSArray* aArray) {
27  for (id elem in aArray) {
28    if ([elem isKindOfClass:[NSString class]]) {
29      aWriter->StringElement(MakeStringSpan([elem UTF8String]));
30    } else if ([elem isKindOfClass:[NSNumber class]]) {
31      aWriter->IntElement([elem longLongValue]);
32    } else if ([elem isKindOfClass:[NSArray class]]) {
33      aWriter->StartArrayElement();
34      EvaluateArray(aWriter, elem);
35      aWriter->EndArray();
36    } else if ([elem isKindOfClass:[NSDictionary class]]) {
37      aWriter->StartObjectElement();
38      EvaluateDict(aWriter, elem);
39      aWriter->EndObject();
40    }
41  }
42}
43
44static void EvaluateDict(JSONWriter* aWriter, NSDictionary<NSString*, id>* aDict) {
45  for (NSString* key in aDict) {
46    id value = aDict[key];
47    if ([value isKindOfClass:[NSString class]]) {
48      aWriter->StringProperty(MakeStringSpan([key UTF8String]), MakeStringSpan([value UTF8String]));
49    } else if ([value isKindOfClass:[NSNumber class]]) {
50      aWriter->IntProperty(MakeStringSpan([key UTF8String]), [value longLongValue]);
51    } else if ([value isKindOfClass:[NSArray class]]) {
52      aWriter->StartArrayProperty(MakeStringSpan([key UTF8String]));
53      EvaluateArray(aWriter, value);
54      aWriter->EndArray();
55    } else if ([value isKindOfClass:[NSDictionary class]]) {
56      aWriter->StartObjectProperty(MakeStringSpan([key UTF8String]));
57      EvaluateDict(aWriter, value);
58      aWriter->EndObject();
59    }
60  }
61}
62
63NS_IMETHODIMP
64nsMacPreferencesReader::PoliciesEnabled(bool* aPoliciesEnabled) {
65  NSString* policiesEnabledStr = [NSString stringWithUTF8String:ENTERPRISE_POLICIES_ENABLED_KEY];
66  *aPoliciesEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:policiesEnabledStr] == YES;
67  return NS_OK;
68}
69
70NS_IMETHODIMP
71nsMacPreferencesReader::ReadPreferences(JSContext* aCx, JS::MutableHandle<JS::Value> aResult) {
72  nsAutoString jsonStr;
73  JSONWriter w(MakeUnique<StringWriteFunc>(jsonStr));
74  w.Start();
75  EvaluateDict(&w, [[NSUserDefaults standardUserDefaults] dictionaryRepresentation]);
76  w.End();
77
78  auto json = static_cast<const char16_t*>(jsonStr.get());
79
80  JS::RootedValue val(aCx);
81  MOZ_ALWAYS_TRUE(JS_ParseJSON(aCx, json, jsonStr.Length(), &val));
82
83  aResult.set(val);
84  return NS_OK;
85}
86