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
6cr.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