blob: e506e3a4d03f208f61e9f521ce9cdfe7c45cbf86 [file] [log] [blame]
// 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.
/**
* @typedef {{
* fulfill: function(PiexLoaderResponse):undefined,
* reject: function(string):undefined}
* }}
*/
var PiexRequestCallbacks;
/**
* Color space.
* @enum {string}
*/
var ColorSpace = {
SRGB: 'sRgb',
ADOBE_RGB: 'adobeRgb'
};
/**
* @param {{id:number, thumbnail:!ArrayBuffer, orientation:number,
* colorSpace: ColorSpace}}
* data Data directly returned from NaCl module.
* @constructor
* @struct
*/
function PiexLoaderResponse(data) {
/**
* @public {number}
* @const
*/
this.id = data.id;
/**
* @public {!ArrayBuffer}
* @const
*/
this.thumbnail = data.thumbnail;
/**
* @public {!ImageOrientation}
* @const
*/
this.orientation =
ImageOrientation.fromExifOrientation(data.orientation);
/**
* @public {ColorSpace}
* @const
*/
this.colorSpace = data.colorSpace;
}
/**
* @constructor
* @struct
*/
function PiexLoader() {
/**
* @private {!Element}
* @const
*/
this.naclModule_ = document.createElement('embed');
/**
* @private {!Promise}
* @const
*/
this.naclPromise_ = new Promise(function(fulfill) {
chrome.fileManagerPrivate.isPiexLoaderEnabled(fulfill);
}).then(function(enabled) {
if (!enabled)
return Promise.reject('PiexLoader is not enabled for chromium build.');
return new Promise(function(fulfill, reject) {
var embed = this.naclModule_;
embed.setAttribute('type', 'application/x-pnacl');
// The extension nmf is not allowed to load. We uses .nmf.js instead.
embed.setAttribute('src', '/piex/piex.nmf.txt');
embed.width = 0;
embed.height = 0;
// The <EMBED> element is wrapped inside a <DIV>, which has both a 'load'
// and a 'message' event listener attached. This wrapping method is used
// instead of attaching the event listeners directly to the <EMBED>
// element to ensure that the listeners are active before the NaCl module
// 'load' event fires.
var listenerContainer = document.createElement('div');
listenerContainer.appendChild(embed);
listenerContainer.addEventListener('load', fulfill, true);
listenerContainer.addEventListener(
'message', this.onMessage_.bind(this), true);
listenerContainer.addEventListener('error', function() {
reject(embed['lastError']);
}.bind(this), true);
listenerContainer.addEventListener('crash', function() {
reject('PiexLoader crashed.');
}.bind(this), true);
listenerContainer.style.height = '0px';
document.body.appendChild(listenerContainer);
}.bind(this));
}.bind(this));
/**
* @private {!Object<number, PiexRequestCallbacks>}
* @const
*/
this.requests_ = {};
/**
* @private {number}
*/
this.requestIdCount_ = 0;
}
/**
* @param {Event} event
* @private
*/
PiexLoader.prototype.onMessage_ = function(event) {
var id = event.data.id;
if (!event.data.error) {
var response = new PiexLoaderResponse(event.data);
this.requests_[id].fulfill(response);
} else {
this.requests_[id].reject(event.data.error);
}
delete this.requests_[id];
};
/**
* Starts to load RAW image.
* @param {string} url
* @return {!Promise<!PiexLoaderResponse>}
*/
PiexLoader.prototype.load = function(url) {
return this.naclPromise_.then(function() {
var message = {
id: this.requestIdCount_++,
name: 'loadThumbnail',
url: url
};
this.naclModule_.postMessage(message);
return new Promise(function(fulfill, reject) {
this.requests_[message.id] = {fulfill: fulfill, reject: reject};
}.bind(this));
}.bind(this));
};