Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / browser / resources / chromeos / mobile_setup.js
blobafd59fa93aba5519d436f48764f1e1aaf7931190
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.
6 cr.define('mobile', function() {
8   function MobileSetup() {
9   }
11   cr.addSingletonGetter(MobileSetup);
13   MobileSetup.PLAN_ACTIVATION_UNKNOWN = -2;
14   MobileSetup.PLAN_ACTIVATION_PAGE_LOADING = -1;
15   MobileSetup.PLAN_ACTIVATION_START = 0;
16   MobileSetup.PLAN_ACTIVATION_TRYING_OTASP = 1;
17   MobileSetup.PLAN_ACTIVATION_INITIATING_ACTIVATION = 3;
18   MobileSetup.PLAN_ACTIVATION_RECONNECTING = 4;
19   MobileSetup.PLAN_ACTIVATION_WAITING_FOR_CONNECTION = 5;
20   MobileSetup.PLAN_ACTIVATION_PAYMENT_PORTAL_LOADING = 6;
21   MobileSetup.PLAN_ACTIVATION_SHOWING_PAYMENT = 7;
22   MobileSetup.PLAN_ACTIVATION_RECONNECTING_PAYMENT = 8;
23   MobileSetup.PLAN_ACTIVATION_DELAY_OTASP = 9;
24   MobileSetup.PLAN_ACTIVATION_START_OTASP = 10;
25   MobileSetup.PLAN_ACTIVATION_OTASP = 11;
26   MobileSetup.PLAN_ACTIVATION_DONE = 12;
27   MobileSetup.PLAN_ACTIVATION_ERROR = 0xFF;
29   MobileSetup.EXTENSION_PAGE_URL =
30       'chrome-extension://iadeocfgjdjdmpenejdbfeaocpbikmab';
31   MobileSetup.ACTIVATION_PAGE_URL = MobileSetup.EXTENSION_PAGE_URL +
32                                     '/activation.html';
33   MobileSetup.PORTAL_OFFLINE_PAGE_URL = MobileSetup.EXTENSION_PAGE_URL +
34                                         '/portal_offline.html';
35   MobileSetup.REDIRECT_POST_PAGE_URL = MobileSetup.EXTENSION_PAGE_URL +
36                                        '/redirect.html';
38   MobileSetup.localStrings_ = new LocalStrings();
40   MobileSetup.prototype = {
41     // Mobile device information.
42     deviceInfo_: null,
43     frameName_: '',
44     initialized_: false,
45     fakedTransaction_: false,
46     paymentShown_: false,
47     frameLoadError_: 0,
48     frameLoadIgnored_: true,
49     carrierPageUrl_: null,
50     spinnerInt_: -1,
51     // UI states.
52     state_: MobileSetup.PLAN_ACTIVATION_UNKNOWN,
53     STATE_UNKNOWN_: 'unknown',
54     STATE_CONNECTING_: 'connecting',
55     STATE_ERROR_: 'error',
56     STATE_PAYMENT_: 'payment',
57     STATE_ACTIVATING_: 'activating',
58     STATE_CONNECTED_: 'connected',
60     initialize: function(frame_name, carrierPage) {
61       if (this.initialized_) {
62         console.log('calling initialize() again?');
63         return;
64       }
65       this.initialized_ = true;
66       self = this;
67       this.frameName_ = frame_name;
69       cr.ui.dialogs.BaseDialog.OK_LABEL =
70         MobileSetup.localStrings_.getString('ok_button');
71       cr.ui.dialogs.BaseDialog.CANCEL_LABEL =
72           MobileSetup.localStrings_.getString('cancel_button');
73       this.confirm_ = new cr.ui.dialogs.ConfirmDialog(document.body);
75       window.addEventListener('message', function(e) {
76           self.onMessageReceived_(e);
77       });
79       $('closeButton').addEventListener('click', function(e) {
80         $('finalStatus').classList.add('hidden');
81       });
83       // Kick off activation process.
84       chrome.send('startActivation');
85     },
87     startSpinner_: function() {
88       this.stopSpinner_();
89       this.spinnerInt_ = setInterval(mobile.MobileSetup.drawProgress, 100);
90     },
92     stopSpinner_: function() {
93       if (this.spinnerInt_ != -1) {
94         clearInterval(this.spinnerInt_);
95         this.spinnerInt_ = -1;
96       }
97     },
99     onFrameLoaded_: function(success) {
100       chrome.send('paymentPortalLoad', [success ? 'ok' : 'failed']);
101     },
103     loadPaymentFrame_: function(deviceInfo) {
104       if (deviceInfo) {
105         this.frameLoadError_ = 0;
106         this.deviceInfo_ = deviceInfo;
107         if (deviceInfo.post_data && deviceInfo.post_data.length) {
108           this.frameLoadIgnored_ = true;
109           $(this.frameName_).contentWindow.location.href =
110               MobileSetup.REDIRECT_POST_PAGE_URL +
111               '?post_data=' + escape(deviceInfo.post_data) +
112               '&formUrl=' + escape(deviceInfo.payment_url);
113         } else {
114           this.frameLoadIgnored_ = false;
115           $(this.frameName_).contentWindow.location.href =
116               deviceInfo.payment_url;
117         }
118       }
119     },
121     onMessageReceived_: function(e) {
122       if (e.origin !=
123               this.deviceInfo_.payment_url.substring(0, e.origin.length) &&
124           e.origin != MobileSetup.EXTENSION_PAGE_URL)
125         return;
127       if (e.data.type == 'requestDeviceInfoMsg') {
128         this.sendDeviceInfo_();
129       } else if (e.data.type == 'framePostReady') {
130         this.frameLoadIgnored_ = false;
131         this.sendPostFrame_(e.origin);
132       } else if (e.data.type == 'reportTransactionStatusMsg') {
133         console.log('calling setTransactionStatus from onMessageReceived_');
134         chrome.send('setTransactionStatus', [e.data.status]);
135       }
136     },
138     changeState_: function(deviceInfo) {
139       var newState = deviceInfo.state;
140       if (this.state_ == newState)
141         return;
143       // The mobile setup is already in its final state.
144       if (this.state_ == MobileSetup.PLAN_ACTIVATION_DONE ||
145           this.state_ == MobileSetup.PLAN_ACTIVATION_ERROR) {
146         return;
147       }
149       // Map handler state to UX.
150       switch (newState) {
151         case MobileSetup.PLAN_ACTIVATION_PAGE_LOADING:
152         case MobileSetup.PLAN_ACTIVATION_START:
153         case MobileSetup.PLAN_ACTIVATION_DELAY_OTASP:
154         case MobileSetup.PLAN_ACTIVATION_START_OTASP:
155         case MobileSetup.PLAN_ACTIVATION_RECONNECTING:
156         case MobileSetup.PLAN_ACTIVATION_RECONNECTING_PAYMENT:
157           // Activation page should not be shown for devices that are activated
158           // over non cellular network.
159           if (deviceInfo.activate_over_non_cellular_network)
160             break;
162           $('statusHeader').textContent =
163               MobileSetup.localStrings_.getString('connecting_header');
164           $('auxHeader').textContent =
165               MobileSetup.localStrings_.getString('please_wait');
166           $('paymentForm').classList.add('hidden');
167           $('finalStatus').classList.add('hidden');
168           this.setCarrierPage_(MobileSetup.ACTIVATION_PAGE_URL);
169           $('systemStatus').classList.remove('hidden');
170           $('canvas').classList.remove('hidden');
171           this.startSpinner_();
172           break;
173         case MobileSetup.PLAN_ACTIVATION_TRYING_OTASP:
174         case MobileSetup.PLAN_ACTIVATION_INITIATING_ACTIVATION:
175         case MobileSetup.PLAN_ACTIVATION_OTASP:
176           // Activation page should not be shown for devices that are activated
177           // over non cellular network.
178           if (deviceInfo.activate_over_non_cellular_network)
179             break;
181           $('statusHeader').textContent =
182               MobileSetup.localStrings_.getString('activating_header');
183           $('auxHeader').textContent =
184               MobileSetup.localStrings_.getString('please_wait');
185           $('paymentForm').classList.add('hidden');
186           $('finalStatus').classList.add('hidden');
187           this.setCarrierPage_(MobileSetup.ACTIVATION_PAGE_URL);
188           $('systemStatus').classList.remove('hidden');
189           $('canvas').classList.remove('hidden');
190           this.startSpinner_();
191           break;
192         case MobileSetup.PLAN_ACTIVATION_PAYMENT_PORTAL_LOADING:
193           // Activation page should not be shown for devices that are activated
194           // over non cellular network.
195           if (!deviceInfo.activate_over_non_cellular_network) {
196             $('statusHeader').textContent =
197                 MobileSetup.localStrings_.getString('connecting_header');
198             $('auxHeader').textContent = '';
199             $('paymentForm').classList.add('hidden');
200             $('finalStatus').classList.add('hidden');
201             this.setCarrierPage_(MobileSetup.ACTIVATION_PAGE_URL);
202             $('systemStatus').classList.remove('hidden');
203             $('canvas').classList.remove('hidden');
204           }
205           this.loadPaymentFrame_(deviceInfo);
206           break;
207         case MobileSetup.PLAN_ACTIVATION_WAITING_FOR_CONNECTION:
208           $('statusHeader').textContent =
209               MobileSetup.localStrings_.getString('portal_unreachable_header');
210           $('auxHeader').textContent = '';
211           $('auxHeader').classList.add('hidden');
212           $('paymentForm').classList.add('hidden');
213           $('finalStatus').classList.add('hidden');
214           $('systemStatus').classList.remove('hidden');
215           this.setCarrierPage_(MobileSetup.PORTAL_OFFLINE_PAGE_URL);
216           $('canvas').classList.remove('hidden');
217           this.startSpinner_();
218           break;
219         case MobileSetup.PLAN_ACTIVATION_SHOWING_PAYMENT:
220           $('statusHeader').textContent = '';
221           $('auxHeader').textContent = '';
222           $('finalStatus').classList.add('hidden');
223           $('systemStatus').classList.add('hidden');
224           $('paymentForm').classList.remove('hidden');
225           $('canvas').classList.add('hidden');
226           this.stopSpinner_();
227           this.paymentShown_ = true;
228           break;
229         case MobileSetup.PLAN_ACTIVATION_DONE:
230           $('statusHeader').textContent = '';
231           $('auxHeader').textContent = '';
232           $('finalHeader').textContent =
233               MobileSetup.localStrings_.getString('completed_header');
234           $('finalMessage').textContent =
235               MobileSetup.localStrings_.getString('completed_text');
236           $('systemStatus').classList.add('hidden');
237           $('closeButton').classList.remove('hidden');
238           $('finalStatus').classList.remove('hidden');
239           $('canvas').classList.add('hidden');
240           $('closeButton').classList.toggle('hidden', !this.paymentShown_);
241           $('paymentForm').classList.toggle('hidden', !this.paymentShown_);
242           this.stopSpinner_();
243           break;
244         case MobileSetup.PLAN_ACTIVATION_ERROR:
245           $('statusHeader').textContent = '';
246           $('auxHeader').textContent = '';
247           $('finalHeader').textContent =
248               MobileSetup.localStrings_.getString('error_header');
249           $('finalMessage').textContent = deviceInfo.error;
250           $('systemStatus').classList.add('hidden');
251           $('canvas').classList.add('hidden');
252           $('closeButton').classList.toggle('hidden', !this.paymentShown_);
253           $('paymentForm').classList.toggle('hidden', !this.paymentShown_);
254           $('finalStatus').classList.remove('hidden');
255           this.stopSpinner_();
256           break;
257       }
258       this.state_ = newState;
259     },
261     setCarrierPage_: function(url) {
262       if (this.carrierPageUrl_ == url)
263         return;
264       this.carrierPageUrl_ = url;
265       $('carrierPage').contentWindow.location.href = url;
266     },
268     updateDeviceStatus_: function(deviceInfo) {
269       this.changeState_(deviceInfo);
270     },
272     portalFrameLoadError_: function(errorCode) {
273       if (this.frameLoadIgnored_)
274         return;
275       console.log('Portal frame load error detected: ', errorCode);
276       this.frameLoadError_ = errorCode;
277     },
279     portalFrameLoadCompleted_: function() {
280       if (this.frameLoadIgnored_)
281         return;
282       console.log('Portal frame load completed!');
283       this.onFrameLoaded_(this.frameLoadError_ == 0);
284     },
286     sendPostFrame_: function(frameUrl) {
287       var msg = { type: 'postFrame' };
288       $(this.frameName_).contentWindow.postMessage(msg, frameUrl);
289     },
291     sendDeviceInfo_: function() {
292       var msg = {
293         type: 'deviceInfoMsg',
294         domain: document.location,
295         payload: {
296           'carrier': this.deviceInfo_.carrier,
297           'MEID': this.deviceInfo_.MEID,
298           'IMEI': this.deviceInfo_.IMEI,
299           'MDN': this.deviceInfo_.MDN
300         }
301       };
302       $(this.frameName_).contentWindow.postMessage(msg,
303           this.deviceInfo_.payment_url);
304     }
306   };
308   MobileSetup.drawProgress = function() {
309     var ctx = canvas.getContext('2d');
310     ctx.clearRect(0, 0, canvas.width, canvas.height);
312     var segmentCount = Math.min(12, canvas.width / 1.6); // Number of segments
313     var rotation = 0.75; // Counterclockwise rotation
315     // Rotate canvas over time
316     ctx.translate(canvas.width / 2, canvas.height / 2);
317     ctx.rotate(Math.PI * 2 / (segmentCount + rotation));
318     ctx.translate(-canvas.width / 2, -canvas.height / 2);
320     var gap = canvas.width / 24; // Gap between segments
321     var oRadius = canvas.width / 2; // Outer radius
322     var iRadius = oRadius * 0.618; // Inner radius
323     var oCircumference = Math.PI * 2 * oRadius; // Outer circumference
324     var iCircumference = Math.PI * 2 * iRadius; // Inner circumference
325     var oGap = gap / oCircumference; // Gap size as fraction of  outer ring
326     var iGap = gap / iCircumference; // Gap size as fraction of  inner ring
327     var oArc = Math.PI * 2 * (1 / segmentCount - oGap); // Angle of outer arcs
328     var iArc = Math.PI * 2 * (1 / segmentCount - iGap); // Angle of inner arcs
330     for (i = 0; i < segmentCount; i++) { // Draw each segment
331       var opacity = Math.pow(1.0 - i / segmentCount, 3.0);
332       opacity = (0.15 + opacity * 0.8); // Vary from 0.15 to 0.95
333       var angle = - Math.PI * 2 * i / segmentCount;
335       ctx.beginPath();
336       ctx.arc(canvas.width / 2, canvas.height / 2, oRadius,
337         angle - oArc / 2, angle + oArc / 2, false);
338       ctx.arc(canvas.width / 2, canvas.height / 2, iRadius,
339         angle + iArc / 2, angle - iArc / 2, true);
340       ctx.closePath();
341       ctx.fillStyle = 'rgba(240, 30, 29, ' + opacity + ')';
342       ctx.fill();
343     }
344   };
346   MobileSetup.deviceStateChanged = function(deviceInfo) {
347     MobileSetup.getInstance().updateDeviceStatus_(deviceInfo);
348   };
350   MobileSetup.portalFrameLoadError = function(errorCode) {
351     MobileSetup.getInstance().portalFrameLoadError_(errorCode);
352   };
354   MobileSetup.portalFrameLoadCompleted = function() {
355     MobileSetup.getInstance().portalFrameLoadCompleted_();
356   };
358   MobileSetup.loadPage = function() {
359     mobile.MobileSetup.getInstance().initialize('paymentForm',
360         mobile.MobileSetup.ACTIVATION_PAGE_URL);
361   };
363   // Export
364   return {
365     MobileSetup: MobileSetup
366   };
369 document.addEventListener('DOMContentLoaded', mobile.MobileSetup.loadPage);