Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / browser / resources / options / sync_setup_overlay.js
blob4b5944987f3996d624c882143e572dc8eba5d77d
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.
5 cr.exportPath('options');
7 /** @typedef {{appsEnforced: boolean,
8  *             appsRegistered: boolean,
9  *             appsSynced: boolean,
10  *             autofillEnforced: boolean,
11  *             autofillRegistered: boolean,
12  *             autofillSynced: boolean,
13  *             bookmarksEnforced: boolean,
14  *             bookmarksRegistered: boolean,
15  *             bookmarksSynced: boolean,
16  *             encryptAllData: boolean,
17  *             encryptAllDataAllowed: boolean,
18  *             enterGooglePassphraseBody: (string|undefined),
19  *             enterPassphraseBody: (string|undefined),
20  *             extensionsEnforced: boolean,
21  *             extensionsRegistered: boolean,
22  *             extensionsSynced: boolean,
23  *             fullEncryptionBody: string,
24  *             passphraseFailed: boolean,
25  *             passwordsEnforced: boolean,
26  *             passwordsRegistered: boolean,
27  *             passwordsSynced: boolean,
28  *             preferencesEnforced: boolean,
29  *             preferencesRegistered: boolean,
30  *             preferencesSynced: boolean,
31  *             showPassphrase: boolean,
32  *             syncAllDataTypes: boolean,
33  *             syncNothing: boolean,
34  *             tabsEnforced: boolean,
35  *             tabsRegistered: boolean,
36  *             tabsSynced: boolean,
37  *             themesEnforced: boolean,
38  *             themesRegistered: boolean,
39  *             themesSynced: boolean,
40  *             typedUrlsEnforced: boolean,
41  *             typedUrlsRegistered: boolean,
42  *             typedUrlsSynced: boolean,
43  *             usePassphrase: boolean,
44  *             wifiCredentialsEnforced: (boolean|undefined),
45  *             wifiCredentialsSynced: (boolean|undefined)}}
46  */
47 var SyncConfig;
49 /**
50  * The user's selection in the synced data type drop-down menu, as an index.
51  * @enum {number}
52  * @const
53  */
54 options.DataTypeSelection = {
55   SYNC_EVERYTHING: 0,
56   CHOOSE_WHAT_TO_SYNC: 1,
57   SYNC_NOTHING: 2
60 cr.define('options', function() {
61   /** @const */ var Page = cr.ui.pageManager.Page;
62   /** @const */ var PageManager = cr.ui.pageManager.PageManager;
64   /**
65    * SyncSetupOverlay class
66    * Encapsulated handling of the 'Sync Setup' overlay page.
67    * @class
68    */
69   function SyncSetupOverlay() {
70     Page.call(this, 'syncSetup',
71               loadTimeData.getString('syncSetupOverlayTabTitle'),
72               'sync-setup-overlay');
73   }
75   cr.addSingletonGetter(SyncSetupOverlay);
77   SyncSetupOverlay.prototype = {
78     __proto__: Page.prototype,
80     /**
81      * True if the synced account uses a custom passphrase.
82      * @private {boolean}
83      */
84     usePassphrase_: false,
86     /**
87      * True if the synced account uses 'encrypt everything'.
88      * @private {boolean}
89      */
90     useEncryptEverything_: false,
92     /**
93      * An object used as a cache of the arguments passed in while initially
94      * displaying the advanced sync settings dialog. Used to switch between the
95      * options in the main drop-down menu. Reset when the dialog is closed.
96      * @private {?SyncConfig}
97      */
98     syncConfigureArgs_: null,
100     /**
101      * A dictionary that maps the sync data type checkbox names to their checked
102      * state. Initialized when the advanced settings dialog is first brought up,
103      * updated any time a box is checked / unchecked, and reset when the dialog
104      * is closed. Used to restore checkbox state while switching between the
105      * options in the main drop-down menu. All checkboxes are checked and
106      * disabled when the "Sync everything" menu-item is selected, and unchecked
107      * and disabled when "Sync nothing" is selected. When "Choose what to sync"
108      * is selected, the boxes are restored to their most recent checked state
109      * from this cache.
110      * @private {Object}
111      */
112     dataTypeBoxesChecked_: {},
114     /**
115      * A dictionary that maps the sync data type checkbox names to their
116      * disabled state (when a data type is enabled programmatically without user
117      * choice).  Initialized when the advanced settings dialog is first brought
118      * up, and reset when the dialog is closed.
119      * @private {Object}
120      */
121     dataTypeBoxesDisabled_: {},
123     /** @override */
124     initializePage: function() {
125       Page.prototype.initializePage.call(this);
127       var self = this;
129       // If 'profilesInfo' doesn't exist, it's forbidden to delete profile.
130       // So don't display the delete-profile checkbox.
131       if (!loadTimeData.valueExists('profilesInfo') &&
132           $('sync-setup-delete-profile')) {
133         $('sync-setup-delete-profile').hidden = true;
134       }
136       $('basic-encryption-option').onchange =
137           $('full-encryption-option').onchange = function() {
138         self.onEncryptionRadioChanged_();
139       };
140       $('choose-datatypes-cancel').onclick =
141           $('confirm-everything-cancel').onclick =
142           $('stop-syncing-cancel').onclick =
143           $('sync-spinner-cancel').onclick = function() {
144         self.closeOverlay_();
145       };
146       $('confirm-everything-ok').onclick = function() {
147         self.sendConfiguration_();
148       };
149       $('timeout-ok').onclick = function() {
150         chrome.send('CloseTimeout');
151         self.closeOverlay_();
152       };
153       $('stop-syncing-ok').onclick = function() {
154         var deleteProfile = $('delete-profile') != undefined &&
155             $('delete-profile').checked;
156         chrome.send('SyncSetupStopSyncing', [deleteProfile]);
157         self.closeOverlay_();
158       };
159       $('use-default-link').onclick = function() {
160         self.showSyncEverythingPage_();
161       };
162     },
164     /** @private */
165     showOverlay_: function() {
166       PageManager.showPageByName('syncSetup');
167     },
169     /** @private */
170     closeOverlay_: function() {
171       this.syncConfigureArgs_ = null;
172       this.dataTypeBoxesChecked_ = {};
173       this.dataTypeBoxesDisabled_ = {};
175       var overlay = $('sync-setup-overlay');
176       if (!overlay.hidden)
177         PageManager.closeOverlay();
178     },
180     /** @override */
181     didShowPage: function() {
182       chrome.send('SyncSetupShowSetupUI');
183     },
185     /** @override */
186     didClosePage: function() {
187       chrome.send('SyncSetupDidClosePage');
188     },
190     /** @private */
191     onEncryptionRadioChanged_: function() {
192       var visible = $('full-encryption-option').checked;
193       // TODO(dbeam): should sync-custom-passphrase-container be hidden instead?
194       $('sync-custom-passphrase').hidden = !visible;
195       chrome.send('coreOptionsUserMetricsAction',
196                   ['Options_SyncSetEncryption']);
197     },
199     /**
200      * Sets the checked state of the individual sync data type checkboxes in the
201      * advanced sync settings dialog.
202      * @param {boolean} value True for checked, false for unchecked.
203      * @private
204      */
205     checkAllDataTypeCheckboxes_: function(value) {
206       // Only check / uncheck the visible ones (since there's no way to uncheck
207       // / check the invisible ones).
208       var checkboxes = $('choose-data-types-body').querySelectorAll(
209           '.sync-type-checkbox:not([hidden]) input');
210       for (var i = 0; i < checkboxes.length; i++) {
211         checkboxes[i].checked = value;
212       }
213     },
215     /**
216      * Restores the checked states of the sync data type checkboxes in the
217      * advanced sync settings dialog. Called when "Choose what to sync" is
218      * selected. Required because all the checkboxes are checked when
219      * "Sync everything" is selected, and unchecked when "Sync nothing" is
220      * selected. Note: We only restore checkboxes for data types that are
221      * actually visible and whose old values are found in the cache, since it's
222      * possible for some data types to not be registered, and therefore, their
223      * checkboxes remain hidden, and never get cached.
224      * @private
225      */
226     restoreDataTypeCheckboxes_: function() {
227       for (var dataType in this.dataTypeBoxesChecked_) {
228         $(dataType).checked = this.dataTypeBoxesChecked_[dataType];
229       }
230     },
232     /**
233      * Enables / grays out the sync data type checkboxes in the advanced
234      * settings dialog.
235      * @param {boolean} enabled True for enabled, false for grayed out.
236      * @private
237      */
238     setDataTypeCheckboxesEnabled_: function(enabled) {
239       for (var dataType in this.dataTypeBoxesDisabled_) {
240         $(dataType).disabled =
241             !enabled || this.dataTypeBoxesDisabled_[dataType];
242       }
243     },
245     /**
246      * Sets the state of the sync data type checkboxes based on whether "Sync
247      * everything", "Choose what to sync", or "Sync nothing" are selected in the
248      * drop-down menu of the advanced settings dialog.
249      * @param {options.DataTypeSelection} selectedIndex Index of user's
250      *     selection.
251      * @private
252      */
253     setDataTypeCheckboxes_: function(selectedIndex) {
254       if (selectedIndex == options.DataTypeSelection.CHOOSE_WHAT_TO_SYNC) {
255         this.setDataTypeCheckboxesEnabled_(true);
256         this.restoreDataTypeCheckboxes_();
257       } else {
258         this.setDataTypeCheckboxesEnabled_(false);
259         this.checkAllDataTypeCheckboxes_(
260             selectedIndex == options.DataTypeSelection.SYNC_EVERYTHING);
261       }
262     },
264     /** @private */
265     checkPassphraseMatch_: function() {
266       var emptyError = $('empty-error');
267       var mismatchError = $('mismatch-error');
268       emptyError.hidden = true;
269       mismatchError.hidden = true;
271       if (!$('full-encryption-option').checked ||
272            $('basic-encryption-option').disabled) {
273         return true;
274       }
276       var customPassphrase = $('custom-passphrase');
277       if (customPassphrase.value.length == 0) {
278         emptyError.hidden = false;
279         return false;
280       }
282       var confirmPassphrase = $('confirm-passphrase');
283       if (confirmPassphrase.value != customPassphrase.value) {
284         mismatchError.hidden = false;
285         return false;
286       }
288       return true;
289     },
291     /** @private */
292     sendConfiguration_: function() {
293       var encryptAllData = $('full-encryption-option').checked;
295       var usePassphrase;
296       var customPassphrase;
297       var googlePassphrase = false;
298       if (!$('sync-existing-passphrase-container').hidden) {
299         // If we were prompted for an existing passphrase, use it.
300         customPassphrase = getRequiredElement('passphrase').value;
301         usePassphrase = true;
302         // If we were displaying the 'enter your old google password' prompt,
303         // then that means this is the user's google password.
304         googlePassphrase = !$('google-passphrase-needed-body').hidden;
305         // We allow an empty passphrase, in case the user has disabled
306         // all their encrypted datatypes. In that case, the PSS will accept
307         // the passphrase and finish configuration. If the user has enabled
308         // encrypted datatypes, the PSS will prompt again specifying that the
309         // passphrase failed.
310       } else if (!$('basic-encryption-option').disabled &&
311                   $('full-encryption-option').checked) {
312         // The user is setting a custom passphrase for the first time.
313         if (!this.checkPassphraseMatch_())
314           return;
315         customPassphrase = $('custom-passphrase').value;
316         usePassphrase = true;
317       } else {
318         // The user is not setting a custom passphrase.
319         usePassphrase = false;
320       }
322       // Don't allow the user to tweak the settings once we send the
323       // configuration to the backend.
324       this.setInputElementsDisabledState_(true);
325       $('use-default-link').hidden = true;
327       // These values need to be kept in sync with where they are read in
328       // sync_setup_handler.cc:GetConfiguration().
329       var syncAll = $('sync-select-datatypes').selectedIndex ==
330                     options.DataTypeSelection.SYNC_EVERYTHING;
331       var syncNothing = $('sync-select-datatypes').selectedIndex ==
332                         options.DataTypeSelection.SYNC_NOTHING;
333       var result = JSON.stringify({
334         'syncAllDataTypes': syncAll,
335         'syncNothing': syncNothing,
336         'bookmarksSynced': syncAll || $('bookmarks-checkbox').checked,
337         'preferencesSynced': syncAll || $('preferences-checkbox').checked,
338         'themesSynced': syncAll || $('themes-checkbox').checked,
339         'passwordsSynced': syncAll || $('passwords-checkbox').checked,
340         'autofillSynced': syncAll || $('autofill-checkbox').checked,
341         'extensionsSynced': syncAll || $('extensions-checkbox').checked,
342         'typedUrlsSynced': syncAll || $('typed-urls-checkbox').checked,
343         'appsSynced': syncAll || $('apps-checkbox').checked,
344         'tabsSynced': syncAll || $('tabs-checkbox').checked,
345         'wifiCredentialsSynced': syncAll ||
346                                  $('wifi-credentials-checkbox').checked,
347         'encryptAllData': encryptAllData,
348         'usePassphrase': usePassphrase,
349         'isGooglePassphrase': googlePassphrase,
350         'passphrase': customPassphrase
351       });
352       chrome.send('SyncSetupConfigure', [result]);
353     },
355     /**
356      * Sets the disabled property of all input elements within the 'Customize
357      * Sync Preferences' screen. This is used to prohibit the user from changing
358      * the inputs after confirming the customized sync preferences, or resetting
359      * the state when re-showing the dialog.
360      * @param {boolean} disabled True if controls should be set to disabled.
361      * @private
362      */
363     setInputElementsDisabledState_: function(disabled) {
364       var self = this;
365       var configureElements =
366           $('customize-sync-preferences').querySelectorAll('input');
367       for (var i = 0; i < configureElements.length; i++)
368         configureElements[i].disabled = disabled;
369       $('sync-select-datatypes').disabled = disabled;
371       $('customize-link').hidden = disabled;
372       $('customize-link').disabled = disabled;
373       $('customize-link').onclick = disabled ? null : function() {
374         SyncSetupOverlay.showCustomizePage(self.syncConfigureArgs_,
375             options.DataTypeSelection.SYNC_EVERYTHING);
376         return false;
377       };
378     },
380     /**
381      * Shows or hides the sync data type checkboxes in the advanced sync
382      * settings dialog. Also initializes |this.dataTypeBoxesChecked_| and
383      * |this.dataTypeBoxedDisabled_| with their values, and makes their onclick
384      * handlers update |this.dataTypeBoxesChecked_|.
385      * @param {SyncConfig} args The configuration data used to show/hide UI.
386      * @private
387      */
388     setChooseDataTypesCheckboxes_: function(args) {
389       var datatypeSelect = $('sync-select-datatypes');
390       datatypeSelect.selectedIndex = args.syncAllDataTypes ?
391           options.DataTypeSelection.SYNC_EVERYTHING :
392           options.DataTypeSelection.CHOOSE_WHAT_TO_SYNC;
394       $('bookmarks-checkbox').checked = args.bookmarksSynced;
395       this.dataTypeBoxesChecked_['bookmarks-checkbox'] = args.bookmarksSynced;
396       this.dataTypeBoxesDisabled_['bookmarks-checkbox'] =
397           args.bookmarksEnforced;
399       $('preferences-checkbox').checked = args.preferencesSynced;
400       this.dataTypeBoxesChecked_['preferences-checkbox'] =
401           args.preferencesSynced;
402       this.dataTypeBoxesDisabled_['preferences-checkbox'] =
403           args.preferencesEnforced;
405       $('themes-checkbox').checked = args.themesSynced;
406       this.dataTypeBoxesChecked_['themes-checkbox'] = args.themesSynced;
407       this.dataTypeBoxesDisabled_['themes-checkbox'] = args.themesEnforced;
409       if (args.passwordsRegistered) {
410         $('passwords-checkbox').checked = args.passwordsSynced;
411         this.dataTypeBoxesChecked_['passwords-checkbox'] = args.passwordsSynced;
412         this.dataTypeBoxesDisabled_['passwords-checkbox'] =
413             args.passwordsEnforced;
414         $('passwords-item').hidden = false;
415       } else {
416         $('passwords-item').hidden = true;
417       }
418       if (args.autofillRegistered) {
419         $('autofill-checkbox').checked = args.autofillSynced;
420         this.dataTypeBoxesChecked_['autofill-checkbox'] = args.autofillSynced;
421         this.dataTypeBoxesDisabled_['autofill-checkbox'] =
422             args.autofillEnforced;
423         $('autofill-item').hidden = false;
424       } else {
425         $('autofill-item').hidden = true;
426       }
427       if (args.extensionsRegistered) {
428         $('extensions-checkbox').checked = args.extensionsSynced;
429         this.dataTypeBoxesChecked_['extensions-checkbox'] =
430             args.extensionsSynced;
431         this.dataTypeBoxesDisabled_['extensions-checkbox'] =
432             args.extensionsEnforced;
433         $('extensions-item').hidden = false;
434       } else {
435         $('extensions-item').hidden = true;
436       }
437       if (args.typedUrlsRegistered) {
438         $('typed-urls-checkbox').checked = args.typedUrlsSynced;
439         this.dataTypeBoxesChecked_['typed-urls-checkbox'] =
440             args.typedUrlsSynced;
441         this.dataTypeBoxesDisabled_['typed-urls-checkbox'] =
442             args.typedUrlsEnforced;
443         $('omnibox-item').hidden = false;
444       } else {
445         $('omnibox-item').hidden = true;
446       }
447       if (args.appsRegistered) {
448         $('apps-checkbox').checked = args.appsSynced;
449         this.dataTypeBoxesChecked_['apps-checkbox'] = args.appsSynced;
450         this.dataTypeBoxesDisabled_['apps-checkbox'] = args.appsEnforced;
451         $('apps-item').hidden = false;
452       } else {
453         $('apps-item').hidden = true;
454       }
455       if (args.tabsRegistered) {
456         $('tabs-checkbox').checked = args.tabsSynced;
457         this.dataTypeBoxesChecked_['tabs-checkbox'] = args.tabsSynced;
458         this.dataTypeBoxesDisabled_['tabs-checkbox'] = args.tabsEnforced;
459         $('tabs-item').hidden = false;
460       } else {
461         $('tabs-item').hidden = true;
462       }
463       if (args.wifiCredentialsRegistered) {
464         $('wifi-credentials-checkbox').checked = args.wifiCredentialsSynced;
465         this.dataTypeBoxesChecked_['wifi-credentials-checkbox'] =
466             args.wifiCredentialsSynced;
467         this.dataTypeBoxesDisabled_['wifi-credentials-checkbox'] =
468             args.wifiCredentialsEnforced;
469         $('wifi-credentials-item').hidden = false;
470       } else {
471         $('wifi-credentials-item').hidden = true;
472       }
474       $('choose-data-types-body').onchange =
475           this.handleDataTypeChange_.bind(this);
477       this.setDataTypeCheckboxes_(datatypeSelect.selectedIndex);
478     },
480     /**
481      * Updates the cached values of the sync data type checkboxes stored in
482      * |this.dataTypeBoxesChecked_|. Used as an onclick handler for each data
483      * type checkbox.
484      * @param {Event} e The change event.
485      * @private
486      */
487     handleDataTypeChange_: function(e) {
488       var input = assertInstanceof(e.target, HTMLInputElement);
489       assert(input.type == 'checkbox');
490       this.dataTypeBoxesChecked_[input.id] = input.checked;
491       chrome.send('coreOptionsUserMetricsAction',
492                   ['Options_SyncToggleDataType']);
493     },
495     /**
496      * @param {SyncConfig} args
497      * @private
498      */
499     setEncryptionRadios_: function(args) {
500       if (!args.encryptAllData && !args.usePassphrase) {
501         $('basic-encryption-option').checked = true;
502       } else {
503         $('full-encryption-option').checked = true;
504         $('full-encryption-option').disabled = true;
505         $('basic-encryption-option').disabled = true;
506       }
507     },
509     /**
510      * @param {SyncConfig} args
511      * @private
512      */
513     setCheckboxesAndErrors_: function(args) {
514       this.setChooseDataTypesCheckboxes_(args);
515       this.setEncryptionRadios_(args);
516     },
518     /**
519      * @param {SyncConfig} args
520      * @private
521      */
522     showConfigure_: function(args) {
523       var datatypeSelect = $('sync-select-datatypes');
524       var self = this;
526       // Cache the sync config args so they can be reused when we transition
527       // between the drop-down menu items in the advanced settings dialog.
528       if (args)
529         this.syncConfigureArgs_ = args;
531       // Once the advanced sync settings dialog is visible, we transition
532       // between its drop-down menu items as follows:
533       // "Sync everything": Show encryption and passphrase sections, and disable
534       // and check all data type checkboxes.
535       // "Sync nothing": Hide encryption and passphrase sections, and disable
536       // and uncheck all data type checkboxes.
537       // "Choose what to sync": Show encryption and passphrase sections, enable
538       // data type checkboxes, and restore their checked state to the last time
539       // the "Choose what to sync" was selected while the dialog was still up.
540       datatypeSelect.onchange = function() {
541         if (this.selectedIndex == options.DataTypeSelection.SYNC_NOTHING) {
542           self.showSyncNothingPage_();
543         } else {
544           self.showCustomizePage_(self.syncConfigureArgs_, this.selectedIndex);
545           if (this.selectedIndex == options.DataTypeSelection.SYNC_EVERYTHING)
546             self.checkAllDataTypeCheckboxes_(true);
547           else
548             self.restoreDataTypeCheckboxes_();
549         }
550       };
552       this.resetPage_('sync-setup-configure');
553       $('sync-setup-configure').hidden = false;
555       // onsubmit is changed when submitting a passphrase. Reset it to its
556       // default.
557       $('choose-data-types-form').onsubmit = function() {
558         self.sendConfiguration_();
559         return false;
560       };
562       if (args) {
563         this.setCheckboxesAndErrors_(args);
565         this.useEncryptEverything_ = args.encryptAllData;
567         // Determine whether to display the 'OK, sync everything' confirmation
568         // dialog or the advanced sync settings dialog, and assign focus to the
569         // OK button, or to the passphrase field if a passphrase is required.
570         this.usePassphrase_ = args.usePassphrase;
571         var index = args.syncAllDataTypes ?
572                         options.DataTypeSelection.SYNC_EVERYTHING :
573                         options.DataTypeSelection.CHOOSE_WHAT_TO_SYNC;
574         this.showCustomizePage_(args, index);
575       }
576     },
578     /** @private */
579     showSpinner_: function() {
580       this.resetPage_('sync-setup-spinner');
581       $('sync-setup-spinner').hidden = false;
582     },
584     /** @private */
585     showTimeoutPage_: function() {
586       this.resetPage_('sync-setup-timeout');
587       $('sync-setup-timeout').hidden = false;
588     },
590     /** @private */
591     showSyncEverythingPage_: function() {
592       chrome.send('coreOptionsUserMetricsAction',
593                   ['Options_SyncSetDefault']);
595       $('confirm-sync-preferences').hidden = false;
596       $('customize-sync-preferences').hidden = true;
598       // Reset the selection to 'Sync everything'.
599       $('sync-select-datatypes').selectedIndex = 0;
601       // The default state is to sync everything.
602       this.setDataTypeCheckboxes_(options.DataTypeSelection.SYNC_EVERYTHING);
604       // TODO(dbeam): should hide sync-custom-passphrase-container instead?
605       if (!this.usePassphrase_)
606         $('sync-custom-passphrase').hidden = true;
608       if (!this.useEncryptEverything_ && !this.usePassphrase_)
609         $('basic-encryption-option').checked = true;
610     },
612     /**
613      * Reveals the UI for when the user chooses not to sync any data types.
614      * This happens when the user signs in and selects "Sync nothing" in the
615      * advanced sync settings dialog.
616      * @private
617      */
618     showSyncNothingPage_: function() {
619       // Reset the selection to 'Sync nothing'.
620       $('sync-select-datatypes').selectedIndex =
621           options.DataTypeSelection.SYNC_NOTHING;
623       // Uncheck and disable the individual data type checkboxes.
624       this.checkAllDataTypeCheckboxes_(false);
625       this.setDataTypeCheckboxesEnabled_(false);
627       // Hide the encryption section.
628       $('customize-sync-encryption-new').hidden = true;
629       $('sync-custom-passphrase-container').hidden = true;
630       $('sync-existing-passphrase-container').hidden = true;
632       // Hide the "use default settings" link.
633       $('use-default-link').hidden = true;
634     },
636     /**
637      * Reveals the UI for entering a custom passphrase during initial setup.
638      * This happens if the user has previously enabled a custom passphrase on a
639      * different machine.
640      * @param {SyncConfig} args The args that contain the passphrase UI
641      *     configuration.
642      * @private
643      */
644     showPassphraseContainer_: function(args) {
645       // Once we require a passphrase, we prevent the user from returning to
646       // the Sync Everything pane.
647       $('use-default-link').hidden = true;
648       $('sync-custom-passphrase-container').hidden = true;
649       $('sync-existing-passphrase-container').hidden = false;
651       // Hide the selection options within the new encryption section when
652       // prompting for a passphrase.
653       $('sync-new-encryption-section-container').hidden = true;
655       $('normal-body').hidden = true;
656       $('google-passphrase-needed-body').hidden = true;
657       // Display the correct prompt to the user depending on what type of
658       // passphrase is needed.
659       if (args.usePassphrase)
660         $('normal-body').hidden = false;
661       else
662         $('google-passphrase-needed-body').hidden = false;
664       $('passphrase-learn-more').hidden = false;
665       // Warn the user about their incorrect passphrase if we need a passphrase
666       // and the passphrase field is non-empty (meaning they tried to set it
667       // previously but failed).
668       $('incorrect-passphrase').hidden =
669           !(args.usePassphrase && args.passphraseFailed);
671       $('sync-passphrase-warning').hidden = false;
672     },
674     /**
675      * Displays the advanced sync setting dialog, and pre-selects either the
676      * "Sync everything" or the "Choose what to sync" drop-down menu item.
677      * @param {SyncConfig} args
678      * @param {options.DataTypeSelection} index Index of item to pre-select.
679      * @private
680      */
681     showCustomizePage_: function(args, index) {
682       $('confirm-sync-preferences').hidden = true;
683       $('customize-sync-preferences').hidden = false;
685       $('sync-custom-passphrase-container').hidden = false;
686       $('sync-new-encryption-section-container').hidden = false;
687       $('customize-sync-encryption-new').hidden = !args.encryptAllDataAllowed;
689       $('sync-existing-passphrase-container').hidden = true;
691       $('sync-select-datatypes').selectedIndex = index;
692       this.setDataTypeCheckboxesEnabled_(
693           index == options.DataTypeSelection.CHOOSE_WHAT_TO_SYNC);
695       if (args.showPassphrase) {
696         this.showPassphraseContainer_(args);
697         // TODO(dbeam): add an #updatePassphrase and only focus with that hash?
698         $('passphrase').focus();
699       } else {
700         // We only show the 'Use Default' link if we're not prompting for an
701         // existing passphrase.
702         $('use-default-link').hidden = false;
703       }
704     },
706     /**
707      * Shows the appropriate sync setup page.
708      * @param {string} page A page of the sync setup to show.
709      * @param {SyncConfig} args Data from the C++ to forward on to the right
710      *     section.
711      */
712     showSyncSetupPage_: function(page, args) {
713       // If the user clicks the OK button, dismiss the dialog immediately, and
714       // do not go through the process of hiding elements of the overlay.
715       // See crbug.com/308873.
716       if (page == 'done') {
717         this.closeOverlay_();
718         return;
719       }
721       this.setThrobbersVisible_(false);
723       // Hide an existing visible overlay (ensuring the close button is not
724       // hidden).
725       var children = document.querySelectorAll(
726           '#sync-setup-overlay > *:not(.close-button)');
727       for (var i = 0; i < children.length; i++)
728         children[i].hidden = true;
730       this.setInputElementsDisabledState_(false);
732       // If new passphrase bodies are present, overwrite the existing ones.
733       if (args && args.enterPassphraseBody != undefined)
734         $('normal-body').innerHTML = args.enterPassphraseBody;
735       if (args && args.enterGooglePassphraseBody != undefined) {
736         $('google-passphrase-needed-body').innerHTML =
737             args.enterGooglePassphraseBody;
738       }
739       if (args && args.fullEncryptionBody != undefined)
740         $('full-encryption-body').innerHTML = args.fullEncryptionBody;
742       // NOTE: Because both showGaiaLogin_() and showConfigure_() change the
743       // focus, we need to ensure that the overlay container and dialog aren't
744       // [hidden] (as trying to focus() nodes inside of a [hidden] DOM section
745       // doesn't work).
746       this.showOverlay_();
748       if (page == 'configure' || page == 'passphrase')
749         this.showConfigure_(args);
750       else if (page == 'spinner')
751         this.showSpinner_();
752       else if (page == 'timeout')
753         this.showTimeoutPage_();
754     },
756     /**
757      * Changes the visibility of throbbers on this page.
758      * @param {boolean} visible Whether or not to set all throbber nodes
759      *     visible.
760      */
761     setThrobbersVisible_: function(visible) {
762       var throbbers = this.pageDiv.getElementsByClassName('throbber');
763       for (var i = 0; i < throbbers.length; i++)
764         throbbers[i].style.visibility = visible ? 'visible' : 'hidden';
765     },
767     /**
768      * Reset the state of all descendant elements of a root element to their
769      * initial state.
770      * The initial state is specified by adding a class to the descendant
771      * element in sync_setup_overlay.html.
772      * @param {string} pageElementId The root page element id.
773      * @private
774      */
775     resetPage_: function(pageElementId) {
776       var page = $(pageElementId);
777       var forEach = function(arr, fn) {
778         var length = arr.length;
779         for (var i = 0; i < length; i++) {
780           fn(arr[i]);
781         }
782       };
784       forEach(page.getElementsByClassName('reset-hidden'),
785           function(elt) { elt.hidden = true; });
786       forEach(page.getElementsByClassName('reset-shown'),
787           function(elt) { elt.hidden = false; });
788       forEach(page.getElementsByClassName('reset-disabled'),
789           function(elt) { elt.disabled = true; });
790       forEach(page.getElementsByClassName('reset-enabled'),
791           function(elt) { elt.disabled = false; });
792       forEach(page.getElementsByClassName('reset-value'),
793           function(elt) { elt.value = ''; });
794       forEach(page.getElementsByClassName('reset-opaque'),
795           function(elt) { elt.classList.remove('transparent'); });
796     },
798     /**
799      * Displays the stop syncing dialog.
800      * @private
801      */
802     showStopSyncingUI_: function() {
803       // Hide any visible children of the overlay.
804       var overlay = $('sync-setup-overlay');
805       for (var i = 0; i < overlay.children.length; i++)
806         overlay.children[i].hidden = true;
808       // Bypass PageManager.showPageByName because it will call didShowPage
809       // which will set its own visible page, based on the flow state.
810       this.visible = true;
812       $('sync-setup-stop-syncing').hidden = false;
813     },
815     /**
816      * Determines the appropriate page to show in the Sync Setup UI based on
817      * the state of the Sync backend. Does nothing if the user is not signed in.
818      * @private
819      */
820     showSetupUI_: function() {
821       chrome.send('SyncSetupShowSetupUI');
822       chrome.send('coreOptionsUserMetricsAction', ['Options_ShowSyncAdvanced']);
823     },
825     /**
826      * Starts the signin process for the user. Does nothing if the user is
827      * already signed in.
828      * @private
829      */
830     startSignIn_: function() {
831       chrome.send('SyncSetupStartSignIn');
832     },
834     /**
835      * Forces user to sign out of Chrome for Chrome OS.
836      * @private
837      */
838     doSignOutOnAuthError_: function() {
839       chrome.send('SyncSetupDoSignOutOnAuthError');
840     },
841   };
843   // These methods are for general consumption.
844   SyncSetupOverlay.closeOverlay = function() {
845     SyncSetupOverlay.getInstance().closeOverlay_();
846   };
848   SyncSetupOverlay.showSetupUI = function() {
849     SyncSetupOverlay.getInstance().showSetupUI_();
850   };
852   SyncSetupOverlay.startSignIn = function() {
853     SyncSetupOverlay.getInstance().startSignIn_();
854   };
856   SyncSetupOverlay.doSignOutOnAuthError = function() {
857     SyncSetupOverlay.getInstance().doSignOutOnAuthError_();
858   };
860   SyncSetupOverlay.showSyncSetupPage = function(page, args) {
861     SyncSetupOverlay.getInstance().showSyncSetupPage_(page, args);
862   };
864   SyncSetupOverlay.showCustomizePage = function(args, index) {
865     SyncSetupOverlay.getInstance().showCustomizePage_(args, index);
866   };
868   SyncSetupOverlay.showStopSyncingUI = function() {
869     SyncSetupOverlay.getInstance().showStopSyncingUI_();
870   };
872   // Export
873   return {
874     SyncSetupOverlay: SyncSetupOverlay
875   };