- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / resources / chromeos / mobile_setup_portal.js
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.
4
5 cr.define('mobile', function() {
6
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';
14
15   var NetworkState = {
16     UNKNOWN: 0,
17     PORTAL_REACHABLE: 1,
18     PORTAL_UNREACHABLE: 2
19   };
20
21   var CarrierPageType = {
22     NOT_SET: 0,
23     PORTAL_OFFLINE: 1,
24     INVALID_DEVICE_INFO: 2
25   };
26
27   var localStrings = new LocalStrings();
28
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;
36   }
37
38   cr.addSingletonGetter(PortalImpl);
39
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');
47     },
48
49     updateDeviceInfo: function(deviceInfo) {
50       this.deviceInfo_ = deviceInfo;
51       this.updateState_();
52     },
53
54     updateNetworkState: function(networkState) {
55       if (this.networkState_ == networkState)
56         return;
57       this.networkState_ = networkState;
58
59       // If the device info is not yet set, the state will be updated on the
60       // device info update.
61       if (this.deviceInfo_)
62         this.updateState_();
63     },
64
65     updateState_: function() {
66       if (!this.deviceInfo_ || this.networkState_ == NetworkState.UNKNOWN)
67         return;
68
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;
81      } else {
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;
87         this.stopSpinner_();
88       }
89     },
90
91     setCarrierPage_: function(type) {
92       // The page is already set, nothing to do.
93       if (type == this.carrierPageType_)
94         return;
95
96       switch (type) {
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_();
103           break;
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');
109           this.stopSpinner_();
110           break;
111         case CarrierPageType.NOT_SET:
112           $('carrierPage').contentWindow.location.href = 'about:blank';
113           $('statusHeader').textContent = '';
114           this.stopSpinner_();
115           break;
116         default:
117           break;
118       }
119
120       this.carrierPageType_ = type;
121     },
122
123     setPortalFrameIfNeeded_: function(deviceInfo) {
124       // The portal should be set only once.
125       if (this.portalFrameSet_)
126         return;
127
128       var postData = '';
129       if (deviceInfo.post_data && deviceInfo.post_data.length)
130         postData = '&post_data=' + encodeURIComponent(deviceInfo.post_data);
131
132       $('portalFrame').contentWindow.location.href = REDIRECT_POST_PAGE_URL +
133           postData + '&formUrl=' + encodeURIComponent(deviceInfo.payment_url);
134
135       this.portalFrameSet_ = true;
136     },
137
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]');
142     },
143
144     startSpinner_: function() {
145       this.stopSpinner_();
146       this.spinnerInt_ = setInterval(this.drawProgress_.bind(this), 100);
147     },
148
149     stopSpinner_: function() {
150       if (this.spinnerInt_ != -1) {
151         clearInterval(this.spinnerInt_);
152         this.spinnerInt_ = -1;
153       }
154       // Clear the spinner canvas.
155       var ctx = canvas.getContext('2d');
156       ctx.clearRect(0, 0, canvas.width, canvas.height);
157     },
158
159     drawProgress_: function() {
160       var ctx = canvas.getContext('2d');
161       ctx.clearRect(0, 0, canvas.width, canvas.height);
162
163       var segmentCount = Math.min(12, canvas.width / 1.6); // Number of segments
164       var rotation = 0.75; // Counterclockwise rotation
165
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);
170
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
180
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;
185
186         ctx.beginPath();
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);
191         ctx.closePath();
192         ctx.fillStyle = 'rgba(240, 30, 29, ' + opacity + ')';
193         ctx.fill();
194       }
195     }
196   };
197
198   function MobileSetupPortal() {}
199
200   MobileSetupPortal.loadPage = function() {
201     PortalImpl.getInstance().initialize();
202   };
203
204   MobileSetupPortal.onGotDeviceInfo = function(deviceInfo) {
205     PortalImpl.getInstance().updateDeviceInfo(deviceInfo);
206   };
207
208   MobileSetupPortal.onConnectivityChanged = function(portalReachable) {
209     PortalImpl.getInstance().updateNetworkState(
210         portalReachable ? NetworkState.PORTAL_REACHABLE :
211                           NetworkState.PORTAL_UNREACHABLE);
212   };
213
214   // Export
215   return {
216     MobileSetupPortal: MobileSetupPortal
217   };
218 });
219
220 document.addEventListener('DOMContentLoaded',
221                           mobile.MobileSetupPortal.loadPage);