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 */ 17function 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 */ 66FileListBannerController.prototype.__proto__ = cr.EventTarget.prototype; 67 68/** 69 * Key in localStorage to keep number of times the Drive Welcome 70 * banner has shown. 71 */ 72var 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. 77var WARNING_DISMISSED_KEY = 'driveSpaceWarningDismissed'; 78 79/** 80 * Maximum times Drive Welcome banner could have shown. 81 */ 82var 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 */ 90FileListBannerController.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 */ 101FileListBannerController.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 */ 111FileListBannerController.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 */ 124FileListBannerController.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 */ 138FileListBannerController.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 */ 147FileListBannerController.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 = '14'; // 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 */ 217FileListBannerController.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 */ 282FileListBannerController.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 */ 292FileListBannerController.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 VolumeManagerCommon.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 // scanning 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 */ 368FileListBannerController.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 */ 396FileListBannerController.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 === VolumeManagerCommon.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 */ 411FileListBannerController.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 */ 425FileListBannerController.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 */ 464FileListBannerController.prototype.isLowSpaceWarningTarget_ = 465 function(volumeInfo) { 466 return volumeInfo && 467 volumeInfo.profile.isCurrentProfile && 468 (volumeInfo.volumeType === VolumeManagerCommon.VolumeType.DOWNLOADS || 469 volumeInfo.volumeType === VolumeManagerCommon.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 */ 477FileListBannerController.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 */ 498FileListBannerController.prototype.maybeShowLowSpaceWarning_ = function( 499 volume) { 500 // TODO(kaznacheev): Unify the two low space warning. 501 var threshold = 0; 502 switch (volume.volumeType) { 503 case VolumeManagerCommon.VolumeType.DOWNLOADS: 504 this.showLowDriveSpaceWarning_(false); 505 threshold = 0.2; 506 break; 507 case VolumeManagerCommon.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.fileSystem) 521 return; 522 523 chrome.fileBrowserPrivate.getSizeStats( 524 volume.volumeId, 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 === VolumeManagerCommon.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 */ 550FileListBannerController.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 */ 559FileListBannerController.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 */ 571FileListBannerController.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 */ 596FileListBannerController.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 */ 626FileListBannerController.prototype.onVolumeInfoListSplice_ = function(event) { 627 var isDriveVolume = function(volumeInfo) { 628 return volumeInfo.volumeType === VolumeManagerCommon.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 */ 640FileListBannerController.prototype.updateDriveUnmountedPanel_ = function() { 641 var node = this.document_.body; 642 if (this.isOnCurrentProfileDrive()) { 643 var driveVolume = this.volumeManager_.getCurrentProfileVolumeInfo( 644 VolumeManagerCommon.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 */ 662FileListBannerController.prototype.maybeShowAuthFailBanner_ = function() { 663 var connection = this.volumeManager_.getDriveConnectionState(); 664 var showDriveNotReachedMessage = 665 this.isOnCurrentProfileDrive() && 666 connection.type == VolumeManagerCommon.DriveConnectionType.OFFLINE && 667 connection.reason == VolumeManagerCommon.DriveConnectionReason.NOT_READY; 668 this.authFailedBanner_.hidden = !showDriveNotReachedMessage; 669}; 670