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.
4
5function Loader(pages) {
6  this.pages_ = pages;
7  this.pagesLoaded_ = false;
8  this.loadedCount_ = false;
9}
10
11// Global instance.
12Loader.instance_ = null;
13
14// static.
15Loader.getInstance = function() {
16  if (!Loader.instance_) {
17    if (!g_pages)
18      console.log('Warning: Undefined g_pages.');
19    Loader.instance_ = new Loader(g_pages);
20  }
21
22  return Loader.instance_;
23};
24
25Loader.prototype = {
26  // Alarm name.
27  ALARM_NAME: 'CrOSBkgLoaderAlarm',
28
29  // Initial delay.
30  DELAY_IN_MINUTES: 1,
31
32  // Periodic wakeup delay.
33  PERIOD_IN_MINUTES: 60,
34
35  // Delayed closing of the background page once when all iframes are loaded.
36  maxDelayMS_: 10000,
37
38  // Loader start up. Kicks off alarm initialization if needed.
39  initialize: function() {
40    if (!g_pages || !g_pages.length) {
41      window.close();
42      return;
43    }
44
45    chrome.alarms.onAlarm.addListener(this.onAlarm_.bind(this));
46    // Check if this alarm already exists, if not then create it.
47    chrome.alarms.get(this.ALARM_NAME, function(alarm) {
48      if (!alarm) {
49        chrome.alarms.create(this.ALARM_NAME,
50                             {delayInMinutes: this.DELAY_IN_MINUTES});
51        window.close();
52        return;
53      }
54    }.bind(this));
55  },
56
57  onAlarm_: function(alarm) {
58    if (alarm.name != this.ALARM_NAME)
59      return;
60
61    this.preparePages_();
62  },
63
64  onMessage_: function(event) {
65    var msg = event.data;
66    if (msg.method == 'validate') {
67      var replyMsg = {
68          method: 'validationResults',
69          os: 'ChromeOS'
70      };
71      event.source.postMessage(replyMsg, event.origin);
72    } else {
73      console.log('#### Loader.onMessage_: unknown message');
74    }
75  },
76
77  // Find an extension in the |list| with matching extension |id|.
78  getExtensionById_: function(list, id) {
79    for (var i = 0; i < list.length; i++) {
80      if (list[i].id == id)
81        return list[i];
82    }
83    return null;
84  },
85
86  preparePages_: function() {
87    if (this.pagesLoaded_)
88      return;
89
90    window.addEventListener('message', this.onMessage_.bind(this), false);
91    chrome.management.getAll(function(list) {
92      // Get total count first.
93      var pagesToLoad = [];
94      for (var i = 0; i < this.pages_.length; i++) {
95        var page = this.pages_[i];
96        if (page.oneTime && page.initialized)
97          continue;
98
99        var extension = this.getExtensionById_(list, page.extensionId);
100        if (!extension || !extension.enabled) {
101          page.initialized = true;
102          continue;
103        }
104
105        page.initialized = true;
106        if (page.unloadDelayMS > this.maxDelayMS_)
107          this.maxDelayMS_ = page.unloadDelayMS;
108
109        pagesToLoad.push(page);
110      }
111      this.loadFrames_(pagesToLoad);
112      this.pagesLoaded_ = true;
113    }.bind(this));
114  },
115
116  loadFrames_: function(pages) {
117    this.load_target_ = pages.length;
118    for (var i = 0; i < pages.length; i++) {
119      this.loadLuncherFrame_(i, pages[i].pageUrl);
120    }
121  },
122
123  incrementLoadCounter_: function() {
124    this.loadedCount_++;
125    if (this.loadedCount_ < this.load_target_)
126      return;
127
128    // Delay closing.
129    setInterval(function() {
130      window.close();
131    }.bind(this), this.maxDelayMS_);
132  },
133
134  loadLuncherFrame_: function(index, pageUrl) {
135    var iframe = document.createElement('iframe');
136    iframe.onload = function() {
137      this.incrementLoadCounter_();
138    }.bind(this);
139    iframe.src = pageUrl;
140    iframe.name = 'frame_' + index;
141    document.body.appendChild(iframe);
142  }
143};
144
145Loader.getInstance().initialize();
146