Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / extensions / renderer / resources / stash_client.js
blob110e700ca12cd114131ff44261221f5957b782f8
1 // Copyright 2015 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.
5 define('stash_client', [
6     'async_waiter',
7     'content/public/renderer/service_provider',
8     'extensions/common/mojo/stash.mojom',
9     'mojo/public/js/buffer',
10     'mojo/public/js/codec',
11     'mojo/public/js/core',
12     'mojo/public/js/router',
13 ], function(asyncWaiter, serviceProvider, stashMojom, bufferModule,
14             codec, core, routerModule) {
15   /**
16    * @module stash_client
17    */
19   var service = new stashMojom.StashService.proxyClass(new routerModule.Router(
20       serviceProvider.connectToService(stashMojom.StashService.name)));
22   var unloadEvent = require('unload_event');
24   /**
25    * A callback invoked to obtain objects to stash from a particular client.
26    * @callback module:stash_client.StashCallback
27    * @return {!Promise<!Array<!Object>>|!Array<!Object>} An array of objects to
28    *     stash or a promise that will resolve to an array of objects to stash.
29    *     The exact type of each object should match the type passed alongside
30    *     this callback.
31    */
33   /**
34    * A stash client registration.
35    * @constructor
36    * @private
37    * @alias module:stash_client~Registration
38    */
39   function Registration(id, type, callback) {
40     /**
41      * The client id.
42      * @type {string}
43      * @private
44      */
45     this.id_ = id;
47     /**
48      * The type of the objects to be stashed.
49      * @type {!Object}
50      * @private
51      */
52     this.type_ = type;
54     /**
55      * The callback to invoke to obtain the objects to stash.
56      * @type {module:stash_client.StashCallback}
57      * @private
58      */
59     this.callback_ = callback;
60   }
62   /**
63    * Serializes and returns this client's stashable objects.
64    * @return
65    * {!Promise<!Array<module:extensions/common/stash.mojom.StashedObject>>} The
66    * serialized stashed objects.
67    */
68   Registration.prototype.serialize = function() {
69     return Promise.resolve(this.callback_()).then($Function.bind(
70         function(stashedObjects) {
71       if (!stashedObjects)
72         return [];
73       return $Array.map(stashedObjects, function(stashed) {
74         var builder = new codec.MessageBuilder(
75             0, codec.align(this.type_.encodedSize));
76         builder.encodeStruct(this.type_, stashed.serialization);
77         var encoded = builder.finish();
78         return new stashMojom.StashedObject({
79           id: this.id_,
80           data: new Uint8Array(encoded.buffer.arrayBuffer),
81           stashed_handles: encoded.handles,
82           monitor_handles: stashed.monitorHandles,
83         });
84       }, this);
85     }, this)).catch(function(e) { return []; });
86   };
88   /**
89    * The registered stash clients.
90    * @type {!Array<!Registration>}
91    */
92   var clients = [];
94   /**
95    * Registers a client to provide objects to stash during shut-down.
96    *
97    * @param {string} id The id of the client. This can be passed to retrieve to
98    *     retrieve the stashed objects.
99    * @param {!Object} type The type of the objects that callback will return.
100    * @param {module:stash_client.StashCallback} callback The callback that
101    *     returns objects to stash.
102    * @alias module:stash_client.registerClient
103    */
104   function registerClient(id, type, callback) {
105     clients.push(new Registration(id, type, callback));
106   }
108   var retrievedStash = service.retrieveStash().then(function(result) {
109     if (!result || !result.stash)
110       return {};
111     var stashById = {};
112     $Array.forEach(result.stash, function(stashed) {
113       if (!stashById[stashed.id])
114         stashById[stashed.id] = [];
115       stashById[stashed.id].push(stashed);
116     });
117     return stashById;
118   }, function() {
119     // If the stash is not available, act as if the stash was empty.
120     return {};
121   });
123   /**
124    * Retrieves the objects that were stashed with the given |id|, deserializing
125    * them into structs with type |type|.
126    *
127    * @param {string} id The id of the client. This should be unique to this
128    *     client and should be passed as the id to registerClient().
129    * @param {!Object} type The mojo struct type that was serialized into the
130    *     each stashed object.
131    * @return {!Promise<!Array<!Object>>} The stashed objects. The exact type of
132    *     each object is that of the |type| parameter.
133    * @alias module:stash_client.retrieve
134    */
135   function retrieve(id, type) {
136     return retrievedStash.then(function(stash) {
137       var stashedObjects = stash[id];
138       if (!stashedObjects)
139         return Promise.resolve([]);
141       return Promise.all($Array.map(stashedObjects, function(stashed) {
142         var encodedData = new ArrayBuffer(stashed.data.length);
143         new Uint8Array(encodedData).set(stashed.data);
144         var reader = new codec.MessageReader(new codec.Message(
145             new bufferModule.Buffer(encodedData), stashed.stashed_handles));
146         var decoded = reader.decodeStruct(type);
147         return decoded;
148       }));
149     });
150   }
152   unloadEvent.addListener(function() {
153     Promise.all($Array.map(clients, function(client) {
154       return client.serialize();
155     })).then(function(stashedObjects) {
156       var flattenedObjectsToStash = [];
157       $Array.forEach(stashedObjects, function(stashedObjects) {
158         flattenedObjectsToStash =
159             $Array.concat(flattenedObjectsToStash, stashedObjects);
160       });
161       service.addToStash(flattenedObjectsToStash);
162     });
163   });
165   return {
166     registerClient: registerClient,
167     retrieve: retrieve,
168   };