~webapps/unity-chromium-extension/14.04

« back to all changes in this revision

Viewing changes to chromium-extension/unity-webapps-binding.js

  • Committer: Tarmac
  • Author(s): Alexandre Abreu
  • Date: 2013-09-16 15:40:39 UTC
  • mfrom: (227.1.5 latest)
  • Revision ID: tarmac-20130916154039-oj5t4j3stjrog9sz
Release version 3.0
Remove tab integration
Keep webapps installation scheme
Keep website api injection but only handle the init() w/ a default desktop file generated to launch the webbrowser-app in chromeless mode
.

Approved by PS Jenkins bot, Robert Bruce Park.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Chromium Unity integration extension
2
 
 * 
3
 
 *   Copyright 2012 Canonical Ltd.
4
 
 *
5
 
 *   This program is free software: you can redistribute it and/or modify it 
6
 
 *   under the terms of the GNU General Public License version 3, as published 
7
 
 *   by the Free Software Foundation.
8
 
 *
9
 
 *  This program is distributed in the hope that it will be useful, but 
10
 
 *   WITHOUT ANY WARRANTY; without even the implied warranties of 
11
 
 *   MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR 
12
 
 *   PURPOSE.  See the GNU General Public License for more details.
13
 
 *
14
 
 *   You should have received a copy of the GNU General Public License along 
15
 
 *   with this program.  If not, see <http://www.gnu.org/licenses/>.
16
 
 **/
17
 
 
18
 
// TODO just there for convenience, will probably reuse those from FF but w/ a better
19
 
//  module mecanism (dunno what is used by FF)
20
 
 
21
 
// FF specific
22
 
// TODO should be properly injected
23
 
var unsafeWindow = window;
24
 
 
25
 
var UnityPopupManager = (
26
 
  function () {
27
 
    UnityPopupManager = {
28
 
      requestIntegration: function (name, domain, integrateCallback, dontAskActionCallback) {
29
 
        var message = chrome.i18n.getMessage("integration_copy", [name, domain]);
30
 
        var details = "";
31
 
        
32
 
        var isconfirmed = function (response) {
33
 
          return response && response.integrate;
34
 
        };
35
 
        UnityContentScriptApi.requestUnityIntegration (message,
36
 
                                                       details,
37
 
                                                       function(response) {
38
 
                                                         if (isconfirmed (response)) {
39
 
                                                           integrateCallback ();
40
 
                                                         }
41
 
                                                         else {
42
 
                                                           dontAskActionCallback ();
43
 
                                                         }
44
 
                                                       });
45
 
      }
46
 
    };
47
 
    
48
 
    return UnityPopupManager;
49
 
  }                                                
50
 
)();
51
 
 
52
 
var UnityFaviconUtils = (
53
 
  function () {
54
 
    function findFaviconLink (document){
55
 
      var linkElements = document.getElementsByTagName("link");
56
 
      var i = 0;
57
 
      
58
 
      for (i = 0; i < linkElements.length; i++){
59
 
        var element = linkElements[i];
60
 
        
61
 
        if (element.hasAttribute("rel") &&
62
 
            (element.rel == "shortcut icon")) {
63
 
          var link = element.href;
64
 
          
65
 
          if (link[0] == "/") {
66
 
            return document.location + link;
67
 
          } else {
68
 
            return link;
69
 
          }
70
 
        }
71
 
      }
72
 
      
73
 
      return null;
74
 
    }
75
 
    
76
 
    UnityFaviconUtils = {
77
 
      getFaviconForDocument: function (document) {
78
 
        var favIcon = findFaviconLink (document);
79
 
        
80
 
        if (favIcon == null) {
81
 
          favIcon = "http://" + document.domain + "/favicon.ico";
82
 
        }
83
 
        
84
 
        return favIcon;
85
 
      }
86
 
    };
87
 
 
88
 
    return UnityFaviconUtils;
89
 
  }
90
 
) ();
91
 
 
92
 
 
93
 
var UnityWindowHelper = (
94
 
  function () {
95
 
    function UnityWindowHelper (aWindow) {
96
 
      this.window = aWindow;
97
 
    };
98
 
 
99
 
    UnityWindowHelper.prototype.FindToplevelContentWindow = function (aWindow) {
100
 
      var toplevelContentWindow = aWindow;
101
 
      
102
 
      while (toplevelContentWindow.parent != toplevelContentWindow){
103
 
        toplevelContentWindow = toplevelContentWindow.parent;
104
 
      }
105
 
      return toplevelContentWindow;
106
 
    };
107
 
 
108
 
    return UnityWindowHelper;
109
 
  }
110
 
) ();
111
 
 
112
 
 
113
 
var UnityPreviewUtils = (
114
 
  function () {
115
 
    UnityPreviewUtils = {
116
 
      getPreviewForWindow: function (window, callback) {
117
 
        
118
 
        UnityContentScriptApi.takeSnapshot (function (dataURL) {
119
 
                                              callback (dataURL);
120
 
                                            });
121
 
      }
122
 
    };
123
 
 
124
 
    return UnityPreviewUtils;
125
 
  }
126
 
)();
127
 
 
128
 
 
129
 
UnityGlobalPropertyInitializer = {
130
 
  makeCallback: function (get_uwa, service, logger) {
131
 
    function callback(aWindow) {
132
 
      var _global = {
133
 
        context: null
134
 
      };
135
 
      var _uwa = get_uwa();
136
 
 
137
 
      // TODO fix, improper "form"
138
 
      var PopupManager = UnityPopupManager;
139
 
      var WindowHelper = new UnityWindowHelper (window);
140
 
      
141
 
      var doListenToTabChanges = function () {
142
 
        // open communication link w/ background page to be informed of everything that happens w/
143
 
        //  the page itself
144
 
        
145
 
        // TODO mmh all tabs userscript will receive this, so it might trigger duplicate is_active(0) calls
146
 
        //  for already unactive tabs
147
 
        chrome.runtime.onMessage.addListener (
148
 
          function (request, sender, response) {
149
 
            if (request && request.method && request.method === 'on_tab_active_changed') {
150
 
              UnityContentScriptApi.getTabInfo (
151
 
                function (response) {
152
 
                  var uwa = get_uwa();
153
 
                  if (request.tabId === response.tabId) {
154
 
                    logger ('Activating context corresponding to tab ' + request.tabId);
155
 
                    uwa.context_set_view_is_active (_global.context, 1);
156
 
                  }
157
 
                  else {
158
 
                    uwa.context_set_view_is_active (_global.context, 0);
159
 
                  }
160
 
                });
161
 
            }
162
 
          });
163
 
      };
164
 
 
165
 
      window.addEventListener("pagehide"
166
 
                              , function(event) {
167
 
                                var uwa = get_uwa();
168
 
                                if (_global.context == null) {return;}
169
 
                                uwa.context_destroy (_global.context, 0);
170
 
                                _global.context = null;
171
 
                              }, false);
172
 
      _global.onInitCallbacks = [];
173
 
      
174
 
      function doInitializeContextWithName (name, service, domain, iconUrl, oninit, homepage, login, mimeTypes, environmentInfos, firstTime) {
175
 
        // If we are adding the site for the first time and there is no homepage, store the point of integration.
176
 
        if (firstTime && homepage == undefined) {
177
 
          homepage = WindowHelper.FindToplevelContentWindow (window).document.location.toString();
178
 
        }
179
 
        
180
 
        var appRaiseCallback = function (context, file, userdata) {
181
 
          UnityContentScriptApi.getTabInfo (
182
 
            function (response) {
183
 
              UnityContentScriptApi.raiseTabWithId({tabId: response.tabId, windowId: response.windowId});
184
 
 
185
 
              if (file !== null) {
186
 
                if (_global.acceptDataCallback) {
187
 
                  try {
188
 
                    _global.acceptDataCallback (file);
189
 
                  }
190
 
                  catch(e) {
191
 
                    console.log ("Error: " + e);
192
 
                  }  
193
 
                }
194
 
              }
195
 
            });
196
 
        };
197
 
        var appCloseCallback = function (context, userdata) {
198
 
          UnityContentScriptApi.getTabInfo (
199
 
            function (response) {
200
 
              UnityContentScriptApi.killTabWithId({tabId: response.tabId, windowId: response.windowId});
201
 
            });
202
 
        };
203
 
        
204
 
        var contextPrepared = function () {
205
 
 
206
 
          var uwa = get_uwa();
207
 
 
208
 
          if (login) {
209
 
            logger("Notifying parent extension of login info");
210
 
            chrome.runtime.sendMessage ({
211
 
                action: "loginEvent",
212
 
                login: login,
213
 
                domain: domain
214
 
            });
215
 
          }
216
 
 
217
 
          // preview request is asynchronous & only for visible tab, so we
218
 
          // take a guess a take a snapshot in the current tab's state
219
 
          // 
220
 
          // TODO make sure that we are still in the same tab (vs visible one).
221
 
          var _previewData = '\0';
222
 
          UnityPreviewUtils.getPreviewForWindow (window, function (dataURL) { _previewData = dataURL; });
223
 
          
224
 
          var previewRequestedCallback = function (context, user_data) {
225
 
            var content = null;
226
 
            
227
 
            try {           
228
 
              content = _previewData + '\0';
229
 
            } catch (e) {
230
 
              logger ("Unity Preview Error: " + e.toString());
231
 
            }
232
 
            
233
 
            return content;
234
 
          };
235
 
          
236
 
          logger ('Got a context for domain '
237
 
                  + domain
238
 
                  + ', service: '
239
 
                  + service
240
 
                  + ', name: '
241
 
                  + name
242
 
                  + ", homepage: "
243
 
                  + homepage
244
 
                  + ', context: '
245
 
                  + _global.context);
246
 
          
247
 
          _global.contextReady = true;
248
 
          
249
 
          uwa.context_add_icon (_global.context
250
 
                                 , UnityFaviconUtils.getFaviconForDocument (document)
251
 
                                 , 16);
252
 
          
253
 
          uwa.context_on_raise_callback (_global.context, appRaiseCallback, null);
254
 
          uwa.context_on_close_callback (_global.context, appCloseCallback, null);
255
 
          uwa.context_set_preview_requested_callback (_global.context, previewRequestedCallback, null);
256
 
          
257
 
          if ((homepage != undefined) && (homepage != null)) {
258
 
            uwa.context_set_homepage (_global.context, homepage);
259
 
          }
260
 
          
261
 
          for (var c in _global.onInitCallbacks) {
262
 
            var callback = _global.onInitCallbacks[c];
263
 
            
264
 
            if (callback != null) {
265
 
              try {
266
 
                logger ('Calling an initialization callback');
267
 
                
268
 
                callback();
269
 
                
270
 
              } catch (e) {
271
 
                logger ("Unity Extension, error calling onInit callback: " + e.toString());
272
 
              }
273
 
            }
274
 
          }
275
 
          
276
 
          doListenToTabChanges ();
277
 
 
278
 
          uwa.context_set_view_is_active (_global.context, 1);
279
 
 
280
 
          uwa.context_set_view_location (_global.context, document.location.toString());
281
 
          uwa.service_set_xid_for_browser_window_id (service
282
 
                                                      , _global.context
283
 
                                                      , environmentInfos.windowId);
284
 
          
285
 
          var context_name = uwa.context_get_name(_global.context);
286
 
          var domain_name = uwa.context_get_domain(_global.context) || domain;
287
 
          var interest_id = uwa.context_get_interest_id(_global.context);
288
 
          UnityContentScriptApi.addIntegrationScriptForTab(context_name
289
 
                                                           , domain_name
290
 
                                                           , interest_id);
291
 
        };
292
 
        
293
 
        if (_global.context != null) {
294
 
          if (_global.contextReady && oninit != null) {
295
 
            
296
 
            try {
297
 
              logger ("Calling integration script's initialization function");
298
 
              
299
 
              oninit();
300
 
              
301
 
            } catch (e) {
302
 
              logger ("Unity Extension, exception calling onInit callback: " + e.toString());
303
 
            }
304
 
          } else if (_global.contextReady == false) {
305
 
            
306
 
            _global.onInitCallbacks.push (oninit);
307
 
          }
308
 
          return;
309
 
        }
310
 
        
311
 
        _global.context = _uwa.context_new_lazy (service, name, domain, iconUrl, mimeTypes);
312
 
        
313
 
        _global.contextReady = false;
314
 
        
315
 
        _global.onInitCallbacks.push (oninit);
316
 
        
317
 
        logger ("Preparing Unity context");
318
 
        
319
 
        _uwa.context_prepare (_global.context, contextPrepared, null);
320
 
      }; // function doInitializeContextWithName
321
 
      
322
 
      function unityInit (options, environmentInfos) {
323
 
        
324
 
        var name = options.name || "Undefined name";
325
 
        var integrationScriptInitCallback = options.onInit || function () { logger ("Default onInit called for '" + name + "'"); };
326
 
        var iconUrl = options.iconUrl;
327
 
        var homepage = options.homepage;
328
 
        var domain = options.domain;
329
 
        var login = options.login;
330
 
        var mimeTypes = options.mimeTypes;
331
 
        
332
 
        var unityInitWithDomain = function (domain) {
333
 
          if (!_uwa.permissions_is_integration_allowed()) {
334
 
            logger ("Unity integration disabled (by user settings).");
335
 
            return;
336
 
          }
337
 
          function integrateActionCallback() {
338
 
            _uwa.permissions_allow_domain (domain);
339
 
 
340
 
            doInitializeContextWithName (name
341
 
                                         , service
342
 
                                         , domain
343
 
                                         , iconUrl
344
 
                                         , integrationScriptInitCallback
345
 
                                         , homepage
346
 
                                         , login
347
 
                                         , mimeTypes
348
 
                                         , environmentInfos
349
 
                                         , true);
350
 
          }
351
 
 
352
 
          function dontAskActionCallback() {
353
 
            _uwa.permissions_dontask_domain (domain);
354
 
          }
355
 
          logger ("Initializing Unity for domain: " + domain);
356
 
 
357
 
          if (_uwa.permissions_get_domain_dontask (domain)) {
358
 
            logger ("Domain has been 'blacklisted'");
359
 
            return;
360
 
          }
361
 
 
362
 
          if (domain == "" || _uwa.permissions_get_domain_allowed (domain)) {
363
 
            logger ("Domain has been 'whilelisted' - skipping the integration step");
364
 
            try {
365
 
              doInitializeContextWithName (name
366
 
                                           , service
367
 
                                           , domain
368
 
                                           , iconUrl
369
 
                                           , integrationScriptInitCallback
370
 
                                           , homepage
371
 
                                           , login
372
 
                                           , mimeTypes
373
 
                                           , environmentInfos
374
 
                                           , false);
375
 
            }
376
 
            catch (e) {
377
 
              logger ("Unity Extension: Error initializing context (" + e.toString() + e.line + e + ")");
378
 
            }
379
 
            return;
380
 
          }
381
 
          logger ('Requesting Unity integration to user');
382
 
 
383
 
          PopupManager.requestIntegration(name
384
 
                                          , domain
385
 
                                          , integrateActionCallback
386
 
                                          , dontAskActionCallback);
387
 
        }; // function unityInitWithDomain
388
 
 
389
 
        if (!mimeTypes) {
390
 
          mimeTypes = null;
391
 
        }
392
 
        if (!iconUrl) {
393
 
          iconUrl = null;
394
 
        }
395
 
 
396
 
        if (domain == undefined) {
397
 
          domain = document.domain;
398
 
 
399
 
          unityInitWithDomain (domain);
400
 
        } else {
401
 
          UnityContentScriptApi.getBaseDomain (document.location.href
402
 
                                               , function (currentBaseDomain) {
403
 
                                                 if ((domain.indexOf(currentBaseDomain,
404
 
                                                                     domain.length-currentBaseDomain.length) == -1)) {
405
 
                                                   throw Error("invalid supplied domain "
406
 
                                                               + domain
407
 
                                                               + " does not have base suffix ("
408
 
                                                               + currentBaseDomain + ")");
409
 
                                                 }
410
 
                                                 unityInitWithDomain (domain);
411
 
                                               });
412
 
        }
413
 
      }; // function unityInit
414
 
 
415
 
      function unityPrepareEnvironment (options) {
416
 
        UnityContentScriptApi.getTabInfo (function (environmentInfos) {
417
 
                                            logger ('Environment informations: '
418
 
                                                    + environmentInfos.windowId
419
 
                                                    + ', tabId: '
420
 
                                                    + environmentInfos.tabId);
421
 
                                            unityInit (options, environmentInfos);
422
 
                                          });
423
 
      };
424
 
 
425
 
      var CallbackManager = {
426
 
        releaseCallback: function (type) {
427
 
        },
428
 
        makeCallback: function (type, callback) {
429
 
          return callback;
430
 
        }
431
 
      };
432
 
 
433
 
      function acceptData(context, mimes, func) {
434
 
        var uwa = get_uwa();
435
 
        uwa.context_set_application_accept_data(_global.context, mimes);
436
 
        _global.acceptDataCallback = func;
437
 
      }
438
 
 
439
 
      function contextAddApplicationActions(actions) {
440
 
        var uwa = get_uwa();
441
 
        var appActions = [];
442
 
        for (var i = 0; i < actions.length; i++) {
443
 
          appActions.push({
444
 
                            path: actions[i].name
445
 
                            , callback: actions[i].callback
446
 
                          });
447
 
        }
448
 
        uwa.context_add_application_actions(_global.context, appActions, actions.length);
449
 
        actions = [];
450
 
      }
451
 
 
452
 
      return makeAPI (setTimeout
453
 
                      , contextAddApplicationActions
454
 
                      , unityPrepareEnvironment
455
 
                      , UnityContentScriptApi.toDataURL
456
 
                      , logger
457
 
                      , get_uwa
458
 
                      , _global
459
 
                      , CallbackManager
460
 
                      , acceptData);
461
 
      
462
 
    } // function callback
463
 
    
464
 
    return callback;
465
 
    
466
 
  } // makeCallback: function
467
 
};
468