1 // Copyright 2013 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.
5 cr.define('mobile', function() {
7 // TODO(tbarzic): Share code with mobile_setup.js.
8 var EXTENSION_BASE_URL =
9 'chrome-extension://iadeocfgjdjdmpenejdbfeaocpbikmab/';
10 var REDIRECT_POST_PAGE_URL = EXTENSION_BASE_URL + 'redirect.html?autoPost=1';
11 var PORTAL_OFFLINE_PAGE_URL = EXTENSION_BASE_URL + 'portal_offline.html';
12 var INVALID_DEVICE_INFO_PAGE_URL =
13 EXTENSION_BASE_URL + 'invalid_device_info.html';
21 var CarrierPageType = {
24 INVALID_DEVICE_INFO: 2
27 var localStrings = new LocalStrings();
29 function PortalImpl() {
30 // Mobile device information.
31 this.deviceInfo_ = null;
32 this.spinnerInt_ = -1;
33 this.networkState_ = NetworkState.UNKNOWN;
34 this.portalFrameSet_ = false;
35 this.carrierPageType_ = CarrierPageType.NOT_SET;
38 cr.addSingletonGetter(PortalImpl);
40 PortalImpl.prototype = {
41 initialize: function() {
42 // Get network device info for which portal should be opened.
43 // For LTE networks, this will also start observing network connection
44 // state and raise |updatePortalReachability| messages when the portal
45 // reachability changes.
46 chrome.send('getDeviceInfo');
49 updateDeviceInfo: function(deviceInfo) {
50 this.deviceInfo_ = deviceInfo;
54 updateNetworkState: function(networkState) {
55 if (this.networkState_ == networkState)
57 this.networkState_ = networkState;
59 // If the device info is not yet set, the state will be updated on the
60 // device info update.
65 updateState_: function() {
66 if (!this.deviceInfo_ || this.networkState_ == NetworkState.UNKNOWN)
69 if (!this.isDeviceInfoValid_()) {
70 // If the device info is not valid, hide portalFrame and show system
71 // status displaying 'invalid device info' page.
72 this.setCarrierPage_(CarrierPageType.INVALID_DEVICE_INFO);
73 $('portalFrame').hidden = true;
74 $('systemStatus').hidden = false;
75 } else if (this.networkState_ != NetworkState.PORTAL_REACHABLE) {
76 // If the portal is not reachable, hide portalFrame and show system
77 // status displaying 'offline portal' page.
78 this.setCarrierPage_(CarrierPageType.PORTAL_OFFLINE);
79 $('portalFrame').hidden = true;
80 $('systemStatus').hidden = false;
82 // If the portal is reachable and device info is valid, set and show
83 // portalFrame; and hide system status displaying 'offline portal' page.
84 this.setPortalFrameIfNeeded_(this.deviceInfo_);
85 $('portalFrame').hidden = false;
86 $('systemStatus').hidden = true;
91 setCarrierPage_: function(type) {
92 // The page is already set, nothing to do.
93 if (type == this.carrierPageType_)
97 case CarrierPageType.PORTAL_OFFLINE:
98 $('carrierPage').contentWindow.location.href =
99 PORTAL_OFFLINE_PAGE_URL;
100 $('statusHeader').textContent =
101 localStrings.getString('portal_unreachable_header');
102 this.startSpinner_();
104 case CarrierPageType.INVALID_DEVICE_INFO:
105 $('carrierPage').contentWindow.location.href =
106 INVALID_DEVICE_INFO_PAGE_URL;
107 $('statusHeader').textContent =
108 localStrings.getString('invalid_device_info_header');
111 case CarrierPageType.NOT_SET:
112 $('carrierPage').contentWindow.location.href = 'about:blank';
113 $('statusHeader').textContent = '';
120 this.carrierPageType_ = type;
123 setPortalFrameIfNeeded_: function(deviceInfo) {
124 // The portal should be set only once.
125 if (this.portalFrameSet_)
129 if (deviceInfo.post_data && deviceInfo.post_data.length)
130 postData = '&post_data=' + encodeURIComponent(deviceInfo.post_data);
132 $('portalFrame').contentWindow.location.href = REDIRECT_POST_PAGE_URL +
133 postData + '&formUrl=' + encodeURIComponent(deviceInfo.payment_url);
135 this.portalFrameSet_ = true;
138 isDeviceInfoValid_: function() {
139 // Device info is valid if it has mdn which doesn't contain only '0's.
140 return this.deviceInfo_ && this.deviceInfo_.MDN &&
141 this.deviceInfo_.MDN.match('[^0]');
144 startSpinner_: function() {
146 this.spinnerInt_ = setInterval(this.drawProgress_.bind(this), 100);
149 stopSpinner_: function() {
150 if (this.spinnerInt_ != -1) {
151 clearInterval(this.spinnerInt_);
152 this.spinnerInt_ = -1;
154 // Clear the spinner canvas.
155 var ctx = canvas.getContext('2d');
156 ctx.clearRect(0, 0, canvas.width, canvas.height);
159 drawProgress_: function() {
160 var ctx = canvas.getContext('2d');
161 ctx.clearRect(0, 0, canvas.width, canvas.height);
163 var segmentCount = Math.min(12, canvas.width / 1.6); // Number of segments
164 var rotation = 0.75; // Counterclockwise rotation
166 // Rotate canvas over time
167 ctx.translate(canvas.width / 2, canvas.height / 2);
168 ctx.rotate(Math.PI * 2 / (segmentCount + rotation));
169 ctx.translate(-canvas.width / 2, -canvas.height / 2);
171 var gap = canvas.width / 24; // Gap between segments
172 var oRadius = canvas.width / 2; // Outer radius
173 var iRadius = oRadius * 0.618; // Inner radius
174 var oCircumference = Math.PI * 2 * oRadius; // Outer circumference
175 var iCircumference = Math.PI * 2 * iRadius; // Inner circumference
176 var oGap = gap / oCircumference; // Gap size as fraction of outer ring
177 var iGap = gap / iCircumference; // Gap size as fraction of inner ring
178 var oArc = Math.PI * 2 * (1 / segmentCount - oGap); // Angle of outer arcs
179 var iArc = Math.PI * 2 * (1 / segmentCount - iGap); // Angle of inner arcs
181 for (i = 0; i < segmentCount; i++) { // Draw each segment
182 var opacity = Math.pow(1.0 - i / segmentCount, 3.0);
183 opacity = (0.15 + opacity * 0.8); // Vary from 0.15 to 0.95
184 var angle = - Math.PI * 2 * i / segmentCount;
187 ctx.arc(canvas.width / 2, canvas.height / 2, oRadius,
188 angle - oArc / 2, angle + oArc / 2, false);
189 ctx.arc(canvas.width / 2, canvas.height / 2, iRadius,
190 angle + iArc / 2, angle - iArc / 2, true);
192 ctx.fillStyle = 'rgba(240, 30, 29, ' + opacity + ')';
198 function MobileSetupPortal() {}
200 MobileSetupPortal.loadPage = function() {
201 PortalImpl.getInstance().initialize();
204 MobileSetupPortal.onGotDeviceInfo = function(deviceInfo) {
205 PortalImpl.getInstance().updateDeviceInfo(deviceInfo);
208 MobileSetupPortal.onConnectivityChanged = function(portalReachable) {
209 PortalImpl.getInstance().updateNetworkState(
210 portalReachable ? NetworkState.PORTAL_REACHABLE :
211 NetworkState.PORTAL_UNREACHABLE);
216 MobileSetupPortal: MobileSetupPortal
220 document.addEventListener('DOMContentLoaded',
221 mobile.MobileSetupPortal.loadPage);