Home | History | Annotate | Download | only in js
      1 // Copyright 2017 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 'use strict';
      6 
      7 if ((typeof mojo !== 'undefined') && mojo.bindingsLibraryInitialized) {
      8   throw new Error('The Mojo bindings library has been initialized.');
      9 }
     10 
     11 var mojo = mojo || {};
     12 mojo.bindingsLibraryInitialized = true;
     13 
     14 mojo.internal = mojo.internal || {};
     15 
     16 mojo.config = mojo.config || {};
     17 if (typeof mojo.config.global === 'undefined') {
     18   mojo.config.global = this;
     19 }
     20 
     21 if (typeof mojo.config.autoLoadMojomDeps === 'undefined') {
     22   // Whether to automatically load mojom dependencies.
     23   // For example, if foo.mojom imports bar.mojom, |autoLoadMojomDeps| set to
     24   // true means that loading foo.mojom.js will insert a <script> tag to load
     25   // bar.mojom.js, if it hasn't been loaded.
     26   //
     27   // The URL of bar.mojom.js is determined by the relative path of bar.mojom
     28   // (relative to the position of foo.mojom at build time) and the URL of
     29   // foo.mojom.js. For exmple, if at build time the two mojom files are
     30   // located at:
     31   //   a/b/c/foo.mojom
     32   //   a/b/d/bar.mojom
     33   // and the URL of foo.mojom.js is:
     34   //   http://example.org/scripts/b/c/foo.mojom.js
     35   // then the URL of bar.mojom.js will be:
     36   //   http://example.org/scripts/b/d/bar.mojom.js
     37   //
     38   // If you would like bar.mojom.js to live at a different location, you need
     39   // to turn off |autoLoadMojomDeps| before loading foo.mojom.js, and manually
     40   // load bar.mojom.js yourself. Similarly, you need to turn off the option if
     41   // you merge bar.mojom.js and foo.mojom.js into a single file.
     42   //
     43   // Performance tip: Avoid loading the same mojom.js file multiple times.
     44   // Assume that |autoLoadMojomDeps| is set to true,
     45   //
     46   // <!--
     47   // (This comment tag is necessary on IOS to avoid interpreting the closing
     48   // script tags in the example.)
     49   //
     50   // No duplicate loading; recommended:
     51   // <script src="http://example.org/scripts/b/c/foo.mojom.js"></script>
     52   //
     53   // No duplicate loading, although unnecessary:
     54   // <script src="http://example.org/scripts/b/d/bar.mojom.js"></script>
     55   // <script src="http://example.org/scripts/b/c/foo.mojom.js"></script>
     56   //
     57   // Load bar.mojom.js twice; should be avoided:
     58   // <script src="http://example.org/scripts/b/c/foo.mojom.js"></script>
     59   // <script src="http://example.org/scripts/b/d/bar.mojom.js"></script>
     60   //
     61   // -->
     62   mojo.config.autoLoadMojomDeps = true;
     63 }
     64 
     65 (function() {
     66   var internal = mojo.internal;
     67   var config = mojo.config;
     68 
     69   var LoadState = {
     70     PENDING_LOAD: 1,
     71     LOADED: 2
     72   };
     73 
     74   var mojomRegistry = new Map();
     75 
     76   function exposeNamespace(namespace) {
     77     var current = config.global;
     78     var parts = namespace.split('.');
     79 
     80     for (var part; parts.length && (part = parts.shift());) {
     81       if (!current[part]) {
     82         current[part] = {};
     83       }
     84       current = current[part];
     85     }
     86 
     87     return current;
     88   }
     89 
     90   function isMojomPendingLoad(id) {
     91     return mojomRegistry.get(id) === LoadState.PENDING_LOAD;
     92   }
     93 
     94   function isMojomLoaded(id) {
     95     return mojomRegistry.get(id) === LoadState.LOADED;
     96   }
     97 
     98   function markMojomPendingLoad(id) {
     99     if (isMojomLoaded(id)) {
    100       throw new Error('The following mojom file has been loaded: ' + id);
    101     }
    102 
    103     mojomRegistry.set(id, LoadState.PENDING_LOAD);
    104   }
    105 
    106   function markMojomLoaded(id) {
    107     mojomRegistry.set(id, LoadState.LOADED);
    108   }
    109 
    110   function loadMojomIfNecessary(id, relativePath) {
    111     if (mojomRegistry.has(id)) {
    112       return;
    113     }
    114 
    115     if (config.global.document === undefined) {
    116       throw new Error(
    117           'Mojom dependency autoloading is not implemented in workers. ' +
    118           'Please see config variable mojo.config.autoLoadMojomDeps for more ' +
    119           'details.');
    120     }
    121 
    122     markMojomPendingLoad(id);
    123     var url = new URL(relativePath, document.currentScript.src).href;
    124     config.global.document.write('<script type="text/javascript" src="' +
    125                                  url + '"><' + '/script>');
    126   }
    127 
    128   internal.exposeNamespace = exposeNamespace;
    129   internal.isMojomPendingLoad = isMojomPendingLoad;
    130   internal.isMojomLoaded = isMojomLoaded;
    131   internal.markMojomPendingLoad = markMojomPendingLoad;
    132   internal.markMojomLoaded = markMojomLoaded;
    133   internal.loadMojomIfNecessary = loadMojomIfNecessary;
    134 })();
    135