// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. /** * @fileoverview Offline message screen implementation. */ cr.define('login', function() { // Screens that should have offline message overlay. const MANAGED_SCREENS = ['gaia-signin']; // Network state constants. const NET_STATE = { OFFLINE: 0, ONLINE: 1, PORTAL: 2 }; // Error reasons which are passed to updateState_() method. const ERROR_REASONS = { PROXY_AUTH_CANCELLED: 'frame error:111', PROXY_CONNECTION_FAILED: 'frame error:130' }; // Frame loading errors. const NET_ERROR = { ABORTED_BY_USER: 3 }; // Link which starts guest session for captive portal fixing. const FIX_CAPTIVE_PORTAL_ID = 'captive-portal-fix-link'; // Id of the element which holds current network name. const CURRENT_NETWORK_NAME_ID = 'captive-portal-network-name'; // Link which triggers frame reload. const RELOAD_PAGE_ID = 'proxy-error-retry-link'; /** * Creates a new offline message screen div. * @constructor * @extends {HTMLDivElement} */ var ErrorMessageScreen = cr.ui.define('div'); /** * Registers with Oobe. */ ErrorMessageScreen.register = function() { var screen = $('error-message'); ErrorMessageScreen.decorate(screen); // Note that ErrorMessageScreen is not registered with Oobe because // it is shown on top of sign-in screen instead of as an independent screen. }; ErrorMessageScreen.prototype = { __proto__: HTMLDivElement.prototype, /** @inheritDoc */ decorate: function() { chrome.send('loginAddNetworkStateObserver', ['login.ErrorMessageScreen.updateState']); cr.ui.DropDown.decorate($('offline-networks-list')); this.updateLocalizedContent_(); }, /** * Updates localized content of the screen that is not updated via template. */ updateLocalizedContent_: function() { $('captive-portal-message-text').innerHTML = localStrings.getStringF( 'captivePortalMessage', '', '', ''); $(FIX_CAPTIVE_PORTAL_ID).onclick = function() { chrome.send('fixCaptivePortal'); }; $('proxy-message-text').innerHTML = localStrings.getStringF( 'proxyMessageText', '', ''); $(RELOAD_PAGE_ID).onclick = function() { var currentScreen = Oobe.getInstance().currentScreen; // Schedules a immediate retry. currentScreen.doReload(); }; $('error-guest-signin').innerHTML = localStrings.getStringF( 'guestSignin', '', ''); $('error-guest-signin-link').onclick = function() { chrome.send('launchIncognito'); }; $('error-offline-login').innerHTML = localStrings.getStringF( 'offlineLogin', '', ''); $('error-offline-login-link').onclick = function() { chrome.send('offlineLogin', []); }; }, onBeforeShow: function(lastNetworkType) { var currentScreen = Oobe.getInstance().currentScreen; cr.ui.DropDown.show('offline-networks-list', false, lastNetworkType); $('error-guest-signin').hidden = $('guestSignin').hidden || !$('add-user-header-bar-item').hidden; $('error-offline-login').hidden = !currentScreen.isOfflineAllowed; }, onBeforeHide: function() { cr.ui.DropDown.hide('offline-networks-list'); }, update: function() { chrome.send('loginRequestNetworkState', ['login.ErrorMessageScreen.updateState', 'update']); }, /** * Shows or hides offline message based on network on/offline state. * @param {Integer} state Current state of the network (see NET_STATE). * @param {string} network Name of the current network. * @param {string} reason Reason the callback was called. * @param {int} lastNetworkType Last active network type. */ updateState_: function(state, network, reason, lastNetworkType) { var currentScreen = Oobe.getInstance().currentScreen; var offlineMessage = this; var isOnline = (state == NET_STATE.ONLINE); var isUnderCaptivePortal = (state == NET_STATE.PORTAL); var isProxyError = reason == ERROR_REASONS.PROXY_AUTH_CANCELLED || reason == ERROR_REASONS.PROXY_CONNECTION_FAILED; var shouldOverlay = MANAGED_SCREENS.indexOf(currentScreen.id) != -1 && !currentScreen.isLocal; if (reason == 'proxy changed' && shouldOverlay && !offlineMessage.classList.contains('hidden') && offlineMessage.classList.contains('show-captive-portal')) { // Schedules a immediate retry. currentScreen.doReload(); console.log('Retry page load since proxy settings has been changed'); } if (!isOnline && shouldOverlay) { console.log('Show offline message: state=' + state + ', network=' + network + ', isUnderCaptivePortal=' + isUnderCaptivePortal); offlineMessage.onBeforeShow(lastNetworkType); if (isUnderCaptivePortal) { if (isProxyError) { offlineMessage.classList.remove('show-offline-message'); offlineMessage.classList.remove('show-captive-portal'); offlineMessage.classList.add('show-proxy-error'); } else { $(CURRENT_NETWORK_NAME_ID).textContent = network; offlineMessage.classList.remove('show-offline-message'); offlineMessage.classList.remove('show-proxy-error'); offlineMessage.classList.add('show-captive-portal'); } } else { offlineMessage.classList.remove('show-captive-portal'); offlineMessage.classList.remove('show-proxy-error'); offlineMessage.classList.add('show-offline-message'); } offlineMessage.classList.remove('hidden'); offlineMessage.classList.remove('faded'); if (!currentScreen.classList.contains('faded')) { currentScreen.classList.add('faded'); currentScreen.addEventListener('webkitTransitionEnd', function f(e) { currentScreen.removeEventListener('webkitTransitionEnd', f); if (currentScreen.classList.contains('faded')) currentScreen.classList.add('hidden'); }); } } else { if (!offlineMessage.classList.contains('faded')) { console.log('Hide offline message.'); offlineMessage.onBeforeHide(); offlineMessage.classList.add('faded'); offlineMessage.addEventListener('webkitTransitionEnd', function f(e) { offlineMessage.removeEventListener('webkitTransitionEnd', f); if (offlineMessage.classList.contains('faded')) offlineMessage.classList.add('hidden'); }); currentScreen.classList.remove('hidden'); currentScreen.classList.remove('faded'); } } }, }; /** * Network state changed callback. * @param {Integer} state Current state of the network (see NET_STATE). * @param {string} network Name of the current network. * @param {string} reason Reason the callback was called. * @param {int} lastNetworkType Last active network type. */ ErrorMessageScreen.updateState = function( state, network, reason, lastNetworkType) { $('error-message').updateState_(state, network, reason, lastNetworkType); }; /** * Handler for iframe's error notification coming from the outside. * For more info see C++ class 'SnifferObserver' which calls this method. * @param {number} error Error code. */ ErrorMessageScreen.onFrameError = function(error) { console.log('Gaia frame error = ' + error); if (error == NET_ERROR.ABORTED_BY_USER) { // Gaia frame was reloaded. Nothing to do here. return; } $('gaia-signin').onFrameError(error); // Offline and simple captive portal cases are handled by the // NetworkStateInformer, so only the case when browser is online is // valuable. if (window.navigator.onLine) { // Check current network state if currentScreen is a managed one. var currentScreen = Oobe.getInstance().currentScreen; if (MANAGED_SCREENS.indexOf(currentScreen.id) != -1) { chrome.send('loginRequestNetworkState', ['login.ErrorMessageScreen.maybeRetry', 'frame error:' + error]); } } }; /** * Network state callback where we decide whether to schdule a retry. */ ErrorMessageScreen.maybeRetry = function(state, network, reason, lastNetworkType) { console.log('ErrorMessageScreen.maybeRetry, state=' + state + ', network=' + network); // No retry if we are not online. if (state != NET_STATE.ONLINE) return; var currentScreen = Oobe.getInstance().currentScreen; if (MANAGED_SCREENS.indexOf(currentScreen.id) != -1) { this.updateState(NET_STATE.PORTAL, network, reason, lastNetworkType); // Schedules a retry. currentScreen.scheduleRetry(); } }; /** * Updates screen localized content like links since they're not updated * via template. */ ErrorMessageScreen.updateLocalizedContent = function() { $('error-message').updateLocalizedContent_(); }; return { ErrorMessageScreen: ErrorMessageScreen }; });