blob: bbfcd54b23fc98c53ccaae590eda511562075420 [file] [log] [blame]
Piotr Pawliczeke8650ea2019-08-10 20:14:07 -07001// Copyright 2019 The Chromium OS 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 "print_tools/ipp_in_json.h"
6
7#include <memory>
8#include <utility>
9
10#include <base/json/json_writer.h>
11#include <base/macros.h>
12#include <base/values.h>
13
14namespace {
15
Piotr Pawliczek70ef9a32019-12-03 12:16:16 -080016std::unique_ptr<base::DictionaryValue> SaveAsJson(const ipp::Collection* coll);
Piotr Pawliczeke8650ea2019-08-10 20:14:07 -070017
18// It saves a single value (at given index) from the attribute as JSON
19// structure. The parameter "attr" cannot be nullptr, "index" must be correct.
Piotr Pawliczek70ef9a32019-12-03 12:16:16 -080020std::unique_ptr<base::Value> SaveAsJson(const ipp::Attribute* attr,
21 unsigned index) {
Piotr Pawliczeke8650ea2019-08-10 20:14:07 -070022 CHECK(attr != nullptr);
23 CHECK(index < attr->GetSize());
24 using AttrType = ipp::AttrType;
25 switch (attr->GetType()) {
26 case AttrType::integer: {
27 int vi;
28 attr->GetValue(&vi, index);
29 return std::make_unique<base::Value>(vi);
30 }
31 case AttrType::boolean: {
32 int vb;
33 attr->GetValue(&vb, index);
34 return std::make_unique<base::Value>(static_cast<bool>(vb));
35 }
36 case AttrType::enum_: {
37 std::string vs;
38 attr->GetValue(&vs, index);
39 if (vs.empty()) {
40 int vi;
41 attr->GetValue(&vi, index);
42 return std::make_unique<base::Value>(vi);
43 }
44 return std::make_unique<base::Value>(vs);
45 }
46 case AttrType::collection:
47 return SaveAsJson(attr->GetCollection(index));
48 case AttrType::text:
49 case AttrType::name: {
50 ipp::StringWithLanguage vs;
51 attr->GetValue(&vs, index);
52 if (vs.language.empty())
53 return std::make_unique<base::Value>(vs.value);
54 std::unique_ptr<base::DictionaryValue> obj(new base::DictionaryValue);
55 obj->SetString("value", vs.value);
56 obj->SetString("language", vs.language);
57 return obj;
58 }
59 case AttrType::dateTime:
60 case AttrType::resolution:
61 case AttrType::rangeOfInteger:
62 case AttrType::octetString:
63 case AttrType::keyword:
64 case AttrType::uri:
65 case AttrType::uriScheme:
66 case AttrType::charset:
67 case AttrType::naturalLanguage:
68 case AttrType::mimeMediaType: {
69 std::string vs;
70 attr->GetValue(&vs, index);
71 return std::make_unique<base::Value>(vs);
72 }
73 }
74 return std::make_unique<base::Value>(); // not reachable
75}
76
77// It saves all attribute's values as JSON structure.
78// The parameter "attr" cannot be nullptr.
Piotr Pawliczek70ef9a32019-12-03 12:16:16 -080079std::unique_ptr<base::Value> SaveAsJson(const ipp::Attribute* attr) {
Piotr Pawliczeke8650ea2019-08-10 20:14:07 -070080 CHECK(attr != nullptr);
81 if (attr->IsASet()) {
82 auto arr = std::make_unique<base::ListValue>();
83 const unsigned size = attr->GetSize();
84 for (unsigned i = 0; i < size; ++i)
85 arr->Append(SaveAsJson(attr, i));
86 return arr;
87 } else {
88 return SaveAsJson(attr, 0);
89 }
90}
91
92// It saves a given Collection as JSON object.
93// The parameter "coll" cannot be nullptr.
Piotr Pawliczek70ef9a32019-12-03 12:16:16 -080094std::unique_ptr<base::DictionaryValue> SaveAsJson(const ipp::Collection* coll) {
Piotr Pawliczeke8650ea2019-08-10 20:14:07 -070095 CHECK(coll != nullptr);
96 auto obj = std::make_unique<base::DictionaryValue>();
Piotr Pawliczek70ef9a32019-12-03 12:16:16 -080097 std::vector<const ipp::Attribute*> attrs = coll->GetAllAttributes();
Piotr Pawliczeke8650ea2019-08-10 20:14:07 -070098
99 for (auto a : attrs) {
100 auto state = a->GetState();
101 if (state == ipp::AttrState::unset)
102 continue;
103
104 if (state == ipp::AttrState::set) {
105 auto obj2 = std::make_unique<base::DictionaryValue>();
106 obj2->SetString("type", ToString(a->GetType()));
107 obj2->Set("value", SaveAsJson(a));
108 obj->Set(a->GetName(), std::move(obj2));
109 } else {
110 obj->SetString(a->GetName(), ToString(state));
111 }
112 }
113
114 return obj;
115}
116
117// It saves all groups from given Package as JSON object.
118// The parameter "pkg" cannot be nullptr.
Piotr Pawliczek70ef9a32019-12-03 12:16:16 -0800119std::unique_ptr<base::DictionaryValue> SaveAsJson(const ipp::Package* pkg) {
Piotr Pawliczeke8650ea2019-08-10 20:14:07 -0700120 CHECK(pkg != nullptr);
121 auto obj = std::make_unique<base::DictionaryValue>();
Piotr Pawliczek70ef9a32019-12-03 12:16:16 -0800122 std::vector<const ipp::Group*> groups = pkg->GetAllGroups();
Piotr Pawliczeke8650ea2019-08-10 20:14:07 -0700123
124 for (auto g : groups) {
125 if (g->IsASet()) {
126 auto arr = std::make_unique<base::ListValue>();
127 const unsigned size = g->GetSize();
128 for (unsigned i = 0; i < size; ++i)
129 arr->Append(SaveAsJson(g->GetCollection(i)));
130
131 obj->Set(ToString(g->GetName()), std::move(arr));
132 } else {
133 obj->Set(ToString(g->GetName()), SaveAsJson(g->GetCollection()));
134 }
135 }
136
137 return obj;
138}
139
140// Saves given logs as JSON array.
141std::unique_ptr<base::ListValue> SaveAsJson(const std::vector<ipp::Log>& log) {
142 auto arr = std::make_unique<base::ListValue>();
143 for (const auto& l : log) {
144 auto obj = std::make_unique<base::DictionaryValue>();
145 obj->SetString("message", l.message);
146 if (!l.frame_context.empty())
147 obj->SetString("frame_context", l.frame_context);
148 if (!l.parser_context.empty())
149 obj->SetString("parser_context", l.parser_context);
150 arr->Append(std::move(obj));
151 }
152 return arr;
153}
154
155} // namespace
156
Piotr Pawliczek70ef9a32019-12-03 12:16:16 -0800157bool ConvertToJson(const ipp::Response& response,
Piotr Pawliczeke8650ea2019-08-10 20:14:07 -0700158 const std::vector<ipp::Log>& log,
159 bool compressed_json,
160 std::string* json) {
161 // Build structure.
162 auto doc = std::make_unique<base::DictionaryValue>();
163 doc->SetString("status", ipp::ToString(response.StatusCode()));
164 if (!log.empty()) {
165 doc->Set("parsing_logs", SaveAsJson(log));
166 }
167 doc->Set("response", SaveAsJson(&response));
168 // Convert to JSON.
169 bool result;
170 if (compressed_json) {
171 result = base::JSONWriter::Write(*doc, json);
172 } else {
173 const int options = base::JSONWriter::OPTIONS_PRETTY_PRINT;
174 result = base::JSONWriter::WriteWithOptions(*doc, options, json);
175 }
176 return result;
177}