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

Side by Side Diff: chrome/browser/resources/options/content_settings_exceptions_area.js

Issue 9814030: get rid of old options pages (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: more fixes Created 8 years, 9 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 | Annotate | Revision Log
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 cr.define('options.contentSettings', function() {
6 const InlineEditableItemList = options.InlineEditableItemList;
7 const InlineEditableItem = options.InlineEditableItem;
8 const ArrayDataModel = cr.ui.ArrayDataModel;
9
10 /**
11 * Creates a new exceptions list item.
12 * @param {string} contentType The type of the list.
13 * @param {string} mode The browser mode, 'otr' or 'normal'.
14 * @param {boolean} enableAskOption Whether to show an 'ask every time'
15 * option in the select.
16 * @param {Object} exception A dictionary that contains the data of the
17 * exception.
18 * @constructor
19 * @extends {options.InlineEditableItem}
20 */
21 function ExceptionsListItem(contentType, mode, enableAskOption, exception) {
22 var el = cr.doc.createElement('div');
23 el.mode = mode;
24 el.contentType = contentType;
25 el.enableAskOption = enableAskOption;
26 el.dataItem = exception;
27 el.__proto__ = ExceptionsListItem.prototype;
28 el.decorate();
29
30 return el;
31 }
32
33 ExceptionsListItem.prototype = {
34 __proto__: InlineEditableItem.prototype,
35
36 /**
37 * Called when an element is decorated as a list item.
38 */
39 decorate: function() {
40 InlineEditableItem.prototype.decorate.call(this);
41
42 this.isPlaceholder = !this.pattern;
43 var patternCell = this.createEditableTextCell(this.pattern);
44 patternCell.className = 'exception-pattern';
45 patternCell.classList.add('weakrtl');
46 this.contentElement.appendChild(patternCell);
47 if (this.pattern)
48 this.patternLabel = patternCell.querySelector('.static-text');
49 var input = patternCell.querySelector('input');
50
51 // TODO(stuartmorgan): Create an createEditableSelectCell abstracting
52 // this code.
53 // Setting label for display mode. |pattern| will be null for the 'add new
54 // exception' row.
55 if (this.pattern) {
56 var settingLabel = cr.doc.createElement('span');
57 settingLabel.textContent = this.settingForDisplay();
58 settingLabel.className = 'exception-setting';
59 settingLabel.setAttribute('displaymode', 'static');
60 this.contentElement.appendChild(settingLabel);
61 this.settingLabel = settingLabel;
62 }
63
64 // Setting select element for edit mode.
65 var select = cr.doc.createElement('select');
66 var optionAllow = cr.doc.createElement('option');
67 optionAllow.textContent = templateData.allowException;
68 optionAllow.value = 'allow';
69 select.appendChild(optionAllow);
70
71 if (this.enableAskOption) {
72 var optionAsk = cr.doc.createElement('option');
73 optionAsk.textContent = templateData.askException;
74 optionAsk.value = 'ask';
75 select.appendChild(optionAsk);
76 }
77
78 if (this.contentType == 'cookies') {
79 var optionSession = cr.doc.createElement('option');
80 optionSession.textContent = templateData.sessionException;
81 optionSession.value = 'session';
82 select.appendChild(optionSession);
83 }
84
85 if (this.contentType != 'fullscreen') {
86 var optionBlock = cr.doc.createElement('option');
87 optionBlock.textContent = templateData.blockException;
88 optionBlock.value = 'block';
89 select.appendChild(optionBlock);
90 }
91
92 this.contentElement.appendChild(select);
93 select.className = 'exception-setting';
94 if (this.pattern)
95 select.setAttribute('displaymode', 'edit');
96
97 // Used to track whether the URL pattern in the input is valid.
98 // This will be true if the browser process has informed us that the
99 // current text in the input is valid. Changing the text resets this to
100 // false, and getting a response from the browser sets it back to true.
101 // It starts off as false for empty string (new exceptions) or true for
102 // already-existing exceptions (which we assume are valid).
103 this.inputValidityKnown = this.pattern;
104 // This one tracks the actual validity of the pattern in the input. This
105 // starts off as true so as not to annoy the user when he adds a new and
106 // empty input.
107 this.inputIsValid = true;
108
109 this.input = input;
110 this.select = select;
111
112 this.updateEditables();
113
114 // Editing notifications and geolocation is disabled for now.
115 if (this.contentType == 'notifications' ||
116 this.contentType == 'location') {
117 this.editable = false;
118 }
119
120 // If the source of the content setting exception is not the user
121 // preference, then the content settings exception is managed and the user
122 // can't edit it.
123 if (this.dataItem.source &&
124 this.dataItem.source != 'preference') {
125 this.setAttribute('managedby', this.dataItem.source);
126 this.deletable = false;
127 this.editable = false;
128 }
129
130 var listItem = this;
131 // Handle events on the editable nodes.
132 input.oninput = function(event) {
133 listItem.inputValidityKnown = false;
134 chrome.send('checkExceptionPatternValidity',
135 [listItem.contentType, listItem.mode, input.value]);
136 };
137
138 // Listen for edit events.
139 this.addEventListener('canceledit', this.onEditCancelled_);
140 this.addEventListener('commitedit', this.onEditCommitted_);
141 },
142
143 /**
144 * The pattern (e.g., a URL) for the exception.
145 * @type {string}
146 */
147 get pattern() {
148 return this.dataItem['displayPattern'];
149 },
150 set pattern(pattern) {
151 this.dataItem['displayPattern'] = pattern;
152 },
153
154 /**
155 * The setting (allow/block) for the exception.
156 * @type {string}
157 */
158 get setting() {
159 return this.dataItem['setting'];
160 },
161 set setting(setting) {
162 this.dataItem['setting'] = setting;
163 },
164
165 /**
166 * Gets a human-readable setting string.
167 * @type {string}
168 */
169 settingForDisplay: function() {
170 var setting = this.setting;
171 if (setting == 'allow')
172 return templateData.allowException;
173 else if (setting == 'block')
174 return templateData.blockException;
175 else if (setting == 'ask')
176 return templateData.askException;
177 else if (setting == 'session')
178 return templateData.sessionException;
179 },
180
181 /**
182 * Update this list item to reflect whether the input is a valid pattern.
183 * @param {boolean} valid Whether said pattern is valid in the context of
184 * a content exception setting.
185 */
186 setPatternValid: function(valid) {
187 if (valid || !this.input.value)
188 this.input.setCustomValidity('');
189 else
190 this.input.setCustomValidity(' ');
191 this.inputIsValid = valid;
192 this.inputValidityKnown = true;
193 },
194
195 /**
196 * Set the <input> to its original contents. Used when the user quits
197 * editing.
198 */
199 resetInput: function() {
200 this.input.value = this.pattern;
201 },
202
203 /**
204 * Copy the data model values to the editable nodes.
205 */
206 updateEditables: function() {
207 this.resetInput();
208
209 var settingOption =
210 this.select.querySelector('[value=\'' + this.setting + '\']');
211 if (settingOption)
212 settingOption.selected = true;
213 },
214
215 /** @inheritDoc */
216 get currentInputIsValid() {
217 return this.inputValidityKnown && this.inputIsValid;
218 },
219
220 /** @inheritDoc */
221 get hasBeenEdited() {
222 var livePattern = this.input.value;
223 var liveSetting = this.select.value;
224 return livePattern != this.pattern || liveSetting != this.setting;
225 },
226
227 /**
228 * Called when committing an edit.
229 * @param {Event} e The end event.
230 * @private
231 */
232 onEditCommitted_: function(e) {
233 var newPattern = this.input.value;
234 var newSetting = this.select.value;
235
236 this.finishEdit(newPattern, newSetting);
237 },
238
239 /**
240 * Called when cancelling an edit; resets the control states.
241 * @param {Event} e The cancel event.
242 * @private
243 */
244 onEditCancelled_: function() {
245 this.updateEditables();
246 this.setPatternValid(true);
247 },
248
249 /**
250 * Editing is complete; update the model.
251 * @param {string} newPattern The pattern that the user entered.
252 * @param {string} newSetting The setting the user chose.
253 */
254 finishEdit: function(newPattern, newSetting) {
255 this.patternLabel.textContent = newPattern;
256 this.settingLabel.textContent = this.settingForDisplay();
257 var oldPattern = this.pattern;
258 this.pattern = newPattern;
259 this.setting = newSetting;
260
261 // TODO(estade): this will need to be updated if geolocation/notifications
262 // become editable.
263 if (oldPattern != newPattern) {
264 chrome.send('removeException',
265 [this.contentType, this.mode, oldPattern]);
266 }
267
268 chrome.send('setException',
269 [this.contentType, this.mode, newPattern, newSetting]);
270 }
271 };
272
273 /**
274 * Creates a new list item for the Add New Item row, which doesn't represent
275 * an actual entry in the exceptions list but allows the user to add new
276 * exceptions.
277 * @param {string} contentType The type of the list.
278 * @param {string} mode The browser mode, 'otr' or 'normal'.
279 * @param {boolean} enableAskOption Whether to show an 'ask every time'
280 * option in the select.
281 * @constructor
282 * @extends {cr.ui.ExceptionsListItem}
283 */
284 function ExceptionsAddRowListItem(contentType, mode, enableAskOption) {
285 var el = cr.doc.createElement('div');
286 el.mode = mode;
287 el.contentType = contentType;
288 el.enableAskOption = enableAskOption;
289 el.dataItem = [];
290 el.__proto__ = ExceptionsAddRowListItem.prototype;
291 el.decorate();
292
293 return el;
294 }
295
296 ExceptionsAddRowListItem.prototype = {
297 __proto__: ExceptionsListItem.prototype,
298
299 decorate: function() {
300 ExceptionsListItem.prototype.decorate.call(this);
301
302 this.input.placeholder = templateData.addNewExceptionInstructions;
303
304 // Do we always want a default of allow?
305 this.setting = 'allow';
306 },
307
308 /**
309 * Clear the <input> and let the placeholder text show again.
310 */
311 resetInput: function() {
312 this.input.value = '';
313 },
314
315 /** @inheritDoc */
316 get hasBeenEdited() {
317 return this.input.value != '';
318 },
319
320 /**
321 * Editing is complete; update the model. As long as the pattern isn't
322 * empty, we'll just add it.
323 * @param {string} newPattern The pattern that the user entered.
324 * @param {string} newSetting The setting the user chose.
325 */
326 finishEdit: function(newPattern, newSetting) {
327 this.resetInput();
328 chrome.send('setException',
329 [this.contentType, this.mode, newPattern, newSetting]);
330 },
331 };
332
333 /**
334 * Creates a new exceptions list.
335 * @constructor
336 * @extends {cr.ui.List}
337 */
338 var ExceptionsList = cr.ui.define('list');
339
340 ExceptionsList.prototype = {
341 __proto__: InlineEditableItemList.prototype,
342
343 /**
344 * Called when an element is decorated as a list.
345 */
346 decorate: function() {
347 InlineEditableItemList.prototype.decorate.call(this);
348
349 this.classList.add('settings-list');
350
351 for (var parentNode = this.parentNode; parentNode;
352 parentNode = parentNode.parentNode) {
353 if (parentNode.hasAttribute('contentType')) {
354 this.contentType = parentNode.getAttribute('contentType');
355 break;
356 }
357 }
358
359 this.mode = this.getAttribute('mode');
360
361 var exceptionList = this;
362
363 // Whether the exceptions in this list allow an 'Ask every time' option.
364 this.enableAskOption = this.contentType == 'plugins';
365
366 this.autoExpands = true;
367 this.reset();
368 },
369
370 /**
371 * Creates an item to go in the list.
372 * @param {Object} entry The element from the data model for this row.
373 */
374 createItem: function(entry) {
375 if (entry) {
376 return new ExceptionsListItem(this.contentType,
377 this.mode,
378 this.enableAskOption,
379 entry);
380 } else {
381 var addRowItem = new ExceptionsAddRowListItem(this.contentType,
382 this.mode,
383 this.enableAskOption);
384 addRowItem.deletable = false;
385 return addRowItem;
386 }
387 },
388
389 /**
390 * Sets the exceptions in the js model.
391 * @param {Object} entries A list of dictionaries of values, each dictionary
392 * represents an exception.
393 */
394 setExceptions: function(entries) {
395 var deleteCount = this.dataModel.length;
396
397 if (this.isEditable()) {
398 // We don't want to remove the Add New Exception row.
399 deleteCount = deleteCount - 1;
400 }
401
402 var args = [0, deleteCount];
403 args.push.apply(args, entries);
404 this.dataModel.splice.apply(this.dataModel, args);
405 },
406
407 /**
408 * The browser has finished checking a pattern for validity. Update the
409 * list item to reflect this.
410 * @param {string} pattern The pattern.
411 * @param {bool} valid Whether said pattern is valid in the context of
412 * a content exception setting.
413 */
414 patternValidityCheckComplete: function(pattern, valid) {
415 var listItems = this.items;
416 for (var i = 0; i < listItems.length; i++) {
417 var listItem = listItems[i];
418 // Don't do anything for messages for the item if it is not the intended
419 // recipient, or if the response is stale (i.e. the input value has
420 // changed since we sent the request to analyze it).
421 if (pattern == listItem.input.value)
422 listItem.setPatternValid(valid);
423 }
424 },
425
426 /**
427 * Returns whether the rows are editable in this list.
428 */
429 isEditable: function() {
430 // Editing notifications and geolocation is disabled for now.
431 return !(this.contentType == 'notifications' ||
432 this.contentType == 'location' ||
433 this.contentType == 'fullscreen');
434 },
435
436 /**
437 * Removes all exceptions from the js model.
438 */
439 reset: function() {
440 if (this.isEditable()) {
441 // The null creates the Add New Exception row.
442 this.dataModel = new ArrayDataModel([null]);
443 } else {
444 this.dataModel = new ArrayDataModel([]);
445 }
446 },
447
448 /** @inheritDoc */
449 deleteItemAtIndex: function(index) {
450 var listItem = this.getListItemByIndex(index);
451 if (listItem.undeletable)
452 return;
453
454 var dataItem = listItem.dataItem;
455 var args = [listItem.contentType];
456 if (listItem.contentType == 'location')
457 args.push(dataItem['origin'], dataItem['embeddingOrigin']);
458 else if (listItem.contentType == 'notifications')
459 args.push(dataItem['origin'], dataItem['setting']);
460 else
461 args.push(listItem.mode, listItem.pattern);
462
463 chrome.send('removeException', args);
464 },
465 };
466
467 var OptionsPage = options.OptionsPage;
468
469 /**
470 * Encapsulated handling of content settings list subpage.
471 * @constructor
472 */
473 function ContentSettingsExceptionsArea() {
474 OptionsPage.call(this, 'contentExceptions',
475 templateData.contentSettingsPageTabTitle,
476 'content-settings-exceptions-area');
477 }
478
479 cr.addSingletonGetter(ContentSettingsExceptionsArea);
480
481 ContentSettingsExceptionsArea.prototype = {
482 __proto__: OptionsPage.prototype,
483
484 initializePage: function() {
485 OptionsPage.prototype.initializePage.call(this);
486
487 var exceptionsLists = this.pageDiv.querySelectorAll('list');
488 for (var i = 0; i < exceptionsLists.length; i++) {
489 options.contentSettings.ExceptionsList.decorate(exceptionsLists[i]);
490 }
491
492 ContentSettingsExceptionsArea.hideOTRLists();
493
494 // If the user types in the URL without a hash, show just cookies.
495 this.showList('cookies');
496 },
497
498 /**
499 * Shows one list and hides all others.
500 * @param {string} type The content type.
501 */
502 showList: function(type) {
503 var header = this.pageDiv.querySelector('h1');
504 header.textContent = templateData[type + '_header'];
505
506 var divs = this.pageDiv.querySelectorAll('div[contentType]');
507 for (var i = 0; i < divs.length; i++) {
508 if (divs[i].getAttribute('contentType') == type)
509 divs[i].hidden = false;
510 else
511 divs[i].hidden = true;
512 }
513 },
514
515 /**
516 * Called after the page has been shown. Show the content type for the
517 * location's hash.
518 */
519 didShowPage: function() {
520 var hash = location.hash;
521 if (hash)
522 this.showList(hash.slice(1));
523 },
524 };
525
526 /**
527 * Called when the last incognito window is closed.
528 */
529 ContentSettingsExceptionsArea.OTRProfileDestroyed = function() {
530 this.hideOTRLists();
531 };
532
533 /**
534 * Clears and hides the incognito exceptions lists.
535 */
536 ContentSettingsExceptionsArea.hideOTRLists = function() {
537 var otrLists = document.querySelectorAll('list[mode=otr]');
538
539 for (var i = 0; i < otrLists.length; i++) {
540 otrLists[i].reset();
541 otrLists[i].parentNode.hidden = true;
542 }
543 };
544
545 return {
546 ExceptionsListItem: ExceptionsListItem,
547 ExceptionsAddRowListItem: ExceptionsAddRowListItem,
548 ExceptionsList: ExceptionsList,
549 ContentSettingsExceptionsArea: ContentSettingsExceptionsArea,
550 };
551 });
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698