This commit is contained in:
Ryan VanderMeulen 2015-02-02 17:06:25 -05:00
Родитель 436c0a44d6 9a17661533
Коммит 0ace9ac204
85 изменённых файлов: 49882 добавлений и 46981 удалений

Просмотреть файл

@ -1,11 +1,21 @@
const TEST_PAGE = "http://mochi.test:8888/browser/browser/base/content/test/general/file_double_close_tab.html";
let expectingDialog = false;
let wantToClose = true;
let resolveDialogPromise;
function onTabModalDialogLoaded(node) {
ok(expectingDialog, "Should be expecting this dialog.");
expectingDialog = false;
// This accepts the dialog, closing it
node.Dialog.ui.button0.click();
if (wantToClose) {
// This accepts the dialog, closing it
node.Dialog.ui.button0.click();
} else {
// This keeps the page open
node.Dialog.ui.button1.click();
}
if (resolveDialogPromise) {
resolveDialogPromise();
}
}
@ -41,4 +51,25 @@ add_task(function* closeWindowWithMultipleTabsIncludingOneBeforeUnload() {
yield windowClosedPromise;
ok(!expectingDialog, "There should have been a dialog.");
ok(newWin.closed, "Window should be closed.");
Services.prefs.clearUserPref("browser.tabs.warnOnClose");
});
add_task(function* closeWindoWithSingleTabTwice() {
let newWin = yield promiseOpenAndLoadWindow({}, true);
let firstTab = newWin.gBrowser.selectedTab;
yield promiseTabLoadEvent(firstTab, TEST_PAGE);
let windowClosedPromise = promiseWindowWillBeClosed(newWin);
expectingDialog = true;
wantToClose = false;
let firstDialogShownPromise = new Promise((resolve, reject) => { resolveDialogPromise = resolve; });
document.getAnonymousElementByAttribute(firstTab, "anonid", "close-button").click();
yield firstDialogShownPromise;
info("Got initial dialog, now trying again");
expectingDialog = true;
wantToClose = true;
resolveDialogPromise = null;
document.getAnonymousElementByAttribute(firstTab, "anonid", "close-button").click();
yield windowClosedPromise;
ok(!expectingDialog, "There should have been a dialog.");
ok(newWin.closed, "Window should be closed.");
});

Просмотреть файл

@ -108,7 +108,9 @@ loop.conversation = (function(mozL10n) {
callback(null, navigator.mozLoop.getLoopPref("ot.guid"));
},
set: function(guid, callback) {
navigator.mozLoop.setLoopPref("ot.guid", guid);
// See nsIPrefBranch
const PREF_STRING = 32;
navigator.mozLoop.setLoopPref("ot.guid", guid, PREF_STRING);
callback(null);
}
});

Просмотреть файл

@ -108,7 +108,9 @@ loop.conversation = (function(mozL10n) {
callback(null, navigator.mozLoop.getLoopPref("ot.guid"));
},
set: function(guid, callback) {
navigator.mozLoop.setLoopPref("ot.guid", guid);
// See nsIPrefBranch
const PREF_STRING = 32;
navigator.mozLoop.setLoopPref("ot.guid", guid, PREF_STRING);
callback(null);
}
});

Просмотреть файл

@ -32,7 +32,9 @@ loop.store.FxOSActiveRoomStore = (function() {
roomState: ROOM_STATES.INIT,
audioMuted: false,
videoMuted: false,
failureReason: undefined
failureReason: undefined,
localVideoDimensions: {},
remoteVideoDimensions: {}
};
},

Просмотреть файл

@ -580,9 +580,6 @@ BrowserGlue.prototype = {
if (Services.prefs.getBoolPref("dom.identity.enabled")) {
SignInToWebsiteUX.init();
}
#endif
#ifdef NIGHTLY_BUILD
ShumwayUtils.init();
#endif
webrtcUI.init();
AboutHome.init();
@ -756,6 +753,12 @@ BrowserGlue.prototype = {
// With older versions of the extension installed, this load will fail
// passively.
aWindow.messageManager.loadFrameScript("resource://pdf.js/pdfjschildbootstrap.js", true);
#ifdef NIGHTLY_BUILD
// Registering Shumway bootstrap script the child processes.
aWindow.messageManager.loadFrameScript("chrome://shumway/content/bootstrap-content.js", true);
// Initializing Shumway (shall be run after child script registration).
ShumwayUtils.init();
#endif
#ifdef XP_WIN
// For windows seven, initialize the jump list module.
const WINTASKBAR_CONTRACTID = "@mozilla.org/windows-taskbar;1";

Просмотреть файл

@ -272,42 +272,6 @@ function promiseIsURIVisited(aURI) {
return deferred.promise;
}
/**
* Waits for all pending async statements on the default connection.
*
* @return {Promise}
* @resolves When all pending async statements finished.
* @rejects Never.
*
* @note The result is achieved by asynchronously executing a query requiring
* a write lock. Since all statements on the same connection are
* serialized, the end of this write operation means that all writes are
* complete. Note that WAL makes so that writers don't block readers, but
* this is a problem only across different connections.
*/
function promiseAsyncUpdates()
{
let deferred = Promise.defer();
let db = DBConn();
let begin = db.createAsyncStatement("BEGIN EXCLUSIVE");
begin.executeAsync();
begin.finalize();
let commit = db.createAsyncStatement("COMMIT");
commit.executeAsync({
handleResult: function () {},
handleError: function () {},
handleCompletion: function(aReason)
{
deferred.resolve();
}
});
commit.finalize();
return deferred.promise;
}
function promiseBookmarksNotification(notification, conditionFn) {
info(`Waiting for ${notification}`);
return new Promise((resolve, reject) => {

Просмотреть файл

@ -22,7 +22,7 @@ function waitForImportAndSmartBookmarks(aCallback) {
Services.obs.removeObserver(waitImport, "bookmarks-restore-success");
// Delay to test eventual smart bookmarks creation.
do_execute_soon(function () {
promiseAsyncUpdates().then(aCallback);
PlacesTestUtils.promiseAsyncUpdates().then(aCallback);
});
}, "bookmarks-restore-success", false);
}

Просмотреть файл

@ -345,7 +345,7 @@ function waitForImportAndSmartBookmarks(aCallback) {
Services.obs.removeObserver(waitImport, "bookmarks-restore-success");
// Delay to test eventual smart bookmarks creation.
do_execute_soon(function () {
promiseAsyncUpdates().then(aCallback);
PlacesTestUtils.promiseAsyncUpdates().then(aCallback);
});
}, "bookmarks-restore-success", false);
}

Просмотреть файл

@ -1 +1,2 @@
content shumway chrome/
resource shumway content/

Просмотреть файл

@ -0,0 +1,192 @@
/*
* Copyright 2014 Mozilla Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
var EXPORTED_SYMBOLS = ['RtmpUtils'];
Components.utils.import('resource://gre/modules/Services.jsm');
var Cc = Components.classes;
var Ci = Components.interfaces;
var Cu = Components.utils;
var Cr = Components.results;
var RtmpUtils = {
get isRtmpEnabled() {
try {
return Services.prefs.getBoolPref('shumway.rtmp.enabled');
} catch (ex) {
return false;
}
},
createSocket: function (sandbox, params) {
var host = params.host, port = params.port, ssl = params.ssl;
var baseSocket = Cc["@mozilla.org/tcp-socket;1"].createInstance(Ci.nsIDOMTCPSocket);
var socket = baseSocket.open(host, port, {useSecureTransport: ssl, binaryType: 'arraybuffer'});
if (!socket) {
return null;
}
var wrapperOnOpen = null, wrapperOnData = null, wrapperOnDrain = null;
var wrapperOnError = null, wrapperOnClose = null;
socket.onopen = function () {
if (wrapperOnOpen) {
wrapperOnOpen.call(wrapper, new sandbox.Object());
}
};
socket.ondata = function (e) {
if (wrapperOnData) {
var wrappedE = new sandbox.Object();
wrappedE.data = Components.utils.cloneInto(e.data, sandbox);
wrapperOnData.call(wrapper, wrappedE);
}
};
socket.ondrain = function () {
if (wrapperOnDrain) {
wrapperOnDrain.call(wrapper, new sandbox.Object());
}
};
socket.onerror = function (e) {
if (wrapperOnError) {
var wrappedE = new sandbox.Object();
wrappedE.data = Components.utils.cloneInto(e.data, sandbox);
wrapperOnError.call(wrapper, wrappedE);
}
};
socket.onclose = function () {
if (wrapperOnClose) {
wrapperOnClose.call(wrapper, new sandbox.Object());
}
};
var wrapper = new sandbox.Object();
var waived = Components.utils.waiveXrays(wrapper);
Object.defineProperties(waived, {
onopen: {
get: function () { return wrapperOnOpen; },
set: function (value) { wrapperOnOpen = value; },
enumerable: true
},
ondata: {
get: function () { return wrapperOnData; },
set: function (value) { wrapperOnData = value; },
enumerable: true
},
ondrain: {
get: function () { return wrapperOnDrain; },
set: function (value) { wrapperOnDrain = value; },
enumerable: true
},
onerror: {
get: function () { return wrapperOnError; },
set: function (value) { wrapperOnError = value; },
enumerable: true
},
onclose: {
get: function () { return wrapperOnClose; },
set: function (value) { wrapperOnClose = value; },
enumerable: true
},
send: {
value: function (buffer, offset, count) {
return socket.send(buffer, offset, count);
}
},
close: {
value: function () {
socket.close();
}
}
});
return wrapper;
},
createXHR: function (sandbox) {
var xhr = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"]
.createInstance(Ci.nsIXMLHttpRequest);
var wrapperOnLoad = null, wrapperOnError = null;
xhr.onload = function () {
if (wrapperOnLoad) {
wrapperOnLoad.call(wrapper, new sandbox.Object());
}
};
xhr.onerror = function () {
if (wrappedOnError) {
wrappedOnError.call(wrapper, new sandbox.Object());
}
};
var wrapper = new sandbox.Object();
var waived = Components.utils.waiveXrays(wrapper);
Object.defineProperties(waived, {
status: {
get: function () { return xhr.status; },
enumerable: true
},
response: {
get: function () { return Components.utils.cloneInto(xhr.response, sandbox); },
enumerable: true
},
responseType: {
get: function () { return xhr.responseType; },
set: function (value) {
if (value !== 'arraybuffer') {
throw new Error('Invalid responseType.');
}
},
enumerable: true
},
onload: {
get: function () { return wrapperOnLoad; },
set: function (value) { wrapperOnLoad = value; },
enumerable: true
},
onerror: {
get: function () { return wrapperOnError; },
set: function (value) { wrapperOnError = value; },
enumerable: true
},
open: {
value: function (method, path, async) {
if (method !== 'POST' || !path || (async !== undefined && !async)) {
throw new Error('invalid open() arguments');
}
// TODO check path
xhr.open('POST', path, true);
xhr.responseType = 'arraybuffer';
xhr.setRequestHeader('Content-Type', 'application/x-fcs');
}
},
setRequestHeader: {
value: function (header, value) {
if (header !== 'Content-Type' || value !== 'application/x-fcs') {
throw new Error('invalid setRequestHeader() arguments');
}
}
},
send: {
value: function (data) {
xhr.send(data);
}
}
});
return wrapper;
}
};

Просмотреть файл

@ -0,0 +1,132 @@
/*
* Copyright 2014 Mozilla Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
var EXPORTED_SYMBOLS = ['SpecialInflate', 'SpecialInflateUtils'];
Components.utils.import('resource://gre/modules/Services.jsm');
var Cc = Components.classes;
var Ci = Components.interfaces;
var Cu = Components.utils;
var Cr = Components.results;
function SimpleStreamListener() {
this.binaryStream = Cc['@mozilla.org/binaryinputstream;1']
.createInstance(Ci.nsIBinaryInputStream);
this.onData = null;
this.buffer = null;
}
SimpleStreamListener.prototype = {
QueryInterface: function (iid) {
if (iid.equals(Ci.nsIStreamListener) ||
iid.equals(Ci.nsIRequestObserver) ||
iid.equals(Ci.nsISupports))
return this;
throw Cr.NS_ERROR_NO_INTERFACE;
},
onStartRequest: function (aRequest, aContext) {
return Cr.NS_OK;
},
onStopRequest: function (aRequest, aContext, sStatusCode) {
return Cr.NS_OK;
},
onDataAvailable: function (aRequest, aContext, aInputStream, aOffset, aCount) {
this.binaryStream.setInputStream(aInputStream);
if (!this.buffer || aCount > this.buffer.byteLength) {
this.buffer = new ArrayBuffer(aCount);
}
this.binaryStream.readArrayBuffer(aCount, this.buffer);
this.onData(new Uint8Array(this.buffer, 0, aCount));
return Cr.NS_OK;
}
};
function SpecialInflate() {
var listener = new SimpleStreamListener();
listener.onData = function (data) {
this.onData(data);
}.bind(this);
var converterService = Cc["@mozilla.org/streamConverters;1"].getService(Ci.nsIStreamConverterService);
var converter = converterService.asyncConvertData("deflate", "uncompressed", listener, null);
converter.onStartRequest(null, null);
this.converter = converter;
var binaryStream = Cc["@mozilla.org/binaryoutputstream;1"].createInstance(Ci.nsIBinaryOutputStream);
var pipe = Cc["@mozilla.org/pipe;1"].createInstance(Ci.nsIPipe);
pipe.init(true, true, 0, 0xFFFFFFFF, null);
binaryStream.setOutputStream(pipe.outputStream);
this.binaryStream = binaryStream;
this.pipeInputStream = pipe.inputStream;
this.onData = null;
}
SpecialInflate.prototype = {
push: function (data) {
this.binaryStream.writeByteArray(data, data.length);
this.converter.onDataAvailable(null, null, this.pipeInputStream, 0, data.length);
},
close: function () {
this.binaryStream.close();
this.converter.onStopRequest(null, null, Cr.NS_OK);
}
};
var SpecialInflateUtils = {
get isSpecialInflateEnabled() {
try {
return Services.prefs.getBoolPref('shumway.specialInflate');
} catch (ex) {
return false; // TODO true;
}
},
createWrappedSpecialInflate: function (sandbox) {
var wrapped = new SpecialInflate();
var wrapperOnData = null;
wrapped.onData = function(data) {
if (wrapperOnData) {
wrapperOnData.call(wrapper, Components.utils.cloneInto(data, sandbox));
}
};
// We will return object created in the sandbox/content, with some exposed
// properties/methods, so we can send data between wrapped object and
// and sandbox/content.
var wrapper = new sandbox.Object();
var waived = Components.utils.waiveXrays(wrapper);
Object.defineProperties(waived, {
onData: {
get: function () { return wrapperOnData; },
set: function (value) { wrapperOnData = value; },
enumerable: true
},
push: {
value: function (data) {
// Uint8Array is expected in the data parameter.
// SpecialInflate.push() fails with other argument types.
return wrapped.push(data);
}
},
close: {
value: function () {
return wrapped.close();
}
}
});
return wrapper;
}
};

80
browser/extensions/shumway/chrome/bootstrap-content.js поставляемый Normal file
Просмотреть файл

@ -0,0 +1,80 @@
/*
* Copyright 2014 Mozilla Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
'use strict';
(function contentScriptClosure() {
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cm = Components.manager;
const Cu = Components.utils;
const Cr = Components.results;
// we need to use closure here -- we are running in the global context
Cu.import('resource://gre/modules/Services.jsm');
var isRemote = Services.appinfo.processType ===
Services.appinfo.PROCESS_TYPE_CONTENT;
var isStarted = false;
function startup() {
if (isStarted) {
return;
}
isStarted = true;
Cu.import('resource://shumway/ShumwayBootstrapUtils.jsm');
ShumwayBootstrapUtils.register();
}
function shutdown() {
if (!isStarted) {
return;
}
isStarted = false;
ShumwayBootstrapUtils.unregister();
Cu.unload('resource://shumway/ShumwayBootstrapUtils.jsm');
}
function updateSettings() {
let mm = Cc["@mozilla.org/childprocessmessagemanager;1"]
.getService(Ci.nsISyncMessageSender);
var results = mm.sendSyncMessage('Shumway:Chrome:isEnabled');
var isEnabled = results.some(function (item) {
return item;
});
if (isEnabled) {
startup();
} else {
shutdown();
}
}
if (isRemote) {
addMessageListener('Shumway:Child:refreshSettings', updateSettings);
updateSettings();
addMessageListener('Shumway:Child:shutdown', function shutdownListener(e) {
removeMessageListener('Shumway:Child:refreshSettings', updateSettings);
removeMessageListener('Shumway:Child:shutdown', shutdownListener);
shutdown();
});
}
})();

Просмотреть файл

@ -0,0 +1,98 @@
/*
* Copyright 2014 Mozilla Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
Components.utils.import('resource://gre/modules/Services.jsm');
Components.utils.import('chrome://shumway/content/SpecialInflate.jsm');
Components.utils.import('chrome://shumway/content/RtmpUtils.jsm');
var externalInterfaceWrapper = {
callback: function (call) {
if (!shumwayComAdapter.onExternalCallback) {
return undefined;
}
return shumwayComAdapter.onExternalCallback(
Components.utils.cloneInto(JSON.parse(call), content));
}
};
// The object allows resending of external interface, clipboard and other
// control messages between unprivileged content and ShumwayStreamConverter.
var shumwayComAdapter;
function sendMessage(action, data, sync, callbackCookie) {
var detail = {action: action, data: data, sync: sync};
if (callbackCookie !== undefined) {
detail.callback = true;
detail.cookie = callbackCookie;
}
if (!sync) {
sendAsyncMessage('Shumway:message', detail);
return;
}
var result = sendSyncMessage('Shumway:message', detail);
return Components.utils.cloneInto(result, content);
}
addMessageListener('Shumway:init', function (message) {
sendAsyncMessage('Shumway:running', {}, {
externalInterface: externalInterfaceWrapper
});
// Exposing ShumwayCom object/adapter to the unprivileged content -- setting
// up Xray wrappers.
shumwayComAdapter = Components.utils.createObjectIn(content, {defineAs: 'ShumwayCom'});
Components.utils.exportFunction(sendMessage, shumwayComAdapter, {defineAs: 'sendMessage'});
Object.defineProperties(shumwayComAdapter, {
onLoadFileCallback: { value: null, writable: true },
onExternalCallback: { value: null, writable: true },
onMessageCallback: { value: null, writable: true }
});
Components.utils.makeObjectPropsNormal(shumwayComAdapter);
// Exposing createSpecialInflate function for DEFLATE stream decoding using
// Gecko API.
if (SpecialInflateUtils.isSpecialInflateEnabled) {
Components.utils.exportFunction(function () {
return SpecialInflateUtils.createWrappedSpecialInflate(content);
}, content, {defineAs: 'createSpecialInflate'});
}
if (RtmpUtils.isRtmpEnabled) {
Components.utils.exportFunction(function (params) {
return RtmpUtils.createSocket(content, params);
}, content, {defineAs: 'createRtmpSocket'});
Components.utils.exportFunction(function () {
return RtmpUtils.createXHR(content);
}, content, {defineAs: 'createRtmpXHR'});
}
content.wrappedJSObject.runViewer();
});
addMessageListener('Shumway:loadFile', function (message) {
if (!shumwayComAdapter.onLoadFileCallback) {
return;
}
shumwayComAdapter.onLoadFileCallback(Components.utils.cloneInto(message.data, content));
});
addMessageListener('Shumway:messageCallback', function (message) {
if (!shumwayComAdapter.onMessageCallback) {
return;
}
shumwayComAdapter.onMessageCallback(message.data.cookie,
Components.utils.cloneInto(message.data.response, content));
});

Просмотреть файл

@ -0,0 +1,46 @@
<!DOCTYPE html>
<!--
Copyright 2013 Mozilla Foundation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<style>
html, body {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
overflow: hidden;
background-color: transparent;
}
iframe {
position:fixed !important;
left:0;top:0;bottom:0;right:0;
overflow: hidden;
line-height: 0;
border: 0px none;
}
</style>
</head>
<body>
<iframe id="viewer" src="resource://shumway/web/viewer.html" width="100%" height="100%" mozbrowser remote="true"></iframe>
<script src="chrome://shumway/content/viewerWrapper.js"></script>
</body>
</html>

Просмотреть файл

@ -0,0 +1,145 @@
/*
* Copyright 2014 Mozilla Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
window.notifyShumwayMessage = function (detail) { };
window.onExternalCallback = null;
window.onMessageCallback = null;
window.onLoadFileCallback = null;
var viewer = document.getElementById('viewer'), onLoaded;
var promise = new Promise(function (resolve) {
onLoaded = resolve;
});
viewer.addEventListener('load', function () {
onLoaded(false);
});
viewer.addEventListener('mozbrowserloadend', function () {
onLoaded(true);
});
Components.utils.import('chrome://shumway/content/SpecialInflate.jsm');
Components.utils.import('chrome://shumway/content/RtmpUtils.jsm');
function runViewer() {
function handler() {
function sendMessage(action, data, sync, callbackCookie) {
var detail = {action: action, data: data, sync: sync};
if (callbackCookie !== undefined) {
detail.callback = true;
detail.cookie = callbackCookie;
}
var result = window.notifyShumwayMessage(detail);
return Components.utils.cloneInto(result, childWindow);
}
var childWindow = viewer.contentWindow.wrappedJSObject;
// Exposing ShumwayCom object/adapter to the unprivileged content -- setting
// up Xray wrappers. This allows resending of external interface, clipboard
// and other control messages between unprivileged content and
// ShumwayStreamConverter.
var shumwayComAdapter = Components.utils.createObjectIn(childWindow, {defineAs: 'ShumwayCom'});
Components.utils.exportFunction(sendMessage, shumwayComAdapter, {defineAs: 'sendMessage'});
Object.defineProperties(shumwayComAdapter, {
onLoadFileCallback: { value: null, writable: true },
onExternalCallback: { value: null, writable: true },
onMessageCallback: { value: null, writable: true }
});
Components.utils.makeObjectPropsNormal(shumwayComAdapter);
// Exposing createSpecialInflate function for DEFLATE stream decoding using
// Gecko API.
if (SpecialInflateUtils.isSpecialInflateEnabled) {
Components.utils.exportFunction(function () {
return SpecialInflateUtils.createWrappedSpecialInflate(childWindow);
}, childWindow, {defineAs: 'createSpecialInflate'});
}
if (RtmpUtils.isRtmpEnabled) {
Components.utils.exportFunction(function (params) {
return RtmpUtils.createSocket(childWindow, params);
}, childWindow, {defineAs: 'createRtmpSocket'});
Components.utils.exportFunction(function () {
return RtmpUtils.createXHR(childWindow);
}, childWindow, {defineAs: 'createRtmpXHR'});
}
window.onExternalCallback = function (call) {
return shumwayComAdapter.onExternalCallback(Components.utils.cloneInto(call, childWindow));
};
window.onMessageCallback = function (response) {
shumwayComAdapter.onMessageCallback(Components.utils.cloneInto(response, childWindow));
};
window.onLoadFileCallback = function (args) {
shumwayComAdapter.onLoadFileCallback(Components.utils.cloneInto(args, childWindow));
};
childWindow.runViewer();
}
function handlerOOP() {
var frameLoader = viewer.QueryInterface(Components.interfaces.nsIFrameLoaderOwner).frameLoader;
var messageManager = frameLoader.messageManager;
messageManager.loadFrameScript('chrome://shumway/content/content.js', false);
var externalInterface;
messageManager.addMessageListener('Shumway:running', function (message) {
externalInterface = message.objects.externalInterface;
});
messageManager.addMessageListener('Shumway:message', function (message) {
var detail = {
action: message.data.action,
data: message.data.data,
sync: message.data.sync
};
if (message.data.callback) {
detail.callback = true;
detail.cookie = message.data.cookie;
}
return window.notifyShumwayMessage(detail);
});
window.onExternalCallback = function (call) {
return externalInterface.callback(JSON.stringify(call));
};
window.onMessageCallback = function (response) {
messageManager.sendAsyncMessage('Shumway:messageCallback', {
cookie: response.cookie,
response: response.response
});
};
window.onLoadFileCallback = function (args) {
messageManager.sendAsyncMessage('Shumway:loadFile', args);
};
messageManager.sendAsyncMessage('Shumway:init', {});
}
promise.then(function (oop) {
if (oop) {
handlerOOP();
} else {
handler();
}
});
}

Просмотреть файл

@ -0,0 +1,95 @@
/*
* Copyright 2014 Mozilla Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
'use strict';
var EXPORTED_SYMBOLS = ['ShumwayBootstrapUtils'];
const PREF_PREFIX = 'shumway.';
const PREF_IGNORE_CTP = PREF_PREFIX + 'ignoreCTP';
const SWF_CONTENT_TYPE = 'application/x-shockwave-flash';
let Cc = Components.classes;
let Ci = Components.interfaces;
let Cm = Components.manager;
let Cu = Components.utils;
Cu.import('resource://gre/modules/XPCOMUtils.jsm');
Cu.import('resource://gre/modules/Services.jsm');
Cu.import('resource://shumway/ShumwayStreamConverter.jsm');
let Ph = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost);
let registerOverlayPreview = 'registerPlayPreviewMimeType' in Ph;
function getBoolPref(pref, def) {
try {
return Services.prefs.getBoolPref(pref);
} catch (ex) {
return def;
}
}
function log(str) {
dump(str + '\n');
}
// Register/unregister a constructor as a factory.
function Factory() {}
Factory.prototype = {
register: function register(targetConstructor) {
var proto = targetConstructor.prototype;
this._classID = proto.classID;
var factory = XPCOMUtils._getFactory(targetConstructor);
this._factory = factory;
var registrar = Cm.QueryInterface(Ci.nsIComponentRegistrar);
registrar.registerFactory(proto.classID, proto.classDescription,
proto.contractID, factory);
},
unregister: function unregister() {
var registrar = Cm.QueryInterface(Ci.nsIComponentRegistrar);
registrar.unregisterFactory(this._classID, this._factory);
}
};
let converterFactory = new Factory();
let overlayConverterFactory = new Factory();
var ShumwayBootstrapUtils = {
register: function () {
// Register the components.
converterFactory.register(ShumwayStreamConverter);
overlayConverterFactory.register(ShumwayStreamOverlayConverter);
if (registerOverlayPreview) {
var ignoreCTP = getBoolPref(PREF_IGNORE_CTP, true);
Ph.registerPlayPreviewMimeType(SWF_CONTENT_TYPE, ignoreCTP);
}
},
unregister: function () {
// Remove the contract/component.
converterFactory.unregister();
overlayConverterFactory.unregister();
if (registerOverlayPreview) {
Ph.unregisterPlayPreviewMimeType(SWF_CONTENT_TYPE);
}
}
};

Просмотреть файл

@ -184,9 +184,17 @@ function fetchPolicyFile(url, cache, callback) {
xhr.send(null);
}
function isContentWindowPrivate(win) {
if (!('isContentWindowPrivate' in PrivateBrowsingUtils)) {
return PrivateBrowsingUtils.isWindowPrivate(win);
}
return PrivateBrowsingUtils.isContentWindowPrivate(win);
}
function isShumwayEnabledFor(actions) {
// disabled for PrivateBrowsing windows
if (PrivateBrowsingUtils.isWindowPrivate(actions.window)) {
if (isContentWindowPrivate(actions.window) &&
!getBoolPref('shumway.enableForPrivate', false)) {
return false;
}
// disabled if embed tag specifies shumwaymode (for testing purpose)
@ -212,13 +220,15 @@ function isShumwayEnabledFor(actions) {
function getVersionInfo() {
var deferred = Promise.defer();
var versionInfo = {
geckoMstone : 'unknown',
version: 'unknown',
geckoBuildID: 'unknown',
shumwayVersion: 'unknown'
};
try {
versionInfo.geckoMstone = Services.prefs.getCharPref('gecko.mstone');
versionInfo.geckoBuildID = Services.prefs.getCharPref('gecko.buildID');
var appInfo = Components.classes["@mozilla.org/xre/app-info;1"]
.getService(Components.interfaces.nsIXULAppInfo);
versionInfo.geckoVersion = appInfo.version;
versionInfo.geckoBuildID = appInfo.appBuildID;
} catch (e) {
log('Error encountered while getting platform version info:', e);
}
@ -275,11 +285,11 @@ ChromeActions.prototype = {
return getBoolPref(data.pref, data.def);
},
getCompilerSettings: function getCompilerSettings() {
return JSON.stringify({
return {
appCompiler: getBoolPref('shumway.appCompiler', true),
sysCompiler: getBoolPref('shumway.sysCompiler', false),
verifier: getBoolPref('shumway.verifier', true)
});
};
},
addProfilerMarker: function (marker) {
if ('nsIProfiler' in Ci) {
@ -288,14 +298,14 @@ ChromeActions.prototype = {
}
},
getPluginParams: function getPluginParams() {
return JSON.stringify({
return {
url: this.url,
baseUrl : this.baseUrl,
movieParams: this.movieParams,
objectParams: this.objectParams,
isOverlay: this.isOverlay,
isPausedAtStart: this.isPausedAtStart
});
};
},
_canDownloadFile: function canDownloadFile(data, callback) {
var url = data.url, checkPolicyFile = data.checkPolicyFile;
@ -352,6 +362,13 @@ ChromeActions.prototype = {
}.bind(this));
},
loadFile: function loadFile(data) {
function notifyLoadFileListener(data) {
if (!win.wrappedJSObject.onLoadFileCallback) {
return;
}
win.wrappedJSObject.onLoadFileCallback(data);
}
var url = data.url;
var checkPolicyFile = data.checkPolicyFile;
var sessionId = data.sessionId;
@ -381,8 +398,8 @@ ChromeActions.prototype = {
xhr.onprogress = function (e) {
var position = e.loaded;
var data = new Uint8Array(xhr.response);
win.postMessage({callback:"loadFile", sessionId: sessionId, topic: "progress",
array: data, loaded: e.loaded, total: e.total}, "*");
notifyLoadFileListener({callback:"loadFile", sessionId: sessionId,
topic: "progress", array: data, loaded: e.loaded, total: e.total});
lastPosition = position;
if (limit && e.total >= limit) {
xhr.abort();
@ -391,16 +408,15 @@ ChromeActions.prototype = {
xhr.onreadystatechange = function(event) {
if (xhr.readyState === 4) {
if (xhr.status !== 200 && xhr.status !== 0) {
win.postMessage({callback:"loadFile", sessionId: sessionId, topic: "error",
error: xhr.statusText}, "*");
notifyLoadFileListener({callback:"loadFile", sessionId: sessionId, topic: "error", error: xhr.statusText});
}
win.postMessage({callback:"loadFile", sessionId: sessionId, topic: "close"}, "*");
notifyLoadFileListener({callback:"loadFile", sessionId: sessionId, topic: "close"});
}
};
if (mimeType)
xhr.setRequestHeader("Content-Type", mimeType);
xhr.send(postData);
win.postMessage({callback:"loadFile", sessionId: sessionId, topic: "open"}, "*");
notifyLoadFileListener({callback:"loadFile", sessionId: sessionId, topic: "open"});
};
this._canDownloadFile({url: url, checkPolicyFile: checkPolicyFile}, function (data) {
@ -408,28 +424,65 @@ ChromeActions.prototype = {
performXHR();
} else {
log("data access id prohibited to " + url + " from " + baseUrl);
win.postMessage({callback:"loadFile", sessionId: sessionId, topic: "error",
error: "only original swf file or file from the same origin loading supported"}, "*");
notifyLoadFileListener({callback:"loadFile", sessionId: sessionId, topic: "error",
error: "only original swf file or file from the same origin loading supported"});
}
});
},
navigateTo: function (data) {
var embedTag = this.embedTag.wrappedJSObject;
var window = embedTag ? embedTag.ownerDocument.defaultView : this.window;
window.open(data.url, data.target || '_self');
},
fallback: function(automatic) {
automatic = !!automatic;
fallbackToNativePlugin(this.window, !automatic, automatic);
},
setClipboard: function (data) {
userInput: function() {
var win = this.window;
var winUtils = win.QueryInterface(Components.interfaces.nsIInterfaceRequestor).
getInterface(Components.interfaces.nsIDOMWindowUtils);
if (winUtils.isHandlingUserInput) {
this.lastUserInput = Date.now();
}
},
isUserInputInProgress: function () {
// TODO userInput does not work for OOP
if (!getBoolPref('shumway.userInputSecurity', true)) {
return true;
}
// We don't trust our Shumway non-privileged code just yet to verify the
// user input -- using monitorUserInput function below to track that.
if (typeof data !== 'string' ||
(Date.now() - this.lastUserInput) > MAX_USER_INPUT_TIMEOUT) {
return;
// user input -- using userInput function above to track that.
if ((Date.now() - this.lastUserInput) > MAX_USER_INPUT_TIMEOUT) {
return false;
}
// TODO other security checks?
return true;
},
setClipboard: function (data) {
if (typeof data !== 'string' || !this.isUserInputInProgress()) {
return;
}
let clipboard = Cc["@mozilla.org/widget/clipboardhelper;1"]
.getService(Ci.nsIClipboardHelper);
clipboard.copyString(data);
},
setFullscreen: function (enabled) {
enabled = !!enabled;
if (!this.isUserInputInProgress()) {
return;
}
var target = this.embedTag || this.document.body;
if (enabled) {
target.mozRequestFullScreen();
} else {
target.ownerDocument.mozCancelFullScreen();
}
},
endActivation: function () {
if (ActivationQueue.currentNonActive === this) {
ActivationQueue.activateNext();
@ -487,20 +540,15 @@ ChromeActions.prototype = {
getVersionInfo().then(function (versions) {
params.versions = versions;
}).then(function () {
params.ffbuild = encodeURIComponent(params.versions.geckoMstone +
' (' + params.versions.geckoBuildID + ')');
params.shubuild = encodeURIComponent(params.versions.shumwayVersion);
params.exceptions = encodeURIComponent(exceptions);
var comment = '%2B%2B%2B This bug was initially via the problem reporting functionality in ' +
'Shumway %2B%2B%2B%0A%0A' +
'Please add any further information that you deem helpful here:%0A%0A%0A' +
'----------------------%0A%0A' +
'Technical Information:%0A' +
'Firefox version: ' + params.ffbuild + '%0A' +
'Shumway version: ' + params.shubuild;
url = url.split('{comment}').join(comment);
//this.window.openDialog('chrome://browser/content', '_blank', 'all,dialog=no', url);
dump(111);
var ffbuild = params.versions.geckoVersion + ' (' + params.versions.geckoBuildID + ')';
//params.exceptions = encodeURIComponent(exceptions);
var comment = '+++ Initially filed via the problem reporting functionality in Shumway +++\n' +
'Please add any further information that you deem helpful here:\n\n\n\n' +
'----------------------\n\n' +
'Technical Information:\n' +
'Firefox version: ' + ffbuild + '\n' +
'Shumway version: ' + params.versions.shumwayVersion;
url = url.split('{comment}').join(encodeURIComponent(comment));
this.window.open(url);
}.bind(this));
},
@ -517,8 +565,7 @@ ChromeActions.prototype = {
return;
this.externalComInitialized = true;
var eventTarget = this.window.document;
initExternalCom(parentWindow, embedTag, eventTarget);
initExternalCom(parentWindow, embedTag, this.window);
return;
case 'getId':
return embedTag.id;
@ -537,33 +584,15 @@ ChromeActions.prototype = {
}
};
function monitorUserInput(actions) {
function notifyUserInput() {
var win = actions.window;
var winUtils = win.QueryInterface(Components.interfaces.nsIInterfaceRequestor).
getInterface(Components.interfaces.nsIDOMWindowUtils);
if (winUtils.isHandlingUserInput) {
actions.lastUserInput = Date.now();
}
}
var document = actions.document;
document.addEventListener('mousedown', notifyUserInput, false);
document.addEventListener('mouseup', notifyUserInput, false);
document.addEventListener('keydown', notifyUserInput, false);
document.addEventListener('keyup', notifyUserInput, false);
}
// Event listener to trigger chrome privedged code.
function RequestListener(actions) {
this.actions = actions;
}
// Receive an event and synchronously or asynchronously responds.
RequestListener.prototype.receive = function(event) {
var message = event.target;
var action = event.detail.action;
var data = event.detail.data;
var sync = event.detail.sync;
RequestListener.prototype.receive = function(detail) {
var action = detail.action;
var data = detail.data;
var sync = detail.sync;
var actions = this.actions;
if (!(action in actions)) {
log('Unknown action: ' + action);
@ -571,30 +600,23 @@ RequestListener.prototype.receive = function(event) {
}
if (sync) {
var response = actions[action].call(this.actions, data);
event.detail.response = response;
} else {
var response;
if (event.detail.callback) {
var cookie = event.detail.cookie;
response = function sendResponse(response) {
var doc = actions.document;
try {
var listener = doc.createEvent('CustomEvent');
listener.initCustomEvent('shumway.response', true, false,
makeContentReadable({
response: response,
cookie: cookie
}, doc.defaultView));
return message.dispatchEvent(listener);
} catch (e) {
// doc is no longer accessible because the requestor is already
// gone. unloaded content cannot receive the response anyway.
}
};
}
actions[action].call(this.actions, data, response);
return response === undefined ? undefined : JSON.stringify(response);
}
var responseCallback;
if (detail.callback) {
var cookie = detail.cookie;
response = function sendResponse(response) {
var win = actions.window;
if (win.wrappedJSObject.onMessageCallback) {
win.wrappedJSObject.onMessageCallback({
response: response === undefined ? undefined : JSON.stringify(response),
cookie: cookie
});
}
};
}
actions[action].call(this.actions, data, responseCallback);
};
var ActivationQueue = {
@ -696,7 +718,7 @@ var ActivationQueue = {
}
};
function activateShumwayScripts(window, preview) {
function activateShumwayScripts(window, requestListener) {
function loadScripts(scripts, callback) {
function loadScript(i) {
if (i >= scripts.length) {
@ -717,14 +739,12 @@ function activateShumwayScripts(window, preview) {
}
function initScripts() {
loadScripts(['resource://shumway/shumway.gfx.js',
'resource://shumway/web/viewer.js'], function () {
window.wrappedJSObject.runViewer();
});
window.wrappedJSObject.notifyShumwayMessage = function () {
return requestListener.receive.apply(requestListener, arguments);
};
window.wrappedJSObject.runViewer();
}
window.wrappedJSObject.SHUMWAY_ROOT = "resource://shumway/";
if (window.document.readyState === "interactive" ||
window.document.readyState === "complete") {
initScripts();
@ -733,7 +753,7 @@ function activateShumwayScripts(window, preview) {
}
}
function initExternalCom(wrappedWindow, wrappedObject, targetDocument) {
function initExternalCom(wrappedWindow, wrappedObject, targetWindow) {
if (!wrappedWindow.__flash__initialized) {
wrappedWindow.__flash__initialized = true;
wrappedWindow.__flash__toXML = function __flash__toXML(obj) {
@ -777,18 +797,15 @@ function initExternalCom(wrappedWindow, wrappedObject, targetDocument) {
}
wrappedObject.__flash__registerCallback = function (functionName) {
wrappedWindow.console.log('__flash__registerCallback: ' + functionName);
this[functionName] = function () {
Components.utils.exportFunction(function () {
var args = Array.prototype.slice.call(arguments, 0);
wrappedWindow.console.log('__flash__callIn: ' + functionName);
var e = targetDocument.createEvent('CustomEvent');
e.initCustomEvent('shumway.remote', true, false, makeContentReadable({
functionName: functionName,
args: args,
result: undefined
}, targetDocument.defaultView));
targetDocument.dispatchEvent(e);
return e.detail.result;
};
var result;
if (targetWindow.wrappedJSObject.onExternalCallback) {
result = targetWindow.wrappedJSObject.onExternalCallback({functionName: functionName, args: args});
}
return wrappedWindow.eval(result);
}, this, { defineAs: functionName });
};
wrappedObject.__flash__unregisterCallback = function (functionName) {
wrappedWindow.console.log('__flash__unregisterCallback: ' + functionName);
@ -849,6 +866,12 @@ ShumwayStreamConverterBase.prototype = {
}
if (isOverlay) {
// HACK For Facebook, CSS embed tag rescaling -- iframe (our overlay)
// has no styling in document. Shall removed with jsplugins.
for (var child = window.frameElement; child !== element; child = child.parentNode) {
child.setAttribute('style', 'max-width: 100%; max-height: 100%');
}
// Checking if overlay is a proper PlayPreview overlay.
for (var i = 0; i < element.children.length; i++) {
if (element.children[i] === containerElement) {
@ -860,7 +883,7 @@ ShumwayStreamConverterBase.prototype = {
if (element) {
// Getting absolute URL from the EMBED tag
url = element.srcURI.spec;
url = element.srcURI && element.srcURI.spec;
pageUrl = element.ownerDocument.location.href; // proper page url?
@ -961,14 +984,8 @@ ShumwayStreamConverterBase.prototype = {
var originalURI = aRequest.URI;
// checking if the plug-in shall be run in simple mode
var isSimpleMode = originalURI.spec === EXPECTED_PLAYPREVIEW_URI_PREFIX &&
getBoolPref('shumway.simpleMode', false);
// Create a new channel that loads the viewer as a resource.
var viewerUrl = isSimpleMode ?
'resource://shumway/web/simple.html' :
'resource://shumway/web/viewer.html';
// Create a new channel that loads the viewer as a chrome resource.
var viewerUrl = 'chrome://shumway/content/viewer.wrapper.html';
var channel = Services.io.newChannel(viewerUrl, null, null);
var converter = this;
@ -1008,17 +1025,13 @@ ShumwayStreamConverterBase.prototype = {
ShumwayTelemetry.onPageIndex(0);
}
actions.activationCallback = function(domWindow, isSimpleMode) {
delete this.activationCallback;
activateShumwayScripts(domWindow, isSimpleMode);
}.bind(actions, domWindow, isSimpleMode);
ActivationQueue.enqueue(actions);
let requestListener = new RequestListener(actions);
domWindow.addEventListener('shumway.message', function(event) {
requestListener.receive(event);
}, false, true);
monitorUserInput(actions);
actions.activationCallback = function(domWindow, requestListener) {
delete this.activationCallback;
activateShumwayScripts(domWindow, requestListener);
}.bind(actions, domWindow, requestListener);
ActivationQueue.enqueue(actions);
listener.onStopRequest(aRequest, context, statusCode);
}
@ -1028,12 +1041,11 @@ ShumwayStreamConverterBase.prototype = {
channel.originalURI = aRequest.URI;
channel.loadGroup = aRequest.loadGroup;
// We can use resource principal when data is fetched by the chrome
// e.g. useful for NoScript
// We can use all powerful principal: we are opening chrome:// web page,
// which will need lots of permission.
var securityManager = Cc['@mozilla.org/scriptsecuritymanager;1']
.getService(Ci.nsIScriptSecurityManager);
var uri = Services.io.newURI(viewerUrl, null, null);
var resourcePrincipal = securityManager.getNoAppCodebasePrincipal(uri);
var resourcePrincipal = securityManager.getSystemPrincipal();
aRequest.owner = resourcePrincipal;
channel.asyncOpen(proxy, aContext);
},

Просмотреть файл

@ -15,12 +15,8 @@
var EXPORTED_SYMBOLS = ["ShumwayUtils"];
const RESOURCE_NAME = 'shumway';
const EXT_PREFIX = 'shumway@research.mozilla.org';
const SWF_CONTENT_TYPE = 'application/x-shockwave-flash';
const PREF_PREFIX = 'shumway.';
const PREF_DISABLED = PREF_PREFIX + 'disabled';
const PREF_IGNORE_CTP = PREF_PREFIX + 'ignoreCTP';
let Cc = Components.classes;
let Ci = Components.interfaces;
@ -30,14 +26,6 @@ let Cu = Components.utils;
Cu.import('resource://gre/modules/XPCOMUtils.jsm');
Cu.import('resource://gre/modules/Services.jsm');
let Svc = {};
XPCOMUtils.defineLazyServiceGetter(Svc, 'mime',
'@mozilla.org/mime;1',
'nsIMIMEService');
XPCOMUtils.defineLazyServiceGetter(Svc, 'pluginHost',
'@mozilla.org/plugin/host;1',
'nsIPluginHost');
function getBoolPref(pref, def) {
try {
return Services.prefs.getBoolPref(pref);
@ -50,31 +38,6 @@ function log(str) {
dump(str + '\n');
}
// Register/unregister a constructor as a factory.
function Factory() {}
Factory.prototype = {
register: function register(targetConstructor) {
var proto = targetConstructor.prototype;
this._classID = proto.classID;
var factory = XPCOMUtils._getFactory(targetConstructor);
this._factory = factory;
var registrar = Cm.QueryInterface(Ci.nsIComponentRegistrar);
registrar.registerFactory(proto.classID, proto.classDescription,
proto.contractID, factory);
},
unregister: function unregister() {
var registrar = Cm.QueryInterface(Ci.nsIComponentRegistrar);
registrar.unregisterFactory(this._classID, this._factory);
this._factory = null;
}
};
let converterFactory = new Factory();
let overlayConverterFactory = new Factory();
let ShumwayUtils = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver]),
_registered: false,
@ -85,6 +48,10 @@ let ShumwayUtils = {
else
this._ensureUnregistered();
Cc["@mozilla.org/parentprocessmessagemanager;1"]
.getService(Ci.nsIMessageBroadcaster)
.addMessageListener('Shumway:Chrome:isEnabled', this);
// Listen for when shumway is completely disabled.
Services.prefs.addObserver(PREF_DISABLED, this, false);
},
@ -96,6 +63,13 @@ let ShumwayUtils = {
else
this._ensureUnregistered();
},
receiveMessage: function(message) {
switch (message.name) {
case 'Shumway:Chrome:isEnabled':
return this.enabled;
}
},
/**
* shumway is only enabled if the global switch enabling is true.
@ -110,17 +84,16 @@ let ShumwayUtils = {
return;
// Load the component and register it.
Cu.import('resource://shumway/ShumwayStreamConverter.jsm');
converterFactory.register(ShumwayStreamConverter);
overlayConverterFactory.register(ShumwayStreamOverlayConverter);
var ignoreCTP = getBoolPref(PREF_IGNORE_CTP, true);
Svc.pluginHost.registerPlayPreviewMimeType(SWF_CONTENT_TYPE, ignoreCTP);
Cu.import('resource://shumway/ShumwayBootstrapUtils.jsm');
ShumwayBootstrapUtils.register();
this._registered = true;
log('Shumway is registered');
let globalMM = Cc['@mozilla.org/globalmessagemanager;1']
.getService(Ci.nsIFrameScriptLoader);
globalMM.broadcastAsyncMessage('Shumway:Child:refreshSettings');
},
_ensureUnregistered: function _ensureUnregistered() {
@ -128,14 +101,15 @@ let ShumwayUtils = {
return;
// Remove the contract/component.
converterFactory.unregister();
overlayConverterFactory.unregister();
Cu.unload('resource://shumway/ShumwayStreamConverter.jsm');
Svc.pluginHost.unregisterPlayPreviewMimeType(SWF_CONTENT_TYPE);
ShumwayBootstrapUtils.unregister();
Cu.unload('resource://shumway/ShumwayBootstrapUtils.jsm');
this._registered = false;
log('Shumway is unregistered');
let globalMM = Cc['@mozilla.org/globalmessagemanager;1']
.getService(Ci.nsIFrameScriptLoader);
globalMM.broadcastAsyncMessage('Shumway:Child:refreshSettings');
}
};

Двоичный файл не отображается.

Двоичный файл не отображается.

Просмотреть файл

@ -1,127 +0,0 @@
/*
precision mediump float;
varying vec4 vColor;
uniform sampler2D uSampler;
varying vec2 vCoordinate;
out vec4 FragmentColor;
uniform float offset[5] = float[]( 0.0, 1.0, 2.0, 3.0, 4.0 );
uniform float weight[5] = float[]( 0.2270270270, 0.1945945946, 0.1216216216,
0.0540540541, 0.0162162162 );
void main(void)
{
FragmentColor = texture2D( uSampler, vec2(vCoordinate) * weight[0];
for (int i=1; i<5; i++) {
FragmentColor +=
texture2D( uSampler, ( vec2(gl_FragCoord)+vec2(0.0, offset[i]) )/1024.0 )
* weight[i];
FragmentColor +=
texture2D( uSampler, ( vec2(gl_FragCoord)-vec2(0.0, offset[i]) )/1024.0 )
* weight[i];
}
}
*/
/*
precision mediump float;
varying vec4 vColor;
uniform sampler2D uSampler;
varying vec2 vCoordinate;
void main() {
const int sampleRadius = 16;
const int samples = sampleRadius * 2 + 1;
float dy = 1.0 / 512.0;
vec4 sample = vec4(0, 0, 0, 0);
for (int i = -sampleRadius; i <= sampleRadius; i++) {
sample += texture2D(uSampler, vCoordinate + vec2(0, float(i) * dy));
}
gl_FragColor = sample / float(samples);
// gl_FragColor = texture2D(uSampler, vCoordinate);
}
*/
precision mediump float;
varying vec4 vColor;
uniform sampler2D uSampler;
varying vec2 vCoordinate;
void main() {
vec4 sum = vec4(0.0);
float blur = 1.0 / 512.0 * 1.0;
sum += texture2D(uSampler, vec2(vCoordinate.x - 4.0 * blur, vCoordinate.y)) * 0.05;
sum += texture2D(uSampler, vec2(vCoordinate.x - 3.0 * blur, vCoordinate.y)) * 0.09;
sum += texture2D(uSampler, vec2(vCoordinate.x - 2.0 * blur, vCoordinate.y)) * 0.12;
sum += texture2D(uSampler, vec2(vCoordinate.x - blur, vCoordinate.y)) * 0.15;
sum += texture2D(uSampler, vec2(vCoordinate.x, vCoordinate.y)) * 0.16;
sum += texture2D(uSampler, vec2(vCoordinate.x + blur, vCoordinate.y)) * 0.15;
sum += texture2D(uSampler, vec2(vCoordinate.x + 2.0 * blur, vCoordinate.y)) * 0.12;
sum += texture2D(uSampler, vec2(vCoordinate.x + 3.0 * blur, vCoordinate.y)) * 0.09;
sum += texture2D(uSampler, vec2(vCoordinate.x + 4.0 * blur, vCoordinate.y)) * 0.05;
gl_FragColor = sum;
// gl_FragColor = texture2D(uSampler, vCoordinate);
}
/*
precision mediump float;
varying vec4 vColor;
uniform sampler2D uSampler;
varying vec2 vCoordinate;
void main() {
vec4 sum = vec4(0.0);
float blur = 0.1;
sum += texture2D(uSampler, vec2(vCoordinate.x - 4.0 * blur, vCoordinate.y)) * 0.05;
sum += texture2D(uSampler, vec2(vCoordinate.x - 3.0 * blur, vCoordinate.y)) * 0.09;
sum += texture2D(uSampler, vec2(vCoordinate.x - 2.0 * blur, vCoordinate.y)) * 0.12;
sum += texture2D(uSampler, vec2(vCoordinate.x - blur, vCoordinate.y)) * 0.15;
sum += texture2D(uSampler, vec2(vCoordinate.x, vCoordinate.y)) * 0.16;
sum += texture2D(uSampler, vec2(vCoordinate.x + blur, vCoordinate.y)) * 0.15;
sum += texture2D(uSampler, vec2(vCoordinate.x + 2.0 * blur, vCoordinate.y)) * 0.12;
sum += texture2D(uSampler, vec2(vCoordinate.x + 3.0 * blur, vCoordinate.y)) * 0.09;
sum += texture2D(uSampler, vec2(vCoordinate.x + 4.0 * blur, vCoordinate.y)) * 0.05;
gl_FragColor = sum;
// gl_FragColor = texture2D(uSampler, vCoordinate);
}
*/
/*
precision mediump float;
varying vec4 vColor;
uniform sampler2D uSampler;
varying vec2 vCoordinate;
void main() {
gl_FragColor = texture2D(uSampler, vCoordinate);
}
*/
/*
precision mediump float;
varying vec2 vCoordinate;
varying float vColor;
uniform float blur;
uniform sampler2D uSampler;
void main(void) {
vec4 sum = vec4(0.0);
sum += texture2D(uSampler, vec2(vCoordinate.x - 4.0*blur, vCoordinate.y)) * 0.05;
sum += texture2D(uSampler, vec2(vCoordinate.x - 3.0*blur, vCoordinate.y)) * 0.09;
sum += texture2D(uSampler, vec2(vCoordinate.x - 2.0*blur, vCoordinate.y)) * 0.12;
sum += texture2D(uSampler, vec2(vCoordinate.x - blur, vCoordinate.y)) * 0.15;
sum += texture2D(uSampler, vec2(vCoordinate.x, vCoordinate.y)) * 0.16;
sum += texture2D(uSampler, vec2(vCoordinate.x + blur, vCoordinate.y)) * 0.15;
sum += texture2D(uSampler, vec2(vCoordinate.x + 2.0*blur, vCoordinate.y)) * 0.12;
sum += texture2D(uSampler, vec2(vCoordinate.x + 3.0*blur, vCoordinate.y)) * 0.09;
sum += texture2D(uSampler, vec2(vCoordinate.x + 4.0*blur, vCoordinate.y)) * 0.05;
gl_FragColor = sum;
}
*/

Просмотреть файл

@ -1,16 +0,0 @@
precision mediump float;
varying vec4 vColor;
uniform sampler2D uSampler;
varying vec2 vCoordinate;
void main() {
const int sampleRadius = 8;
const int samples = sampleRadius * 2 + 1;
float dx = 0.01;
vec4 sample = vec4(0, 0, 0, 0);
for (int i = -sampleRadius; i <= sampleRadius; i++) {
sample += texture2D(uSampler, vCoordinate + vec2(0, float(i) * dy));
}
gl_FragColor = sample / float(samples);
}

Просмотреть файл

@ -1,19 +0,0 @@
uniform vec2 uResolution;
uniform mat3 uTransformMatrix;
uniform float uZ;
attribute vec2 aPosition;
attribute vec4 aColor;
attribute vec2 aCoordinate;
varying vec4 vColor;
varying vec2 vCoordinate;
void main() {
vec2 position = ((uTransformMatrix * vec3(aPosition, 1.0)).xy / uResolution) * 2.0 - 1.0;
position *= vec2(1.0, -1.0);
// position *= vec2(40.0, -4.0);
gl_Position = vec4(vec3(position, uZ), 1.0);
vColor = aColor;
vCoordinate = aCoordinate;
}

Просмотреть файл

@ -1,18 +0,0 @@
precision mediump float;
uniform vec4 uColor;
varying vec2 vTextureCoordinate;
void main() {
gl_FragColor = uColor;
gl_FragColor = vec4(vTextureCoordinate.x, vTextureCoordinate.y, 0, 0.5);
float u = vTextureCoordinate.x;
float v = vTextureCoordinate.y;
float r = u * u - v;
if (r < 0.0) {
gl_FragColor = vec4(1, 0, 0, 1);
} else {
gl_FragColor = vec4(1, 0, 0, 0.2);
}
}

Просмотреть файл

@ -1,7 +0,0 @@
precision mediump float;
varying vec4 vColor;
void main() {
gl_FragColor = vColor;
}

Просмотреть файл

@ -1,15 +0,0 @@
uniform vec2 uResolution;
uniform mat3 uTransformMatrix;
uniform float uZ;
attribute vec2 aPosition;
attribute vec4 aColor;
varying vec4 vColor;
void main() {
vec2 position = ((uTransformMatrix * vec3(aPosition, 1.0)).xy / uResolution) * 2.0 - 1.0;
position *= vec2(1.0, -1.0);
gl_Position = vec4(vec3(position, uZ), 1.0);
vColor = aColor;
}

Просмотреть файл

@ -1,12 +0,0 @@
precision mediump float;
varying vec4 vColor;
uniform sampler2D uSampler;
varying vec2 vCoordinate;
void main() {
// gl_FragColor = vColor;
// gl_FragColor = vec4(vTextureCoordinate.x, vTextureCoordinate.y, 0, 0.5);
// gl_FragColor = gl_FragColor; // + texture2D(uSampler, vCoordinate);
gl_FragColor = texture2D(uSampler, vCoordinate);
}

Просмотреть файл

@ -1,19 +0,0 @@
uniform vec2 uResolution;
uniform mat3 uTransformMatrix;
uniform float uZ;
attribute vec2 aPosition;
attribute vec4 aColor;
attribute vec2 aCoordinate;
varying vec4 vColor;
varying vec2 vCoordinate;
void main() {
vec2 position = ((uTransformMatrix * vec3(aPosition, 1.0)).xy / uResolution) * 2.0 - 1.0;
position *= vec2(1.0, -1.0);
// position *= vec2(40.0, -4.0);
gl_Position = vec4(vec3(position, uZ), 1.0);
vColor = aColor;
vCoordinate = aCoordinate;
}

Двоичный файл не отображается.

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,2 +1,2 @@
0.9.2970
22f884f
0.9.3693
217e2e2

Просмотреть файл

@ -35,7 +35,7 @@ limitations under the License.
display: none;
}
#stageContainer {
#easelContainer {
position:fixed !important;
left:0;top:0;bottom:0;right:0;
overflow: hidden;
@ -49,7 +49,7 @@ limitations under the License.
#overlay.enabled {
display: block;
position:fixed;
bottom: 0;
top: 0;
right: 0;
}
@ -58,7 +58,7 @@ limitations under the License.
width: 70px; height: 16px;
padding: 8px 4px 4px;
color: white;
background-color: rgba(0, 0, 0, 0.62);
background-color: rgba(218, 56, 7, 0.63);
font: bold 10px sans-serif;
text-align: center;
text-decoration: none;
@ -100,7 +100,7 @@ limitations under the License.
<body contextmenu="shumwayMenu">
<iframe id="playerWindow" width="9" height="9" src=""></iframe>
<div id="stageContainer"></div>
<div id="easelContainer"></div>
<section>
<div id="overlay">
<a id="fallback" href="#">Shumway <span class="icon">&times;</span></a>
@ -114,5 +114,8 @@ limitations under the License.
<menuitem label="About Shumway" id="aboutMenu"></menuitem>
</menu>
</section>
<script src='resource://shumway/shumway.gfx.js'></script>
<script src='resource://shumway/web/viewer.js'></script>
</body>
</html>

Просмотреть файл

@ -27,11 +27,8 @@ var FirefoxCom = (function FirefoxComClosure() {
* @return {*} The response.
*/
requestSync: function(action, data) {
var e = document.createEvent('CustomEvent');
e.initCustomEvent('shumway.message', true, false,
{action: action, data: data, sync: true});
document.dispatchEvent(e);
return e.detail.response;
var result = String(ShumwayCom.sendMessage(action, data, true, undefined));
return result !== 'undefined' ? JSON.parse(result) : undefined;
},
/**
* Creates an event that the extension is listening for and will
@ -42,38 +39,45 @@ var FirefoxCom = (function FirefoxComClosure() {
* with one data argument.
*/
request: function(action, data, callback) {
var e = document.createEvent('CustomEvent');
e.initCustomEvent('shumway.message', true, false,
{action: action, data: data, sync: false});
var cookie = undefined;
if (callback) {
if ('nextId' in FirefoxCom.request) {
FirefoxCom.request.nextId = 1;
cookie = "requestId" + (this._nextRequestId++);
if (!ShumwayCom.onMessageCallback) {
ShumwayCom.onMessageCallback = this._notifyMessageCallback.bind(this);
}
var cookie = "requestId" + (FirefoxCom.request.nextId++);
e.detail.cookie = cookie;
e.detail.callback = true;
document.addEventListener('shumway.response', function listener(event) {
if (cookie !== event.detail.cookie)
return;
document.removeEventListener('shumway.response', listener, false);
var response = event.detail.response;
return callback(response);
}, false);
this._requestCallbacks[cookie] = callback;
}
return document.dispatchEvent(e);
ShumwayCom.sendMessage(action, data, false, cookie);
},
_notifyMessageCallback: function (cookie, response) {
var callback = this._requestCallbacks[cookie];
if (!callback) {
return;
}
delete this._requestCallbacks[cookie];
callback(response !== 'undefined' ? JSON.parse(response) : undefined);
},
_nextRequestId: 1,
_requestCallbacks: Object.create(null),
initJS: function (callback) {
FirefoxCom.request('externalCom', {action: 'init'});
document.addEventListener('shumway.remote', function (e) {
e.detail.result = callback(e.detail.functionName, e.detail.args);
}, false);
ShumwayCom.onExternalCallback = function (call) {
return callback(call.functionName, call.args);
};
}
};
})();
function notifyUserInput() {
ShumwayCom.sendMessage('userInput', null, true, undefined);
}
document.addEventListener('mousedown', notifyUserInput, true);
document.addEventListener('mouseup', notifyUserInput, true);
document.addEventListener('keydown', notifyUserInput, true);
document.addEventListener('keyup', notifyUserInput, true);
function fallback() {
FirefoxCom.requestSync('fallback', null)
}
@ -82,13 +86,14 @@ window.print = function(msg) {
console.log(msg);
};
var SHUMWAY_ROOT = "resource://shumway/";
var viewerPlayerglobalInfo = {
abcs: SHUMWAY_ROOT + "playerglobal/playerglobal.abcs",
catalog: SHUMWAY_ROOT + "playerglobal/playerglobal.json"
};
var builtinPath = SHUMWAY_ROOT + "avm2/generated/builtin/builtin.abc";
var avm1Path = SHUMWAY_ROOT + "avm2/generated/avm1lib/avm1lib.abc";
var playerWindow;
var playerWindowLoaded = new Promise(function(resolve) {
@ -101,7 +106,14 @@ var playerWindowLoaded = new Promise(function(resolve) {
});
function runViewer() {
var flashParams = JSON.parse(FirefoxCom.requestSync('getPluginParams', null));
ShumwayCom.onLoadFileCallback = function (data) {
playerWindow.postMessage({
type: "loadFileResponse",
args: data
}, '*');
};
var flashParams = FirefoxCom.requestSync('getPluginParams', null);
movieUrl = flashParams.url;
if (!movieUrl) {
@ -112,6 +124,7 @@ function runViewer() {
movieParams = flashParams.movieParams;
objectParams = flashParams.objectParams;
var baseUrl = flashParams.baseUrl;
var isOverlay = flashParams.isOverlay;
pauseExecution = flashParams.isPausedAtStart;
@ -125,7 +138,7 @@ function runViewer() {
}
playerWindowLoaded.then(function () {
parseSwf(movieUrl, movieParams, objectParams);
parseSwf(movieUrl, baseUrl, movieParams, objectParams);
});
if (isOverlay) {
@ -193,12 +206,6 @@ var movieUrl, movieParams, objectParams;
window.addEventListener("message", function handlerMessage(e) {
var args = e.data;
switch (args.callback) {
case 'loadFile':
playerWindow.postMessage({
type: "loadFileResponse",
args: args
}, '*');
break;
case 'loadFileRequest':
FirefoxCom.request('loadFile', args.data, null);
break;
@ -208,6 +215,9 @@ window.addEventListener("message", function handlerMessage(e) {
case 'setClipboard':
FirefoxCom.request('setClipboard', args.data, null);
break;
case 'navigateTo':
FirefoxCom.request('navigateTo', args.data, null);
break;
case 'started':
document.body.classList.add('started');
break;
@ -232,13 +242,11 @@ function processExternalCommand(command) {
}
}
function parseSwf(url, movieParams, objectParams) {
var compilerSettings = JSON.parse(
FirefoxCom.requestSync('getCompilerSettings', null));
function parseSwf(url, baseUrl, movieParams, objectParams) {
var compilerSettings = FirefoxCom.requestSync('getCompilerSettings', null);
// init misc preferences
var turboMode = FirefoxCom.requestSync('getBoolPref', {pref: 'shumway.turboMode', def: false});
Shumway.GFX.backend.value = FirefoxCom.requestSync('getBoolPref', {pref: 'shumway.webgl', def: false}) ? 1 : 0;
Shumway.GFX.hud.value = FirefoxCom.requestSync('getBoolPref', {pref: 'shumway.hud', def: false});
//forceHidpi.value = FirefoxCom.requestSync('getBoolPref', {pref: 'shumway.force_hidpi', def: false});
//dummyAnimation.value = FirefoxCom.requestSync('getBoolPref', {pref: 'shumway.dummyMode', def: false});
@ -249,22 +257,23 @@ function parseSwf(url, movieParams, objectParams) {
FirefoxCom.request('endActivation', null);
}
var bgcolor;
var backgroundColor;
if (objectParams) {
var m;
if (objectParams.bgcolor && (m = /#([0-9A-F]{6})/i.exec(objectParams.bgcolor))) {
var hexColor = parseInt(m[1], 16);
bgcolor = hexColor << 8 | 0xff;
backgroundColor = hexColor << 8 | 0xff;
}
if (objectParams.wmode === 'transparent') {
bgcolor = 0;
backgroundColor = 0;
}
}
var easel = createEasel(bgcolor);
var easel = createEasel(backgroundColor);
easelHost = new Shumway.GFX.Window.WindowEaselHost(easel, playerWindow, window);
easelHost.processExternalCommand = processExternalCommand;
var displayParameters = easel.getDisplayParameters();
var data = {
type: 'runSwf',
settings: Shumway.Settings.getSettings(),
@ -272,21 +281,21 @@ function parseSwf(url, movieParams, objectParams) {
compilerSettings: compilerSettings,
movieParams: movieParams,
objectParams: objectParams,
displayParameters: displayParameters,
turboMode: turboMode,
bgcolor: bgcolor,
bgcolor: backgroundColor,
url: url,
baseUrl: url
baseUrl: baseUrl || url
}
};
playerWindow.postMessage(data, '*');
}
function createEasel(bgcolor) {
function createEasel(backgroundColor) {
var Stage = Shumway.GFX.Stage;
var Easel = Shumway.GFX.Easel;
var Canvas2DStageRenderer = Shumway.GFX.Canvas2DStageRenderer;
var Canvas2DRenderer = Shumway.GFX.Canvas2DRenderer;
Shumway.GFX.WebGL.SHADER_ROOT = SHUMWAY_ROOT + "gfx/gl/shaders/";
var backend = Shumway.GFX.backend.value | 0;
return new Easel(document.getElementById("stageContainer"), backend, false, bgcolor);
return new Easel(document.getElementById("easelContainer"), false, backgroundColor);
}

Просмотреть файл

@ -24,7 +24,6 @@ var viewerPlayerglobalInfo = {
var avm2Root = SHUMWAY_ROOT + "avm2/";
var builtinPath = avm2Root + "generated/builtin/builtin.abc";
var avm1Path = avm2Root + "generated/avm1lib/avm1lib.abc";
window.print = function(msg) {
console.log(msg);
@ -38,29 +37,32 @@ function runSwfPlayer(flashParams) {
var appMode = compilerSettings.appCompiler ? EXECUTION_MODE.COMPILE : EXECUTION_MODE.INTERPRET;
var asyncLoading = true;
var baseUrl = flashParams.baseUrl;
var movieParams = flashParams.movieParams;
var objectParams = flashParams.objectParams;
var movieUrl = flashParams.url;
Shumway.frameRateOption.value = flashParams.turboMode ? 60 : -1;
Shumway.AVM2.Verifier.enabled.value = compilerSettings.verifier;
Shumway.createAVM2(builtinPath, viewerPlayerglobalInfo, avm1Path, sysMode, appMode, function (avm2) {
Shumway.createAVM2(builtinPath, viewerPlayerglobalInfo, sysMode, appMode, function (avm2) {
function runSWF(file) {
var player = new Shumway.Player.Window.WindowPlayer(window, window.parent);
player.defaultStageColor = flashParams.bgcolor;
player.movieParams = flashParams.movieParams;
player.stageAlign = (objectParams && (objectParams.salign || objectParams.align)) || '';
player.stageScale = (objectParams && objectParams.scale) || 'showall';
player.displayParameters = flashParams.displayParameters;
Shumway.ExternalInterfaceService.instance = player.createExternalInterfaceService();
player.load(file);
}
file = Shumway.FileLoadingService.instance.setBaseUrl(baseUrl);
Shumway.FileLoadingService.instance.setBaseUrl(baseUrl);
if (asyncLoading) {
runSWF(movieUrl);
} else {
new Shumway.BinaryFileReader(movieUrl).readAll(null, function(buffer, error) {
if (!buffer) {
throw "Unable to open the file " + file + ": " + error;
throw "Unable to open the file " + movieUrl + ": " + error;
}
runSWF(movieUrl, buffer);
});
@ -129,32 +131,34 @@ function setupServices() {
};
},
setBaseUrl: function (url) {
var baseUrl;
if (typeof URL !== 'undefined') {
baseUrl = new URL(url, document.location.href).href;
} else {
var a = document.createElement('a');
a.href = url || '#';
a.setAttribute('style', 'display: none;');
document.body.appendChild(a);
baseUrl = a.href;
document.body.removeChild(a);
}
Shumway.FileLoadingService.instance.baseUrl = baseUrl;
return baseUrl;
Shumway.FileLoadingService.instance.baseUrl = url;
},
resolveUrl: function (url) {
if (url.indexOf('://') >= 0) return url;
var base = Shumway.FileLoadingService.instance.baseUrl;
base = base.lastIndexOf('/') >= 0 ? base.substring(0, base.lastIndexOf('/') + 1) : '';
if (url.indexOf('/') === 0) {
var m = /^[^:]+:\/\/[^\/]+/.exec(base);
if (m) base = m[0];
}
return base + url;
return new URL(url, Shumway.FileLoadingService.instance.baseUrl).href;
},
navigateTo: function (url, target) {
window.parent.postMessage({
callback: 'navigateTo',
data: {
url: this.resolveUrl(url),
target: target
}
}, '*');
}
};
// Using SpecialInflate when chrome code provides it.
if (parent.createSpecialInflate) {
window.SpecialInflate = function () {
return parent.createSpecialInflate();
};
}
// Using createRtmpXHR/createRtmpSocket when chrome code provides it.
if (parent.createRtmpXHR) {
window.createRtmpSocket = parent.createRtmpSocket;
window.createRtmpXHR = parent.createRtmpXHR;
}
}
window.addEventListener('message', function onWindowMessage(e) {

Просмотреть файл

@ -58,6 +58,11 @@ filefield + button {
border-bottom: none;
}
#advancedPrefs {
margin-right: 0; /*override margin from normal preferences.css */
margin-left: 0;
}
/**
* Dialog
*/

Просмотреть файл

@ -202,10 +202,6 @@ description > html|a {
-moz-margin-start: 0;
}
#advancedPrefs {
padding-bottom: 0; /* no padding needed in inContent prefs */
}
#tabsElement {
-moz-margin-end: 4px; /* add the 4px end-margin of other elements */
}

Просмотреть файл

@ -2,6 +2,10 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#defaultEngine {
-moz-margin-start: 0;
}
#defaultEngine > .menulist-label-box > .menulist-icon {
height: 16px;
}
@ -12,7 +16,7 @@
}
#engineList {
margin: .5em 6px;
margin: .5em 0;
}
#engineList treechildren::-moz-tree-image(engineShown, checked) {
@ -51,3 +55,9 @@
#addEnginesBox {
margin-bottom: 1em;
}
#removeEngineButton,
#restoreDefaultSearchEngines {
margin-right: 0;
margin-left: 0;
}

Просмотреть файл

@ -13,6 +13,10 @@ filefield + button {
-moz-margin-start: -4px;
}
#advancedPrefs {
padding-bottom: 0; /* override padding from normal preferences.css */
}
/**
* Dialog
*/

Просмотреть файл

@ -1,24 +1,29 @@
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.gecko;
import java.text.DecimalFormat;
import java.nio.ByteBuffer;
import org.mozilla.gecko.gfx.ImmutableViewportMetrics;
import org.mozilla.gecko.gfx.LayerView;
import org.mozilla.gecko.gfx.PanZoomController;
import org.mozilla.gecko.gfx.PointUtils;
import org.mozilla.gecko.mozglue.DirectBufferAllocator;
import org.mozilla.gecko.util.GeckoEventListener;
import org.mozilla.gecko.util.ThreadUtils;
import org.json.JSONException;
import org.json.JSONObject;
import org.mozilla.gecko.gfx.ImmutableViewportMetrics;
import org.mozilla.gecko.gfx.LayerView;
import org.mozilla.gecko.util.GeckoEventListener;
import org.mozilla.gecko.util.ThreadUtils;
import org.mozilla.gecko.mozglue.DirectBufferAllocator;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.graphics.PointF;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.Matrix;
import android.graphics.Point;
import android.graphics.PointF;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
@ -28,8 +33,11 @@ import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import java.nio.ByteBuffer;
import java.text.DecimalFormat;
public class ZoomedView extends FrameLayout implements LayerView.OnMetricsChangedListener,
LayerView.OnZoomedViewListener, GeckoEventListener {
LayerView.ZoomedViewListener, GeckoEventListener {
private static final String LOGTAG = "Gecko" + ZoomedView.class.getSimpleName();
private static final int ZOOM_FACTOR = 2;
@ -40,27 +48,26 @@ public class ZoomedView extends FrameLayout implements LayerView.OnMetricsChange
private ImageView zoomedImageView;
private LayerView layerView;
private MotionEvent actionDownEvent;
private int viewWidth;
private int viewHeight;
private int xLastPosition;
private int yLastPosition;
private Point lastPosition;
private boolean shouldSetVisibleOnUpdate;
private PointF returnValue;
private boolean stopUpdateView;
private int lastOrientation = 0;
private int lastOrientation;
private ByteBuffer buffer;
private Runnable requestRenderRunnable;
private long startTimeReRender = 0;
private long lastStartTimeReRender = 0;
private long startTimeReRender;
private long lastStartTimeReRender;
private class ZoomedViewTouchListener implements View.OnTouchListener {
private float originRawX;
private float originRawY;
private int touchState;
private boolean dragged;
private MotionEvent actionDownEvent;
@Override
public boolean onTouch(View view, MotionEvent event) {
@ -71,13 +78,13 @@ public class ZoomedView extends FrameLayout implements LayerView.OnMetricsChange
switch (event.getAction()) {
case MotionEvent.ACTION_MOVE:
if (moveZoomedView(event)) {
touchState = MotionEvent.ACTION_MOVE;
dragged = true;
}
break;
case MotionEvent.ACTION_UP:
if (touchState == MotionEvent.ACTION_MOVE) {
touchState = -1;
if (dragged) {
dragged = false;
} else {
layerView.dispatchTouchEvent(actionDownEvent);
actionDownEvent.recycle();
@ -91,7 +98,7 @@ public class ZoomedView extends FrameLayout implements LayerView.OnMetricsChange
break;
case MotionEvent.ACTION_DOWN:
touchState = -1;
dragged = false;
originRawX = event.getRawX();
originRawY = event.getRawY();
PointF convertedPosition = getUnzoomedPositionFromPointInZoomedView(event.getX(), event.getY());
@ -105,8 +112,8 @@ public class ZoomedView extends FrameLayout implements LayerView.OnMetricsChange
private boolean moveZoomedView(MotionEvent event) {
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) ZoomedView.this.getLayoutParams();
if ((touchState != MotionEvent.ACTION_MOVE) && (Math.abs((int) (event.getRawX() - originRawX)) < 1)
&& (Math.abs((int) (event.getRawY() - originRawY)) < 1)) {
if ((!dragged) && (Math.abs((int) (event.getRawX() - originRawX)) < PanZoomController.CLICK_THRESHOLD)
&& (Math.abs((int) (event.getRawY() - originRawY)) < PanZoomController.CLICK_THRESHOLD)) {
// When the user just touches the screen ACTION_MOVE can be detected for a very small delta on position.
// In this case, the move is ignored if the delta is lower than 1 unit.
return false;
@ -236,10 +243,6 @@ public class ZoomedView extends FrameLayout implements LayerView.OnMetricsChange
}
private void moveZoomedView(ImmutableViewportMetrics metrics, float newLeftMargin, float newTopMargin) {
if (layerView == null) {
return;
}
final float parentWidth = metrics.getWidth();
final float parentHeight = metrics.getHeight();
RelativeLayout.LayoutParams newLayoutParams = (RelativeLayout.LayoutParams) getLayoutParams();
@ -253,7 +256,7 @@ public class ZoomedView extends FrameLayout implements LayerView.OnMetricsChange
if (newTopMargin < topMarginMin) {
newLayoutParams.topMargin = topMarginMin;
} else if (newTopMargin + viewHeight >= parentHeight) {
} else if (newTopMargin + viewHeight > parentHeight) {
newLayoutParams.topMargin = (int) (parentHeight - viewHeight);
}
@ -265,8 +268,7 @@ public class ZoomedView extends FrameLayout implements LayerView.OnMetricsChange
setLayoutParams(newLayoutParams);
PointF convertedPosition = getUnzoomedPositionFromPointInZoomedView(0, 0);
xLastPosition = Math.round(convertedPosition.x);
yLastPosition = Math.round(convertedPosition.y);
lastPosition = PointUtils.round(convertedPosition);
requestZoomedViewRender();
}
@ -282,7 +284,7 @@ public class ZoomedView extends FrameLayout implements LayerView.OnMetricsChange
}
}
public void refreshZoomedViewSize(ImmutableViewportMetrics viewport) {
private void refreshZoomedViewSize(ImmutableViewportMetrics viewport) {
if (layerView == null) {
return;
}
@ -292,27 +294,24 @@ public class ZoomedView extends FrameLayout implements LayerView.OnMetricsChange
moveZoomedView(viewport, params.leftMargin, params.topMargin);
}
public void setCapturedSize(ImmutableViewportMetrics metrics) {
if (layerView == null) {
return;
}
private void setCapturedSize(ImmutableViewportMetrics metrics) {
float parentMinSize = Math.min(metrics.getWidth(), metrics.getHeight());
viewWidth = (int) (parentMinSize * W_CAPTURED_VIEW_IN_PERCENT / (ZOOM_FACTOR * 100.0)) * ZOOM_FACTOR;
viewHeight = (int) (parentMinSize * H_CAPTURED_VIEW_IN_PERCENT / (ZOOM_FACTOR * 100.0)) * ZOOM_FACTOR;
}
public void shouldBlockUpdate(boolean shouldBlockUpdate) {
private void shouldBlockUpdate(boolean shouldBlockUpdate) {
stopUpdateView = shouldBlockUpdate;
}
public Bitmap.Config getBitmapConfig() {
private Bitmap.Config getBitmapConfig() {
return (GeckoAppShell.getScreenDepth() == 24) ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
}
public void startZoomDisplay(LayerView aLayerView, final int leftFromGecko, final int topFromGecko) {
private void startZoomDisplay(LayerView aLayerView, final int leftFromGecko, final int topFromGecko) {
if (layerView == null) {
layerView = aLayerView;
layerView.addOnZoomedViewListener(this);
layerView.addZoomedViewListener(this);
layerView.setOnMetricsChangedZoomedViewportListener(this);
ImmutableViewportMetrics metrics = layerView.getViewportMetrics();
setCapturedSize(metrics);
@ -322,13 +321,13 @@ public class ZoomedView extends FrameLayout implements LayerView.OnMetricsChange
moveUsingGeckoPosition(leftFromGecko, topFromGecko);
}
public void stopZoomDisplay() {
private void stopZoomDisplay() {
shouldSetVisibleOnUpdate = false;
this.setVisibility(View.GONE);
ThreadUtils.removeCallbacksFromUiThread(requestRenderRunnable);
if (layerView != null) {
layerView.setOnMetricsChangedZoomedViewportListener(null);
layerView.removeOnZoomedViewListener(this);
layerView.removeZoomedViewListener(this);
layerView = null;
}
}
@ -362,9 +361,6 @@ public class ZoomedView extends FrameLayout implements LayerView.OnMetricsChange
}
private void moveUsingGeckoPosition(int leftFromGecko, int topFromGecko) {
if (layerView == null) {
return;
}
ImmutableViewportMetrics metrics = layerView.getViewportMetrics();
PointF convertedPosition = getZoomedViewTopLeftPositionFromTouchPosition((leftFromGecko * metrics.zoomFactor),
(topFromGecko * metrics.zoomFactor));
@ -379,9 +375,6 @@ public class ZoomedView extends FrameLayout implements LayerView.OnMetricsChange
ThreadUtils.postToUiThread(new Runnable() {
@Override
public void run() {
if (layerView == null) {
return;
}
shouldBlockUpdate(false);
refreshZoomedViewSize(viewport);
}
@ -477,11 +470,11 @@ public class ZoomedView extends FrameLayout implements LayerView.OnMetricsChange
PointF origin = metrics.getOrigin();
PointF offset = metrics.getMarginOffset();
final int xPos = (int) (origin.x - offset.x) + xLastPosition;
final int yPos = (int) (origin.y - offset.y) + yLastPosition;
final int xPos = (int) (origin.x - offset.x) + lastPosition.x;
final int yPos = (int) (origin.y - offset.y) + lastPosition.y;
GeckoEvent e = GeckoEvent.createZoomedViewEvent(tabId, xPos, yPos, viewWidth,
viewHeight, (float) (2.0 * metrics.zoomFactor), buffer);
viewHeight, ZOOM_FACTOR * metrics.zoomFactor, buffer);
GeckoAppShell.sendEventToGecko(e);
}

Просмотреть файл

@ -915,10 +915,10 @@ class GeckoLayerClient implements LayerView.Listener, PanZoomTarget
@Override
public void panZoomStopped() {
if (mDynamicToolbarViewportChangeListener != null) {
mDynamicToolbarViewportChangeListener.onPanZoomStopped();
mDynamicToolbarViewportChangeListener.onPanZoomStopped();
}
if (mZoomedViewViewportChangeListener != null) {
mZoomedViewViewportChangeListener.onPanZoomStopped();
mZoomedViewViewportChangeListener.onPanZoomStopped();
}
}

Просмотреть файл

@ -96,9 +96,9 @@ public class LayerRenderer implements Tabs.OnTabsChangedListener {
private int mSampleHandle;
private int mTMatrixHandle;
private List<LayerView.OnZoomedViewListener> mZoomedViewListeners;
private float mViewLeft = 0.0f;
private float mViewTop = 0.0f;
private List<LayerView.ZoomedViewListener> mZoomedViewListeners;
private float mLastViewLeft;
private float mLastViewTop;
// column-major matrix applied to each vertex to shift the viewport from
// one ranging from (-1, -1),(1,1) to (0,0),(1,1) and to scale all sizes by
@ -168,7 +168,7 @@ public class LayerRenderer implements Tabs.OnTabsChangedListener {
mCoordBuffer = mCoordByteBuffer.asFloatBuffer();
Tabs.registerOnTabsChangedListener(this);
mZoomedViewListeners = new ArrayList<LayerView.OnZoomedViewListener>();
mZoomedViewListeners = new ArrayList<LayerView.ZoomedViewListener>();
}
private Bitmap expandCanvasToPowerOfTwo(Bitmap image, IntSize size) {
@ -598,7 +598,7 @@ public class LayerRenderer implements Tabs.OnTabsChangedListener {
}
public void maybeRequestZoomedViewRender(RenderContext context){
private void maybeRequestZoomedViewRender(RenderContext context) {
// Concurrently update of mZoomedViewListeners should not be an issue here
// because the following line is just a short-circuit
if (mZoomedViewListeners.size() == 0) {
@ -612,13 +612,13 @@ public class LayerRenderer implements Tabs.OnTabsChangedListener {
final float viewTop = context.viewport.top - context.offset.y;
boolean shouldWaitToRender = false;
if (Math.abs(mViewLeft - viewLeft) > MAX_SCROLL_SPEED_TO_REQUEST_ZOOM_RENDER ||
Math.abs(mViewTop - viewTop) > MAX_SCROLL_SPEED_TO_REQUEST_ZOOM_RENDER) {
if (Math.abs(mLastViewLeft - viewLeft) > MAX_SCROLL_SPEED_TO_REQUEST_ZOOM_RENDER ||
Math.abs(mLastViewTop - viewTop) > MAX_SCROLL_SPEED_TO_REQUEST_ZOOM_RENDER) {
shouldWaitToRender = true;
}
mViewLeft = viewLeft;
mViewTop = viewTop;
mLastViewLeft = viewLeft;
mLastViewTop = viewTop;
if (shouldWaitToRender) {
return;
@ -627,7 +627,7 @@ public class LayerRenderer implements Tabs.OnTabsChangedListener {
ThreadUtils.postToUiThread(new Runnable() {
@Override
public void run() {
for (LayerView.OnZoomedViewListener listener : mZoomedViewListeners) {
for (LayerView.ZoomedViewListener listener : mZoomedViewListeners) {
listener.requestZoomedViewRender();
}
}
@ -697,19 +697,20 @@ public class LayerRenderer implements Tabs.OnTabsChangedListener {
ThreadUtils.postToUiThread(new Runnable() {
@Override
public void run() {
for (LayerView.OnZoomedViewListener listener : mZoomedViewListeners) {
for (LayerView.ZoomedViewListener listener : mZoomedViewListeners) {
data.position(0);
listener.updateView(data);
}
}
});
}
public void addOnZoomedViewListener(LayerView.OnZoomedViewListener listener) {
public void addZoomedViewListener(LayerView.ZoomedViewListener listener) {
ThreadUtils.assertOnUiThread();
mZoomedViewListeners.add(listener);
}
public void removeOnZoomedViewListener(LayerView.OnZoomedViewListener listener) {
public void removeZoomedViewListener(LayerView.ZoomedViewListener listener) {
ThreadUtils.assertOnUiThread();
mZoomedViewListeners.remove(listener);
}

Просмотреть файл

@ -532,17 +532,16 @@ public class LayerView extends FrameLayout implements Tabs.OnTabsChangedListener
}
}
//This method is called on the Gecko main thread.
@WrapElementForJNI(allowMultithread = true, stubName = "updateZoomedView")
public static void updateZoomedView(ByteBuffer data) {
data.position(0);
LayerView layerView = GeckoAppShell.getLayerView();
if (layerView != null) {
LayerRenderer layerRenderer = layerView.getRenderer();
if (layerRenderer != null){
if (layerRenderer != null) {
layerRenderer.updateZoomedView(data);
}
}
return;
}
public interface Listener {
@ -687,17 +686,17 @@ public class LayerView extends FrameLayout implements Tabs.OnTabsChangedListener
// Public hooks for zoomed view
public interface OnZoomedViewListener {
public interface ZoomedViewListener {
public void requestZoomedViewRender();
public void updateView(ByteBuffer data);
}
public void addOnZoomedViewListener(OnZoomedViewListener listener) {
mRenderer.addOnZoomedViewListener(listener);
public void addZoomedViewListener(ZoomedViewListener listener) {
mRenderer.addZoomedViewListener(listener);
}
public void removeOnZoomedViewListener(OnZoomedViewListener listener) {
mRenderer.removeOnZoomedViewListener(listener);
public void removeZoomedViewListener(ZoomedViewListener listener) {
mRenderer.removeZoomedViewListener(listener);
}
}

Просмотреть файл

@ -91,5 +91,39 @@ this.PlacesTestUtils = Object.freeze({
});
return Promise.all([expirationFinished, PlacesUtils.history.clear()]);
},
/**
* Waits for all pending async statements on the default connection.
*
* @return {Promise}
* @resolves When all pending async statements finished.
* @rejects Never.
*
* @note The result is achieved by asynchronously executing a query requiring
* a write lock. Since all statements on the same connection are
* serialized, the end of this write operation means that all writes are
* complete. Note that WAL makes so that writers don't block readers, but
* this is a problem only across different connections.
*/
promiseAsyncUpdates() {
return new Promise(resolve => {
let db = PlacesUtils.history.DBConnection;
let begin = db.createAsyncStatement("BEGIN EXCLUSIVE");
begin.executeAsync();
begin.finalize();
let commit = db.createAsyncStatement("COMMIT");
commit.executeAsync({
handleResult: function () {},
handleError: function () {},
handleCompletion: function(aReason)
{
resolve();
}
});
commit.finalize();
});
}
});

Просмотреть файл

@ -277,7 +277,7 @@ function run_test() {
// At this point frecency could still be updating due to latest pages
// updates. This is not a problem in real life, but autocomplete tests
// should return reliable resultsets, thus we have to wait.
yield promiseAsyncUpdates();
yield PlacesTestUtils.promiseAsyncUpdates();
}).then(function () ensure_results(search, expected),
do_report_unexpected_exception);

Просмотреть файл

@ -12,7 +12,7 @@ added or removed and also the maintenance task to fix wrong counts.
const T_URI = NetUtil.newURI("https://www.mozilla.org/firefox/nightly/firstrun/");
function* getForeignCountForURL(conn, url) {
yield promiseAsyncUpdates();
yield PlacesTestUtils.promiseAsyncUpdates();
url = url instanceof Ci.nsIURI ? url.spec : url;
let rows = yield conn.executeCached(
"SELECT foreign_count FROM moz_places WHERE url = :t_url ", { t_url: url });

Просмотреть файл

@ -56,7 +56,7 @@ add_task(function* test_eraseEverything() {
PlacesUtils.annotations.setItemAnnotation((yield PlacesUtils.promiseItemId(toolbarBookmarkInFolder.guid)),
"testanno1", "testvalue1", 0, 0);
yield promiseAsyncUpdates();
yield PlacesTestUtils.promiseAsyncUpdates();
Assert.ok(frecencyForUrl("http://example.com/") > frecencyForExample);
Assert.ok(frecencyForUrl("http://example.com/") > frecencyForMozilla);

Просмотреть файл

@ -277,7 +277,7 @@ add_task(function* create_bookmark_frecency() {
title: "a bookmark" });
checkBookmarkObject(bm);
yield promiseAsyncUpdates();
yield PlacesTestUtils.promiseAsyncUpdates();
Assert.ok(frecencyForUrl(bm.url) > 0, "Check frecency has been updated")
});

Просмотреть файл

@ -77,7 +77,7 @@ add_test(function test_addBookmarkWithKeyword()
check_bookmark_keyword(itemId, "keyword");
check_uri_keyword(URIS[0], "keyword");
promiseAsyncUpdates().then(function() {
PlacesTestUtils.promiseAsyncUpdates().then(() => {
check_orphans();
run_next_test();
});
@ -94,7 +94,7 @@ add_test(function test_addBookmarkToURIHavingKeyword()
check_bookmark_keyword(itemId, null);
check_uri_keyword(URIS[0], "keyword");
promiseAsyncUpdates().then(function() {
PlacesTestUtils.promiseAsyncUpdates().then(() => {
check_orphans();
run_next_test();
});
@ -120,7 +120,7 @@ add_test(function test_addSameKeywordToOtherURI()
check_uri_keyword(URIS[1], "keyword");
check_uri_keyword(URIS[0], "keyword");
promiseAsyncUpdates().then(function() {
PlacesTestUtils.promiseAsyncUpdates().then(() => {
check_orphans();
run_next_test();
});
@ -143,7 +143,7 @@ add_test(function test_removeBookmarkWithKeyword()
check_uri_keyword(URIS[1], "keyword");
check_uri_keyword(URIS[0], "keyword");
promiseAsyncUpdates().then(function() {
PlacesTestUtils.promiseAsyncUpdates().then(() => {
check_orphans();
run_next_test();
});
@ -157,7 +157,7 @@ add_test(function test_removeFolderWithKeywordedBookmarks()
check_uri_keyword(URIS[1], null);
check_uri_keyword(URIS[0], null);
promiseAsyncUpdates().then(function() {
PlacesTestUtils.promiseAsyncUpdates().then(() => {
check_orphans();
run_next_test();
});

Просмотреть файл

@ -55,7 +55,7 @@ function errorListener() {
"Docshell URI is the original URI.");
// Global history does not record URI of a failed request.
promiseAsyncUpdates().then(function() {
PlacesTestUtils.promiseAsyncUpdates().then(() => {
gAsyncHistory.isURIVisited(kUniqueURI, errorAsyncListener);
});
}
@ -91,7 +91,7 @@ function reloadListener() {
"Document URI is not the offline-error page, but the original URI.");
// Check if global history remembers the successfully-requested URI.
promiseAsyncUpdates().then(function() {
PlacesTestUtils.promiseAsyncUpdates().then(() => {
gAsyncHistory.isURIVisited(kUniqueURI, reloadAsyncListener);
});
}

Просмотреть файл

@ -18,43 +18,6 @@ XPCOMUtils.defineLazyModuleGetter(this, "Promise",
XPCOMUtils.defineLazyModuleGetter(this, "Task",
"resource://gre/modules/Task.jsm");
/**
* Waits for all pending async statements on the default connection.
*
* @return {Promise}
* @resolves When all pending async statements finished.
* @rejects Never.
*
* @note The result is achieved by asynchronously executing a query requiring
* a write lock. Since all statements on the same connection are
* serialized, the end of this write operation means that all writes are
* complete. Note that WAL makes so that writers don't block readers, but
* this is a problem only across different connections.
*/
function promiseAsyncUpdates()
{
let deferred = Promise.defer();
let db = PlacesUtils.history.QueryInterface(Ci.nsPIPlacesDatabase)
.DBConnection;
let begin = db.createAsyncStatement("BEGIN EXCLUSIVE");
begin.executeAsync();
begin.finalize();
let commit = db.createAsyncStatement("COMMIT");
commit.executeAsync({
handleResult: function() {},
handleError: function() {},
handleCompletion: function(aReason)
{
deferred.resolve();
}
});
commit.finalize();
return deferred.promise;
}
/**
* Returns a moz_places field value for a url.
*

Просмотреть файл

@ -69,7 +69,7 @@ add_test(function test_query_result_favicon_changed_on_child()
// operation, and then for the main thread to process any pending
// notifications that came from the asynchronous thread, before we can be
// sure that nodeIconChanged was not invoked in the meantime.
promiseAsyncUpdates().then(function QRFCOC_asyncUpdates() {
PlacesTestUtils.promiseAsyncUpdates().then(function QRFCOC_asyncUpdates() {
do_execute_soon(function QRFCOC_soon() {
result.removeObserver(resultObserver);

Просмотреть файл

@ -139,7 +139,7 @@ add_task(function test_replaceFaviconData_replaceExisting() {
iconsvc.replaceFaviconData(
firstFavicon.uri, secondFavicon.data, secondFavicon.data.length,
secondFavicon.mimetype);
promiseAsyncUpdates().then(function() {
PlacesTestUtils.promiseAsyncUpdates().then(() => {
checkFaviconDataForPage(
pageURI, secondFavicon.mimetype, secondFavicon.data,
function test_replaceFaviconData_overrideDefaultFavicon_secondCallback() {

Просмотреть файл

@ -598,42 +598,6 @@ function is_time_ordered(before, after) {
return after - before > -skew;
}
/**
* Waits for all pending async statements on the default connection.
*
* @return {Promise}
* @resolves When all pending async statements finished.
* @rejects Never.
*
* @note The result is achieved by asynchronously executing a query requiring
* a write lock. Since all statements on the same connection are
* serialized, the end of this write operation means that all writes are
* complete. Note that WAL makes so that writers don't block readers, but
* this is a problem only across different connections.
*/
function promiseAsyncUpdates()
{
let deferred = Promise.defer();
let db = DBConn();
let begin = db.createAsyncStatement("BEGIN EXCLUSIVE");
begin.executeAsync();
begin.finalize();
let commit = db.createAsyncStatement("COMMIT");
commit.executeAsync({
handleResult: function () {},
handleError: function () {},
handleCompletion: function(aReason)
{
deferred.resolve();
}
});
commit.finalize();
return deferred.promise;
}
/**
* Shutdowns Places, invoking the callback when the connection has been closed.
*

Просмотреть файл

@ -166,8 +166,8 @@ function run_test() {
// updates.
// This is not a problem in real life, but autocomplete tests should
// return reliable resultsets, thus we have to wait.
promiseAsyncUpdates().then(function () ensure_results(searchString,
expectedValue));
PlacesTestUtils.promiseAsyncUpdates()
.then(() => ensure_results(searchString, expectedValue));
})
}, this);

Просмотреть файл

@ -20,7 +20,7 @@ add_task(function* test_moz_hosts() {
yield db.execute("SELECT host, frecency, typed, prefix FROM moz_hosts");
// moz_hosts is populated asynchronously, so we need to wait.
yield promiseAsyncUpdates();
yield PlacesTestUtils.promiseAsyncUpdates();
// check the number of entries in moz_hosts equals the number of
// unique rev_host in moz_places

Просмотреть файл

@ -283,7 +283,7 @@ add_task(function test_add_visits_to_database()
add_task(function test_redirects()
{
// Frecency and hidden are updated asynchronously, wait for them.
yield promiseAsyncUpdates();
yield PlacesTestUtils.promiseAsyncUpdates();
// This array will be used by cartProd to generate a matrix of all possible
// combinations.

Просмотреть файл

@ -1266,7 +1266,7 @@ add_task(function test_sorting()
{
for (let [, test] in Iterator(tests)) {
yield test.setup();
yield promiseAsyncUpdates();
yield PlacesTestUtils.promiseAsyncUpdates();
test.check();
// sorting reversed, usually SORT_BY have ASC and DESC
test.check_reverse();

Просмотреть файл

@ -101,7 +101,7 @@ function* check_autocomplete(test) {
// updates.
// This is not a problem in real life, but autocomplete tests should
// return reliable resultsets, thus we have to wait.
yield promiseAsyncUpdates();
yield PlacesTestUtils.promiseAsyncUpdates();
// Make an AutoCompleteInput that uses our searches and confirms results.
let input = new AutoCompleteInput(["unifiedcomplete"]);

Просмотреть файл

@ -52,7 +52,7 @@ add_task(function* test_searchEngine_autoFill() {
}
yield promiseAddVisits(visits);
addBookmark({ uri: uri, title: "Example bookmark" });
yield promiseAsyncUpdates();
yield PlacesTestUtils.promiseAsyncUpdates();
ok(frecencyForUrl(uri) > 10000, "Added URI should have expected high frecency");
do_print("Check search domain is autoFilled even if there's an higher frecency match");

Просмотреть файл

@ -216,7 +216,7 @@ add_task(function test_frecency()
// DEBUG
//results.every(function(el) { dump("result: " + el[1] + ": " + el[0].spec + " (" + el[2] + ")\n"); return true; })
yield promiseAsyncUpdates();
yield PlacesTestUtils.promiseAsyncUpdates();
var controller = Components.classes["@mozilla.org/autocomplete/controller;1"].
getService(Components.interfaces.nsIAutoCompleteController);

Просмотреть файл

@ -53,7 +53,7 @@ function run_test() {
// 2. run the test-suite
Task.spawn(function() {
yield validate();
yield promiseAsyncUpdates();
yield PlacesTestUtils.promiseAsyncUpdates();
// Test exporting a Places canonical json file.
// 1. export to bookmarks.exported.json
@ -73,7 +73,7 @@ function run_test() {
yield validate();
LOG("validated import");
yield promiseAsyncUpdates();
yield PlacesTestUtils.promiseAsyncUpdates();
do_test_finished();
});
}

Просмотреть файл

@ -21,14 +21,14 @@ add_task(function changeuri_unvisited_bookmark()
TEST_URI,
PlacesUtils.bookmarks.DEFAULT_INDEX,
"bookmark title");
yield promiseAsyncUpdates();
yield PlacesTestUtils.promiseAsyncUpdates();
do_print("Bookmarked => frecency of URI should be != 0");
do_check_neq(frecencyForUrl(TEST_URI), 0);
PlacesUtils.bookmarks.changeBookmarkURI(id, uri("http://example.com/2"));
yield promiseAsyncUpdates();
yield PlacesTestUtils.promiseAsyncUpdates();
do_print("Unvisited URI no longer bookmarked => frecency should = 0");
do_check_eq(frecencyForUrl(TEST_URI), 0);
@ -47,18 +47,18 @@ add_task(function changeuri_visited_bookmark()
PlacesUtils.bookmarks.DEFAULT_INDEX,
"bookmark title");
yield promiseAsyncUpdates();
yield PlacesTestUtils.promiseAsyncUpdates();
do_print("Bookmarked => frecency of URI should be != 0");
do_check_neq(frecencyForUrl(TEST_URI), 0);
yield promiseAddVisits(TEST_URI);
yield promiseAsyncUpdates();
yield PlacesTestUtils.promiseAsyncUpdates();
PlacesUtils.bookmarks.changeBookmarkURI(id, uri("http://example.com/2"));
yield promiseAsyncUpdates();
yield PlacesTestUtils.promiseAsyncUpdates();
do_print("*Visited* URI no longer bookmarked => frecency should != 0");
do_check_neq(frecencyForUrl(TEST_URI), 0);
@ -82,14 +82,14 @@ add_task(function changeuri_bookmark_still_bookmarked()
PlacesUtils.bookmarks.DEFAULT_INDEX,
"bookmark 2 title");
yield promiseAsyncUpdates();
yield PlacesTestUtils.promiseAsyncUpdates();
do_print("Bookmarked => frecency of URI should be != 0");
do_check_neq(frecencyForUrl(TEST_URI), 0);
PlacesUtils.bookmarks.changeBookmarkURI(id1, uri("http://example.com/2"));
yield promiseAsyncUpdates();
yield PlacesTestUtils.promiseAsyncUpdates();
do_print("URI still bookmarked => frecency should != 0");
do_check_neq(frecencyForUrl(TEST_URI), 0);

Просмотреть файл

@ -40,7 +40,7 @@ add_test(function test_keywordRemovedOnUniqueItemRemoval() {
// remove bookmark
bmsvc.removeItem(bookmarkId);
promiseAsyncUpdates().then(function() {
PlacesTestUtils.promiseAsyncUpdates().then(() => {
// Check that keyword has been removed from the database.
// The removal is asynchronous.
var sql = "SELECT id FROM moz_keywords WHERE keyword = ?1";
@ -77,7 +77,7 @@ add_test(function test_keywordNotRemovedOnNonUniqueItemRemoval() {
// remove first bookmark
bmsvc.removeItem(bookmarkId1);
promiseAsyncUpdates().then(function() {
PlacesTestUtils.promiseAsyncUpdates().then(() => {
// check that keyword is still there
var sql = "SELECT id FROM moz_keywords WHERE keyword = ?1";
var stmt = mDBConn.createStatement(sql);

Просмотреть файл

@ -388,7 +388,7 @@ add_task(function* test_non_addable_uri_errors() {
do_check_eq(place.resultCode, Cr.NS_ERROR_INVALID_ARG);
do_check_false(yield promiseIsURIVisited(place.info.uri));
}
yield promiseAsyncUpdates();
yield PlacesTestUtils.promiseAsyncUpdates();
});
add_task(function* test_duplicate_guid_errors() {
@ -426,7 +426,7 @@ add_task(function* test_duplicate_guid_errors() {
do_check_eq(badPlaceInfo.resultCode, Cr.NS_ERROR_STORAGE_CONSTRAINT);
do_check_false(yield promiseIsURIVisited(badPlaceInfo.info.uri));
yield promiseAsyncUpdates();
yield PlacesTestUtils.promiseAsyncUpdates();
});
add_task(function* test_invalid_referrerURI_ignored() {
@ -462,7 +462,7 @@ add_task(function* test_invalid_referrerURI_ignored() {
do_check_eq(stmt.row.from_visit, 0);
stmt.finalize();
yield promiseAsyncUpdates();
yield PlacesTestUtils.promiseAsyncUpdates();
});
add_task(function* test_nonnsIURI_referrerURI_ignored() {
@ -494,7 +494,7 @@ add_task(function* test_nonnsIURI_referrerURI_ignored() {
do_check_eq(stmt.row.from_visit, 0);
stmt.finalize();
yield promiseAsyncUpdates();
yield PlacesTestUtils.promiseAsyncUpdates();
});
add_task(function* test_old_referrer_ignored() {
@ -553,7 +553,7 @@ add_task(function* test_old_referrer_ignored() {
do_check_eq(stmt.row.count, 1);
stmt.finalize();
yield promiseAsyncUpdates();
yield PlacesTestUtils.promiseAsyncUpdates();
});
add_task(function* test_place_id_ignored() {
@ -593,7 +593,7 @@ add_task(function* test_place_id_ignored() {
do_check_neq(placeInfo.placeId, placeId);
do_check_true(yield promiseIsURIVisited(badPlace.uri));
yield promiseAsyncUpdates();
yield PlacesTestUtils.promiseAsyncUpdates();
});
add_task(function* test_handleCompletion_called_when_complete() {
@ -634,7 +634,7 @@ add_task(function* test_handleCompletion_called_when_complete() {
do_check_eq(callbackCountSuccess, EXPECTED_COUNT_SUCCESS);
do_check_eq(callbackCountFailure, EXPECTED_COUNT_FAILURE);
yield promiseAsyncUpdates();
yield PlacesTestUtils.promiseAsyncUpdates();
});
add_task(function* test_add_visit() {
@ -695,7 +695,7 @@ add_task(function* test_add_visit() {
// If we have had all of our callbacks, continue running tests.
if (++callbackCount == place.visits.length) {
yield promiseAsyncUpdates();
yield PlacesTestUtils.promiseAsyncUpdates();
}
}
});
@ -778,7 +778,7 @@ add_task(function* test_properties_saved() {
// If we have had all of our callbacks, continue running tests.
if (++callbackCount == places.length) {
yield promiseAsyncUpdates();
yield PlacesTestUtils.promiseAsyncUpdates();
}
}
});
@ -803,7 +803,7 @@ add_task(function* test_guid_saved() {
do_check_true(yield promiseIsURIVisited(uri));
do_check_eq(placeInfo.guid, place.guid);
do_check_guid_for_uri(uri, place.guid);
yield promiseAsyncUpdates();
yield PlacesTestUtils.promiseAsyncUpdates();
});
add_task(function* test_referrer_saved() {
@ -853,7 +853,7 @@ add_task(function* test_referrer_saved() {
do_check_eq(stmt.row.count, 1);
stmt.finalize();
yield promiseAsyncUpdates();
yield PlacesTestUtils.promiseAsyncUpdates();
}
}
});
@ -881,7 +881,7 @@ add_task(function* test_guid_change_saved() {
}
do_check_guid_for_uri(place.uri, place.guid);
yield promiseAsyncUpdates();
yield PlacesTestUtils.promiseAsyncUpdates();
});
add_task(function* test_title_change_saved() {
@ -927,7 +927,7 @@ add_task(function* test_title_change_saved() {
}
do_check_title_for_uri(place.uri, place.title);
yield promiseAsyncUpdates();
yield PlacesTestUtils.promiseAsyncUpdates();
});
add_task(function* test_no_title_does_not_clear_title() {
@ -955,7 +955,7 @@ add_task(function* test_no_title_does_not_clear_title() {
}
do_check_title_for_uri(place.uri, TITLE);
yield promiseAsyncUpdates();
yield PlacesTestUtils.promiseAsyncUpdates();
});
add_task(function* test_title_change_notifies() {
@ -1011,7 +1011,7 @@ add_task(function* test_title_change_notifies() {
}
yield promiseTitleChangedObserver(place);
yield promiseAsyncUpdates();
yield PlacesTestUtils.promiseAsyncUpdates();
});
add_task(function* test_visit_notifies() {
@ -1059,7 +1059,7 @@ add_task(function* test_visit_notifies() {
}
yield promiseVisitObserver(place);
yield promiseAsyncUpdates();
yield PlacesTestUtils.promiseAsyncUpdates();
});
// test with empty mozIVisitInfoCallback object
@ -1089,7 +1089,7 @@ add_task(function* test_callbacks_not_supplied() {
});
PlacesUtils.asyncHistory.updatePlaces(places, {});
yield promiseAsyncUpdates();
yield PlacesTestUtils.promiseAsyncUpdates();
});
// Test that we don't wrongly overwrite typed and hidden when adding new visits.

Просмотреть файл

@ -99,11 +99,11 @@ add_task(function* setup() {
// 2. run the test-suite
// Note: we do not empty the db before this import to catch bugs like 380999
yield BookmarkHTMLUtils.importFromFile(gBookmarksFileOld, true);
yield promiseAsyncUpdates();
yield PlacesTestUtils.promiseAsyncUpdates();
yield testImportedBookmarks();
yield BookmarkHTMLUtils.exportToFile(gBookmarksFileNew);
yield promiseAsyncUpdates();
yield PlacesTestUtils.promiseAsyncUpdates();
remove_all_bookmarks();
});
@ -113,10 +113,10 @@ add_task(function* test_import_new()
// 1. import bookmarks.exported.html
// 2. run the test-suite
yield BookmarkHTMLUtils.importFromFile(gBookmarksFileNew, true);
yield promiseAsyncUpdates();
yield PlacesTestUtils.promiseAsyncUpdates();
yield testImportedBookmarks();
yield promiseAsyncUpdates();
yield PlacesTestUtils.promiseAsyncUpdates();
remove_all_bookmarks();
});
@ -135,7 +135,7 @@ add_task(function* test_emptytitle_export()
// 9. empty bookmarks db and continue
yield BookmarkHTMLUtils.importFromFile(gBookmarksFileNew, true);
yield promiseAsyncUpdates();
yield PlacesTestUtils.promiseAsyncUpdates();
const NOTITLE_URL = "http://notitle.mozilla.org/";
let id = PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId,
@ -145,11 +145,11 @@ add_task(function* test_emptytitle_export()
test_bookmarks.unfiled.push({ title: "", url: NOTITLE_URL });
yield BookmarkHTMLUtils.exportToFile(gBookmarksFileNew);
yield promiseAsyncUpdates();
yield PlacesTestUtils.promiseAsyncUpdates();
remove_all_bookmarks();
yield BookmarkHTMLUtils.importFromFile(gBookmarksFileNew, true);
yield promiseAsyncUpdates();
yield PlacesTestUtils.promiseAsyncUpdates();
yield testImportedBookmarks();
// Cleanup.
@ -157,7 +157,7 @@ add_task(function* test_emptytitle_export()
PlacesUtils.bookmarks.removeItem(id);
yield BookmarkHTMLUtils.exportToFile(gBookmarksFileNew);
yield promiseAsyncUpdates();
yield PlacesTestUtils.promiseAsyncUpdates();
remove_all_bookmarks();
});
@ -179,7 +179,7 @@ add_task(function* test_import_chromefavicon()
const CHROME_FAVICON_URI_2 = NetUtil.newURI("chrome://global/skin/icons/error-16.png");
yield BookmarkHTMLUtils.importFromFile(gBookmarksFileNew, true);
yield promiseAsyncUpdates();
yield PlacesTestUtils.promiseAsyncUpdates();
let id = PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId,
PAGE_URI,
PlacesUtils.bookmarks.DEFAULT_INDEX,
@ -204,7 +204,7 @@ add_task(function* test_import_chromefavicon()
{ title: "Test", url: PAGE_URI.spec, icon: base64Icon });
yield BookmarkHTMLUtils.exportToFile(gBookmarksFileNew);
yield promiseAsyncUpdates();
yield PlacesTestUtils.promiseAsyncUpdates();
// Change the favicon to check it's really imported again later.
deferred = Promise.defer();
@ -217,7 +217,7 @@ add_task(function* test_import_chromefavicon()
remove_all_bookmarks();
yield BookmarkHTMLUtils.importFromFile(gBookmarksFileNew, true);
yield promiseAsyncUpdates();
yield PlacesTestUtils.promiseAsyncUpdates();
yield testImportedBookmarks();
// Cleanup.
@ -225,7 +225,7 @@ add_task(function* test_import_chromefavicon()
PlacesUtils.bookmarks.removeItem(id);
yield BookmarkHTMLUtils.exportToFile(gBookmarksFileNew);
yield promiseAsyncUpdates();
yield PlacesTestUtils.promiseAsyncUpdates();
remove_all_bookmarks();
});
@ -240,14 +240,14 @@ add_task(function* test_import_ontop()
// 4. run the test-suite
yield BookmarkHTMLUtils.importFromFile(gBookmarksFileNew, true);
yield promiseAsyncUpdates();
yield PlacesTestUtils.promiseAsyncUpdates();
yield BookmarkHTMLUtils.exportToFile(gBookmarksFileNew);
yield promiseAsyncUpdates();
yield PlacesTestUtils.promiseAsyncUpdates();
yield BookmarkHTMLUtils.importFromFile(gBookmarksFileNew, true);
yield promiseAsyncUpdates();
yield PlacesTestUtils.promiseAsyncUpdates();
yield testImportedBookmarks();
yield promiseAsyncUpdates();
yield PlacesTestUtils.promiseAsyncUpdates();
remove_all_bookmarks();
});

Просмотреть файл

@ -78,7 +78,7 @@ add_task(function test_import_bookmarks() {
let bookmarksFile = OS.Path.join(do_get_cwd().path, "bookmarks.json");
yield BookmarkJSONUtils.importFromFile(bookmarksFile, true);
yield promiseAsyncUpdates();
yield PlacesTestUtils.promiseAsyncUpdates();
yield testImportedBookmarks();
});
@ -86,24 +86,24 @@ add_task(function test_export_bookmarks() {
bookmarksExportedFile = OS.Path.join(OS.Constants.Path.profileDir,
"bookmarks.exported.json");
yield BookmarkJSONUtils.exportToFile(bookmarksExportedFile);
yield promiseAsyncUpdates();
yield PlacesTestUtils.promiseAsyncUpdates();
});
add_task(function test_import_exported_bookmarks() {
remove_all_bookmarks();
yield BookmarkJSONUtils.importFromFile(bookmarksExportedFile, true);
yield promiseAsyncUpdates();
yield PlacesTestUtils.promiseAsyncUpdates();
yield testImportedBookmarks();
});
add_task(function test_import_ontop() {
remove_all_bookmarks();
yield BookmarkJSONUtils.importFromFile(bookmarksExportedFile, true);
yield promiseAsyncUpdates();
yield PlacesTestUtils.promiseAsyncUpdates();
yield BookmarkJSONUtils.exportToFile(bookmarksExportedFile);
yield promiseAsyncUpdates();
yield PlacesTestUtils.promiseAsyncUpdates();
yield BookmarkJSONUtils.importFromFile(bookmarksExportedFile, true);
yield promiseAsyncUpdates();
yield PlacesTestUtils.promiseAsyncUpdates();
yield testImportedBookmarks();
});

Просмотреть файл

@ -73,8 +73,8 @@ AutoCompleteInput.prototype = {
function ensure_results(uris, searchTerm)
{
promiseAsyncUpdates().then(function () ensure_results_internal(uris,
searchTerm));
PlacesTestUtils.promiseAsyncUpdates()
.then(() => ensure_results_internal(uris, searchTerm));
}
function ensure_results_internal(uris, searchTerm)

Просмотреть файл

@ -15,13 +15,13 @@ add_task(function ()
TEST_URI,
PlacesUtils.bookmarks.DEFAULT_INDEX,
"A title");
yield promiseAsyncUpdates();
yield PlacesTestUtils.promiseAsyncUpdates();
do_check_true(frecencyForUrl(TEST_URI) > 0);
// Removing the bookmark should leave an orphan page with zero frecency.
// Note this would usually be expired later by expiration.
PlacesUtils.bookmarks.removeItem(id);
yield promiseAsyncUpdates();
yield PlacesTestUtils.promiseAsyncUpdates();
do_check_eq(frecencyForUrl(TEST_URI), 0);
// Now add a valid visit to the page, frecency should increase.

Просмотреть файл

@ -91,7 +91,7 @@ add_task(function* test_history_clear()
{ uri: uri("http://frecency.mozilla.org/"),
transition: TRANSITION_LINK },
]);
yield promiseAsyncUpdates();
yield PlacesTestUtils.promiseAsyncUpdates();
// Clear history and wait for the onClearHistory notification.
let promiseWaitClearHistory = promiseOnClearHistoryObserved();
@ -102,7 +102,7 @@ add_task(function* test_history_clear()
do_check_eq(0, PlacesUtils.history.hasHistoryEntries);
yield promiseTopicObserved(PlacesUtils.TOPIC_EXPIRATION_FINISHED);
yield promiseAsyncUpdates();
yield PlacesTestUtils.promiseAsyncUpdates();
// Check that frecency for not cleared items (bookmarks) has been converted
// to -MAX(visit_count, 1), so we will be able to recalculate frecency

Просмотреть файл

@ -151,7 +151,7 @@ add_test(function check_history_query() {
do_check_eq(resultObserver.closedContainer, resultObserver.openedContainer);
result.removeObserver(resultObserver);
resultObserver.reset();
promiseAsyncUpdates().then(run_next_test);
PlacesTestUtils.promiseAsyncUpdates().then(run_next_test);
});
});
});
@ -219,7 +219,7 @@ add_test(function check_bookmarks_query() {
do_check_eq(resultObserver.closedContainer, resultObserver.openedContainer);
result.removeObserver(resultObserver);
resultObserver.reset();
promiseAsyncUpdates().then(run_next_test);
PlacesTestUtils.promiseAsyncUpdates().then(run_next_test);
});
add_test(function check_mixed_query() {
@ -252,5 +252,5 @@ add_test(function check_mixed_query() {
do_check_eq(resultObserver.closedContainer, resultObserver.openedContainer);
result.removeObserver(resultObserver);
resultObserver.reset();
promiseAsyncUpdates().then(run_next_test);
PlacesTestUtils.promiseAsyncUpdates().then(run_next_test);
});

Просмотреть файл

@ -27,7 +27,7 @@ add_task(function remove_visits_outside_unbookmarked_uri() {
do_print("Remove visits using timerange outside the URI's visits.");
PlacesUtils.history.removeVisitsByTimeframe(NOW - 10, NOW);
yield promiseAsyncUpdates();
yield PlacesTestUtils.promiseAsyncUpdates();
do_print("URI should still exist in moz_places.");
do_check_true(page_in_database(TEST_URI.spec));
@ -49,7 +49,7 @@ add_task(function remove_visits_outside_unbookmarked_uri() {
do_print("asyncHistory.isURIVisited should return true.");
do_check_true(yield promiseIsURIVisited(TEST_URI));
yield promiseAsyncUpdates();
yield PlacesTestUtils.promiseAsyncUpdates();
do_print("Frecency should be positive.")
do_check_true(frecencyForUrl(TEST_URI) > 0);
@ -70,11 +70,11 @@ add_task(function remove_visits_outside_bookmarked_uri() {
TEST_URI,
PlacesUtils.bookmarks.DEFAULT_INDEX,
"bookmark title");
yield promiseAsyncUpdates();
yield PlacesTestUtils.promiseAsyncUpdates();
do_print("Remove visits using timerange outside the URI's visits.");
PlacesUtils.history.removeVisitsByTimeframe(NOW - 10, NOW);
yield promiseAsyncUpdates();
yield PlacesTestUtils.promiseAsyncUpdates();
do_print("URI should still exist in moz_places.");
do_check_true(page_in_database(TEST_URI.spec));
@ -95,7 +95,7 @@ add_task(function remove_visits_outside_bookmarked_uri() {
do_print("asyncHistory.isURIVisited should return true.");
do_check_true(yield promiseIsURIVisited(TEST_URI));
yield promiseAsyncUpdates();
yield PlacesTestUtils.promiseAsyncUpdates();
do_print("Frecency should be positive.")
do_check_true(frecencyForUrl(TEST_URI) > 0);
@ -115,7 +115,7 @@ add_task(function remove_visits_unbookmarked_uri() {
do_print("Remove the 5 most recent visits.");
PlacesUtils.history.removeVisitsByTimeframe(NOW - 4, NOW);
yield promiseAsyncUpdates();
yield PlacesTestUtils.promiseAsyncUpdates();
do_print("URI should still exist in moz_places.");
do_check_true(page_in_database(TEST_URI.spec));
@ -136,7 +136,7 @@ add_task(function remove_visits_unbookmarked_uri() {
do_print("asyncHistory.isURIVisited should return true.");
do_check_true(yield promiseIsURIVisited(TEST_URI));
yield promiseAsyncUpdates();
yield PlacesTestUtils.promiseAsyncUpdates();
do_print("Frecency should be positive.")
do_check_true(frecencyForUrl(TEST_URI) > 0);
@ -158,11 +158,11 @@ add_task(function remove_visits_bookmarked_uri() {
TEST_URI,
PlacesUtils.bookmarks.DEFAULT_INDEX,
"bookmark title");
yield promiseAsyncUpdates();
yield PlacesTestUtils.promiseAsyncUpdates();
do_print("Remove the 5 most recent visits.");
PlacesUtils.history.removeVisitsByTimeframe(NOW - 4, NOW);
yield promiseAsyncUpdates();
yield PlacesTestUtils.promiseAsyncUpdates();
do_print("URI should still exist in moz_places.");
do_check_true(page_in_database(TEST_URI.spec));
@ -183,7 +183,7 @@ add_task(function remove_visits_bookmarked_uri() {
do_print("asyncHistory.isURIVisited should return true.");
do_check_true(yield promiseIsURIVisited(TEST_URI));
yield promiseAsyncUpdates()
yield PlacesTestUtils.promiseAsyncUpdates()
do_print("Frecency should be positive.")
do_check_true(frecencyForUrl(TEST_URI) > 0);
@ -203,7 +203,7 @@ add_task(function remove_all_visits_unbookmarked_uri() {
do_print("Remove all visits.");
PlacesUtils.history.removeVisitsByTimeframe(NOW - 10, NOW);
yield promiseAsyncUpdates();
yield PlacesTestUtils.promiseAsyncUpdates();
do_print("URI should no longer exist in moz_places.");
do_check_false(page_in_database(TEST_URI.spec));
@ -235,7 +235,7 @@ add_task(function remove_all_visits_unbookmarked_place_uri() {
do_print("Remove all visits.");
PlacesUtils.history.removeVisitsByTimeframe(NOW - 10, NOW);
yield promiseAsyncUpdates();
yield PlacesTestUtils.promiseAsyncUpdates();
do_print("URI should still exist in moz_places.");
do_check_true(page_in_database(PLACE_URI.spec));
@ -252,7 +252,7 @@ add_task(function remove_all_visits_unbookmarked_place_uri() {
do_print("asyncHistory.isURIVisited should return false.");
do_check_false(yield promiseIsURIVisited(PLACE_URI));
yield promiseAsyncUpdates();
yield PlacesTestUtils.promiseAsyncUpdates();
do_print("Frecency should be zero.")
do_check_eq(frecencyForUrl(PLACE_URI.spec), 0);
@ -274,11 +274,11 @@ add_task(function remove_all_visits_bookmarked_uri() {
TEST_URI,
PlacesUtils.bookmarks.DEFAULT_INDEX,
"bookmark title");
yield promiseAsyncUpdates();
yield PlacesTestUtils.promiseAsyncUpdates();
do_print("Remove all visits.");
PlacesUtils.history.removeVisitsByTimeframe(NOW - 10, NOW);
yield promiseAsyncUpdates();
yield PlacesTestUtils.promiseAsyncUpdates();
do_print("URI should still exist in moz_places.");
do_check_true(page_in_database(TEST_URI.spec));
@ -298,7 +298,7 @@ add_task(function remove_all_visits_bookmarked_uri() {
do_print("nsINavBookmarksService.isBookmarked should return true.");
do_check_true(PlacesUtils.bookmarks.isBookmarked(TEST_URI));
yield promiseAsyncUpdates();
yield PlacesTestUtils.promiseAsyncUpdates();
do_print("Frecency should be negative.")
do_check_true(frecencyForUrl(TEST_URI) < 0);
@ -317,7 +317,7 @@ add_task(function remove_all_visits_bookmarked_uri() {
do_print("Remove newer visit.");
PlacesUtils.history.removeVisitsByTimeframe(NOW - 10, NOW);
yield promiseAsyncUpdates();
yield PlacesTestUtils.promiseAsyncUpdates();
do_print("URI should still exist in moz_places.");
do_check_true(page_in_database(TEST_URI.spec));

Просмотреть файл

@ -59,7 +59,7 @@ add_task(function test_execute()
.getService(Ci.nsIObserver)
.observe(null, "gather-telemetry", null);
yield promiseAsyncUpdates();
yield PlacesTestUtils.promiseAsyncUpdates();
// Test expiration probes.
for (let i = 0; i < 2; i++) {

Просмотреть файл

@ -21,15 +21,13 @@ add_test(function removed_bookmark()
TEST_URI,
PlacesUtils.bookmarks.DEFAULT_INDEX,
"bookmark title");
promiseAsyncUpdates().then(function ()
{
PlacesTestUtils.promiseAsyncUpdates().then(() => {
do_print("Bookmarked => frecency of URI should be != 0");
do_check_neq(frecencyForUrl(TEST_URI), 0);
PlacesUtils.bookmarks.removeItem(id);
promiseAsyncUpdates().then(function ()
{
PlacesTestUtils.promiseAsyncUpdates().then(() => {
do_print("Unvisited URI no longer bookmarked => frecency should = 0");
do_check_eq(frecencyForUrl(TEST_URI), 0);
@ -48,16 +46,14 @@ add_test(function removed_but_visited_bookmark()
TEST_URI,
PlacesUtils.bookmarks.DEFAULT_INDEX,
"bookmark title");
promiseAsyncUpdates().then(function ()
{
PlacesTestUtils.promiseAsyncUpdates().then(() => {
do_print("Bookmarked => frecency of URI should be != 0");
do_check_neq(frecencyForUrl(TEST_URI), 0);
promiseAddVisits(TEST_URI).then(function () {
PlacesUtils.bookmarks.removeItem(id);
promiseAsyncUpdates().then(function ()
{
PlacesTestUtils.promiseAsyncUpdates().then(() => {
do_print("*Visited* URI no longer bookmarked => frecency should != 0");
do_check_neq(frecencyForUrl(TEST_URI), 0);
@ -81,15 +77,13 @@ add_test(function remove_bookmark_still_bookmarked()
TEST_URI,
PlacesUtils.bookmarks.DEFAULT_INDEX,
"bookmark 2 title");
promiseAsyncUpdates().then(function ()
{
PlacesTestUtils.promiseAsyncUpdates().then(() => {
do_print("Bookmarked => frecency of URI should be != 0");
do_check_neq(frecencyForUrl(TEST_URI), 0);
PlacesUtils.bookmarks.removeItem(id1);
promiseAsyncUpdates().then(function ()
{
PlacesTestUtils.promiseAsyncUpdates().then(() => {
do_print("URI still bookmarked => frecency should != 0");
do_check_neq(frecencyForUrl(TEST_URI), 0);
@ -108,16 +102,14 @@ add_test(function cleared_parent_of_visited_bookmark()
TEST_URI,
PlacesUtils.bookmarks.DEFAULT_INDEX,
"bookmark title");
promiseAsyncUpdates().then(function ()
{
PlacesTestUtils.promiseAsyncUpdates().then(() => {
do_print("Bookmarked => frecency of URI should be != 0");
do_check_neq(frecencyForUrl(TEST_URI), 0);
promiseAddVisits(TEST_URI).then(function () {
PlacesUtils.bookmarks.removeFolderChildren(PlacesUtils.unfiledBookmarksFolderId);
promiseAsyncUpdates().then(function ()
{
PlacesTestUtils.promiseAsyncUpdates().then(() => {
do_print("*Visited* URI no longer bookmarked => frecency should != 0");
do_check_neq(frecencyForUrl(TEST_URI), 0);
@ -143,15 +135,13 @@ add_test(function cleared_parent_of_bookmark_still_bookmarked()
TEST_URI,
PlacesUtils.bookmarks.DEFAULT_INDEX,
"bookmark 2 title");
promiseAsyncUpdates().then(function ()
{
PlacesTestUtils.promiseAsyncUpdates().then(() => {
do_print("Bookmarked => frecency of URI should be != 0");
do_check_neq(frecencyForUrl(TEST_URI), 0);
PlacesUtils.bookmarks.removeFolderChildren(PlacesUtils.unfiledBookmarksFolderId);
promiseAsyncUpdates().then(function ()
{
PlacesTestUtils.promiseAsyncUpdates().then(() => {
// URI still bookmarked => frecency should != 0.
do_check_neq(frecencyForUrl(TEST_URI), 0);

Просмотреть файл

@ -28,9 +28,11 @@ function closeWindow(aClose, aPromptFunction)
if (typeof(aPromptFunction) == "function" && !aPromptFunction())
return false;
if (aClose)
if (aClose) {
window.close();
return window.closed;
}
return true;
}

Просмотреть файл

@ -297,7 +297,7 @@
}
#header-utils-btn {
list-style-image: url("chrome://mozapps/skin/extensions/utilities.png");
list-style-image: url("chrome://mozapps/skin/extensions/utilities.svg#utilities");
-moz-margin-end: 18px;
}

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 3.4 KiB

Просмотреть файл

@ -32,7 +32,7 @@ toolkit.jar:
skin/classic/mozapps/extensions/rating-won.png (extensions/rating-won.png)
skin/classic/mozapps/extensions/rating-not-won.png (extensions/rating-not-won.png)
skin/classic/mozapps/extensions/cancel.png (extensions/cancel.png)
skin/classic/mozapps/extensions/utilities.png (extensions/utilities.png)
skin/classic/mozapps/extensions/utilities.svg (../../shared/extensions/utilities.svg)
skin/classic/mozapps/extensions/toolbarbutton-dropmarker.png (extensions/toolbarbutton-dropmarker.png)
skin/classic/mozapps/extensions/heart.png (extensions/heart.png)
skin/classic/mozapps/extensions/navigation.png (extensions/navigation.png)

Просмотреть файл

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
x="0"
y="0"
width="16"
height="16"
viewBox="0 0 16 16">
<style>
use:not(:target) {
display: none;
}
use {
fill: #424f5a;
}
use[id$="-native"] {
fill: GrayText;
}
</style>
<defs style="display: none;">
<path id="utilities-shape" d="m11.5,13.9l-.6-1.5c.3-.2 .5-.4 .8-.6 .2-.2 .4-.5 .6-.7l1.5,.6c.3,.1 .6,0 .7-.3l.4-1c.1-.3 0-.6-.3-.7l-1.5-.6c.1-.6 .1-1.3 0-2l1.5-.6c.3-.1 .4-.4 .3-.7l-.4-1c-.1-.3-.4-.4-.7-.3l-1.5,.6c-.2-.3-.4-.5-.6-.8-.2-.1-.5-.3-.7-.5l.6-1.5c.1-.3 0-.6-.3-.7l-.9-.4c-.3-.1-.6,0-.7,.3l-.6,1.5c-.6-.1-1.3-.1-2,0l-.6-1.5c-.1-.3-.4-.4-.7-.3l-1,.4c-.2,.1-.3,.4-.2,.6l.6,1.5c-.3,.3-.5,.5-.8,.7-.2,.3-.4,.5-.6,.8l-1.5-.7c-.3-.1-.6,0-.7,.3l-.4,.9c-.1,.3 0,.6 .3,.7l1.5,.7c-.1,.6-.1,1.3 0,1.9l-1.5,.6c-.3,.1-.4,.4-.3,.7l.4,1c.1,.3 .4,.4 .7,.3l1.5-.6c.2,.3 .4,.5 .6,.8 .2,.2 .5,.4 .7,.6l-.6,1.5c-.1,.3 0,.6 .3,.7l1,.4c.3,.1 .6,0 .7-.3l.6-1.5c.6,.1 1.3,.1 2,0l.6,1.5c.1,.3 .4,.4 .7,.3l1-.4c.1-.1 .3-.4 .1-.7zm-5.1-4.2c-.9-.9-.9-2.4 0-3.3 .9-.9 2.4-.9 3.3,0 .9,.9 .9,2.4 0,3.3-.9,.9-2.4,.9-3.3,0z"/>
</defs>
<use id="utilities" xlink:href="#utilities-shape"/>
<use id="utilities-native" xlink:href="#utilities-shape"/>
</svg>

После

Ширина:  |  Высота:  |  Размер: 1.3 KiB

Просмотреть файл

@ -332,10 +332,16 @@
}
#header-utils-btn {
list-style-image: url("chrome://mozapps/skin/extensions/utilities.png");
list-style-image: url("chrome://mozapps/skin/extensions/utilities.svg#utilities");
-moz-margin-end: 16px;
}
@media not all and (-moz-windows-default-theme) {
#header-utils-btn {
list-style-image: url("chrome://mozapps/skin/extensions/utilities.svg#utilities-native");
}
}
.view-header {
background-color: rgba(251, 252, 253, 0.25);
padding: 4px;

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 848 B

Просмотреть файл

@ -40,7 +40,7 @@ toolkit.jar:
skin/classic/mozapps/extensions/rating-won.png (extensions/rating-won.png)
skin/classic/mozapps/extensions/rating-not-won.png (extensions/rating-not-won.png)
skin/classic/mozapps/extensions/cancel.png (extensions/cancel.png)
skin/classic/mozapps/extensions/utilities.png (extensions/utilities.png)
skin/classic/mozapps/extensions/utilities.svg (../../shared/extensions/utilities.svg)
skin/classic/mozapps/extensions/heart.png (extensions/heart.png)
skin/classic/mozapps/extensions/navigation.png (extensions/navigation.png)
skin/classic/mozapps/extensions/stripes-warning.png (extensions/stripes-warning.png)
@ -122,7 +122,7 @@ toolkit.jar:
skin/classic/aero/mozapps/extensions/rating-won.png (extensions/rating-won.png)
skin/classic/aero/mozapps/extensions/rating-not-won.png (extensions/rating-not-won.png)
skin/classic/aero/mozapps/extensions/cancel.png (extensions/cancel.png)
skin/classic/aero/mozapps/extensions/utilities.png (extensions/utilities.png)
skin/classic/aero/mozapps/extensions/utilities.svg (../../shared/extensions/utilities.svg)
skin/classic/aero/mozapps/extensions/heart.png (extensions/heart.png)
skin/classic/aero/mozapps/extensions/navigation.png (extensions/navigation.png)
skin/classic/aero/mozapps/extensions/stripes-warning.png (extensions/stripes-warning.png)

Просмотреть файл

@ -1705,88 +1705,86 @@ AndroidBridge::GetFrameNameJavaProfiling(uint32_t aThreadId, uint32_t aSampleId,
}
static float
GetScaleFactor(nsPresContext* mPresContext) {
nsIPresShell* presShell = mPresContext->PresShell();
LayoutDeviceToLayerScale cumulativeResolution(presShell->GetCumulativeResolution().width);
return cumulativeResolution.scale;
GetScaleFactor(nsPresContext* aPresContext) {
nsIPresShell* presShell = aPresContext->PresShell();
LayoutDeviceToLayerScale cumulativeResolution(presShell->GetCumulativeResolution().width);
return cumulativeResolution.scale;
}
nsresult
AndroidBridge::CaptureZoomedView (nsIDOMWindow *window, nsIntRect zoomedViewRect, Object::Param buffer,
AndroidBridge::CaptureZoomedView(nsIDOMWindow *window, nsIntRect zoomedViewRect, Object::Param buffer,
float zoomFactor) {
nsresult rv;
struct timeval timeStart;
gettimeofday (&timeStart, NULL);
nsresult rv;
if (!buffer)
return NS_ERROR_FAILURE;
if (!buffer)
return NS_ERROR_FAILURE;
nsCOMPtr < nsIDOMWindowUtils > utils = do_GetInterface (window);
if (!utils)
return NS_ERROR_FAILURE;
nsCOMPtr <nsIDOMWindowUtils> utils = do_GetInterface(window);
if (!utils)
return NS_ERROR_FAILURE;
JNIEnv* env = GetJNIEnv ();
JNIEnv* env = GetJNIEnv();
AutoLocalJNIFrame jniFrame (env, 0);
AutoLocalJNIFrame jniFrame(env, 0);
nsCOMPtr < nsPIDOMWindow > win = do_QueryInterface (window);
if (!win) {
return NS_ERROR_FAILURE;
}
nsRefPtr < nsPresContext > presContext;
nsCOMPtr <nsPIDOMWindow> win = do_QueryInterface(window);
if (!win) {
return NS_ERROR_FAILURE;
}
nsRefPtr <nsPresContext> presContext;
nsIDocShell* docshell = win->GetDocShell ();
nsIDocShell* docshell = win->GetDocShell();
if (docshell) {
docshell->GetPresContext (getter_AddRefs (presContext));
}
if (docshell) {
docshell->GetPresContext(getter_AddRefs(presContext));
}
if (!presContext) {
return NS_ERROR_FAILURE;
}
nsCOMPtr < nsIPresShell > presShell = presContext->PresShell ();
if (!presContext) {
return NS_ERROR_FAILURE;
}
nsCOMPtr <nsIPresShell> presShell = presContext->PresShell();
float scaleFactor = GetScaleFactor(presContext) ;
float scaleFactor = GetScaleFactor(presContext) ;
nscolor bgColor = NS_RGB (255, 255, 255);
uint32_t renderDocFlags = (nsIPresShell::RENDER_IGNORE_VIEWPORT_SCROLLING | nsIPresShell::RENDER_DOCUMENT_RELATIVE);
nsRect r (presContext->DevPixelsToAppUnits(zoomedViewRect.x / scaleFactor),
presContext->DevPixelsToAppUnits(zoomedViewRect.y / scaleFactor ),
presContext->DevPixelsToAppUnits(zoomedViewRect.width / scaleFactor ),
presContext->DevPixelsToAppUnits(zoomedViewRect.height / scaleFactor ));
nscolor bgColor = NS_RGB(255, 255, 255);
uint32_t renderDocFlags = (nsIPresShell::RENDER_IGNORE_VIEWPORT_SCROLLING | nsIPresShell::RENDER_DOCUMENT_RELATIVE);
nsRect r(presContext->DevPixelsToAppUnits(zoomedViewRect.x / scaleFactor),
presContext->DevPixelsToAppUnits(zoomedViewRect.y / scaleFactor ),
presContext->DevPixelsToAppUnits(zoomedViewRect.width / scaleFactor ),
presContext->DevPixelsToAppUnits(zoomedViewRect.height / scaleFactor ));
bool is24bit = (GetScreenDepth () == 24);
SurfaceFormat format = is24bit ? SurfaceFormat::B8G8R8X8 : SurfaceFormat::R5G6B5;
gfxImageFormat iFormat = gfx::SurfaceFormatToImageFormat(format);
uint32_t stride = gfxASurface::FormatStrideForWidth(iFormat, zoomedViewRect.width);
bool is24bit = (GetScreenDepth() == 24);
SurfaceFormat format = is24bit ? SurfaceFormat::B8G8R8X8 : SurfaceFormat::R5G6B5;
gfxImageFormat iFormat = gfx::SurfaceFormatToImageFormat(format);
uint32_t stride = gfxASurface::FormatStrideForWidth(iFormat, zoomedViewRect.width);
uint8_t* data = static_cast<uint8_t*> (env->GetDirectBufferAddress (buffer.Get()));
if (!data) {
return NS_ERROR_FAILURE;
}
uint8_t* data = static_cast<uint8_t*> (env->GetDirectBufferAddress(buffer.Get()));
if (!data) {
return NS_ERROR_FAILURE;
}
MOZ_ASSERT (gfxPlatform::GetPlatform ()->SupportsAzureContentForType (BackendType::CAIRO),
MOZ_ASSERT (gfxPlatform::GetPlatform()->SupportsAzureContentForType(BackendType::CAIRO),
"Need BackendType::CAIRO support");
RefPtr < DrawTarget > dt = Factory::CreateDrawTargetForData (
BackendType::CAIRO, data, IntSize (zoomedViewRect.width, zoomedViewRect.height), stride,
format);
if (!dt) {
ALOG_BRIDGE ("Error creating DrawTarget");
return NS_ERROR_FAILURE;
}
nsRefPtr < gfxContext > context = new gfxContext (dt);
context->SetMatrix (context->CurrentMatrix ().Scale(zoomFactor, zoomFactor));
RefPtr < DrawTarget > dt = Factory::CreateDrawTargetForData(
BackendType::CAIRO, data, IntSize(zoomedViewRect.width, zoomedViewRect.height), stride,
format);
if (!dt) {
ALOG_BRIDGE("Error creating DrawTarget");
return NS_ERROR_FAILURE;
}
nsRefPtr <gfxContext> context = new gfxContext(dt);
context->SetMatrix(context->CurrentMatrix().Scale(zoomFactor, zoomFactor));
rv = presShell->RenderDocument (r, renderDocFlags, bgColor, context);
rv = presShell->RenderDocument(r, renderDocFlags, bgColor, context);
if (is24bit) {
gfxUtils::ConvertBGRAtoRGBA (data, stride * zoomedViewRect.height);
}
if (is24bit) {
gfxUtils::ConvertBGRAtoRGBA(data, stride * zoomedViewRect.height);
}
LayerView::updateZoomedView(buffer);
LayerView::updateZoomedView(buffer);
NS_ENSURE_SUCCESS (rv, rv);
return NS_OK;
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
nsresult AndroidBridge::CaptureThumbnail(nsIDOMWindow *window, int32_t bufW, int32_t bufH, int32_t tabId, Object::Param buffer, bool &shouldStore)