1// Copyright (c) 2012 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 "base/json/json_file_value_serializer.h"
6
7#include "base/files/file_util.h"
8#include "base/json/json_string_value_serializer.h"
9#include "base/logging.h"
10#include "build/build_config.h"
11
12using base::FilePath;
13
14const char JSONFileValueDeserializer::kAccessDenied[] = "Access denied.";
15const char JSONFileValueDeserializer::kCannotReadFile[] = "Can't read file.";
16const char JSONFileValueDeserializer::kFileLocked[] = "File locked.";
17const char JSONFileValueDeserializer::kNoSuchFile[] = "File doesn't exist.";
18
19JSONFileValueSerializer::JSONFileValueSerializer(
20    const base::FilePath& json_file_path)
21    : json_file_path_(json_file_path) {
22}
23
24JSONFileValueSerializer::~JSONFileValueSerializer() {
25}
26
27bool JSONFileValueSerializer::Serialize(const base::Value& root) {
28  return SerializeInternal(root, false);
29}
30
31bool JSONFileValueSerializer::SerializeAndOmitBinaryValues(
32    const base::Value& root) {
33  return SerializeInternal(root, true);
34}
35
36bool JSONFileValueSerializer::SerializeInternal(const base::Value& root,
37                                                bool omit_binary_values) {
38  std::string json_string;
39  JSONStringValueSerializer serializer(&json_string);
40  serializer.set_pretty_print(true);
41  bool result = omit_binary_values ?
42      serializer.SerializeAndOmitBinaryValues(root) :
43      serializer.Serialize(root);
44  if (!result)
45    return false;
46
47  int data_size = static_cast<int>(json_string.size());
48  if (base::WriteFile(json_file_path_, json_string.data(), data_size) !=
49      data_size)
50    return false;
51
52  return true;
53}
54
55JSONFileValueDeserializer::JSONFileValueDeserializer(
56    const base::FilePath& json_file_path)
57    : json_file_path_(json_file_path),
58      allow_trailing_comma_(false),
59      last_read_size_(0U) {
60}
61
62JSONFileValueDeserializer::~JSONFileValueDeserializer() {
63}
64
65int JSONFileValueDeserializer::ReadFileToString(std::string* json_string) {
66  DCHECK(json_string);
67  if (!base::ReadFileToString(json_file_path_, json_string)) {
68#if defined(OS_WIN)
69    int error = ::GetLastError();
70    if (error == ERROR_SHARING_VIOLATION || error == ERROR_LOCK_VIOLATION) {
71      return JSON_FILE_LOCKED;
72    } else if (error == ERROR_ACCESS_DENIED) {
73      return JSON_ACCESS_DENIED;
74    }
75#endif
76    if (!base::PathExists(json_file_path_))
77      return JSON_NO_SUCH_FILE;
78    else
79      return JSON_CANNOT_READ_FILE;
80  }
81
82  last_read_size_ = json_string->size();
83  return JSON_NO_ERROR;
84}
85
86const char* JSONFileValueDeserializer::GetErrorMessageForCode(int error_code) {
87  switch (error_code) {
88    case JSON_NO_ERROR:
89      return "";
90    case JSON_ACCESS_DENIED:
91      return kAccessDenied;
92    case JSON_CANNOT_READ_FILE:
93      return kCannotReadFile;
94    case JSON_FILE_LOCKED:
95      return kFileLocked;
96    case JSON_NO_SUCH_FILE:
97      return kNoSuchFile;
98    default:
99      NOTREACHED();
100      return "";
101  }
102}
103
104std::unique_ptr<base::Value> JSONFileValueDeserializer::Deserialize(
105    int* error_code,
106    std::string* error_str) {
107  std::string json_string;
108  int error = ReadFileToString(&json_string);
109  if (error != JSON_NO_ERROR) {
110    if (error_code)
111      *error_code = error;
112    if (error_str)
113      *error_str = GetErrorMessageForCode(error);
114    return NULL;
115  }
116
117  JSONStringValueDeserializer deserializer(json_string);
118  deserializer.set_allow_trailing_comma(allow_trailing_comma_);
119  return deserializer.Deserialize(error_code, error_str);
120}
121