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 {VolumeManager} 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_.addEventListener('drive-status-changed', 37 this.updateDriveUnmountedPanel_.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.logoutUser(); 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 numer 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 * Location of the FAQ about Google Drive. 86 */ 87 var GOOGLE_DRIVE_FAQ_URL = 88 'https://support.google.com/chromeos/?p=filemanager_drive'; 89 90 /** 91 * Location of the page to buy more storage for Google Drive. 92 */ 93 var GOOGLE_DRIVE_BUY_STORAGE = 94 'https://www.google.com/settings/storage'; 95 96 var GOOGLE_DRIVE_REDEEM = 97 'http://www.google.com/intl/en/chrome/devices/goodies.html'; 98 99 /** 100 * Location of the FAQ about the downloads directory. 101 */ 102 var DOWNLOADS_FAQ_URL = 103 'http://support.google.com/chromeos/bin/answer.py?answer=1061547'; 104 105 /** 106 * Location of the help page about connecting to Google Drive. 107 */ 108 var GOOGLE_DRIVE_ERROR_HELP_URL = 109 'https://support.google.com/chromeos/?p=filemanager_driveerror'; 110 111 /** 112 * Initializes the banner to promote DRIVE. 113 * This method must be called before any of showing banner functions, and 114 * also before registering them as callbacks. 115 * @private 116 */ 117 FileListBannerController.prototype.initializeWelcomeBanner_ = function() { 118 this.useNewWelcomeBanner_ = (!util.boardIs('x86-mario') && 119 !util.boardIs('x86-zgb') && 120 !util.boardIs('x86-alex')); 121 }; 122 123 /** 124 * @param {number} value How many times the Drive Welcome header banner 125 * has shown. 126 * @private 127 */ 128 FileListBannerController.prototype.setWelcomeHeaderCounter_ = function(value) { 129 var values = {}; 130 values[WELCOME_HEADER_COUNTER_KEY] = value; 131 chrome.storage.local.set(values); 132 }; 133 134 /** 135 * @param {number} value How many times the low space warning has dismissed. 136 * @private 137 */ 138 FileListBannerController.prototype.setWarningDismissedCounter_ = 139 function(value) { 140 var values = {}; 141 values[WARNING_DISMISSED_KEY] = value; 142 chrome.storage.local.set(values); 143 }; 144 145 /** 146 * chrome.storage.onChanged event handler. 147 * @param {Object.<string, Object>} changes Changes values. 148 * @param {string} areaName "local" or "sync". 149 * @private 150 */ 151 FileListBannerController.prototype.onStorageChange_ = function(changes, 152 areaName) { 153 if (areaName == 'local' && WELCOME_HEADER_COUNTER_KEY in changes) { 154 this.welcomeHeaderCounter_ = changes[WELCOME_HEADER_COUNTER_KEY].newValue; 155 } 156 if (areaName == 'local' && WARNING_DISMISSED_KEY in changes) { 157 this.warningDismissedCounter_ = changes[WARNING_DISMISSED_KEY].newValue; 158 } 159 }; 160 161 /** 162 * Invoked when the drive connection status is change in the volume manager. 163 * @private 164 */ 165 FileListBannerController.prototype.onDriveConnectionChanged_ = function() { 166 this.maybeShowAuthFailBanner_(); 167 }; 168 169 /** 170 * @param {string} type 'none'|'page'|'header'. 171 * @param {string} messageId Reource ID of the message. 172 * @private 173 */ 174 FileListBannerController.prototype.prepareAndShowWelcomeBanner_ = 175 function(type, messageId) { 176 this.showWelcomeBanner_(type); 177 178 var container = this.document_.querySelector('.drive-welcome.' + type); 179 if (container.firstElementChild) 180 return; // Do not re-create. 181 182 if (!this.document_.querySelector('link[drive-welcome-style]')) { 183 var style = this.document_.createElement('link'); 184 style.rel = 'stylesheet'; 185 style.href = 'css/drive_welcome.css'; 186 style.setAttribute('drive-welcome-style', ''); 187 this.document_.head.appendChild(style); 188 } 189 190 var wrapper = util.createChild(container, 'drive-welcome-wrapper'); 191 util.createChild(wrapper, 'drive-welcome-icon'); 192 193 var close = util.createChild(wrapper, 'cr-dialog-close'); 194 close.addEventListener('click', this.closeWelcomeBanner_.bind(this)); 195 196 var message = util.createChild(wrapper, 'drive-welcome-message'); 197 198 var title = util.createChild(message, 'drive-welcome-title'); 199 200 var text = util.createChild(message, 'drive-welcome-text'); 201 text.innerHTML = str(messageId); 202 203 var links = util.createChild(message, 'drive-welcome-links'); 204 205 var more; 206 if (this.useNewWelcomeBanner_) { 207 var welcomeTitle = str('DRIVE_WELCOME_TITLE_ALTERNATIVE'); 208 if (util.boardIs('link')) 209 welcomeTitle = str('DRIVE_WELCOME_TITLE_ALTERNATIVE_1TB'); 210 title.textContent = welcomeTitle; 211 more = util.createChild(links, 212 'drive-welcome-button drive-welcome-start', 'a'); 213 more.textContent = str('DRIVE_WELCOME_CHECK_ELIGIBILITY'); 214 more.href = GOOGLE_DRIVE_REDEEM; 215 } else { 216 title.textContent = str('DRIVE_WELCOME_TITLE'); 217 more = util.createChild(links, 'plain-link', 'a'); 218 more.textContent = str('DRIVE_LEARN_MORE'); 219 more.href = GOOGLE_DRIVE_FAQ_URL; 220 } 221 more.target = '_blank'; 222 223 var dismiss; 224 if (this.useNewWelcomeBanner_) 225 dismiss = util.createChild(links, 'drive-welcome-button'); 226 else 227 dismiss = util.createChild(links, 'plain-link'); 228 229 dismiss.classList.add('drive-welcome-dismiss'); 230 dismiss.textContent = str('DRIVE_WELCOME_DISMISS'); 231 dismiss.addEventListener('click', this.closeWelcomeBanner_.bind(this)); 232 233 this.previousDirWasOnDrive_ = false; 234 }; 235 236 /** 237 * Show or hide the "Low Google Drive space" warning. 238 * @param {boolean} show True if the box need to be shown. 239 * @param {Object} sizeStats Size statistics. Should be defined when showing the 240 * warning. 241 * @private 242 */ 243 FileListBannerController.prototype.showLowDriveSpaceWarning_ = 244 function(show, sizeStats) { 245 var box = this.document_.querySelector('#volume-space-warning'); 246 247 // Avoid showing two banners. 248 // TODO(kaznacheev): Unify the low space warning and the promo header. 249 if (show) 250 this.cleanupWelcomeBanner_(); 251 252 if (box.hidden == !show) 253 return; 254 255 if (this.warningDismissedCounter_) { 256 if (this.warningDismissedCounter_ == 257 sizeStats.totalSizeKB && // Quota had not changed 258 sizeStats.remainingSizeKB / sizeStats.totalSizeKB < 0.15) { 259 // Since the last dismissal decision the quota has not changed AND 260 // the user did not free up significant space. Obey the dismissal. 261 show = false; 262 } else { 263 // Forget the dismissal. Warning will be shown again. 264 this.setWarningDismissedCounter_(0); 265 } 266 } 267 268 box.textContent = ''; 269 if (show) { 270 var icon = this.document_.createElement('div'); 271 icon.className = 'drive-icon'; 272 box.appendChild(icon); 273 274 var text = this.document_.createElement('div'); 275 text.className = 'drive-text'; 276 text.textContent = strf('DRIVE_SPACE_AVAILABLE_LONG', 277 util.bytesToString(sizeStats.remainingSizeKB * 1024)); 278 box.appendChild(text); 279 280 var link = this.document_.createElement('a'); 281 link.className = 'plain-link'; 282 link.textContent = str('DRIVE_BUY_MORE_SPACE_LINK'); 283 link.href = GOOGLE_DRIVE_BUY_STORAGE; 284 link.target = '_blank'; 285 box.appendChild(link); 286 287 var close = this.document_.createElement('div'); 288 close.className = 'cr-dialog-close'; 289 box.appendChild(close); 290 close.addEventListener('click', function(total) { 291 window.localStorage[WARNING_DISMISSED_KEY] = total; 292 box.hidden = true; 293 this.requestRelayout_(100); 294 }.bind(this, sizeStats.totalSizeKB)); 295 } 296 297 if (box.hidden != !show) { 298 box.hidden = !show; 299 this.requestRelayout_(100); 300 } 301 }; 302 /** 303 * Closes the Drive Welcome banner. 304 * @private 305 */ 306 FileListBannerController.prototype.closeWelcomeBanner_ = function() { 307 this.cleanupWelcomeBanner_(); 308 // Stop showing the welcome banner. 309 this.setWelcomeHeaderCounter_(WELCOME_HEADER_COUNTER_LIMIT); 310 }; 311 312 /** 313 * Shows or hides the welcome banner for drive. 314 * @private 315 */ 316 FileListBannerController.prototype.checkSpaceAndMaybeShowWelcomeBanner_ = 317 function() { 318 if (!this.isOnDrive()) { 319 // We are not on the drive file system. Do not show (close) the welcome 320 // banner. 321 this.cleanupWelcomeBanner_(); 322 this.previousDirWasOnDrive_ = false; 323 return; 324 } 325 326 if (this.welcomeHeaderCounter_ >= WELCOME_HEADER_COUNTER_LIMIT || 327 !this.directoryModel_.isDriveMounted()) { 328 // The banner is already shown enough times or the drive FS is not mounted. 329 // So, do nothing here. 330 return; 331 } 332 333 if (!this.showOffers_) { 334 // Because it is not necessary to show the offer, set 335 // |useNewWelcomeBanner_| false here. Note that it probably should be able 336 // to do this in the constructor, but there remains non-trivial path, 337 // which may be causes |useNewWelcomeBanner_| == true's behavior even 338 // if |showOffers_| is false. 339 // TODO(hidehiko): Make sure if it is expected or not, and simplify 340 // |showOffers_| if possible. 341 this.useNewWelcomeBanner_ = false; 342 } 343 344 var self = this; 345 if (self.useNewWelcomeBanner_) { 346 // getSizeStats for Drive file system accesses to the server, so we should 347 // minimize the invocation. 348 chrome.fileBrowserPrivate.getSizeStats( 349 util.makeFilesystemUrl(self.directoryModel_.getCurrentRootPath()), 350 function(result) { 351 var offerSpaceKb = util.boardIs('link') ? 352 1024 * 1024 * 1024 : // 1TB. 353 100 * 1024 * 1024; // 100GB. 354 if (result && result.totalSizeKB >= offerSpaceKb) { 355 self.useNewWelcomeBanner_ = false; 356 } 357 self.maybeShowWelcomeBanner_(); 358 }); 359 } else { 360 self.maybeShowWelcomeBanner_(); 361 } 362 }; 363 364 /** 365 * Decides which banner should be shown, and show it. This method is designed 366 * to be called only from checkSpaceAndMaybeShowWelcomeBanner_. 367 * @private 368 */ 369 FileListBannerController.prototype.maybeShowWelcomeBanner_ = function() { 370 if (this.directoryModel_.getFileList().length == 0 && 371 this.welcomeHeaderCounter_ == 0) { 372 // Only show the full page banner if the header banner was never shown. 373 // Do not increment the counter. 374 // The timeout below is required because sometimes another 375 // 'rescan-completed' event arrives shortly with non-empty file list. 376 setTimeout(function() { 377 if (this.isOnDrive() && this.welcomeHeaderCounter_ == 0) { 378 this.prepareAndShowWelcomeBanner_('page', 'DRIVE_WELCOME_TEXT_LONG'); 379 } 380 }.bind(this), 2000); 381 } else { 382 // We do not want to increment the counter when the user navigates 383 // between different directories on Drive, but we increment the counter 384 // once anyway to prevent the full page banner from showing. 385 if (!this.previousDirWasOnDrive_ || this.welcomeHeaderCounter_ == 0) { 386 this.setWelcomeHeaderCounter_(this.welcomeHeaderCounter_ + 1); 387 this.prepareAndShowWelcomeBanner_('header', 'DRIVE_WELCOME_TEXT_SHORT'); 388 } 389 } 390 this.previousDirWasOnDrive_ = true; 391 }; 392 393 /** 394 * @return {boolean} True if current directory is on Drive. 395 */ 396 FileListBannerController.prototype.isOnDrive = function() { 397 return this.directoryModel_.getCurrentRootType() === RootType.DRIVE; 398 }; 399 400 /** 401 * Shows the Drive Welcome banner. 402 * @param {string} type 'page'|'head'|'none'. 403 * @private 404 */ 405 FileListBannerController.prototype.showWelcomeBanner_ = function(type) { 406 var container = this.document_.querySelector('.dialog-container'); 407 if (container.getAttribute('drive-welcome') != type) { 408 container.setAttribute('drive-welcome', type); 409 this.requestRelayout_(200); // Resize only after the animation is done. 410 } 411 }; 412 413 /** 414 * Update the UI when the current directory changes. 415 * 416 * @param {cr.Event} event The directory-changed event. 417 * @private 418 */ 419 FileListBannerController.prototype.onDirectoryChanged_ = function(event) { 420 var root = PathUtil.getTopDirectory(event.newDirEntry.fullPath); 421 // Show (or hide) the low space warning. 422 this.maybeShowLowSpaceWarning_(root); 423 424 // Add or remove listener to show low space warning, if necessary. 425 var isLowSpaceWarningTarget = this.isLowSpaceWarningTarget_(root); 426 var previousRoot = PathUtil.getTopDirectory(event.previousDirEntry.fullPath); 427 if (isLowSpaceWarningTarget !== this.isLowSpaceWarningTarget_(previousRoot)) { 428 if (isLowSpaceWarningTarget) { 429 chrome.fileBrowserPrivate.onDirectoryChanged.addListener( 430 this.privateOnDirectoryChangedBound_); 431 } else { 432 chrome.fileBrowserPrivate.onDirectoryChanged.removeListener( 433 this.privateOnDirectoryChangedBound_); 434 } 435 } 436 437 if (!this.isOnDrive()) { 438 this.cleanupWelcomeBanner_(); 439 this.authFailedBanner_.hidden = true; 440 } 441 442 this.updateDriveUnmountedPanel_(); 443 if (this.isOnDrive()) { 444 this.unmountedPanel_.classList.remove('retry-enabled'); 445 this.maybeShowAuthFailBanner_(); 446 } 447 }; 448 449 /** 450 * @param {string} root Root directory to be checked. 451 * @return {boolean} true if the file system specified by |root| is a target 452 * to show low space warning. Otherwise false. 453 * @private 454 */ 455 FileListBannerController.prototype.isLowSpaceWarningTarget_ = function(root) { 456 return (root == RootDirectory.DOWNLOADS || root == RootDirectory.DRIVE); 457 }; 458 459 /** 460 * Callback which is invoked when the file system has been changed. 461 * @param {Object} event chrome.fileBrowserPrivate.onDirectoryChanged event. 462 * @private 463 */ 464 FileListBannerController.prototype.privateOnDirectoryChanged_ = function( 465 event) { 466 var currentRoot = PathUtil.getTopDirectory( 467 this.directoryModel_.getCurrentDirPath()); 468 var eventRoot = PathUtil.getTopDirectory( 469 util.extractFilePath(event.directoryUrl)); 470 if (currentRoot == eventRoot) { 471 // The file system we are currently on is changed. 472 // So, check the free space. 473 this.maybeShowLowSpaceWarning_(eventRoot); 474 } 475 }; 476 477 /** 478 * Shows or hides the low space warning. 479 * @param {string} root Root directory of the file system, which we are 480 * interested in. 481 * @private 482 */ 483 FileListBannerController.prototype.maybeShowLowSpaceWarning_ = function(root) { 484 // TODO(kaznacheev): Unify the two low space warning. 485 var threshold = 0; 486 if (root === RootDirectory.DOWNLOADS) { 487 this.showLowDriveSpaceWarning_(false); 488 threshold = 0.2; 489 } else if (root === RootDirectory.DRIVE) { 490 this.showLowDownloadsSpaceWarning_(false); 491 threshold = 0.1; 492 } else { 493 // If the current file system is neither the DOWNLOAD nor the DRIVE, 494 // just hide the warning. 495 this.showLowDownloadsSpaceWarning_(false); 496 this.showLowDriveSpaceWarning_(false); 497 return; 498 } 499 500 var self = this; 501 chrome.fileBrowserPrivate.getSizeStats( 502 util.makeFilesystemUrl(root), 503 function(sizeStats) { 504 var currentRoot = PathUtil.getTopDirectory( 505 self.directoryModel_.getCurrentDirPath()); 506 if (root != currentRoot) { 507 // This happens when the current directory is moved during requesting 508 // the file system size. Just ignore it. 509 return; 510 } 511 512 // sizeStats is undefined, if some error occurs. 513 var remainingRatio = (sizeStats && sizeStats.totalSizeKB > 0) ? 514 (sizeStats.remainingSizeKB / sizeStats.totalSizeKB) : 1; 515 var isLowDiskSpace = remainingRatio < threshold; 516 if (root == RootDirectory.DOWNLOADS) 517 self.showLowDownloadsSpaceWarning_(isLowDiskSpace); 518 else 519 self.showLowDriveSpaceWarning_(isLowDiskSpace, sizeStats); 520 }); 521 }; 522 523 /** 524 * removes the Drive Welcome banner. 525 * @private 526 */ 527 FileListBannerController.prototype.cleanupWelcomeBanner_ = function() { 528 this.showWelcomeBanner_('none'); 529 }; 530 531 /** 532 * Notifies the file manager what layout must be recalculated. 533 * @param {number} delay In milliseconds. 534 * @private 535 */ 536 FileListBannerController.prototype.requestRelayout_ = function(delay) { 537 var self = this; 538 setTimeout(function() { 539 cr.dispatchSimpleEvent(self, 'relayout'); 540 }, delay); 541 }; 542 543 /** 544 * Show or hide the "Low disk space" warning. 545 * @param {boolean} show True if the box need to be shown. 546 * @private 547 */ 548 FileListBannerController.prototype.showLowDownloadsSpaceWarning_ = 549 function(show) { 550 var box = this.document_.querySelector('.downloads-warning'); 551 552 if (box.hidden == !show) return; 553 554 if (show) { 555 var html = util.htmlUnescape(str('DOWNLOADS_DIRECTORY_WARNING')); 556 box.innerHTML = html; 557 var link = box.querySelector('a'); 558 link.href = DOWNLOADS_FAQ_URL; 559 link.target = '_blank'; 560 } else { 561 box.innerHTML = ''; 562 } 563 564 box.hidden = !show; 565 this.requestRelayout_(100); 566 }; 567 568 /** 569 * Creates contents for the DRIVE unmounted panel. 570 * @private 571 */ 572 FileListBannerController.prototype.ensureDriveUnmountedPanelInitialized_ = 573 function() { 574 var panel = this.unmountedPanel_; 575 if (panel.firstElementChild) 576 return; 577 578 var create = function(parent, tag, className, opt_textContent) { 579 var div = panel.ownerDocument.createElement(tag); 580 div.className = className; 581 div.textContent = opt_textContent || ''; 582 parent.appendChild(div); 583 return div; 584 }; 585 586 var loading = create(panel, 'div', 'loading', str('DRIVE_LOADING')); 587 var spinnerBox = create(loading, 'div', 'spinner-box'); 588 create(spinnerBox, 'div', 'spinner'); 589 create(panel, 'div', 'error', str('DRIVE_CANNOT_REACH')); 590 591 var retryButton = create(panel, 'button', 'retry', str('DRIVE_RETRY')); 592 retryButton.hidden = true; 593 var vm = this.volumeManager_; 594 retryButton.onclick = function() { 595 vm.mountDrive(function() {}, function() {}); 596 }; 597 598 var learnMore = create(panel, 'a', 'learn-more plain-link', 599 str('DRIVE_LEARN_MORE')); 600 learnMore.href = GOOGLE_DRIVE_ERROR_HELP_URL; 601 learnMore.target = '_blank'; 602 }; 603 604 /** 605 * Shows the panel when current directory is DRIVE and it's unmounted. 606 * Hides it otherwise. The pannel shows spinner if DRIVE is mounting or 607 * an error message if it failed. 608 * @private 609 */ 610 FileListBannerController.prototype.updateDriveUnmountedPanel_ = function() { 611 var node = this.document_.body; 612 if (this.isOnDrive()) { 613 var status = this.volumeManager_.getDriveStatus(); 614 if (status == VolumeManager.DriveStatus.MOUNTING || 615 status == VolumeManager.DriveStatus.ERROR) { 616 this.ensureDriveUnmountedPanelInitialized_(); 617 } 618 if (status == VolumeManager.DriveStatus.MOUNTING && 619 this.welcomeHeaderCounter_ == 0) { 620 // Do not increment banner counter in order to not prevent the full 621 // page banner of being shown (otherwise it would never be shown). 622 this.showWelcomeBanner_('header', 'DRIVE_WELCOME_TEXT_SHORT'); 623 } 624 if (status == VolumeManager.DriveStatus.ERROR) 625 this.unmountedPanel_.classList.add('retry-enabled'); 626 else 627 this.unmountedPanel_.classList.remove('retry-enabled'); 628 node.setAttribute('drive', status); 629 } else { 630 node.removeAttribute('drive'); 631 } 632 }; 633 634 /** 635 * Updates the visibility of Drive Connection Warning banner, retrieving the 636 * current connection information. 637 * @private 638 */ 639 FileListBannerController.prototype.maybeShowAuthFailBanner_ = function() { 640 var connection = this.volumeManager_.getDriveConnectionState(); 641 var reasons = connection.reasons; 642 var showDriveNotReachedMessage = 643 this.isOnDrive() && 644 connection.type == VolumeManager.DriveConnectionType.OFFLINE && 645 // Show the banner only when authentication fails. Don't show it when the 646 // drive service is disabled. 647 reasons.indexOf(VolumeManager.DriveConnectionReason.NOT_READY) != -1 && 648 reasons.indexOf(VolumeManager.DriveConnectionReason.NO_SERVICE) == -1; 649 this.authFailedBanner_.hidden = !showDriveNotReachedMessage; 650 }; 651