Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / components / cloud_devices / common / printer_description.cc
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "components/cloud_devices/common/printer_description.h"
6
7 #include <algorithm>
8
9 #include "base/json/json_reader.h"
10 #include "base/json/json_writer.h"
11 #include "base/strings/string_util.h"
12 #include "base/values.h"
13 #include "components/cloud_devices/common/cloud_device_description_consts.h"
14 #include "components/cloud_devices/common/description_items_inl.h"
15
16 namespace cloud_devices {
17
18 namespace printer {
19
20 namespace {
21
22 const int32 kMaxPageNumber = 1000000;
23
24 const char kSectionPrint[] = "print";
25 const char kSectionPrinter[] = "printer";
26
27 const char kCustomName[] = "custom_display_name";
28 const char kKeyContentType[] = "content_type";
29 const char kKeyName[] = "name";
30 const char kKeyType[] = "type";
31 const char kKeyVendorId[] = "vendor_id";
32
33 // extern is required to be used in templates.
34 extern const char kOptionCollate[] = "collate";
35 extern const char kOptionColor[] = "color";
36 extern const char kOptionContentType[] = "supported_content_type";
37 extern const char kOptionCopies[] = "copies";
38 extern const char kOptionDpi[] = "dpi";
39 extern const char kOptionDuplex[] = "duplex";
40 extern const char kOptionFitToPage[] = "fit_to_page";
41 extern const char kOptionMargins[] = "margins";
42 extern const char kOptionMediaSize[] = "media_size";
43 extern const char kOptionPageOrientation[] = "page_orientation";
44 extern const char kOptionPageRange[] = "page_range";
45 extern const char kOptionReverse[] = "reverse_order";
46 extern const char kOptionPwgRasterConfig[] = "pwg_raster_config";
47
48 const char kMargineBottom[] = "bottom_microns";
49 const char kMargineLeft[] = "left_microns";
50 const char kMargineRight[] = "right_microns";
51 const char kMargineTop[] = "top_microns";
52
53 const char kDpiHorizontal[] = "horizontal_dpi";
54 const char kDpiVertical[] = "vertical_dpi";
55
56 const char kMediaWidth[] = "width_microns";
57 const char kMediaHeight[] = "height_microns";
58 const char kMediaIsContinuous[] = "is_continuous_feed";
59
60 const char kPageRangeInterval[] = "interval";
61 const char kPageRangeEnd[] = "end";
62 const char kPageRangeStart[] = "start";
63
64 const char kPwgRasterDocumentSheetBack[] = "document_sheet_back";
65 const char kPwgRasterReverseOrderStreaming[] = "reverse_order_streaming";
66 const char kPwgRasterRotateAllPages[] = "rotate_all_pages";
67
68 const char kTypeColorColor[] = "STANDARD_COLOR";
69 const char kTypeColorMonochrome[] = "STANDARD_MONOCHROME";
70 const char kTypeColorCustomColor[] = "CUSTOM_COLOR";
71 const char kTypeColorCustomMonochrome[] = "CUSTOM_MONOCHROME";
72 const char kTypeColorAuto[] = "AUTO";
73
74 const char kTypeDuplexLongEdge[] = "LONG_EDGE";
75 const char kTypeDuplexNoDuplex[] = "NO_DUPLEX";
76 const char kTypeDuplexShortEdge[] = "SHORT_EDGE";
77
78 const char kTypeFitToPageFillPage[] = "FILL_PAGE";
79 const char kTypeFitToPageFitToPage[] = "FIT_TO_PAGE";
80 const char kTypeFitToPageGrowToPage[] = "GROW_TO_PAGE";
81 const char kTypeFitToPageNoFitting[] = "NO_FITTING";
82 const char kTypeFitToPageShrinkToPage[] = "SHRINK_TO_PAGE";
83
84 const char kTypeMarginsBorderless[] = "BORDERLESS";
85 const char kTypeMarginsCustom[] = "CUSTOM";
86 const char kTypeMarginsStandard[] = "STANDARD";
87 const char kTypeOrientationAuto[] = "AUTO";
88
89 const char kTypeOrientationLandscape[] = "LANDSCAPE";
90 const char kTypeOrientationPortrait[] = "PORTRAIT";
91
92 const char kTypeDocumentSheetBackNormal[] = "NORMAL";
93 const char kTypeDocumentSheetBackRotated[] = "ROTATED";
94 const char kTypeDocumentSheetBackManualTumble[] = "MANUAL_TUMBLE";
95 const char kTypeDocumentSheetBackFlipped[] = "FLIPPED";
96
97 const struct ColorNames {
98   ColorType id;
99   const char* const json_name;
100 } kColorNames[] = {
101       {STANDARD_COLOR, kTypeColorColor},
102       {STANDARD_MONOCHROME, kTypeColorMonochrome},
103       {CUSTOM_COLOR, kTypeColorCustomColor},
104       {CUSTOM_MONOCHROME, kTypeColorCustomMonochrome},
105       {AUTO_COLOR, kTypeColorAuto},
106 };
107
108 const struct DuplexNames {
109   DuplexType id;
110   const char* const json_name;
111 } kDuplexNames[] = {
112       {NO_DUPLEX, kTypeDuplexNoDuplex},
113       {LONG_EDGE, kTypeDuplexLongEdge},
114       {SHORT_EDGE, kTypeDuplexShortEdge},
115 };
116
117 const struct OrientationNames {
118   OrientationType id;
119   const char* const json_name;
120 } kOrientationNames[] = {
121       {PORTRAIT, kTypeOrientationPortrait},
122       {LANDSCAPE, kTypeOrientationLandscape},
123       {AUTO_ORIENTATION, kTypeOrientationAuto},
124 };
125
126 const struct MarginsNames {
127   MarginsType id;
128   const char* const json_name;
129 } kMarginsNames[] = {
130       {NO_MARGINS, kTypeMarginsBorderless},
131       {STANDARD_MARGINS, kTypeMarginsStandard},
132       {CUSTOM_MARGINS, kTypeMarginsCustom},
133 };
134
135 const struct FitToPageNames {
136   FitToPageType id;
137   const char* const json_name;
138 } kFitToPageNames[] = {
139       {NO_FITTING, kTypeFitToPageNoFitting},
140       {FIT_TO_PAGE, kTypeFitToPageFitToPage},
141       {GROW_TO_PAGE, kTypeFitToPageGrowToPage},
142       {SHRINK_TO_PAGE, kTypeFitToPageShrinkToPage},
143       {FILL_PAGE, kTypeFitToPageFillPage},
144 };
145
146 const struct DocumentSheetBackNames {
147   DocumentSheetBack id;
148   const char* const json_name;
149 } kDocumentSheetBackNames[] = {
150       {NORMAL, kTypeDocumentSheetBackNormal},
151       {ROTATED, kTypeDocumentSheetBackRotated},
152       {MANUAL_TUMBLE, kTypeDocumentSheetBackManualTumble},
153       {FLIPPED, kTypeDocumentSheetBackFlipped}};
154
155 const int32 kInchToUm = 25400;
156 const int32 kMmToUm = 1000;
157 const int32 kSizeTrasholdUm = 1000;
158
159 #define MAP_CLOUD_PRINT_MEDIA_TYPE(type, width, height, unit_um) \
160   {                                                              \
161     type, #type, static_cast<int>(width* unit_um + 0.5),         \
162         static_cast<int>(height* unit_um + 0.5)                  \
163   }
164
165 const struct MadiaDefinition {
166   MediaType id;
167   const char* const json_name;
168   int width_um;
169   int height_um;
170 } kMediaDefinitions[] = {
171       {CUSTOM_MEDIA, "CUSTOM", 0, 0},
172       MAP_CLOUD_PRINT_MEDIA_TYPE(NA_INDEX_3X5, 3, 5, kInchToUm),
173       MAP_CLOUD_PRINT_MEDIA_TYPE(NA_PERSONAL, 3.625f, 6.5f, kInchToUm),
174       MAP_CLOUD_PRINT_MEDIA_TYPE(NA_MONARCH, 3.875f, 7.5f, kInchToUm),
175       MAP_CLOUD_PRINT_MEDIA_TYPE(NA_NUMBER_9, 3.875f, 8.875f, kInchToUm),
176       MAP_CLOUD_PRINT_MEDIA_TYPE(NA_INDEX_4X6, 4, 6, kInchToUm),
177       MAP_CLOUD_PRINT_MEDIA_TYPE(NA_NUMBER_10, 4.125f, 9.5f, kInchToUm),
178       MAP_CLOUD_PRINT_MEDIA_TYPE(NA_A2, 4.375f, 5.75f, kInchToUm),
179       MAP_CLOUD_PRINT_MEDIA_TYPE(NA_NUMBER_11, 4.5f, 10.375f, kInchToUm),
180       MAP_CLOUD_PRINT_MEDIA_TYPE(NA_NUMBER_12, 4.75f, 11, kInchToUm),
181       MAP_CLOUD_PRINT_MEDIA_TYPE(NA_5X7, 5, 7, kInchToUm),
182       MAP_CLOUD_PRINT_MEDIA_TYPE(NA_INDEX_5X8, 5, 8, kInchToUm),
183       MAP_CLOUD_PRINT_MEDIA_TYPE(NA_NUMBER_14, 5, 11.5f, kInchToUm),
184       MAP_CLOUD_PRINT_MEDIA_TYPE(NA_INVOICE, 5.5f, 8.5f, kInchToUm),
185       MAP_CLOUD_PRINT_MEDIA_TYPE(NA_INDEX_4X6_EXT, 6, 8, kInchToUm),
186       MAP_CLOUD_PRINT_MEDIA_TYPE(NA_6X9, 6, 9, kInchToUm),
187       MAP_CLOUD_PRINT_MEDIA_TYPE(NA_C5, 6.5f, 9.5f, kInchToUm),
188       MAP_CLOUD_PRINT_MEDIA_TYPE(NA_7X9, 7, 9, kInchToUm),
189       MAP_CLOUD_PRINT_MEDIA_TYPE(NA_EXECUTIVE, 7.25f, 10.5f, kInchToUm),
190       MAP_CLOUD_PRINT_MEDIA_TYPE(NA_GOVT_LETTER, 8, 10, kInchToUm),
191       MAP_CLOUD_PRINT_MEDIA_TYPE(NA_GOVT_LEGAL, 8, 13, kInchToUm),
192       MAP_CLOUD_PRINT_MEDIA_TYPE(NA_QUARTO, 8.5f, 10.83f, kInchToUm),
193       MAP_CLOUD_PRINT_MEDIA_TYPE(NA_LETTER, 8.5f, 11, kInchToUm),
194       MAP_CLOUD_PRINT_MEDIA_TYPE(NA_FANFOLD_EUR, 8.5f, 12, kInchToUm),
195       MAP_CLOUD_PRINT_MEDIA_TYPE(NA_LETTER_PLUS, 8.5f, 12.69f, kInchToUm),
196       MAP_CLOUD_PRINT_MEDIA_TYPE(NA_FOOLSCAP, 8.5f, 13, kInchToUm),
197       MAP_CLOUD_PRINT_MEDIA_TYPE(NA_LEGAL, 8.5f, 14, kInchToUm),
198       MAP_CLOUD_PRINT_MEDIA_TYPE(NA_SUPER_A, 8.94f, 14, kInchToUm),
199       MAP_CLOUD_PRINT_MEDIA_TYPE(NA_9X11, 9, 11, kInchToUm),
200       MAP_CLOUD_PRINT_MEDIA_TYPE(NA_ARCH_A, 9, 12, kInchToUm),
201       MAP_CLOUD_PRINT_MEDIA_TYPE(NA_LETTER_EXTRA, 9.5f, 12, kInchToUm),
202       MAP_CLOUD_PRINT_MEDIA_TYPE(NA_LEGAL_EXTRA, 9.5f, 15, kInchToUm),
203       MAP_CLOUD_PRINT_MEDIA_TYPE(NA_10X11, 10, 11, kInchToUm),
204       MAP_CLOUD_PRINT_MEDIA_TYPE(NA_10X13, 10, 13, kInchToUm),
205       MAP_CLOUD_PRINT_MEDIA_TYPE(NA_10X14, 10, 14, kInchToUm),
206       MAP_CLOUD_PRINT_MEDIA_TYPE(NA_10X15, 10, 15, kInchToUm),
207       MAP_CLOUD_PRINT_MEDIA_TYPE(NA_11X12, 11, 12, kInchToUm),
208       MAP_CLOUD_PRINT_MEDIA_TYPE(NA_EDP, 11, 14, kInchToUm),
209       MAP_CLOUD_PRINT_MEDIA_TYPE(NA_FANFOLD_US, 11, 14.875f, kInchToUm),
210       MAP_CLOUD_PRINT_MEDIA_TYPE(NA_11X15, 11, 15, kInchToUm),
211       MAP_CLOUD_PRINT_MEDIA_TYPE(NA_LEDGER, 11, 17, kInchToUm),
212       MAP_CLOUD_PRINT_MEDIA_TYPE(NA_EUR_EDP, 12, 14, kInchToUm),
213       MAP_CLOUD_PRINT_MEDIA_TYPE(NA_ARCH_B, 12, 18, kInchToUm),
214       MAP_CLOUD_PRINT_MEDIA_TYPE(NA_12X19, 12, 19, kInchToUm),
215       MAP_CLOUD_PRINT_MEDIA_TYPE(NA_B_PLUS, 12, 19.17f, kInchToUm),
216       MAP_CLOUD_PRINT_MEDIA_TYPE(NA_SUPER_B, 13, 19, kInchToUm),
217       MAP_CLOUD_PRINT_MEDIA_TYPE(NA_C, 17, 22, kInchToUm),
218       MAP_CLOUD_PRINT_MEDIA_TYPE(NA_ARCH_C, 18, 24, kInchToUm),
219       MAP_CLOUD_PRINT_MEDIA_TYPE(NA_D, 22, 34, kInchToUm),
220       MAP_CLOUD_PRINT_MEDIA_TYPE(NA_ARCH_D, 24, 36, kInchToUm),
221       MAP_CLOUD_PRINT_MEDIA_TYPE(NA_ASME_F, 28, 40, kInchToUm),
222       MAP_CLOUD_PRINT_MEDIA_TYPE(NA_WIDE_FORMAT, 30, 42, kInchToUm),
223       MAP_CLOUD_PRINT_MEDIA_TYPE(NA_E, 34, 44, kInchToUm),
224       MAP_CLOUD_PRINT_MEDIA_TYPE(NA_ARCH_E, 36, 48, kInchToUm),
225       MAP_CLOUD_PRINT_MEDIA_TYPE(NA_F, 44, 68, kInchToUm),
226       MAP_CLOUD_PRINT_MEDIA_TYPE(ROC_16K, 7.75f, 10.75f, kInchToUm),
227       MAP_CLOUD_PRINT_MEDIA_TYPE(ROC_8K, 10.75f, 15.5f, kInchToUm),
228       MAP_CLOUD_PRINT_MEDIA_TYPE(PRC_32K, 97, 151, kMmToUm),
229       MAP_CLOUD_PRINT_MEDIA_TYPE(PRC_1, 102, 165, kMmToUm),
230       MAP_CLOUD_PRINT_MEDIA_TYPE(PRC_2, 102, 176, kMmToUm),
231       MAP_CLOUD_PRINT_MEDIA_TYPE(PRC_4, 110, 208, kMmToUm),
232       MAP_CLOUD_PRINT_MEDIA_TYPE(PRC_5, 110, 220, kMmToUm),
233       MAP_CLOUD_PRINT_MEDIA_TYPE(PRC_8, 120, 309, kMmToUm),
234       MAP_CLOUD_PRINT_MEDIA_TYPE(PRC_6, 120, 230, kMmToUm),
235       MAP_CLOUD_PRINT_MEDIA_TYPE(PRC_3, 125, 176, kMmToUm),
236       MAP_CLOUD_PRINT_MEDIA_TYPE(PRC_16K, 146, 215, kMmToUm),
237       MAP_CLOUD_PRINT_MEDIA_TYPE(PRC_7, 160, 230, kMmToUm),
238       MAP_CLOUD_PRINT_MEDIA_TYPE(OM_JUURO_KU_KAI, 198, 275, kMmToUm),
239       MAP_CLOUD_PRINT_MEDIA_TYPE(OM_PA_KAI, 267, 389, kMmToUm),
240       MAP_CLOUD_PRINT_MEDIA_TYPE(OM_DAI_PA_KAI, 275, 395, kMmToUm),
241       MAP_CLOUD_PRINT_MEDIA_TYPE(PRC_10, 324, 458, kMmToUm),
242       MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A10, 26, 37, kMmToUm),
243       MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A9, 37, 52, kMmToUm),
244       MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A8, 52, 74, kMmToUm),
245       MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A7, 74, 105, kMmToUm),
246       MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A6, 105, 148, kMmToUm),
247       MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A5, 148, 210, kMmToUm),
248       MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A5_EXTRA, 174, 235, kMmToUm),
249       MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A4, 210, 297, kMmToUm),
250       MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A4_TAB, 225, 297, kMmToUm),
251       MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A4_EXTRA, 235, 322, kMmToUm),
252       MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A3, 297, 420, kMmToUm),
253       MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A4X3, 297, 630, kMmToUm),
254       MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A4X4, 297, 841, kMmToUm),
255       MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A4X5, 297, 1051, kMmToUm),
256       MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A4X6, 297, 1261, kMmToUm),
257       MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A4X7, 297, 1471, kMmToUm),
258       MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A4X8, 297, 1682, kMmToUm),
259       MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A4X9, 297, 1892, kMmToUm),
260       MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A3_EXTRA, 322, 445, kMmToUm),
261       MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A2, 420, 594, kMmToUm),
262       MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A3X3, 420, 891, kMmToUm),
263       MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A3X4, 420, 1189, kMmToUm),
264       MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A3X5, 420, 1486, kMmToUm),
265       MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A3X6, 420, 1783, kMmToUm),
266       MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A3X7, 420, 2080, kMmToUm),
267       MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A1, 594, 841, kMmToUm),
268       MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A2X3, 594, 1261, kMmToUm),
269       MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A2X4, 594, 1682, kMmToUm),
270       MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A2X5, 594, 2102, kMmToUm),
271       MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A0, 841, 1189, kMmToUm),
272       MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A1X3, 841, 1783, kMmToUm),
273       MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A1X4, 841, 2378, kMmToUm),
274       MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_2A0, 1189, 1682, kMmToUm),
275       MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_A0X3, 1189, 2523, kMmToUm),
276       MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_B10, 31, 44, kMmToUm),
277       MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_B9, 44, 62, kMmToUm),
278       MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_B8, 62, 88, kMmToUm),
279       MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_B7, 88, 125, kMmToUm),
280       MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_B6, 125, 176, kMmToUm),
281       MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_B6C4, 125, 324, kMmToUm),
282       MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_B5, 176, 250, kMmToUm),
283       MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_B5_EXTRA, 201, 276, kMmToUm),
284       MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_B4, 250, 353, kMmToUm),
285       MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_B3, 353, 500, kMmToUm),
286       MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_B2, 500, 707, kMmToUm),
287       MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_B1, 707, 1000, kMmToUm),
288       MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_B0, 1000, 1414, kMmToUm),
289       MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_C10, 28, 40, kMmToUm),
290       MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_C9, 40, 57, kMmToUm),
291       MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_C8, 57, 81, kMmToUm),
292       MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_C7, 81, 114, kMmToUm),
293       MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_C7C6, 81, 162, kMmToUm),
294       MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_C6, 114, 162, kMmToUm),
295       MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_C6C5, 114, 229, kMmToUm),
296       MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_C5, 162, 229, kMmToUm),
297       MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_C4, 229, 324, kMmToUm),
298       MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_C3, 324, 458, kMmToUm),
299       MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_C2, 458, 648, kMmToUm),
300       MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_C1, 648, 917, kMmToUm),
301       MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_C0, 917, 1297, kMmToUm),
302       MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_DL, 110, 220, kMmToUm),
303       MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_RA2, 430, 610, kMmToUm),
304       MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_SRA2, 450, 640, kMmToUm),
305       MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_RA1, 610, 860, kMmToUm),
306       MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_SRA1, 640, 900, kMmToUm),
307       MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_RA0, 860, 1220, kMmToUm),
308       MAP_CLOUD_PRINT_MEDIA_TYPE(ISO_SRA0, 900, 1280, kMmToUm),
309       MAP_CLOUD_PRINT_MEDIA_TYPE(JIS_B10, 32, 45, kMmToUm),
310       MAP_CLOUD_PRINT_MEDIA_TYPE(JIS_B9, 45, 64, kMmToUm),
311       MAP_CLOUD_PRINT_MEDIA_TYPE(JIS_B8, 64, 91, kMmToUm),
312       MAP_CLOUD_PRINT_MEDIA_TYPE(JIS_B7, 91, 128, kMmToUm),
313       MAP_CLOUD_PRINT_MEDIA_TYPE(JIS_B6, 128, 182, kMmToUm),
314       MAP_CLOUD_PRINT_MEDIA_TYPE(JIS_B5, 182, 257, kMmToUm),
315       MAP_CLOUD_PRINT_MEDIA_TYPE(JIS_B4, 257, 364, kMmToUm),
316       MAP_CLOUD_PRINT_MEDIA_TYPE(JIS_B3, 364, 515, kMmToUm),
317       MAP_CLOUD_PRINT_MEDIA_TYPE(JIS_B2, 515, 728, kMmToUm),
318       MAP_CLOUD_PRINT_MEDIA_TYPE(JIS_B1, 728, 1030, kMmToUm),
319       MAP_CLOUD_PRINT_MEDIA_TYPE(JIS_B0, 1030, 1456, kMmToUm),
320       MAP_CLOUD_PRINT_MEDIA_TYPE(JIS_EXEC, 216, 330, kMmToUm),
321       MAP_CLOUD_PRINT_MEDIA_TYPE(JPN_CHOU4, 90, 205, kMmToUm),
322       MAP_CLOUD_PRINT_MEDIA_TYPE(JPN_HAGAKI, 100, 148, kMmToUm),
323       MAP_CLOUD_PRINT_MEDIA_TYPE(JPN_YOU4, 105, 235, kMmToUm),
324       MAP_CLOUD_PRINT_MEDIA_TYPE(JPN_CHOU2, 111.1f, 146, kMmToUm),
325       MAP_CLOUD_PRINT_MEDIA_TYPE(JPN_CHOU3, 120, 235, kMmToUm),
326       MAP_CLOUD_PRINT_MEDIA_TYPE(JPN_OUFUKU, 148, 200, kMmToUm),
327       MAP_CLOUD_PRINT_MEDIA_TYPE(JPN_KAHU, 240, 322.1f, kMmToUm),
328       MAP_CLOUD_PRINT_MEDIA_TYPE(JPN_KAKU2, 240, 332, kMmToUm),
329       MAP_CLOUD_PRINT_MEDIA_TYPE(OM_SMALL_PHOTO, 100, 150, kMmToUm),
330       MAP_CLOUD_PRINT_MEDIA_TYPE(OM_ITALIAN, 110, 230, kMmToUm),
331       MAP_CLOUD_PRINT_MEDIA_TYPE(OM_POSTFIX, 114, 229, kMmToUm),
332       MAP_CLOUD_PRINT_MEDIA_TYPE(OM_LARGE_PHOTO, 200, 300, kMmToUm),
333       MAP_CLOUD_PRINT_MEDIA_TYPE(OM_FOLIO, 210, 330, kMmToUm),
334       MAP_CLOUD_PRINT_MEDIA_TYPE(OM_FOLIO_SP, 215, 315, kMmToUm),
335       MAP_CLOUD_PRINT_MEDIA_TYPE(OM_INVITE, 220, 220, kMmToUm)};
336 #undef MAP_CLOUD_PRINT_MEDIA_TYPE
337
338 const MadiaDefinition* FindMediaBySize(int32 width_um, int32 height_um) {
339   const MadiaDefinition* result = NULL;
340   for (size_t i = 0; i < arraysize(kMediaDefinitions); ++i) {
341     int32 diff = std::max(std::abs(width_um - kMediaDefinitions[i].width_um),
342                           std::abs(height_um - kMediaDefinitions[i].height_um));
343     if (diff < kSizeTrasholdUm)
344       result = &kMediaDefinitions[i];
345   }
346   return result;
347 }
348
349 template <class T, class IdType>
350 std::string TypeToString(const T& names, IdType id) {
351   for (size_t i = 0; i < arraysize(names); ++i) {
352     if (id == names[i].id)
353       return names[i].json_name;
354   }
355   NOTREACHED();
356   return std::string();
357 }
358
359 template <class T, class IdType>
360 bool TypeFromString(const T& names, const std::string& type, IdType* id) {
361   for (size_t i = 0; i < arraysize(names); ++i) {
362     if (type == names[i].json_name) {
363       *id = names[i].id;
364       return true;
365     }
366   }
367   return false;
368 }
369
370 }  // namespace
371
372 PwgRasterConfig::PwgRasterConfig()
373     : document_sheet_back(ROTATED),
374       reverse_order_streaming(false),
375       rotate_all_pages(false) {
376 }
377
378 Color::Color() : type(AUTO_COLOR) {
379 }
380
381 Color::Color(ColorType type) : type(type) {
382 }
383
384 bool Color::operator==(const Color& other) const {
385   return type == other.type && vendor_id == other.vendor_id &&
386          custom_display_name == other.custom_display_name;
387 }
388
389 bool Color::IsValid() const {
390   if (type != CUSTOM_COLOR && type != CUSTOM_MONOCHROME)
391     return true;
392   return !vendor_id.empty() && !custom_display_name.empty();
393 }
394
395 Margins::Margins()
396     : type(STANDARD_MARGINS), top_um(0), right_um(0), bottom_um(0), left_um(0) {
397 }
398
399 Margins::Margins(MarginsType type,
400                  int32 top_um,
401                  int32 right_um,
402                  int32 bottom_um,
403                  int32 left_um)
404     : type(type),
405       top_um(top_um),
406       right_um(right_um),
407       bottom_um(bottom_um),
408       left_um(left_um) {
409 }
410
411 bool Margins::operator==(const Margins& other) const {
412   return type == other.type && top_um == other.top_um &&
413          right_um == other.right_um && bottom_um == other.bottom_um;
414 }
415
416 Dpi::Dpi() : horizontal(0), vertical(0) {
417 }
418
419 Dpi::Dpi(int32 horizontal, int32 vertical)
420     : horizontal(horizontal), vertical(vertical) {
421 }
422
423 bool Dpi::IsValid() const {
424   return horizontal > 0 && vertical > 0;
425 }
426
427 bool Dpi::operator==(const Dpi& other) const {
428   return horizontal == other.horizontal && vertical == other.vertical;
429 }
430
431 Media::Media()
432     : type(CUSTOM_MEDIA), width_um(0), height_um(0), is_continuous_feed(false) {
433 }
434
435 Media::Media(MediaType type, int32 width_um, int32 height_um)
436     : type(type),
437       width_um(width_um),
438       height_um(height_um),
439       is_continuous_feed(width_um <= 0 || height_um <= 0) {
440 }
441
442 Media::Media(const std::string& custom_display_name,
443              int32 width_um,
444              int32 height_um)
445     : type(CUSTOM_MEDIA),
446       width_um(width_um),
447       height_um(height_um),
448       is_continuous_feed(width_um <= 0 || height_um <= 0),
449       custom_display_name(custom_display_name) {
450 }
451
452 bool Media::MatchBySize() {
453   const MadiaDefinition* media = FindMediaBySize(width_um, height_um);
454   if (!media)
455     return false;
456   type = media->id;
457   custom_display_name.clear();
458   return true;
459 }
460
461 bool Media::IsValid() const {
462   if (is_continuous_feed) {
463     if (width_um <= 0 && height_um <= 0)
464       return false;
465   } else {
466     if (width_um <= 0 || height_um <= 0)
467       return false;
468   }
469   return true;
470 }
471
472 bool Media::operator==(const Media& other) const {
473   return type == other.type && width_um == other.width_um &&
474          height_um == other.height_um &&
475          is_continuous_feed == other.is_continuous_feed;
476 }
477
478 Interval::Interval() : start(0), end(0) {
479 }
480
481 Interval::Interval(int32 start, int32 end) : start(start), end(end) {
482 }
483
484 Interval::Interval(int32 start) : start(start), end(kMaxPageNumber) {
485 }
486
487 bool Interval::operator==(const Interval& other) const {
488   return start == other.start && end == other.end;
489 }
490
491 template <const char* kName>
492 class ItemsTraits {
493  public:
494   static std::string GetCapabilityPath() {
495     std::string result = kSectionPrinter;
496     result += '.';
497     result += kName;
498     return result;
499   }
500
501   static std::string GetTicketItemPath() {
502     std::string result = kSectionPrint;
503     result += '.';
504     result += kName;
505     return result;
506   }
507 };
508
509 class NoValueValidation {
510  public:
511   template <class Option>
512   static bool IsValid(const Option&) {
513     return true;
514   }
515 };
516
517 class ContentTypeTraits : public NoValueValidation,
518                           public ItemsTraits<kOptionContentType> {
519  public:
520   static bool Load(const base::DictionaryValue& dict, ContentType* option) {
521     return dict.GetString(kKeyContentType, option);
522   }
523
524   static void Save(ContentType option, base::DictionaryValue* dict) {
525     dict->SetString(kKeyContentType, option);
526   }
527 };
528
529 class PwgRasterConfigTraits : public NoValueValidation,
530                               public ItemsTraits<kOptionPwgRasterConfig> {
531  public:
532   static bool Load(const base::DictionaryValue& dict, PwgRasterConfig* option) {
533     std::string document_sheet_back;
534     PwgRasterConfig option_out;
535     if (dict.GetString(kPwgRasterDocumentSheetBack, &document_sheet_back)) {
536       if (!TypeFromString(kDocumentSheetBackNames,
537                           document_sheet_back,
538                           &option_out.document_sheet_back)) {
539         return false;
540       }
541     }
542
543     dict.GetBoolean(kPwgRasterReverseOrderStreaming,
544                     &option_out.reverse_order_streaming);
545     dict.GetBoolean(kPwgRasterRotateAllPages, &option_out.rotate_all_pages);
546     *option = option_out;
547     return true;
548   }
549
550   static void Save(const PwgRasterConfig& option, base::DictionaryValue* dict) {
551     dict->SetString(
552         kPwgRasterDocumentSheetBack,
553         TypeToString(kDocumentSheetBackNames, option.document_sheet_back));
554     if (option.reverse_order_streaming)
555       dict->SetBoolean(kPwgRasterReverseOrderStreaming,
556                        option.reverse_order_streaming);
557
558     if (option.rotate_all_pages)
559       dict->SetBoolean(kPwgRasterRotateAllPages, option.rotate_all_pages);
560   }
561 };
562
563 class ColorTraits : public ItemsTraits<kOptionColor> {
564  public:
565   static bool IsValid(const Color& option) { return option.IsValid(); }
566
567   static bool Load(const base::DictionaryValue& dict, Color* option) {
568     std::string type_str;
569     if (!dict.GetString(kKeyType, &type_str))
570       return false;
571     if (!TypeFromString(kColorNames, type_str, &option->type))
572       return false;
573     dict.GetString(kKeyVendorId, &option->vendor_id);
574     dict.GetString(kCustomName, &option->custom_display_name);
575     return true;
576   }
577
578   static void Save(const Color& option, base::DictionaryValue* dict) {
579     dict->SetString(kKeyType, TypeToString(kColorNames, option.type));
580     if (!option.vendor_id.empty())
581       dict->SetString(kKeyVendorId, option.vendor_id);
582     if (!option.custom_display_name.empty())
583       dict->SetString(kCustomName, option.custom_display_name);
584   }
585 };
586
587 class DuplexTraits : public NoValueValidation,
588                      public ItemsTraits<kOptionDuplex> {
589  public:
590   static bool Load(const base::DictionaryValue& dict, DuplexType* option) {
591     std::string type_str;
592     return dict.GetString(kKeyType, &type_str) &&
593            TypeFromString(kDuplexNames, type_str, option);
594   }
595
596   static void Save(DuplexType option, base::DictionaryValue* dict) {
597     dict->SetString(kKeyType, TypeToString(kDuplexNames, option));
598   }
599 };
600
601 class OrientationTraits : public NoValueValidation,
602                           public ItemsTraits<kOptionPageOrientation> {
603  public:
604   static bool Load(const base::DictionaryValue& dict, OrientationType* option) {
605     std::string type_str;
606     return dict.GetString(kKeyType, &type_str) &&
607            TypeFromString(kOrientationNames, type_str, option);
608   }
609
610   static void Save(OrientationType option, base::DictionaryValue* dict) {
611     dict->SetString(kKeyType, TypeToString(kOrientationNames, option));
612   }
613 };
614
615 class CopiesTraits : public ItemsTraits<kOptionCopies> {
616  public:
617   static bool IsValid(int32 option) { return option >= 1; }
618
619   static bool Load(const base::DictionaryValue& dict, int32* option) {
620     return dict.GetInteger(kOptionCopies, option);
621   }
622
623   static void Save(int32 option, base::DictionaryValue* dict) {
624     dict->SetInteger(kOptionCopies, option);
625   }
626 };
627
628 class MarginsTraits : public NoValueValidation,
629                       public ItemsTraits<kOptionMargins> {
630  public:
631   static bool Load(const base::DictionaryValue& dict, Margins* option) {
632     std::string type_str;
633     if (!dict.GetString(kKeyType, &type_str))
634       return false;
635     if (!TypeFromString(kMarginsNames, type_str, &option->type))
636       return false;
637     return dict.GetInteger(kMargineTop, &option->top_um) &&
638            dict.GetInteger(kMargineRight, &option->right_um) &&
639            dict.GetInteger(kMargineBottom, &option->bottom_um) &&
640            dict.GetInteger(kMargineLeft, &option->left_um);
641   }
642
643   static void Save(const Margins& option, base::DictionaryValue* dict) {
644     dict->SetString(kKeyType, TypeToString(kMarginsNames, option.type));
645     dict->SetInteger(kMargineTop, option.top_um);
646     dict->SetInteger(kMargineRight, option.right_um);
647     dict->SetInteger(kMargineBottom, option.bottom_um);
648     dict->SetInteger(kMargineLeft, option.left_um);
649   }
650 };
651
652 class DpiTraits : public ItemsTraits<kOptionDpi> {
653  public:
654   static bool IsValid(const Dpi& option) { return option.IsValid(); }
655
656   static bool Load(const base::DictionaryValue& dict, Dpi* option) {
657     if (!dict.GetInteger(kDpiHorizontal, &option->horizontal) ||
658         !dict.GetInteger(kDpiVertical, &option->vertical)) {
659       return false;
660     }
661     return true;
662   }
663
664   static void Save(const Dpi& option, base::DictionaryValue* dict) {
665     dict->SetInteger(kDpiHorizontal, option.horizontal);
666     dict->SetInteger(kDpiVertical, option.vertical);
667   }
668 };
669
670 class FitToPageTraits : public NoValueValidation,
671                         public ItemsTraits<kOptionFitToPage> {
672  public:
673   static bool Load(const base::DictionaryValue& dict, FitToPageType* option) {
674     std::string type_str;
675     return dict.GetString(kKeyType, &type_str) &&
676            TypeFromString(kFitToPageNames, type_str, option);
677   }
678
679   static void Save(FitToPageType option, base::DictionaryValue* dict) {
680     dict->SetString(kKeyType, TypeToString(kFitToPageNames, option));
681   }
682 };
683
684 class PageRangeTraits : public ItemsTraits<kOptionPageRange> {
685  public:
686   static bool IsValid(const PageRange& option) {
687     for (size_t i = 0; i < option.size(); ++i) {
688       if (option[i].start < 1 || option[i].end < 1) {
689         return false;
690       }
691     }
692     return true;
693   }
694
695   static bool Load(const base::DictionaryValue& dict, PageRange* option) {
696     const base::ListValue* list = NULL;
697     if (!dict.GetList(kPageRangeInterval, &list))
698       return false;
699     for (size_t i = 0; i < list->GetSize(); ++i) {
700       const base::DictionaryValue* interval = NULL;
701       if (!list->GetDictionary(i, &interval))
702         return false;
703       Interval new_interval(1, kMaxPageNumber);
704       interval->GetInteger(kPageRangeStart, &new_interval.start);
705       interval->GetInteger(kPageRangeEnd, &new_interval.end);
706       option->push_back(new_interval);
707     }
708     return true;
709   }
710
711   static void Save(const PageRange& option, base::DictionaryValue* dict) {
712     if (!option.empty()) {
713       base::ListValue* list = new base::ListValue;
714       dict->Set(kPageRangeInterval, list);
715       for (size_t i = 0; i < option.size(); ++i) {
716         base::DictionaryValue* interval = new base::DictionaryValue;
717         list->Append(interval);
718         interval->SetInteger(kPageRangeStart, option[i].start);
719         if (option[i].end < kMaxPageNumber)
720           interval->SetInteger(kPageRangeEnd, option[i].end);
721       }
722     }
723   }
724 };
725
726 class MediaTraits : public ItemsTraits<kOptionMediaSize> {
727  public:
728   static bool IsValid(const Media& option) { return option.IsValid(); }
729
730   static bool Load(const base::DictionaryValue& dict, Media* option) {
731     std::string type_str;
732     if (dict.GetString(kKeyName, &type_str)) {
733       if (!TypeFromString(kMediaDefinitions, type_str, &option->type))
734         return false;
735     }
736
737     dict.GetInteger(kMediaWidth, &option->width_um);
738     dict.GetInteger(kMediaHeight, &option->height_um);
739     dict.GetBoolean(kMediaIsContinuous, &option->is_continuous_feed);
740     dict.GetString(kCustomName, &option->custom_display_name);
741     return true;
742   }
743
744   static void Save(const Media& option, base::DictionaryValue* dict) {
745     if (option.type != CUSTOM_MEDIA)
746       dict->SetString(kKeyName, TypeToString(kMediaDefinitions, option.type));
747     if (!option.custom_display_name.empty() || option.type == CUSTOM_MEDIA)
748       dict->SetString(kCustomName, option.custom_display_name);
749     if (option.width_um > 0)
750       dict->SetInteger(kMediaWidth, option.width_um);
751     if (option.height_um > 0)
752       dict->SetInteger(kMediaHeight, option.height_um);
753     if (option.is_continuous_feed)
754       dict->SetBoolean(kMediaIsContinuous, true);
755   }
756 };
757
758 class CollateTraits : public NoValueValidation,
759                       public ItemsTraits<kOptionCollate> {
760  public:
761   static const bool kDefault = true;
762
763   static bool Load(const base::DictionaryValue& dict, bool* option) {
764     return dict.GetBoolean(kOptionCollate, option);
765   }
766
767   static void Save(bool option, base::DictionaryValue* dict) {
768     dict->SetBoolean(kOptionCollate, option);
769   }
770 };
771
772 class ReverseTraits : public NoValueValidation,
773                       public ItemsTraits<kOptionReverse> {
774  public:
775   static const bool kDefault = false;
776
777   static bool Load(const base::DictionaryValue& dict, bool* option) {
778     return dict.GetBoolean(kOptionReverse, option);
779   }
780
781   static void Save(bool option, base::DictionaryValue* dict) {
782     dict->SetBoolean(kOptionReverse, option);
783   }
784 };
785
786 }  // namespace printer
787
788 using namespace printer;
789
790 template class ListCapability<ContentType, ContentTypeTraits>;
791 template class ValueCapability<PwgRasterConfig, PwgRasterConfigTraits>;
792 template class SelectionCapability<Color, ColorTraits>;
793 template class SelectionCapability<DuplexType, DuplexTraits>;
794 template class SelectionCapability<OrientationType, OrientationTraits>;
795 template class SelectionCapability<Margins, MarginsTraits>;
796 template class SelectionCapability<Dpi, DpiTraits>;
797 template class SelectionCapability<FitToPageType, FitToPageTraits>;
798 template class SelectionCapability<Media, MediaTraits>;
799 template class EmptyCapability<class CopiesTraits>;
800 template class EmptyCapability<class PageRangeTraits>;
801 template class BooleanCapability<class CollateTraits>;
802 template class BooleanCapability<class ReverseTraits>;
803
804 template class TicketItem<PwgRasterConfig, PwgRasterConfigTraits>;
805 template class TicketItem<Color, ColorTraits>;
806 template class TicketItem<DuplexType, DuplexTraits>;
807 template class TicketItem<OrientationType, OrientationTraits>;
808 template class TicketItem<Margins, MarginsTraits>;
809 template class TicketItem<Dpi, DpiTraits>;
810 template class TicketItem<FitToPageType, FitToPageTraits>;
811 template class TicketItem<Media, MediaTraits>;
812 template class TicketItem<int32, CopiesTraits>;
813 template class TicketItem<PageRange, PageRangeTraits>;
814 template class TicketItem<bool, CollateTraits>;
815 template class TicketItem<bool, ReverseTraits>;
816
817 }  // namespace cloud_devices