From 8c912b533f434aa8509495bf0dd6e2dd177d0fce Mon Sep 17 00:00:00 2001 From: robliao Date: Mon, 21 Mar 2016 14:34:15 -0700 Subject: Refactor JSONValueConverter Out of DisplayLayout Separate the JSON processing code out of DisplayLayout in preparing to move to ui/gfx since ui/gfx has no JSON dependency. BUG=595498 Review URL: https://codereview.chromium.org/1808253004 Cr-Commit-Position: refs/heads/master@{#382398} --- ash/display/json_converter.cc | 197 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 197 insertions(+) create mode 100644 ash/display/json_converter.cc (limited to 'ash/display/json_converter.cc') diff --git a/ash/display/json_converter.cc b/ash/display/json_converter.cc new file mode 100644 index 0000000..91017b6 --- /dev/null +++ b/ash/display/json_converter.cc @@ -0,0 +1,197 @@ +// Copyright 2016 The Chromium 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 "ash/display/json_converter.h" + +#include + +#include "ash/display/display_layout.h" +#include "ash/display/display_pref_util.h" +#include "base/logging.h" +#include "base/memory/scoped_vector.h" +#include "base/strings/string_number_conversions.h" +#include "base/values.h" + +namespace ash { + +namespace { + +// Persistent key names +const char kMirroredKey[] = "mirrored"; +const char kDefaultUnifiedKey[] = "default_unified"; +const char kPrimaryIdKey[] = "primary-id"; +const char kDisplayPlacementKey[] = "display_placement"; + +// DisplayPlacement key names +const char kPositionKey[] = "position"; +const char kOffsetKey[] = "offset"; +const char kDisplayPlacementDisplayIdKey[] = "display_id"; +const char kDisplayPlacementParentDisplayIdKey[] = "parent_display_id"; + +bool AddLegacyValuesFromValue(const base::Value& value, DisplayLayout* layout) { + const base::DictionaryValue* dict_value = nullptr; + if (!value.GetAsDictionary(&dict_value)) + return false; + int offset; + if (dict_value->GetInteger(kOffsetKey, &offset)) { + DisplayPlacement::Position position; + std::string position_str; + if (!dict_value->GetString(kPositionKey, &position_str)) + return false; + DisplayPlacement::StringToPosition(position_str, &position); + layout->placement_list.push_back(new DisplayPlacement(position, offset)); + } + return true; +} + +// Returns true if +// The key is missing - output is left unchanged +// The key matches the type - output is updated to the value. +template +bool UpdateFromDict(const base::DictionaryValue* dict_value, + const std::string& field_name, + Getter getter, + Output* output) { + const base::Value* field = nullptr; + if (!dict_value->Get(field_name, &field)) { + LOG(WARNING) << "Missing field: " << field_name; + return true; + } + + return (field->*getter)(output); +} + +// No implementation here as specialization is required. +template +bool UpdateFromDict(const base::DictionaryValue* dict_value, + const std::string& field_name, + Output* output); + +template <> +bool UpdateFromDict(const base::DictionaryValue* dict_value, + const std::string& field_name, + bool* output) { + return UpdateFromDict(dict_value, field_name, &base::Value::GetAsBoolean, + output); +} + +template <> +bool UpdateFromDict(const base::DictionaryValue* dict_value, + const std::string& field_name, + int* output) { + return UpdateFromDict(dict_value, field_name, &base::Value::GetAsInteger, + output); +} + +template <> +bool UpdateFromDict(const base::DictionaryValue* dict_value, + const std::string& field_name, + DisplayPlacement::Position* output) { + bool (base::Value::*getter)(std::string*) const = &base::Value::GetAsString; + std::string value; + if (!UpdateFromDict(dict_value, field_name, getter, &value)) + return false; + + return value.empty() ? true + : DisplayPlacement::StringToPosition(value, output); +} + +template <> +bool UpdateFromDict(const base::DictionaryValue* dict_value, + const std::string& field_name, + int64_t* output) { + bool (base::Value::*getter)(std::string*) const = &base::Value::GetAsString; + std::string value; + if (!UpdateFromDict(dict_value, field_name, getter, &value)) + return false; + + return value.empty() ? true : base::StringToInt64(value, output); +} + +template <> +bool UpdateFromDict(const base::DictionaryValue* dict_value, + const std::string& field_name, + ScopedVector* output) { + bool (base::Value::*getter)(const base::ListValue**) const = + &base::Value::GetAsList; + const base::ListValue* list = nullptr; + if (!UpdateFromDict(dict_value, field_name, getter, &list)) + return false; + + if (list == nullptr) + return true; + + output->reserve(list->GetSize()); + for (const auto& list_item : *list) { + const base::DictionaryValue* item_values = nullptr; + if (!list_item->GetAsDictionary(&item_values)) + return false; + + scoped_ptr item(new DisplayPlacement); + if (!UpdateFromDict(item_values, kOffsetKey, &item->offset) || + !UpdateFromDict(item_values, kPositionKey, &item->position) || + !UpdateFromDict(item_values, kDisplayPlacementDisplayIdKey, + &item->display_id) || + !UpdateFromDict(item_values, kDisplayPlacementParentDisplayIdKey, + &item->parent_display_id)) { + return false; + } + + output->push_back(std::move(item)); + } + return true; +} + +} // namespace + +bool JsonToDisplayLayout(const base::Value& value, DisplayLayout* layout) { + layout->placement_list.clear(); + const base::DictionaryValue* dict_value = nullptr; + if (!value.GetAsDictionary(&dict_value)) + return false; + + if (!UpdateFromDict(dict_value, kMirroredKey, &layout->mirrored) || + !UpdateFromDict(dict_value, kDefaultUnifiedKey, + &layout->default_unified) || + !UpdateFromDict(dict_value, kPrimaryIdKey, &layout->primary_id)) { + return false; + } + + UpdateFromDict(dict_value, kDisplayPlacementKey, &layout->placement_list); + + if (layout->placement_list.size() != 0u) + return true; + + // For compatibility with old format. + return AddLegacyValuesFromValue(value, layout); +} + +bool DisplayLayoutToJson(const DisplayLayout& layout, base::Value* value) { + base::DictionaryValue* dict_value = nullptr; + if (!value->GetAsDictionary(&dict_value)) + return false; + + dict_value->SetBoolean(kMirroredKey, layout.mirrored); + dict_value->SetBoolean(kDefaultUnifiedKey, layout.default_unified); + dict_value->SetString(kPrimaryIdKey, base::Int64ToString(layout.primary_id)); + + scoped_ptr placement_list(new base::ListValue); + for (const auto* placement : layout.placement_list) { + scoped_ptr placement_value( + new base::DictionaryValue); + placement_value->SetString( + kPositionKey, DisplayPlacement::PositionToString(placement->position)); + placement_value->SetInteger(kOffsetKey, placement->offset); + placement_value->SetString(kDisplayPlacementDisplayIdKey, + base::Int64ToString(placement->display_id)); + placement_value->SetString( + kDisplayPlacementParentDisplayIdKey, + base::Int64ToString(placement->parent_display_id)); + placement_list->Append(std::move(placement_value)); + } + dict_value->Set(kDisplayPlacementKey, std::move(placement_list)); + return true; +} + +} // namespace ash -- cgit v1.1