diff options
author | vitalybuka@chromium.org <vitalybuka@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-02-04 01:01:52 +0000 |
---|---|---|
committer | vitalybuka@chromium.org <vitalybuka@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-02-04 01:01:52 +0000 |
commit | 89b80cce73826d7fc3b7b5eb692fbf89b0cba2dd (patch) | |
tree | a2d5e58424231ee2e01b8b59af93a312c97e51cc | |
parent | 15b44822b226721f14d9b494c00f8eeaee022bfe (diff) | |
download | chromium_src-89b80cce73826d7fc3b7b5eb692fbf89b0cba2dd.zip chromium_src-89b80cce73826d7fc3b7b5eb692fbf89b0cba2dd.tar.gz chromium_src-89b80cce73826d7fc3b7b5eb692fbf89b0cba2dd.tar.bz2 |
Reading, writing of CDD and CJT JSON formats.
Printer description and print job ticket formats.
BUG=317027
Review URL: https://codereview.chromium.org/150993002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@248644 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | components/cloud_devices.gypi | 10 | ||||
-rw-r--r-- | components/cloud_devices/cloud_device_description.cc | 78 | ||||
-rw-r--r-- | components/cloud_devices/cloud_device_description.h | 57 | ||||
-rw-r--r-- | components/cloud_devices/cloud_device_description_consts.cc | 20 | ||||
-rw-r--r-- | components/cloud_devices/cloud_device_description_consts.h | 25 | ||||
-rw-r--r-- | components/cloud_devices/cloud_devices_json_consts.cc | 74 | ||||
-rw-r--r-- | components/cloud_devices/cloud_devices_json_consts.h | 84 | ||||
-rw-r--r-- | components/cloud_devices/description_items.h | 231 | ||||
-rw-r--r-- | components/cloud_devices/description_items_inl.h | 211 | ||||
-rw-r--r-- | components/cloud_devices/printer_description.cc | 729 | ||||
-rw-r--r-- | components/cloud_devices/printer_description.h | 362 | ||||
-rw-r--r-- | components/cloud_devices/printer_description_unittest.cc | 581 |
12 files changed, 2302 insertions, 160 deletions
diff --git a/components/cloud_devices.gypi b/components/cloud_devices.gypi index d0ab6a8..27adfd1 100644 --- a/components/cloud_devices.gypi +++ b/components/cloud_devices.gypi @@ -14,8 +14,14 @@ '../base/base.gyp:base', ], 'sources': [ - 'cloud_devices/cloud_devices_json_consts.cc', - 'cloud_devices/cloud_devices_json_consts.h', + 'cloud_devices/cloud_device_description.cc', + 'cloud_devices/cloud_device_description.h', + 'cloud_devices/cloud_device_description_consts.cc', + 'cloud_devices/cloud_device_description_consts.h', + 'cloud_devices/description_items.h', + 'cloud_devices/description_items_inl.h', + 'cloud_devices/printer_description.cc', + 'cloud_devices/printer_description.h', ], }, ], diff --git a/components/cloud_devices/cloud_device_description.cc b/components/cloud_devices/cloud_device_description.cc new file mode 100644 index 0000000..124bb49 --- /dev/null +++ b/components/cloud_devices/cloud_device_description.cc @@ -0,0 +1,78 @@ +// Copyright 2014 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 "components/cloud_devices/cloud_device_description.h" + +#include "base/json/json_reader.h" +#include "base/json/json_writer.h" +#include "base/logging.h" +#include "base/values.h" +#include "components/cloud_devices/cloud_device_description_consts.h" + +namespace cloud_devices { + +CloudDeviceDescription::CloudDeviceDescription() { + Reset(); +} + +CloudDeviceDescription::~CloudDeviceDescription() { +} + +void CloudDeviceDescription::Reset() { + root_.reset(new base::DictionaryValue); + root_->SetString(json::kVersion, json::kVersion10); +} + +bool CloudDeviceDescription::InitFromString(const std::string& json) { + Reset(); + + scoped_ptr<base::Value> parsed(base::JSONReader::Read(json)); + base::DictionaryValue* description = NULL; + if (!parsed || !parsed->GetAsDictionary(&description)) + return false; + root_.reset(description); + ignore_result(parsed.release()); + + std::string version; + description->GetString(json::kVersion, &version); + return version == json::kVersion10; +} + +std::string CloudDeviceDescription::ToString() const { + std::string json; + base::JSONWriter::WriteWithOptions(root_.get(), + base::JSONWriter::OPTIONS_PRETTY_PRINT, + &json); + return json; +} + +const base::DictionaryValue* CloudDeviceDescription::GetItem( + const std::string& path) const { + const base::DictionaryValue* value = NULL; + root_->GetDictionary(path, &value); + return value; +} + +base::DictionaryValue* CloudDeviceDescription::CreateItem( + const std::string& path) { + base::DictionaryValue* value = new base::DictionaryValue; + root_->Set(path, value); + return value; +} + +const base::ListValue* CloudDeviceDescription::GetListItem( + const std::string& path) const { + const base::ListValue* value = NULL; + root_->GetList(path, &value); + return value; +} + +base::ListValue* CloudDeviceDescription::CreateListItem( + const std::string& path) { + base::ListValue* value = new base::ListValue; + root_->Set(path, value); + return value; +} + +} // namespace cloud_devices diff --git a/components/cloud_devices/cloud_device_description.h b/components/cloud_devices/cloud_device_description.h new file mode 100644 index 0000000..ec59c87 --- /dev/null +++ b/components/cloud_devices/cloud_device_description.h @@ -0,0 +1,57 @@ +// Copyright 2014 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. + +#ifndef COMPONENTS_CLOUD_DEVICES_CLOUD_DEVICE_DESCRIPTION_H_ +#define COMPONENTS_CLOUD_DEVICES_CLOUD_DEVICE_DESCRIPTION_H_ + +#include <string> + +#include "base/callback.h" + +namespace base { +class DictionaryValue; +class ListValue; +} + +namespace cloud_devices { + +// Provides parsing, serialization and validation Cloud Device Description or +// Cloud Job Ticket. +// https://developers.google.com/cloud-print/docs/cdd +class CloudDeviceDescription { + public: + CloudDeviceDescription(); + ~CloudDeviceDescription(); + + void Reset(); + + bool InitFromString(const std::string& json); + + std::string ToString() const; + + // Returns dictionary with capability/option. + // Returns NULL if missing. + const base::DictionaryValue* GetItem(const std::string& path) const; + + // Create dictionary for capability/option. + // Never returns NULL. + base::DictionaryValue* CreateItem(const std::string& path); + + // Returns list with capability/option. + // Returns NULL if missing. + const base::ListValue* GetListItem(const std::string& path) const; + + // Create list for capability/option. + // Never returns NULL. + base::ListValue* CreateListItem(const std::string& path); + + private: + scoped_ptr<base::DictionaryValue> root_; + + DISALLOW_COPY_AND_ASSIGN(CloudDeviceDescription); +}; + +} // namespace cloud_devices + +#endif // COMPONENTS_CLOUD_DEVICES_CLOUD_DEVICE_DESCRIPTION_H_ diff --git a/components/cloud_devices/cloud_device_description_consts.cc b/components/cloud_devices/cloud_device_description_consts.cc new file mode 100644 index 0000000..79d9d92 --- /dev/null +++ b/components/cloud_devices/cloud_device_description_consts.cc @@ -0,0 +1,20 @@ +// Copyright 2014 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 "components/cloud_devices/cloud_device_description_consts.h" + +namespace cloud_devices { + +namespace json { + +const char kVersion[] = "version"; +const char kVersion10[] = "1.0"; + +const char kKeyDefault[] = "default"; +const char kKeyIsDefault[] = "is_default"; +const char kKeyOption[] = "option"; + +} // namespace json + +} // namespace cloud_devices diff --git a/components/cloud_devices/cloud_device_description_consts.h b/components/cloud_devices/cloud_device_description_consts.h new file mode 100644 index 0000000..77443c9 --- /dev/null +++ b/components/cloud_devices/cloud_device_description_consts.h @@ -0,0 +1,25 @@ +// Copyright 2014 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. + +#ifndef COMPONENTS_CLOUD_DEVICESCLOUD_DEVICE_DESCRIPTION_CONSTS_H_ +#define COMPONENTS_CLOUD_DEVICESCLOUD_DEVICE_DESCRIPTION_CONSTS_H_ + +// Constants for common parts of JSON representation of CDD/CJT. + +namespace cloud_devices { + +namespace json { + +extern const char kVersion[]; +extern const char kVersion10[]; + +extern const char kKeyDefault[]; +extern const char kKeyIsDefault[]; +extern const char kKeyOption[]; + +} // namespace json + +} // namespace cloud_devices + +#endif // COMPONENTS_CLOUD_DEVICESCLOUD_DEVICE_DESCRIPTION_CONSTS_H_ diff --git a/components/cloud_devices/cloud_devices_json_consts.cc b/components/cloud_devices/cloud_devices_json_consts.cc deleted file mode 100644 index a94c060..0000000 --- a/components/cloud_devices/cloud_devices_json_consts.cc +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright 2014 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 "components/cloud_devices/cloud_devices_json_consts.h" - -namespace cloud_devices { - -namespace cdd { - -const char kVersion[] = "version"; -const char kVersion10[] = "1.0"; -const char kSectionPrinter[] = "printer"; - -const char kKeyContentType[] = "content_type"; -const char kKeyDefault[] = "default"; -const char kKeyIsDefault[] = "is_default"; -const char kKeyMax[] = "max"; -const char kKeyType[] = "type"; -const char kKeyOption[] = "option"; -const char kKeyVendorId[] = "vendor_id"; -const char kCustomName[] = "custom_display_name"; - -const char kMargineBottomMicrons[] = "bottom_microns"; -const char kMargineLeftMicrons[] = "left_microns"; -const char kMargineRightMicrons[] = "right_microns"; -const char kMargineTopMicrons[] = "top_microns"; - -const char kDpiHorizontal[] = "horizontal_dpi"; -const char kDpiVertical[] = "vertical_dpi"; - -const char kOptionCollate[] = "collate"; -const char kOptionColor[] = "color"; -const char kOptionContentType[] = "supported_content_type"; -const char kOptionCopies[] = "copies"; -const char kOptionDpi[] = "dpi"; -const char kOptionDuplex[] = "duplex"; -const char kOptionFitToPage[] = "fit_to_page"; -const char kOptionMargins[] = "margins"; -const char kOptionMediaSize[] = "media_size"; -const char kOptionPageOrientation[] = "page_orientation"; -const char kOptionPageRange[] = "page_range"; -const char kOptionReverse[] = "reverse_order"; - -const char kPageRangeEnd[] = "end"; -const char kPageRangeStart[] = "start"; - -const char kTypeColorColor[] = "STANDARD_COLOR"; -const char kTypeColorMonochrome[] = "STANDARD_MONOCHROME"; -const char kTypeColorCustomColor[] = "CUSTOM_COLOR"; -const char kTypeColorCustomMonochrome[] = "CUSTOM_MONOCHROME"; -const char kTypeColorAuto[] = "AUTO"; - -const char kTypeDuplexLongEdge[] = "LONG_EDGE"; -const char kTypeDuplexNoDuplex[] = "NO_DUPLEX"; -const char kTypeDuplexShortEdge[] = "SHORT_EDGE"; - -const char kTypeFitToPageFillPage[] = "FILL_PAGE"; -const char kTypeFitToPageFitToPage[] = "FIT_TO_PAGE"; -const char kTypeFitToPageGrowToPage[] = "GROW_TO_PAGE"; -const char kTypeFitToPageNoFitting[] = "NO_FITTING"; -const char kTypeFitToPageShrinkToPage[] = "SHRINK_TO_PAGE"; - -const char kTypeMarginsBorderless[] = "BORDERLESS"; -const char kTypeMarginsCustom[] = "CUSTOM"; -const char kTypeMarginsStandard[] = "STANDARD"; -const char kTypeOrientationAuto[] = "AUTO"; - -const char kTypeOrientationLandscape[] = "LANDSCAPE"; -const char kTypeOrientationPortrait[] = "PORTRAIT"; - -} // namespace cdd - -} // namespace cloud_devices diff --git a/components/cloud_devices/cloud_devices_json_consts.h b/components/cloud_devices/cloud_devices_json_consts.h deleted file mode 100644 index 5862a50..0000000 --- a/components/cloud_devices/cloud_devices_json_consts.h +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright 2014 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. - -// Defines strings constants for parsing Cloud Device Description. -// https://developers.google.com/cloud-print/docs/cdd - -#ifndef COMPONENTS_CLOUD_DEVICES_CLOUD_DEVICES_JSON_CONSTANTS_H_ -#define COMPONENTS_CLOUD_DEVICES_CLOUD_DEVICES_JSON_CONSTANTS_H_ - -#include <vector> - -#include "base/memory/scoped_ptr.h" - -namespace cloud_devices { - -namespace cdd { - -extern const char kVersion[]; -extern const char kVersion10[]; -extern const char kSectionPrinter[]; - -extern const char kKeyContentType[]; -extern const char kKeyDefault[]; -extern const char kKeyIsDefault[]; -extern const char kKeyMax[]; -extern const char kKeyType[]; -extern const char kKeyOption[]; -extern const char kKeyVendorId[]; -extern const char kCustomName[]; - -extern const char kMargineBottomMicrons[]; -extern const char kMargineLeftMicrons[]; -extern const char kMargineRightMicrons[]; -extern const char kMargineTopMicrons[]; - -extern const char kDpiHorizontal[]; -extern const char kDpiVertical[]; - -extern const char kOptionCollate[]; -extern const char kOptionColor[]; -extern const char kOptionContentType[]; -extern const char kOptionCopies[]; -extern const char kOptionDpi[]; -extern const char kOptionDuplex[]; -extern const char kOptionFitToPage[]; -extern const char kOptionMargins[]; -extern const char kOptionMediaSize[]; -extern const char kOptionPageOrientation[]; -extern const char kOptionPageRange[]; -extern const char kOptionReverse[]; - -extern const char kPageRangeEnd[]; -extern const char kPageRangeStart[]; - -extern const char kTypeColorColor[]; -extern const char kTypeColorMonochrome[]; -extern const char kTypeColorCustomColor[]; -extern const char kTypeColorCustomMonochrome[]; -extern const char kTypeColorAuto[]; - -extern const char kTypeDuplexLongEdge[]; -extern const char kTypeDuplexNoDuplex[]; -extern const char kTypeDuplexShortEdge[]; - -extern const char kTypeFitToPageFillPage[]; -extern const char kTypeFitToPageFitToPage[]; -extern const char kTypeFitToPageGrowToPage[]; -extern const char kTypeFitToPageNoFitting[]; -extern const char kTypeFitToPageShrinkToPage[]; - -extern const char kTypeMarginsBorderless[]; -extern const char kTypeMarginsCustom[]; -extern const char kTypeMarginsStandard[]; -extern const char kTypeOrientationAuto[]; - -extern const char kTypeOrientationLandscape[]; -extern const char kTypeOrientationPortrait[]; - -} // namespace cdd - -} // namespace cloud_devices - -#endif // COMPONENTS_CLOUD_DEVICES_CLOUD_DEVICES_JSON_CONSTANTS_H_ diff --git a/components/cloud_devices/description_items.h b/components/cloud_devices/description_items.h new file mode 100644 index 0000000..2dd404e --- /dev/null +++ b/components/cloud_devices/description_items.h @@ -0,0 +1,231 @@ +// Copyright 2014 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. + +#ifndef COMPONENTS_CLOUD_DEVICES_CAPABILITY_INTERFACES_H_ +#define COMPONENTS_CLOUD_DEVICES_CAPABILITY_INTERFACES_H_ + +// Defines common templates that could be used to create device specific +// capabilities and print tickets. + +#include <vector> + +#include "base/logging.h" + +#include "components/cloud_devices/cloud_device_description.h" + +namespace base { +class DictionaryValue; +} + +namespace cloud_devices { + +// All traits below specify how to serialize and validate capabilities and +// ticket items. +// Traits should have following methods: +// // Returns true if capability semantically valid. +// static bool IsValid(const Option&); +// +// // Returns json path relative to the root of CDD/CJT. +// static std::string GetItemPath(); +// +// // Loads ticket item. Returns false if failed. +// static bool Load(const base::DictionaryValue& dict, ContentType* option); +// +// // Saves ticket item. +// static void Save(ContentType option, base::DictionaryValue* dict); + +// Represents a CDD capability that is stored as a JSON list +// Ex: "<CAPABILITY_NAME>": [ {<VALUE>}, {<VALUE>}, {<VALUE>} ] +// Option specifies data type for <VALUE>. +// Traits specifies how <VALUE> is stored in JSON and semantic validation. +template <class Option, class Traits> +class ListCapability { + public: + ListCapability(); + ~ListCapability(); + + bool LoadFrom(const CloudDeviceDescription& description); + void SaveTo(CloudDeviceDescription* description) const; + + void Reset() { + options_.clear(); + } + + bool IsValid() const; + + bool empty() const { + return options_.empty(); + } + + size_t size() const { + return options_.size(); + } + + const Option& operator[](size_t i) const { + return options_[i]; + } + + bool Contains(const Option& option) const{ + return std::find(options_.begin(), options_.end(), option) != + options_.end(); + } + + void AddOption(const Option& option) { + options_.push_back(option); + } + + private: + typedef std::vector<Option> OptionVector; + OptionVector options_; + + DISALLOW_COPY_AND_ASSIGN(ListCapability); +}; + +// Represents CDD capability stored as JSON list with default_value value. +// Ex: "<CAPABILITY_NAME>": { "option": [{ "is_default": true, <VALUE>}, +// {<VALUE>} ]} +// Option specifies data type for <VALUE>. +// Traits specifies how <VALUE> is stored in JSON and semantic validation. +template <class Option, class Traits> +class SelectionCapability { + public: + SelectionCapability(); + ~SelectionCapability(); + + bool LoadFrom(const CloudDeviceDescription& description); + void SaveTo(CloudDeviceDescription* description) const; + + void Reset() { + options_.clear(); + default_idx_ = -1; + } + + bool IsValid() const; + + bool empty() const { + return options_.empty(); + } + + size_t size() const { + return options_.size(); + } + + const Option& operator[](size_t i) const { + return options_[i]; + } + + bool Contains(const Option& option) const{ + return std::find(options_.begin(), options_.end(), option) != + options_.end(); + } + + const Option& GetDefault() const { + CHECK_GE(default_idx_, 0); + return options_[default_idx_]; + } + + void AddOption(const Option& option) { + AddDefaultOption(option, false); + } + + void AddDefaultOption(const Option& option, bool is_default) { + options_.push_back(option); + if (is_default) { + DCHECK_EQ(default_idx_, -1); + // Point to the last element. + default_idx_ = size() - 1; + } + } + + private: + typedef std::vector<Option> OptionVector; + + OptionVector options_; + int default_idx_; + + DISALLOW_COPY_AND_ASSIGN(SelectionCapability); +}; + +// Represents CDD capability that can be true or false. +// Ex: "<CAPABILITY_NAME>": { "default_value": true } +// Traits specifies how <VALUE> is stored in JSON and semantic validation. +template <class Traits> +class BooleanCapability { + public: + BooleanCapability(); + ~BooleanCapability(); + + bool LoadFrom(const CloudDeviceDescription& description); + void SaveTo(CloudDeviceDescription* description) const; + + void Reset() { + default_value_ = false; + } + + void set_default_value(bool value) { + default_value_ = value; + } + + bool default_value() const { + return default_value_; + } + + private: + bool default_value_; + + DISALLOW_COPY_AND_ASSIGN(BooleanCapability); +}; + +// Represents CDD capability for which existence is only important. +// Ex: "<CAPABILITY_NAME>": { } +// Traits specifies how <VALUE> is stored in JSON and semantic validation. +template <class Traits> +class EmptyCapability { + public: + EmptyCapability() {}; + ~EmptyCapability() {}; + + bool LoadFrom(const CloudDeviceDescription& description); + void SaveTo(CloudDeviceDescription* description) const; + + private: + DISALLOW_COPY_AND_ASSIGN(EmptyCapability); +}; + +// Represents CJT items. +// Ex: "<CAPABILITY_NAME>": {<VALUE>} +// Option specifies data type for <VALUE>. +// Traits specifies how <VALUE> is stored in JSON and semantic validation. +template <class Option, class Traits> +class TicketItem { + public: + TicketItem(); + ~TicketItem(); + + bool LoadFrom(const CloudDeviceDescription& description); + void SaveTo(CloudDeviceDescription* description) const; + + void Reset() { + value_ = Option(); + } + + bool IsValid() const; + + const Option& value() const { + return value_; + } + + void set_value(const Option& value) { + value_ = value; + } + + private: + Option value_; + + DISALLOW_COPY_AND_ASSIGN(TicketItem); +}; + +} // namespace cloud_devices + +#endif // COMPONENTS_CLOUD_DEVICES_CAPABILITY_INTERFACES_H_ diff --git a/components/cloud_devices/description_items_inl.h b/components/cloud_devices/description_items_inl.h new file mode 100644 index 0000000..a3e2df8 --- /dev/null +++ b/components/cloud_devices/description_items_inl.h @@ -0,0 +1,211 @@ +// Copyright 2014 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. + +#ifndef COMPONENTS_CLOUD_DEVICES_DESCRIPTION_DESCRIPTION_ITEMS_INL_H_ +#define COMPONENTS_CLOUD_DEVICES_DESCRIPTION_DESCRIPTION_ITEMS_INL_H_ + +#include <vector> + +#include "components/cloud_devices/description_items.h" + +// Implementation of templates defined in header file. +// This file should be included from CC file with implementation of device +// specific capabilities. + +namespace cloud_devices { + +template <class Option, class Traits> +ListCapability<Option, Traits>::ListCapability() { + Reset(); +} + +template <class Option, class Traits> +ListCapability<Option, Traits>::~ListCapability() { } + +template <class Option, class Traits> +bool ListCapability<Option, Traits>::IsValid() const { + if (empty()) + return false; // This type of capabilities can't be empty. + for (size_t i = 0; i < options_.size(); ++i) { + if (!Traits::IsValid(options_[i])) + return false; + } + return true; +} + +template <class Option, class Traits> +bool ListCapability<Option, Traits>::LoadFrom( + const CloudDeviceDescription& description) { + Reset(); + const base::ListValue* options = + description.GetListItem(Traits::GetItemPath()); + if (!options) + return false; + for (size_t i = 0; i < options->GetSize(); ++i) { + const base::DictionaryValue* option_value = NULL; + if (!options->GetDictionary(i, &option_value)) + return false; // Every entry must be a dictionary. + Option option; + if (!Traits::Load(*option_value, &option)) + return false; + AddOption(option); + } + return IsValid(); +} + +template <class Option, class Traits> +void ListCapability<Option, Traits>::SaveTo( + CloudDeviceDescription* description) const { + DCHECK(IsValid()); + base::ListValue* options_list = + description->CreateListItem(Traits::GetItemPath()); + for (size_t i = 0; i < options_.size(); ++i) { + base::DictionaryValue* option_value = new base::DictionaryValue; + options_list->Append(option_value); + Traits::Save(options_[i], option_value); + } +} + +template <class Option, class Traits> +SelectionCapability<Option, Traits>::SelectionCapability() { + Reset(); +} + +template <class Option, class Traits> +SelectionCapability<Option, Traits>::~SelectionCapability() { } + +template <class Option, class Traits> +bool SelectionCapability<Option, Traits>::IsValid() const { + if (empty()) + return false; // This type of capabilities can't be empty + for (size_t i = 0; i < options_.size(); ++i) { + if (!Traits::IsValid(options_[i])) + return false; + } + return default_idx_ >= 0 && default_idx_ < static_cast<int>(size()); +} + +template <class Option, class Traits> +bool SelectionCapability<Option, Traits>::LoadFrom( + const CloudDeviceDescription& description) { + Reset(); + const base::DictionaryValue* item = + description.GetItem(Traits::GetItemPath()); + if (!item) + return false; + const base::ListValue* options = NULL; + if (!item->GetList(json::kKeyOption, &options)) + return false; + for (size_t i = 0; i < options->GetSize(); ++i) { + const base::DictionaryValue* option_value = NULL; + if (!options->GetDictionary(i, &option_value)) + return false; // Every entry must be a dictionary. + Option option; + if (!Traits::Load(*option_value, &option)) + return false; + bool is_default = false; + option_value->GetBoolean(json::kKeyIsDefault, &is_default); + if (is_default && default_idx_ >= 0) { + return false; // Multiple defaults. + } + AddDefaultOption(option, is_default); + } + return IsValid(); +} + +template <class Option, class Traits> +void SelectionCapability<Option, Traits>::SaveTo( + CloudDeviceDescription* description) const { + DCHECK(IsValid()); + base::ListValue* options_list = new base::ListValue; + description->CreateItem(Traits::GetItemPath())->Set(json::kKeyOption, + options_list); + for (size_t i = 0; i < options_.size(); ++i) { + base::DictionaryValue* option_value = new base::DictionaryValue; + options_list->Append(option_value); + if (static_cast<int>(i) == default_idx_) + option_value->SetBoolean(json::kKeyIsDefault, true); + Traits::Save(options_[i], option_value); + } +} + +template <class Traits> +BooleanCapability<Traits>::BooleanCapability() { + Reset(); +} + +template <class Traits> +BooleanCapability<Traits>::~BooleanCapability() { } + +template <class Traits> +bool BooleanCapability<Traits>::LoadFrom( + const CloudDeviceDescription& description) { + Reset(); + const base::DictionaryValue* dict = + description.GetItem(Traits::GetItemPath()); + if (!dict) + return false; + default_value_ = Traits::kDefault; + dict->GetBoolean(json::kKeyDefault, &default_value_); + return true; +} + +template <class Traits> +void BooleanCapability<Traits>::SaveTo( + CloudDeviceDescription* description) const { + base::DictionaryValue* dict = description->CreateItem(Traits::GetItemPath()); + if (default_value_ != Traits::kDefault) + dict->SetBoolean(json::kKeyDefault, default_value_); +} + +template <class Traits> +bool EmptyCapability<Traits>::LoadFrom( + const CloudDeviceDescription& description) { + return description.GetItem(Traits::GetItemPath()) != NULL; +} + +template <class Traits> +void EmptyCapability<Traits>::SaveTo( + CloudDeviceDescription* description) const { + description->CreateItem(Traits::GetItemPath()); +} + +template <class Option, class Traits> +TicketItem<Option, Traits>::TicketItem() { + Reset(); +} + +template <class Option, class Traits> +TicketItem<Option, Traits>::~TicketItem() { } + +template <class Option, class Traits> +bool TicketItem<Option, Traits>::IsValid() const { + return Traits::IsValid(value()); +} + +template <class Option, class Traits> +bool TicketItem<Option, Traits>::LoadFrom( + const CloudDeviceDescription& description) { + Reset(); + const base::DictionaryValue* option_value = + description.GetItem(Traits::GetItemPath()); + if (!option_value) + return false; + Option option; + if (!Traits::Load(*option_value, &option)) + return false; + set_value(option); + return IsValid(); +} + +template <class Option, class Traits> +void TicketItem<Option, Traits>::SaveTo( + CloudDeviceDescription* description) const { + DCHECK(IsValid()); + Traits::Save(value(), description->CreateItem(Traits::GetItemPath())); +} + +} // namespace cloud_devices + +#endif // COMPONENTS_CLOUD_DEVICES_DESCRIPTION_DESCRIPTION_ITEMS_INL_H_ diff --git a/components/cloud_devices/printer_description.cc b/components/cloud_devices/printer_description.cc new file mode 100644 index 0000000..13f8710 --- /dev/null +++ b/components/cloud_devices/printer_description.cc @@ -0,0 +1,729 @@ +// Copyright 2014 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 "components/cloud_devices/printer_description.h" + +#include <algorithm> + +#include "base/json/json_reader.h" +#include "base/json/json_writer.h" +#include "base/strings/string_util.h" +#include "base/values.h" +#include "components/cloud_devices/cloud_device_description_consts.h" +#include "components/cloud_devices/description_items_inl.h" + +namespace cloud_devices { + +namespace printer { + +namespace { + +const int32 kMaxPageNumber = 1000000; + +const char kSectionPrinter[] = "printer"; + +const char kCustomName[] = "custom_display_name"; +const char kKeyContentType[] = "content_type"; +const char kKeyName[] = "name"; +const char kKeyType[] = "type"; +const char kKeyVendorId[] = "vendor_id"; + +// extern is required to be used in templates. +extern const char kOptionCollate[] = "collate"; +extern const char kOptionColor[] = "color"; +extern const char kOptionContentType[] = "supported_content_type"; +extern const char kOptionCopies[] = "copies"; +extern const char kOptionDpi[] = "dpi"; +extern const char kOptionDuplex[] = "duplex"; +extern const char kOptionFitToPage[] = "fit_to_page"; +extern const char kOptionMargins[] = "margins"; +extern const char kOptionMediaSize[] = "media_size"; +extern const char kOptionPageOrientation[] = "page_orientation"; +extern const char kOptionPageRange[] = "page_range"; +extern const char kOptionReverse[] = "reverse_order"; + +const char kMargineBottomMicrons[] = "bottom_microns"; +const char kMargineLeftMicrons[] = "left_microns"; +const char kMargineRightMicrons[] = "right_microns"; +const char kMargineTopMicrons[] = "top_microns"; + +const char kDpiHorizontal[] = "horizontal_dpi"; +const char kDpiVertical[] = "vertical_dpi"; + +const char kMediaWidth[] = "width_microns"; +const char kMediaHeight[] = "height_microns"; +const char kMediaIsContinuous[] = "is_continuous_feed"; + +const char kPageRangeInterval[] = "interval"; +const char kPageRangeEnd[] = "end"; +const char kPageRangeStart[] = "start"; + +const char kTypeColorColor[] = "STANDARD_COLOR"; +const char kTypeColorMonochrome[] = "STANDARD_MONOCHROME"; +const char kTypeColorCustomColor[] = "CUSTOM_COLOR"; +const char kTypeColorCustomMonochrome[] = "CUSTOM_MONOCHROME"; +const char kTypeColorAuto[] = "AUTO"; + +const char kTypeDuplexLongEdge[] = "LONG_EDGE"; +const char kTypeDuplexNoDuplex[] = "NO_DUPLEX"; +const char kTypeDuplexShortEdge[] = "SHORT_EDGE"; + +const char kTypeFitToPageFillPage[] = "FILL_PAGE"; +const char kTypeFitToPageFitToPage[] = "FIT_TO_PAGE"; +const char kTypeFitToPageGrowToPage[] = "GROW_TO_PAGE"; +const char kTypeFitToPageNoFitting[] = "NO_FITTING"; +const char kTypeFitToPageShrinkToPage[] = "SHRINK_TO_PAGE"; + +const char kTypeMarginsBorderless[] = "BORDERLESS"; +const char kTypeMarginsCustom[] = "CUSTOM"; +const char kTypeMarginsStandard[] = "STANDARD"; +const char kTypeOrientationAuto[] = "AUTO"; + +const char kTypeOrientationLandscape[] = "LANDSCAPE"; +const char kTypeOrientationPortrait[] = "PORTRAIT"; + +template <class IdType> +struct TypePair { + IdType id; + const char* const json_name; + static const TypePair kTypeMap[]; +}; + +template<> +const TypePair<ColorType> TypePair<ColorType>::kTypeMap[] = { + { STANDARD_COLOR, kTypeColorColor }, + { STANDARD_MONOCHROME, kTypeColorMonochrome }, + { CUSTOM_COLOR, kTypeColorCustomColor }, + { CUSTOM_MONOCHROME, kTypeColorCustomMonochrome }, + { AUTO_COLOR, kTypeColorAuto }, +}; + +template<> +const TypePair<DuplexType> + TypePair<DuplexType>::kTypeMap[] = { + { NO_DUPLEX, kTypeDuplexNoDuplex }, + { LONG_EDGE, kTypeDuplexLongEdge }, + { SHORT_EDGE, kTypeDuplexShortEdge }, +}; + +template<> +const TypePair<OrientationType> + TypePair<OrientationType>::kTypeMap[] = { + { PORTRAIT, kTypeOrientationPortrait }, + { LANDSCAPE, kTypeOrientationLandscape }, + { AUTO_ORIENTATION, kTypeOrientationAuto }, +}; + +template<> +const TypePair<MarginsType> + TypePair<MarginsType>::kTypeMap[] = { + { NO_MARGINS, kTypeMarginsBorderless }, + { STANDARD_MARGINS, kTypeMarginsStandard }, + { CUSTOM_MARGINS, kTypeMarginsCustom }, +}; + +template<> +const TypePair<FitToPageType> + TypePair<FitToPageType>::kTypeMap[] = { + { NO_FITTING, kTypeFitToPageNoFitting }, + { FIT_TO_PAGE, kTypeFitToPageFitToPage }, + { GROW_TO_PAGE, kTypeFitToPageGrowToPage }, + { SHRINK_TO_PAGE, kTypeFitToPageShrinkToPage }, + { FILL_PAGE, kTypeFitToPageFillPage }, +}; + + +template<> +const TypePair<MediaType> + TypePair<MediaType>::kTypeMap[] = { +#define MAP_CLOUD_PRINT_MEDIA_TYPE(type) { type, #type } + { CUSTOM_MEDIA, "CUSTOM" }, + MAP_CLOUD_PRINT_MEDIA_TYPE(NA_INDEX_3X5), + MAP_CLOUD_PRINT_MEDIA_TYPE(NA_PERSONAL), + MAP_CLOUD_PRINT_MEDIA_TYPE(NA_MONARCH), + MAP_CLOUD_PRINT_MEDIA_TYPE(NA_NUMBER_9), + MAP_CLOUD_PRINT_MEDIA_TYPE(NA_INDEX_4X6), + MAP_CLOUD_PRINT_MEDIA_TYPE(NA_NUMBER_10), + MAP_CLOUD_PRINT_MEDIA_TYPE(NA_A2), + MAP_CLOUD_PRINT_MEDIA_TYPE(NA_NUMBER_11), + MAP_CLOUD_PRINT_MEDIA_TYPE(NA_NUMBER_12), + MAP_CLOUD_PRINT_MEDIA_TYPE(NA_5X7), + MAP_CLOUD_PRINT_MEDIA_TYPE(NA_INDEX_5X8), + MAP_CLOUD_PRINT_MEDIA_TYPE(NA_NUMBER_14), + MAP_CLOUD_PRINT_MEDIA_TYPE(NA_INVOICE), + MAP_CLOUD_PRINT_MEDIA_TYPE(NA_INDEX_4X6_EXT), + MAP_CLOUD_PRINT_MEDIA_TYPE(NA_6X9), + MAP_CLOUD_PRINT_MEDIA_TYPE(NA_C5), + MAP_CLOUD_PRINT_MEDIA_TYPE(NA_7X9), + MAP_CLOUD_PRINT_MEDIA_TYPE(NA_EXECUTIVE), + MAP_CLOUD_PRINT_MEDIA_TYPE(NA_GOVT_LETTER), + MAP_CLOUD_PRINT_MEDIA_TYPE(NA_GOVT_LEGAL), + MAP_CLOUD_PRINT_MEDIA_TYPE(NA_QUARTO), + MAP_CLOUD_PRINT_MEDIA_TYPE(NA_LETTER), + MAP_CLOUD_PRINT_MEDIA_TYPE(NA_FANFOLD_EUR), + MAP_CLOUD_PRINT_MEDIA_TYPE(NA_LETTER_PLUS), + MAP_CLOUD_PRINT_MEDIA_TYPE(NA_FOOLSCAP), + MAP_CLOUD_PRINT_MEDIA_TYPE(NA_LEGAL), + MAP_CLOUD_PRINT_MEDIA_TYPE(NA_SUPER_A), + MAP_CLOUD_PRINT_MEDIA_TYPE(NA_9X11), + MAP_CLOUD_PRINT_MEDIA_TYPE(NA_ARCH_A), + MAP_CLOUD_PRINT_MEDIA_TYPE(NA_LETTER_EXTRA), + MAP_CLOUD_PRINT_MEDIA_TYPE(NA_LEGAL_EXTRA), + MAP_CLOUD_PRINT_MEDIA_TYPE(NA_10X11), + MAP_CLOUD_PRINT_MEDIA_TYPE(NA_10X13), + MAP_CLOUD_PRINT_MEDIA_TYPE(NA_10X14), + MAP_CLOUD_PRINT_MEDIA_TYPE(NA_10X15), + MAP_CLOUD_PRINT_MEDIA_TYPE(NA_11X12), + MAP_CLOUD_PRINT_MEDIA_TYPE(NA_EDP), + MAP_CLOUD_PRINT_MEDIA_TYPE(NA_FANFOLD_US), + MAP_CLOUD_PRINT_MEDIA_TYPE(NA_11X15), + MAP_CLOUD_PRINT_MEDIA_TYPE(NA_LEDGER), + MAP_CLOUD_PRINT_MEDIA_TYPE(NA_EUR_EDP), + MAP_CLOUD_PRINT_MEDIA_TYPE(NA_ARCH_B), + MAP_CLOUD_PRINT_MEDIA_TYPE(NA_12X19), + MAP_CLOUD_PRINT_MEDIA_TYPE(NA_B_PLUS), + MAP_CLOUD_PRINT_MEDIA_TYPE(NA_SUPER_B), + MAP_CLOUD_PRINT_MEDIA_TYPE(NA_C), + MAP_CLOUD_PRINT_MEDIA_TYPE(NA_ARCH_C), + MAP_CLOUD_PRINT_MEDIA_TYPE(NA_D), + MAP_CLOUD_PRINT_MEDIA_TYPE(NA_ARCH_D), + MAP_CLOUD_PRINT_MEDIA_TYPE(NA_ASME_F), + MAP_CLOUD_PRINT_MEDIA_TYPE(NA_WIDE_FORMAT), + MAP_CLOUD_PRINT_MEDIA_TYPE(NA_E), + MAP_CLOUD_PRINT_MEDIA_TYPE(NA_ARCH_E), + MAP_CLOUD_PRINT_MEDIA_TYPE(NA_F), + MAP_CLOUD_PRINT_MEDIA_TYPE(ROC_16K), + MAP_CLOUD_PRINT_MEDIA_TYPE(ROC_8K), + MAP_CLOUD_PRINT_MEDIA_TYPE(PRC_32K), + MAP_CLOUD_PRINT_MEDIA_TYPE(PRC_1), + MAP_CLOUD_PRINT_MEDIA_TYPE(PRC_2), + MAP_CLOUD_PRINT_MEDIA_TYPE(PRC_4), + MAP_CLOUD_PRINT_MEDIA_TYPE(PRC_5), + MAP_CLOUD_PRINT_MEDIA_TYPE(PRC_8), + MAP_CLOUD_PRINT_MEDIA_TYPE(PRC_6), + MAP_CLOUD_PRINT_MEDIA_TYPE(PRC_3), + MAP_CLOUD_PRINT_MEDIA_TYPE(PRC_16K), + MAP_CLOUD_PRINT_MEDIA_TYPE(PRC_7), + MAP_CLOUD_PRINT_MEDIA_TYPE(OM_JUURO_KU_KAI), + MAP_CLOUD_PRINT_MEDIA_TYPE(OM_PA_KAI), + MAP_CLOUD_PRINT_MEDIA_TYPE(OM_DAI_PA_KAI), + MAP_CLOUD_PRINT_MEDIA_TYPE(PRC_10), + MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A10), + MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A9), + MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A8), + MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A7), + MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A6), + MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A5), + MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A5_EXTRA), + MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A4), + MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A4_TAB), + MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A4_EXTRA), + MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A3), + MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A4X3), + MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A4X4), + MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A4X5), + MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A4X6), + MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A4X7), + MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A4X8), + MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A4X9), + MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A3_EXTRA), + MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A2), + MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A3X3), + MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A3X4), + MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A3X5), + MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A3X6), + MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A3X7), + MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A1), + MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A2X3), + MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A2X4), + MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A2X5), + MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A0), + MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A1X3), + MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A1X4), + MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_2A0), + MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A0X3), + MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_B10), + MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_B9), + MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_B8), + MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_B7), + MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_B6), + MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_B6C4), + MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_B5), + MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_B5_EXTRA), + MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_B4), + MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_B3), + MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_B2), + MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_B1), + MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_B0), + MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_C10), + MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_C9), + MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_C8), + MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_C7), + MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_C7C6), + MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_C6), + MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_C6C5), + MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_C5), + MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_C4), + MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_C3), + MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_C2), + MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_C1), + MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_C0), + MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_DL), + MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_RA2), + MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_SRA2), + MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_RA1), + MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_SRA1), + MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_RA0), + MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_SRA0), + MAP_CLOUD_PRINT_MEDIA_TYPE(JIS_B10), + MAP_CLOUD_PRINT_MEDIA_TYPE(JIS_B9), + MAP_CLOUD_PRINT_MEDIA_TYPE(JIS_B8), + MAP_CLOUD_PRINT_MEDIA_TYPE(JIS_B7), + MAP_CLOUD_PRINT_MEDIA_TYPE(JIS_B6), + MAP_CLOUD_PRINT_MEDIA_TYPE(JIS_B5), + MAP_CLOUD_PRINT_MEDIA_TYPE(JIS_B4), + MAP_CLOUD_PRINT_MEDIA_TYPE(JIS_B3), + MAP_CLOUD_PRINT_MEDIA_TYPE(JIS_B2), + MAP_CLOUD_PRINT_MEDIA_TYPE(JIS_B1), + MAP_CLOUD_PRINT_MEDIA_TYPE(JIS_B0), + MAP_CLOUD_PRINT_MEDIA_TYPE(JIS_EXEC), + MAP_CLOUD_PRINT_MEDIA_TYPE(JPN_CHOU4), + MAP_CLOUD_PRINT_MEDIA_TYPE(JPN_HAGAKI), + MAP_CLOUD_PRINT_MEDIA_TYPE(JPN_YOU4), + MAP_CLOUD_PRINT_MEDIA_TYPE(JPN_CHOU2), + MAP_CLOUD_PRINT_MEDIA_TYPE(JPN_CHOU3), + MAP_CLOUD_PRINT_MEDIA_TYPE(JPN_OUFUKU), + MAP_CLOUD_PRINT_MEDIA_TYPE(JPN_KAHU), + MAP_CLOUD_PRINT_MEDIA_TYPE(JPN_KAKU2), + MAP_CLOUD_PRINT_MEDIA_TYPE(OM_SMALL_PHOTO), + MAP_CLOUD_PRINT_MEDIA_TYPE(OM_ITALIAN), + MAP_CLOUD_PRINT_MEDIA_TYPE(OM_POSTFIX), + MAP_CLOUD_PRINT_MEDIA_TYPE(OM_LARGE_PHOTO), + MAP_CLOUD_PRINT_MEDIA_TYPE(OM_FOLIO), + MAP_CLOUD_PRINT_MEDIA_TYPE(OM_FOLIO_SP), + MAP_CLOUD_PRINT_MEDIA_TYPE(OM_INVITE), +#undef MAP_CLOUD_PRINT_MEDIA_TYPE +}; + +template<class IdType> +std::string TypeToString(IdType id) { + for (size_t i = 0; i < arraysize(TypePair<IdType>::kTypeMap); ++i) { + if (id == TypePair<IdType>::kTypeMap[i].id) + return TypePair<IdType>::kTypeMap[i].json_name; + } + NOTREACHED(); + return std::string(); +} + +template<class IdType> +bool TypeFromString(const std::string& type, IdType* id) { + for (size_t i = 0; i < arraysize(TypePair<IdType>::kTypeMap); ++i) { + if (type == TypePair<IdType>::kTypeMap[i].json_name) { + *id = TypePair<IdType>::kTypeMap[i].id; + return true; + } + } + return false; +} + +} // namespace + +Color::Color() : type(AUTO_COLOR) {} + +Color::Color(ColorType type) : type(type) {} + +bool Color::operator==(const Color& other) const { + return type == other.type && vendor_id == other.vendor_id && + custom_display_name == other.custom_display_name; +} + +bool Color::IsValid() const { + if (type != CUSTOM_COLOR && type != CUSTOM_MONOCHROME) + return true; + return !vendor_id.empty() && !custom_display_name.empty(); +} + +Margins::Margins() + : type(STANDARD_MARGINS), + top_microns(0), + right_microns(0), + bottom_microns(0), + left_microns(0) { +} + +Margins::Margins(MarginsType type, + int32 top_microns, + int32 right_microns, + int32 bottom_microns, + int32 left_microns) + : type(type), + top_microns(top_microns), + right_microns(right_microns), + bottom_microns(bottom_microns), + left_microns(left_microns) { +} + +bool Margins::operator==(const Margins& other) const { + return type == other.type && + top_microns == other.top_microns && + right_microns == other.right_microns && + bottom_microns == other.bottom_microns; +} + +Dpi::Dpi() : horizontal(0), vertical(0) {} + +Dpi::Dpi(int32 horizontal, int32 vertical) + : horizontal(horizontal), vertical(vertical) {} + +bool Dpi::operator==(const Dpi& other) const { + return horizontal == other.horizontal && vertical == other.vertical; +} + +Media::Media() + : type(CUSTOM_MEDIA), + width_microns(0), + height_microns(0), + is_continuous_feed(false) { + +} + +Media::Media(MediaType type, int32 width_microns, int32 height_microns) + : type(type), + width_microns(width_microns), + height_microns(height_microns), + is_continuous_feed(width_microns <= 0 || height_microns <= 0) { +} + +Media::Media(const std::string& custom_display_name, int32 width_microns, + int32 height_microns) + : type(CUSTOM_MEDIA), + width_microns(width_microns), + height_microns(height_microns), + is_continuous_feed(width_microns <= 0 || height_microns <= 0), + custom_display_name(custom_display_name) { +} + +bool Media::IsValid() const { + if (is_continuous_feed) { + if (width_microns <= 0 && height_microns <= 0) + return false; + } else { + if (width_microns <= 0 || height_microns <= 0) + return false; + } + return true; +} + +bool Media::operator==(const Media& other) const { + return type == other.type && + width_microns == other.width_microns && + height_microns == other.height_microns && + is_continuous_feed == other.is_continuous_feed; +} + +Interval::Interval() : start(0), end(0) {} + +Interval::Interval(int32 start, int32 end) + : start(start), end(end) {} + +Interval::Interval(int32 start) + : start(start), end(kMaxPageNumber) {} + +bool Interval::operator==(const Interval& other) const { + return start == other.start && end == other.end; +} + +template<const char* kName> +class ItemsTraits { + public: + static std::string GetItemPath() { + std::string result = kSectionPrinter; + result += '.'; + result += kName; + return result; + } +}; + +class NoValueValidation { + public: + template <class Option> + static bool IsValid(const Option&) { + return true; + } +}; + +class ContentTypeTraits : public NoValueValidation, + public ItemsTraits<kOptionContentType> { + public: + static bool Load(const base::DictionaryValue& dict, ContentType* option) { + return dict.GetString(kKeyContentType, option); + } + + static void Save(ContentType option, base::DictionaryValue* dict) { + dict->SetString(kKeyContentType, option); + } +}; + +class ColorTraits : public ItemsTraits<kOptionColor> { + public: + static bool IsValid(const Color& option) { + return option.IsValid(); + } + + static bool Load(const base::DictionaryValue& dict, Color* option) { + std::string type_str; + if (!dict.GetString(kKeyType, &type_str)) + return false; + if (!TypeFromString(type_str, &option->type)) + return false; + dict.GetString(kKeyVendorId, &option->vendor_id); + dict.GetString(kCustomName, &option->custom_display_name); + return true; + } + + static void Save(const Color& option, base::DictionaryValue* dict) { + dict->SetString(kKeyType, TypeToString(option.type)); + if (!option.vendor_id.empty()) + dict->SetString(kKeyVendorId, option.vendor_id); + if (!option.custom_display_name.empty()) + dict->SetString(kCustomName, option.custom_display_name); + } +}; + +class DuplexTraits : public NoValueValidation, + public ItemsTraits<kOptionDuplex> { + public: + static bool Load(const base::DictionaryValue& dict, DuplexType* option) { + std::string type_str; + return dict.GetString(kKeyType, &type_str) && + TypeFromString(type_str, option); + } + + static void Save(DuplexType option, base::DictionaryValue* dict) { + dict->SetString(kKeyType, TypeToString(option)); + } +}; + +class OrientationTraits : public NoValueValidation, + public ItemsTraits<kOptionPageOrientation> { + public: + static bool Load(const base::DictionaryValue& dict, OrientationType* option) { + std::string type_str; + return dict.GetString(kKeyType, &type_str) && + TypeFromString(type_str, option); + } + + static void Save(OrientationType option, base::DictionaryValue* dict) { + dict->SetString(kKeyType, TypeToString(option)); + } +}; + +class CopiesTraits : public ItemsTraits<kOptionCopies> { + public: + static bool IsValid(int32 option) { + return option >= 1; + } + + static bool Load(const base::DictionaryValue& dict, int32* option) { + return dict.GetInteger(kOptionCopies, option); + } + + static void Save(int32 option, base::DictionaryValue* dict) { + dict->SetInteger(kOptionCopies, option); + } +}; + +class MarginsTraits : public NoValueValidation, + public ItemsTraits<kOptionMargins> { + public: + static bool Load(const base::DictionaryValue& dict, Margins* option) { + std::string type_str; + if (!dict.GetString(kKeyType, &type_str)) + return false; + if (!TypeFromString(type_str, &option->type)) + return false; + return + dict.GetInteger(kMargineTopMicrons, &option->top_microns) && + dict.GetInteger(kMargineRightMicrons, &option->right_microns) && + dict.GetInteger(kMargineBottomMicrons, &option->bottom_microns) && + dict.GetInteger(kMargineLeftMicrons, &option->left_microns); + } + + static void Save(const Margins& option, base::DictionaryValue* dict) { + dict->SetString(kKeyType, TypeToString(option.type)); + dict->SetInteger(kMargineTopMicrons, option.top_microns); + dict->SetInteger(kMargineRightMicrons, option.right_microns); + dict->SetInteger(kMargineBottomMicrons, option.bottom_microns); + dict->SetInteger(kMargineLeftMicrons, option.left_microns); + } +}; + +class DpiTraits : public ItemsTraits<kOptionDpi> { + public: + static bool IsValid(const Dpi& option) { + return option.horizontal && option.vertical > 0; + } + + static bool Load(const base::DictionaryValue& dict, Dpi* option) { + if (!dict.GetInteger(kDpiHorizontal, &option->horizontal) || + !dict.GetInteger(kDpiVertical, &option->vertical)) { + return false; + } + return true; + } + + static void Save(const Dpi& option, base::DictionaryValue* dict) { + dict->SetInteger(kDpiHorizontal, option.horizontal); + dict->SetInteger(kDpiVertical, option.vertical); + } +}; + +class FitToPageTraits : public NoValueValidation, + public ItemsTraits<kOptionFitToPage> { + public: + static bool Load(const base::DictionaryValue& dict, FitToPageType* option) { + std::string type_str; + return dict.GetString(kKeyType, &type_str) && + TypeFromString(type_str, option); + } + + static void Save(FitToPageType option, base::DictionaryValue* dict) { + dict->SetString(kKeyType, TypeToString(option)); + } +}; + +class PageRangeTraits : public ItemsTraits<kOptionPageRange> { + public: + static bool IsValid(const PageRange& option) { + for (size_t i = 0; i < option.size(); ++i) { + if (option[i].start < 1 || option[i].end < 1) { + return false; + } + } + return true; + } + + static bool Load(const base::DictionaryValue& dict, PageRange* option) { + const base::ListValue* list = NULL; + if (!dict.GetList(kPageRangeInterval, &list)) + return false; + for (size_t i = 0; i < list->GetSize(); ++i) { + const base::DictionaryValue* interval = NULL; + if (!list->GetDictionary(i, &interval)) + return false; + Interval new_interval(1, kMaxPageNumber); + interval->GetInteger(kPageRangeStart, &new_interval.start); + interval->GetInteger(kPageRangeEnd, &new_interval.end); + option->push_back(new_interval); + } + return true; + } + + static void Save(const PageRange& option, base::DictionaryValue* dict) { + if (!option.empty()) { + base::ListValue* list = new base::ListValue; + dict->Set(kPageRangeInterval, list); + for (size_t i = 0; i < option.size(); ++i) { + base::DictionaryValue* interval = new base::DictionaryValue; + list->Append(interval); + interval->SetInteger(kPageRangeStart, option[i].start); + if (option[i].end < kMaxPageNumber) + interval->SetInteger(kPageRangeEnd, option[i].end); + } + } + } +}; + +class MediaTraits : public ItemsTraits<kOptionMediaSize> { + public: + static bool IsValid(const Media& option) { + return option.IsValid(); + } + + static bool Load(const base::DictionaryValue& dict, Media* option) { + std::string type_str; + if (dict.GetString(kKeyName, &type_str)) { + if (!TypeFromString(type_str, &option->type)) + return false; + } + + dict.GetInteger(kMediaWidth, &option->width_microns); + dict.GetInteger(kMediaHeight, &option->height_microns); + dict.GetBoolean(kMediaIsContinuous, &option->is_continuous_feed); + dict.GetString(kCustomName, &option->custom_display_name); + return true; + } + + static void Save(const Media& option, base::DictionaryValue* dict) { + if (option.type != CUSTOM_MEDIA) + dict->SetString(kKeyName, TypeToString(option.type)); + if (!option.custom_display_name.empty()) + dict->SetString(kCustomName, option.custom_display_name); + if (option.width_microns > 0) + dict->SetInteger(kMediaWidth, option.width_microns); + if (option.height_microns > 0) + dict->SetInteger(kMediaHeight, option.height_microns); + if (option.is_continuous_feed) + dict->SetBoolean(kMediaIsContinuous, true); + } +}; + +class CollateTraits : public NoValueValidation, + public ItemsTraits<kOptionCollate> { + public: + static const bool kDefault = true; + + static bool Load(const base::DictionaryValue& dict, bool* option) { + return dict.GetBoolean(kOptionCollate, option); + } + + static void Save(bool option, base::DictionaryValue* dict) { + dict->SetBoolean(kOptionCollate, option); + } +}; + +class ReverseTraits : public NoValueValidation, + public ItemsTraits<kOptionReverse> { + public: + static const bool kDefault = false; + + static bool Load(const base::DictionaryValue& dict, bool* option) { + return dict.GetBoolean(kOptionReverse, option); + } + + static void Save(bool option, base::DictionaryValue* dict) { + dict->SetBoolean(kOptionReverse, option); + } +}; + +} // namespace printer + +using namespace printer; + +template class ListCapability<ContentType, ContentTypeTraits>; +template class SelectionCapability<Color, ColorTraits>; +template class SelectionCapability<DuplexType, DuplexTraits>; +template class SelectionCapability<OrientationType, OrientationTraits>; +template class SelectionCapability<Margins, MarginsTraits>; +template class SelectionCapability<Dpi, DpiTraits>; +template class SelectionCapability<FitToPageType, FitToPageTraits>; +template class SelectionCapability<Media, MediaTraits>; +template class EmptyCapability<class CopiesTraits>; +template class EmptyCapability<class PageRangeTraits>; +template class BooleanCapability<class CollateTraits>; +template class BooleanCapability<class ReverseTraits>; + +template class TicketItem<Color, ColorTraits>; +template class TicketItem<DuplexType, DuplexTraits>; +template class TicketItem<OrientationType, OrientationTraits>; +template class TicketItem<Margins, MarginsTraits>; +template class TicketItem<Dpi, DpiTraits>; +template class TicketItem<FitToPageType, FitToPageTraits>; +template class TicketItem<Media, MediaTraits>; +template class TicketItem<int32, CopiesTraits>; +template class TicketItem<PageRange, PageRangeTraits>; +template class TicketItem<bool, CollateTraits>; +template class TicketItem<bool, ReverseTraits>; + +} // namespace cloud_devices diff --git a/components/cloud_devices/printer_description.h b/components/cloud_devices/printer_description.h new file mode 100644 index 0000000..cc9b654 --- /dev/null +++ b/components/cloud_devices/printer_description.h @@ -0,0 +1,362 @@ +// Copyright 2014 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. + +#ifndef COMPONENTS_CLOUD_DEVICES_CLOUD_PRINTER_DESCRIPTION_H_ +#define COMPONENTS_CLOUD_DEVICES_CLOUD_PRINTER_DESCRIPTION_H_ + +#include <string> + +#include "base/logging.h" +#include "components/cloud_devices/description_items.h" + +// Defines printer options, CDD and CJT items. +// https://developers.google.com/cloud-print/docs/cdd + +namespace cloud_devices { + +namespace printer { + +typedef std::string ContentType; + +enum ColorType { + STANDARD_COLOR, + STANDARD_MONOCHROME, + CUSTOM_COLOR, + CUSTOM_MONOCHROME, + AUTO_COLOR, +}; + +struct Color { + Color(); + explicit Color(ColorType type); + + bool IsValid() const; + bool operator==(const Color& other) const; + bool operator!=(const Color& other) const { + return !(*this == other); + } + + ColorType type; + std::string vendor_id; + std::string custom_display_name; +}; + +enum DuplexType { + NO_DUPLEX, + LONG_EDGE, + SHORT_EDGE, +}; + +enum OrientationType { + PORTRAIT, + LANDSCAPE, + AUTO_ORIENTATION, +}; + +enum MarginsType { + NO_MARGINS, + STANDARD_MARGINS, + CUSTOM_MARGINS, +}; + +struct Margins { + Margins(); + Margins(MarginsType type, + int32 top_microns, + int32 right_microns, + int32 bottom_microns, + int32 left_microns); + + bool operator==(const Margins& other) const; + bool operator!=(const Margins& other) const { + return !(*this == other); + } + + MarginsType type; + int32 top_microns; + int32 right_microns; + int32 bottom_microns; + int32 left_microns; +}; + +struct Dpi { + Dpi(); + Dpi(int32 horizontal, int32 vertical); + + bool operator==(const Dpi& other) const; + bool operator!=(const Dpi& other) const { + return !(*this == other); + } + + int32 horizontal; + int32 vertical; +}; + +enum FitToPageType { + NO_FITTING, + FIT_TO_PAGE, + GROW_TO_PAGE, + SHRINK_TO_PAGE, + FILL_PAGE, +}; + +enum MediaType { + CUSTOM_MEDIA, + + // North American standard sheet media names. + NA_INDEX_3X5, + NA_PERSONAL, + NA_MONARCH, + NA_NUMBER_9, + NA_INDEX_4X6, + NA_NUMBER_10, + NA_A2, + NA_NUMBER_11, + NA_NUMBER_12, + NA_5X7, + NA_INDEX_5X8, + NA_NUMBER_14, + NA_INVOICE, + NA_INDEX_4X6_EXT, + NA_6X9, + NA_C5, + NA_7X9, + NA_EXECUTIVE, + NA_GOVT_LETTER, + NA_GOVT_LEGAL, + NA_QUARTO, + NA_LETTER, + NA_FANFOLD_EUR, + NA_LETTER_PLUS, + NA_FOOLSCAP, + NA_LEGAL, + NA_SUPER_A, + NA_9X11, + NA_ARCH_A, + NA_LETTER_EXTRA, + NA_LEGAL_EXTRA, + NA_10X11, + NA_10X13, + NA_10X14, + NA_10X15, + NA_11X12, + NA_EDP, + NA_FANFOLD_US, + NA_11X15, + NA_LEDGER, + NA_EUR_EDP, + NA_ARCH_B, + NA_12X19, + NA_B_PLUS, + NA_SUPER_B, + NA_C, + NA_ARCH_C, + NA_D, + NA_ARCH_D, + NA_ASME_F, + NA_WIDE_FORMAT, + NA_E, + NA_ARCH_E, + NA_F, + + // Chinese standard sheet media size names. + ROC_16K, + ROC_8K, + PRC_32K, + PRC_1, + PRC_2, + PRC_4, + PRC_5, + PRC_8, + PRC_6, + PRC_3, + PRC_16K, + PRC_7, + OM_JUURO_KU_KAI, + OM_PA_KAI, + OM_DAI_PA_KAI, + PRC_10, + + // ISO standard sheet media size names. + ISO_A10, + ISO_A9, + ISO_A8, + ISO_A7, + ISO_A6, + ISO_A5, + ISO_A5_EXTRA, + ISO_A4, + ISO_A4_TAB, + ISO_A4_EXTRA, + ISO_A3, + ISO_A4X3, + ISO_A4X4, + ISO_A4X5, + ISO_A4X6, + ISO_A4X7, + ISO_A4X8, + ISO_A4X9, + ISO_A3_EXTRA, + ISO_A2, + ISO_A3X3, + ISO_A3X4, + ISO_A3X5, + ISO_A3X6, + ISO_A3X7, + ISO_A1, + ISO_A2X3, + ISO_A2X4, + ISO_A2X5, + ISO_A0, + ISO_A1X3, + ISO_A1X4, + ISO_2A0, + ISO_A0X3, + ISO_B10, + ISO_B9, + ISO_B8, + ISO_B7, + ISO_B6, + ISO_B6C4, + ISO_B5, + ISO_B5_EXTRA, + ISO_B4, + ISO_B3, + ISO_B2, + ISO_B1, + ISO_B0, + ISO_C10, + ISO_C9, + ISO_C8, + ISO_C7, + ISO_C7C6, + ISO_C6, + ISO_C6C5, + ISO_C5, + ISO_C4, + ISO_C3, + ISO_C2, + ISO_C1, + ISO_C0, + ISO_DL, + ISO_RA2, + ISO_SRA2, + ISO_RA1, + ISO_SRA1, + ISO_RA0, + ISO_SRA0, + + // Japanese standard sheet media size names. + JIS_B10, + JIS_B9, + JIS_B8, + JIS_B7, + JIS_B6, + JIS_B5, + JIS_B4, + JIS_B3, + JIS_B2, + JIS_B1, + JIS_B0, + JIS_EXEC, + JPN_CHOU4, + JPN_HAGAKI, + JPN_YOU4, + JPN_CHOU2, + JPN_CHOU3, + JPN_OUFUKU, + JPN_KAHU, + JPN_KAKU2, + + // Other metric standard sheet media size names. + OM_SMALL_PHOTO, + OM_ITALIAN, + OM_POSTFIX, + OM_LARGE_PHOTO, + OM_FOLIO, + OM_FOLIO_SP, + OM_INVITE, +}; + +struct Media { + Media(); + + Media(MediaType type, int32 width_microns, int32 height_microns); + + Media(const std::string& custom_display_name, + int32 width_microns, int32 height_microns); + + bool IsValid() const; + bool operator==(const Media& other) const; + bool operator!=(const Media& other) const { + return !(*this == other); + } + + MediaType type; + int32 width_microns; + int32 height_microns; + bool is_continuous_feed; + std::string custom_display_name; +}; + +struct Interval { + Interval(); + Interval(int32 start, int32 end); + Interval(int32 start); + + bool operator==(const Interval& other) const; + bool operator!=(const Interval& other) const { + return !(*this == other); + } + + int32 start; + int32 end; +}; + +typedef std::vector<Interval> PageRange; + +class ContentTypeTraits; +class ColorTraits; +class DuplexTraits; +class OrientationTraits; +class MarginsTraits; +class DpiTraits; +class FitToPageTraits; +class MediaTraits; +class CopiesTraits; +class PageRangeTraits; +class CollateTraits; +class ReverseTraits; + +typedef ListCapability<ContentType, ContentTypeTraits> ContentTypesCapability; +typedef SelectionCapability<Color, ColorTraits> ColorCapability; +typedef SelectionCapability<DuplexType, DuplexTraits> DuplexCapability; +typedef SelectionCapability<OrientationType, + OrientationTraits> OrientationCapability; +typedef SelectionCapability<Margins, MarginsTraits> MarginsCapability; +typedef SelectionCapability<Dpi, DpiTraits> DpiCapability; +typedef SelectionCapability<FitToPageType, FitToPageTraits> FitToPageCapability; +typedef SelectionCapability<Media, MediaTraits> MediaCapability; +typedef EmptyCapability<class CopiesTraits> CopiesCapability; +typedef EmptyCapability<class PageRangeTraits> PageRangeCapability; +typedef BooleanCapability<class CollateTraits> CollateCapability; +typedef BooleanCapability<class ReverseTraits> ReverseCapability; + +typedef TicketItem<Color, ColorTraits> ColorTicketItem; +typedef TicketItem<DuplexType, DuplexTraits> DuplexTicketItem; +typedef TicketItem<OrientationType, OrientationTraits> OrientationTicketItem; +typedef TicketItem<Margins, MarginsTraits> MarginsTicketItem; +typedef TicketItem<Dpi, DpiTraits> DpiTicketItem; +typedef TicketItem<FitToPageType, FitToPageTraits> FitToPageTicketItem; +typedef TicketItem<Media, MediaTraits> MediaTicketItem; +typedef TicketItem<int32, CopiesTraits> CopiesTicketItem; +typedef TicketItem<PageRange, PageRangeTraits> PageRangeTicketItem; +typedef TicketItem<bool, CollateTraits> CollateTicketItem; +typedef TicketItem<bool, ReverseTraits> ReverseTicketItem; + +} // namespace printer + +} // namespace cloud_devices + +#endif // COMPONENTS_CLOUD_DEVICES_CLOUD_PRINTER_DESCRIPTION_H_ diff --git a/components/cloud_devices/printer_description_unittest.cc b/components/cloud_devices/printer_description_unittest.cc new file mode 100644 index 0000000..d6a68f0 --- /dev/null +++ b/components/cloud_devices/printer_description_unittest.cc @@ -0,0 +1,581 @@ +// Copyright 2014 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 "components/cloud_devices/printer_description.h" + +#include "base/json/json_reader.h" +#include "base/json/json_writer.h" +#include "base/strings/string_util.h" +#include "base/values.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace cloud_devices { + +namespace printer { + +// Replaces ' with " to allow readable json constants in tests. +// Makes sure that same json value represented by same strings to simplify +// comparison. +std::string NormalizeJson(const std::string& json) { + std::string result = json; + base::ReplaceChars(result, "'", "\"", &result); + scoped_ptr<base::Value> value(base::JSONReader::Read(result)); + DCHECK(value); + base::JSONWriter::Write(value.get(), &result); + return result; +} + +const char kCdd[] = +"{" +" 'version': '1.0'," +" 'printer': {" +" 'supported_content_type': [ {" +" 'content_type': 'image/pwg-raster'" +" }, {" +" 'content_type': 'image/jpeg'" +" } ]," +" 'color': {" +" 'option': [ {" +" 'is_default': true," +" 'type': 'STANDARD_COLOR'" +" }, {" +" 'type': 'STANDARD_MONOCHROME'" +" }, {" +" 'type': 'CUSTOM_MONOCHROME'," +" 'vendor_id': '123'," +" 'custom_display_name': 'monochrome'" +" } ]" +" }," +" 'duplex': {" +" 'option': [ {" +" 'is_default': true," +" 'type': 'LONG_EDGE'" +" }, {" +" 'type': 'SHORT_EDGE'" +" }, {" +" 'type': 'NO_DUPLEX'" +" } ]" +" }," +" 'page_orientation': {" +" 'option': [ {" +" 'type': 'PORTRAIT'" +" }, {" +" 'type': 'LANDSCAPE'" +" }, {" +" 'is_default': true," +" 'type': 'AUTO'" +" } ]" +" }," +" 'copies': {" +" }," +" 'margins': {" +" 'option': [ {" +" 'is_default': true," +" 'type': 'BORDERLESS'," +" 'top_microns': 0," +" 'right_microns': 0," +" 'bottom_microns': 0," +" 'left_microns': 0" +" }, {" +" 'type': 'STANDARD'," +" 'top_microns': 100," +" 'right_microns': 200," +" 'bottom_microns': 300," +" 'left_microns': 400" +" }, {" +" 'type': 'CUSTOM'," +" 'top_microns': 1," +" 'right_microns': 2," +" 'bottom_microns': 3," +" 'left_microns': 4" +" } ]" +" }," +" 'dpi': {" +" 'option': [ {" +" 'horizontal_dpi': 150," +" 'vertical_dpi': 250" +" }, {" +" 'is_default': true," +" 'horizontal_dpi': 600," +" 'vertical_dpi': 1600" +" } ]" +" }," +" 'fit_to_page': {" +" 'option': [ {" +" 'is_default': true," +" 'type': 'NO_FITTING'" +" }, {" +" 'type': 'FIT_TO_PAGE'" +" }, {" +" 'type': 'GROW_TO_PAGE'" +" }, {" +" 'type': 'SHRINK_TO_PAGE'" +" }, {" +" 'type': 'FILL_PAGE'" +" } ]" +" }," +" 'page_range': {" +" }," +" 'media_size': {" +" 'option': [ {" +" 'is_default': true," +" 'name': 'NA_LETTER'," +" 'width_microns': 2222," +" 'height_microns': 3333" +" }, {" +" 'name': 'ISO_A6'," +" 'width_microns': 4444," +" 'height_microns': 5555" +" }, {" +" 'name': 'JPN_YOU4'," +" 'width_microns': 6666," +" 'height_microns': 7777" +" }, {" +" 'width_microns': 1111," +" 'is_continuous_feed': true," +" 'custom_display_name': 'FEED'" +" } ]" +" }," +" 'collate': {" +" 'default': false" +" }," +" 'reverse_order': {" +" 'default': true" +" }" +" }" +"}"; + + +const char kDefaultCdd[] = +"{" +" 'version': '1.0'" +"}"; + +const char kBadVersionCdd[] = +"{" +" 'version': '1.1'," +" 'printer': {" +" }" +"}"; + +const char kNoDefaultCdd[] = +"{" +" 'version': '1.0'," +" 'printer': {" +" 'color': {" +" 'option': [ {" +" 'type': 'STANDARD_COLOR'" +" }, {" +" 'type': 'STANDARD_MONOCHROME'" +" } ]" +" }" +" }" +"}"; + +const char kMultyDefaultCdd[] = +"{" +" 'version': '1.0'," +" 'printer': {" +" 'color': {" +" 'option': [ {" +" 'is_default': true," +" 'type': 'STANDARD_COLOR'" +" }, {" +" 'is_default': true," +" 'type': 'STANDARD_MONOCHROME'" +" } ]" +" }" +" }" +"}"; + +const char kCjt[] = +"{" +" 'version': '1.0'," +" 'printer': {" +" 'color': {" +" 'type': 'STANDARD_MONOCHROME'" +" }," +" 'duplex': {" +" 'type': 'NO_DUPLEX'" +" }," +" 'page_orientation': {" +" 'type': 'LANDSCAPE'" +" }," +" 'copies': {" +" 'copies': 123" +" }," +" 'margins': {" +" 'type': 'CUSTOM'," +" 'top_microns': 7," +" 'right_microns': 6," +" 'bottom_microns': 3," +" 'left_microns': 1" +" }," +" 'dpi': {" +" 'horizontal_dpi': 562," +" 'vertical_dpi': 125" +" }," +" 'fit_to_page': {" +" 'type': 'SHRINK_TO_PAGE'" +" }," +" 'page_range': {" +" 'interval': [ {" +" 'start': 1," +" 'end': 99" +" }, {" +" 'start': 150" +" } ]" +" }," +" 'media_size': {" +" 'name': 'ISO_C7C6'," +" 'width_microns': 4261," +" 'height_microns': 334" +" }," +" 'collate': {" +" 'collate': false" +" }," +" 'reverse_order': {" +" 'reverse_order': true" +" }" +" }" +"}"; + +const char kDefaultCjt[] = +"{" +" 'version': '1.0'" +"}"; + +const char kBadVersionCjt[] = +"{" +" 'version': '1.1'," +" 'printer': {" +" }" +"}"; + +TEST(PrinterDescriptionTest, CddInit) { + CloudDeviceDescription description; + EXPECT_EQ(NormalizeJson(kDefaultCdd), NormalizeJson(description.ToString())); + + ContentTypesCapability content_types; + ColorCapability color; + DuplexCapability duplex; + OrientationCapability orientation; + MarginsCapability margins; + DpiCapability dpi; + FitToPageCapability fit_to_page; + MediaCapability media; + CopiesCapability copies; + PageRangeCapability page_range; + CollateCapability collate; + ReverseCapability reverse; + + EXPECT_FALSE(content_types.LoadFrom(description)); + EXPECT_FALSE(color.LoadFrom(description)); + EXPECT_FALSE(duplex.LoadFrom(description)); + EXPECT_FALSE(orientation.LoadFrom(description)); + EXPECT_FALSE(copies.LoadFrom(description)); + EXPECT_FALSE(margins.LoadFrom(description)); + EXPECT_FALSE(dpi.LoadFrom(description)); + EXPECT_FALSE(fit_to_page.LoadFrom(description)); + EXPECT_FALSE(page_range.LoadFrom(description)); + EXPECT_FALSE(media.LoadFrom(description)); + EXPECT_FALSE(collate.LoadFrom(description)); + EXPECT_FALSE(reverse.LoadFrom(description)); + EXPECT_FALSE(media.LoadFrom(description)); +} + +TEST(PrinterDescriptionTest, CddInvalid) { + CloudDeviceDescription description; + ColorCapability color; + + EXPECT_FALSE(description.InitFromString(NormalizeJson(kBadVersionCdd))); + + EXPECT_TRUE(description.InitFromString(NormalizeJson(kNoDefaultCdd))); + EXPECT_FALSE(color.LoadFrom(description)); + + EXPECT_TRUE(description.InitFromString(NormalizeJson(kMultyDefaultCdd))); + EXPECT_FALSE(color.LoadFrom(description)); +} + +TEST(PrinterDescriptionTest, CddSetAll) { + CloudDeviceDescription description; + + ContentTypesCapability content_types; + ColorCapability color; + DuplexCapability duplex; + OrientationCapability orientation; + MarginsCapability margins; + DpiCapability dpi; + FitToPageCapability fit_to_page; + MediaCapability media; + CopiesCapability copies; + PageRangeCapability page_range; + CollateCapability collate; + ReverseCapability reverse; + + content_types.AddOption("image/pwg-raster"); + content_types.AddOption("image/jpeg"); + + color.AddDefaultOption(Color(STANDARD_COLOR), true); + color.AddOption(Color(STANDARD_MONOCHROME)); + Color custom(CUSTOM_MONOCHROME); + custom.vendor_id = "123"; + custom.custom_display_name = "monochrome"; + color.AddOption(custom); + + duplex.AddDefaultOption(LONG_EDGE, true); + duplex.AddOption(SHORT_EDGE); + duplex.AddOption(NO_DUPLEX); + + orientation.AddOption(PORTRAIT); + orientation.AddOption(LANDSCAPE); + orientation.AddDefaultOption(AUTO_ORIENTATION, true); + + margins.AddDefaultOption(Margins(NO_MARGINS, 0, 0, 0, 0), true); + margins.AddOption(Margins(STANDARD_MARGINS, 100, 200, 300, 400)); + margins.AddOption(Margins(CUSTOM_MARGINS, 1, 2, 3, 4)); + + dpi.AddOption(Dpi(150, 250)); + dpi.AddDefaultOption(Dpi(600, 1600), true); + + fit_to_page.AddDefaultOption(NO_FITTING, true); + fit_to_page.AddOption(FIT_TO_PAGE); + fit_to_page.AddOption(GROW_TO_PAGE); + fit_to_page.AddOption(SHRINK_TO_PAGE); + fit_to_page.AddOption(FILL_PAGE); + + media.AddDefaultOption(Media(NA_LETTER, 2222, 3333), true); + media.AddOption(Media(ISO_A6, 4444, 5555)); + media.AddOption(Media(JPN_YOU4, 6666, 7777)); + media.AddOption(Media("FEED", 1111, 0)); + + collate.set_default_value(false); + reverse.set_default_value(true); + + content_types.SaveTo(&description); + color.SaveTo(&description); + duplex.SaveTo(&description); + orientation.SaveTo(&description); + copies.SaveTo(&description); + margins.SaveTo(&description); + dpi.SaveTo(&description); + fit_to_page.SaveTo(&description); + page_range.SaveTo(&description); + media.SaveTo(&description); + collate.SaveTo(&description); + reverse.SaveTo(&description); + + EXPECT_EQ(NormalizeJson(kCdd), NormalizeJson(description.ToString())); +} + +TEST(PrinterDescriptionTest, CddGetAll) { + CloudDeviceDescription description; + ASSERT_TRUE(description.InitFromString(NormalizeJson(kCdd))); + + ContentTypesCapability content_types; + ColorCapability color; + DuplexCapability duplex; + OrientationCapability orientation; + MarginsCapability margins; + DpiCapability dpi; + FitToPageCapability fit_to_page; + MediaCapability media; + CopiesCapability copies; + PageRangeCapability page_range; + CollateCapability collate; + ReverseCapability reverse; + + EXPECT_TRUE(content_types.LoadFrom(description)); + EXPECT_TRUE(color.LoadFrom(description)); + EXPECT_TRUE(duplex.LoadFrom(description)); + EXPECT_TRUE(orientation.LoadFrom(description)); + EXPECT_TRUE(copies.LoadFrom(description)); + EXPECT_TRUE(margins.LoadFrom(description)); + EXPECT_TRUE(dpi.LoadFrom(description)); + EXPECT_TRUE(fit_to_page.LoadFrom(description)); + EXPECT_TRUE(page_range.LoadFrom(description)); + EXPECT_TRUE(media.LoadFrom(description)); + EXPECT_TRUE(collate.LoadFrom(description)); + EXPECT_TRUE(reverse.LoadFrom(description)); + EXPECT_TRUE(media.LoadFrom(description)); + + EXPECT_TRUE(content_types.Contains("image/pwg-raster")); + EXPECT_TRUE(content_types.Contains("image/jpeg")); + + EXPECT_TRUE(color.Contains(Color(STANDARD_COLOR))); + EXPECT_TRUE(color.Contains(Color(STANDARD_MONOCHROME))); + Color custom(CUSTOM_MONOCHROME); + custom.vendor_id = "123"; + custom.custom_display_name = "monochrome"; + EXPECT_TRUE(color.Contains(custom)); + EXPECT_EQ(Color(STANDARD_COLOR), color.GetDefault()); + + EXPECT_TRUE(duplex.Contains(LONG_EDGE)); + EXPECT_TRUE(duplex.Contains(SHORT_EDGE)); + EXPECT_TRUE(duplex.Contains(NO_DUPLEX)); + EXPECT_EQ(LONG_EDGE, duplex.GetDefault()); + + EXPECT_TRUE(orientation.Contains(PORTRAIT)); + EXPECT_TRUE(orientation.Contains(LANDSCAPE)); + EXPECT_TRUE(orientation.Contains(AUTO_ORIENTATION)); + EXPECT_EQ(AUTO_ORIENTATION, orientation.GetDefault()); + + EXPECT_TRUE(margins.Contains(Margins(NO_MARGINS, 0, 0, 0, 0))); + EXPECT_TRUE(margins.Contains(Margins(STANDARD_MARGINS, 100, 200, 300, 400))); + EXPECT_TRUE(margins.Contains(Margins(CUSTOM_MARGINS, 1, 2, 3, 4))); + EXPECT_EQ(Margins(NO_MARGINS, 0, 0, 0, 0), margins.GetDefault()); + + EXPECT_TRUE(dpi.Contains(Dpi(150, 250))); + EXPECT_TRUE(dpi.Contains(Dpi(600, 1600))); + EXPECT_EQ(Dpi(600, 1600), dpi.GetDefault()); + + EXPECT_TRUE(fit_to_page.Contains(NO_FITTING)); + EXPECT_TRUE(fit_to_page.Contains(FIT_TO_PAGE)); + EXPECT_TRUE(fit_to_page.Contains(GROW_TO_PAGE)); + EXPECT_TRUE(fit_to_page.Contains(SHRINK_TO_PAGE)); + EXPECT_TRUE(fit_to_page.Contains(FILL_PAGE)); + EXPECT_EQ(NO_FITTING, fit_to_page.GetDefault()); + + EXPECT_TRUE(media.Contains(Media(NA_LETTER, 2222, 3333))); + EXPECT_TRUE(media.Contains(Media(ISO_A6, 4444, 5555))); + EXPECT_TRUE(media.Contains(Media(JPN_YOU4, 6666, 7777))); + EXPECT_TRUE(media.Contains(Media("FEED", 1111, 0))); + EXPECT_EQ(Media(NA_LETTER, 2222, 3333), media.GetDefault()); + + EXPECT_FALSE(collate.default_value()); + EXPECT_TRUE(reverse.default_value()); + + EXPECT_EQ(NormalizeJson(kCdd), NormalizeJson(description.ToString())); +} + +TEST(PrinterDescriptionTest, CjtInit) { + CloudDeviceDescription description; + EXPECT_EQ(NormalizeJson(kDefaultCjt), NormalizeJson(description.ToString())); + + ColorTicketItem color; + DuplexTicketItem duplex; + OrientationTicketItem orientation; + MarginsTicketItem margins; + DpiTicketItem dpi; + FitToPageTicketItem fit_to_page; + MediaTicketItem media; + CopiesTicketItem copies; + PageRangeTicketItem page_range; + CollateTicketItem collate; + ReverseTicketItem reverse; + + EXPECT_FALSE(color.LoadFrom(description)); + EXPECT_FALSE(duplex.LoadFrom(description)); + EXPECT_FALSE(orientation.LoadFrom(description)); + EXPECT_FALSE(copies.LoadFrom(description)); + EXPECT_FALSE(margins.LoadFrom(description)); + EXPECT_FALSE(dpi.LoadFrom(description)); + EXPECT_FALSE(fit_to_page.LoadFrom(description)); + EXPECT_FALSE(page_range.LoadFrom(description)); + EXPECT_FALSE(media.LoadFrom(description)); + EXPECT_FALSE(collate.LoadFrom(description)); + EXPECT_FALSE(reverse.LoadFrom(description)); + EXPECT_FALSE(media.LoadFrom(description)); +} + +TEST(PrinterDescriptionTest, CjtInvalid) { + CloudDeviceDescription ticket; + EXPECT_FALSE(ticket.InitFromString(NormalizeJson(kBadVersionCjt))); +} + +TEST(PrinterDescriptionTest, GjtSetAll) { + CloudDeviceDescription description; + + ColorTicketItem color; + DuplexTicketItem duplex; + OrientationTicketItem orientation; + MarginsTicketItem margins; + DpiTicketItem dpi; + FitToPageTicketItem fit_to_page; + MediaTicketItem media; + CopiesTicketItem copies; + PageRangeTicketItem page_range; + CollateTicketItem collate; + ReverseTicketItem reverse; + + color.set_value(Color(STANDARD_MONOCHROME)); + duplex.set_value(NO_DUPLEX); + orientation.set_value(LANDSCAPE); + copies.set_value(123); + margins.set_value(Margins(CUSTOM_MARGINS, 7, 6, 3, 1)); + dpi.set_value(Dpi(562, 125)); + fit_to_page.set_value(SHRINK_TO_PAGE); + PageRange page_ranges; + page_ranges.push_back(Interval(1, 99)); + page_ranges.push_back(Interval(150)); + page_range.set_value(page_ranges); + media.set_value(Media(ISO_C7C6, 4261, 334)); + collate.set_value(false); + reverse.set_value(true); + + color.SaveTo(&description); + duplex.SaveTo(&description); + orientation.SaveTo(&description); + copies.SaveTo(&description); + margins.SaveTo(&description); + dpi.SaveTo(&description); + fit_to_page.SaveTo(&description); + page_range.SaveTo(&description); + media.SaveTo(&description); + collate.SaveTo(&description); + reverse.SaveTo(&description); + + EXPECT_EQ(NormalizeJson(kCjt), NormalizeJson(description.ToString())); +} + +TEST(PrinterDescriptionTest, CjtGetAll) { + CloudDeviceDescription description; + ASSERT_TRUE(description.InitFromString(NormalizeJson(kCjt))); + + ColorTicketItem color; + DuplexTicketItem duplex; + OrientationTicketItem orientation; + MarginsTicketItem margins; + DpiTicketItem dpi; + FitToPageTicketItem fit_to_page; + MediaTicketItem media; + CopiesTicketItem copies; + PageRangeTicketItem page_range; + CollateTicketItem collate; + ReverseTicketItem reverse; + + EXPECT_TRUE(color.LoadFrom(description)); + EXPECT_TRUE(duplex.LoadFrom(description)); + EXPECT_TRUE(orientation.LoadFrom(description)); + EXPECT_TRUE(copies.LoadFrom(description)); + EXPECT_TRUE(margins.LoadFrom(description)); + EXPECT_TRUE(dpi.LoadFrom(description)); + EXPECT_TRUE(fit_to_page.LoadFrom(description)); + EXPECT_TRUE(page_range.LoadFrom(description)); + EXPECT_TRUE(media.LoadFrom(description)); + EXPECT_TRUE(collate.LoadFrom(description)); + EXPECT_TRUE(reverse.LoadFrom(description)); + EXPECT_TRUE(media.LoadFrom(description)); + + EXPECT_EQ(color.value(), Color(STANDARD_MONOCHROME)); + EXPECT_EQ(duplex.value(), NO_DUPLEX); + EXPECT_EQ(orientation.value(), LANDSCAPE); + EXPECT_EQ(copies.value(), 123); + EXPECT_EQ(margins.value(), Margins(CUSTOM_MARGINS, 7, 6, 3, 1)); + EXPECT_EQ(dpi.value(), Dpi(562, 125)); + EXPECT_EQ(fit_to_page.value(), SHRINK_TO_PAGE); + PageRange page_ranges; + page_ranges.push_back(Interval(1, 99)); + page_ranges.push_back(Interval(150)); + EXPECT_EQ(page_range.value(), page_ranges); + EXPECT_EQ(media.value(), Media(ISO_C7C6, 4261, 334)); + EXPECT_FALSE(collate.value()); + EXPECT_TRUE(reverse.value()); + + EXPECT_EQ(NormalizeJson(kCjt), NormalizeJson(description.ToString())); +} + +} // namespace printer + +} // namespace cloud_devices |