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
|
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
define('stash_client', [
'async_waiter',
'content/public/renderer/frame_service_registry',
'extensions/common/mojo/stash.mojom',
'mojo/public/js/buffer',
'mojo/public/js/codec',
'mojo/public/js/core',
'mojo/public/js/router',
], function(asyncWaiter, serviceProvider, stashMojom, bufferModule,
codec, core, routerModule) {
/**
* @module stash_client
*/
var service = new stashMojom.StashService.proxyClass(new routerModule.Router(
serviceProvider.connectToService(stashMojom.StashService.name)));
/**
* A callback invoked to obtain objects to stash from a particular client.
* @callback module:stash_client.StashCallback
* @return {!Promise<!Array<!Object>>|!Array<!Object>} An array of objects to
* stash or a promise that will resolve to an array of objects to stash.
* The exact type of each object should match the type passed alongside
* this callback.
*/
/**
* A stash client registration.
* @constructor
* @private
* @alias module:stash_client~Registration
*/
function Registration(id, type, callback) {
/**
* The client id.
* @type {string}
* @private
*/
this.id_ = id;
/**
* The type of the objects to be stashed.
* @type {!Object}
* @private
*/
this.type_ = type;
/**
* The callback to invoke to obtain the objects to stash.
* @type {module:stash_client.StashCallback}
* @private
*/
this.callback_ = callback;
}
/**
* Serializes and returns this client's stashable objects.
* @return
* {!Promise<!Array<module:extensions/common/stash.mojom.StashedObject>>} The
* serialized stashed objects.
*/
Registration.prototype.serialize = function() {
return Promise.resolve(this.callback_()).then($Function.bind(
function(stashedObjects) {
if (!stashedObjects)
return [];
return $Array.map(stashedObjects, function(stashed) {
var builder = new codec.MessageBuilder(
0, codec.align(this.type_.encodedSize));
builder.encodeStruct(this.type_, stashed.serialization);
var encoded = builder.finish();
return new stashMojom.StashedObject({
id: this.id_,
data: new Uint8Array(encoded.buffer.arrayBuffer),
stashed_handles: encoded.handles,
monitor_handles: stashed.monitorHandles,
});
}, this);
}, this)).catch(function(e) { return []; });
};
/**
* The registered stash clients.
* @type {!Array<!Registration>}
*/
var clients = [];
/**
* Registers a client to provide objects to stash during shut-down.
*
* @param {string} id The id of the client. This can be passed to retrieve to
* retrieve the stashed objects.
* @param {!Object} type The type of the objects that callback will return.
* @param {module:stash_client.StashCallback} callback The callback that
* returns objects to stash.
* @alias module:stash_client.registerClient
*/
function registerClient(id, type, callback) {
clients.push(new Registration(id, type, callback));
}
var retrievedStash = service.retrieveStash().then(function(result) {
if (!result || !result.stash)
return {};
var stashById = {};
$Array.forEach(result.stash, function(stashed) {
if (!stashById[stashed.id])
stashById[stashed.id] = [];
stashById[stashed.id].push(stashed);
});
return stashById;
}, function() {
// If the stash is not available, act as if the stash was empty.
return {};
});
/**
* Retrieves the objects that were stashed with the given |id|, deserializing
* them into structs with type |type|.
*
* @param {string} id The id of the client. This should be unique to this
* client and should be passed as the id to registerClient().
* @param {!Object} type The mojo struct type that was serialized into the
* each stashed object.
* @return {!Promise<!Array<!Object>>} The stashed objects. The exact type of
* each object is that of the |type| parameter.
* @alias module:stash_client.retrieve
*/
function retrieve(id, type) {
return retrievedStash.then(function(stash) {
var stashedObjects = stash[id];
if (!stashedObjects)
return Promise.resolve([]);
return Promise.all($Array.map(stashedObjects, function(stashed) {
var encodedData = new ArrayBuffer(stashed.data.length);
new Uint8Array(encodedData).set(stashed.data);
var reader = new codec.MessageReader(new codec.Message(
new bufferModule.Buffer(encodedData), stashed.stashed_handles));
var decoded = reader.decodeStruct(type);
return decoded;
}));
});
}
function saveStashForTesting() {
Promise.all($Array.map(clients, function(client) {
return client.serialize();
})).then(function(stashedObjects) {
var flattenedObjectsToStash = [];
$Array.forEach(stashedObjects, function(stashedObjects) {
flattenedObjectsToStash =
$Array.concat(flattenedObjectsToStash, stashedObjects);
});
service.addToStash(flattenedObjectsToStash);
});
}
return {
registerClient: registerClient,
retrieve: retrieve,
saveStashForTesting: saveStashForTesting,
};
});
|