| // Copyright 2019 The Chromium OS Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "print_tools/ipp_in_json.h" |
| |
| #include <memory> |
| #include <utility> |
| |
| #include <base/json/json_writer.h> |
| #include <base/macros.h> |
| #include <base/values.h> |
| |
| namespace { |
| |
| std::unique_ptr<base::DictionaryValue> SaveAsJson(const ipp::Collection* coll); |
| |
| // It saves a single value (at given index) from the attribute as JSON |
| // structure. The parameter "attr" cannot be nullptr, "index" must be correct. |
| std::unique_ptr<base::Value> SaveAsJson(const ipp::Attribute* attr, |
| unsigned index) { |
| CHECK(attr != nullptr); |
| CHECK(index < attr->GetSize()); |
| using AttrType = ipp::AttrType; |
| switch (attr->GetType()) { |
| case AttrType::integer: { |
| int vi; |
| attr->GetValue(&vi, index); |
| return std::make_unique<base::Value>(vi); |
| } |
| case AttrType::boolean: { |
| int vb; |
| attr->GetValue(&vb, index); |
| return std::make_unique<base::Value>(static_cast<bool>(vb)); |
| } |
| case AttrType::enum_: { |
| std::string vs; |
| attr->GetValue(&vs, index); |
| if (vs.empty()) { |
| int vi; |
| attr->GetValue(&vi, index); |
| return std::make_unique<base::Value>(vi); |
| } |
| return std::make_unique<base::Value>(vs); |
| } |
| case AttrType::collection: |
| return SaveAsJson(attr->GetCollection(index)); |
| case AttrType::text: |
| case AttrType::name: { |
| ipp::StringWithLanguage vs; |
| attr->GetValue(&vs, index); |
| if (vs.language.empty()) |
| return std::make_unique<base::Value>(vs.value); |
| std::unique_ptr<base::DictionaryValue> obj(new base::DictionaryValue); |
| obj->SetString("value", vs.value); |
| obj->SetString("language", vs.language); |
| return obj; |
| } |
| case AttrType::dateTime: |
| case AttrType::resolution: |
| case AttrType::rangeOfInteger: |
| case AttrType::octetString: |
| case AttrType::keyword: |
| case AttrType::uri: |
| case AttrType::uriScheme: |
| case AttrType::charset: |
| case AttrType::naturalLanguage: |
| case AttrType::mimeMediaType: { |
| std::string vs; |
| attr->GetValue(&vs, index); |
| return std::make_unique<base::Value>(vs); |
| } |
| } |
| return std::make_unique<base::Value>(); // not reachable |
| } |
| |
| // It saves all attribute's values as JSON structure. |
| // The parameter "attr" cannot be nullptr. |
| std::unique_ptr<base::Value> SaveAsJson(const ipp::Attribute* attr) { |
| CHECK(attr != nullptr); |
| if (attr->IsASet()) { |
| auto arr = std::make_unique<base::ListValue>(); |
| const unsigned size = attr->GetSize(); |
| for (unsigned i = 0; i < size; ++i) |
| arr->Append(SaveAsJson(attr, i)); |
| return arr; |
| } else { |
| return SaveAsJson(attr, 0); |
| } |
| } |
| |
| // It saves a given Collection as JSON object. |
| // The parameter "coll" cannot be nullptr. |
| std::unique_ptr<base::DictionaryValue> SaveAsJson(const ipp::Collection* coll) { |
| CHECK(coll != nullptr); |
| auto obj = std::make_unique<base::DictionaryValue>(); |
| std::vector<const ipp::Attribute*> attrs = coll->GetAllAttributes(); |
| |
| for (auto a : attrs) { |
| auto state = a->GetState(); |
| if (state == ipp::AttrState::unset) |
| continue; |
| |
| if (state == ipp::AttrState::set) { |
| auto obj2 = std::make_unique<base::DictionaryValue>(); |
| obj2->SetString("type", ToString(a->GetType())); |
| obj2->Set("value", SaveAsJson(a)); |
| obj->Set(a->GetName(), std::move(obj2)); |
| } else { |
| obj->SetString(a->GetName(), ToString(state)); |
| } |
| } |
| |
| return obj; |
| } |
| |
| // It saves all groups from given Package as JSON object. |
| // The parameter "pkg" cannot be nullptr. |
| std::unique_ptr<base::DictionaryValue> SaveAsJson(const ipp::Package* pkg) { |
| CHECK(pkg != nullptr); |
| auto obj = std::make_unique<base::DictionaryValue>(); |
| std::vector<const ipp::Group*> groups = pkg->GetAllGroups(); |
| |
| for (auto g : groups) { |
| const size_t size = g->GetSize(); |
| if (size == 0) |
| continue; |
| if (g->IsASet()) { |
| auto arr = std::make_unique<base::ListValue>(); |
| for (size_t i = 0; i < size; ++i) |
| arr->Append(SaveAsJson(g->GetCollection(i))); |
| obj->Set(ToString(g->GetName()), std::move(arr)); |
| } else { |
| obj->Set(ToString(g->GetName()), SaveAsJson(g->GetCollection())); |
| } |
| } |
| |
| return obj; |
| } |
| |
| // Saves given logs as JSON array. |
| std::unique_ptr<base::ListValue> SaveAsJson(const std::vector<ipp::Log>& log) { |
| auto arr = std::make_unique<base::ListValue>(); |
| for (const auto& l : log) { |
| auto obj = std::make_unique<base::DictionaryValue>(); |
| obj->SetString("message", l.message); |
| if (!l.frame_context.empty()) |
| obj->SetString("frame_context", l.frame_context); |
| if (!l.parser_context.empty()) |
| obj->SetString("parser_context", l.parser_context); |
| arr->Append(std::move(obj)); |
| } |
| return arr; |
| } |
| |
| } // namespace |
| |
| bool ConvertToJson(const ipp::Response& response, |
| const std::vector<ipp::Log>& log, |
| bool compressed_json, |
| std::string* json) { |
| // Build structure. |
| auto doc = std::make_unique<base::DictionaryValue>(); |
| doc->SetString("status", ipp::ToString(response.StatusCode())); |
| if (!log.empty()) { |
| doc->Set("parsing_logs", SaveAsJson(log)); |
| } |
| doc->Set("response", SaveAsJson(&response)); |
| // Convert to JSON. |
| bool result; |
| if (compressed_json) { |
| result = base::JSONWriter::Write(*doc, json); |
| } else { |
| const int options = base::JSONWriter::OPTIONS_PRETTY_PRINT; |
| result = base::JSONWriter::WriteWithOptions(*doc, options, json); |
| } |
| return result; |
| } |