Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / resources / file_manager / foreground / js / drive_banners.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 'use strict';
6
7 /**
8  * Responsible for showing following banners in the file list.
9  *  - WelcomeBanner
10  *  - AuthFailBanner
11  * @param {DirectoryModel} directoryModel The model.
12  * @param {VolumeManagerWrapper} volumeManager The manager.
13  * @param {DOMDocument} document HTML document.
14  * @param {boolean} showOffers True if we should show offer banners.
15  * @constructor
16  */
17 function FileListBannerController(
18     directoryModel, volumeManager, document, showOffers) {
19   this.directoryModel_ = directoryModel;
20   this.volumeManager_ = volumeManager;
21   this.document_ = document;
22   this.showOffers_ = showOffers;
23   this.driveEnabled_ = false;
24
25   this.initializeWelcomeBanner_();
26   this.privateOnDirectoryChangedBound_ =
27       this.privateOnDirectoryChanged_.bind(this);
28
29   var handler = this.checkSpaceAndMaybeShowWelcomeBanner_.bind(this);
30   this.directoryModel_.addEventListener('scan-completed', handler);
31   this.directoryModel_.addEventListener('rescan-completed', handler);
32   this.directoryModel_.addEventListener('directory-changed',
33       this.onDirectoryChanged_.bind(this));
34
35   this.unmountedPanel_ = this.document_.querySelector('#unmounted-panel');
36   this.volumeManager_.volumeInfoList.addEventListener(
37       'splice', this.onVolumeInfoListSplice_.bind(this));
38   this.volumeManager_.addEventListener('drive-connection-changed',
39       this.onDriveConnectionChanged_.bind(this));
40
41   chrome.storage.onChanged.addListener(this.onStorageChange_.bind(this));
42   this.welcomeHeaderCounter_ = WELCOME_HEADER_COUNTER_LIMIT;
43   this.warningDismissedCounter_ = 0;
44   chrome.storage.local.get([WELCOME_HEADER_COUNTER_KEY, WARNING_DISMISSED_KEY],
45                          function(values) {
46     this.welcomeHeaderCounter_ =
47         parseInt(values[WELCOME_HEADER_COUNTER_KEY]) || 0;
48     this.warningDismissedCounter_ =
49         parseInt(values[WARNING_DISMISSED_KEY]) || 0;
50   }.bind(this));
51
52   this.authFailedBanner_ =
53       this.document_.querySelector('#drive-auth-failed-warning');
54   var authFailedText = this.authFailedBanner_.querySelector('.drive-text');
55   authFailedText.innerHTML = util.htmlUnescape(str('DRIVE_NOT_REACHED'));
56   authFailedText.querySelector('a').addEventListener('click', function(e) {
57     chrome.fileBrowserPrivate.logoutUserForReauthentication();
58     e.preventDefault();
59   });
60   this.maybeShowAuthFailBanner_();
61 }
62
63 /**
64  * FileListBannerController extends cr.EventTarget.
65  */
66 FileListBannerController.prototype.__proto__ = cr.EventTarget.prototype;
67
68 /**
69  * Key in localStorage to keep number of times the Drive Welcome
70  * banner has shown.
71  */
72 var WELCOME_HEADER_COUNTER_KEY = 'driveWelcomeHeaderCounter';
73
74 // If the warning was dismissed before, this key stores the quota value
75 // (as of the moment of dismissal).
76 // If the warning was never dismissed or was reset this key stores 0.
77 var WARNING_DISMISSED_KEY = 'driveSpaceWarningDismissed';
78
79 /**
80  * Maximum times Drive Welcome banner could have shown.
81  */
82 var WELCOME_HEADER_COUNTER_LIMIT = 25;
83
84 /**
85  * Initializes the banner to promote DRIVE.
86  * This method must be called before any of showing banner functions, and
87  * also before registering them as callbacks.
88  * @private
89  */
90 FileListBannerController.prototype.initializeWelcomeBanner_ = function() {
91   this.usePromoWelcomeBanner_ = !util.boardIs('x86-mario') &&
92                                 !util.boardIs('x86-zgb') &&
93                                 !util.boardIs('x86-alex');
94 };
95
96 /**
97  * @param {number} value How many times the Drive Welcome header banner
98  * has shown.
99  * @private
100  */
101 FileListBannerController.prototype.setWelcomeHeaderCounter_ = function(value) {
102   var values = {};
103   values[WELCOME_HEADER_COUNTER_KEY] = value;
104   chrome.storage.local.set(values);
105 };
106
107 /**
108  * @param {number} value How many times the low space warning has dismissed.
109  * @private
110  */
111 FileListBannerController.prototype.setWarningDismissedCounter_ =
112     function(value) {
113   var values = {};
114   values[WARNING_DISMISSED_KEY] = value;
115   chrome.storage.local.set(values);
116 };
117
118 /**
119  * chrome.storage.onChanged event handler.
120  * @param {Object.<string, Object>} changes Changes values.
121  * @param {string} areaName "local" or "sync".
122  * @private
123  */
124 FileListBannerController.prototype.onStorageChange_ = function(changes,
125                                                                areaName) {
126   if (areaName == 'local' && WELCOME_HEADER_COUNTER_KEY in changes) {
127     this.welcomeHeaderCounter_ = changes[WELCOME_HEADER_COUNTER_KEY].newValue;
128   }
129   if (areaName == 'local' && WARNING_DISMISSED_KEY in changes) {
130     this.warningDismissedCounter_ = changes[WARNING_DISMISSED_KEY].newValue;
131   }
132 };
133
134 /**
135  * Invoked when the drive connection status is change in the volume manager.
136  * @private
137  */
138 FileListBannerController.prototype.onDriveConnectionChanged_ = function() {
139   this.maybeShowAuthFailBanner_();
140 };
141
142 /**
143  * @param {string} type 'none'|'page'|'header'.
144  * @param {string} messageId Resource ID of the message.
145  * @private
146  */
147 FileListBannerController.prototype.prepareAndShowWelcomeBanner_ =
148     function(type, messageId) {
149   this.showWelcomeBanner_(type);
150
151   var container = this.document_.querySelector('.drive-welcome.' + type);
152   if (container.firstElementChild)
153     return;  // Do not re-create.
154
155   if (!this.document_.querySelector('link[drive-welcome-style]')) {
156     var style = this.document_.createElement('link');
157     style.rel = 'stylesheet';
158     style.href = 'foreground/css/drive_welcome.css';
159     style.setAttribute('drive-welcome-style', '');
160     this.document_.head.appendChild(style);
161   }
162
163   var wrapper = util.createChild(container, 'drive-welcome-wrapper');
164   util.createChild(wrapper, 'drive-welcome-icon');
165
166   var close = util.createChild(wrapper, 'cr-dialog-close');
167   close.addEventListener('click', this.closeWelcomeBanner_.bind(this));
168
169   var message = util.createChild(wrapper, 'drive-welcome-message');
170
171   var title = util.createChild(message, 'drive-welcome-title');
172
173   var text = util.createChild(message, 'drive-welcome-text');
174   text.innerHTML = str(messageId);
175
176   var links = util.createChild(message, 'drive-welcome-links');
177
178   var more;
179   if (this.usePromoWelcomeBanner_) {
180     var welcomeTitle = str('DRIVE_WELCOME_TITLE_ALTERNATIVE');
181     if (util.boardIs('link'))
182       welcomeTitle = str('DRIVE_WELCOME_TITLE_ALTERNATIVE_1TB');
183     title.textContent = welcomeTitle;
184     more = util.createChild(links,
185         'drive-welcome-button drive-welcome-start', 'a');
186     more.textContent = str('DRIVE_WELCOME_CHECK_ELIGIBILITY');
187     more.href = str('GOOGLE_DRIVE_REDEEM_URL');
188   } else {
189     title.textContent = str('DRIVE_WELCOME_TITLE');
190     more = util.createChild(links, 'plain-link', 'a');
191     more.textContent = str('DRIVE_LEARN_MORE');
192     more.href = str('GOOGLE_DRIVE_OVERVIEW_URL');
193   }
194   more.tabIndex = '13';  // See: go/filesapp-tabindex.
195   more.target = '_blank';
196
197   var dismiss;
198   if (this.usePromoWelcomeBanner_)
199     dismiss = util.createChild(links, 'drive-welcome-button');
200   else
201     dismiss = util.createChild(links, 'plain-link');
202
203   dismiss.classList.add('drive-welcome-dismiss');
204   dismiss.textContent = str('DRIVE_WELCOME_DISMISS');
205   dismiss.addEventListener('click', this.closeWelcomeBanner_.bind(this));
206
207   this.previousDirWasOnDrive_ = false;
208 };
209
210 /**
211  * Show or hide the "Low Google Drive space" warning.
212  * @param {boolean} show True if the box need to be shown.
213  * @param {Object} sizeStats Size statistics. Should be defined when showing the
214  *     warning.
215  * @private
216  */
217 FileListBannerController.prototype.showLowDriveSpaceWarning_ =
218       function(show, sizeStats) {
219   var box = this.document_.querySelector('#volume-space-warning');
220
221   // Avoid showing two banners.
222   // TODO(kaznacheev): Unify the low space warning and the promo header.
223   if (show)
224     this.cleanupWelcomeBanner_();
225
226   if (box.hidden == !show)
227     return;
228
229   if (this.warningDismissedCounter_) {
230     if (this.warningDismissedCounter_ ==
231             sizeStats.totalSize && // Quota had not changed
232         sizeStats.remainingSize / sizeStats.totalSize < 0.15) {
233       // Since the last dismissal decision the quota has not changed AND
234       // the user did not free up significant space. Obey the dismissal.
235       show = false;
236     } else {
237       // Forget the dismissal. Warning will be shown again.
238       this.setWarningDismissedCounter_(0);
239     }
240   }
241
242   box.textContent = '';
243   if (show) {
244     var icon = this.document_.createElement('div');
245     icon.className = 'drive-icon';
246     box.appendChild(icon);
247
248     var text = this.document_.createElement('div');
249     text.className = 'drive-text';
250     text.textContent = strf('DRIVE_SPACE_AVAILABLE_LONG',
251         util.bytesToString(sizeStats.remainingSize));
252     box.appendChild(text);
253
254     var link = this.document_.createElement('a');
255     link.className = 'plain-link';
256     link.textContent = str('DRIVE_BUY_MORE_SPACE_LINK');
257     link.href = str('GOOGLE_DRIVE_BUY_STORAGE_URL');
258     link.target = '_blank';
259     box.appendChild(link);
260
261     var close = this.document_.createElement('div');
262     close.className = 'cr-dialog-close';
263     box.appendChild(close);
264     close.addEventListener('click', function(total) {
265       var values = {};
266       values[WARNING_DISMISSED_KEY] = total;
267       chrome.storage.local.set(values);
268       box.hidden = true;
269       this.requestRelayout_(100);
270     }.bind(this, sizeStats.totalSize));
271   }
272
273   if (box.hidden != !show) {
274     box.hidden = !show;
275     this.requestRelayout_(100);
276   }
277 };
278 /**
279  * Closes the Drive Welcome banner.
280  * @private
281  */
282 FileListBannerController.prototype.closeWelcomeBanner_ = function() {
283   this.cleanupWelcomeBanner_();
284   // Stop showing the welcome banner.
285   this.setWelcomeHeaderCounter_(WELCOME_HEADER_COUNTER_LIMIT);
286 };
287
288 /**
289  * Shows or hides the welcome banner for drive.
290  * @private
291  */
292 FileListBannerController.prototype.checkSpaceAndMaybeShowWelcomeBanner_ =
293     function() {
294   if (!this.isOnCurrentProfileDrive()) {
295     // We are not on the drive file system. Do not show (close) the welcome
296     // banner.
297     this.cleanupWelcomeBanner_();
298     this.previousDirWasOnDrive_ = false;
299     return;
300   }
301
302   var driveVolume = this.volumeManager_.getCurrentProfileVolumeInfo(
303       util.VolumeType.DRIVE);
304   if (this.welcomeHeaderCounter_ >= WELCOME_HEADER_COUNTER_LIMIT ||
305       !driveVolume || driveVolume.error) {
306     // The banner is already shown enough times or the drive FS is not mounted.
307     // So, do nothing here.
308     return;
309   }
310
311   if (!this.showOffers_) {
312     // Because it is not necessary to show the offer, set
313     // |usePromoWelcomeBanner_| false here. Note that it probably should be able
314     // to do this in the constructor, but there remains non-trivial path,
315     // which may be causes |usePromoWelcomeBanner_| == true's behavior even
316     // if |showOffers_| is false.
317     // TODO(hidehiko): Make sure if it is expected or not, and simplify
318     // |showOffers_| if possible.
319     this.usePromoWelcomeBanner_ = false;
320   }
321
322   // Perform asynchronous tasks in parallel.
323   var group = new AsyncUtil.Group();
324
325   // Choose the offer basing on the board name. The default one is 100 GB.
326   var offerSize = 100;  // In GB.
327   var offerServiceId = 'drive.cros.echo.1';
328
329   if (util.boardIs('link')) {
330     offerSize = 1024;  // 1 TB.
331     offerServiceId = 'drive.cros.echo.2';
332   }
333
334   // If the offer has been checked, then do not show the promo anymore.
335   group.add(function(onCompleted) {
336     chrome.echoPrivate.getOfferInfo(offerServiceId, function(offerInfo) {
337       // If the offer has not been checked, then an error is raised.
338       if (!chrome.runtime.lastError)
339         this.usePromoWelcomeBanner_ = false;
340       onCompleted();
341     }.bind(this));
342   }.bind(this));
343
344   if (this.usePromoWelcomeBanner_) {
345     // getSizeStats for Drive file system accesses to the server, so we should
346     // minimize the invocation.
347     group.add(function(onCompleted) {
348       // Current directory must be set, since this code is called after
349       // scaning is completed. However, the volumeInfo may be gone.
350       chrome.fileBrowserPrivate.getSizeStats(
351           driveVolume.volumeId,
352           function(result) {
353             if (result && result.totalSize >= offerSize * 1024 * 1024 * 1024)
354               this.usePromoWelcomeBanner_ = false;
355             onCompleted();
356           }.bind(this));
357     }.bind(this));
358   }
359
360   group.run(this.maybeShowWelcomeBanner_.bind(this));
361 };
362
363 /**
364  * Decides which banner should be shown, and show it. This method is designed
365  * to be called only from checkSpaceAndMaybeShowWelcomeBanner_.
366  * @private
367  */
368 FileListBannerController.prototype.maybeShowWelcomeBanner_ = function() {
369   if (this.directoryModel_.getFileList().length == 0 &&
370       this.welcomeHeaderCounter_ == 0) {
371     // Only show the full page banner if the header banner was never shown.
372     // Do not increment the counter.
373     // The timeout below is required because sometimes another
374     // 'rescan-completed' event arrives shortly with non-empty file list.
375     setTimeout(function() {
376       if (this.isOnCurrentProfileDrive() && this.welcomeHeaderCounter_ == 0) {
377         this.prepareAndShowWelcomeBanner_('page', 'DRIVE_WELCOME_TEXT_LONG');
378       }
379     }.bind(this), 2000);
380   } else {
381     // We do not want to increment the counter when the user navigates
382     // between different directories on Drive, but we increment the counter
383     // once anyway to prevent the full page banner from showing.
384     if (!this.previousDirWasOnDrive_ || this.welcomeHeaderCounter_ == 0) {
385       this.setWelcomeHeaderCounter_(this.welcomeHeaderCounter_ + 1);
386       this.prepareAndShowWelcomeBanner_('header', 'DRIVE_WELCOME_TEXT_SHORT');
387     }
388   }
389   this.previousDirWasOnDrive_ = true;
390 };
391
392 /**
393  * @return {boolean} True if current directory is on Drive root of current
394  * profile.
395  */
396 FileListBannerController.prototype.isOnCurrentProfileDrive = function() {
397   var entry = this.directoryModel_.getCurrentDirEntry();
398   if (!entry || util.isFakeEntry(entry))
399     return false;
400   var locationInfo = this.volumeManager_.getLocationInfo(entry);
401   return locationInfo &&
402       locationInfo.rootType === RootType.DRIVE &&
403       locationInfo.volumeInfo.profile.isCurrentProfile;
404 };
405
406 /**
407  * Shows the Drive Welcome banner.
408  * @param {string} type 'page'|'head'|'none'.
409  * @private
410  */
411 FileListBannerController.prototype.showWelcomeBanner_ = function(type) {
412   var container = this.document_.querySelector('.dialog-container');
413   if (container.getAttribute('drive-welcome') != type) {
414     container.setAttribute('drive-welcome', type);
415     this.requestRelayout_(200);  // Resize only after the animation is done.
416   }
417 };
418
419 /**
420  * Update the UI when the current directory changes.
421  *
422  * @param {Event} event The directory-changed event.
423  * @private
424  */
425 FileListBannerController.prototype.onDirectoryChanged_ = function(event) {
426   var rootVolume = this.volumeManager_.getVolumeInfo(event.newDirEntry);
427   var previousRootVolume = event.previousDirEntry ?
428       this.volumeManager_.getVolumeInfo(event.previousDirEntry) : null;
429
430   // Show (or hide) the low space warning.
431   this.maybeShowLowSpaceWarning_(rootVolume);
432
433   // Add or remove listener to show low space warning, if necessary.
434   var isLowSpaceWarningTarget = this.isLowSpaceWarningTarget_(rootVolume);
435   if (isLowSpaceWarningTarget !==
436       this.isLowSpaceWarningTarget_(previousRootVolume)) {
437     if (isLowSpaceWarningTarget) {
438       chrome.fileBrowserPrivate.onDirectoryChanged.addListener(
439           this.privateOnDirectoryChangedBound_);
440     } else {
441       chrome.fileBrowserPrivate.onDirectoryChanged.removeListener(
442           this.privateOnDirectoryChangedBound_);
443     }
444   }
445
446   if (!this.isOnCurrentProfileDrive()) {
447     this.cleanupWelcomeBanner_();
448     this.authFailedBanner_.hidden = true;
449   }
450
451   this.updateDriveUnmountedPanel_();
452   if (this.isOnCurrentProfileDrive()) {
453     this.unmountedPanel_.classList.remove('retry-enabled');
454     this.maybeShowAuthFailBanner_();
455   }
456 };
457
458 /**
459  * @param {VolumeInfo} volumeInfo Volume info to be checked.
460  * @return {boolean} true if the file system specified by |root| is a target
461  *     to show low space warning. Otherwise false.
462  * @private
463  */
464 FileListBannerController.prototype.isLowSpaceWarningTarget_ =
465     function(volumeInfo) {
466   return volumeInfo &&
467       volumeInfo.profile.isCurrentProfile &&
468       (volumeInfo.volumeType === util.VolumeType.DOWNLOADS ||
469        volumeInfo.volumeType === util.VolumeType.DRIVE);
470 };
471
472 /**
473  * Callback which is invoked when the file system has been changed.
474  * @param {Object} event chrome.fileBrowserPrivate.onDirectoryChanged event.
475  * @private
476  */
477 FileListBannerController.prototype.privateOnDirectoryChanged_ = function(
478     event) {
479   if (!this.directoryModel_.getCurrentDirEntry())
480     return;
481
482   var currentDirEntry = this.directoryModel_.getCurrentDirEntry();
483   var currentVolume = currentDirEntry &&
484       this.volumeManager_.getVolumeInfo(currentDirEntry);
485   var eventVolume = this.volumeManager_.getVolumeInfo(event.entry);
486   if (currentVolume === eventVolume) {
487     // The file system we are currently on is changed.
488     // So, check the free space.
489     this.maybeShowLowSpaceWarning_(currentVolume);
490   }
491 };
492
493 /**
494  * Shows or hides the low space warning.
495  * @param {VolumeInfo} volume Type of volume, which we are interested in.
496  * @private
497  */
498 FileListBannerController.prototype.maybeShowLowSpaceWarning_ = function(
499     volume) {
500   // TODO(kaznacheev): Unify the two low space warning.
501   var threshold = 0;
502   switch (volume.volumeType) {
503     case util.VolumeType.DOWNLOADS:
504       this.showLowDriveSpaceWarning_(false);
505       threshold = 0.2;
506       break;
507     case util.VolumeType.DRIVE:
508       this.showLowDownloadsSpaceWarning_(false);
509       threshold = 0.1;
510       break;
511     default:
512       // If the current file system is neither the DOWNLOAD nor the DRIVE,
513       // just hide the warning.
514       this.showLowDownloadsSpaceWarning_(false);
515       this.showLowDriveSpaceWarning_(false);
516       return;
517   }
518
519   // If not mounted correctly, then do not continue.
520   if (!volume.root)
521     return;
522
523   chrome.fileBrowserPrivate.getSizeStats(
524       volume.root.toURL(),
525       function(sizeStats) {
526         var currentVolume = this.volumeManager_.getVolumeInfo(
527             this.directoryModel_.getCurrentDirEntry());
528         if (volume !== currentVolume) {
529           // This happens when the current directory is moved during requesting
530           // the file system size. Just ignore it.
531           return;
532         }
533         // sizeStats is undefined, if some error occurs.
534         if (!sizeStats || sizeStats.totalSize == 0)
535           return;
536
537         var remainingRatio = sizeStats.remainingSize / sizeStats.totalSize;
538         var isLowDiskSpace = remainingRatio < threshold;
539         if (volume.volumeType === util.VolumeType.DOWNLOADS)
540           this.showLowDownloadsSpaceWarning_(isLowDiskSpace);
541         else
542           this.showLowDriveSpaceWarning_(isLowDiskSpace, sizeStats);
543       }.bind(this));
544 };
545
546 /**
547  * removes the Drive Welcome banner.
548  * @private
549  */
550 FileListBannerController.prototype.cleanupWelcomeBanner_ = function() {
551   this.showWelcomeBanner_('none');
552 };
553
554 /**
555  * Notifies the file manager what layout must be recalculated.
556  * @param {number} delay In milliseconds.
557  * @private
558  */
559 FileListBannerController.prototype.requestRelayout_ = function(delay) {
560   var self = this;
561   setTimeout(function() {
562     cr.dispatchSimpleEvent(self, 'relayout');
563   }, delay);
564 };
565
566 /**
567  * Show or hide the "Low disk space" warning.
568  * @param {boolean} show True if the box need to be shown.
569  * @private
570  */
571 FileListBannerController.prototype.showLowDownloadsSpaceWarning_ =
572     function(show) {
573   var box = this.document_.querySelector('.downloads-warning');
574
575   if (box.hidden == !show) return;
576
577   if (show) {
578     var html = util.htmlUnescape(str('DOWNLOADS_DIRECTORY_WARNING'));
579     box.innerHTML = html;
580     box.querySelector('a').addEventListener('click', function(e) {
581       util.visitURL(str('DOWNLOADS_LOW_SPACE_WARNING_HELP_URL'));
582       e.preventDefault();
583     });
584   } else {
585     box.innerHTML = '';
586   }
587
588   box.hidden = !show;
589   this.requestRelayout_(100);
590 };
591
592 /**
593  * Creates contents for the DRIVE unmounted panel.
594  * @private
595  */
596 FileListBannerController.prototype.ensureDriveUnmountedPanelInitialized_ =
597     function() {
598   var panel = this.unmountedPanel_;
599   if (panel.firstElementChild)
600     return;
601
602   var create = function(parent, tag, className, opt_textContent) {
603     var div = panel.ownerDocument.createElement(tag);
604     div.className = className;
605     div.textContent = opt_textContent || '';
606     parent.appendChild(div);
607     return div;
608   };
609
610   var loading = create(panel, 'div', 'loading', str('DRIVE_LOADING'));
611   var spinnerBox = create(loading, 'div', 'spinner-box');
612   create(spinnerBox, 'div', 'spinner');
613   create(panel, 'div', 'error', str('DRIVE_CANNOT_REACH'));
614
615   var learnMore = create(panel, 'a', 'learn-more plain-link',
616                          str('DRIVE_LEARN_MORE'));
617   learnMore.href = str('GOOGLE_DRIVE_ERROR_HELP_URL');
618   learnMore.target = '_blank';
619 };
620
621 /**
622  * Called when volume info list is updated.
623  * @param {Event} event Splice event data on volume info list.
624  * @private
625  */
626 FileListBannerController.prototype.onVolumeInfoListSplice_ = function(event) {
627   var isDriveVolume = function(volumeInfo) {
628     return volumeInfo.volumeType === util.VolumeType.DRIVE;
629   };
630   if (event.removed.some(isDriveVolume) || event.added.some(isDriveVolume))
631     this.updateDriveUnmountedPanel_();
632 };
633
634 /**
635  * Shows the panel when current directory is DRIVE and it's unmounted.
636  * Hides it otherwise. The panel shows spinner if DRIVE is mounting or
637  * an error message if it failed.
638  * @private
639  */
640 FileListBannerController.prototype.updateDriveUnmountedPanel_ = function() {
641   var node = this.document_.body;
642   if (this.isOnCurrentProfileDrive()) {
643     var driveVolume = this.volumeManager_.getCurrentProfileVolumeInfo(
644         util.VolumeType.DRIVE);
645     if (driveVolume && driveVolume.error) {
646       this.ensureDriveUnmountedPanelInitialized_();
647       this.unmountedPanel_.classList.add('retry-enabled');
648     } else {
649       this.unmountedPanel_.classList.remove('retry-enabled');
650     }
651     node.setAttribute('drive', status);
652   } else {
653     node.removeAttribute('drive');
654   }
655 };
656
657 /**
658  * Updates the visibility of Drive Connection Warning banner, retrieving the
659  * current connection information.
660  * @private
661  */
662 FileListBannerController.prototype.maybeShowAuthFailBanner_ = function() {
663   var connection = this.volumeManager_.getDriveConnectionState();
664   var showDriveNotReachedMessage =
665       this.isOnCurrentProfileDrive() &&
666       connection.type == util.DriveConnectionType.OFFLINE &&
667       connection.reason == util.DriveConnectionReason.NOT_READY;
668   this.authFailedBanner_.hidden = !showDriveNotReachedMessage;
669 };