1 // Copyright (c) 2010 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 6 cr.define('mobile', function() { 7 8 function MobileSetup() { 9 } 10 11 cr.addSingletonGetter(MobileSetup); 12 13 MobileSetup.PLAN_ACTIVATION_PAGE_LOADING = -1; 14 MobileSetup.PLAN_ACTIVATION_START = 0; 15 MobileSetup.PLAN_ACTIVATION_TRYING_OTASP = 1; 16 MobileSetup.PLAN_ACTIVATION_RECONNECTING_OTASP_TRY = 2; 17 MobileSetup.PLAN_ACTIVATION_INITIATING_ACTIVATION = 3; 18 MobileSetup.PLAN_ACTIVATION_RECONNECTING = 4; 19 MobileSetup.PLAN_ACTIVATION_SHOWING_PAYMENT = 5; 20 MobileSetup.PLAN_ACTIVATION_DELAY_OTASP = 6; 21 MobileSetup.PLAN_ACTIVATION_START_OTASP = 7; 22 MobileSetup.PLAN_ACTIVATION_OTASP = 8; 23 MobileSetup.PLAN_ACTIVATION_RECONNECTING_OTASP = 9; 24 MobileSetup.PLAN_ACTIVATION_DONE = 10; 25 MobileSetup.PLAN_ACTIVATION_ERROR = 0xFF; 26 27 MobileSetup.ACTIVATION_PAGE_URL = 28 'chrome-extension://iadeocfgjdjdmpenejdbfeaocpbikmab/activation.html'; 29 30 MobileSetup.localStrings_ = new LocalStrings(); 31 32 MobileSetup.prototype = { 33 // Mobile device information. 34 deviceInfo_: null, 35 frameName_ : '', 36 initialized_ : false, 37 faked_transaction_ : false, 38 payment_shown_ : false, 39 // UI states. 40 state_ : -1, 41 STATE_UNKNOWN_: "unknown", 42 STATE_CONNECTING_: "connecting", 43 STATE_ERROR_: "error", 44 STATE_PAYMENT_: "payment", 45 STATE_ACTIVATING_: "activating", 46 STATE_CONNECTED_: "connected", 47 48 initialize: function(frame_name, carrierPage) { 49 if (this.initialized_) { 50 console.log('calling initialize() again?'); 51 return; 52 } 53 this.initialized_ = true; 54 self = this; 55 this.frameName_ = frame_name; 56 window.addEventListener('message', function(e) { 57 self.onMessageReceived_(e); 58 }); 59 $('closeButton').addEventListener('click', function(e) { 60 $('finalStatus').classList.add('hidden'); 61 }); 62 $(frame_name).addEventListener('load', function(e) { 63 // Flip the visibility of the payment page only after the frame is 64 // fully loaded. 65 if (self.state_ == MobileSetup.PLAN_ACTIVATION_SHOWING_PAYMENT) { 66 $('statusHeader').textContent = ''; 67 $('auxHeader').textContent = ''; 68 $('finalStatus').classList.add('hidden'); 69 $('systemStatus').classList.add('hidden'); 70 $('canvas').classList.add('hidden'); 71 $('carrierPage').classList.add('hidden'); 72 $('paymentForm').classList.remove('hidden'); 73 } 74 }); 75 76 this.changeState_({state: MobileSetup.PLAN_ACTIVATION_PAGE_LOADING}); 77 setInterval(mobile.MobileSetup.drawProgress, 100); 78 // Kick off activation process. 79 chrome.send('startActivation', []); 80 }, 81 82 loadPaymentFrame_: function(deviceInfo) { 83 if (deviceInfo) { 84 this.deviceInfo_ = deviceInfo; 85 86 $(this.frameName_).contentWindow.location.href = 87 this.deviceInfo_.payment_url; 88 } 89 }, 90 91 onMessageReceived_: function(e) { 92 if (e.origin != 93 this.deviceInfo_.payment_url.substring(0, e.origin.length)) 94 return; 95 96 if (e.data.type == 'requestDeviceInfoMsg') { 97 this.sendDeviceInfo_(); 98 } else if (e.data.type == 'reportTransactionStatusMsg') { 99 console.log('calling setTransactionStatus from onMessageReceived_'); 100 $('paymentForm').classList.add('hidden'); 101 chrome.send('setTransactionStatus', [e.data.status]); 102 } 103 }, 104 105 changeState_: function(deviceInfo) { 106 var new_state = deviceInfo.state; 107 if (this.state_ == new_state) 108 return; 109 var main = $('mainbody'); 110 // Map handler state to UX. 111 switch(new_state) { 112 case MobileSetup.PLAN_ACTIVATION_PAGE_LOADING: 113 case MobileSetup.PLAN_ACTIVATION_START: 114 case MobileSetup.PLAN_ACTIVATION_DELAY_OTASP: 115 case MobileSetup.PLAN_ACTIVATION_START_OTASP: 116 case MobileSetup.PLAN_ACTIVATION_RECONNECTING: 117 case MobileSetup.PLAN_ACTIVATION_RECONNECTING_OTASP_TRY: 118 case MobileSetup.PLAN_ACTIVATION_RECONNECTING_OTASP: 119 $('statusHeader').textContent = 120 MobileSetup.localStrings_.getString('connecting_header'); 121 $('auxHeader').textContent = 122 MobileSetup.localStrings_.getString('please_wait'); 123 $('paymentForm').classList.add('hidden'); 124 $('finalStatus').classList.add('hidden'); 125 $('systemStatus').classList.remove('hidden'); 126 $('canvas').classList.remove('hidden'); 127 $('carrierPage').classList.remove('hidden'); 128 break; 129 case MobileSetup.PLAN_ACTIVATION_TRYING_OTASP: 130 case MobileSetup.PLAN_ACTIVATION_INITIATING_ACTIVATION: 131 case MobileSetup.PLAN_ACTIVATION_OTASP: 132 $('statusHeader').textContent = 133 MobileSetup.localStrings_.getString('activating_header'); 134 $('auxHeader').textContent = 135 MobileSetup.localStrings_.getString('please_wait'); 136 $('paymentForm').classList.add('hidden'); 137 $('finalStatus').classList.add('hidden'); 138 $('systemStatus').classList.remove('hidden'); 139 $('canvas').classList.remove('hidden'); 140 $('carrierPage').classList.remove('hidden'); 141 break; 142 case MobileSetup.PLAN_ACTIVATION_SHOWING_PAYMENT: 143 $('statusHeader').textContent = 144 MobileSetup.localStrings_.getString('connecting_header'); 145 $('auxHeader').textContent = ''; 146 $('paymentForm').classList.add('hidden'); 147 $('finalStatus').classList.add('hidden'); 148 $('systemStatus').classList.remove('hidden'); 149 $('canvas').classList.remove('hidden'); 150 this.loadPaymentFrame_(deviceInfo); 151 this.payment_shown_ = true; 152 break; 153 case MobileSetup.PLAN_ACTIVATION_DONE: 154 $('statusHeader').textContent = ''; 155 $('auxHeader').textContent = ''; 156 $('finalHeader').textContent = 157 MobileSetup.localStrings_.getString('completed_header'); 158 $('finalMessage').textContent = 159 MobileSetup.localStrings_.getString('completed_text'); 160 $('systemStatus').classList.add('hidden'); 161 $('canvas').classList.add('hidden'); 162 $('carrierPage').classList.add('hidden'); 163 $('paymentForm').classList.remove('hidden'); 164 $('closeButton').classList.remove('hidden'); 165 $('finalStatus').classList.remove('hidden'); 166 if (this.payment_shown_) 167 $('closeButton').classList.remove('hidden'); 168 else 169 $('closeButton').classList.add('hidden'); 170 break; 171 case MobileSetup.PLAN_ACTIVATION_ERROR: 172 $('statusHeader').textContent = ''; 173 $('auxHeader').textContent = ''; 174 $('finalHeader').textContent = 175 MobileSetup.localStrings_.getString('error_header'); 176 $('finalMessage').textContent = deviceInfo.error; 177 $('systemStatus').classList.add('hidden'); 178 $('canvas').classList.add('hidden'); 179 $('carrierPage').classList.add('hidden'); 180 $('paymentForm').classList.remove('hidden'); 181 if (this.payment_shown_) 182 $('closeButton').classList.remove('hidden'); 183 else 184 $('closeButton').classList.add('hidden'); 185 $('finalStatus').classList.remove('hidden'); 186 break; 187 } 188 this.state_ = new_state; 189 }, 190 191 updateDeviceStatus_: function(deviceInfo) { 192 this.changeState_(deviceInfo); 193 }, 194 195 sendDeviceInfo_ : function() { 196 var msg = { 197 type: 'deviceInfoMsg', 198 domain: document.location, 199 payload: { 200 'carrier': this.deviceInfo_.carrier, 201 'MEID': this.deviceInfo_.MEID, 202 'IMEI': this.deviceInfo_.IMEI, 203 'MDN': this.deviceInfo_.MDN 204 } 205 }; 206 $(this.frameName_).contentWindow.postMessage(msg, 207 this.deviceInfo_.payment_url); 208 } 209 210 }; 211 212 MobileSetup.drawProgress = function () { 213 var ctx = canvas.getContext('2d'); 214 ctx.clearRect(0, 0, canvas.width, canvas.height); 215 216 var segmentCount = Math.min(12, canvas.width/1.6) // Number of segments 217 var rotation = 0.75; // Counterclockwise rotation 218 219 // Rotate canvas over time 220 ctx.translate(canvas.width/2, canvas.height/2); 221 ctx.rotate(Math.PI * 2 / (segmentCount + rotation)); 222 ctx.translate(-canvas.width/2, -canvas.height/2); 223 224 var gap = canvas.width / 24; // Gap between segments 225 var oRadius = canvas.width/2; // Outer radius 226 var iRadius = oRadius * 0.618; // Inner radius 227 var oCircumference = Math.PI * 2 * oRadius; // Outer circumference 228 var iCircumference = Math.PI * 2 * iRadius; // Inner circumference 229 var oGap = gap / oCircumference; // Gap size as fraction of outer ring 230 var iGap = gap / iCircumference; // Gap size as fraction of inner ring 231 var oArc = Math.PI * 2 * ( 1 / segmentCount - oGap); // Angle of outer arcs 232 var iArc = Math.PI * 2 * ( 1 / segmentCount - iGap); // Angle of inner arcs 233 234 for (i = 0; i < segmentCount; i++){ // Draw each segment 235 var opacity = Math.pow(1.0 - i / segmentCount, 3.0); 236 opacity = (0.15 + opacity * 0.8) // Vary from 0.15 to 0.95 237 var angle = - Math.PI * 2 * i / segmentCount; 238 239 ctx.beginPath(); 240 ctx.arc(canvas.width/2, canvas.height/2, oRadius, 241 angle - oArc/2, angle + oArc/2, false); 242 ctx.arc(canvas.width/2, canvas.height/2, iRadius, 243 angle + iArc/2, angle - iArc/2, true); 244 ctx.closePath(); 245 ctx.fillStyle = "rgba(240, 30, 29, " + opacity + ")"; 246 ctx.fill(); 247 } 248 }; 249 250 MobileSetup.deviceStateChanged = function(deviceInfo) { 251 MobileSetup.getInstance().updateDeviceStatus_(deviceInfo); 252 }; 253 254 MobileSetup.loadPage = function() { 255 mobile.MobileSetup.getInstance().initialize('paymentForm', 256 mobile.MobileSetup.ACTIVATION_PAGE_URL); 257 }; 258 259 // Export 260 return { 261 MobileSetup: MobileSetup 262 }; 263 264 }); 265 266