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