Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/apps/system/js/wifi.js
blob: 3456fdffcf8bb386aac043baf2ae0b8451348b48 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- /
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */

'use strict';

var Wifi = {
  wifiWakeLocked: false,

  wifiEnabled: true,

  wifiDisabledByWakelock: false,

  // Without wake lock, wait for kOffTime milliseconds and turn wifi off
  // after the conditions are met.
  kOffTime: 60 * 1000,

  // if Wifi is enabled but disconnected, try to scan for networks every
  // kScanInterval ms.
  kScanInterval: 20 * 1000,

  _scanTimer: null,

  init: function wf_init() {
    window.addEventListener('screenchange', this);

    var battery = window.navigator.battery;
    battery.addEventListener('chargingchange', this);

    if (!window.navigator.mozSettings)
      return;

    // If wifi is turned off by us and phone got rebooted,
    // bring wifi back.
    var name = 'wifi.disabled_by_wakelock';
    var req = SettingsListener.getSettingsLock().get(name);
    req.onsuccess = function gotWifiDisabledByWakelock() {
      if (!req.result[name])
        return;

      // Re-enable wifi and reset wifi.disabled_by_wakelock
      // SettingsListener.getSettingsLock() always return invalid lock
      // in our usage here.
      // See https://bugzilla.mozilla.org/show_bug.cgi?id=793239
      var lock = navigator.mozSettings.createLock();
      lock.set({ 'wifi.enabled': true });
      lock.set({ 'wifi.disabled_by_wakelock': false });
    };

    var self = this;
    var wifiManager = window.navigator.mozWifiManager;
    // when wifi is really enabled, emit event to notify QuickSettings
    wifiManager.onenabled = function onWifiEnabled() {
      var evt = document.createEvent('CustomEvent');
      evt.initCustomEvent('wifi-enabled',
        /* canBubble */ true, /* cancelable */ false, null);
      window.dispatchEvent(evt);
    };

    // when wifi is really disabled, emit event to notify QuickSettings
    wifiManager.ondisabled = function onWifiDisabled() {
      var evt = document.createEvent('CustomEvent');
      evt.initCustomEvent('wifi-disabled',
        /* canBubble */ true, /* cancelable */ false, null);
      window.dispatchEvent(evt);
    };

    // when wifi status change, emit event to notify StatusBar/UpdateManager
    wifiManager.onstatuschange = function onWifiDisabled() {
      var evt = document.createEvent('CustomEvent');
      evt.initCustomEvent('wifi-statuschange',
        /* canBubble */ true, /* cancelable */ false, null);
      window.dispatchEvent(evt);
    };

    // Track the wifi.enabled mozSettings value
    SettingsListener.observe('wifi.enabled', true, function(value) {
      if (!wifiManager && value) {
        self.wifiEnabled = false;

        // roll back the setting value to notify the UIs
        // that wifi interface is not available
        if (value) {
          SettingsListener.getSettingsLock().set({
            'wifi.enabled': false
          });
        }

        return;
      }

      self.wifiEnabled = value;

      clearTimeout(self._scanTimer);
      if (!value)
        return;

      // If wifi is enabled but disconnected.
      // we would need to call getNetworks() continuously
      // so we could join known wifi network
      self._scanTimer = setInterval(function wifi_scan() {
        if (wifiManager.connection.status == 'disconnected')
          wifiManager.getNetworks();
      });
    });

    var power = navigator.mozPower;
    power.addWakeLockListener(function wifi_handleWakeLock(topic, state) {
      if (topic !== 'wifi')
        return;

      self.wifiWakeLocked = (state == 'locked-foreground' ||
                             state == 'locked-background');

      self.maybeToggleWifi();
    });
  },

  handleEvent: function wifi_handleEvent(evt) {
    this.maybeToggleWifi();
  },

  // Check the status of screen, wifi wake lock and power source
  // and turn on/off wifi accordingly
  maybeToggleWifi: function wifi_maybeToggleWifi() {
    var battery = window.navigator.battery;
    var wifiManager = window.navigator.mozWifiManager;
    if (!battery || !wifiManager ||
        (!this.wifiEnabled && !this.wifiDisabledByWakelock))
      return;


    // Let's quietly turn off wifi if there is no wake lock and
    // the screen is off and we are not on a power source.
    if (!ScreenManager.screenEnabled &&
        !this.wifiWakeLocked && !battery.charging) {
      // We don't need to do anything if wifi is not enabled currently
      if (!this.wifiEnabled)
        return;

      // We still need to turn of wifi even if there is no Alarm API
      if (!navigator.mozAlarms) {
        console.warn('Turning off wifi without sleep timer because' +
          ' Alarm API is not available');
        this.sleep();

        return;
      }

      // Set System Message Handler, so we will be notified when alarm goes off.
      this.setSystemMessageHandler();

      // Start with a timer, only turn off wifi till timeout.
      var date = new Date(Date.now() + this.kOffTime);
      var self = this;
      var req = navigator.mozAlarms.add(date, 'ignoreTimezone', 'wifi-off');
      req.onsuccess = function wifi_offAlarmSet() {
        self._alarmId = req.result;
      };
      req.onerror = function wifi_offAlarmSetFailed() {
        console.warn('Fail to set wifi sleep timer on Alarm API. ' +
          'Turn off wifi immediately.');
        self.sleep();
      };
    }
    // ... and quietly turn it back on or cancel the timer otherwise
    else {
      if (this._alarmId) {
        navigator.mozAlarms.remove(this._alarmId);
        this._alarmId = null;
      }

      // If wifi is enabled but disconnected.
      // we would need to call getNetworks() so we could join known wifi network
      if (this.wifiEnabled && wifiManager.connection.status == 'disconnected') {
        wifiManager.getNetworks();
      }

      // We don't need to do anything if we didn't disable wifi at first place.
      if (!this.wifiDisabledByWakelock)
        return;

      var lock = SettingsListener.getSettingsLock();
      // turn wifi back on.
      lock.set({ 'wifi.enabled': true });

      this.wifiDisabledByWakelock = false;
      lock.set({ 'wifi.disabled_by_wakelock': false });
    }
  },

  // Quietly turn off wifi for real, set wifiDisabledByWakelock to true
  // so we will turn it back on.
  sleep: function wifi_sleep() {
    var lock = SettingsListener.getSettingsLock();
    // Actually turn off the wifi
    lock.set({ 'wifi.enabled': false });

    // Remember that it was turned off by us.
    this.wifiDisabledByWakelock = true;

    // Keep this value in disk so if the phone reboots we'll
    // be able to turn the wifi back on.
    lock.set({ 'wifi.disabled_by_wakelock': true });
  },

  // Register for handling system message,
  // this cannot be done during |init()| because of bug 797803
  setSystemMessageHandler: function wifi_setSystemMessageHandler() {
    if (this._systemMessageHandlerRegistered)
      return;

    this._systemMessageHandlerRegistered = true;
    var self = this;
    navigator.mozSetMessageHandler('alarm', function gotAlarm(message) {
      if (message.data !== 'wifi-off')
        return;

      self.sleep();
    });
  }
};

Wifi.init();