Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(24)

Side by Side Diff: chrome/browser/resources/print_preview/data/app_state.js

Issue 2346153002: Save most recent 3 destinations across multiple sessions (Closed)
Patch Set: Add check for bad struct read in Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | chrome/browser/resources/print_preview/data/destination_store.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 cr.define('print_preview', function() { 5 cr.define('print_preview', function() {
6 'use strict'; 6 'use strict';
7 7
8 /** 8 /**
9 * Object used to represent a recent destination in the app state.
10 * @constructor
11 */
12 function RecentDestination(destination) {
13 /**
14 * ID of the RecentDestination.
15 * @type {string}
16 */
17 this.id = destination.id;
18
19 /**
20 * Origin of the RecentDestination.
21 * @type {string}
22 */
23 this.origin = destination.origin;
24
25 /**
26 * Account the RecentDestination is registered for.
27 * @type {string}
28 */
29 this.account = destination.account || '';
30
31 /**
32 * CDD of the RecentDestination.
33 * @type {print_preview.Cdd}
34 */
35 this.capabilities = destination.capabilities;
36
37 /**
38 * Name of the RecentDestination.
39 * @type {string}
40 */
41 this.name = destination.name || '';
42
43 /**
44 * Extension ID associated with the RecentDestination.
45 * @type {string}
46 */
47 this.extensionId = destination.extension_id || '';
48
49 /**
50 * Extension name associated with the RecentDestination.
51 * @type {string}
52 */
53 this.extensionName = destination.extension_name || '';
54 };
55
56 /**
9 * Object used to get and persist the print preview application state. 57 * Object used to get and persist the print preview application state.
10 * @constructor 58 * @constructor
11 */ 59 */
12 function AppState() { 60 function AppState() {
13 /** 61 /**
14 * Internal representation of application state. 62 * Internal representation of application state.
15 * @type {Object} 63 * @type {Object}
16 * @private 64 * @private
17 */ 65 */
18 this.state_ = {}; 66 this.state_ = {};
19 this.state_[AppState.Field.VERSION] = AppState.VERSION_; 67 this.state_[AppState.Field.VERSION] = AppState.VERSION_;
20 this.state_[AppState.Field.IS_GCP_PROMO_DISMISSED] = true; 68 this.state_[AppState.Field.IS_GCP_PROMO_DISMISSED] = true;
69 this.state_[AppState.Field.RECENT_DESTINATIONS] = [];
21 70
22 /** 71 /**
23 * Whether the app state has been initialized. The app state will ignore all 72 * Whether the app state has been initialized. The app state will ignore all
24 * writes until it has been initialized. 73 * writes until it has been initialized.
25 * @type {boolean} 74 * @type {boolean}
26 * @private 75 * @private
27 */ 76 */
28 this.isInitialized_ = false; 77 this.isInitialized_ = false;
29 }; 78 };
30 79
31 /** 80 /**
81 * Number of recent print destinations to store across browser sessions.
82 * @const {number}
83 */
84 AppState.NUM_DESTINATIONS_ = 3;
85
86
87 /**
32 * Enumeration of field names for serialized app state. 88 * Enumeration of field names for serialized app state.
33 * @enum {string} 89 * @enum {string}
34 */ 90 */
35 AppState.Field = { 91 AppState.Field = {
36 VERSION: 'version', 92 VERSION: 'version',
37 SELECTED_DESTINATION_ID: 'selectedDestinationId', 93 RECENT_DESTINATIONS: 'recentDestinations',
38 SELECTED_DESTINATION_ACCOUNT: 'selectedDestinationAccount',
39 SELECTED_DESTINATION_ORIGIN: 'selectedDestinationOrigin',
40 SELECTED_DESTINATION_CAPABILITIES: 'selectedDestinationCapabilities',
41 SELECTED_DESTINATION_NAME: 'selectedDestinationName',
42 SELECTED_DESTINATION_EXTENSION_ID: 'selectedDestinationExtensionId',
43 SELECTED_DESTINATION_EXTENSION_NAME: 'selectedDestinationExtensionName',
44 IS_GCP_PROMO_DISMISSED: 'isGcpPromoDismissed', 94 IS_GCP_PROMO_DISMISSED: 'isGcpPromoDismissed',
45 DPI: 'dpi', 95 DPI: 'dpi',
46 MEDIA_SIZE: 'mediaSize', 96 MEDIA_SIZE: 'mediaSize',
47 MARGINS_TYPE: 'marginsType', 97 MARGINS_TYPE: 'marginsType',
48 CUSTOM_MARGINS: 'customMargins', 98 CUSTOM_MARGINS: 'customMargins',
49 IS_COLOR_ENABLED: 'isColorEnabled', 99 IS_COLOR_ENABLED: 'isColorEnabled',
50 IS_DUPLEX_ENABLED: 'isDuplexEnabled', 100 IS_DUPLEX_ENABLED: 'isDuplexEnabled',
51 IS_HEADER_FOOTER_ENABLED: 'isHeaderFooterEnabled', 101 IS_HEADER_FOOTER_ENABLED: 'isHeaderFooterEnabled',
52 IS_LANDSCAPE_ENABLED: 'isLandscapeEnabled', 102 IS_LANDSCAPE_ENABLED: 'isLandscapeEnabled',
53 IS_COLLATE_ENABLED: 'isCollateEnabled', 103 IS_COLLATE_ENABLED: 'isCollateEnabled',
(...skipping 13 matching lines...) Expand all
67 117
68 /** 118 /**
69 * Name of C++ layer function to persist app state. 119 * Name of C++ layer function to persist app state.
70 * @type {string} 120 * @type {string}
71 * @const 121 * @const
72 * @private 122 * @private
73 */ 123 */
74 AppState.NATIVE_FUNCTION_NAME_ = 'saveAppState'; 124 AppState.NATIVE_FUNCTION_NAME_ = 'saveAppState';
75 125
76 AppState.prototype = { 126 AppState.prototype = {
127
128 /**
129 * Helper function to get the most recent destination.
130 * @return {?RecentDestination} The most recent value of the
131 * destination.
132 */
133 getSelectedDestination_: function() {
134 return (this.state_[AppState.Field.RECENT_DESTINATIONS].length > 0) ?
135 this.state_[AppState.Field.RECENT_DESTINATIONS][0] : null;
136 },
137
77 /** @return {?string} ID of the selected destination. */ 138 /** @return {?string} ID of the selected destination. */
78 get selectedDestinationId() { 139 get selectedDestinationId() {
79 return this.state_[AppState.Field.SELECTED_DESTINATION_ID]; 140 return this.getSelectedDestination_ ?
141 this.getSelectedDestination_.id : null;
80 }, 142 },
81 143
82 /** @return {?string} Account the selected destination is registered for. */ 144 /** @return {?string} Account the selected destination is registered for. */
83 get selectedDestinationAccount() { 145 get selectedDestinationAccount() {
84 return this.state_[AppState.Field.SELECTED_DESTINATION_ACCOUNT]; 146 return this.getSelectedDestination_ ?
147 this.getSelectedDestination_.account : null;
85 }, 148 },
86 149
87 /** 150 /**
88 * @return {?print_preview.Destination.Origin<string>} Origin of the 151 * @return {?print_preview.Destination.Origin<string>} Origin of the
89 * selected destination. 152 * selected destination.
90 */ 153 */
91 get selectedDestinationOrigin() { 154 get selectedDestinationOrigin() {
92 return this.state_[AppState.Field.SELECTED_DESTINATION_ORIGIN]; 155 return this.getSelectedDestination_ ?
156 this.getSelectedDestination_.origin : null;
93 }, 157 },
94 158
95 /** @return {?print_preview.Cdd} CDD of the selected destination. */ 159 /** @return {?print_preview.Cdd} CDD of the selected destination. */
96 get selectedDestinationCapabilities() { 160 get selectedDestinationCapabilities() {
97 return this.state_[AppState.Field.SELECTED_DESTINATION_CAPABILITIES]; 161 return this.getSelectedDestination_ ?
162 this.getSelectedDestination_.capabilities : null;
98 }, 163 },
99 164
100 /** @return {?string} Name of the selected destination. */ 165 /** @return {?string} Name of the selected destination. */
101 get selectedDestinationName() { 166 get selectedDestinationName() {
102 return this.state_[AppState.Field.SELECTED_DESTINATION_NAME]; 167 return this.getSelectedDestination_ ?
168 this.getSelectedDestination_.name : null;
103 }, 169 },
104 170
105 /** 171 /**
106 * @return {?string} Extension ID associated with the selected destination. 172 * @return {?string} Extension ID associated with the selected destination.
107 */ 173 */
108 get selectedDestinationExtensionId() { 174 get selectedDestinationExtensionId() {
109 return this.state_[AppState.Field.SELECTED_DESTINATION_EXTENSION_ID]; 175 return this.getSelectedDestination_ ?
176 this.getSelectedDestination_.extensionId : null;
110 }, 177 },
111 178
112 /** 179 /**
113 * @return {?string} Extension name associated with the selected 180 * @return {?string} Extension name associated with the selected
114 * destination. 181 * destination.
115 */ 182 */
116 get selectedDestinationExtensionName() { 183 get selectedDestinationExtensionName() {
117 return this.state_[AppState.Field.SELECTED_DESTINATION_EXTENSION_NAME]; 184 return this.getSelectedDestination_ ?
185 this.getSelectedDestination_.extensionName : null;
186 },
187
188 /**
189 * @return {?RecentDestination} The most recent destination, which is
190 * currently the selected destination.
191 */
192 get selectedDestination() {
193 return this.getSelectedDestination_;
194 },
195
196 /**
197 * @return {?Array<!RecentDestination>} The AppState.NUM_DESTINATIONS_ most
198 * recent destinations.
199 */
200 get recentDestinations() {
201 return this.state_[AppState.Field.RECENT_DESTINATIONS];
118 }, 202 },
119 203
120 /** @return {boolean} Whether the GCP promotion has been dismissed. */ 204 /** @return {boolean} Whether the GCP promotion has been dismissed. */
121 get isGcpPromoDismissed() { 205 get isGcpPromoDismissed() {
122 return this.state_[AppState.Field.IS_GCP_PROMO_DISMISSED]; 206 return this.state_[AppState.Field.IS_GCP_PROMO_DISMISSED];
123 }, 207 },
124 208
125 /** 209 /**
126 * @param {!print_preview.AppState.Field} field App state field to check if 210 * @param {!print_preview.AppState.Field} field App state field to check if
127 * set. 211 * set.
(...skipping 29 matching lines...) Expand all
157 if (state[AppState.Field.VERSION] == AppState.VERSION_) { 241 if (state[AppState.Field.VERSION] == AppState.VERSION_) {
158 this.state_ = state; 242 this.state_ = state;
159 } 243 }
160 } catch(e) { 244 } catch(e) {
161 console.error('Unable to parse state: ' + e); 245 console.error('Unable to parse state: ' + e);
162 // Proceed with default state. 246 // Proceed with default state.
163 } 247 }
164 } else { 248 } else {
165 // Set some state defaults. 249 // Set some state defaults.
166 this.state_[AppState.Field.IS_GCP_PROMO_DISMISSED] = false; 250 this.state_[AppState.Field.IS_GCP_PROMO_DISMISSED] = false;
251 this.state_[AppState.Field.RECENT_DESTINATIONS] = [];
252 }
253 if (!this.state_[AppState.Field.RECENT_DESTINATIONS]) {
254 this.state_[AppState.Field.RECENT_DESTINATIONS] = [];
255 } else if (!(this.state_[AppState.Field.RECENT_DESTINATIONS] instanceof
256 Array)) {
257 var tmp = this.state_[AppState.Field.RECENT_DESTINATIONS];
258 this.state_[AppState.Field.RECENT_DESTINATIONS] = [tmp];
259 } else if (!this.state_[AppState.Field.RECENT_DESTINATIONS][0] ||
260 !this.state_[AppState.Field.RECENT_DESTINATIONS][0].id) {
261 // read in incorrectly
262 this.state_[AppState.Field.RECENT_DESTINATIONS] = [];
263 } else if (this.state_[AppState.Field.RECENT_DESTINATIONS].length >
264 AppState.NUM_DESTINATIONS_) {
265 this.state_[AppState.Field.RECENT_DESTINATIONS].length =
266 AppState.NUM_DESTINATIONS_;
167 } 267 }
168 }, 268 },
169 269
170 /** 270 /**
171 * Sets to initialized state. Now object will accept persist requests. 271 * Sets to initialized state. Now object will accept persist requests.
172 */ 272 */
173 setInitialized: function() { 273 setInitialized: function() {
174 this.isInitialized_ = true; 274 this.isInitialized_ = true;
175 }, 275 },
176 276
(...skipping 13 matching lines...) Expand all
190 this.persist_(); 290 this.persist_();
191 }, 291 },
192 292
193 /** 293 /**
194 * Persists the selected destination. 294 * Persists the selected destination.
195 * @param {!print_preview.Destination} dest Destination to persist. 295 * @param {!print_preview.Destination} dest Destination to persist.
196 */ 296 */
197 persistSelectedDestination: function(dest) { 297 persistSelectedDestination: function(dest) {
198 if (!this.isInitialized_) 298 if (!this.isInitialized_)
199 return; 299 return;
200 this.state_[AppState.Field.SELECTED_DESTINATION_ID] = dest.id; 300
201 this.state_[AppState.Field.SELECTED_DESTINATION_ACCOUNT] = dest.account; 301 // Determine if this destination is already in the recent destinations,
202 this.state_[AppState.Field.SELECTED_DESTINATION_ORIGIN] = dest.origin; 302 // and where in the array it is located.
203 this.state_[AppState.Field.SELECTED_DESTINATION_CAPABILITIES] = 303 var newDestination = new RecentDestination(dest);
204 dest.capabilities; 304 var indexFound = this.state_[
205 this.state_[AppState.Field.SELECTED_DESTINATION_NAME] = dest.displayName; 305 AppState.Field.RECENT_DESTINATIONS].findIndex(function(recent) {
206 this.state_[AppState.Field.SELECTED_DESTINATION_EXTENSION_ID] = 306 return (newDestination.id == recent.id &&
207 dest.extensionId; 307 newDestination.origin == recent.origin);
208 this.state_[AppState.Field.SELECTED_DESTINATION_EXTENSION_NAME] = 308 });
209 dest.extensionName; 309
310 // No change
311 if (indexFound == 0) {
312 this.persist_();
313 return;
314 }
315
316 // Shift the array so that the nth most recent destination is located at
317 // index n.
318 if (indexFound == -1 &&
319 this.state_[AppState.Field.RECENT_DESTINATIONS].length ==
320 AppState.NUM_DESTINATIONS_) {
321 indexFound = AppState.NUM_DESTINATIONS_ - 1;
322 }
323 if (indexFound != -1)
324 this.state_[AppState.Field.RECENT_DESTINATIONS].splice(indexFound, 1);
325
326 // Add the most recent destination
327 this.state_[AppState.Field.RECENT_DESTINATIONS].splice(
328 0, 0, newDestination);
329
210 this.persist_(); 330 this.persist_();
211 }, 331 },
212 332
213 /** 333 /**
214 * Persists whether the GCP promotion has been dismissed. 334 * Persists whether the GCP promotion has been dismissed.
215 * @param {boolean} isGcpPromoDismissed Whether the GCP promotion has been 335 * @param {boolean} isGcpPromoDismissed Whether the GCP promotion has been
216 * dismissed. 336 * dismissed.
217 */ 337 */
218 persistIsGcpPromoDismissed: function(isGcpPromoDismissed) { 338 persistIsGcpPromoDismissed: function(isGcpPromoDismissed) {
219 if (!this.isInitialized_) 339 if (!this.isInitialized_)
220 return; 340 return;
221 this.state_[AppState.Field.IS_GCP_PROMO_DISMISSED] = isGcpPromoDismissed; 341 this.state_[AppState.Field.IS_GCP_PROMO_DISMISSED] = isGcpPromoDismissed;
222 this.persist_(); 342 this.persist_();
223 }, 343 },
224 344
225 /** 345 /**
226 * Calls into the native layer to persist the application state. 346 * Calls into the native layer to persist the application state.
227 * @private 347 * @private
228 */ 348 */
229 persist_: function() { 349 persist_: function() {
230 chrome.send(AppState.NATIVE_FUNCTION_NAME_, 350 chrome.send(AppState.NATIVE_FUNCTION_NAME_,
231 [JSON.stringify(this.state_)]); 351 [JSON.stringify(this.state_)]);
232 } 352 }
233 }; 353 };
234 354
235 return { 355 return {
236 AppState: AppState 356 AppState: AppState
237 }; 357 };
238 }); 358 });
OLDNEW
« no previous file with comments | « no previous file | chrome/browser/resources/print_preview/data/destination_store.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698