mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge fx-team to m-c.
This commit is contained in:
commit
5263f8a089
@ -981,7 +981,7 @@ var WebappsHelper = {
|
||||
});
|
||||
break;
|
||||
case "webapps-close":
|
||||
shell.sendEvent(shell.getContentWindow(), "webapps-close",
|
||||
shell.sendEvent(getContentWindow(), "webapps-close",
|
||||
{
|
||||
__exposedProps__: { "manifestURL": "r" },
|
||||
"manifestURL": json.manifestURL
|
||||
|
@ -4206,6 +4206,10 @@ var TabsProgressListener = {
|
||||
if (aFlags & Ci.nsIWebProgressListener.LOCATION_CHANGE_SAME_DOCUMENT)
|
||||
return;
|
||||
|
||||
// Filter out location changes in sub documents.
|
||||
if (!aWebProgress.isTopLevel)
|
||||
return;
|
||||
|
||||
// Only need to call locationChange if the PopupNotifications object
|
||||
// for this window has already been initialized (i.e. its getter no
|
||||
// longer exists)
|
||||
@ -4214,10 +4218,7 @@ var TabsProgressListener = {
|
||||
|
||||
gBrowser.getNotificationBox(aBrowser).removeTransientNotifications();
|
||||
|
||||
// Filter out location changes in sub documents.
|
||||
if (aWebProgress.isTopLevel) {
|
||||
FullZoom.onLocationChange(aLocationURI, false, aBrowser);
|
||||
}
|
||||
FullZoom.onLocationChange(aLocationURI, false, aBrowser);
|
||||
},
|
||||
|
||||
onRefreshAttempted: function (aBrowser, aWebProgress, aURI, aDelay, aSameURI) {
|
||||
|
@ -31,6 +31,15 @@ let gPage = {
|
||||
this._updateAttributes(enabled);
|
||||
},
|
||||
|
||||
/**
|
||||
* True if the page is allowed to capture thumbnails using the background
|
||||
* thumbnail service.
|
||||
*/
|
||||
get allowBackgroundCaptures() {
|
||||
return document.documentElement.getAttribute("allow-background-captures") ==
|
||||
"true";
|
||||
},
|
||||
|
||||
/**
|
||||
* Listens for notifications specific to this page.
|
||||
*/
|
||||
@ -74,6 +83,20 @@ let gPage = {
|
||||
|
||||
this._initialized = true;
|
||||
|
||||
this._mutationObserver = new MutationObserver(() => {
|
||||
if (this.allowBackgroundCaptures) {
|
||||
for (let site of gGrid.sites) {
|
||||
if (site) {
|
||||
site.captureIfMissing();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
this._mutationObserver.observe(document.documentElement, {
|
||||
attributes: true,
|
||||
attributeFilter: ["allow-background-captures"],
|
||||
});
|
||||
|
||||
gLinks.populateCache(function () {
|
||||
// Initialize and render the grid.
|
||||
gGrid.init();
|
||||
@ -123,6 +146,7 @@ let gPage = {
|
||||
handleEvent: function Page_handleEvent(aEvent) {
|
||||
switch (aEvent.type) {
|
||||
case "unload":
|
||||
this._mutationObserver.disconnect();
|
||||
gAllPages.unregister(this);
|
||||
break;
|
||||
case "click":
|
||||
|
31
browser/base/content/newtab/preloaderContent.js
Normal file
31
browser/base/content/newtab/preloaderContent.js
Normal file
@ -0,0 +1,31 @@
|
||||
/* 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/. */
|
||||
|
||||
(function () { // bug 673569 workaround :(
|
||||
|
||||
const ALLOW_BG_CAPTURES_MSG = "BrowserNewTabPreloader:allowBackgroundCaptures";
|
||||
|
||||
addMessageListener(ALLOW_BG_CAPTURES_MSG, function onMsg(msg) {
|
||||
removeMessageListener(ALLOW_BG_CAPTURES_MSG, onMsg);
|
||||
|
||||
if (content.document.readyState == "complete") {
|
||||
setAllowBackgroundCaptures();
|
||||
return;
|
||||
}
|
||||
|
||||
// This is the case when preloading is disabled.
|
||||
addEventListener("load", function onLoad(event) {
|
||||
if (event.target == content.document) {
|
||||
removeEventListener("load", onLoad, true);
|
||||
setAllowBackgroundCaptures();
|
||||
}
|
||||
}, true);
|
||||
});
|
||||
|
||||
function setAllowBackgroundCaptures() {
|
||||
content.document.documentElement.setAttribute("allow-background-captures",
|
||||
"true");
|
||||
}
|
||||
|
||||
})();
|
@ -133,11 +133,20 @@ Site.prototype = {
|
||||
this._updateAttributes(true);
|
||||
// Capture the page if the thumbnail is missing, which will cause page.js
|
||||
// to be notified and call our refreshThumbnail() method.
|
||||
BackgroundPageThumbs.captureIfMissing(this.url);
|
||||
this.captureIfMissing();
|
||||
// but still display whatever thumbnail might be available now.
|
||||
this.refreshThumbnail();
|
||||
},
|
||||
|
||||
/**
|
||||
* Captures the site's thumbnail in the background, but only if there's no
|
||||
* existing thumbnail and the page allows background captures.
|
||||
*/
|
||||
captureIfMissing: function Site_captureIfMissing() {
|
||||
if (gPage.allowBackgroundCaptures)
|
||||
BackgroundPageThumbs.captureIfMissing(this.url);
|
||||
},
|
||||
|
||||
/**
|
||||
* Refreshes the thumbnail for the site.
|
||||
*/
|
||||
|
@ -829,23 +829,41 @@ var tests = [
|
||||
});
|
||||
}
|
||||
},
|
||||
{ // Test #28 - location change in embedded frame removes notification
|
||||
{ // Test #28 - location change in an embedded frame should not remove a notification
|
||||
run: function () {
|
||||
loadURI("data:text/html,<iframe id='iframe' src='http://example.com/'>", function () {
|
||||
let notifyObj = new basicNotification();
|
||||
notifyObj.options.eventCallback = function (eventName) {
|
||||
loadURI("data:text/html;charset=utf8,<iframe id='iframe' src='http://example.com/'>", function () {
|
||||
this.notifyObj = new basicNotification();
|
||||
this.notifyObj.options.eventCallback = function (eventName) {
|
||||
if (eventName == "removed") {
|
||||
ok(true, "Notification removed in background tab after reloading");
|
||||
executeSoon(goNext);
|
||||
ok(false, "Test 28: Notification removed from browser when subframe navigated");
|
||||
}
|
||||
};
|
||||
showNotification(notifyObj);
|
||||
executeSoon(function () {
|
||||
content.document.getElementById("iframe")
|
||||
.setAttribute("src", "http://example.org/");
|
||||
});
|
||||
});
|
||||
}
|
||||
showNotification(this.notifyObj);
|
||||
}.bind(this));
|
||||
},
|
||||
onShown: function (popup) {
|
||||
let self = this;
|
||||
let progressListener = {
|
||||
onLocationChange: function onLocationChange(aBrowser) {
|
||||
if (aBrowser != gBrowser.selectedBrowser) {
|
||||
return;
|
||||
}
|
||||
let notification = PopupNotifications.getNotification(self.notifyObj.id,
|
||||
self.notifyObj.browser);
|
||||
ok(notification != null, "Test 28: Notification remained when subframe navigated");
|
||||
self.notifyObj.options.eventCallback = undefined;
|
||||
|
||||
notification.remove();
|
||||
gBrowser.removeTabsProgressListener(progressListener);
|
||||
},
|
||||
};
|
||||
|
||||
info("Test 28: Adding progress listener and performing navigation");
|
||||
gBrowser.addTabsProgressListener(progressListener);
|
||||
content.document.getElementById("iframe")
|
||||
.setAttribute("src", "http://example.org/");
|
||||
},
|
||||
onHidden: function () {}
|
||||
},
|
||||
{ // Test #29 - Popup Notifications should catch exceptions from callbacks
|
||||
run: function () {
|
||||
|
@ -1,6 +1,7 @@
|
||||
[DEFAULT]
|
||||
support-files = head.js
|
||||
|
||||
[browser_newtab_background_captures.js]
|
||||
[browser_newtab_block.js]
|
||||
[browser_newtab_bug721442.js]
|
||||
[browser_newtab_bug722273.js]
|
||||
|
@ -0,0 +1,100 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Verifies that hidden, pre-loaded newtabs don't allow background captures, and
|
||||
* when unhidden, do allow background captures.
|
||||
*/
|
||||
|
||||
const CAPTURE_PREF = "browser.pagethumbnails.capturing_disabled";
|
||||
|
||||
function runTests() {
|
||||
let imports = {};
|
||||
Cu.import("resource://gre/modules/PageThumbs.jsm", imports);
|
||||
Cu.import("resource:///modules/BrowserNewTabPreloader.jsm", imports);
|
||||
|
||||
// Disable captures.
|
||||
let originalDisabledState = Services.prefs.getBoolPref(CAPTURE_PREF);
|
||||
Services.prefs.setBoolPref(CAPTURE_PREF, true);
|
||||
|
||||
// Make sure the thumbnail doesn't exist yet.
|
||||
let siteName = "newtab_background_captures";
|
||||
let url = "http://example.com/#" + siteName;
|
||||
let path = imports.PageThumbsStorage.getFilePathForURL(url);
|
||||
let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
|
||||
file.initWithPath(path);
|
||||
try {
|
||||
file.remove(false);
|
||||
}
|
||||
catch (err) {}
|
||||
|
||||
// Add a top site.
|
||||
yield setLinks(siteName);
|
||||
|
||||
// We need a handle to a hidden, pre-loaded newtab so we can verify that it
|
||||
// doesn't allow background captures. Add a newtab, which triggers creation
|
||||
// of a hidden newtab, and then keep calling BrowserNewTabPreloader.newTab
|
||||
// until it returns true, meaning that it swapped the passed-in tab's docshell
|
||||
// for the hidden newtab docshell.
|
||||
let tab = gWindow.gBrowser.addTab("about:blank");
|
||||
yield addNewTabPageTab();
|
||||
let swapWaitCount = 0;
|
||||
let swapped = imports.BrowserNewTabPreloader.newTab(tab);
|
||||
while (!swapped) {
|
||||
if (++swapWaitCount == 10) {
|
||||
ok(false, "Timed out waiting for newtab docshell swap.");
|
||||
return;
|
||||
}
|
||||
// Give the hidden newtab some time to finish loading.
|
||||
yield wait(2000);
|
||||
info("Checking newtab swap " + swapWaitCount);
|
||||
swapped = imports.BrowserNewTabPreloader.newTab(tab);
|
||||
}
|
||||
|
||||
// The tab's docshell is now the previously hidden newtab docshell.
|
||||
let doc = tab.linkedBrowser.contentDocument;
|
||||
isnot(doc.documentElement.getAttribute("allow-background-captures"), "true",
|
||||
"Pre-loaded docshell just synchronously swapped, so background " +
|
||||
"captures should not be allowed yet");
|
||||
|
||||
// Enable captures.
|
||||
Services.prefs.setBoolPref(CAPTURE_PREF, false);
|
||||
|
||||
// Now that the newtab is visible, its allow-background-captures attribute
|
||||
// should be set eventually.
|
||||
let allowBackgroundCaptures = false;
|
||||
let mutationObserver = new MutationObserver(() => {
|
||||
mutationObserver.disconnect();
|
||||
allowBackgroundCaptures = true;
|
||||
is(doc.documentElement.getAttribute("allow-background-captures"), "true",
|
||||
"allow-background-captures should now be true");
|
||||
info("Waiting for thumbnail to be created after observing " +
|
||||
"allow-background-captures change");
|
||||
});
|
||||
mutationObserver.observe(doc.documentElement, {
|
||||
attributes: true,
|
||||
attributeFilter: ["allow-background-captures"],
|
||||
});
|
||||
|
||||
// And the allow-background-captures change should trigger the thumbnail
|
||||
// capture.
|
||||
Services.obs.addObserver(function onCreate(subj, topic, data) {
|
||||
if (data != url)
|
||||
return;
|
||||
ok(allowBackgroundCaptures,
|
||||
"page-thumbnail:create should be observed after " +
|
||||
"allow-background-captures was set");
|
||||
Services.obs.removeObserver(onCreate, "page-thumbnail:create");
|
||||
// Test finished!
|
||||
Services.prefs.setBoolPref(CAPTURE_PREF, originalDisabledState);
|
||||
file.remove(false);
|
||||
TestRunner.next();
|
||||
}, "page-thumbnail:create", false);
|
||||
|
||||
info("Waiting for allow-background-captures change");
|
||||
yield true;
|
||||
}
|
||||
|
||||
function wait(ms) {
|
||||
setTimeout(TestRunner.next, ms);
|
||||
}
|
@ -64,6 +64,7 @@ browser.jar:
|
||||
content/browser/newtab/newTab.xul (content/newtab/newTab.xul)
|
||||
* content/browser/newtab/newTab.js (content/newtab/newTab.js)
|
||||
content/browser/newtab/newTab.css (content/newtab/newTab.css)
|
||||
content/browser/newtab/preloaderContent.js (content/newtab/preloaderContent.js)
|
||||
* content/browser/pageinfo/pageInfo.xul (content/pageinfo/pageInfo.xul)
|
||||
content/browser/pageinfo/pageInfo.js (content/pageinfo/pageInfo.js)
|
||||
content/browser/pageinfo/pageInfo.css (content/pageinfo/pageInfo.css)
|
||||
|
@ -205,7 +205,7 @@ var bookmarksObserver = {
|
||||
}
|
||||
},
|
||||
|
||||
onItemRemoved: function PSB_onItemRemoved(aItemId, aFolder, aIndex,
|
||||
onItemRemoved: function PSB_onItemRemoved(aItemId, aFolderId, aIndex,
|
||||
aItemType) {
|
||||
var views = getViewsForFolder(aFolderId);
|
||||
ok(views.length > 0, "Found affected views (" + views.length + "): " + views);
|
||||
|
@ -19,11 +19,11 @@ module.exports = ConnectionStore = function(connection) {
|
||||
|
||||
ObservableObject.call(this, {status:null,host:null,port:null});
|
||||
|
||||
this._destroy = this._destroy.bind(this);
|
||||
this.destroy = this.destroy.bind(this);
|
||||
this._feedStore = this._feedStore.bind(this);
|
||||
|
||||
this._connection = connection;
|
||||
this._connection.once(Connection.Events.DESTROYED, this._destroy);
|
||||
this._connection.once(Connection.Events.DESTROYED, this.destroy);
|
||||
this._connection.on(Connection.Events.STATUS_CHANGED, this._feedStore);
|
||||
this._connection.on(Connection.Events.PORT_CHANGED, this._feedStore);
|
||||
this._connection.on(Connection.Events.HOST_CHANGED, this._feedStore);
|
||||
@ -32,12 +32,18 @@ module.exports = ConnectionStore = function(connection) {
|
||||
}
|
||||
|
||||
ConnectionStore.prototype = {
|
||||
_destroy: function() {
|
||||
this._connection.off(Connection.Events.STATUS_CHANGED, this._feedStore);
|
||||
this._connection.off(Connection.Events.PORT_CHANGED, this._feedStore);
|
||||
this._connection.off(Connection.Events.HOST_CHANGED, this._feedStore);
|
||||
_knownConnectionStores.delete(this._connection);
|
||||
this._connection = null;
|
||||
destroy: function() {
|
||||
if (this._connection) {
|
||||
// While this.destroy is bound using .once() above, that event may not
|
||||
// have occurred when the ConnectionStore client calls destroy, so we
|
||||
// manually remove it here.
|
||||
this._connection.off(Connection.Events.DESTROYED, this.destroy);
|
||||
this._connection.off(Connection.Events.STATUS_CHANGED, this._feedStore);
|
||||
this._connection.off(Connection.Events.PORT_CHANGED, this._feedStore);
|
||||
this._connection.off(Connection.Events.HOST_CHANGED, this._feedStore);
|
||||
_knownConnectionStores.delete(this._connection);
|
||||
this._connection = null;
|
||||
}
|
||||
},
|
||||
|
||||
_feedStore: function() {
|
||||
|
@ -18,6 +18,11 @@ const DeviceStore = require("devtools/app-manager/device-store");
|
||||
const simulatorsStore = require("devtools/app-manager/simulators-store");
|
||||
const adbStore = require("devtools/app-manager/builtin-adb-store");
|
||||
|
||||
window.addEventListener("unload", function onUnload() {
|
||||
window.removeEventListener("unload", onUnload);
|
||||
UI.destroy();
|
||||
});
|
||||
|
||||
let UI = {
|
||||
init: function() {
|
||||
this.useFloatingScrollbarsIfNeeded();
|
||||
@ -54,10 +59,7 @@ let UI = {
|
||||
let pre = document.querySelector("#logs > pre");
|
||||
pre.textContent = this.connection.logs;
|
||||
pre.scrollTop = pre.scrollTopMax;
|
||||
this.connection.on(Connection.Events.NEW_LOG, (event, str) => {
|
||||
pre.textContent += "\n" + str;
|
||||
pre.scrollTop = pre.scrollTopMax;
|
||||
});
|
||||
this.connection.on(Connection.Events.NEW_LOG, this._onNewLog);
|
||||
|
||||
this.template = new Template(document.body, this.store, Utils.l10n);
|
||||
this.template.start();
|
||||
@ -66,6 +68,18 @@ let UI = {
|
||||
this._onSimulatorDisconnected = this._onSimulatorDisconnected.bind(this);
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
this.store.destroy();
|
||||
this.connection.off(Connection.Events.NEW_LOG, this._onNewLog);
|
||||
this.template.destroy();
|
||||
},
|
||||
|
||||
_onNewLog: function(event, str) {
|
||||
let pre = document.querySelector("#logs > pre");
|
||||
pre.textContent += "\n" + str;
|
||||
pre.scrollTop = pre.scrollTopMax;
|
||||
},
|
||||
|
||||
useFloatingScrollbarsIfNeeded: function() {
|
||||
if (Services.appinfo.OS == "Darwin") {
|
||||
return;
|
||||
|
@ -32,12 +32,16 @@ window.addEventListener("message", function(event) {
|
||||
} catch(e) {
|
||||
Cu.reportError(e);
|
||||
}
|
||||
}, false);
|
||||
});
|
||||
|
||||
window.addEventListener("unload", function onUnload() {
|
||||
window.removeEventListener("unload", onUnload);
|
||||
UI.destroy();
|
||||
});
|
||||
|
||||
let UI = {
|
||||
init: function() {
|
||||
this.showFooterIfNeeded();
|
||||
this._onConnectionStatusChange = this._onConnectionStatusChange.bind(this);
|
||||
this.setTab("apps");
|
||||
if (this.connection) {
|
||||
this.onNewConnection();
|
||||
@ -46,6 +50,18 @@ let UI = {
|
||||
}
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
if (this.connection) {
|
||||
this.connection.off(Connection.Events.STATUS_CHANGED, this._onConnectionStatusChange);
|
||||
}
|
||||
if (this.store) {
|
||||
this.store.destroy();
|
||||
}
|
||||
if (this.template) {
|
||||
this.template.destroy();
|
||||
}
|
||||
},
|
||||
|
||||
showFooterIfNeeded: function() {
|
||||
let footer = document.querySelector("#connection-footer");
|
||||
if (window.parent == window) {
|
||||
@ -73,6 +89,9 @@ let UI = {
|
||||
"apps": new WebappsStore(this.connection),
|
||||
});
|
||||
|
||||
if (this.template) {
|
||||
this.template.destroy();
|
||||
}
|
||||
this.template = new Template(document.body, this.store, Utils.l10n);
|
||||
|
||||
this.template.start();
|
||||
@ -189,3 +208,7 @@ let UI = {
|
||||
return deferred.promise;
|
||||
},
|
||||
}
|
||||
|
||||
// This must be bound immediately, as it might be used via the message listener
|
||||
// before UI.init() has been called.
|
||||
UI._onConnectionStatusChange = UI._onConnectionStatusChange.bind(UI);
|
||||
|
@ -40,13 +40,25 @@ window.addEventListener("message", function(event) {
|
||||
}
|
||||
}, false);
|
||||
|
||||
window.addEventListener("unload", function onUnload() {
|
||||
window.removeEventListener("unload", onUnload);
|
||||
if (connection) {
|
||||
connection.off(Connection.Status.CONNECTED, onConnected);
|
||||
connection.off(Connection.Status.DISCONNECTED, onDisconnected);
|
||||
}
|
||||
});
|
||||
|
||||
function onNewConnection() {
|
||||
connection.on(Connection.Status.CONNECTED, () => {
|
||||
document.querySelector("#content").classList.add("connected");
|
||||
});
|
||||
connection.on(Connection.Status.DISCONNECTED, () => {
|
||||
document.querySelector("#content").classList.remove("connected");
|
||||
});
|
||||
connection.on(Connection.Status.CONNECTED, onConnected);
|
||||
connection.on(Connection.Status.DISCONNECTED, onDisconnected);
|
||||
}
|
||||
|
||||
function onConnected() {
|
||||
document.querySelector("#content").classList.add("connected");
|
||||
}
|
||||
|
||||
function onDisconnected() {
|
||||
document.querySelector("#content").classList.remove("connected");
|
||||
}
|
||||
|
||||
function selectTab(id) {
|
||||
|
@ -35,7 +35,12 @@ window.addEventListener("message", function(event) {
|
||||
}
|
||||
}
|
||||
} catch(e) {}
|
||||
}, false);
|
||||
});
|
||||
|
||||
window.addEventListener("unload", function onUnload() {
|
||||
window.removeEventListener("unload", onUnload);
|
||||
UI.destroy();
|
||||
});
|
||||
|
||||
let UI = {
|
||||
isReady: false,
|
||||
@ -55,8 +60,15 @@ let UI = {
|
||||
});
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
if (this.connection) {
|
||||
this.connection.off(Connection.Events.STATUS_CHANGED, this._onConnectionStatusChange);
|
||||
}
|
||||
this.template.destroy();
|
||||
},
|
||||
|
||||
onNewConnection: function() {
|
||||
this.connection.on(Connection.Events.STATUS_CHANGED, () => this._onConnectionStatusChange());
|
||||
this.connection.on(Connection.Events.STATUS_CHANGED, this._onConnectionStatusChange);
|
||||
this._onConnectionStatusChange();
|
||||
},
|
||||
|
||||
@ -427,4 +439,8 @@ let UI = {
|
||||
}
|
||||
};
|
||||
|
||||
// This must be bound immediately, as it might be used via the message listener
|
||||
// before UI.onload() has been called.
|
||||
UI._onConnectionStatusChange = UI._onConnectionStatusChange.bind(UI);
|
||||
|
||||
EventEmitter.decorate(UI);
|
||||
|
@ -69,7 +69,8 @@ function Template(root, store, l10nResolver) {
|
||||
this._root = root;
|
||||
this._doc = this._root.ownerDocument;
|
||||
|
||||
this._store.on("set", (event,path,value) => this._storeChanged(path,value));
|
||||
this._storeChanged = this._storeChanged.bind(this);
|
||||
this._store.on("set", this._storeChanged);
|
||||
}
|
||||
|
||||
Template.prototype = {
|
||||
@ -77,6 +78,12 @@ Template.prototype = {
|
||||
this._processTree(this._root);
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
this._store.off("set", this._storeChanged);
|
||||
this._root = null;
|
||||
this._doc = null;
|
||||
},
|
||||
|
||||
_resolvePath: function(path, defaultValue=null) {
|
||||
|
||||
// From the store, get the value of an object located
|
||||
@ -110,7 +117,7 @@ Template.prototype = {
|
||||
return obj;
|
||||
},
|
||||
|
||||
_storeChanged: function(path, value) {
|
||||
_storeChanged: function(event, path, value) {
|
||||
|
||||
// The store has changed (a "set" event has been emitted).
|
||||
// We need to invalidate and rebuild the affected elements.
|
||||
|
@ -19,19 +19,36 @@ let Utils = (function() {
|
||||
const EventEmitter = require("devtools/shared/event-emitter");
|
||||
|
||||
|
||||
function _forwardSetEvent(key, store, finalStore) {
|
||||
store.on("set", function(event, path, value) {
|
||||
function _createSetEventForwarder(key, finalStore) {
|
||||
return function(event, path, value) {
|
||||
finalStore.emit("set", [key].concat(path), value);
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
function mergeStores(stores) {
|
||||
let finalStore = {object:{}};
|
||||
|
||||
EventEmitter.decorate(finalStore);
|
||||
|
||||
let setEventForwarders = {};
|
||||
|
||||
for (let key in stores) {
|
||||
finalStore.object[key] = stores[key].object,
|
||||
_forwardSetEvent(key, stores[key], finalStore);
|
||||
let store = stores[key];
|
||||
finalStore.object[key] = store.object;
|
||||
setEventForwarders[key] = _createSetEventForwarder(key, finalStore);
|
||||
store.on("set", setEventForwarders[key]);
|
||||
}
|
||||
|
||||
finalStore.destroy = () => {
|
||||
for (let key in stores) {
|
||||
let store = stores[key];
|
||||
store.off("set", setEventForwarders[key]);
|
||||
if (store.destroy) {
|
||||
store.destroy();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return finalStore;
|
||||
}
|
||||
|
||||
|
@ -25,21 +25,27 @@ module.exports = DeviceStore = function(connection) {
|
||||
|
||||
this._resetStore();
|
||||
|
||||
this._destroy = this._destroy.bind(this);
|
||||
this.destroy = this.destroy.bind(this);
|
||||
this._onStatusChanged = this._onStatusChanged.bind(this);
|
||||
|
||||
this._connection = connection;
|
||||
this._connection.once(Connection.Events.DESTROYED, this._destroy);
|
||||
this._connection.once(Connection.Events.DESTROYED, this.destroy);
|
||||
this._connection.on(Connection.Events.STATUS_CHANGED, this._onStatusChanged);
|
||||
this._onStatusChanged();
|
||||
return this;
|
||||
}
|
||||
|
||||
DeviceStore.prototype = {
|
||||
_destroy: function() {
|
||||
this._connection.off(Connection.Events.STATUS_CHANGED, this._onStatusChanged);
|
||||
_knownDeviceStores.delete(this._connection);
|
||||
this._connection = null;
|
||||
destroy: function() {
|
||||
if (this._connection) {
|
||||
// While this.destroy is bound using .once() above, that event may not
|
||||
// have occurred when the DeviceStore client calls destroy, so we
|
||||
// manually remove it here.
|
||||
this._connection.off(Connection.Events.DESTROYED, this.destroy);
|
||||
this._connection.off(Connection.Events.STATUS_CHANGED, this._onStatusChanged);
|
||||
_knownDeviceStores.delete(this._connection);
|
||||
this._connection = null;
|
||||
}
|
||||
},
|
||||
|
||||
_resetStore: function() {
|
||||
|
@ -101,7 +101,9 @@ function waitForProjectsPanel(deferred = promise.defer()) {
|
||||
let projectsWindow = getProjectsWindow();
|
||||
let projectsUI = projectsWindow.UI;
|
||||
if (!projectsUI) {
|
||||
info("projectsUI false");
|
||||
projectsWindow.addEventListener("load", function onLoad() {
|
||||
info("got load event");
|
||||
projectsWindow.removeEventListener("load", onLoad);
|
||||
waitForProjectsPanel(deferred);
|
||||
});
|
||||
@ -109,10 +111,12 @@ function waitForProjectsPanel(deferred = promise.defer()) {
|
||||
}
|
||||
|
||||
if (projectsUI.isReady) {
|
||||
info("projectsUI ready");
|
||||
deferred.resolve();
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
info("projectsUI not ready");
|
||||
projectsUI.once("ready", deferred.resolve);
|
||||
return deferred.promise;
|
||||
}
|
||||
|
@ -25,21 +25,27 @@ module.exports = WebappsStore = function(connection) {
|
||||
|
||||
this._resetStore();
|
||||
|
||||
this._destroy = this._destroy.bind(this);
|
||||
this.destroy = this.destroy.bind(this);
|
||||
this._onStatusChanged = this._onStatusChanged.bind(this);
|
||||
|
||||
this._connection = connection;
|
||||
this._connection.once(Connection.Events.DESTROYED, this._destroy);
|
||||
this._connection.once(Connection.Events.DESTROYED, this.destroy);
|
||||
this._connection.on(Connection.Events.STATUS_CHANGED, this._onStatusChanged);
|
||||
this._onStatusChanged();
|
||||
return this;
|
||||
}
|
||||
|
||||
WebappsStore.prototype = {
|
||||
_destroy: function() {
|
||||
this._connection.off(Connection.Events.STATUS_CHANGED, this._onStatusChanged);
|
||||
_knownWebappsStores.delete(this._connection);
|
||||
this._connection = null;
|
||||
destroy: function() {
|
||||
if (this._connection) {
|
||||
// While this.destroy is bound using .once() above, that event may not
|
||||
// have occurred when the WebappsStore client calls destroy, so we
|
||||
// manually remove it here.
|
||||
this._connection.off(Connection.Events.DESTROYED, this.destroy);
|
||||
this._connection.off(Connection.Events.STATUS_CHANGED, this._onStatusChanged);
|
||||
_knownWebappsStores.delete(this._connection);
|
||||
this._connection = null;
|
||||
}
|
||||
},
|
||||
|
||||
_resetStore: function() {
|
||||
|
@ -49,7 +49,7 @@
|
||||
<button id="requests-menu-status-button"
|
||||
class="requests-menu-header-button requests-menu-status"
|
||||
onclick="NetMonitorView.RequestsMenu.sortBy('status')"
|
||||
label="&netmonitorUI.toolbar.status;">
|
||||
label="&netmonitorUI.toolbar.status2;">
|
||||
</button>
|
||||
<button id="requests-menu-method-button"
|
||||
class="requests-menu-header-button requests-menu-method"
|
||||
|
@ -19,8 +19,13 @@ const Editor = require("devtools/sourceeditor/editor");
|
||||
|
||||
// The panel's window global is an EventEmitter firing the following events:
|
||||
const EVENTS = {
|
||||
// When new programs are received from the server.
|
||||
NEW_PROGRAM: "ShaderEditor:NewProgram",
|
||||
PROGRAMS_ADDED: "ShaderEditor:ProgramsAdded",
|
||||
|
||||
// When the vertex and fragment sources were shown in the editor.
|
||||
SOURCES_SHOWN: "ShaderEditor:SourcesShown",
|
||||
|
||||
// When a shader's source was edited and compiled via the editor.
|
||||
SHADER_COMPILED: "ShaderEditor:ShaderCompiled"
|
||||
};
|
||||
@ -72,10 +77,12 @@ let EventsHandler = {
|
||||
*/
|
||||
initialize: function() {
|
||||
this._onHostChanged = this._onHostChanged.bind(this);
|
||||
this._onWillNavigate = this._onWillNavigate.bind(this);
|
||||
this._onTabNavigated = this._onTabNavigated.bind(this);
|
||||
this._onProgramLinked = this._onProgramLinked.bind(this);
|
||||
this._onProgramsAdded = this._onProgramsAdded.bind(this);
|
||||
gToolbox.on("host-changed", this._onHostChanged);
|
||||
gTarget.on("will-navigate", this._onWillNavigate);
|
||||
gTarget.on("will-navigate", this._onTabNavigated);
|
||||
gTarget.on("navigate", this._onTabNavigated);
|
||||
gFront.on("program-linked", this._onProgramLinked);
|
||||
|
||||
},
|
||||
@ -85,7 +92,8 @@ let EventsHandler = {
|
||||
*/
|
||||
destroy: function() {
|
||||
gToolbox.off("host-changed", this._onHostChanged);
|
||||
gTarget.off("will-navigate", this._onWillNavigate);
|
||||
gTarget.off("will-navigate", this._onTabNavigated);
|
||||
gTarget.off("navigate", this._onTabNavigated);
|
||||
gFront.off("program-linked", this._onProgramLinked);
|
||||
},
|
||||
|
||||
@ -101,20 +109,51 @@ let EventsHandler = {
|
||||
/**
|
||||
* Called for each location change in the debugged tab.
|
||||
*/
|
||||
_onWillNavigate: function() {
|
||||
gFront.setup();
|
||||
_onTabNavigated: function(event) {
|
||||
switch (event) {
|
||||
case "will-navigate": {
|
||||
// Make sure the backend is prepared to handle WebGL contexts.
|
||||
gFront.setup({ reload: false });
|
||||
|
||||
ShadersListView.empty();
|
||||
ShadersEditorsView.setText({ vs: "", fs: "" });
|
||||
$("#reload-notice").hidden = true;
|
||||
$("#waiting-notice").hidden = false;
|
||||
$("#content").hidden = true;
|
||||
// Reset UI.
|
||||
ShadersListView.empty();
|
||||
ShadersEditorsView.setText({ vs: "", fs: "" });
|
||||
$("#reload-notice").hidden = true;
|
||||
$("#waiting-notice").hidden = false;
|
||||
$("#content").hidden = true;
|
||||
break;
|
||||
}
|
||||
case "navigate": {
|
||||
// Manually retrieve the list of program actors known to the server,
|
||||
// because the backend won't emit "program-linked" notifications
|
||||
// in the case of a bfcache navigation (since no new programs are
|
||||
// actually linked).
|
||||
gFront.getPrograms().then(this._onProgramsAdded);
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Called every time a program was linked in the debugged tab.
|
||||
*/
|
||||
_onProgramLinked: function(programActor) {
|
||||
this._addProgram(programActor);
|
||||
window.emit(EVENTS.NEW_PROGRAM);
|
||||
},
|
||||
|
||||
/**
|
||||
* Callback for the front's getPrograms() method.
|
||||
*/
|
||||
_onProgramsAdded: function(programActors) {
|
||||
programActors.forEach(this._addProgram);
|
||||
window.emit(EVENTS.PROGRAMS_ADDED);
|
||||
},
|
||||
|
||||
/**
|
||||
* Adds a program to the shaders list and unhides any modal notices.
|
||||
*/
|
||||
_addProgram: function(programActor) {
|
||||
$("#waiting-notice").hidden = true;
|
||||
$("#reload-notice").hidden = true;
|
||||
$("#content").hidden = false;
|
||||
@ -163,6 +202,10 @@ let ShadersListView = Heritage.extend(WidgetMethods, {
|
||||
* The program actor coming from the active thread.
|
||||
*/
|
||||
addProgram: function(programActor) {
|
||||
if (this.hasProgram(programActor)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Currently, there's no good way of differentiating between programs
|
||||
// in a way that helps humans. It will be a good idea to implement a
|
||||
// standard of allowing debuggees to add some identifiable metadata to their
|
||||
@ -192,6 +235,18 @@ let ShadersListView = Heritage.extend(WidgetMethods, {
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns whether a program was already added to this programs container.
|
||||
*
|
||||
* @param object programActor
|
||||
* The program actor coming from the active thread.
|
||||
* @param boolean
|
||||
* True if the program was added, false otherwise.
|
||||
*/
|
||||
hasProgram: function(programActor) {
|
||||
return !!this.attachments.filter(e => e.programActor == programActor).length;
|
||||
},
|
||||
|
||||
/**
|
||||
* The select listener for the sources container.
|
||||
*/
|
||||
|
@ -24,7 +24,7 @@
|
||||
<button id="requests-menu-reload-notice-button"
|
||||
class="devtools-toolbarbutton"
|
||||
label="&shaderEditorUI.reloadNotice1;"
|
||||
oncommand="gFront.setup();"/>
|
||||
oncommand="gFront.setup({ reload: true });"/>
|
||||
<label id="requests-menu-reload-notice-label"
|
||||
class="plain"
|
||||
value="&shaderEditorUI.reloadNotice2;"/>
|
||||
|
@ -6,6 +6,7 @@ support-files =
|
||||
head.js
|
||||
|
||||
[browser_se_aaa_run_first_leaktest.js]
|
||||
[browser_se_bfcache.js]
|
||||
[browser_se_editors-contents.js]
|
||||
[browser_se_editors-lazy-init.js]
|
||||
[browser_se_first-run.js]
|
||||
@ -31,3 +32,5 @@ support-files =
|
||||
[browser_webgl-actor-test-12.js]
|
||||
[browser_webgl-actor-test-13.js]
|
||||
[browser_webgl-actor-test-14.js]
|
||||
[browser_webgl-actor-test-15.js]
|
||||
[browser_webgl-actor-test-16.js]
|
||||
|
64
browser/devtools/shadereditor/test/browser_se_bfcache.js
Normal file
64
browser/devtools/shadereditor/test/browser_se_bfcache.js
Normal file
@ -0,0 +1,64 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Tests if the shader editor works with bfcache.
|
||||
*/
|
||||
|
||||
function ifWebGLSupported() {
|
||||
let [target, debuggee, panel] = yield initShaderEditor(SIMPLE_CANVAS_URL);
|
||||
let { gFront, $, EVENTS, ShadersListView, ShadersEditorsView } = panel.panelWin;
|
||||
|
||||
let reloaded = reload(target);
|
||||
let firstProgram = yield once(gFront, "program-linked");
|
||||
yield reloaded;
|
||||
|
||||
let navigated = navigate(target, MULTIPLE_CONTEXTS_URL);
|
||||
let secondProgram = yield once(gFront, "program-linked");
|
||||
let thirdProgram = yield once(gFront, "program-linked");
|
||||
yield navigated;
|
||||
|
||||
let vsEditor = yield ShadersEditorsView._getEditor("vs");
|
||||
let fsEditor = yield ShadersEditorsView._getEditor("fs");
|
||||
|
||||
yield navigateInHistory(target, "back", "will-navigate");
|
||||
yield once(panel.panelWin, EVENTS.PROGRAMS_ADDED);
|
||||
yield once(panel.panelWin, EVENTS.SOURCES_SHOWN);
|
||||
|
||||
is($("#content").hidden, false,
|
||||
"The tool's content should not be hidden.");
|
||||
is(ShadersListView.itemCount, 1,
|
||||
"The shaders list contains one entry after navigating back.");
|
||||
is(ShadersListView.selectedIndex, 0,
|
||||
"The shaders list has a correct selection after navigating back.");
|
||||
|
||||
is(vsEditor.getText().indexOf("gl_Position"), 170,
|
||||
"The vertex shader editor contains the correct text.");
|
||||
is(fsEditor.getText().indexOf("gl_FragColor"), 97,
|
||||
"The fragment shader editor contains the correct text.");
|
||||
|
||||
yield navigateInHistory(target, "forward", "will-navigate");
|
||||
yield once(panel.panelWin, EVENTS.PROGRAMS_ADDED);
|
||||
yield once(panel.panelWin, EVENTS.SOURCES_SHOWN);
|
||||
|
||||
is($("#content").hidden, false,
|
||||
"The tool's content should not be hidden.");
|
||||
is(ShadersListView.itemCount, 2,
|
||||
"The shaders list contains two entries after navigating forward.");
|
||||
is(ShadersListView.selectedIndex, 0,
|
||||
"The shaders list has a correct selection after navigating forward.");
|
||||
|
||||
is(vsEditor.getText().indexOf("gl_Position"), 100,
|
||||
"The vertex shader editor contains the correct text.");
|
||||
is(fsEditor.getText().indexOf("gl_FragColor"), 89,
|
||||
"The fragment shader editor contains the correct text.");
|
||||
|
||||
yield teardown(panel);
|
||||
finish();
|
||||
}
|
||||
|
||||
function once(aTarget, aEvent) {
|
||||
let deferred = promise.defer();
|
||||
aTarget.once(aEvent, deferred.resolve);
|
||||
return deferred.promise;
|
||||
}
|
@ -12,7 +12,7 @@ function ifWebGLSupported() {
|
||||
let navigated = once(target, "navigate");
|
||||
let linked = once(front, "program-linked");
|
||||
|
||||
yield front.setup();
|
||||
yield front.setup({ reload: true });
|
||||
ok(true, "The front was setup up successfully.");
|
||||
|
||||
yield navigated;
|
||||
|
@ -8,7 +8,7 @@
|
||||
|
||||
function ifWebGLSupported() {
|
||||
let [target, debuggee, front] = yield initBackend(SIMPLE_CANVAS_URL);
|
||||
front.setup();
|
||||
front.setup({ reload: true });
|
||||
|
||||
let programActor = yield once(front, "program-linked");
|
||||
ok(programActor,
|
||||
|
@ -8,7 +8,7 @@
|
||||
|
||||
function ifWebGLSupported() {
|
||||
let [target, debuggee, front] = yield initBackend(SIMPLE_CANVAS_URL);
|
||||
front.setup();
|
||||
front.setup({ reload: true });
|
||||
|
||||
let programActor = yield once(front, "program-linked");
|
||||
let vertexShader = yield programActor.getVertexShader();
|
||||
|
@ -8,7 +8,7 @@
|
||||
|
||||
function ifWebGLSupported() {
|
||||
let [target, debuggee, front] = yield initBackend(SIMPLE_CANVAS_URL);
|
||||
front.setup();
|
||||
front.setup({ reload: true });
|
||||
|
||||
let programActor = yield once(front, "program-linked");
|
||||
let vertexShader = yield programActor.getVertexShader();
|
||||
|
@ -7,7 +7,7 @@
|
||||
|
||||
function ifWebGLSupported() {
|
||||
let [target, debuggee, front] = yield initBackend(SIMPLE_CANVAS_URL);
|
||||
front.setup();
|
||||
front.setup({ reload: true });
|
||||
|
||||
let programActor = yield once(front, "program-linked");
|
||||
let vertexShader = yield programActor.getVertexShader();
|
||||
|
@ -8,7 +8,7 @@
|
||||
|
||||
function ifWebGLSupported() {
|
||||
let [target, debuggee, front] = yield initBackend(SIMPLE_CANVAS_URL);
|
||||
front.setup();
|
||||
front.setup({ reload: true });
|
||||
|
||||
let programActor = yield once(front, "program-linked");
|
||||
let vertexShader = yield programActor.getVertexShader();
|
||||
|
@ -8,7 +8,7 @@
|
||||
|
||||
function ifWebGLSupported() {
|
||||
let [target, debuggee, front] = yield initBackend(SIMPLE_CANVAS_URL);
|
||||
front.setup();
|
||||
front.setup({ reload: true });
|
||||
|
||||
let programActor = yield once(front, "program-linked");
|
||||
let vertexShader = yield programActor.getVertexShader();
|
||||
|
@ -9,36 +9,33 @@
|
||||
function ifWebGLSupported() {
|
||||
let [target, debuggee, front] = yield initBackend(SIMPLE_CANVAS_URL);
|
||||
|
||||
let linked = once(front, "program-linked");
|
||||
yield front.setup();
|
||||
yield linked;
|
||||
front.setup({ reload: true });
|
||||
yield testHighlighting((yield once(front, "program-linked")));
|
||||
ok(true, "Canvas was correctly instrumented on the first navigation.");
|
||||
|
||||
let linked = once(front, "program-linked");
|
||||
yield reload(target);
|
||||
yield linked;
|
||||
reload(target);
|
||||
yield testHighlighting((yield once(front, "program-linked")));
|
||||
ok(true, "Canvas was correctly instrumented on the second navigation.");
|
||||
|
||||
let linked = once(front, "program-linked");
|
||||
yield reload(target);
|
||||
yield linked;
|
||||
reload(target);
|
||||
yield testHighlighting((yield once(front, "program-linked")));
|
||||
ok(true, "Canvas was correctly instrumented on the third navigation.");
|
||||
|
||||
let programActor = yield linked;
|
||||
let vertexShader = yield programActor.getVertexShader();
|
||||
let fragmentShader = yield programActor.getFragmentShader();
|
||||
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 0, b: 0, a: 255 }, true);
|
||||
ok(true, "The top left pixel color was correct before highlighting.");
|
||||
|
||||
yield programActor.highlight([0, 0, 1, 1]);
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 0, b: 255, a: 255 }, true);
|
||||
ok(true, "The top left pixel color is correct after highlighting.");
|
||||
|
||||
yield programActor.unhighlight();
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 0, b: 0, a: 255 }, true);
|
||||
ok(true, "The top left pixel color is correct after unhighlighting.");
|
||||
|
||||
yield removeTab(target.tab);
|
||||
finish();
|
||||
|
||||
function testHighlighting(programActor) {
|
||||
return Task.spawn(function() {
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 0, b: 0, a: 255 }, true);
|
||||
ok(true, "The top left pixel color was correct before highlighting.");
|
||||
|
||||
yield programActor.highlight([0, 0, 1, 1]);
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 0, b: 255, a: 255 }, true);
|
||||
ok(true, "The top left pixel color is correct after highlighting.");
|
||||
|
||||
yield programActor.unhighlight();
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 0, b: 0, a: 255 }, true);
|
||||
ok(true, "The top left pixel color is correct after unhighlighting.");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ function ifWebGLSupported() {
|
||||
let [target, debuggee, front] = yield initBackend(SIMPLE_CANVAS_URL);
|
||||
|
||||
let linked = once(front, "program-linked");
|
||||
yield front.setup();
|
||||
front.setup({ reload: true });
|
||||
yield linked;
|
||||
ok(true, "Canvas was correctly instrumented on the first navigation.");
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
|
||||
function ifWebGLSupported() {
|
||||
let [target, debuggee, front] = yield initBackend(SHADER_ORDER_URL);
|
||||
front.setup();
|
||||
front.setup({ reload: true });
|
||||
|
||||
let programActor = yield once(front, "program-linked");
|
||||
let vertexShader = yield programActor.getVertexShader();
|
||||
|
@ -7,7 +7,7 @@
|
||||
|
||||
function ifWebGLSupported() {
|
||||
let [target, debuggee, front] = yield initBackend(MULTIPLE_CONTEXTS_URL);
|
||||
front.setup();
|
||||
front.setup({ reload: true });
|
||||
|
||||
let firstProgramActor = yield once(front, "program-linked");
|
||||
let secondProgramActor = yield once(front, "program-linked");
|
||||
|
@ -8,7 +8,7 @@
|
||||
|
||||
function ifWebGLSupported() {
|
||||
let [target, debuggee, front] = yield initBackend(MULTIPLE_CONTEXTS_URL);
|
||||
front.setup();
|
||||
front.setup({ reload: true });
|
||||
|
||||
let firstProgramActor = yield once(front, "program-linked");
|
||||
let secondProgramActor = yield once(front, "program-linked");
|
||||
|
@ -0,0 +1,127 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Tests if program actors are cached when navigating in the bfcache.
|
||||
*/
|
||||
|
||||
function ifWebGLSupported() {
|
||||
let [target, debuggee, front] = yield initBackend(SIMPLE_CANVAS_URL);
|
||||
front.setup({ reload: false });
|
||||
|
||||
reload(target);
|
||||
let firstProgram = yield once(front, "program-linked");
|
||||
yield checkFirstCachedPrograms(firstProgram);
|
||||
yield checkHighlightingInTheFirstPage(firstProgram);
|
||||
ok(true, "The cached programs behave correctly before the navigation.");
|
||||
|
||||
navigate(target, MULTIPLE_CONTEXTS_URL);
|
||||
let secondProgram = yield once(front, "program-linked");
|
||||
let thirdProgram = yield once(front, "program-linked");
|
||||
yield checkSecondCachedPrograms(firstProgram, [secondProgram, thirdProgram]);
|
||||
yield checkHighlightingInTheSecondPage(secondProgram, thirdProgram);
|
||||
ok(true, "The cached programs behave correctly after the navigation.");
|
||||
|
||||
once(front, "program-linked").then(() => {
|
||||
ok(false, "Shouldn't have received any more program-linked notifications.");
|
||||
});
|
||||
|
||||
yield navigateInHistory(target, "back");
|
||||
yield checkFirstCachedPrograms(firstProgram);
|
||||
yield checkHighlightingInTheFirstPage(firstProgram);
|
||||
ok(true, "The cached programs behave correctly after navigating back.");
|
||||
|
||||
yield navigateInHistory(target, "forward");
|
||||
yield checkSecondCachedPrograms(firstProgram, [secondProgram, thirdProgram]);
|
||||
yield checkHighlightingInTheSecondPage(secondProgram, thirdProgram);
|
||||
ok(true, "The cached programs behave correctly after navigating forward.");
|
||||
|
||||
yield navigateInHistory(target, "back");
|
||||
yield checkFirstCachedPrograms(firstProgram);
|
||||
yield checkHighlightingInTheFirstPage(firstProgram);
|
||||
ok(true, "The cached programs behave correctly after navigating back again.");
|
||||
|
||||
yield navigateInHistory(target, "forward");
|
||||
yield checkSecondCachedPrograms(firstProgram, [secondProgram, thirdProgram]);
|
||||
yield checkHighlightingInTheSecondPage(secondProgram, thirdProgram);
|
||||
ok(true, "The cached programs behave correctly after navigating forward again.");
|
||||
|
||||
yield removeTab(target.tab);
|
||||
finish();
|
||||
|
||||
function checkFirstCachedPrograms(programActor) {
|
||||
return Task.spawn(function() {
|
||||
let programs = yield front.getPrograms();
|
||||
|
||||
is(programs.length, 1,
|
||||
"There should be 1 cached program actor.");
|
||||
is(programs[0], programActor,
|
||||
"The cached program actor was the expected one.");
|
||||
})
|
||||
}
|
||||
|
||||
function checkSecondCachedPrograms(oldProgramActor, newProgramActors) {
|
||||
return Task.spawn(function() {
|
||||
let programs = yield front.getPrograms();
|
||||
|
||||
is(programs.length, 2,
|
||||
"There should be 2 cached program actors after the navigation.");
|
||||
is(programs[0], newProgramActors[0],
|
||||
"The first cached program actor was the expected one after the navigation.");
|
||||
is(programs[1], newProgramActors[1],
|
||||
"The second cached program actor was the expected one after the navigation.");
|
||||
|
||||
isnot(newProgramActors[0], oldProgramActor,
|
||||
"The old program actor is not equal to the new first program actor.");
|
||||
isnot(newProgramActors[1], oldProgramActor,
|
||||
"The old program actor is not equal to the new second program actor.");
|
||||
});
|
||||
}
|
||||
|
||||
function checkHighlightingInTheFirstPage(programActor) {
|
||||
return Task.spawn(function() {
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 0, b: 0, a: 255 }, true);
|
||||
ok(true, "The top left pixel color was correct before highlighting.");
|
||||
|
||||
yield programActor.highlight([0, 0, 1, 1]);
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 0, b: 255, a: 255 }, true);
|
||||
ok(true, "The top left pixel color is correct after highlighting.");
|
||||
|
||||
yield programActor.unhighlight();
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 0, b: 0, a: 255 }, true);
|
||||
ok(true, "The top left pixel color is correct after unhighlighting.");
|
||||
});
|
||||
}
|
||||
|
||||
function checkHighlightingInTheSecondPage(firstProgramActor, secondProgramActor) {
|
||||
return Task.spawn(function() {
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 255, b: 0, a: 255 }, true, "#canvas1");
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 255, b: 255, a: 255 }, true, "#canvas2");
|
||||
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 255, g: 255, b: 0, a: 255 }, true, "#canvas1");
|
||||
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 255, b: 255, a: 255 }, true, "#canvas2");
|
||||
ok(true, "The two canvases are correctly drawn before highlighting.");
|
||||
|
||||
yield firstProgramActor.highlight([1, 0, 0, 1]);
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 0, b: 0, a: 255 }, true, "#canvas1");
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 255, b: 255, a: 255 }, true, "#canvas2");
|
||||
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 255, g: 0, b: 0, a: 255 }, true, "#canvas1");
|
||||
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 255, b: 255, a: 255 }, true, "#canvas2");
|
||||
ok(true, "The first canvas was correctly filled after highlighting.");
|
||||
|
||||
yield secondProgramActor.highlight([0, 1, 0, 1]);
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 0, b: 0, a: 255 }, true, "#canvas1");
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 255, b: 0, a: 255 }, true, "#canvas2");
|
||||
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 255, g: 0, b: 0, a: 255 }, true, "#canvas1");
|
||||
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 255, b: 0, a: 255 }, true, "#canvas2");
|
||||
ok(true, "The second canvas was correctly filled after highlighting.");
|
||||
|
||||
yield firstProgramActor.unhighlight();
|
||||
yield secondProgramActor.unhighlight();
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 255, b: 0, a: 255 }, true, "#canvas1");
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 255, b: 255, a: 255 }, true, "#canvas2");
|
||||
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 255, g: 255, b: 0, a: 255 }, true, "#canvas1");
|
||||
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 255, b: 255, a: 255 }, true, "#canvas2");
|
||||
ok(true, "The two canvases were correctly filled after unhighlighting.");
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,105 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Tests if program actors are invalidated from the cache when a window is
|
||||
* removed from the bfcache.
|
||||
*/
|
||||
|
||||
function ifWebGLSupported() {
|
||||
let [target, debuggee, front] = yield initBackend(SIMPLE_CANVAS_URL);
|
||||
front.setup({ reload: false });
|
||||
|
||||
reload(target);
|
||||
let firstProgram = yield once(front, "program-linked");
|
||||
|
||||
navigate(target, MULTIPLE_CONTEXTS_URL);
|
||||
let secondProgram = yield once(front, "program-linked");
|
||||
let thirdProgram = yield once(front, "program-linked");
|
||||
|
||||
yield navigateInHistory(target, "back");
|
||||
let globalDestroyed = observe("inner-window-destroyed");
|
||||
let globalCreated = observe("content-document-global-created");
|
||||
reload(target);
|
||||
|
||||
yield globalDestroyed;
|
||||
let programs = yield front.getPrograms();
|
||||
is(programs.length, 0,
|
||||
"There should be no cached program actors yet.");
|
||||
|
||||
yield globalCreated;
|
||||
let programs = yield front.getPrograms();
|
||||
is(programs.length, 1,
|
||||
"There should be 1 cached program actor now.");
|
||||
|
||||
yield checkHighlightingInTheFirstPage(programs[0]);
|
||||
ok(true, "The cached programs behave correctly after navigating back and reloading.");
|
||||
|
||||
yield navigateInHistory(target, "forward");
|
||||
let globalDestroyed = observe("inner-window-destroyed");
|
||||
let globalCreated = observe("content-document-global-created");
|
||||
reload(target);
|
||||
|
||||
yield globalDestroyed;
|
||||
let programs = yield front.getPrograms();
|
||||
is(programs.length, 0,
|
||||
"There should be no cached program actors yet.");
|
||||
|
||||
yield globalCreated;
|
||||
let programs = yield front.getPrograms();
|
||||
is(programs.length, 2,
|
||||
"There should be 2 cached program actors now.");
|
||||
|
||||
yield checkHighlightingInTheSecondPage(programs[0], programs[1]);
|
||||
ok(true, "The cached programs behave correctly after navigating forward and reloading.");
|
||||
|
||||
yield removeTab(target.tab);
|
||||
finish();
|
||||
|
||||
function checkHighlightingInTheFirstPage(programActor) {
|
||||
return Task.spawn(function() {
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 0, b: 0, a: 255 }, true);
|
||||
ok(true, "The top left pixel color was correct before highlighting.");
|
||||
|
||||
yield programActor.highlight([0, 0, 1, 1]);
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 0, b: 255, a: 255 }, true);
|
||||
ok(true, "The top left pixel color is correct after highlighting.");
|
||||
|
||||
yield programActor.unhighlight();
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 0, b: 0, a: 255 }, true);
|
||||
ok(true, "The top left pixel color is correct after unhighlighting.");
|
||||
});
|
||||
}
|
||||
|
||||
function checkHighlightingInTheSecondPage(firstProgramActor, secondProgramActor) {
|
||||
return Task.spawn(function() {
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 255, b: 0, a: 255 }, true, "#canvas1");
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 255, b: 255, a: 255 }, true, "#canvas2");
|
||||
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 255, g: 255, b: 0, a: 255 }, true, "#canvas1");
|
||||
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 255, b: 255, a: 255 }, true, "#canvas2");
|
||||
ok(true, "The two canvases are correctly drawn before highlighting.");
|
||||
|
||||
yield firstProgramActor.highlight([1, 0, 0, 1]);
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 0, b: 0, a: 255 }, true, "#canvas1");
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 255, b: 255, a: 255 }, true, "#canvas2");
|
||||
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 255, g: 0, b: 0, a: 255 }, true, "#canvas1");
|
||||
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 255, b: 255, a: 255 }, true, "#canvas2");
|
||||
ok(true, "The first canvas was correctly filled after highlighting.");
|
||||
|
||||
yield secondProgramActor.highlight([0, 1, 0, 1]);
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 0, b: 0, a: 255 }, true, "#canvas1");
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 255, b: 0, a: 255 }, true, "#canvas2");
|
||||
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 255, g: 0, b: 0, a: 255 }, true, "#canvas1");
|
||||
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 255, b: 0, a: 255 }, true, "#canvas2");
|
||||
ok(true, "The second canvas was correctly filled after highlighting.");
|
||||
|
||||
yield firstProgramActor.unhighlight();
|
||||
yield secondProgramActor.unhighlight();
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 255, b: 0, a: 255 }, true, "#canvas1");
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 255, b: 255, a: 255 }, true, "#canvas2");
|
||||
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 255, g: 255, b: 0, a: 255 }, true, "#canvas1");
|
||||
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 255, b: 255, a: 255 }, true, "#canvas2");
|
||||
ok(true, "The two canvases were correctly filled after unhighlighting.");
|
||||
});
|
||||
}
|
||||
}
|
@ -133,6 +133,19 @@ function once(aTarget, aEventName, aUseCapture = false) {
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function observe(aNotificationName, aOwnsWeak = false) {
|
||||
info("Waiting for observer notification: '" + aNotificationName + ".");
|
||||
|
||||
let deferred = promise.defer();
|
||||
|
||||
Services.obs.addObserver(function onNotification(...aArgs) {
|
||||
Services.obs.removeObserver(onNotification, aNotificationName);
|
||||
deferred.resolve.apply(deferred, aArgs);
|
||||
}, aNotificationName, aOwnsWeak);
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function waitForFrame(aDebuggee) {
|
||||
let deferred = promise.defer();
|
||||
aDebuggee.requestAnimationFrame(deferred.resolve);
|
||||
@ -193,16 +206,19 @@ function ensurePixelIs(aDebuggee, aPosition, aColor, aWaitFlag = false, aSelecto
|
||||
return promise.reject(null);
|
||||
}
|
||||
|
||||
function navigate(aTarget, aUrl) {
|
||||
let navigated = once(aTarget, "navigate");
|
||||
aTarget.client.activeTab.navigateTo(aUrl);
|
||||
return navigated;
|
||||
function navigateInHistory(aTarget, aDirection, aWaitForTargetEvent = "navigate") {
|
||||
executeSoon(() => content.history[aDirection]());
|
||||
return once(aTarget, aWaitForTargetEvent);
|
||||
}
|
||||
|
||||
function reload(aTarget) {
|
||||
let navigated = once(aTarget, "navigate");
|
||||
function navigate(aTarget, aUrl, aWaitForTargetEvent = "navigate") {
|
||||
executeSoon(() => aTarget.client.activeTab.navigateTo(aUrl));
|
||||
return once(aTarget, aWaitForTargetEvent);
|
||||
}
|
||||
|
||||
function reload(aTarget, aWaitForTargetEvent = "navigate") {
|
||||
executeSoon(() => aTarget.client.activeTab.reload());
|
||||
return navigated;
|
||||
return once(aTarget, aWaitForTargetEvent);
|
||||
}
|
||||
|
||||
function initBackend(aUrl) {
|
||||
|
@ -181,6 +181,10 @@ Tooltip.prototype = {
|
||||
this.stopTogglingOnHover();
|
||||
}
|
||||
|
||||
// If no targetNodeCb callback is provided, then we need to hide the tooltip
|
||||
// on mouseleave since baseNode is the target node itself
|
||||
this._hideOnMouseLeave = !targetNodeCb;
|
||||
|
||||
this._basedNode = baseNode;
|
||||
this._showDelay = showDelay;
|
||||
this._targetNodeCb = targetNodeCb || (() => true);
|
||||
@ -221,7 +225,7 @@ Tooltip.prototype = {
|
||||
},
|
||||
|
||||
_showOnHover: function(target) {
|
||||
if (this._targetNodeCb && this._targetNodeCb(target, this)) {
|
||||
if (this._targetNodeCb(target, this)) {
|
||||
this.show(target);
|
||||
this._lastHovered = target;
|
||||
}
|
||||
@ -230,6 +234,9 @@ Tooltip.prototype = {
|
||||
_onBaseNodeMouseLeave: function() {
|
||||
clearNamedTimeout(this.uid);
|
||||
this._lastHovered = null;
|
||||
if (this._hideOnMouseLeave) {
|
||||
this.hide();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -49,8 +49,6 @@ let Svc = {};
|
||||
XPCOMUtils.defineLazyServiceGetter(Svc, 'mime',
|
||||
'@mozilla.org/mime;1', 'nsIMIMEService');
|
||||
|
||||
let profiler = Cc["@mozilla.org/tools/profiler;1"].getService(Ci.nsIProfiler);
|
||||
|
||||
function getBoolPref(pref, def) {
|
||||
try {
|
||||
return Services.prefs.getBoolPref(pref);
|
||||
@ -222,7 +220,10 @@ ChromeActions.prototype = {
|
||||
});
|
||||
},
|
||||
addProfilerMarker: function (marker) {
|
||||
profiler.AddMarker(marker);
|
||||
if ('nsIProfiler' in Ci) {
|
||||
let profiler = Cc["@mozilla.org/tools/profiler;1"].getService(Ci.nsIProfiler);
|
||||
profiler.AddMarker(marker);
|
||||
}
|
||||
},
|
||||
getPluginParams: function getPluginParams() {
|
||||
return JSON.stringify({
|
||||
|
@ -1 +1 @@
|
||||
0.7.501
|
||||
0.7.502
|
||||
|
@ -15,9 +15,9 @@
|
||||
- in the network table when empty. -->
|
||||
<!ENTITY netmonitorUI.emptyNotice2 "Perform a request or reload the page to see detailed information about network activity.">
|
||||
|
||||
<!-- LOCALIZATION NOTE (netmonitorUI.toolbar.status): This is the label displayed
|
||||
<!-- LOCALIZATION NOTE (netmonitorUI.toolbar.status2): This is the label displayed
|
||||
- in the network table toolbar, above the "status" column. -->
|
||||
<!ENTITY netmonitorUI.toolbar.status "√">
|
||||
<!ENTITY netmonitorUI.toolbar.status2 "✓">
|
||||
|
||||
<!-- LOCALIZATION NOTE (netmonitorUI.toolbar.method): This is the label displayed
|
||||
- in the network table toolbar, above the "method" column. -->
|
||||
|
@ -9,8 +9,7 @@ let Cu = Components.utils;
|
||||
let Cr = Components.results;
|
||||
|
||||
/**
|
||||
* Handler for APZC display port and pan begin/end notifications.
|
||||
* These notifications are only sent by widget/windows/winrt code when
|
||||
* Misc. front end utilities for apzc management.
|
||||
* the pref: layers.async-pan-zoom.enabled is true.
|
||||
*/
|
||||
|
||||
@ -29,7 +28,6 @@ var APZCObserver = {
|
||||
}
|
||||
|
||||
let os = Services.obs;
|
||||
os.addObserver(this, "apzc-request-content-repaint", false);
|
||||
os.addObserver(this, "apzc-handle-pan-begin", false);
|
||||
os.addObserver(this, "apzc-handle-pan-end", false);
|
||||
|
||||
@ -42,6 +40,10 @@ var APZCObserver = {
|
||||
switch (aEvent.type) {
|
||||
case 'pageshow':
|
||||
case 'TabSelect':
|
||||
// ROOT_ID doesn't really identify the view we want. When we call
|
||||
// this on a content document (tab), findElementWithViewId will
|
||||
// always return the root content document associated with the
|
||||
// scrollable frame.
|
||||
const ROOT_ID = 1;
|
||||
let windowUtils = Browser.selectedBrowser.contentWindow.
|
||||
QueryInterface(Ci.nsIInterfaceRequestor).
|
||||
@ -73,6 +75,7 @@ var APZCObserver = {
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
shutdown: function shutdown() {
|
||||
if (!this._enabled) {
|
||||
return;
|
||||
@ -82,45 +85,12 @@ var APZCObserver = {
|
||||
Elements.tabList.removeEventListener("TabClose", this, true);
|
||||
|
||||
let os = Services.obs;
|
||||
os.removeObserver(this, "apzc-request-content-repaint");
|
||||
os.removeObserver(this, "apzc-handle-pan-begin");
|
||||
os.removeObserver(this, "apzc-handle-pan-end");
|
||||
},
|
||||
|
||||
observe: function ao_observe(aSubject, aTopic, aData) {
|
||||
if (aTopic == "apzc-request-content-repaint") {
|
||||
let frameMetrics = JSON.parse(aData);
|
||||
let scrollId = frameMetrics.scrollId;
|
||||
let scrollTo = frameMetrics.scrollTo;
|
||||
let displayPort = frameMetrics.displayPort;
|
||||
let resolution = frameMetrics.resolution;
|
||||
let compositedRect = frameMetrics.compositedRect;
|
||||
|
||||
let windowUtils = Browser.selectedBrowser.contentWindow.
|
||||
QueryInterface(Ci.nsIInterfaceRequestor).
|
||||
getInterface(Ci.nsIDOMWindowUtils);
|
||||
windowUtils.setScrollPositionClampingScrollPortSize(compositedRect.width,
|
||||
compositedRect.height);
|
||||
Browser.selectedBrowser.messageManager.sendAsyncMessage("Content:SetDisplayPort", {
|
||||
scrollX: scrollTo.x,
|
||||
scrollY: scrollTo.y,
|
||||
x: displayPort.x + scrollTo.x,
|
||||
y: displayPort.y + scrollTo.y,
|
||||
w: displayPort.width,
|
||||
h: displayPort.height,
|
||||
scale: resolution,
|
||||
id: scrollId
|
||||
});
|
||||
|
||||
if (this._debugEvents) {
|
||||
Util.dumpLn("APZC scrollId: " + scrollId);
|
||||
Util.dumpLn("APZC scrollTo.x: " + scrollTo.x + ", scrollTo.y: " + scrollTo.y);
|
||||
Util.dumpLn("APZC setResolution: " + resolution);
|
||||
Util.dumpLn("APZC setDisplayPortForElement: displayPort.x: " +
|
||||
displayPort.x + ", displayPort.y: " + displayPort.y +
|
||||
", displayPort.width: " + displayPort.width +
|
||||
", displayort.height: " + displayPort.height);
|
||||
}
|
||||
} else if (aTopic == "apzc-handle-pan-begin") {
|
||||
if (aTopic == "apzc-handle-pan-begin") {
|
||||
// When we're panning, hide the main scrollbars by setting imprecise
|
||||
// input (which sets a property on the browser which hides the scrollbar
|
||||
// via CSS). This reduces jittering from left to right. We may be able
|
||||
@ -141,7 +111,7 @@ var APZCObserver = {
|
||||
// its scroll offset data.
|
||||
case "Browser:ContentScroll": {
|
||||
let data = json.viewId + " " + json.presShellId + " (" + json.scrollOffset.x + ", " + json.scrollOffset.y + ")";
|
||||
Services.obs.notifyObservers(null, "scroll-offset-changed", data);
|
||||
Services.obs.notifyObservers(null, "apzc-scroll-offset-changed", data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -552,7 +552,6 @@ let ContentScroll = {
|
||||
_scrollOffset: { x: 0, y: 0 },
|
||||
|
||||
init: function() {
|
||||
addMessageListener("Content:SetDisplayPort", this);
|
||||
addMessageListener("Content:SetWindowSize", this);
|
||||
|
||||
if (Services.prefs.getBoolPref("layers.async-pan-zoom.enabled")) {
|
||||
@ -575,77 +574,9 @@ let ContentScroll = {
|
||||
return { x: aElement.scrollLeft, y: aElement.scrollTop };
|
||||
},
|
||||
|
||||
setScrollOffsetForElement: function(aElement, aLeft, aTop) {
|
||||
if (aElement.parentNode == aElement.ownerDocument) {
|
||||
aElement.ownerDocument.defaultView.scrollTo(aLeft, aTop);
|
||||
} else {
|
||||
aElement.scrollLeft = aLeft;
|
||||
aElement.scrollTop = aTop;
|
||||
}
|
||||
},
|
||||
|
||||
receiveMessage: function(aMessage) {
|
||||
let json = aMessage.json;
|
||||
switch (aMessage.name) {
|
||||
// Sent to us from chrome when the the apz has requested that the
|
||||
// display port be updated and that content should repaint.
|
||||
case "Content:SetDisplayPort": {
|
||||
// Set resolution for root view
|
||||
let rootCwu = content.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
|
||||
if (json.id == 1) {
|
||||
rootCwu.setResolution(json.scale, json.scale);
|
||||
if (!WebProgressListener._firstPaint)
|
||||
break;
|
||||
}
|
||||
|
||||
let displayport = new Rect(json.x, json.y, json.w, json.h);
|
||||
if (displayport.isEmpty())
|
||||
break;
|
||||
|
||||
// Map ID to element
|
||||
let element = null;
|
||||
try {
|
||||
element = rootCwu.findElementWithViewId(json.id);
|
||||
} catch(e) {
|
||||
// This could give NS_ERROR_NOT_AVAILABLE. In that case, the
|
||||
// presshell is not available because the page is reloading.
|
||||
}
|
||||
|
||||
if (!element)
|
||||
break;
|
||||
|
||||
let binding = element.ownerDocument.getBindingParent(element);
|
||||
if (binding instanceof Ci.nsIDOMHTMLInputElement && binding.mozIsTextField(false))
|
||||
break;
|
||||
|
||||
// Set the scroll offset for this element if specified
|
||||
if (json.scrollX >= 0 || json.scrollY >= 0) {
|
||||
this.setScrollOffsetForElement(element, json.scrollX, json.scrollY);
|
||||
if (element == content.document.documentElement) {
|
||||
// scrollTo can make some small adjustments to the offset before
|
||||
// actually scrolling the document. To ensure that _scrollOffset
|
||||
// actually matches the offset stored in the window, re-query it.
|
||||
this._scrollOffset = this.getScrollOffset(content);
|
||||
}
|
||||
}
|
||||
|
||||
// Set displayport. We want to set this after setting the scroll offset, because
|
||||
// it is calculated based on the scroll offset.
|
||||
let scrollOffset = this.getScrollOffsetForElement(element);
|
||||
let x = displayport.x - scrollOffset.x;
|
||||
let y = displayport.y - scrollOffset.y;
|
||||
|
||||
if (json.id == 1) {
|
||||
x = Math.round(x * json.scale) / json.scale;
|
||||
y = Math.round(y * json.scale) / json.scale;
|
||||
}
|
||||
|
||||
let win = element.ownerDocument.defaultView;
|
||||
let winCwu = win.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
|
||||
winCwu.setDisplayPortForElement(x, y, displayport.width, displayport.height, element);
|
||||
break;
|
||||
}
|
||||
|
||||
case "Content:SetWindowSize": {
|
||||
let cwu = content.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
|
||||
cwu.setCSSViewport(json.width, json.height);
|
||||
@ -704,8 +635,7 @@ let ContentScroll = {
|
||||
if (target == content.document) {
|
||||
if (this._scrollOffset.x == scrollOffset.x && this._scrollOffset.y == scrollOffset.y) {
|
||||
// Don't send a scroll message back to APZC if it's the same as the
|
||||
// last one set by APZC. We use this to avoid sending APZC back an
|
||||
// event that it originally triggered.
|
||||
// last one.
|
||||
return;
|
||||
}
|
||||
this._scrollOffset = scrollOffset;
|
||||
|
@ -35,6 +35,8 @@ const TOPIC_TIMER_CALLBACK = "timer-callback";
|
||||
const TOPIC_DELAYED_STARTUP = "browser-delayed-startup-finished";
|
||||
const TOPIC_XUL_WINDOW_CLOSED = "xul-window-destroyed";
|
||||
|
||||
const FRAME_SCRIPT_URL = "chrome://browser/content/newtab/preloaderContent.js";
|
||||
|
||||
function createTimer(obj, delay) {
|
||||
let timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
|
||||
timer.init(obj, delay, Ci.nsITimer.TYPE_ONE_SHOT);
|
||||
@ -61,6 +63,7 @@ this.BrowserNewTabPreloader = {
|
||||
},
|
||||
|
||||
newTab: function Preloader_newTab(aTab) {
|
||||
let swapped = false;
|
||||
let win = aTab.ownerDocument.defaultView;
|
||||
if (win.gBrowser) {
|
||||
let utils = win.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
@ -69,11 +72,17 @@ this.BrowserNewTabPreloader = {
|
||||
let {width, height} = utils.getBoundsWithoutFlushing(win.gBrowser);
|
||||
let hiddenBrowser = HiddenBrowsers.get(width, height)
|
||||
if (hiddenBrowser) {
|
||||
return hiddenBrowser.swapWithNewTab(aTab);
|
||||
swapped = hiddenBrowser.swapWithNewTab(aTab);
|
||||
}
|
||||
|
||||
// aTab's browser is now visible and is therefore allowed to make
|
||||
// background captures.
|
||||
let msgMan = aTab.linkedBrowser.messageManager;
|
||||
msgMan.loadFrameScript(FRAME_SCRIPT_URL, false);
|
||||
msgMan.sendAsyncMessage("BrowserNewTabPreloader:allowBackgroundCaptures");
|
||||
}
|
||||
|
||||
return false;
|
||||
return swapped;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -50,6 +50,7 @@ html|*.highlighter-nodeinfobar-pseudo-classes {
|
||||
|
||||
.highlighter-nodeinfobar-button {
|
||||
-moz-appearance: none;
|
||||
border-width: 0;
|
||||
padding: 0;
|
||||
width: 26px;
|
||||
min-height: 26px;
|
||||
|
@ -2380,11 +2380,6 @@ toolbarbutton.bookmark-item[dragover="true"][open="true"] {
|
||||
width: 16px;
|
||||
}
|
||||
|
||||
#identity-popup-help-icon:-moz-focusring {
|
||||
outline: 1px dotted;
|
||||
outline-offset: 1px;
|
||||
}
|
||||
|
||||
#identity-popup-more-info-button {
|
||||
margin-top: 6px;
|
||||
margin-bottom: 0;
|
||||
|
@ -68,14 +68,14 @@ function submitForm(idNum) {
|
||||
|
||||
function submitFormMouse(idNum) {
|
||||
$("test"+idNum).setAttribute("onload", "frameLoaded(this)");
|
||||
// Use 4.999 instead of 5 to guard against the possibility that the
|
||||
// Use 4.99 instead of 5 to guard against the possibility that the
|
||||
// image's 'top' is exactly N + 0.5 pixels from the root. In that case
|
||||
// we'd round up the widget mouse coordinate to N + 6, which relative
|
||||
// to the image would be 5.5, which would get rounded up to 6 when
|
||||
// submitting the form. Instead we round the widget mouse coordinate to
|
||||
// N + 5, which relative to the image would be 4.5 which gets rounded up
|
||||
// to 5.
|
||||
synthesizeMouse($("test" + idNum + "image"), 4.999, 4.999, {});
|
||||
synthesizeMouse($("test" + idNum + "image"), 4.99, 4.99, {});
|
||||
}
|
||||
|
||||
addLoadEvent(function() {
|
||||
|
@ -651,6 +651,9 @@ static const dom::ConstantSpec gWinProperties[] =
|
||||
INT_CONSTANT(MOVEFILE_COPY_ALLOWED),
|
||||
INT_CONSTANT(MOVEFILE_REPLACE_EXISTING),
|
||||
|
||||
// GetFileAttributes error constant
|
||||
INT_CONSTANT(INVALID_FILE_ATTRIBUTES),
|
||||
|
||||
// Errors
|
||||
INT_CONSTANT(ERROR_ACCESS_DENIED),
|
||||
INT_CONSTANT(ERROR_DIR_NOT_EMPTY),
|
||||
|
@ -1077,6 +1077,14 @@ nsIPresShell::SetAuthorStyleDisabled(bool aStyleDisabled)
|
||||
if (aStyleDisabled != mStyleSet->GetAuthorStyleDisabled()) {
|
||||
mStyleSet->SetAuthorStyleDisabled(aStyleDisabled);
|
||||
ReconstructStyleData();
|
||||
|
||||
nsCOMPtr<nsIObserverService> observerService =
|
||||
mozilla::services::GetObserverService();
|
||||
if (observerService) {
|
||||
observerService->NotifyObservers(mDocument,
|
||||
"author-style-disabled-changed",
|
||||
nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -99,8 +99,8 @@ function updateList() {
|
||||
request.onsuccess = function() {
|
||||
for (let i = 0; i < request.result.length; i++)
|
||||
addApplication(request.result[i]);
|
||||
if (!request.result.length)
|
||||
document.getElementById("noapps").className = "";
|
||||
if (request.result.length)
|
||||
document.getElementById("main-container").classList.remove("hidden");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -39,7 +39,7 @@
|
||||
<div id="header-button" role="button" aria-label="&aboutApps.browseMarketplace;" pref="app.marketplaceURL" onclick="openLink(this);"/>
|
||||
</div>
|
||||
|
||||
<div id="main-container" class="list hidden">
|
||||
<div id="main-container" class="hidden">
|
||||
<div>
|
||||
<div class="spacer" id="spacer1"> </div>
|
||||
<div id="appgrid"/>
|
||||
|
@ -134,7 +134,8 @@ Object.defineProperty(OSError.prototype, "becauseExists", {
|
||||
*/
|
||||
Object.defineProperty(OSError.prototype, "becauseNoSuchFile", {
|
||||
get: function becauseNoSuchFile() {
|
||||
return this.winLastError == Const.ERROR_FILE_NOT_FOUND;
|
||||
return this.winLastError == Const.ERROR_FILE_NOT_FOUND ||
|
||||
this.winLastError == Const.ERROR_PATH_NOT_FOUND;
|
||||
}
|
||||
});
|
||||
/**
|
||||
|
@ -345,6 +345,17 @@
|
||||
"FlushFileBuffers", ctypes.winapi_abi,
|
||||
/*return*/ Type.zero_or_nothing,
|
||||
/*file*/ Type.HANDLE);
|
||||
|
||||
declareLazyFFI(SysFile, "GetFileAttributes", libc,
|
||||
"GetFileAttributesW", ctypes.winapi_abi,
|
||||
/*return*/ Type.DWORD,
|
||||
/*fileName*/ Type.path);
|
||||
|
||||
declareLazyFFI(SysFile, "SetFileAttributes", libc,
|
||||
"SetFileAttributesW", ctypes.winapi_abi,
|
||||
/*return*/ Type.zero_or_nothing,
|
||||
/*fileName*/ Type.path,
|
||||
/*fileAttributes*/ Type.DWORD);
|
||||
};
|
||||
|
||||
exports.OS.Win = {
|
||||
|
@ -382,14 +382,27 @@
|
||||
* @throws {OS.File.Error} In case of I/O error.
|
||||
*/
|
||||
File.remove = function remove(path, options = {}) {
|
||||
let result = WinFile.DeleteFile(path);
|
||||
if (!result) {
|
||||
if ((!("ignoreAbsent" in options) || options.ignoreAbsent) &&
|
||||
ctypes.winLastError == Const.ERROR_FILE_NOT_FOUND) {
|
||||
if (WinFile.DeleteFile(path)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (ctypes.winLastError == Const.ERROR_FILE_NOT_FOUND) {
|
||||
if ((!("ignoreAbsent" in options) || options.ignoreAbsent)) {
|
||||
return;
|
||||
}
|
||||
throw new File.Error("remove");
|
||||
} else if (ctypes.winLastError == Const.ERROR_ACCESS_DENIED) {
|
||||
let attributes = WinFile.GetFileAttributes(path);
|
||||
if (attributes != Const.INVALID_FILE_ATTRIBUTES &&
|
||||
attributes & Const.FILE_ATTRIBUTE_READONLY) {
|
||||
let newAttributes = attributes & ~Const.FILE_ATTRIBUTE_READONLY;
|
||||
if (WinFile.SetFileAttributes(path, newAttributes) &&
|
||||
WinFile.DeleteFile(path)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw new File.Error("remove");
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -151,7 +151,6 @@ let test = maketest("Main", function main(test) {
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
yield test_constants();
|
||||
yield test_path();
|
||||
yield test_open();
|
||||
yield test_stat();
|
||||
yield test_debug();
|
||||
yield test_info_features_detect();
|
||||
@ -199,50 +198,6 @@ let test_path = maketest("path", function path(test) {
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Test OS.File.open for reading:
|
||||
* - with an existing file (should succeed);
|
||||
* - with a non-existing file (should fail);
|
||||
* - with inconsistent arguments (should fail).
|
||||
*/
|
||||
let test_open = maketest("open", function open(test) {
|
||||
return Task.spawn(function() {
|
||||
// Attempt to open a file that does not exist, ensure that it yields the
|
||||
// appropriate error.
|
||||
try {
|
||||
let fd = yield OS.File.open(OS.Path.join(".", "This file does not exist"));
|
||||
test.ok(false, "File opening 1 succeeded (it should fail)" + fd);
|
||||
} catch (err) {
|
||||
test.ok(true, "File opening 1 failed " + err);
|
||||
test.ok(err instanceof OS.File.Error, "File opening 1 returned a file error");
|
||||
test.ok(err.becauseNoSuchFile, "File opening 1 informed that the file does not exist");
|
||||
}
|
||||
|
||||
// Attempt to open a file with the wrong args, so that it fails before
|
||||
// serialization, ensure that it yields the appropriate error.
|
||||
test.info("Attempting to open a file with wrong arguments");
|
||||
try {
|
||||
let fd = yield OS.File.open(1, 2, 3);
|
||||
test.ok(false, "File opening 2 succeeded (it should fail)" + fd);
|
||||
} catch (err) {
|
||||
test.ok(true, "File opening 2 failed " + err);
|
||||
test.ok(!(err instanceof OS.File.Error), "File opening 2 returned something that is not a file error");
|
||||
test.ok(err.constructor.name == "TypeError", "File opening 2 returned a TypeError");
|
||||
}
|
||||
|
||||
// Attempt to open a file correctly
|
||||
test.info("Attempting to open a file correctly");
|
||||
let openedFile = yield OS.File.open(EXISTING_FILE);
|
||||
test.ok(true, "File opened correctly");
|
||||
|
||||
test.info("Attempting to close a file correctly");
|
||||
yield openedFile.close();
|
||||
|
||||
test.info("Attempting to close a file again");
|
||||
yield openedFile.close();
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Test OS.File.stat and OS.File.prototype.stat
|
||||
*/
|
||||
|
@ -844,4 +844,16 @@ function test_remove_file()
|
||||
OS.File.remove(absent_file_name);
|
||||
});
|
||||
ok(!exn, "test_remove_file: ignoreAbsent works");
|
||||
|
||||
if (OS.Win) {
|
||||
let file_name = "test_osfile_front_file_to_remove.tmp";
|
||||
let file = OS.File.open(file_name, {write: true});
|
||||
file.close();
|
||||
ok(OS.File.exists(file_name), "test_remove_file: test file exists");
|
||||
OS.Win.File.SetFileAttributes(file_name,
|
||||
OS.Constants.Win.FILE_ATTRIBUTE_READONLY);
|
||||
OS.File.remove(file_name);
|
||||
ok(!OS.File.exists(file_name),
|
||||
"test_remove_file: test file has been removed");
|
||||
}
|
||||
}
|
||||
|
75
toolkit/components/osfile/tests/xpcshell/test_open.js
Normal file
75
toolkit/components/osfile/tests/xpcshell/test_open.js
Normal file
@ -0,0 +1,75 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
Components.utils.import("resource://gre/modules/osfile.jsm");
|
||||
|
||||
function run_test() {
|
||||
do_test_pending();
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test OS.File.open for reading:
|
||||
* - with an existing file (should succeed);
|
||||
* - with a non-existing file (should fail);
|
||||
* - with inconsistent arguments (should fail).
|
||||
*/
|
||||
add_task(function() {
|
||||
// Attempt to open a file that does not exist, ensure that it yields the
|
||||
// appropriate error.
|
||||
try {
|
||||
let fd = yield OS.File.open(OS.Path.join(".", "This file does not exist"));
|
||||
do_check_true(false, "File opening 1 succeeded (it should fail)");
|
||||
} catch (err if err instanceof OS.File.Error && err.becauseNoSuchFile) {
|
||||
do_print("File opening 1 failed " + err);
|
||||
}
|
||||
|
||||
// Attempt to open a file with the wrong args, so that it fails before
|
||||
// serialization, ensure that it yields the appropriate error.
|
||||
do_print("Attempting to open a file with wrong arguments");
|
||||
try {
|
||||
let fd = yield OS.File.open(1, 2, 3);
|
||||
do_check_true(false, "File opening 2 succeeded (it should fail)" + fd);
|
||||
} catch (err) {
|
||||
do_print("File opening 2 failed " + err);
|
||||
do_check_false(err instanceof OS.File.Error,
|
||||
"File opening 2 returned something that is not a file error");
|
||||
do_check_true(err.constructor.name == "TypeError",
|
||||
"File opening 2 returned a TypeError");
|
||||
}
|
||||
|
||||
// Attempt to open a file correctly
|
||||
do_print("Attempting to open a file correctly");
|
||||
let openedFile = yield OS.File.open(OS.Path.join(do_get_cwd().path, "test_open.js"));
|
||||
do_print("File opened correctly");
|
||||
|
||||
do_print("Attempting to close a file correctly");
|
||||
yield openedFile.close();
|
||||
|
||||
do_print("Attempting to close a file again");
|
||||
yield openedFile.close();
|
||||
});
|
||||
|
||||
/**
|
||||
* Test the error thrown by OS.File.open when attempting to open a directory
|
||||
* that does not exist.
|
||||
*/
|
||||
add_task(function test_error_attributes () {
|
||||
|
||||
let dir = OS.Path.join(do_get_profile().path, "test_osfileErrorAttrs");
|
||||
let fpath = OS.Path.join(dir, "test_error_attributes.txt");
|
||||
|
||||
try {
|
||||
yield OS.File.open(fpath, {truncate: true}, {});
|
||||
do_check_true(false, "Opening path suceeded (it should fail) " + fpath);
|
||||
} catch (err) {
|
||||
do_check_true(err instanceof OS.File.Error);
|
||||
do_check_true(err.becauseNoSuchFile);
|
||||
}
|
||||
});
|
||||
|
||||
add_task(function() {
|
||||
do_test_finished();
|
||||
});
|
@ -19,3 +19,4 @@ tail =
|
||||
[test_reset.js]
|
||||
[test_shutdown.js]
|
||||
[test_unique.js]
|
||||
[test_open.js]
|
||||
|
@ -1,9 +1,27 @@
|
||||
/*
|
||||
* Initialization: for each test, remove any prior notifications.
|
||||
*/
|
||||
function cleanUpPopupNotifications() {
|
||||
var container = getPopupNotifications(window.top);
|
||||
var notes = container._currentNotifications;
|
||||
info(true, "Removing " + notes.length + " popup notifications.");
|
||||
for (var i = notes.length-1; i >= 0; i--) {
|
||||
notes[i].remove();
|
||||
}
|
||||
}
|
||||
cleanUpPopupNotifications();
|
||||
|
||||
/*
|
||||
* getPopupNotifications
|
||||
*
|
||||
* Fetches the popup notification for the specified window.
|
||||
*/
|
||||
function getPopupNotifications(aWindow) {
|
||||
var Ci = SpecialPowers.Ci;
|
||||
var Cc = SpecialPowers.Cc;
|
||||
ok(Ci != null, "Access Ci");
|
||||
ok(Cc != null, "Access Cc");
|
||||
|
||||
var chromeWin = SpecialPowers.wrap(aWindow)
|
||||
.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebNavigation)
|
||||
|
@ -27,6 +27,8 @@ loader:
|
||||
5. Prepend `module.exports = ` to the package.json file contents, so that the
|
||||
JSON data is exported, and we can load package.json as a module.
|
||||
|
||||
Bug 933482: Note, this is a workaround for Bug 910594, which will allow the SDK loader to require JSON files. To remove ambiguity, comment out the `require('./package.json').version` line in `escodegen.js` so that when Bug 910594 is uplifted into central, it does not attempt to look for `package.json`, rather than `package.json.js`. This is a temporary workaround, and once Bug 933500 is solved, either `package.json` or `package.json.js` will work.
|
||||
|
||||
6. Copy the estraverse.js that escodegen depends on into our tree:
|
||||
|
||||
$ cp node_modules/estraverse/estraverse.js /path/to/mozilla-central/devtools/escodegen/estraverse.js
|
||||
|
@ -2055,7 +2055,7 @@
|
||||
|
||||
FORMAT_DEFAULTS = getDefaultOptions().format;
|
||||
|
||||
exports.version = require('./package.json').version;
|
||||
// exports.version = require('./package.json').version;
|
||||
exports.generate = generate;
|
||||
exports.attachComments = estraverse.attachComments;
|
||||
exports.browser = false;
|
||||
|
@ -767,7 +767,7 @@ BrowserTabActor.prototype = {
|
||||
* Prepare to enter a nested event loop by disabling debuggee events.
|
||||
*/
|
||||
preNest: function BTA_preNest() {
|
||||
if (!this.browser) {
|
||||
if (!this.window) {
|
||||
// The tab is already closed.
|
||||
return;
|
||||
}
|
||||
@ -782,7 +782,7 @@ BrowserTabActor.prototype = {
|
||||
* Prepare to exit a nested event loop by enabling debuggee events.
|
||||
*/
|
||||
postNest: function BTA_postNest(aNestData) {
|
||||
if (!this.browser) {
|
||||
if (!this.window) {
|
||||
// The tab is already closed.
|
||||
return;
|
||||
}
|
||||
|
@ -184,7 +184,9 @@ let WebGLActor = exports.WebGLActor = protocol.ActorClass({
|
||||
protocol.Actor.prototype.initialize.call(this, conn);
|
||||
this.tabActor = tabActor;
|
||||
this._onGlobalCreated = this._onGlobalCreated.bind(this);
|
||||
this._onGlobalDestroyed = this._onGlobalDestroyed.bind(this);
|
||||
this._onProgramLinked = this._onProgramLinked.bind(this);
|
||||
this._programActorsCache = [];
|
||||
},
|
||||
destroy: function(conn) {
|
||||
protocol.Actor.prototype.destroy.call(this, conn);
|
||||
@ -198,7 +200,7 @@ let WebGLActor = exports.WebGLActor = protocol.ActorClass({
|
||||
*
|
||||
* See ContentObserver and WebGLInstrumenter for more details.
|
||||
*/
|
||||
setup: method(function() {
|
||||
setup: method(function({ reload }) {
|
||||
if (this._initialized) {
|
||||
return;
|
||||
}
|
||||
@ -206,10 +208,14 @@ let WebGLActor = exports.WebGLActor = protocol.ActorClass({
|
||||
this._contentObserver = new ContentObserver(this.tabActor);
|
||||
this._webglObserver = new WebGLObserver();
|
||||
on(this._contentObserver, "global-created", this._onGlobalCreated);
|
||||
on(this._contentObserver, "global-destroyed", this._onGlobalDestroyed);
|
||||
on(this._webglObserver, "program-linked", this._onProgramLinked);
|
||||
|
||||
this.tabActor.window.location.reload();
|
||||
if (reload) {
|
||||
this.tabActor.window.location.reload();
|
||||
}
|
||||
}, {
|
||||
request: { reload: Option(0, "boolean") },
|
||||
oneway: true
|
||||
}),
|
||||
|
||||
@ -225,11 +231,23 @@ let WebGLActor = exports.WebGLActor = protocol.ActorClass({
|
||||
this._initialized = false;
|
||||
this._contentObserver.stopListening();
|
||||
off(this._contentObserver, "global-created", this._onGlobalCreated);
|
||||
off(this._contentObserver, "global-destroyed", this._onGlobalDestroyed);
|
||||
off(this._webglObserver, "program-linked", this._onProgramLinked);
|
||||
}, {
|
||||
oneway: true
|
||||
}),
|
||||
|
||||
/**
|
||||
* Gets an array of cached program actors for the current tab actor's window.
|
||||
* This is useful for dealing with bfcache, when no new programs are linked.
|
||||
*/
|
||||
getPrograms: method(function() {
|
||||
let id = getInnerWindowID(this.tabActor.window);
|
||||
return this._programActorsCache.filter(e => e.owner == id).map(e => e.actor);
|
||||
}, {
|
||||
response: { programs: RetVal("array:gl-program") }
|
||||
}),
|
||||
|
||||
/**
|
||||
* Events emitted by this actor. The "program-linked" event is fired
|
||||
* every time a WebGL program was linked with its respective two shaders.
|
||||
@ -248,6 +266,14 @@ let WebGLActor = exports.WebGLActor = protocol.ActorClass({
|
||||
WebGLInstrumenter.handle(window, this._webglObserver);
|
||||
},
|
||||
|
||||
/**
|
||||
* Invoked whenever the current tab actor's inner window is destroyed.
|
||||
*/
|
||||
_onGlobalDestroyed: function(id) {
|
||||
this._programActorsCache =
|
||||
this._programActorsCache.filter(e => e.owner != id);
|
||||
},
|
||||
|
||||
/**
|
||||
* Invoked whenever the current WebGL context links a program.
|
||||
*/
|
||||
@ -275,6 +301,11 @@ let WebGLActor = exports.WebGLActor = protocol.ActorClass({
|
||||
programActor.program = program;
|
||||
programActor.shadersData = shadersData;
|
||||
|
||||
this._programActorsCache.push({
|
||||
owner: getInnerWindowID(this.tabActor.window),
|
||||
actor: programActor
|
||||
});
|
||||
|
||||
events.emit(this, "program-linked", programActor);
|
||||
}
|
||||
});
|
||||
@ -297,8 +328,9 @@ let WebGLFront = exports.WebGLFront = protocol.FrontClass(WebGLActor, {
|
||||
* instrument the HTMLCanvasElement with the appropriate inspection methods.
|
||||
*/
|
||||
function ContentObserver(tabActor) {
|
||||
this._contentWindow = tabActor.browser.contentWindow;
|
||||
this._contentWindow = tabActor.window;
|
||||
this._onContentGlobalCreated = this._onContentGlobalCreated.bind(this);
|
||||
this._onInnerWindowDestroyed = this._onInnerWindowDestroyed.bind(this);
|
||||
this.startListening();
|
||||
}
|
||||
|
||||
@ -309,6 +341,8 @@ ContentObserver.prototype = {
|
||||
startListening: function() {
|
||||
Services.obs.addObserver(
|
||||
this._onContentGlobalCreated, "content-document-global-created", false);
|
||||
Services.obs.addObserver(
|
||||
this._onInnerWindowDestroyed, "inner-window-destroyed", false);
|
||||
},
|
||||
|
||||
/**
|
||||
@ -317,6 +351,8 @@ ContentObserver.prototype = {
|
||||
stopListening: function() {
|
||||
Services.obs.removeObserver(
|
||||
this._onContentGlobalCreated, "content-document-global-created", false);
|
||||
Services.obs.removeObserver(
|
||||
this._onInnerWindowDestroyed, "inner-window-destroyed", false);
|
||||
},
|
||||
|
||||
/**
|
||||
@ -326,6 +362,14 @@ ContentObserver.prototype = {
|
||||
if (subject == this._contentWindow) {
|
||||
emit(this, "global-created", subject);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Fired when an inner window is removed from the backward/forward cache.
|
||||
*/
|
||||
_onInnerWindowDestroyed: function(subject, topic, data) {
|
||||
let id = subject.QueryInterface(Ci.nsISupportsPRUint64).data;
|
||||
emit(this, "global-destroyed", id);
|
||||
}
|
||||
};
|
||||
|
||||
@ -849,3 +893,10 @@ WebGLProxy.prototype = {
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
function getInnerWindowID(window) {
|
||||
return window
|
||||
.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils)
|
||||
.currentInnerWindowID;
|
||||
}
|
||||
|
@ -177,16 +177,64 @@ let PendingErrors = {
|
||||
lineNumber: null
|
||||
};
|
||||
try { // Defend against non-enumerable values
|
||||
if (typeof error == "object" && error) {
|
||||
if (error && error instanceof Ci.nsIException) {
|
||||
// nsIException does things a little differently.
|
||||
try {
|
||||
// For starters |.toString()| does not only contain the message, but
|
||||
// also the top stack frame, and we don't really want that.
|
||||
value.message = error.message;
|
||||
} catch (ex) {
|
||||
// Ignore field
|
||||
}
|
||||
try {
|
||||
// All lowercase filename. ;)
|
||||
value.fileName = error.filename;
|
||||
} catch (ex) {
|
||||
// Ignore field
|
||||
}
|
||||
try {
|
||||
value.lineNumber = error.lineNumber;
|
||||
} catch (ex) {
|
||||
// Ignore field
|
||||
}
|
||||
} else if (typeof error == "object" && error) {
|
||||
for (let k of ["fileName", "stack", "lineNumber"]) {
|
||||
try { // Defend against fallible getters and string conversions
|
||||
let v = error[k];
|
||||
value[k] = v ? ("" + v):null;
|
||||
value[k] = v ? ("" + v) : null;
|
||||
} catch (ex) {
|
||||
// Ignore field
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!value.stack) {
|
||||
// |error| is not an Error (or Error-alike). Try to figure out the stack.
|
||||
let stack = null;
|
||||
if (error && error.location &&
|
||||
error.location instanceof Ci.nsIStackFrame) {
|
||||
// nsIException has full stack frames in the |.location| member.
|
||||
stack = error.location;
|
||||
} else {
|
||||
// Components.stack to the rescue!
|
||||
stack = Components.stack;
|
||||
// Remove those top frames that refer to Promise.jsm.
|
||||
while (stack) {
|
||||
if (!stack.filename.endsWith("/Promise.jsm")) {
|
||||
break;
|
||||
}
|
||||
stack = stack.caller;
|
||||
}
|
||||
}
|
||||
if (stack) {
|
||||
let frames = [];
|
||||
while (stack) {
|
||||
frames.push(stack);
|
||||
stack = stack.caller;
|
||||
}
|
||||
value.stack = frames.join("\n");
|
||||
}
|
||||
}
|
||||
} catch (ex) {
|
||||
// Ignore value
|
||||
}
|
||||
|
@ -757,14 +757,20 @@ function wait_for_uncaught(aMustAppear, aTimeout = undefined) {
|
||||
let make_string_rejection = function make_string_rejection() {
|
||||
let salt = (Math.random() * ( Math.pow(2, 24) - 1 ));
|
||||
let string = "This is an uncaught rejection " + salt;
|
||||
return {mustFind: [string], error: string};
|
||||
// Our error is not Error-like nor an nsIException, so the stack will
|
||||
// include the closure doing the actual rejection.
|
||||
return {mustFind: ["test_rejection_closure", string], error: string};
|
||||
};
|
||||
let make_num_rejection = function make_num_rejection() {
|
||||
let salt = (Math.random() * ( Math.pow(2, 24) - 1 ));
|
||||
return {mustFind: [salt], error: salt};
|
||||
// Our error is not Error-like nor an nsIException, so the stack will
|
||||
// include the closure doing the actual rejection.
|
||||
return {mustFind: ["test_rejection_closure", salt], error: salt};
|
||||
};
|
||||
let make_undefined_rejection = function make_undefined_rejection() {
|
||||
return {mustFind: [], error: undefined};
|
||||
// Our error is not Error-like nor an nsIException, so the stack will
|
||||
// include the closure doing the actual rejection.
|
||||
return {mustFind: ["test_rejection_closure"], error: undefined};
|
||||
};
|
||||
let make_error_rejection = function make_error_rejection() {
|
||||
let salt = (Math.random() * ( Math.pow(2, 24) - 1 ));
|
||||
@ -774,16 +780,26 @@ function wait_for_uncaught(aMustAppear, aTimeout = undefined) {
|
||||
error: error
|
||||
};
|
||||
};
|
||||
let make_exception_rejection = function make_exception_rejection() {
|
||||
let salt = (Math.random() * ( Math.pow(2, 24) - 1 ));
|
||||
let exn = new Components.Exception("This is an uncaught exception " + salt,
|
||||
Components.results.NS_ERROR_NOT_AVAILABLE);
|
||||
return {
|
||||
mustFind: [exn.message, exn.filename, exn.lineNumber, exn.location.toString()],
|
||||
error: exn
|
||||
};
|
||||
};
|
||||
for (let make_rejection of [make_string_rejection,
|
||||
make_num_rejection,
|
||||
make_undefined_rejection,
|
||||
make_error_rejection]) {
|
||||
make_error_rejection,
|
||||
make_exception_rejection]) {
|
||||
let {mustFind, error} = make_rejection();
|
||||
let name = make_rejection.name;
|
||||
tests.push(make_promise_test(function test_uncaught_is_reported() {
|
||||
do_print("Testing with rejection " + name);
|
||||
let promise = wait_for_uncaught(mustFind);
|
||||
(function() {
|
||||
(function test_rejection_closure() {
|
||||
// For the moment, we cannot be absolutely certain that a value is
|
||||
// garbage-collected, even if it is not referenced anymore, due to
|
||||
// the conservative stack-scanning algorithm.
|
||||
|
@ -11,6 +11,11 @@
|
||||
#include "nsIDOMMouseEvent.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
|
||||
#ifdef MOZ_LOGGING
|
||||
#define FORCE_PR_LOG /* Allow logging in the release build */
|
||||
#endif // MOZ_LOGGING
|
||||
#include "prlog.h"
|
||||
|
||||
#include "nsString.h"
|
||||
#include "nsDirectoryServiceUtils.h"
|
||||
#include "imgIContainer.h"
|
||||
@ -35,6 +40,10 @@
|
||||
#include "nsTextStore.h"
|
||||
#endif // #ifdef NS_ENABLE_TSF
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
PRLogModuleInfo* gWindowsLog = nullptr;
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
namespace widget {
|
||||
|
||||
@ -75,6 +84,11 @@ WinUtils::DwmGetCompositionTimingInfoProc WinUtils::dwmGetCompositionTimingInfoP
|
||||
void
|
||||
WinUtils::Initialize()
|
||||
{
|
||||
#ifdef PR_LOGGING
|
||||
if (!gWindowsLog) {
|
||||
gWindowsLog = PR_NewLogModule("Widget");
|
||||
}
|
||||
#endif
|
||||
if (!sDwmDll && WinUtils::GetWindowsVersion() >= WinUtils::VISTA_VERSION) {
|
||||
sDwmDll = ::LoadLibraryW(kDwmLibraryName);
|
||||
|
||||
@ -128,6 +142,81 @@ WinUtils::GetWindowsServicePackVersion(UINT& aOutMajor, UINT& aOutMinor)
|
||||
return true;
|
||||
}
|
||||
|
||||
// static
|
||||
void
|
||||
WinUtils::LogW(const wchar_t *fmt, ...)
|
||||
{
|
||||
va_list args = NULL;
|
||||
if(!lstrlenW(fmt)) {
|
||||
return;
|
||||
}
|
||||
va_start(args, fmt);
|
||||
int buflen = _vscwprintf(fmt, args);
|
||||
wchar_t* buffer = new wchar_t[buflen+1];
|
||||
if (!buffer) {
|
||||
va_end(args);
|
||||
return;
|
||||
}
|
||||
vswprintf(buffer, buflen, fmt, args);
|
||||
va_end(args);
|
||||
|
||||
// MSVC, including remote debug sessions
|
||||
OutputDebugStringW(buffer);
|
||||
OutputDebugStringW(L"\n");
|
||||
|
||||
int len = wcslen(buffer);
|
||||
if (len) {
|
||||
char* utf8 = new char[len+1];
|
||||
memset(utf8, 0, sizeof(utf8));
|
||||
if (WideCharToMultiByte(CP_ACP, 0, buffer,
|
||||
-1, utf8, len+1, NULL,
|
||||
NULL) > 0) {
|
||||
// desktop console
|
||||
printf("%s\n", utf8);
|
||||
#ifdef PR_LOGGING
|
||||
NS_ASSERTION(gWindowsLog, "Called WinUtils Log() but Widget "
|
||||
"log module doesn't exist!");
|
||||
PR_LOG(gWindowsLog, PR_LOG_ALWAYS, (utf8));
|
||||
#endif
|
||||
}
|
||||
delete[] utf8;
|
||||
}
|
||||
delete[] buffer;
|
||||
}
|
||||
|
||||
// static
|
||||
void
|
||||
WinUtils::Log(const char *fmt, ...)
|
||||
{
|
||||
va_list args = NULL;
|
||||
if(!strlen(fmt)) {
|
||||
return;
|
||||
}
|
||||
va_start(args, fmt);
|
||||
int buflen = _vscprintf(fmt, args);
|
||||
char* buffer = new char[buflen+1];
|
||||
if (!buffer) {
|
||||
va_end(args);
|
||||
return;
|
||||
}
|
||||
vsprintf(buffer, fmt, args);
|
||||
va_end(args);
|
||||
|
||||
// MSVC, including remote debug sessions
|
||||
OutputDebugStringA(buffer);
|
||||
OutputDebugStringW(L"\n");
|
||||
|
||||
// desktop console
|
||||
printf("%s\n", buffer);
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
NS_ASSERTION(gWindowsLog, "Called WinUtils Log() but Widget "
|
||||
"log module doesn't exist!");
|
||||
PR_LOG(gWindowsLog, PR_LOG_ALWAYS, (buffer));
|
||||
#endif
|
||||
delete[] buffer;
|
||||
}
|
||||
|
||||
/* static */
|
||||
bool
|
||||
WinUtils::PeekMessage(LPMSG aMsg, HWND aWnd, UINT aFirstMessage,
|
||||
|
@ -53,6 +53,13 @@ namespace widget {
|
||||
QS_ALLPOSTMESSAGE | QS_RAWINPUT | \
|
||||
QS_TOUCH | QS_POINTER)
|
||||
|
||||
// Logging macros
|
||||
#define LogFunction() mozilla::widget::WinUtils::Log(__FUNCTION__)
|
||||
#define LogThread() mozilla::widget::WinUtils::Log("%s: IsMainThread:%d ThreadId:%X", __FUNCTION__, NS_IsMainThread(), GetCurrentThreadId())
|
||||
#define LogThis() mozilla::widget::WinUtils::Log("[%X] %s", this, __FUNCTION__)
|
||||
#define LogException(e) mozilla::widget::WinUtils::Log("%s Exception:%s", __FUNCTION__, e->ToString()->Data())
|
||||
#define LogHRESULT(hr) mozilla::widget::WinUtils::Log("%s hr=%X", __FUNCTION__, hr)
|
||||
|
||||
class myDownloadObserver MOZ_FINAL : public nsIDownloadObserver
|
||||
{
|
||||
public:
|
||||
@ -76,6 +83,13 @@ public:
|
||||
// Returns true on success, false on failure.
|
||||
static bool GetWindowsServicePackVersion(UINT& aOutMajor, UINT& aOutMinor);
|
||||
|
||||
/**
|
||||
* Logging helpers that dump output to prlog module 'Widget', console, and
|
||||
* OutputDebugString. Note these output in both debug and release builds.
|
||||
*/
|
||||
static void Log(const char *fmt, ...);
|
||||
static void LogW(const wchar_t *fmt, ...);
|
||||
|
||||
/**
|
||||
* PeekMessage() and GetMessage() are wrapper methods for PeekMessageW(),
|
||||
* GetMessageW(), ITfMessageMgr::PeekMessageW() and
|
||||
|
@ -253,7 +253,7 @@ uint32_t nsWindow::sOOPPPluginFocusEvent =
|
||||
static const char *sScreenManagerContractID = "@mozilla.org/gfx/screenmanager;1";
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
PRLogModuleInfo* gWindowsLog = nullptr;
|
||||
extern PRLogModuleInfo* gWindowsLog;
|
||||
#endif
|
||||
|
||||
// Global used in Show window enumerations.
|
||||
@ -311,12 +311,6 @@ static const int32_t kResizableBorderMinSize = 3;
|
||||
|
||||
nsWindow::nsWindow() : nsWindowBase()
|
||||
{
|
||||
#ifdef PR_LOGGING
|
||||
if (!gWindowsLog) {
|
||||
gWindowsLog = PR_NewLogModule("nsWindow");
|
||||
}
|
||||
#endif
|
||||
|
||||
mIconSmall = nullptr;
|
||||
mIconBig = nullptr;
|
||||
mWnd = nullptr;
|
||||
|
@ -8,57 +8,201 @@
|
||||
#include "nsThreadUtils.h"
|
||||
#include "MetroUtils.h"
|
||||
#include "nsPrintfCString.h"
|
||||
#include "nsIWidgetListener.h"
|
||||
#include "APZCCallbackHelper.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsPresContext.h"
|
||||
#include "nsIDOMElement.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "nsIDOMWindowUtils.h"
|
||||
#include "nsIInterfaceRequestorUtils.h"
|
||||
|
||||
//#define DEBUG_CONTROLLER 1
|
||||
|
||||
#ifdef DEBUG_CONTROLLER
|
||||
#include "WinUtils.h"
|
||||
using namespace mozilla::widget;
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
namespace widget {
|
||||
namespace winrt {
|
||||
|
||||
nsRefPtr<mozilla::layers::APZCTreeManager> APZController::sAPZC;
|
||||
|
||||
/*
|
||||
* Metro layout specific - test to see if a sub document is a
|
||||
* tab.
|
||||
*/
|
||||
static bool
|
||||
IsTab(nsCOMPtr<nsIDocument>& aSubDocument)
|
||||
{
|
||||
nsRefPtr<nsIDocument> parent = aSubDocument->GetParentDocument();
|
||||
if (!parent) {
|
||||
NS_WARNING("huh? IsTab should always get a sub document for a parameter");
|
||||
return false;
|
||||
}
|
||||
return parent->IsRootDisplayDocument();
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the sub document associated with the scroll id.
|
||||
*/
|
||||
static bool
|
||||
GetDOMTargets(nsIPresShell* aPresShell, uint64_t aScrollId,
|
||||
nsCOMPtr<nsIDocument>& aSubDocument,
|
||||
nsCOMPtr<nsIDOMElement>& aTargetElement)
|
||||
{
|
||||
MOZ_ASSERT(aPresShell);
|
||||
nsRefPtr<nsIDocument> rootDocument = aPresShell->GetDocument();
|
||||
if (!rootDocument) {
|
||||
return false;
|
||||
}
|
||||
nsCOMPtr<nsIDOMWindowUtils> rootUtils;
|
||||
nsCOMPtr<nsIDOMWindow> rootWindow = rootDocument->GetDefaultView();
|
||||
if (!rootWindow) {
|
||||
return false;
|
||||
}
|
||||
rootUtils = do_GetInterface(rootWindow);
|
||||
if (!rootUtils) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// For tabs and subframes this will return the HTML sub document
|
||||
rootUtils->FindElementWithViewId(aScrollId, getter_AddRefs(aTargetElement));
|
||||
if (!aTargetElement) {
|
||||
return false;
|
||||
}
|
||||
nsCOMPtr<mozilla::dom::Element> domElement = do_QueryInterface(aTargetElement);
|
||||
if (!domElement) {
|
||||
return false;
|
||||
}
|
||||
|
||||
aSubDocument = domElement->OwnerDoc();
|
||||
|
||||
if (!aSubDocument) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If the root element equals domElement, FindElementWithViewId found
|
||||
// a document, vs. an element within a document.
|
||||
if (aSubDocument->GetRootElement() == domElement && IsTab(aSubDocument)) {
|
||||
aTargetElement = nullptr;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
class RequestContentRepaintEvent : public nsRunnable
|
||||
{
|
||||
typedef mozilla::layers::FrameMetrics FrameMetrics;
|
||||
typedef mozilla::layers::FrameMetrics FrameMetrics;
|
||||
|
||||
public:
|
||||
RequestContentRepaintEvent(const FrameMetrics& aFrameMetrics) : mFrameMetrics(aFrameMetrics)
|
||||
{
|
||||
RequestContentRepaintEvent(const FrameMetrics& aFrameMetrics,
|
||||
nsIWidgetListener* aListener,
|
||||
CSSIntPoint* aLastOffsetOut) :
|
||||
mFrameMetrics(aFrameMetrics),
|
||||
mWidgetListener(aListener),
|
||||
mLastOffsetOut(aLastOffsetOut)
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHOD Run() {
|
||||
// This event shuts down the worker thread and so must be main thread.
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
#ifdef DEBUG_CONTROLLER
|
||||
WinUtils::Log("APZController: mScrollOffset: %f %f", mFrameMetrics.mScrollOffset.x,
|
||||
mFrameMetrics.mScrollOffset.y);
|
||||
#endif
|
||||
|
||||
nsIPresShell* presShell = mWidgetListener->GetPresShell();
|
||||
if (!presShell) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD Run() {
|
||||
// This event shuts down the worker thread and so must be main thread.
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
CSSToScreenScale resolution = mFrameMetrics.mZoom;
|
||||
CSSRect compositedRect = mFrameMetrics.CalculateCompositedRectInCssPixels();
|
||||
|
||||
NS_ConvertASCIItoUTF16 data(nsPrintfCString("{ " \
|
||||
" \"resolution\": %.2f, " \
|
||||
" \"scrollId\": %d, " \
|
||||
" \"compositedRect\": { \"width\": %d, \"height\": %d }, " \
|
||||
" \"displayPort\": { \"x\": %d, \"y\": %d, \"width\": %d, \"height\": %d }, " \
|
||||
" \"scrollTo\": { \"x\": %d, \"y\": %d }" \
|
||||
"}",
|
||||
(float)(resolution.scale / mFrameMetrics.mDevPixelsPerCSSPixel.scale),
|
||||
(int)mFrameMetrics.mScrollId,
|
||||
(int)compositedRect.width,
|
||||
(int)compositedRect.height,
|
||||
(int)mFrameMetrics.mDisplayPort.x,
|
||||
(int)mFrameMetrics.mDisplayPort.y,
|
||||
(int)mFrameMetrics.mDisplayPort.width,
|
||||
(int)mFrameMetrics.mDisplayPort.height,
|
||||
(int)mFrameMetrics.mScrollOffset.x,
|
||||
(int)mFrameMetrics.mScrollOffset.y));
|
||||
|
||||
MetroUtils::FireObserver("apzc-request-content-repaint", data.get());
|
||||
return NS_OK;
|
||||
nsCOMPtr<nsIDocument> subDocument;
|
||||
nsCOMPtr<nsIDOMElement> targetElement;
|
||||
if (!GetDOMTargets(presShell, mFrameMetrics.mScrollId,
|
||||
subDocument, targetElement)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// If we're dealing with a sub frame or content editable element,
|
||||
// call UpdateSubFrame.
|
||||
if (targetElement) {
|
||||
#ifdef DEBUG_CONTROLLER
|
||||
WinUtils::Log("APZController: detected subframe or content editable");
|
||||
#endif
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(targetElement);
|
||||
if (content) {
|
||||
APZCCallbackHelper::UpdateSubFrame(content, mFrameMetrics);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_CONTROLLER
|
||||
WinUtils::Log("APZController: detected tab");
|
||||
#endif
|
||||
|
||||
// We're dealing with a tab, call UpdateRootFrame.
|
||||
nsCOMPtr<nsIDOMWindowUtils> utils;
|
||||
nsCOMPtr<nsIDOMWindow> window = subDocument->GetDefaultView();
|
||||
if (window) {
|
||||
utils = do_GetInterface(window);
|
||||
if (utils) {
|
||||
APZCCallbackHelper::UpdateRootFrame(utils, mFrameMetrics);
|
||||
|
||||
// Return the actual scroll value so we can use it to filter
|
||||
// out scroll messages triggered by setting the display port.
|
||||
CSSIntPoint actualScrollOffset;
|
||||
utils->GetScrollXY(false, &actualScrollOffset.x, &actualScrollOffset.y);
|
||||
if (mLastOffsetOut) {
|
||||
*mLastOffsetOut = actualScrollOffset;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_CONTROLLER
|
||||
WinUtils::Log("APZController: %I64d mDisplayPort: %0.2f %0.2f %0.2f %0.2f",
|
||||
mFrameMetrics.mScrollId,
|
||||
mFrameMetrics.mDisplayPort.x,
|
||||
mFrameMetrics.mDisplayPort.y,
|
||||
mFrameMetrics.mDisplayPort.width,
|
||||
mFrameMetrics.mDisplayPort.height);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
protected:
|
||||
const FrameMetrics mFrameMetrics;
|
||||
FrameMetrics mFrameMetrics;
|
||||
nsIWidgetListener* mWidgetListener;
|
||||
CSSIntPoint* mLastOffsetOut;
|
||||
};
|
||||
|
||||
void
|
||||
APZController::SetWidgetListener(nsIWidgetListener* aWidgetListener)
|
||||
{
|
||||
mWidgetListener = aWidgetListener;
|
||||
}
|
||||
|
||||
// APZC sends us this request when we need to update the display port on
|
||||
// the scrollable frame the apzc is managing.
|
||||
void
|
||||
APZController::RequestContentRepaint(const FrameMetrics& aFrameMetrics)
|
||||
{
|
||||
// Send the result back to the main thread so that it can shutdown
|
||||
nsCOMPtr<nsIRunnable> r1 = new RequestContentRepaintEvent(aFrameMetrics);
|
||||
if (!mWidgetListener) {
|
||||
NS_WARNING("Can't update display port, !mWidgetListener");
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_CONTROLLER
|
||||
WinUtils::Log("APZController::RequestContentRepaint scroll id = %I64d",
|
||||
aFrameMetrics.mScrollId);
|
||||
#endif
|
||||
nsCOMPtr<nsIRunnable> r1 = new RequestContentRepaintEvent(aFrameMetrics,
|
||||
mWidgetListener,
|
||||
&mLastScrollOffset);
|
||||
if (!NS_IsMainThread()) {
|
||||
NS_DispatchToMainThread(r1);
|
||||
} else {
|
||||
@ -66,6 +210,27 @@ APZController::RequestContentRepaint(const FrameMetrics& aFrameMetrics)
|
||||
}
|
||||
}
|
||||
|
||||
// Content send us this when it detect content has scrolled via
|
||||
// a dom scroll event. Note we get these in response to dom scroll
|
||||
// events and as a result of apzc scrolling which we filter out.
|
||||
void
|
||||
APZController::UpdateScrollOffset(const mozilla::layers::ScrollableLayerGuid& aScrollLayerId,
|
||||
CSSIntPoint& aScrollOffset)
|
||||
{
|
||||
#ifdef DEBUG_CONTROLLER
|
||||
WinUtils::Log("APZController::UpdateScrollOffset: %d %d == %d %d",
|
||||
aScrollOffset.x, aScrollOffset.y,
|
||||
mLastScrollOffset.x, mLastScrollOffset.y);
|
||||
#endif
|
||||
|
||||
if (!sAPZC || mLastScrollOffset == aScrollOffset) {
|
||||
return;
|
||||
}
|
||||
sAPZC->UpdateScrollOffset(aScrollLayerId, aScrollOffset);
|
||||
}
|
||||
|
||||
// Gesture event handlers from the APZC. Currently not in use.
|
||||
|
||||
void
|
||||
APZController::HandleDoubleTap(const CSSIntPoint& aPoint)
|
||||
{
|
||||
@ -81,8 +246,11 @@ APZController::HandleLongTap(const CSSIntPoint& aPoint)
|
||||
{
|
||||
}
|
||||
|
||||
// requests that we send a mozbrowserasyncscroll domevent. not in use.
|
||||
void
|
||||
APZController::SendAsyncScrollDOMEvent(FrameMetrics::ViewID aScrollId, const CSSRect &aContentRect, const CSSSize &aScrollableSize)
|
||||
APZController::SendAsyncScrollDOMEvent(FrameMetrics::ViewID aScrollId,
|
||||
const CSSRect &aContentRect,
|
||||
const CSSSize &aScrollableSize)
|
||||
{
|
||||
}
|
||||
|
||||
@ -92,6 +260,8 @@ APZController::PostDelayedTask(Task* aTask, int aDelayMs)
|
||||
MessageLoop::current()->PostDelayedTask(FROM_HERE, aTask, aDelayMs);
|
||||
}
|
||||
|
||||
// async scroll notifications
|
||||
|
||||
void
|
||||
APZController::HandlePanBegin()
|
||||
{
|
||||
|
@ -7,18 +7,23 @@
|
||||
#include "mozwrlbase.h"
|
||||
|
||||
#include "mozilla/layers/GeckoContentController.h"
|
||||
#include "mozilla/layers/APZCTreeManager.h"
|
||||
#include "FrameMetrics.h"
|
||||
#include "Units.h"
|
||||
|
||||
class nsIWidgetListener;
|
||||
|
||||
namespace mozilla {
|
||||
namespace widget {
|
||||
namespace winrt {
|
||||
|
||||
class APZController : public mozilla::layers::GeckoContentController
|
||||
class APZController :
|
||||
public mozilla::layers::GeckoContentController
|
||||
{
|
||||
typedef mozilla::layers::FrameMetrics FrameMetrics;
|
||||
|
||||
public:
|
||||
// GeckoContentController interface
|
||||
virtual void RequestContentRepaint(const FrameMetrics& aFrameMetrics);
|
||||
virtual void HandleDoubleTap(const mozilla::CSSIntPoint& aPoint);
|
||||
virtual void HandleSingleTap(const mozilla::CSSIntPoint& aPoint);
|
||||
@ -27,6 +32,16 @@ public:
|
||||
virtual void PostDelayedTask(Task* aTask, int aDelayMs);
|
||||
virtual void HandlePanBegin();
|
||||
virtual void HandlePanEnd();
|
||||
|
||||
void SetWidgetListener(nsIWidgetListener* aWidgetListener);
|
||||
void UpdateScrollOffset(const mozilla::layers::ScrollableLayerGuid& aScrollLayerId, CSSIntPoint& aScrollOffset);
|
||||
|
||||
public:
|
||||
static nsRefPtr<mozilla::layers::APZCTreeManager> sAPZC;
|
||||
|
||||
private:
|
||||
nsIWidgetListener* mWidgetListener;
|
||||
CSSIntPoint mLastScrollOffset;
|
||||
};
|
||||
|
||||
} } }
|
@ -98,7 +98,7 @@ FrameworkView::Run()
|
||||
mMetroApp->Run();
|
||||
|
||||
// Gecko is completely shut down at this point.
|
||||
Log("Exiting FrameworkView::Run()");
|
||||
WinUtils::Log("Exiting FrameworkView::Run()");
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
@ -463,10 +463,9 @@ FrameworkView::OnAutomationProviderRequested(ICoreWindow* aSender,
|
||||
LogFunction();
|
||||
if (!EnsureAutomationProviderCreated())
|
||||
return E_FAIL;
|
||||
Log("OnAutomationProviderRequested %X", mAutomationProvider.Get());
|
||||
HRESULT hr = aArgs->put_AutomationProvider(mAutomationProvider.Get());
|
||||
if (FAILED(hr)) {
|
||||
Log("put failed? %X", hr);
|
||||
WinUtils::Log("put failed? %X", hr);
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ using namespace ABI::Windows::System;
|
||||
using namespace ABI::Windows::Foundation;
|
||||
using namespace Microsoft::WRL;
|
||||
using namespace Microsoft::WRL::Wrappers;
|
||||
using namespace mozilla::widget;
|
||||
|
||||
// Metro specific XRE methods we call from here on an
|
||||
// appropriate thread.
|
||||
@ -83,11 +84,11 @@ MetroApp::Run()
|
||||
this, &MetroApp::OnResuming).Get(), &mResumeEvent);
|
||||
AssertHRESULT(hr);
|
||||
|
||||
Log("XPCOM startup initialization began");
|
||||
WinUtils::Log("XPCOM startup initialization began");
|
||||
nsresult rv = XRE_metroStartup(true);
|
||||
Log("XPCOM startup initialization complete");
|
||||
WinUtils::Log("XPCOM startup initialization complete");
|
||||
if (NS_FAILED(rv)) {
|
||||
Log("XPCOM startup initialization failed, bailing. rv=%X", rv);
|
||||
WinUtils::Log("XPCOM startup initialization failed, bailing. rv=%X", rv);
|
||||
CoreExit();
|
||||
}
|
||||
}
|
||||
@ -153,7 +154,7 @@ HRESULT
|
||||
MetroApp::OnAsyncTileCreated(ABI::Windows::Foundation::IAsyncOperation<bool>* aOperation,
|
||||
AsyncStatus aStatus)
|
||||
{
|
||||
Log("Async operation status: %d", aStatus);
|
||||
WinUtils::Log("Async operation status: %d", aStatus);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
@ -217,12 +218,6 @@ XRE_MetroCoreApplicationRun()
|
||||
|
||||
using namespace mozilla::widget::winrt;
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
if (!gWindowsLog) {
|
||||
gWindowsLog = PR_NewLogModule("nsWindow");
|
||||
}
|
||||
#endif
|
||||
|
||||
sMetroApp = Make<MetroApp>();
|
||||
|
||||
HStringReference className(RuntimeClass_Windows_ApplicationModel_Core_CoreApplication);
|
||||
@ -256,7 +251,7 @@ XRE_MetroCoreApplicationRun()
|
||||
hr = sCoreApp->Run(sMetroApp.Get());
|
||||
sFrameworkView = nullptr;
|
||||
|
||||
Log("Exiting CoreApplication::Run");
|
||||
WinUtils::Log("Exiting CoreApplication::Run");
|
||||
|
||||
sCoreApp = nullptr;
|
||||
sMetroApp = nullptr;
|
||||
|
@ -281,7 +281,7 @@ MetroAppShell::ProcessOneNativeEventIfPresent()
|
||||
// Calling into ProcessNativeEvents is harmless, but won't actually process any
|
||||
// native events. So we log here so we can spot this and get a handle on the
|
||||
// corner cases where this can happen.
|
||||
Log("WARNING: Reentrant call into process events detected, returning early.");
|
||||
WinUtils::Log("WARNING: Reentrant call into process events detected, returning early.");
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -395,7 +395,7 @@ MetroAppShell::Observe(nsISupports *subject, const char *topic,
|
||||
NS_ENSURE_ARG_POINTER(topic);
|
||||
if (!strcmp(topic, "dl-start")) {
|
||||
if (mPowerRequestCount++ == 0) {
|
||||
Log("Download started - Disallowing suspend");
|
||||
WinUtils::Log("Download started - Disallowing suspend");
|
||||
REASON_CONTEXT context;
|
||||
context.Version = POWER_REQUEST_CONTEXT_VERSION;
|
||||
context.Flags = POWER_REQUEST_CONTEXT_SIMPLE_STRING;
|
||||
@ -408,7 +408,7 @@ MetroAppShell::Observe(nsISupports *subject, const char *topic,
|
||||
!strcmp(topic, "dl-cancel") ||
|
||||
!strcmp(topic, "dl-failed")) {
|
||||
if (--mPowerRequestCount == 0 && mPowerRequest) {
|
||||
Log("All downloads ended - Allowing suspend");
|
||||
WinUtils::Log("All downloads ended - Allowing suspend");
|
||||
PowerClearRequestDyn(mPowerRequest, PowerRequestExecutionRequired);
|
||||
mPowerRequest.reset();
|
||||
}
|
||||
|
@ -59,7 +59,7 @@ FrameworkView::SearchActivated(ComPtr<ISearchActivatedEventArgs>& aArgs, bool aS
|
||||
return;
|
||||
|
||||
unsigned int length;
|
||||
LogW(L"SearchActivated text=%s", data.GetRawBuffer(&length));
|
||||
WinUtils::LogW(L"SearchActivated text=%s", data.GetRawBuffer(&length));
|
||||
if (aStartup) {
|
||||
mActivationURI = data.GetRawBuffer(&length);
|
||||
} else {
|
||||
@ -136,7 +136,7 @@ FrameworkView::ProcessLaunchArguments()
|
||||
NS_ConvertUTF16toUTF8 arg(argv[i]);
|
||||
argvUTF8[i] = new char[arg.Length() + 1];
|
||||
strcpy(argvUTF8[i], const_cast<char *>(arg.BeginReading()));
|
||||
LogW(L"Launch arg[%d]: '%s'", i, argv[i]);
|
||||
WinUtils::LogW(L"Launch arg[%d]: '%s'", i, argv[i]);
|
||||
}
|
||||
|
||||
nsresult rv = cmdLine->Init(argc,
|
||||
@ -163,7 +163,7 @@ FrameworkView::ProcessActivationArgs(IActivatedEventArgs* aArgs, bool aStartup)
|
||||
return;
|
||||
ComPtr<IActivatedEventArgs> args(aArgs);
|
||||
if (kind == ActivationKind::ActivationKind_Protocol) {
|
||||
Log("Activation argument kind: Protocol");
|
||||
WinUtils::Log("Activation argument kind: Protocol");
|
||||
ComPtr<IProtocolActivatedEventArgs> protoArgs;
|
||||
AssertHRESULT(args.As(&protoArgs));
|
||||
ComPtr<IUriRuntimeClass> uri;
|
||||
@ -183,17 +183,17 @@ FrameworkView::ProcessActivationArgs(IActivatedEventArgs* aArgs, bool aStartup)
|
||||
PerformURILoad(data);
|
||||
}
|
||||
} else if (kind == ActivationKind::ActivationKind_Search) {
|
||||
Log("Activation argument kind: Search");
|
||||
WinUtils::Log("Activation argument kind: Search");
|
||||
ComPtr<ISearchActivatedEventArgs> searchArgs;
|
||||
args.As(&searchArgs);
|
||||
SearchActivated(searchArgs, aStartup);
|
||||
} else if (kind == ActivationKind::ActivationKind_File) {
|
||||
Log("Activation argument kind: File");
|
||||
WinUtils::Log("Activation argument kind: File");
|
||||
ComPtr<IFileActivatedEventArgs> fileArgs;
|
||||
args.As(&fileArgs);
|
||||
FileActivated(fileArgs, aStartup);
|
||||
} else if (kind == ActivationKind::ActivationKind_Launch) {
|
||||
Log("Activation argument kind: Launch");
|
||||
WinUtils::Log("Activation argument kind: Launch");
|
||||
ComPtr<ILaunchActivatedEventArgs> launchArgs;
|
||||
args.As(&launchArgs);
|
||||
LaunchActivated(launchArgs, aStartup);
|
||||
@ -263,7 +263,7 @@ FrameworkView::PerformURILoad(HString& aURI)
|
||||
LogFunction();
|
||||
|
||||
unsigned int length;
|
||||
LogW(L"PerformURILoad uri=%s", aURI.GetRawBuffer(&length));
|
||||
WinUtils::LogW(L"PerformURILoad uri=%s", aURI.GetRawBuffer(&length));
|
||||
|
||||
nsCOMPtr<nsICommandLineRunner> cmdLine =
|
||||
(do_CreateInstance("@mozilla.org/toolkit/command-line;1"));
|
||||
@ -323,7 +323,7 @@ FrameworkView::PerformURILoadOrSearch(HString& aString)
|
||||
LogFunction();
|
||||
|
||||
if (WindowsIsStringEmpty(aString.Get())) {
|
||||
Log("Emptry string passed to PerformURILoadOrSearch");
|
||||
WinUtils::Log("Emptry string passed to PerformURILoadOrSearch");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -3,11 +3,6 @@
|
||||
* 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/. */
|
||||
|
||||
#ifdef MOZ_LOGGING
|
||||
// so we can get logging even in release builds
|
||||
#define FORCE_PR_LOG 1
|
||||
#endif
|
||||
|
||||
#include "MetroUtils.h"
|
||||
#include <windows.h>
|
||||
#include "nsICommandLineRunner.h"
|
||||
@ -39,10 +34,6 @@ using namespace ABI::Windows::Graphics::Display;
|
||||
|
||||
// File-scoped statics (unnamed namespace)
|
||||
namespace {
|
||||
#ifdef PR_LOGGING
|
||||
PRLogModuleInfo* metroWidgetLog = PR_NewLogModule("MetroWidget");
|
||||
#endif
|
||||
|
||||
FLOAT LogToPhysFactor() {
|
||||
ComPtr<IDisplayPropertiesStatics> dispProps;
|
||||
if (SUCCEEDED(GetActivationFactory(HStringReference(RuntimeClass_Windows_Graphics_Display_DisplayProperties).Get(),
|
||||
@ -68,75 +59,6 @@ namespace {
|
||||
}
|
||||
};
|
||||
|
||||
void LogW(const wchar_t *fmt, ...)
|
||||
{
|
||||
va_list args = nullptr;
|
||||
if(!lstrlenW(fmt))
|
||||
return;
|
||||
va_start(args, fmt);
|
||||
int buflen = _vscwprintf(fmt, args);
|
||||
wchar_t* buffer = new wchar_t[buflen+1];
|
||||
if (!buffer) {
|
||||
va_end(args);
|
||||
return;
|
||||
}
|
||||
vswprintf(buffer, buflen, fmt, args);
|
||||
va_end(args);
|
||||
|
||||
// MSVC, including remote debug sessions
|
||||
OutputDebugStringW(buffer);
|
||||
OutputDebugStringW(L"\n");
|
||||
|
||||
int len = wcslen(buffer);
|
||||
if (len) {
|
||||
char* utf8 = new char[len+1];
|
||||
memset(utf8, 0, sizeof(utf8));
|
||||
if (WideCharToMultiByte(CP_ACP, 0, buffer,
|
||||
-1, utf8, len+1, nullptr,
|
||||
nullptr) > 0) {
|
||||
// desktop console
|
||||
printf("%s\n", utf8);
|
||||
#ifdef PR_LOGGING
|
||||
NS_ASSERTION(metroWidgetLog, "Called MetroUtils Log() but MetroWidget "
|
||||
"log module doesn't exist!");
|
||||
PR_LOG(metroWidgetLog, PR_LOG_ALWAYS, (utf8));
|
||||
#endif
|
||||
}
|
||||
delete[] utf8;
|
||||
}
|
||||
delete[] buffer;
|
||||
}
|
||||
|
||||
void Log(const char *fmt, ...)
|
||||
{
|
||||
va_list args = nullptr;
|
||||
if(!strlen(fmt))
|
||||
return;
|
||||
va_start(args, fmt);
|
||||
int buflen = _vscprintf(fmt, args);
|
||||
char* buffer = new char[buflen+1];
|
||||
if (!buffer) {
|
||||
va_end(args);
|
||||
return;
|
||||
}
|
||||
vsprintf(buffer, fmt, args);
|
||||
va_end(args);
|
||||
|
||||
// MSVC, including remote debug sessions
|
||||
OutputDebugStringA(buffer);
|
||||
OutputDebugStringW(L"\n");
|
||||
|
||||
// desktop console
|
||||
printf("%s\n", buffer);
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
NS_ASSERTION(metroWidgetLog, "Called MetroUtils Log() but MetroWidget "
|
||||
"log module doesn't exist!");
|
||||
PR_LOG(metroWidgetLog, PR_LOG_ALWAYS, (buffer));
|
||||
#endif
|
||||
delete[] buffer;
|
||||
}
|
||||
|
||||
// Conversion between logical and physical coordinates
|
||||
int32_t
|
||||
MetroUtils::LogToPhys(FLOAT aValue)
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsString.h"
|
||||
#include "nsPoint.h"
|
||||
#include "WinUtils.h"
|
||||
|
||||
#include "mozwrlbase.h"
|
||||
|
||||
@ -16,15 +17,6 @@
|
||||
#include <windows.foundation.h>
|
||||
#include <windows.ui.viewmanagement.h>
|
||||
|
||||
void Log(const char *fmt, ...);
|
||||
void LogW(const wchar_t *fmt, ...);
|
||||
|
||||
#define LogFunction() Log(__FUNCTION__)
|
||||
#define LogThread() Log("%s: IsMainThread:%d ThreadId:%X", __FUNCTION__, NS_IsMainThread(), GetCurrentThreadId())
|
||||
#define LogThis() Log("[%X] %s", this, __FUNCTION__)
|
||||
#define LogException(e) Log("%s Exception:%s", __FUNCTION__, e->ToString()->Data())
|
||||
#define LogHRESULT(hr) Log("%s hr=%X", __FUNCTION__, hr)
|
||||
|
||||
// HRESULT checkers, these warn on failure in debug builds
|
||||
#ifdef DEBUG
|
||||
#define DebugLogHR(hr) LogHRESULT(hr)
|
||||
|
@ -120,20 +120,20 @@ namespace {
|
||||
for (uint32_t i = 0; i < aExtraInputsLen; i++) {
|
||||
inputs[keySequence.Length()+i] = aExtraInputs[i];
|
||||
}
|
||||
Log(" Sending inputs");
|
||||
WinUtils::Log(" Sending inputs");
|
||||
for (uint32_t i = 0; i < len; i++) {
|
||||
if (inputs[i].type == INPUT_KEYBOARD) {
|
||||
Log(" Key press: 0x%x %s",
|
||||
WinUtils::Log(" Key press: 0x%x %s",
|
||||
inputs[i].ki.wVk,
|
||||
inputs[i].ki.dwFlags & KEYEVENTF_KEYUP
|
||||
? "UP"
|
||||
: "DOWN");
|
||||
} else if(inputs[i].type == INPUT_MOUSE) {
|
||||
Log(" Mouse input: 0x%x 0x%x",
|
||||
WinUtils::Log(" Mouse input: 0x%x 0x%x",
|
||||
inputs[i].mi.dwFlags,
|
||||
inputs[i].mi.mouseData);
|
||||
} else {
|
||||
Log(" Unknown input type!");
|
||||
WinUtils::Log(" Unknown input type!");
|
||||
}
|
||||
}
|
||||
::SendInput(len, inputs, sizeof(INPUT));
|
||||
@ -143,7 +143,7 @@ namespace {
|
||||
// waiting to be processed by our event loop. Now we manually pump
|
||||
// those messages so that, upon our return, all the inputs have been
|
||||
// processed.
|
||||
Log(" Inputs sent. Waiting for input messages to clear");
|
||||
WinUtils::Log(" Inputs sent. Waiting for input messages to clear");
|
||||
MSG msg;
|
||||
while (WinUtils::PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) {
|
||||
if (nsTextStore::ProcessRawKeyMessage(msg)) {
|
||||
@ -151,17 +151,14 @@ namespace {
|
||||
}
|
||||
::TranslateMessage(&msg);
|
||||
::DispatchMessage(&msg);
|
||||
Log(" Dispatched 0x%x 0x%x 0x%x", msg.message, msg.wParam, msg.lParam);
|
||||
WinUtils::Log(" Dispatched 0x%x 0x%x 0x%x", msg.message, msg.wParam, msg.lParam);
|
||||
}
|
||||
Log(" No more input messages");
|
||||
WinUtils::Log(" No more input messages");
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED0(MetroWidget, nsBaseWidget)
|
||||
|
||||
|
||||
nsRefPtr<mozilla::layers::APZCTreeManager> MetroWidget::sAPZC;
|
||||
|
||||
MetroWidget::MetroWidget() :
|
||||
mTransparencyMode(eTransparencyOpaque),
|
||||
mWnd(nullptr),
|
||||
@ -188,7 +185,7 @@ MetroWidget::~MetroWidget()
|
||||
|
||||
// Global shutdown
|
||||
if (!gInstanceCount) {
|
||||
MetroWidget::sAPZC = nullptr;
|
||||
APZController::sAPZC = nullptr;
|
||||
nsTextStore::Terminate();
|
||||
} // !gInstanceCount
|
||||
}
|
||||
@ -217,20 +214,20 @@ MetroWidget::Create(nsIWidget *aParent,
|
||||
if (mWindowType != eWindowType_toplevel) {
|
||||
switch(mWindowType) {
|
||||
case eWindowType_dialog:
|
||||
Log("eWindowType_dialog window requested, returning failure.");
|
||||
WinUtils::Log("eWindowType_dialog window requested, returning failure.");
|
||||
break;
|
||||
case eWindowType_child:
|
||||
Log("eWindowType_child window requested, returning failure.");
|
||||
WinUtils::Log("eWindowType_child window requested, returning failure.");
|
||||
break;
|
||||
case eWindowType_popup:
|
||||
Log("eWindowType_popup window requested, returning failure.");
|
||||
WinUtils::Log("eWindowType_popup window requested, returning failure.");
|
||||
break;
|
||||
case eWindowType_plugin:
|
||||
Log("eWindowType_plugin window requested, returning failure.");
|
||||
WinUtils::Log("eWindowType_plugin window requested, returning failure.");
|
||||
break;
|
||||
// we should support toolkit's eWindowType_invisible at some point.
|
||||
case eWindowType_invisible:
|
||||
Log("eWindowType_invisible window requested, this doesn't actually exist!");
|
||||
WinUtils::Log("eWindowType_invisible window requested, this doesn't actually exist!");
|
||||
return NS_OK;
|
||||
}
|
||||
NS_WARNING("Invalid window type requested.");
|
||||
@ -271,7 +268,7 @@ MetroWidget::Destroy()
|
||||
{
|
||||
if (mOnDestroyCalled)
|
||||
return NS_OK;
|
||||
Log("[%X] %s mWnd=%X type=%d", this, __FUNCTION__, mWnd, mWindowType);
|
||||
WinUtils::Log("[%X] %s mWnd=%X type=%d", this, __FUNCTION__, mWnd, mWindowType);
|
||||
mOnDestroyCalled = true;
|
||||
|
||||
nsCOMPtr<nsIWidget> kungFuDeathGrip(this);
|
||||
@ -280,7 +277,7 @@ MetroWidget::Destroy()
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIObserverService> observerService = do_GetService("@mozilla.org/observer-service;1", &rv);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
observerService->RemoveObserver(this, "scroll-offset-changed");
|
||||
observerService->RemoveObserver(this, "apzc-scroll-offset-changed");
|
||||
}
|
||||
}
|
||||
|
||||
@ -520,7 +517,7 @@ MetroWidget::SynthesizeNativeMouseEvent(nsIntPoint aPoint,
|
||||
uint32_t aNativeMessage,
|
||||
uint32_t aModifierFlags)
|
||||
{
|
||||
Log("ENTERED SynthesizeNativeMouseEvent");
|
||||
WinUtils::Log("ENTERED SynthesizeNativeMouseEvent");
|
||||
|
||||
INPUT inputs[2];
|
||||
memset(inputs, 0, 2*sizeof(INPUT));
|
||||
@ -535,7 +532,7 @@ MetroWidget::SynthesizeNativeMouseEvent(nsIntPoint aPoint,
|
||||
inputs[1].mi.dwFlags = aNativeMessage;
|
||||
SendInputs(aModifierFlags, inputs, 2);
|
||||
|
||||
Log("Exiting SynthesizeNativeMouseEvent");
|
||||
WinUtils::Log("Exiting SynthesizeNativeMouseEvent");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -814,7 +811,7 @@ MetroWidget::WindowProcedure(HWND aWnd, UINT aMsg, WPARAM aWParam, LPARAM aLPara
|
||||
return res;
|
||||
}
|
||||
NS_ASSERTION(res, "UiaReturnRawElementProvider failed!");
|
||||
Log("UiaReturnRawElementProvider failed! GetLastError=%X", GetLastError());
|
||||
WinUtils::Log("UiaReturnRawElementProvider failed! GetLastError=%X", GetLastError());
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -941,22 +938,34 @@ MetroWidget::ShouldUseAPZC()
|
||||
Preferences::GetBool(kPrefName, false);
|
||||
}
|
||||
|
||||
void
|
||||
MetroWidget::SetWidgetListener(nsIWidgetListener* aWidgetListener)
|
||||
{
|
||||
mWidgetListener = aWidgetListener;
|
||||
if (mController) {
|
||||
mController->SetWidgetListener(aWidgetListener);
|
||||
}
|
||||
}
|
||||
|
||||
CompositorParent* MetroWidget::NewCompositorParent(int aSurfaceWidth, int aSurfaceHeight)
|
||||
{
|
||||
CompositorParent *compositor = nsBaseWidget::NewCompositorParent(aSurfaceWidth, aSurfaceHeight);
|
||||
|
||||
if (ShouldUseAPZC()) {
|
||||
mRootLayerTreeId = compositor->RootLayerTreeId();
|
||||
|
||||
mController = new APZController();
|
||||
mController->SetWidgetListener(mWidgetListener);
|
||||
|
||||
CompositorParent::SetControllerForLayerTree(mRootLayerTreeId, mController);
|
||||
|
||||
MetroWidget::sAPZC = CompositorParent::GetAPZCTreeManager(compositor->RootLayerTreeId());
|
||||
MetroWidget::sAPZC->SetDPI(GetDPI());
|
||||
APZController::sAPZC = CompositorParent::GetAPZCTreeManager(compositor->RootLayerTreeId());
|
||||
APZController::sAPZC->SetDPI(GetDPI());
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIObserverService> observerService = do_GetService("@mozilla.org/observer-service;1", &rv);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
observerService->AddObserver(this, "scroll-offset-changed", false);
|
||||
observerService->AddObserver(this, "apzc-scroll-offset-changed", false);
|
||||
}
|
||||
}
|
||||
|
||||
@ -967,29 +976,29 @@ void
|
||||
MetroWidget::ApzContentConsumingTouch()
|
||||
{
|
||||
LogFunction();
|
||||
if (!MetroWidget::sAPZC) {
|
||||
if (!APZController::sAPZC) {
|
||||
return;
|
||||
}
|
||||
MetroWidget::sAPZC->ContentReceivedTouch(mRootLayerTreeId, true);
|
||||
APZController::sAPZC->ContentReceivedTouch(mRootLayerTreeId, true);
|
||||
}
|
||||
|
||||
void
|
||||
MetroWidget::ApzContentIgnoringTouch()
|
||||
{
|
||||
LogFunction();
|
||||
if (!MetroWidget::sAPZC) {
|
||||
if (!APZController::sAPZC) {
|
||||
return;
|
||||
}
|
||||
MetroWidget::sAPZC->ContentReceivedTouch(mRootLayerTreeId, false);
|
||||
APZController::sAPZC->ContentReceivedTouch(mRootLayerTreeId, false);
|
||||
}
|
||||
|
||||
bool
|
||||
MetroWidget::HitTestAPZC(ScreenPoint& pt)
|
||||
{
|
||||
if (!MetroWidget::sAPZC) {
|
||||
if (!APZController::sAPZC) {
|
||||
return false;
|
||||
}
|
||||
return MetroWidget::sAPZC->HitTestAPZC(pt);
|
||||
return APZController::sAPZC->HitTestAPZC(pt);
|
||||
}
|
||||
|
||||
nsEventStatus
|
||||
@ -997,10 +1006,10 @@ MetroWidget::ApzReceiveInputEvent(WidgetInputEvent* aEvent)
|
||||
{
|
||||
MOZ_ASSERT(aEvent);
|
||||
|
||||
if (!MetroWidget::sAPZC) {
|
||||
if (!APZController::sAPZC) {
|
||||
return nsEventStatus_eIgnore;
|
||||
}
|
||||
return MetroWidget::sAPZC->ReceiveInputEvent(*aEvent->AsInputEvent());
|
||||
return APZController::sAPZC->ReceiveInputEvent(*aEvent->AsInputEvent());
|
||||
}
|
||||
|
||||
nsEventStatus
|
||||
@ -1010,11 +1019,11 @@ MetroWidget::ApzReceiveInputEvent(WidgetInputEvent* aInEvent,
|
||||
MOZ_ASSERT(aInEvent);
|
||||
MOZ_ASSERT(aOutEvent);
|
||||
|
||||
if (!MetroWidget::sAPZC) {
|
||||
if (!APZController::sAPZC) {
|
||||
return nsEventStatus_eIgnore;
|
||||
}
|
||||
return MetroWidget::sAPZC->ReceiveInputEvent(*aInEvent->AsInputEvent(),
|
||||
aOutEvent);
|
||||
return APZController::sAPZC->ReceiveInputEvent(*aInEvent->AsInputEvent(),
|
||||
aOutEvent);
|
||||
}
|
||||
|
||||
LayerManager*
|
||||
@ -1517,7 +1526,7 @@ NS_IMETHODIMP
|
||||
MetroWidget::Observe(nsISupports *subject, const char *topic, const PRUnichar *data)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(topic);
|
||||
if (!strcmp(topic, "scroll-offset-changed")) {
|
||||
if (!strcmp(topic, "apzc-scroll-offset-changed")) {
|
||||
uint64_t scrollId;
|
||||
int32_t presShellId;
|
||||
CSSIntPoint scrollOffset;
|
||||
@ -1531,11 +1540,11 @@ MetroWidget::Observe(nsISupports *subject, const char *topic, const PRUnichar *d
|
||||
NS_WARNING("Malformed scroll-offset-changed message");
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
if (MetroWidget::sAPZC) {
|
||||
MetroWidget::sAPZC->UpdateScrollOffset(
|
||||
ScrollableLayerGuid(mRootLayerTreeId, presShellId, scrollId),
|
||||
scrollOffset);
|
||||
if (!mController) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
mController->UpdateScrollOffset(ScrollableLayerGuid(mRootLayerTreeId, presShellId, scrollId),
|
||||
scrollOffset);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -22,7 +22,6 @@
|
||||
#endif
|
||||
#include "mozilla/EventForwards.h"
|
||||
#include "mozilla/layers/CompositorParent.h"
|
||||
#include "mozilla/layers/APZCTreeManager.h"
|
||||
#include "mozilla/layers/LayerManagerComposite.h"
|
||||
#include "nsDeque.h"
|
||||
#include "APZController.h"
|
||||
@ -85,6 +84,7 @@ public:
|
||||
|
||||
// nsBaseWidget
|
||||
virtual CompositorParent* NewCompositorParent(int aSurfaceWidth, int aSurfaceHeight);
|
||||
virtual void SetWidgetListener(nsIWidgetListener* aWidgetListener);
|
||||
|
||||
// nsIWidget interface
|
||||
NS_IMETHOD Create(nsIWidget *aParent,
|
||||
@ -235,10 +235,6 @@ protected:
|
||||
void DispatchAsyncScrollEvent(DispatchMsg* aEvent);
|
||||
void DeliverNextScrollEvent();
|
||||
void DeliverNextKeyboardEvent();
|
||||
DispatchMsg* CreateDispatchMsg(UINT aMsg, WPARAM aWParam, LPARAM aLParam);
|
||||
|
||||
public:
|
||||
static nsRefPtr<mozilla::layers::APZCTreeManager> sAPZC;
|
||||
|
||||
protected:
|
||||
OleInitializeWrapper mOleInitializeWrapper;
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include "MetroUtils.h"
|
||||
#include "UIABridgePrivate.h"
|
||||
#include "MetroWidget.h"
|
||||
#include "WinUtils.h"
|
||||
|
||||
#include <wrl.h>
|
||||
#include <OAIdl.h>
|
||||
@ -15,6 +16,7 @@
|
||||
#ifdef ACCESSIBILITY
|
||||
using namespace mozilla::a11y;
|
||||
#endif
|
||||
using namespace mozilla::widget;
|
||||
using namespace Microsoft::WRL;
|
||||
using namespace Microsoft::WRL::Wrappers;
|
||||
using namespace ABI::Windows::UI;
|
||||
@ -26,10 +28,11 @@ using namespace ABI::Windows::System;
|
||||
#if !defined(DEBUG_BRIDGE)
|
||||
#undef LogThread
|
||||
#undef LogFunction
|
||||
#undef Log
|
||||
#define LogThread()
|
||||
#define LogFunction()
|
||||
#define Log(...)
|
||||
#define BridgeLog(...)
|
||||
#else
|
||||
#define BridgeLog(...) WinUtils::Log(__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \
|
||||
@ -49,7 +52,6 @@ static ComPtr<IUIAElement> gElement = nullptr;
|
||||
HRESULT
|
||||
UIABridge_CreateInstance(IInspectable **retVal)
|
||||
{
|
||||
LogFunction();
|
||||
HRESULT hr = E_OUTOFMEMORY;
|
||||
*retVal = nullptr;
|
||||
ComPtr<UIABridge> spProvider = Make<UIABridge>();
|
||||
@ -129,12 +131,14 @@ UIABridge::Connected()
|
||||
HRESULT
|
||||
UIABridge::SetFocusInternal(LONG_PTR aAccessible)
|
||||
{
|
||||
LogFunction();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
UIABridge::ClearFocus()
|
||||
{
|
||||
LogFunction();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
@ -147,9 +151,9 @@ DumpChildInfo(nsCOMPtr<nsIAccessible>& aChild)
|
||||
}
|
||||
nsString str;
|
||||
aChild->GetName(str);
|
||||
Log("name: %ls", str.BeginReading());
|
||||
BridgeLog("name: %ls", str.BeginReading());
|
||||
aChild->GetDescription(str);
|
||||
Log("description: %ls", str.BeginReading());
|
||||
BridgeLog("description: %ls", str.BeginReading());
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -157,7 +161,7 @@ static bool
|
||||
ChildHasFocus(nsCOMPtr<nsIAccessible>& aChild)
|
||||
{
|
||||
Accessible* access = (Accessible*)aChild.get();
|
||||
Log("Focus element flags: editable:%d focusable:%d readonly:%d",
|
||||
BridgeLog("Focus element flags: editable:%d focusable:%d readonly:%d",
|
||||
((access->NativeState() & mozilla::a11y::states::EDITABLE) > 0),
|
||||
((access->NativeState() & mozilla::a11y::states::FOCUSABLE) > 0),
|
||||
((access->NativeState() & mozilla::a11y::states::READONLY) > 0));
|
||||
@ -207,7 +211,7 @@ UIABridge::ElementProviderFromPoint(double x, double y, IRawElementProviderFragm
|
||||
}
|
||||
|
||||
// Windows calls this looking for the current focus element. Windows
|
||||
// will call here before accessible sends up any observer events through
|
||||
// will call here before accessible sends us any observer events through
|
||||
// the accessibility bridge, so update child focus information.
|
||||
HRESULT
|
||||
UIABridge::GetFocus(IRawElementProviderFragment ** retVal)
|
||||
@ -220,7 +224,7 @@ UIABridge::GetFocus(IRawElementProviderFragment ** retVal)
|
||||
nsCOMPtr<nsIAccessible> child;
|
||||
nsresult rv = mAccessible->GetFocusedChild(getter_AddRefs(child));
|
||||
if (!child) {
|
||||
Log("mAccessible->GetFocusedChild failed.");
|
||||
BridgeLog("mAccessible->GetFocusedChild failed.");
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
@ -229,7 +233,7 @@ UIABridge::GetFocus(IRawElementProviderFragment ** retVal)
|
||||
ComPtr<IUIAElement> element;
|
||||
gElement.As(&element);
|
||||
if (!element) {
|
||||
Log("gElement as IUIAElement failed.");
|
||||
BridgeLog("gElement as IUIAElement failed.");
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
@ -256,20 +260,20 @@ UIABridge::Navigate(NavigateDirection direction, IRawElementProviderFragment **
|
||||
|
||||
switch(direction) {
|
||||
case NavigateDirection_Parent:
|
||||
Log("UIABridge::Navigate NavigateDirection_Parent");
|
||||
BridgeLog("UIABridge::Navigate NavigateDirection_Parent");
|
||||
break;
|
||||
case NavigateDirection_NextSibling:
|
||||
Log("UIABridge::Navigate NavigateDirection_NextSibling");
|
||||
BridgeLog("UIABridge::Navigate NavigateDirection_NextSibling");
|
||||
break;
|
||||
case NavigateDirection_PreviousSibling:
|
||||
Log("UIABridge::Navigate NavigateDirection_PreviousSibling");
|
||||
BridgeLog("UIABridge::Navigate NavigateDirection_PreviousSibling");
|
||||
break;
|
||||
case NavigateDirection_FirstChild:
|
||||
Log("UIABridge::Navigate NavigateDirection_FirstChild");
|
||||
BridgeLog("UIABridge::Navigate NavigateDirection_FirstChild");
|
||||
gElement.Get()->QueryInterface(IID_PPV_ARGS(retVal));
|
||||
break;
|
||||
case NavigateDirection_LastChild:
|
||||
Log("UIABridge::Navigate NavigateDirection_LastChild");
|
||||
BridgeLog("UIABridge::Navigate NavigateDirection_LastChild");
|
||||
gElement.Get()->QueryInterface(IID_PPV_ARGS(retVal));
|
||||
break;
|
||||
}
|
||||
@ -366,7 +370,7 @@ HRESULT
|
||||
UIABridge::GetPatternProvider(PATTERNID patternId, IUnknown **ppRetVal)
|
||||
{
|
||||
LogFunction();
|
||||
Log("UIABridge::GetPatternProvider=%d", patternId);
|
||||
BridgeLog("UIABridge::GetPatternProvider=%d", patternId);
|
||||
|
||||
// The root window doesn't support any specific pattern
|
||||
*ppRetVal = nullptr;
|
||||
@ -381,37 +385,37 @@ UIABridge::GetPropertyValue(PROPERTYID idProp, VARIANT * pRetVal)
|
||||
|
||||
switch (idProp) {
|
||||
case UIA_AutomationIdPropertyId:
|
||||
Log("UIABridge::GetPropertyValue: idProp=UIA_AutomationIdPropertyId");
|
||||
BridgeLog("UIABridge::GetPropertyValue: idProp=UIA_AutomationIdPropertyId");
|
||||
break;
|
||||
case UIA_ControlTypePropertyId:
|
||||
Log("UIABridge::GetPropertyValue: idProp=UIA_ControlTypePropertyId");
|
||||
BridgeLog("UIABridge::GetPropertyValue: idProp=UIA_ControlTypePropertyId");
|
||||
break;
|
||||
case UIA_IsKeyboardFocusablePropertyId:
|
||||
Log("UIABridge::GetPropertyValue: idProp=UIA_IsKeyboardFocusablePropertyId");
|
||||
BridgeLog("UIABridge::GetPropertyValue: idProp=UIA_IsKeyboardFocusablePropertyId");
|
||||
break;
|
||||
case UIA_IsContentElementPropertyId:
|
||||
Log("UIABridge::GetPropertyValue: idProp=UIA_IsContentElementPropertyId");
|
||||
BridgeLog("UIABridge::GetPropertyValue: idProp=UIA_IsContentElementPropertyId");
|
||||
break;
|
||||
case UIA_IsControlElementPropertyId:
|
||||
Log("UIABridge::GetPropertyValue: idProp=UIA_IsControlElementPropertyId");
|
||||
BridgeLog("UIABridge::GetPropertyValue: idProp=UIA_IsControlElementPropertyId");
|
||||
break;
|
||||
case UIA_IsEnabledPropertyId:
|
||||
Log("UIABridge::GetPropertyValue: idProp=UIA_IsEnabledPropertyId");
|
||||
BridgeLog("UIABridge::GetPropertyValue: idProp=UIA_IsEnabledPropertyId");
|
||||
break;
|
||||
case UIA_HasKeyboardFocusPropertyId:
|
||||
Log("UIABridge::GetPropertyValue: idProp=UIA_HasKeyboardFocusPropertyId");
|
||||
BridgeLog("UIABridge::GetPropertyValue: idProp=UIA_HasKeyboardFocusPropertyId");
|
||||
break;
|
||||
case UIA_NamePropertyId:
|
||||
Log("UIABridge::GetPropertyValue: idProp=UIA_NamePropertyId");
|
||||
BridgeLog("UIABridge::GetPropertyValue: idProp=UIA_NamePropertyId");
|
||||
break;
|
||||
case UIA_IsPasswordPropertyId:
|
||||
Log("UIABridge::GetPropertyValue: idProp=UIA_IsPasswordPropertyId");
|
||||
BridgeLog("UIABridge::GetPropertyValue: idProp=UIA_IsPasswordPropertyId");
|
||||
break;
|
||||
case UIA_NativeWindowHandlePropertyId:
|
||||
Log("UIABridge::GetPropertyValue: idProp=UIA_NativeWindowHandlePropertyId");
|
||||
BridgeLog("UIABridge::GetPropertyValue: idProp=UIA_NativeWindowHandlePropertyId");
|
||||
break;
|
||||
default:
|
||||
Log("UIABridge::GetPropertyValue: idProp=%d", idProp);
|
||||
BridgeLog("UIABridge::GetPropertyValue: idProp=%d", idProp);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -459,7 +463,7 @@ UIABridge::GetPropertyValue(PROPERTYID idProp, VARIANT * pRetVal)
|
||||
break;
|
||||
|
||||
default:
|
||||
Log("UIABridge: Unhandled property");
|
||||
BridgeLog("UIABridge: Unhandled property");
|
||||
break;
|
||||
}
|
||||
return S_OK;
|
||||
@ -564,7 +568,7 @@ UIATextElement::get_BoundingRectangle(UiaRect * retVal)
|
||||
retVal->width = (float)docWidth;
|
||||
retVal->height = (float)docHeight;
|
||||
|
||||
Log("get_BoundingRectangle: left=%d top=%d right=%d bottom=%d", docX, docY, docX + docWidth, docY + docHeight);
|
||||
BridgeLog("get_BoundingRectangle: left=%d top=%d right=%d bottom=%d", docX, docY, docX + docWidth, docY + docHeight);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
@ -603,7 +607,7 @@ HRESULT
|
||||
UIATextElement::GetPatternProvider(PATTERNID patternId, IUnknown **ppRetVal)
|
||||
{
|
||||
LogFunction();
|
||||
Log("UIATextElement::GetPatternProvider=%d", patternId);
|
||||
BridgeLog("UIATextElement::GetPatternProvider=%d", patternId);
|
||||
|
||||
// UIA_ValuePatternId - 10002
|
||||
// UIA_TextPatternId - 10014
|
||||
@ -611,12 +615,12 @@ UIATextElement::GetPatternProvider(PATTERNID patternId, IUnknown **ppRetVal)
|
||||
|
||||
*ppRetVal = nullptr;
|
||||
if (patternId == UIA_TextPatternId) {
|
||||
Log("** TextPattern requested from element.");
|
||||
BridgeLog("** TextPattern requested from element.");
|
||||
*ppRetVal = static_cast<ITextProvider*>(this);
|
||||
AddRef();
|
||||
return S_OK;
|
||||
} else if (patternId == UIA_ValuePatternId) {
|
||||
Log("** ValuePattern requested from element.");
|
||||
BridgeLog("** ValuePattern requested from element.");
|
||||
*ppRetVal = static_cast<IValueProvider*>(this);
|
||||
AddRef();
|
||||
return S_OK;
|
||||
@ -637,34 +641,34 @@ UIATextElement::GetPropertyValue(PROPERTYID idProp, VARIANT * pRetVal)
|
||||
|
||||
switch (idProp) {
|
||||
case UIA_AutomationIdPropertyId:
|
||||
Log("UIATextElement::GetPropertyValue: idProp=UIA_AutomationIdPropertyId");
|
||||
BridgeLog("UIATextElement::GetPropertyValue: idProp=UIA_AutomationIdPropertyId");
|
||||
break;
|
||||
case UIA_ControlTypePropertyId:
|
||||
Log("UIATextElement::GetPropertyValue: idProp=UIA_ControlTypePropertyId");
|
||||
BridgeLog("UIATextElement::GetPropertyValue: idProp=UIA_ControlTypePropertyId");
|
||||
break;
|
||||
case UIA_IsKeyboardFocusablePropertyId:
|
||||
Log("UIATextElement::GetPropertyValue: idProp=UIA_IsKeyboardFocusablePropertyId");
|
||||
BridgeLog("UIATextElement::GetPropertyValue: idProp=UIA_IsKeyboardFocusablePropertyId");
|
||||
break;
|
||||
case UIA_IsContentElementPropertyId:
|
||||
Log("UIATextElement::GetPropertyValue: idProp=UIA_IsContentElementPropertyId");
|
||||
BridgeLog("UIATextElement::GetPropertyValue: idProp=UIA_IsContentElementPropertyId");
|
||||
break;
|
||||
case UIA_IsControlElementPropertyId:
|
||||
Log("UIATextElement::GetPropertyValue: idProp=UIA_IsControlElementPropertyId");
|
||||
BridgeLog("UIATextElement::GetPropertyValue: idProp=UIA_IsControlElementPropertyId");
|
||||
break;
|
||||
case UIA_IsEnabledPropertyId:
|
||||
Log("UIATextElement::GetPropertyValue: idProp=UIA_IsEnabledPropertyId");
|
||||
BridgeLog("UIATextElement::GetPropertyValue: idProp=UIA_IsEnabledPropertyId");
|
||||
break;
|
||||
case UIA_HasKeyboardFocusPropertyId:
|
||||
Log("UIATextElement::GetPropertyValue: idProp=UIA_HasKeyboardFocusPropertyId");
|
||||
BridgeLog("UIATextElement::GetPropertyValue: idProp=UIA_HasKeyboardFocusPropertyId");
|
||||
break;
|
||||
case UIA_NamePropertyId:
|
||||
Log("UIATextElement::GetPropertyValue: idProp=UIA_NamePropertyId");
|
||||
BridgeLog("UIATextElement::GetPropertyValue: idProp=UIA_NamePropertyId");
|
||||
break;
|
||||
case UIA_IsPasswordPropertyId:
|
||||
Log("UIATextElement::GetPropertyValue: idProp=UIA_IsPasswordPropertyId");
|
||||
BridgeLog("UIATextElement::GetPropertyValue: idProp=UIA_IsPasswordPropertyId");
|
||||
break;
|
||||
default:
|
||||
Log("UIATextElement::GetPropertyValue: idProp=%d", idProp);
|
||||
BridgeLog("UIATextElement::GetPropertyValue: idProp=%d", idProp);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -719,7 +723,7 @@ UIATextElement::GetPropertyValue(PROPERTYID idProp, VARIANT * pRetVal)
|
||||
break;
|
||||
|
||||
default:
|
||||
Log("UIATextElement: Unhandled property");
|
||||
BridgeLog("UIATextElement: Unhandled property");
|
||||
break;
|
||||
}
|
||||
return S_OK;
|
||||
|
Loading…
Reference in New Issue
Block a user