mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge m-c to b2g-inbound
This commit is contained in:
commit
5e7558a65a
@ -425,3 +425,4 @@ skip-if = e10s # Bug 516755 - SessionStore disabled for e10s
|
|||||||
skip-if = e10s # Bug 940206 - nsIWebContentHandlerRegistrar::registerProtocolHandler doesn't work in e10s
|
skip-if = e10s # Bug 940206 - nsIWebContentHandlerRegistrar::registerProtocolHandler doesn't work in e10s
|
||||||
[browser_no_mcb_on_http_site.js]
|
[browser_no_mcb_on_http_site.js]
|
||||||
skip-if = e10s # Bug 516755 - SessionStore disabled for e10s
|
skip-if = e10s # Bug 516755 - SessionStore disabled for e10s
|
||||||
|
[browser_bug1003461-switchtab-override.js]
|
||||||
|
@ -0,0 +1,63 @@
|
|||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
add_task(function* test_switchtab_override() {
|
||||||
|
let testURL = "http://example.org/browser/browser/base/content/test/general/dummy_page.html";
|
||||||
|
|
||||||
|
info("Opening first tab");
|
||||||
|
let tab = gBrowser.addTab(testURL);
|
||||||
|
let deferred = Promise.defer();
|
||||||
|
whenTabLoaded(tab, deferred.resolve);
|
||||||
|
yield deferred.promise;
|
||||||
|
|
||||||
|
info("Opening and selecting second tab");
|
||||||
|
let secondTab = gBrowser.selectedTab = gBrowser.addTab();
|
||||||
|
registerCleanupFunction(() => {
|
||||||
|
try {
|
||||||
|
gBrowser.removeTab(tab);
|
||||||
|
gBrowser.removeTab(secondTab);
|
||||||
|
} catch(ex) { /* tabs may have already been closed in case of failure */ }
|
||||||
|
});
|
||||||
|
|
||||||
|
info("Wait for autocomplete")
|
||||||
|
deferred = Promise.defer();
|
||||||
|
let onSearchComplete = gURLBar.onSearchComplete;
|
||||||
|
registerCleanupFunction(() => {
|
||||||
|
gURLBar.onSearchComplete = onSearchComplete;
|
||||||
|
});
|
||||||
|
gURLBar.onSearchComplete = function () {
|
||||||
|
ok(gURLBar.popupOpen, "The autocomplete popup is correctly open");
|
||||||
|
onSearchComplete.apply(gURLBar);
|
||||||
|
deferred.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
|
gURLBar.focus();
|
||||||
|
gURLBar.value = "dummy_pag";
|
||||||
|
EventUtils.synthesizeKey("e" , {});
|
||||||
|
yield deferred.promise;
|
||||||
|
|
||||||
|
info("Select first autocomplete popup entry");
|
||||||
|
EventUtils.synthesizeKey("VK_DOWN" , {});
|
||||||
|
ok(/moz-action:switchtab/.test(gURLBar.value), "switch to tab entry found");
|
||||||
|
|
||||||
|
info("Override switch-to-tab");
|
||||||
|
let deferred = Promise.defer();
|
||||||
|
// In case of failure this would switch tab.
|
||||||
|
let onTabSelect = event => {
|
||||||
|
deferred.reject(new Error("Should have overridden switch to tab"));
|
||||||
|
};
|
||||||
|
gBrowser.tabContainer.addEventListener("TabSelect", onTabSelect, false);
|
||||||
|
registerCleanupFunction(() => {
|
||||||
|
gBrowser.tabContainer.removeEventListener("TabSelect", onTabSelect, false);
|
||||||
|
});
|
||||||
|
// Otherwise it would load the page.
|
||||||
|
whenTabLoaded(secondTab, deferred.resolve);
|
||||||
|
|
||||||
|
EventUtils.synthesizeKey("VK_SHIFT" , { type: "keydown" });
|
||||||
|
EventUtils.synthesizeKey("VK_RETURN" , { });
|
||||||
|
EventUtils.synthesizeKey("VK_SHIFT" , { type: "keyup" });
|
||||||
|
yield deferred.promise;
|
||||||
|
|
||||||
|
yield promiseClearHistory();
|
||||||
|
});
|
@ -292,6 +292,39 @@ function promiseHistoryClearedState(aURIs, aShouldBeCleared) {
|
|||||||
return deferred.promise;
|
return deferred.promise;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows waiting for an observer notification once.
|
||||||
|
*
|
||||||
|
* @param topic
|
||||||
|
* Notification topic to observe.
|
||||||
|
*
|
||||||
|
* @return {Promise}
|
||||||
|
* @resolves The array [subject, data] from the observed notification.
|
||||||
|
* @rejects Never.
|
||||||
|
*/
|
||||||
|
function promiseTopicObserved(topic)
|
||||||
|
{
|
||||||
|
let deferred = Promise.defer();
|
||||||
|
Services.obs.addObserver(function PTO_observe(subject, topic, data) {
|
||||||
|
Services.obs.removeObserver(PTO_observe, topic);
|
||||||
|
deferred.resolve([subject, data]);
|
||||||
|
}, topic, false);
|
||||||
|
return deferred.promise;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears history asynchronously.
|
||||||
|
*
|
||||||
|
* @return {Promise}
|
||||||
|
* @resolves When history has been cleared.
|
||||||
|
* @rejects Never.
|
||||||
|
*/
|
||||||
|
function promiseClearHistory() {
|
||||||
|
let promise = promiseTopicObserved(PlacesUtils.TOPIC_EXPIRATION_FINISHED);
|
||||||
|
PlacesUtils.bhistory.removeAllPages();
|
||||||
|
return promise;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Waits for the next top-level document load in the current browser. The URI
|
* Waits for the next top-level document load in the current browser. The URI
|
||||||
* of the document is compared against aExpectedURL. The load is then stopped
|
* of the document is compared against aExpectedURL. The load is then stopped
|
||||||
|
@ -143,7 +143,9 @@
|
|||||||
this._value = aValue;
|
this._value = aValue;
|
||||||
var returnValue = aValue;
|
var returnValue = aValue;
|
||||||
var action = this._parseActionUrl(aValue);
|
var action = this._parseActionUrl(aValue);
|
||||||
if (action) {
|
// Don't put back the action if we are invoked while override actions
|
||||||
|
// is active.
|
||||||
|
if (action && this._numNoActionsKeys <= 0) {
|
||||||
returnValue = action.param;
|
returnValue = action.param;
|
||||||
this.setAttribute("actiontype", action.type);
|
this.setAttribute("actiontype", action.type);
|
||||||
} else {
|
} else {
|
||||||
|
@ -24,10 +24,10 @@ add_task(function*() {
|
|||||||
ChromeUtils.synthesizeDrop(identityBox, overflowChevron, [], null);
|
ChromeUtils.synthesizeDrop(identityBox, overflowChevron, [], null);
|
||||||
yield panelShownPromise;
|
yield panelShownPromise;
|
||||||
|
|
||||||
ok(true, "Overflow panel is shown.");
|
info("Overflow panel is shown.");
|
||||||
|
|
||||||
let panelHiddenPromise = promisePanelElementHidden(window, widgetOverflowPanel);
|
let panelHiddenPromise = promisePanelElementHidden(window, widgetOverflowPanel);
|
||||||
EventUtils.synthesizeKey("VK_ESCAPE", {});
|
widgetOverflowPanel.hidePopup();
|
||||||
yield panelHiddenPromise;
|
yield panelHiddenPromise;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -11,22 +11,42 @@ add_task(function() {
|
|||||||
yield startCustomizing();
|
yield startCustomizing();
|
||||||
CustomizableUI.addWidgetToArea("personal-bookmarks", CustomizableUI.AREA_PANEL);
|
CustomizableUI.addWidgetToArea("personal-bookmarks", CustomizableUI.AREA_PANEL);
|
||||||
yield endCustomizing();
|
yield endCustomizing();
|
||||||
|
|
||||||
yield PanelUI.show();
|
yield PanelUI.show();
|
||||||
|
|
||||||
let bookmarksToolbarPlaceholder = document.getElementById(buttonId);
|
let bookmarksToolbarPlaceholder = document.getElementById(buttonId);
|
||||||
ok(bookmarksToolbarPlaceholder.classList.contains("toolbarbutton-1"),
|
ok(bookmarksToolbarPlaceholder.classList.contains("toolbarbutton-1"),
|
||||||
"Button should have toolbarbutton-1 class");
|
"Button should have toolbarbutton-1 class");
|
||||||
is(bookmarksToolbarPlaceholder.getAttribute("wrap"), "true",
|
is(bookmarksToolbarPlaceholder.getAttribute("wrap"), "true",
|
||||||
"Button should have the 'wrap' attribute");
|
"Button should have the 'wrap' attribute");
|
||||||
yield PanelUI.hide();
|
|
||||||
|
|
||||||
let newWin = yield openAndLoadWindow();
|
info("Waiting for panel to close");
|
||||||
|
let panelHiddenPromise = promisePanelHidden(window);
|
||||||
|
PanelUI.hide();
|
||||||
|
yield panelHiddenPromise;
|
||||||
|
|
||||||
|
info("Waiting for window to open");
|
||||||
|
let newWin = yield openAndLoadWindow({}, true);
|
||||||
|
|
||||||
|
info("Waiting for panel in new window to open");
|
||||||
yield newWin.PanelUI.show();
|
yield newWin.PanelUI.show();
|
||||||
let newWinBookmarksToolbarPlaceholder = newWin.document.getElementById(buttonId);
|
let newWinBookmarksToolbarPlaceholder = newWin.document.getElementById(buttonId);
|
||||||
ok(newWinBookmarksToolbarPlaceholder.classList.contains("toolbarbutton-1"),
|
ok(newWinBookmarksToolbarPlaceholder.classList.contains("toolbarbutton-1"),
|
||||||
"Button in new window should have toolbarbutton-1 class");
|
"Button in new window should have toolbarbutton-1 class");
|
||||||
is(newWinBookmarksToolbarPlaceholder.getAttribute("wrap"), "true",
|
is(newWinBookmarksToolbarPlaceholder.getAttribute("wrap"), "true",
|
||||||
"Button in new window should have 'wrap' attribute");
|
"Button in new window should have 'wrap' attribute");
|
||||||
yield newWin.PanelUI.hide();
|
|
||||||
|
info("Waiting for panel in new window to close");
|
||||||
|
panelHiddenPromise = promisePanelHidden(newWin);
|
||||||
|
newWin.PanelUI.hide();
|
||||||
|
yield panelHiddenPromise;
|
||||||
|
|
||||||
|
info("Waiting for new window to close");
|
||||||
yield promiseWindowClosed(newWin);
|
yield promiseWindowClosed(newWin);
|
||||||
|
});
|
||||||
|
|
||||||
|
add_task(function asyncCleanUp() {
|
||||||
|
yield endCustomizing();
|
||||||
CustomizableUI.reset();
|
CustomizableUI.reset();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -16,6 +16,10 @@ function test() {
|
|||||||
const PREF_UPGRADE = "browser.sessionstore.upgradeBackup.latestBuildID";
|
const PREF_UPGRADE = "browser.sessionstore.upgradeBackup.latestBuildID";
|
||||||
let buildID = Services.appinfo.platformBuildID;
|
let buildID = Services.appinfo.platformBuildID;
|
||||||
|
|
||||||
|
// Write state once before starting the test to
|
||||||
|
// ensure sessionstore.js writes won't happen in between.
|
||||||
|
yield forceSaveState();
|
||||||
|
|
||||||
// Force backup to take place with a file decided by us
|
// Force backup to take place with a file decided by us
|
||||||
Services.prefs.setCharPref(PREF_UPGRADE, "");
|
Services.prefs.setCharPref(PREF_UPGRADE, "");
|
||||||
let contents = "browser_upgrade_backup.js";
|
let contents = "browser_upgrade_backup.js";
|
||||||
@ -28,13 +32,13 @@ function test() {
|
|||||||
is((yield OS.File.exists(pathBackup)), true, "upgrade backup file has been created");
|
is((yield OS.File.exists(pathBackup)), true, "upgrade backup file has been created");
|
||||||
|
|
||||||
let data = yield OS.File.read(pathBackup);
|
let data = yield OS.File.read(pathBackup);
|
||||||
is(contents, (new TextDecoder()).decode(data), "upgrade backup contains the expected contents");
|
is(new TextDecoder().decode(data), contents, "upgrade backup contains the expected contents");
|
||||||
|
|
||||||
// Ensure that we don't re-backup by accident
|
// Ensure that we don't re-backup by accident
|
||||||
yield OS.File.writeAtomic(pathStore, "something else entirely", { tmpPath: pathStore + ".tmp" });
|
yield OS.File.writeAtomic(pathStore, "something else entirely", { tmpPath: pathStore + ".tmp" });
|
||||||
yield SessionStore._internal._performUpgradeBackup();
|
yield SessionStore._internal._performUpgradeBackup();
|
||||||
data = yield OS.File.read(pathBackup);
|
data = yield OS.File.read(pathBackup);
|
||||||
is(contents, (new TextDecoder()).decode(data), "upgrade backup hasn't changed");
|
is(new TextDecoder().decode(data), contents, "upgrade backup hasn't changed");
|
||||||
|
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
ok(false, "Uncaught error: " + ex + " at " + ex.stack);
|
ok(false, "Uncaught error: " + ex + " at " + ex.stack);
|
||||||
|
@ -85,6 +85,9 @@ function MarkupView(aInspector, aFrame, aControllerWindow) {
|
|||||||
this._boundMutationObserver = this._mutationObserver.bind(this);
|
this._boundMutationObserver = this._mutationObserver.bind(this);
|
||||||
this.walker.on("mutations", this._boundMutationObserver);
|
this.walker.on("mutations", this._boundMutationObserver);
|
||||||
|
|
||||||
|
this._boundOnDisplayChange = this._onDisplayChange.bind(this);
|
||||||
|
this.walker.on("display-change", this._boundOnDisplayChange);
|
||||||
|
|
||||||
this._boundOnNewSelection = this._onNewSelection.bind(this);
|
this._boundOnNewSelection = this._onNewSelection.bind(this);
|
||||||
this._inspector.selection.on("new-node-front", this._boundOnNewSelection);
|
this._inspector.selection.on("new-node-front", this._boundOnNewSelection);
|
||||||
this._onNewSelection();
|
this._onNewSelection();
|
||||||
@ -614,6 +617,19 @@ MarkupView.prototype = {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* React to display-change events from the walker
|
||||||
|
* @param {Array} nodes An array of nodeFronts
|
||||||
|
*/
|
||||||
|
_onDisplayChange: function(nodes) {
|
||||||
|
for (let node of nodes) {
|
||||||
|
let container = this._containers.get(node);
|
||||||
|
if (container) {
|
||||||
|
container.isDisplayed = node.isDisplayed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Given a list of mutations returned by the mutation observer, flash the
|
* Given a list of mutations returned by the mutation observer, flash the
|
||||||
* corresponding containers to attract attention.
|
* corresponding containers to attract attention.
|
||||||
@ -1110,6 +1126,9 @@ MarkupView.prototype = {
|
|||||||
this.walker.off("mutations", this._boundMutationObserver)
|
this.walker.off("mutations", this._boundMutationObserver)
|
||||||
this._boundMutationObserver = null;
|
this._boundMutationObserver = null;
|
||||||
|
|
||||||
|
this.walker.off("display-change", this._boundOnDisplayChange);
|
||||||
|
this._boundOnDisplayChange = null;
|
||||||
|
|
||||||
this._elt.removeEventListener("mousemove", this._onMouseMove, false);
|
this._elt.removeEventListener("mousemove", this._onMouseMove, false);
|
||||||
this._elt.removeEventListener("mouseleave", this._onMouseLeave, false);
|
this._elt.removeEventListener("mouseleave", this._onMouseLeave, false);
|
||||||
this._elt = null;
|
this._elt = null;
|
||||||
@ -1268,6 +1287,9 @@ function MarkupContainer(aMarkupView, aNode, aInspector) {
|
|||||||
|
|
||||||
// Prepare the image preview tooltip data if any
|
// Prepare the image preview tooltip data if any
|
||||||
this._prepareImagePreview();
|
this._prepareImagePreview();
|
||||||
|
|
||||||
|
// Marking the node as shown or hidden
|
||||||
|
this.isDisplayed = this.node.isDisplayed;
|
||||||
}
|
}
|
||||||
|
|
||||||
MarkupContainer.prototype = {
|
MarkupContainer.prototype = {
|
||||||
@ -1342,6 +1364,16 @@ MarkupContainer.prototype = {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the element has displayed or not
|
||||||
|
*/
|
||||||
|
set isDisplayed(isDisplayed) {
|
||||||
|
this.elt.classList.remove("not-displayed");
|
||||||
|
if (!isDisplayed) {
|
||||||
|
this.elt.classList.add("not-displayed");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
copyImageDataUri: function() {
|
copyImageDataUri: function() {
|
||||||
// We need to send again a request to gettooltipData even if one was sent for
|
// We need to send again a request to gettooltipData even if one was sent for
|
||||||
// the tooltip, because we want the full-size image
|
// the tooltip, because we want the full-size image
|
||||||
|
@ -6,6 +6,7 @@ support-files =
|
|||||||
doc_markup_flashing.html
|
doc_markup_flashing.html
|
||||||
doc_markup_mutation.html
|
doc_markup_mutation.html
|
||||||
doc_markup_navigation.html
|
doc_markup_navigation.html
|
||||||
|
doc_markup_not_displayed.html
|
||||||
doc_markup_pagesize_01.html
|
doc_markup_pagesize_01.html
|
||||||
doc_markup_pagesize_02.html
|
doc_markup_pagesize_02.html
|
||||||
doc_markup_search.html
|
doc_markup_search.html
|
||||||
@ -26,6 +27,8 @@ support-files =
|
|||||||
[browser_markupview_mutation_01.js]
|
[browser_markupview_mutation_01.js]
|
||||||
[browser_markupview_mutation_02.js]
|
[browser_markupview_mutation_02.js]
|
||||||
[browser_markupview_navigation.js]
|
[browser_markupview_navigation.js]
|
||||||
|
[browser_markupview_node_not_displayed_01.js]
|
||||||
|
[browser_markupview_node_not_displayed_02.js]
|
||||||
[browser_markupview_pagesize_01.js]
|
[browser_markupview_pagesize_01.js]
|
||||||
[browser_markupview_pagesize_02.js]
|
[browser_markupview_pagesize_02.js]
|
||||||
[browser_markupview_search_01.js]
|
[browser_markupview_search_01.js]
|
||||||
|
@ -0,0 +1,33 @@
|
|||||||
|
/* vim: set ts=2 et sw=2 tw=80: */
|
||||||
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
// Tests that nodes that are not displayed appear differently in the markup-view
|
||||||
|
// when these nodes are imported in the view.
|
||||||
|
|
||||||
|
// Note that nodes inside a display:none parent are obviously not displayed too
|
||||||
|
// but the markup-view uses css inheritance to mark those as hidden instead of
|
||||||
|
// having to visit each and every child of a hidden node. So there's no sense
|
||||||
|
// testing children nodes.
|
||||||
|
|
||||||
|
const TEST_URL = TEST_URL_ROOT + "doc_markup_not_displayed.html";
|
||||||
|
const TEST_DATA = [
|
||||||
|
{selector: "#normal-div", isDisplayed: true},
|
||||||
|
{selector: "head", isDisplayed: false},
|
||||||
|
{selector: "#display-none", isDisplayed: false},
|
||||||
|
{selector: "#hidden-true", isDisplayed: false},
|
||||||
|
{selector: "#visibility-hidden", isDisplayed: true}
|
||||||
|
];
|
||||||
|
|
||||||
|
let test = asyncTest(function*() {
|
||||||
|
let {inspector} = yield addTab(TEST_URL).then(openInspector);
|
||||||
|
|
||||||
|
for (let {selector, isDisplayed} of TEST_DATA) {
|
||||||
|
info("Getting node " + selector);
|
||||||
|
let container = getContainerForRawNode(selector, inspector);
|
||||||
|
is(!container.elt.classList.contains("not-displayed"), isDisplayed,
|
||||||
|
"The container for " + selector + " is marked as displayed " + isDisplayed);
|
||||||
|
}
|
||||||
|
});
|
@ -0,0 +1,132 @@
|
|||||||
|
/* vim: set ts=2 et sw=2 tw=80: */
|
||||||
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
// Tests that nodes are marked as displayed and not-displayed dynamically, when
|
||||||
|
// their display changes
|
||||||
|
|
||||||
|
const TEST_URL = TEST_URL_ROOT + "doc_markup_not_displayed.html";
|
||||||
|
const TEST_DATA = [
|
||||||
|
{
|
||||||
|
desc: "Hiding a node by creating a new stylesheet",
|
||||||
|
selector: "#normal-div",
|
||||||
|
before: true,
|
||||||
|
changeStyle: (doc, node) => {
|
||||||
|
let div = doc.createElement("div");
|
||||||
|
div.id = "new-style";
|
||||||
|
div.innerHTML = "<style>#normal-div {display:none;}</style>";
|
||||||
|
doc.body.appendChild(div);
|
||||||
|
},
|
||||||
|
after: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "Showing a node by deleting an existing stylesheet",
|
||||||
|
selector: "#normal-div",
|
||||||
|
before: false,
|
||||||
|
changeStyle: (doc, node) => {
|
||||||
|
doc.getElementById("new-style").remove();
|
||||||
|
},
|
||||||
|
after: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "Hiding a node by changing its style property",
|
||||||
|
selector: "#display-none",
|
||||||
|
before: false,
|
||||||
|
changeStyle: (doc, node) => {
|
||||||
|
node.style.display = "block";
|
||||||
|
},
|
||||||
|
after: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "Showing a node by removing its hidden attribute",
|
||||||
|
selector: "#hidden-true",
|
||||||
|
before: false,
|
||||||
|
changeStyle: (doc, node) => {
|
||||||
|
node.removeAttribute("hidden");
|
||||||
|
},
|
||||||
|
after: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "Hiding a node by adding a hidden attribute",
|
||||||
|
selector: "#hidden-true",
|
||||||
|
before: true,
|
||||||
|
changeStyle: (doc, node) => {
|
||||||
|
node.setAttribute("hidden", "true");
|
||||||
|
},
|
||||||
|
after: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "Showing a node by changin a stylesheet's rule",
|
||||||
|
selector: "#hidden-via-stylesheet",
|
||||||
|
before: false,
|
||||||
|
changeStyle: (doc, node) => {
|
||||||
|
doc.styleSheets[0].cssRules[0].style.setProperty("display", "inline");
|
||||||
|
},
|
||||||
|
after: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "Hiding a node by adding a new rule to a stylesheet",
|
||||||
|
selector: "#hidden-via-stylesheet",
|
||||||
|
before: true,
|
||||||
|
changeStyle: (doc, node) => {
|
||||||
|
doc.styleSheets[0].insertRule(
|
||||||
|
"#hidden-via-stylesheet {display: none;}", 1);
|
||||||
|
},
|
||||||
|
after: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "Hiding a node by adding a class that matches an existing rule",
|
||||||
|
selector: "#normal-div",
|
||||||
|
before: true,
|
||||||
|
changeStyle: (doc, node) => {
|
||||||
|
doc.styleSheets[0].insertRule(
|
||||||
|
".a-new-class {display: none;}", 2);
|
||||||
|
node.classList.add("a-new-class");
|
||||||
|
},
|
||||||
|
after: false
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
let test = asyncTest(function*() {
|
||||||
|
let {inspector} = yield addTab(TEST_URL).then(openInspector);
|
||||||
|
|
||||||
|
for (let data of TEST_DATA) {
|
||||||
|
info("Running test case: " + data.desc);
|
||||||
|
yield runTestData(inspector, data);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function runTestData(inspector, {selector, before, changeStyle, after}) {
|
||||||
|
let def = promise.defer();
|
||||||
|
|
||||||
|
info("Getting the " + selector + " test node");
|
||||||
|
let container = getContainerForRawNode(selector, inspector);
|
||||||
|
is(!container.elt.classList.contains("not-displayed"), before,
|
||||||
|
"The container is marked as " + (before ? "shown" : "hidden"));
|
||||||
|
|
||||||
|
info("Listening for the display-change event");
|
||||||
|
inspector.markup.walker.once("display-change", nodes => {
|
||||||
|
info("Verifying that the list of changed nodes include our container");
|
||||||
|
|
||||||
|
ok(nodes.length, "The display-change event was received with a nodes");
|
||||||
|
let foundContainer = false;
|
||||||
|
for (let node of nodes) {
|
||||||
|
if (inspector.markup.getContainer(node) === container) {
|
||||||
|
foundContainer = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ok(foundContainer, "Container is part of the list of changed nodes");
|
||||||
|
|
||||||
|
is(!container.elt.classList.contains("not-displayed"), after,
|
||||||
|
"The container is marked as " + (after ? "shown" : "hidden"));
|
||||||
|
def.resolve();
|
||||||
|
});
|
||||||
|
|
||||||
|
info("Making style changes");
|
||||||
|
changeStyle(content.document, getNode(selector));
|
||||||
|
|
||||||
|
return def.promise;
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<style>
|
||||||
|
#hidden-via-stylesheet {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="normal-div"></div>
|
||||||
|
<div id="display-none" style="display:none;"></div>
|
||||||
|
<div id="hidden-true" hidden="true"></div>
|
||||||
|
<div id="visibility-hidden" style="visibility:hidden;"></div>
|
||||||
|
<div id="hidden-via-stylesheet"></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -30,6 +30,12 @@
|
|||||||
color: #f5f7fa; /* Light foreground text */
|
color: #f5f7fa; /* Light foreground text */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* In case a node isn't displayed in the page, we fade the syntax highlighting */
|
||||||
|
.not-displayed .open,
|
||||||
|
.not-displayed .close {
|
||||||
|
opacity: .7;
|
||||||
|
}
|
||||||
|
|
||||||
.tag-line {
|
.tag-line {
|
||||||
padding-left: 2px;
|
padding-left: 2px;
|
||||||
}
|
}
|
||||||
|
@ -12,12 +12,14 @@ public class AnnotationInfo {
|
|||||||
public final boolean isStatic;
|
public final boolean isStatic;
|
||||||
public final boolean isMultithreaded;
|
public final boolean isMultithreaded;
|
||||||
public final boolean noThrow;
|
public final boolean noThrow;
|
||||||
|
public final boolean narrowChars;
|
||||||
|
|
||||||
public AnnotationInfo(String aWrapperName, boolean aIsStatic, boolean aIsMultithreaded,
|
public AnnotationInfo(String aWrapperName, boolean aIsStatic, boolean aIsMultithreaded,
|
||||||
boolean aNoThrow) {
|
boolean aNoThrow, boolean aNarrowChars) {
|
||||||
wrapperName = aWrapperName;
|
wrapperName = aWrapperName;
|
||||||
isStatic = aIsStatic;
|
isStatic = aIsStatic;
|
||||||
isMultithreaded = aIsMultithreaded;
|
isMultithreaded = aIsMultithreaded;
|
||||||
noThrow = aNoThrow;
|
noThrow = aNoThrow;
|
||||||
|
narrowChars = aNarrowChars;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -103,8 +103,8 @@ public class CodeGenerator {
|
|||||||
Class<?> returnType = theMethod.getReturnType();
|
Class<?> returnType = theMethod.getReturnType();
|
||||||
|
|
||||||
// Get the C++ method signature for this method.
|
// Get the C++ method signature for this method.
|
||||||
String implementationSignature = Utils.getCImplementationMethodSignature(parameterTypes, returnType, CMethodName, mCClassName);
|
String implementationSignature = Utils.getCImplementationMethodSignature(parameterTypes, returnType, CMethodName, mCClassName, aMethodTuple.mAnnotationInfo.narrowChars);
|
||||||
String headerSignature = Utils.getCHeaderMethodSignature(parameterTypes, theMethod.getParameterAnnotations(), returnType, CMethodName, mCClassName, shallGenerateStatic);
|
String headerSignature = Utils.getCHeaderMethodSignature(parameterTypes, theMethod.getParameterAnnotations(), returnType, CMethodName, mCClassName, shallGenerateStatic, aMethodTuple.mAnnotationInfo.narrowChars);
|
||||||
|
|
||||||
// Add the header signature to the header file.
|
// Add the header signature to the header file.
|
||||||
writeSignatureToHeader(headerSignature);
|
writeSignatureToHeader(headerSignature);
|
||||||
@ -113,10 +113,11 @@ public class CodeGenerator {
|
|||||||
writeMethodBody(implementationSignature, CMethodName, theMethod, mClassToWrap,
|
writeMethodBody(implementationSignature, CMethodName, theMethod, mClassToWrap,
|
||||||
aMethodTuple.mAnnotationInfo.isStatic,
|
aMethodTuple.mAnnotationInfo.isStatic,
|
||||||
aMethodTuple.mAnnotationInfo.isMultithreaded,
|
aMethodTuple.mAnnotationInfo.isMultithreaded,
|
||||||
aMethodTuple.mAnnotationInfo.noThrow);
|
aMethodTuple.mAnnotationInfo.noThrow,
|
||||||
|
aMethodTuple.mAnnotationInfo.narrowChars);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateGetterOrSetterBody(Class<?> aFieldType, String aFieldName, boolean aIsFieldStatic, boolean isSetter) {
|
private void generateGetterOrSetterBody(Class<?> aFieldType, String aFieldName, boolean aIsFieldStatic, boolean isSetter, boolean aNarrowChars) {
|
||||||
StringBuilder argumentContent = null;
|
StringBuilder argumentContent = null;
|
||||||
|
|
||||||
if (isSetter) {
|
if (isSetter) {
|
||||||
@ -133,7 +134,7 @@ public class CodeGenerator {
|
|||||||
wrapperMethodBodies.append("return ");
|
wrapperMethodBodies.append("return ");
|
||||||
|
|
||||||
if (isObjectReturningMethod) {
|
if (isObjectReturningMethod) {
|
||||||
wrapperMethodBodies.append("static_cast<").append(Utils.getCReturnType(aFieldType)).append(">(");
|
wrapperMethodBodies.append("static_cast<").append(Utils.getCReturnType(aFieldType, aNarrowChars)).append(">(");
|
||||||
}
|
}
|
||||||
|
|
||||||
wrapperMethodBodies.append("env->Get");
|
wrapperMethodBodies.append("env->Get");
|
||||||
@ -184,14 +185,14 @@ public class CodeGenerator {
|
|||||||
boolean shallGenerateStatic = isFieldStatic || aFieldTuple.mAnnotationInfo.isStatic;
|
boolean shallGenerateStatic = isFieldStatic || aFieldTuple.mAnnotationInfo.isStatic;
|
||||||
|
|
||||||
String getterName = "get" + CFieldName;
|
String getterName = "get" + CFieldName;
|
||||||
String getterSignature = Utils.getCImplementationMethodSignature(EMPTY_CLASS_ARRAY, fieldType, getterName, mCClassName);
|
String getterSignature = Utils.getCImplementationMethodSignature(EMPTY_CLASS_ARRAY, fieldType, getterName, mCClassName, aFieldTuple.mAnnotationInfo.narrowChars);
|
||||||
String getterHeaderSignature = Utils.getCHeaderMethodSignature(EMPTY_CLASS_ARRAY, GETTER_ARGUMENT_ANNOTATIONS, fieldType, getterName, mCClassName, shallGenerateStatic);
|
String getterHeaderSignature = Utils.getCHeaderMethodSignature(EMPTY_CLASS_ARRAY, GETTER_ARGUMENT_ANNOTATIONS, fieldType, getterName, mCClassName, shallGenerateStatic, aFieldTuple.mAnnotationInfo.narrowChars);
|
||||||
|
|
||||||
writeSignatureToHeader(getterHeaderSignature);
|
writeSignatureToHeader(getterHeaderSignature);
|
||||||
|
|
||||||
writeFunctionStartupBoilerPlate(getterSignature, fieldType, isFieldStatic, true);
|
writeFunctionStartupBoilerPlate(getterSignature, fieldType, isFieldStatic, true);
|
||||||
|
|
||||||
generateGetterOrSetterBody(fieldType, CFieldName, isFieldStatic, false);
|
generateGetterOrSetterBody(fieldType, CFieldName, isFieldStatic, false, aFieldTuple.mAnnotationInfo.narrowChars);
|
||||||
|
|
||||||
// If field not final, also generate a setter function.
|
// If field not final, also generate a setter function.
|
||||||
if (!isFieldFinal) {
|
if (!isFieldFinal) {
|
||||||
@ -199,14 +200,14 @@ public class CodeGenerator {
|
|||||||
|
|
||||||
Class<?>[] setterArguments = new Class<?>[]{fieldType};
|
Class<?>[] setterArguments = new Class<?>[]{fieldType};
|
||||||
|
|
||||||
String setterSignature = Utils.getCImplementationMethodSignature(setterArguments, Void.class, setterName, mCClassName);
|
String setterSignature = Utils.getCImplementationMethodSignature(setterArguments, Void.class, setterName, mCClassName, aFieldTuple.mAnnotationInfo.narrowChars);
|
||||||
String setterHeaderSignature = Utils.getCHeaderMethodSignature(setterArguments, SETTER_ARGUMENT_ANNOTATIONS, Void.class, setterName, mCClassName, shallGenerateStatic);
|
String setterHeaderSignature = Utils.getCHeaderMethodSignature(setterArguments, SETTER_ARGUMENT_ANNOTATIONS, Void.class, setterName, mCClassName, shallGenerateStatic, aFieldTuple.mAnnotationInfo.narrowChars);
|
||||||
|
|
||||||
writeSignatureToHeader(setterHeaderSignature);
|
writeSignatureToHeader(setterHeaderSignature);
|
||||||
|
|
||||||
writeFunctionStartupBoilerPlate(setterSignature, Void.class, isFieldStatic, true);
|
writeFunctionStartupBoilerPlate(setterSignature, Void.class, isFieldStatic, true);
|
||||||
|
|
||||||
generateGetterOrSetterBody(fieldType, CFieldName, isFieldStatic, true);
|
generateGetterOrSetterBody(fieldType, CFieldName, isFieldStatic, true, aFieldTuple.mAnnotationInfo.narrowChars);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -217,8 +218,8 @@ public class CodeGenerator {
|
|||||||
|
|
||||||
generateMemberCommon(theCtor, mCClassName, mClassToWrap);
|
generateMemberCommon(theCtor, mCClassName, mClassToWrap);
|
||||||
|
|
||||||
String implementationSignature = Utils.getCImplementationMethodSignature(theCtor.getParameterTypes(), Void.class, CMethodName, mCClassName);
|
String implementationSignature = Utils.getCImplementationMethodSignature(theCtor.getParameterTypes(), Void.class, CMethodName, mCClassName, aCtorTuple.mAnnotationInfo.narrowChars);
|
||||||
String headerSignature = Utils.getCHeaderMethodSignature(theCtor.getParameterTypes(), theCtor.getParameterAnnotations(), Void.class, CMethodName, mCClassName, false);
|
String headerSignature = Utils.getCHeaderMethodSignature(theCtor.getParameterTypes(), theCtor.getParameterAnnotations(), Void.class, CMethodName, mCClassName, false, aCtorTuple.mAnnotationInfo.narrowChars);
|
||||||
|
|
||||||
// Slice off the "void " from the start of the constructor declaration.
|
// Slice off the "void " from the start of the constructor declaration.
|
||||||
headerSignature = headerSignature.substring(5);
|
headerSignature = headerSignature.substring(5);
|
||||||
@ -426,7 +427,7 @@ public class CodeGenerator {
|
|||||||
*/
|
*/
|
||||||
private void writeMethodBody(String methodSignature, String aCMethodName, Method aMethod,
|
private void writeMethodBody(String methodSignature, String aCMethodName, Method aMethod,
|
||||||
Class<?> aClass, boolean aIsStaticBridgeMethod, boolean aIsMultithreaded,
|
Class<?> aClass, boolean aIsStaticBridgeMethod, boolean aIsMultithreaded,
|
||||||
boolean aNoThrow) {
|
boolean aNoThrow, boolean aNarrowChars) {
|
||||||
Class<?>[] argumentTypes = aMethod.getParameterTypes();
|
Class<?>[] argumentTypes = aMethod.getParameterTypes();
|
||||||
Class<?> returnType = aMethod.getReturnType();
|
Class<?> returnType = aMethod.getReturnType();
|
||||||
|
|
||||||
@ -455,7 +456,7 @@ public class CodeGenerator {
|
|||||||
if (isObjectReturningMethod) {
|
if (isObjectReturningMethod) {
|
||||||
wrapperMethodBodies.append("jobject");
|
wrapperMethodBodies.append("jobject");
|
||||||
} else {
|
} else {
|
||||||
wrapperMethodBodies.append(Utils.getCReturnType(returnType));
|
wrapperMethodBodies.append(Utils.getCReturnType(returnType, aNarrowChars));
|
||||||
}
|
}
|
||||||
wrapperMethodBodies.append(" temp = ");
|
wrapperMethodBodies.append(" temp = ");
|
||||||
}
|
}
|
||||||
@ -494,8 +495,8 @@ public class CodeGenerator {
|
|||||||
// value.
|
// value.
|
||||||
if (isObjectReturningMethod) {
|
if (isObjectReturningMethod) {
|
||||||
wrapperMethodBodies.append(" ")
|
wrapperMethodBodies.append(" ")
|
||||||
.append(Utils.getCReturnType(returnType))
|
.append(Utils.getCReturnType(returnType, aNarrowChars))
|
||||||
.append(" ret = static_cast<").append(Utils.getCReturnType(returnType)).append(">(env->PopLocalFrame(temp));\n" +
|
.append(" ret = static_cast<").append(Utils.getCReturnType(returnType, aNarrowChars)).append(">(env->PopLocalFrame(temp));\n" +
|
||||||
" return ret;\n");
|
" return ret;\n");
|
||||||
} else if (!returnType.getCanonicalName().equals("void")) {
|
} else if (!returnType.getCanonicalName().equals("void")) {
|
||||||
// If we're a primitive-returning function, just return the directly-obtained primative
|
// If we're a primitive-returning function, just return the directly-obtained primative
|
||||||
|
@ -76,6 +76,7 @@ public class GeneratableElementIterator implements Iterator<AnnotatableEntity> {
|
|||||||
boolean isStaticStub = false;
|
boolean isStaticStub = false;
|
||||||
boolean isMultithreadedStub = false;
|
boolean isMultithreadedStub = false;
|
||||||
boolean noThrow = false;
|
boolean noThrow = false;
|
||||||
|
boolean narrowChars = false;
|
||||||
try {
|
try {
|
||||||
// Determine the explicitly-given name of the stub to generate, if any.
|
// Determine the explicitly-given name of the stub to generate, if any.
|
||||||
final Method stubNameMethod = annotationType.getDeclaredMethod("stubName");
|
final Method stubNameMethod = annotationType.getDeclaredMethod("stubName");
|
||||||
@ -97,6 +98,11 @@ public class GeneratableElementIterator implements Iterator<AnnotatableEntity> {
|
|||||||
noThrowMethod.setAccessible(true);
|
noThrowMethod.setAccessible(true);
|
||||||
noThrow = (Boolean) noThrowMethod.invoke(annotation);
|
noThrow = (Boolean) noThrowMethod.invoke(annotation);
|
||||||
|
|
||||||
|
// Determine if strings should be wide or narrow
|
||||||
|
final Method narrowCharsMethod = annotationType.getDeclaredMethod("narrowChars");
|
||||||
|
narrowCharsMethod.setAccessible(true);
|
||||||
|
narrowChars = (Boolean) narrowCharsMethod.invoke(annotation);
|
||||||
|
|
||||||
} catch (NoSuchMethodException e) {
|
} catch (NoSuchMethodException e) {
|
||||||
System.err.println("Unable to find expected field on WrapElementForJNI annotation. Did the signature change?");
|
System.err.println("Unable to find expected field on WrapElementForJNI annotation. Did the signature change?");
|
||||||
e.printStackTrace(System.err);
|
e.printStackTrace(System.err);
|
||||||
@ -118,7 +124,7 @@ public class GeneratableElementIterator implements Iterator<AnnotatableEntity> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
AnnotationInfo annotationInfo = new AnnotationInfo(
|
AnnotationInfo annotationInfo = new AnnotationInfo(
|
||||||
stubName, isStaticStub, isMultithreadedStub, noThrow);
|
stubName, isStaticStub, isMultithreadedStub, noThrow, narrowChars);
|
||||||
mNextReturnValue = new AnnotatableEntity(candidateElement, annotationInfo);
|
mNextReturnValue = new AnnotatableEntity(candidateElement, annotationInfo);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -128,7 +134,7 @@ public class GeneratableElementIterator implements Iterator<AnnotatableEntity> {
|
|||||||
// thanks to the "Generate everything" annotation.
|
// thanks to the "Generate everything" annotation.
|
||||||
if (mIterateEveryEntry) {
|
if (mIterateEveryEntry) {
|
||||||
AnnotationInfo annotationInfo = new AnnotationInfo(
|
AnnotationInfo annotationInfo = new AnnotationInfo(
|
||||||
candidateElement.getName(), false, false, false);
|
candidateElement.getName(), false, false, false, false);
|
||||||
mNextReturnValue = new AnnotatableEntity(candidateElement, annotationInfo);
|
mNextReturnValue = new AnnotatableEntity(candidateElement, annotationInfo);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -137,7 +137,7 @@ public class Utils {
|
|||||||
* @param type Class to determine the corresponding JNI type for.
|
* @param type Class to determine the corresponding JNI type for.
|
||||||
* @return true if the type an object type, false otherwise.
|
* @return true if the type an object type, false otherwise.
|
||||||
*/
|
*/
|
||||||
public static String getCParameterType(Class<?> type) {
|
public static String getCParameterType(Class<?> type, boolean aNarrowChars) {
|
||||||
String name = type.getCanonicalName();
|
String name = type.getCanonicalName();
|
||||||
if (sBasicCTypes.containsKey(name)) {
|
if (sBasicCTypes.containsKey(name)) {
|
||||||
return sBasicCTypes.get(name);
|
return sBasicCTypes.get(name);
|
||||||
@ -161,6 +161,9 @@ public class Utils {
|
|||||||
|
|
||||||
// Check for CharSequences (Strings and things that are string-like)
|
// Check for CharSequences (Strings and things that are string-like)
|
||||||
if (isCharSequence(type)) {
|
if (isCharSequence(type)) {
|
||||||
|
if (aNarrowChars) {
|
||||||
|
return "const nsACString&";
|
||||||
|
}
|
||||||
return "const nsAString&";
|
return "const nsAString&";
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -181,12 +184,12 @@ public class Utils {
|
|||||||
* @param type The Java return type.
|
* @param type The Java return type.
|
||||||
* @return A string representation of the C++ return type.
|
* @return A string representation of the C++ return type.
|
||||||
*/
|
*/
|
||||||
public static String getCReturnType(Class<?> type) {
|
public static String getCReturnType(Class<?> type, boolean aNarrowChars) {
|
||||||
if (type.getCanonicalName().equals("java.lang.Void")) {
|
if (type.getCanonicalName().equals("java.lang.Void")) {
|
||||||
return "void";
|
return "void";
|
||||||
}
|
}
|
||||||
String cParameterType = getCParameterType(type);
|
String cParameterType = getCParameterType(type, aNarrowChars);
|
||||||
if (cParameterType.equals("const nsAString&")) {
|
if (cParameterType.equals("const nsAString&") || cParameterType.equals("const nsACString&")) {
|
||||||
return "jstring";
|
return "jstring";
|
||||||
} else {
|
} else {
|
||||||
return cParameterType;
|
return cParameterType;
|
||||||
@ -381,10 +384,10 @@ public class Utils {
|
|||||||
* @param aCClassName Name of the C++ class into which the method is declared.
|
* @param aCClassName Name of the C++ class into which the method is declared.
|
||||||
* @return The C++ method implementation signature for the method described.
|
* @return The C++ method implementation signature for the method described.
|
||||||
*/
|
*/
|
||||||
public static String getCImplementationMethodSignature(Class<?>[] aArgumentTypes, Class<?> aReturnType, String aCMethodName, String aCClassName) {
|
public static String getCImplementationMethodSignature(Class<?>[] aArgumentTypes, Class<?> aReturnType, String aCMethodName, String aCClassName, boolean aNarrowChars) {
|
||||||
StringBuilder retBuffer = new StringBuilder();
|
StringBuilder retBuffer = new StringBuilder();
|
||||||
|
|
||||||
retBuffer.append(getCReturnType(aReturnType));
|
retBuffer.append(getCReturnType(aReturnType, aNarrowChars));
|
||||||
retBuffer.append(' ');
|
retBuffer.append(' ');
|
||||||
retBuffer.append(aCClassName);
|
retBuffer.append(aCClassName);
|
||||||
retBuffer.append("::");
|
retBuffer.append("::");
|
||||||
@ -393,7 +396,7 @@ public class Utils {
|
|||||||
|
|
||||||
// Write argument types...
|
// Write argument types...
|
||||||
for (int aT = 0; aT < aArgumentTypes.length; aT++) {
|
for (int aT = 0; aT < aArgumentTypes.length; aT++) {
|
||||||
retBuffer.append(getCParameterType(aArgumentTypes[aT]));
|
retBuffer.append(getCParameterType(aArgumentTypes[aT], aNarrowChars));
|
||||||
retBuffer.append(" a");
|
retBuffer.append(" a");
|
||||||
// We, imaginatively, call our arguments a1, a2, a3...
|
// We, imaginatively, call our arguments a1, a2, a3...
|
||||||
// The only way to preserve the names from Java would be to parse the
|
// The only way to preserve the names from Java would be to parse the
|
||||||
@ -420,7 +423,7 @@ public class Utils {
|
|||||||
* @param aIsStaticStub true if the generated C++ method should be static, false otherwise.
|
* @param aIsStaticStub true if the generated C++ method should be static, false otherwise.
|
||||||
* @return The generated C++ header method signature for the method described.
|
* @return The generated C++ header method signature for the method described.
|
||||||
*/
|
*/
|
||||||
public static String getCHeaderMethodSignature(Class<?>[] aArgumentTypes, Annotation[][] aArgumentAnnotations, Class<?> aReturnType, String aCMethodName, String aCClassName, boolean aIsStaticStub) {
|
public static String getCHeaderMethodSignature(Class<?>[] aArgumentTypes, Annotation[][] aArgumentAnnotations, Class<?> aReturnType, String aCMethodName, String aCClassName, boolean aIsStaticStub, boolean aNarrowChars) {
|
||||||
StringBuilder retBuffer = new StringBuilder();
|
StringBuilder retBuffer = new StringBuilder();
|
||||||
|
|
||||||
// Add the static keyword, if applicable.
|
// Add the static keyword, if applicable.
|
||||||
@ -429,14 +432,14 @@ public class Utils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Write return type..
|
// Write return type..
|
||||||
retBuffer.append(getCReturnType(aReturnType));
|
retBuffer.append(getCReturnType(aReturnType, aNarrowChars));
|
||||||
retBuffer.append(' ');
|
retBuffer.append(' ');
|
||||||
retBuffer.append(aCMethodName);
|
retBuffer.append(aCMethodName);
|
||||||
retBuffer.append('(');
|
retBuffer.append('(');
|
||||||
|
|
||||||
// Write argument types...
|
// Write argument types...
|
||||||
for (int aT = 0; aT < aArgumentTypes.length; aT++) {
|
for (int aT = 0; aT < aArgumentTypes.length; aT++) {
|
||||||
retBuffer.append(getCParameterType(aArgumentTypes[aT]));
|
retBuffer.append(getCParameterType(aArgumentTypes[aT], aNarrowChars));
|
||||||
retBuffer.append(" a");
|
retBuffer.append(" a");
|
||||||
// We, imaginatively, call our arguments a1, a2, a3...
|
// We, imaginatively, call our arguments a1, a2, a3...
|
||||||
// The only way to preserve the names from Java would be to parse the
|
// The only way to preserve the names from Java would be to parse the
|
||||||
|
@ -2536,7 +2536,9 @@ this.DOMApplicationRegistry = {
|
|||||||
yield this._saveApps();
|
yield this._saveApps();
|
||||||
|
|
||||||
this.broadcastMessage("Webapps:AddApp", { id: id, app: appObject });
|
this.broadcastMessage("Webapps:AddApp", { id: id, app: appObject });
|
||||||
if (aData.isPackage && aData.autoInstall) {
|
|
||||||
|
// The presence of a requestID means that we have a page to update.
|
||||||
|
if (aData.isPackage && aData.apkInstall && !aData.requestID) {
|
||||||
// Skip directly to onInstallSuccessAck, since there isn't
|
// Skip directly to onInstallSuccessAck, since there isn't
|
||||||
// a WebappsRegistry to receive Webapps:Install:Return:OK and respond
|
// a WebappsRegistry to receive Webapps:Install:Return:OK and respond
|
||||||
// Webapps:Install:Return:Ack when an app is being auto-installed.
|
// Webapps:Install:Return:Ack when an app is being auto-installed.
|
||||||
|
@ -40,26 +40,6 @@ function getIntPref(prefName, def) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function exposeAll(obj) {
|
|
||||||
// Filter for Objects and Arrays.
|
|
||||||
if (typeof obj !== "object" || !obj)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Recursively expose our children.
|
|
||||||
Object.keys(obj).forEach(function(key) {
|
|
||||||
exposeAll(obj[key]);
|
|
||||||
});
|
|
||||||
|
|
||||||
// If we're not an Array, generate an __exposedProps__ object for ourselves.
|
|
||||||
if (obj instanceof Array)
|
|
||||||
return;
|
|
||||||
var exposed = {};
|
|
||||||
Object.keys(obj).forEach(function(key) {
|
|
||||||
exposed[key] = 'rw';
|
|
||||||
});
|
|
||||||
obj.__exposedProps__ = exposed;
|
|
||||||
}
|
|
||||||
|
|
||||||
function defineAndExpose(obj, name, value) {
|
function defineAndExpose(obj, name, value) {
|
||||||
obj[name] = value;
|
obj[name] = value;
|
||||||
if (!('__exposedProps__' in obj))
|
if (!('__exposedProps__' in obj))
|
||||||
@ -499,7 +479,7 @@ BrowserElementParent.prototype = {
|
|||||||
// This will have to change if we ever want to send a CustomEvent with null
|
// This will have to change if we ever want to send a CustomEvent with null
|
||||||
// detail. For now, it's OK.
|
// detail. For now, it's OK.
|
||||||
if (detail !== undefined && detail !== null) {
|
if (detail !== undefined && detail !== null) {
|
||||||
exposeAll(detail);
|
detail = Cu.cloneInto(detail, this._window);
|
||||||
return new this._window.CustomEvent('mozbrowser' + evtName,
|
return new this._window.CustomEvent('mozbrowser' + evtName,
|
||||||
{ bubbles: true,
|
{ bubbles: true,
|
||||||
cancelable: cancelable,
|
cancelable: cancelable,
|
||||||
|
@ -47,11 +47,9 @@ class ProfileEntry
|
|||||||
int32_t volatile lineOrPc;
|
int32_t volatile lineOrPc;
|
||||||
|
|
||||||
// General purpose storage describing this frame.
|
// General purpose storage describing this frame.
|
||||||
uint32_t volatile flags;
|
uint32_t volatile flags_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ProfileEntry(void) : flags(0) {}
|
|
||||||
|
|
||||||
// These traits are bit masks. Make sure they're powers of 2.
|
// These traits are bit masks. Make sure they're powers of 2.
|
||||||
enum Flags {
|
enum Flags {
|
||||||
// Indicate whether a profile entry represents a CPP frame. If not set,
|
// Indicate whether a profile entry represents a CPP frame. If not set,
|
||||||
@ -61,7 +59,10 @@ class ProfileEntry
|
|||||||
|
|
||||||
// Indicate that copying the frame label is not necessary when taking a
|
// Indicate that copying the frame label is not necessary when taking a
|
||||||
// sample of the pseudostack.
|
// sample of the pseudostack.
|
||||||
FRAME_LABEL_COPY = 0x02
|
FRAME_LABEL_COPY = 0x02,
|
||||||
|
|
||||||
|
// Mask for removing all flags except the category information.
|
||||||
|
CATEGORY_MASK = ~IS_CPP_ENTRY & ~FRAME_LABEL_COPY
|
||||||
};
|
};
|
||||||
|
|
||||||
MOZ_BEGIN_NESTED_ENUM_CLASS(Category, uint32_t)
|
MOZ_BEGIN_NESTED_ENUM_CLASS(Category, uint32_t)
|
||||||
@ -93,26 +94,33 @@ class ProfileEntry
|
|||||||
const char *label() const volatile { return string; }
|
const char *label() const volatile { return string; }
|
||||||
|
|
||||||
void setJsFrame(JSScript *aScript, jsbytecode *aPc) volatile {
|
void setJsFrame(JSScript *aScript, jsbytecode *aPc) volatile {
|
||||||
flags &= ~IS_CPP_ENTRY;
|
flags_ = 0;
|
||||||
spOrScript = aScript;
|
spOrScript = aScript;
|
||||||
setPC(aPc);
|
setPC(aPc);
|
||||||
}
|
}
|
||||||
void setCppFrame(void *aSp, uint32_t aLine) volatile {
|
void setCppFrame(void *aSp, uint32_t aLine) volatile {
|
||||||
flags |= IS_CPP_ENTRY;
|
flags_ = IS_CPP_ENTRY;
|
||||||
spOrScript = aSp;
|
spOrScript = aSp;
|
||||||
lineOrPc = static_cast<int32_t>(aLine);
|
lineOrPc = static_cast<int32_t>(aLine);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setFlag(uint32_t flag) volatile {
|
void setFlag(uint32_t flag) volatile {
|
||||||
MOZ_ASSERT(flag != IS_CPP_ENTRY);
|
MOZ_ASSERT(flag != IS_CPP_ENTRY);
|
||||||
flags |= flag;
|
flags_ |= flag;
|
||||||
}
|
}
|
||||||
void unsetFlag(uint32_t flag) volatile {
|
void unsetFlag(uint32_t flag) volatile {
|
||||||
MOZ_ASSERT(flag != IS_CPP_ENTRY);
|
MOZ_ASSERT(flag != IS_CPP_ENTRY);
|
||||||
flags &= ~flag;
|
flags_ &= ~flag;
|
||||||
}
|
}
|
||||||
bool hasFlag(uint32_t flag) const volatile {
|
bool hasFlag(uint32_t flag) const volatile {
|
||||||
return bool(flags & uint32_t(flag));
|
return bool(flags_ & flag);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t flags() const volatile {
|
||||||
|
return flags_;
|
||||||
|
}
|
||||||
|
uint32_t category() const volatile {
|
||||||
|
return flags_ & CATEGORY_MASK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *stackAddress() const volatile {
|
void *stackAddress() const volatile {
|
||||||
@ -140,7 +148,7 @@ class ProfileEntry
|
|||||||
static size_t offsetOfLabel() { return offsetof(ProfileEntry, string); }
|
static size_t offsetOfLabel() { return offsetof(ProfileEntry, string); }
|
||||||
static size_t offsetOfSpOrScript() { return offsetof(ProfileEntry, spOrScript); }
|
static size_t offsetOfSpOrScript() { return offsetof(ProfileEntry, spOrScript); }
|
||||||
static size_t offsetOfLineOrPc() { return offsetof(ProfileEntry, lineOrPc); }
|
static size_t offsetOfLineOrPc() { return offsetof(ProfileEntry, lineOrPc); }
|
||||||
static size_t offsetOfFlags() { return offsetof(ProfileEntry, flags); }
|
static size_t offsetOfFlags() { return offsetof(ProfileEntry, flags_); }
|
||||||
};
|
};
|
||||||
|
|
||||||
JS_FRIEND_API(void)
|
JS_FRIEND_API(void)
|
||||||
|
@ -215,6 +215,7 @@ SPSProfiler::enterNative(const char *string, void *sp)
|
|||||||
if (current < max_) {
|
if (current < max_) {
|
||||||
stack[current].setLabel(string);
|
stack[current].setLabel(string);
|
||||||
stack[current].setCppFrame(sp, 0);
|
stack[current].setCppFrame(sp, 0);
|
||||||
|
JS_ASSERT(stack[current].flags() == js::ProfileEntry::IS_CPP_ENTRY);
|
||||||
}
|
}
|
||||||
*size = current + 1;
|
*size = current + 1;
|
||||||
}
|
}
|
||||||
@ -235,10 +236,14 @@ SPSProfiler::push(const char *string, void *sp, JSScript *script, jsbytecode *pc
|
|||||||
volatile ProfileEntry &entry = stack[current];
|
volatile ProfileEntry &entry = stack[current];
|
||||||
entry.setLabel(string);
|
entry.setLabel(string);
|
||||||
|
|
||||||
if (sp != nullptr)
|
if (sp != nullptr) {
|
||||||
entry.setCppFrame(sp, 0);
|
entry.setCppFrame(sp, 0);
|
||||||
else
|
JS_ASSERT(entry.flags() == js::ProfileEntry::IS_CPP_ENTRY);
|
||||||
|
}
|
||||||
|
else {
|
||||||
entry.setJsFrame(script, pc);
|
entry.setJsFrame(script, pc);
|
||||||
|
JS_ASSERT(entry.flags() == 0);
|
||||||
|
}
|
||||||
|
|
||||||
// Track if mLabel needs a copy.
|
// Track if mLabel needs a copy.
|
||||||
if (copy)
|
if (copy)
|
||||||
|
@ -16,6 +16,8 @@ import java.io.InputStreamReader;
|
|||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.io.StringWriter;
|
import java.io.StringWriter;
|
||||||
|
import java.net.URLConnection;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
import java.net.Proxy;
|
import java.net.Proxy;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
@ -2720,4 +2722,31 @@ public class GeckoAppShell
|
|||||||
toast.show();
|
toast.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@WrapElementForJNI(allowMultithread = true)
|
||||||
|
static InputStream createInputStream(URLConnection connection) throws IOException {
|
||||||
|
return connection.getInputStream();
|
||||||
|
}
|
||||||
|
|
||||||
|
@WrapElementForJNI(allowMultithread = true, narrowChars = true)
|
||||||
|
static URLConnection getConnection(String url) throws MalformedURLException, IOException {
|
||||||
|
String spec;
|
||||||
|
if (url.startsWith("android://")) {
|
||||||
|
spec = url.substring(10);
|
||||||
|
} else {
|
||||||
|
spec = url.substring(8);
|
||||||
|
}
|
||||||
|
|
||||||
|
// if the colon got stripped, put it back
|
||||||
|
int colon = spec.indexOf(':');
|
||||||
|
if (colon == -1 || colon > spec.indexOf('/')) {
|
||||||
|
spec = spec.replaceFirst("/", ":/");
|
||||||
|
}
|
||||||
|
return new URL(spec).openConnection();
|
||||||
|
}
|
||||||
|
|
||||||
|
@WrapElementForJNI(allowMultithread = true, narrowChars = true)
|
||||||
|
static String connectionGetMimeType(URLConnection connection) {
|
||||||
|
return connection.getContentType();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -64,6 +64,10 @@ public interface TelemetryContract {
|
|||||||
// Sharing content.
|
// Sharing content.
|
||||||
SHARE("share.1"),
|
SHARE("share.1"),
|
||||||
|
|
||||||
|
// Undoing a user action.
|
||||||
|
// Note: Only used in JavaScript for now, but here for completeness.
|
||||||
|
UNDO("undo.1"),
|
||||||
|
|
||||||
// Unpinning an item.
|
// Unpinning an item.
|
||||||
UNPIN("unpin.1"),
|
UNPIN("unpin.1"),
|
||||||
|
|
||||||
@ -137,6 +141,10 @@ public interface TelemetryContract {
|
|||||||
// Action triggered from a suggestion provided to the user.
|
// Action triggered from a suggestion provided to the user.
|
||||||
SUGGESTION("suggestion"),
|
SUGGESTION("suggestion"),
|
||||||
|
|
||||||
|
// Action triggered from a SuperToast.
|
||||||
|
// Note: Only used in JavaScript for now, but here for completeness.
|
||||||
|
TOAST("toast"),
|
||||||
|
|
||||||
// VALUES BELOW THIS LINE ARE EXCLUSIVE TO TESTING.
|
// VALUES BELOW THIS LINE ARE EXCLUSIVE TO TESTING.
|
||||||
_TEST1("_test_method_1"),
|
_TEST1("_test_method_1"),
|
||||||
_TEST2("_test_method_2"),
|
_TEST2("_test_method_2"),
|
||||||
|
@ -546,13 +546,17 @@ if '-march=armv7' in CONFIG['OS_CFLAGS']:
|
|||||||
else:
|
else:
|
||||||
DEFINES['MOZ_MIN_CPU_VERSION'] = 5
|
DEFINES['MOZ_MIN_CPU_VERSION'] = 5
|
||||||
|
|
||||||
|
generated_recursive_make_targets = ['.aapt.deps', '.locales.deps'] # Captures dependencies on Android manifest and all resources.
|
||||||
|
|
||||||
generated = add_android_eclipse_library_project('FennecResourcesGenerated')
|
generated = add_android_eclipse_library_project('FennecResourcesGenerated')
|
||||||
generated.package_name = 'org.mozilla.fennec.resources.generated'
|
generated.package_name = 'org.mozilla.fennec.resources.generated'
|
||||||
generated.res = OBJDIR + '/res'
|
generated.res = OBJDIR + '/res'
|
||||||
|
generated.recursive_make_targets += generated_recursive_make_targets
|
||||||
|
|
||||||
branding = add_android_eclipse_library_project('FennecResourcesBranding')
|
branding = add_android_eclipse_library_project('FennecResourcesBranding')
|
||||||
branding.package_name = 'org.mozilla.fennec.resources.branding'
|
branding.package_name = 'org.mozilla.fennec.resources.branding'
|
||||||
branding.res = TOPSRCDIR + '/' + CONFIG['MOZ_BRANDING_DIRECTORY'] + '/res'
|
branding.res = TOPSRCDIR + '/' + CONFIG['MOZ_BRANDING_DIRECTORY'] + '/res'
|
||||||
|
branding.recursive_make_targets += generated_recursive_make_targets
|
||||||
|
|
||||||
main = add_android_eclipse_project('Fennec', OBJDIR + '/AndroidManifest.xml')
|
main = add_android_eclipse_project('Fennec', OBJDIR + '/AndroidManifest.xml')
|
||||||
main.package_name = 'org.mozilla.gecko'
|
main.package_name = 'org.mozilla.gecko'
|
||||||
@ -565,7 +569,7 @@ main.filtered_resources += [
|
|||||||
'1.0-projectRelativePath-matches-false-false-*org/mozilla/gecko/tests/**',
|
'1.0-projectRelativePath-matches-false-false-*org/mozilla/gecko/tests/**',
|
||||||
]
|
]
|
||||||
|
|
||||||
main.recursive_make_targets += ['.aapt.deps'] # Captures dependencies on Android manifest and all resources.
|
main.recursive_make_targets += generated_recursive_make_targets
|
||||||
main.recursive_make_targets += [OBJDIR + '/generated/' + f for f in mgjar.generated_sources]
|
main.recursive_make_targets += [OBJDIR + '/generated/' + f for f in mgjar.generated_sources]
|
||||||
main.recursive_make_targets += [OBJDIR + '/generated/' + f for f in gbjar.generated_sources]
|
main.recursive_make_targets += [OBJDIR + '/generated/' + f for f in gbjar.generated_sources]
|
||||||
|
|
||||||
@ -591,6 +595,7 @@ resources = add_android_eclipse_library_project('FennecResources')
|
|||||||
resources.package_name = 'org.mozilla.fennec.resources'
|
resources.package_name = 'org.mozilla.fennec.resources'
|
||||||
resources.res = SRCDIR + '/resources'
|
resources.res = SRCDIR + '/resources'
|
||||||
resources.included_projects += ['../' + generated.name, '../' + branding.name]
|
resources.included_projects += ['../' + generated.name, '../' + branding.name]
|
||||||
|
resources.recursive_make_targets += generated_recursive_make_targets
|
||||||
|
|
||||||
main.included_projects += ['../' + resources.name]
|
main.included_projects += ['../' + resources.name]
|
||||||
main.referenced_projects += [resources.name]
|
main.referenced_projects += [resources.name]
|
||||||
|
@ -44,4 +44,6 @@ public @interface WrapElementForJNI {
|
|||||||
* Any exception must be handled or cleared by the code calling the stub.
|
* Any exception must be handled or cleared by the code calling the stub.
|
||||||
*/
|
*/
|
||||||
boolean noThrow() default false;
|
boolean noThrow() default false;
|
||||||
|
|
||||||
|
boolean narrowChars() default false;
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ Cu.import("resource://gre/modules/SimpleServiceDiscovery.jsm");
|
|||||||
function discovery_observer(subject, topic, data) {
|
function discovery_observer(subject, topic, data) {
|
||||||
do_print("Observer: " + data);
|
do_print("Observer: " + data);
|
||||||
|
|
||||||
let service = SimpleServiceDiscovery.findServiceForLocation(data);
|
let service = SimpleServiceDiscovery.findServiceForID(data);
|
||||||
if (!service)
|
if (!service)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -24,13 +24,22 @@ function discovery_observer(subject, topic, data) {
|
|||||||
run_next_test();
|
run_next_test();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var testTarget = {
|
||||||
|
target: "test:service",
|
||||||
|
factory: function(service) { /* dummy */ }
|
||||||
|
};
|
||||||
|
|
||||||
add_test(function test_default() {
|
add_test(function test_default() {
|
||||||
do_register_cleanup(function cleanup() {
|
do_register_cleanup(function cleanup() {
|
||||||
|
SimpleServiceDiscovery.unregisterTarget(testTarget);
|
||||||
Services.obs.removeObserver(discovery_observer, "ssdp-service-found");
|
Services.obs.removeObserver(discovery_observer, "ssdp-service-found");
|
||||||
});
|
});
|
||||||
|
|
||||||
Services.obs.addObserver(discovery_observer, "ssdp-service-found", false);
|
Services.obs.addObserver(discovery_observer, "ssdp-service-found", false);
|
||||||
|
|
||||||
|
// We need to register a target or processService will ignore us
|
||||||
|
SimpleServiceDiscovery.registerTarget(testTarget);
|
||||||
|
|
||||||
// Create a pretend service
|
// Create a pretend service
|
||||||
let service = {
|
let service = {
|
||||||
location: "http://mochi.test:8888/tests/robocop/simpleservice.xml",
|
location: "http://mochi.test:8888/tests/robocop/simpleservice.xml",
|
||||||
|
@ -260,6 +260,11 @@ public class ToolbarEditText extends CustomEditText
|
|||||||
// replace() preserves the autocomplete spans that we set before.
|
// replace() preserves the autocomplete spans that we set before.
|
||||||
text.replace(autoCompleteStart, textLength, result, autoCompleteStart, resultLength);
|
text.replace(autoCompleteStart, textLength, result, autoCompleteStart, resultLength);
|
||||||
|
|
||||||
|
// Reshow the cursor if there is no longer any autocomplete text.
|
||||||
|
if (autoCompleteStart == resultLength) {
|
||||||
|
setCursorVisible(true);
|
||||||
|
}
|
||||||
|
|
||||||
endSettingAutocomplete();
|
endSettingAutocomplete();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
@ -8,12 +8,15 @@ package org.mozilla.gecko.webapp;
|
|||||||
import org.mozilla.gecko.ActivityHandlerHelper;
|
import org.mozilla.gecko.ActivityHandlerHelper;
|
||||||
import org.mozilla.gecko.AppConstants;
|
import org.mozilla.gecko.AppConstants;
|
||||||
import org.mozilla.gecko.GeckoAppShell;
|
import org.mozilla.gecko.GeckoAppShell;
|
||||||
|
import org.mozilla.gecko.GeckoEvent;
|
||||||
import org.mozilla.gecko.GeckoProfile;
|
import org.mozilla.gecko.GeckoProfile;
|
||||||
import org.mozilla.gecko.favicons.decoders.FaviconDecoder;
|
import org.mozilla.gecko.favicons.decoders.FaviconDecoder;
|
||||||
import org.mozilla.gecko.gfx.BitmapUtils;
|
import org.mozilla.gecko.gfx.BitmapUtils;
|
||||||
import org.mozilla.gecko.util.ActivityResultHandler;
|
import org.mozilla.gecko.util.ActivityResultHandler;
|
||||||
import org.mozilla.gecko.EventDispatcher;
|
import org.mozilla.gecko.EventDispatcher;
|
||||||
import org.mozilla.gecko.util.GeckoEventListener;
|
import org.mozilla.gecko.util.EventCallback;
|
||||||
|
import org.mozilla.gecko.util.NativeEventListener;
|
||||||
|
import org.mozilla.gecko.util.NativeJSObject;
|
||||||
import org.mozilla.gecko.util.ThreadUtils;
|
import org.mozilla.gecko.util.ThreadUtils;
|
||||||
import org.mozilla.gecko.WebappAllocator;
|
import org.mozilla.gecko.WebappAllocator;
|
||||||
|
|
||||||
@ -30,15 +33,15 @@ import android.net.Uri;
|
|||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.json.JSONArray;
|
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
|
||||||
public class EventListener implements GeckoEventListener {
|
public class EventListener implements NativeEventListener {
|
||||||
|
|
||||||
private static final String LOGTAG = "GeckoWebappEventListener";
|
private static final String LOGTAG = "GeckoWebappEventListener";
|
||||||
|
|
||||||
@ -63,10 +66,10 @@ public class EventListener implements GeckoEventListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleMessage(String event, JSONObject message) {
|
public void handleMessage(String event, NativeJSObject message, EventCallback callback) {
|
||||||
try {
|
try {
|
||||||
if (AppConstants.MOZ_ANDROID_SYNTHAPKS && event.equals("Webapps:InstallApk")) {
|
if (AppConstants.MOZ_ANDROID_SYNTHAPKS && event.equals("Webapps:InstallApk")) {
|
||||||
installApk(GeckoAppShell.getGeckoInterface().getActivity(), message.getString("filePath"), message.getString("data"));
|
installApk(GeckoAppShell.getGeckoInterface().getActivity(), message, callback);
|
||||||
} else if (event.equals("Webapps:Postinstall")) {
|
} else if (event.equals("Webapps:Postinstall")) {
|
||||||
if (AppConstants.MOZ_ANDROID_SYNTHAPKS) {
|
if (AppConstants.MOZ_ANDROID_SYNTHAPKS) {
|
||||||
postInstallWebapp(message.getString("apkPackageName"), message.getString("origin"));
|
postInstallWebapp(message.getString("apkPackageName"), message.getString("origin"));
|
||||||
@ -94,12 +97,12 @@ public class EventListener implements GeckoEventListener {
|
|||||||
|
|
||||||
JSONObject obj = new JSONObject();
|
JSONObject obj = new JSONObject();
|
||||||
obj.put("profile", preInstallWebapp(name, manifestURL, origin).toString());
|
obj.put("profile", preInstallWebapp(name, manifestURL, origin).toString());
|
||||||
EventDispatcher.sendResponse(message, obj);
|
callback.sendSuccess(obj);
|
||||||
} else if (event.equals("Webapps:GetApkVersions")) {
|
} else if (event.equals("Webapps:GetApkVersions")) {
|
||||||
JSONObject obj = new JSONObject();
|
JSONObject obj = new JSONObject();
|
||||||
obj.put("versions", getApkVersions(GeckoAppShell.getGeckoInterface().getActivity(),
|
obj.put("versions", getApkVersions(GeckoAppShell.getGeckoInterface().getActivity(),
|
||||||
message.getJSONArray("packageNames")));
|
message.getStringArray("packageNames")));
|
||||||
EventDispatcher.sendResponse(message, obj);
|
callback.sendSuccess(obj);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Log.e(LOGTAG, "Exception handling message \"" + event + "\":", e);
|
Log.e(LOGTAG, "Exception handling message \"" + event + "\":", e);
|
||||||
@ -180,25 +183,27 @@ public class EventListener implements GeckoEventListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void installApk(final Activity context, String filePath, String data) {
|
public static void installApk(final Activity context, NativeJSObject message, EventCallback callback) {
|
||||||
// This is the data that mozApps.install sent to Webapps.jsm.
|
final JSONObject messageData;
|
||||||
JSONObject argsObj = null;
|
|
||||||
|
|
||||||
// We get the manifest url out of javascript here so we can use it as a checksum
|
// We get the manifest url out of javascript here so we can use it as a checksum
|
||||||
// in a minute, when a package has been installed.
|
// in a minute, when a package has been installed.
|
||||||
String manifestUrl = null;
|
String manifestUrl = null;
|
||||||
|
String filePath = null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
argsObj = new JSONObject(data);
|
filePath = message.getString("filePath");
|
||||||
manifestUrl = argsObj.getJSONObject("app").getString("manifestURL");
|
messageData = new JSONObject(message.getObject("data").toString());
|
||||||
|
manifestUrl = messageData.getJSONObject("app").getString("manifestURL");
|
||||||
} catch (JSONException e) {
|
} catch (JSONException e) {
|
||||||
Log.e(LOGTAG, "can't get manifest URL from JSON data", e);
|
Log.wtf(LOGTAG, "Error getting file path and data", e);
|
||||||
// TODO: propagate the error back to the mozApps.install caller.
|
callback.sendError("Error getting file path and data: " + e.toString());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We will check the manifestUrl from the one in the APK.
|
// We will check the manifestUrl from the one in the APK.
|
||||||
// Thus, we can have a one-to-one mapping of apk to receiver.
|
// Thus, we can have a one-to-one mapping of apk to receiver.
|
||||||
final InstallListener receiver = new InstallListener(manifestUrl, argsObj);
|
final InstallListener receiver = new InstallListener(manifestUrl, messageData);
|
||||||
|
|
||||||
// Listen for packages being installed.
|
// Listen for packages being installed.
|
||||||
IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
|
IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
|
||||||
@ -208,7 +213,7 @@ public class EventListener implements GeckoEventListener {
|
|||||||
File file = new File(filePath);
|
File file = new File(filePath);
|
||||||
if (!file.exists()) {
|
if (!file.exists()) {
|
||||||
Log.wtf(LOGTAG, "APK file doesn't exist at path " + filePath);
|
Log.wtf(LOGTAG, "APK file doesn't exist at path " + filePath);
|
||||||
// TODO: propagate the error back to the mozApps.install caller.
|
callback.sendError("APK file doesn't exist at path " + filePath);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -239,15 +244,9 @@ public class EventListener implements GeckoEventListener {
|
|||||||
|
|
||||||
private static final int DEFAULT_VERSION_CODE = -1;
|
private static final int DEFAULT_VERSION_CODE = -1;
|
||||||
|
|
||||||
public static JSONObject getApkVersions(Activity context, JSONArray packageNames) {
|
public static JSONObject getApkVersions(Activity context, String[] packageNames) {
|
||||||
Set<String> packageNameSet = new HashSet<String>();
|
Set<String> packageNameSet = new HashSet<String>();
|
||||||
for (int i = 0; i < packageNames.length(); i++) {
|
packageNameSet.addAll(Arrays.asList(packageNames));
|
||||||
try {
|
|
||||||
packageNameSet.add(packageNames.getString(i));
|
|
||||||
} catch (JSONException e) {
|
|
||||||
Log.w(LOGTAG, "exception populating settings item", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
final PackageManager pm = context.getPackageManager();
|
final PackageManager pm = context.getPackageManager();
|
||||||
List<ApplicationInfo> apps = pm.getInstalledApplications(0);
|
List<ApplicationInfo> apps = pm.getInstalledApplications(0);
|
||||||
|
@ -3,6 +3,16 @@
|
|||||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
// Define service targets. We should consider moving these to their respective
|
||||||
|
// JSM files, but we left them here to allow for better lazy JSM loading.
|
||||||
|
var rokuTarget = {
|
||||||
|
target: "roku:ecp",
|
||||||
|
factory: function(aService) {
|
||||||
|
Cu.import("resource://gre/modules/RokuApp.jsm");
|
||||||
|
return new RokuApp(aService);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
var CastingApps = {
|
var CastingApps = {
|
||||||
_castMenuId: -1,
|
_castMenuId: -1,
|
||||||
|
|
||||||
@ -11,11 +21,8 @@ var CastingApps = {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register a service target
|
// Register targets
|
||||||
SimpleServiceDiscovery.registerTarget("roku:ecp", function(aService) {
|
SimpleServiceDiscovery.registerTarget(rokuTarget);
|
||||||
Cu.import("resource://gre/modules/RokuApp.jsm");
|
|
||||||
return new RokuApp(aService);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Search for devices continuously every 120 seconds
|
// Search for devices continuously every 120 seconds
|
||||||
SimpleServiceDiscovery.search(120 * 1000);
|
SimpleServiceDiscovery.search(120 * 1000);
|
||||||
@ -252,6 +259,10 @@ var CastingApps = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
_findCastableVideo: function _findCastableVideo(aBrowser) {
|
_findCastableVideo: function _findCastableVideo(aBrowser) {
|
||||||
|
if (!aBrowser) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
// Scan for a <video> being actively cast. Also look for a castable <video>
|
// Scan for a <video> being actively cast. Also look for a castable <video>
|
||||||
// on the page.
|
// on the page.
|
||||||
let castableVideo = null;
|
let castableVideo = null;
|
||||||
@ -451,4 +462,3 @@ var CastingApps = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -989,6 +989,7 @@ var BrowserApp = {
|
|||||||
icon: "drawable://undo_button_icon",
|
icon: "drawable://undo_button_icon",
|
||||||
label: Strings.browser.GetStringFromName("undoCloseToast.action2"),
|
label: Strings.browser.GetStringFromName("undoCloseToast.action2"),
|
||||||
callback: function() {
|
callback: function() {
|
||||||
|
UITelemetry.addEvent("undo.1", "toast", null, "closetab");
|
||||||
let ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore);
|
let ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore);
|
||||||
ss.undoCloseTab(window, 0);
|
ss.undoCloseTab(window, 0);
|
||||||
}
|
}
|
||||||
|
@ -12,9 +12,9 @@ const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
|
|||||||
Cu.import("resource://gre/modules/Services.jsm");
|
Cu.import("resource://gre/modules/Services.jsm");
|
||||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||||
|
|
||||||
function log(msg) {
|
// Define the "log" function as a binding of the Log.d function so it specifies
|
||||||
Services.console.logStringMessage("[SSDP] " + msg);
|
// the "debug" priority and a log tag.
|
||||||
}
|
let log = Cu.import("resource://gre/modules/AndroidLog.jsm", {}).AndroidLog.d.bind(null, "SSDP");
|
||||||
|
|
||||||
XPCOMUtils.defineLazyGetter(this, "converter", function () {
|
XPCOMUtils.defineLazyGetter(this, "converter", function () {
|
||||||
let conv = Cc["@mozilla.org/intl/scriptableunicodeconverter"].createInstance(Ci.nsIScriptableUnicodeConverter);
|
let conv = Cc["@mozilla.org/intl/scriptableunicodeconverter"].createInstance(Ci.nsIScriptableUnicodeConverter);
|
||||||
@ -69,38 +69,32 @@ var SimpleServiceDiscovery = {
|
|||||||
// Listen for responses from specific targets. There could be more than one
|
// Listen for responses from specific targets. There could be more than one
|
||||||
// available.
|
// available.
|
||||||
let response = aMessage.data.split("\n");
|
let response = aMessage.data.split("\n");
|
||||||
let location;
|
let service = {};
|
||||||
let target;
|
response.forEach(function(row) {
|
||||||
let valid = false;
|
let name = row.toUpperCase();
|
||||||
response.some(function(row) {
|
if (name.startsWith("LOCATION")) {
|
||||||
let header = row.toUpperCase();
|
service.location = row.substr(10).trim();
|
||||||
if (header.startsWith("LOCATION")) {
|
} else if (name.startsWith("ST")) {
|
||||||
location = row.substr(10).trim();
|
service.target = row.substr(4).trim();
|
||||||
} else if (header.startsWith("ST")) {
|
} else if (name.startsWith("SERVER")) {
|
||||||
target = row.substr(4).trim();
|
service.server = row.substr(8).trim();
|
||||||
if (this._targets.has(target)) {
|
|
||||||
valid = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (location && valid) {
|
|
||||||
location = this._forceTrailingSlash(location);
|
|
||||||
|
|
||||||
// When we find a valid response, package up the service information
|
|
||||||
// and pass it on.
|
|
||||||
let service = {
|
|
||||||
location: location,
|
|
||||||
target: target
|
|
||||||
};
|
|
||||||
|
|
||||||
try {
|
|
||||||
this._processService(service);
|
|
||||||
} catch (e) {}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
|
|
||||||
|
if (service.location && this._targets.has(service.target)) {
|
||||||
|
service.location = this._forceTrailingSlash(service.location);
|
||||||
|
|
||||||
|
// We add the server as an additional way to filter services
|
||||||
|
if (!("server" in service)) {
|
||||||
|
service.server = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// When we find a valid response, package up the service information
|
||||||
|
// and pass it on.
|
||||||
|
try {
|
||||||
|
this._processService(service);
|
||||||
|
} catch (e) {}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
onStopListening: function(aSocket, aStatus) {
|
onStopListening: function(aSocket, aStatus) {
|
||||||
@ -218,17 +212,35 @@ var SimpleServiceDiscovery = {
|
|||||||
// Clean out any stale services
|
// Clean out any stale services
|
||||||
for (let [key, service] of this._services) {
|
for (let [key, service] of this._services) {
|
||||||
if (service.lastPing != this._searchTimestamp) {
|
if (service.lastPing != this._searchTimestamp) {
|
||||||
Services.obs.notifyObservers(null, EVENT_SERVICE_LOST, service.location);
|
Services.obs.notifyObservers(null, EVENT_SERVICE_LOST, service.uuid);
|
||||||
this._services.delete(service.location);
|
this._services.delete(service.uuid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
registerTarget: function registerTarget(aTarget, aAppFactory) {
|
registerTarget: function registerTarget(aTarget) {
|
||||||
|
// We must have "target" and "factory" defined
|
||||||
|
if (!("target" in aTarget) || !("factory" in aTarget)) {
|
||||||
|
// Fatal for registration
|
||||||
|
throw "Registration requires a target and a location";
|
||||||
|
}
|
||||||
|
|
||||||
// Only add if we don't already know about this target
|
// Only add if we don't already know about this target
|
||||||
if (!this._targets.has(aTarget)) {
|
if (!this._targets.has(aTarget.target)) {
|
||||||
this._targets.set(aTarget, { target: aTarget, factory: aAppFactory });
|
this._targets.set(aTarget.target, aTarget);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
unregisterTarget: function unregisterTarget(aTarget) {
|
||||||
|
// We must have "target" and "factory" defined
|
||||||
|
if (!("target" in aTarget) || !("factory" in aTarget)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only remove if we know about this target
|
||||||
|
if (this._targets.has(aTarget.target)) {
|
||||||
|
this._targets.delete(aTarget.target);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -244,9 +256,9 @@ var SimpleServiceDiscovery = {
|
|||||||
return null;
|
return null;
|
||||||
},
|
},
|
||||||
|
|
||||||
findServiceForLocation: function findServiceForLocation(aLocation) {
|
findServiceForID: function findServiceForID(aUUID) {
|
||||||
if (this._services.has(aLocation)) {
|
if (this._services.has(aUUID)) {
|
||||||
return this._services.get(aLocation);
|
return this._services.get(aUUID);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
},
|
},
|
||||||
@ -260,6 +272,29 @@ var SimpleServiceDiscovery = {
|
|||||||
return array;
|
return array;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// Returns false if the service does not match the target's filters
|
||||||
|
_filterService: function _filterService(aService) {
|
||||||
|
let target = this._targets.get(aService.target);
|
||||||
|
if (!target) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we have no filter, everything passes
|
||||||
|
if (!("filters" in target)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If any filter fails, the service fails
|
||||||
|
let filters = target.filters;
|
||||||
|
for (let filter in filters) {
|
||||||
|
if (filter in aService && aService[filter] != filters[filter]) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
|
||||||
_processService: function _processService(aService) {
|
_processService: function _processService(aService) {
|
||||||
// Use the REST api to request more information about this service
|
// Use the REST api to request more information about this service
|
||||||
let xhr = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstance(Ci.nsIXMLHttpRequest);
|
let xhr = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstance(Ci.nsIXMLHttpRequest);
|
||||||
@ -278,14 +313,19 @@ var SimpleServiceDiscovery = {
|
|||||||
aService.manufacturer = doc.querySelector("manufacturer").textContent;
|
aService.manufacturer = doc.querySelector("manufacturer").textContent;
|
||||||
aService.modelName = doc.querySelector("modelName").textContent;
|
aService.modelName = doc.querySelector("modelName").textContent;
|
||||||
|
|
||||||
|
// Filter out services that do not match the target filter
|
||||||
|
if (!this._filterService(aService)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Only add and notify if we don't already know about this service
|
// Only add and notify if we don't already know about this service
|
||||||
if (!this._services.has(aService.location)) {
|
if (!this._services.has(aService.uuid)) {
|
||||||
this._services.set(aService.location, aService);
|
this._services.set(aService.uuid, aService);
|
||||||
Services.obs.notifyObservers(null, EVENT_SERVICE_FOUND, aService.location);
|
Services.obs.notifyObservers(null, EVENT_SERVICE_FOUND, aService.uuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure we remember this service is not stale
|
// Make sure we remember this service is not stale
|
||||||
this._services.get(aService.location).lastPing = this._searchTimestamp;
|
this._services.get(aService.uuid).lastPing = this._searchTimestamp;
|
||||||
}
|
}
|
||||||
}).bind(this), false);
|
}).bind(this), false);
|
||||||
|
|
||||||
|
@ -103,7 +103,13 @@ this.WebappManager = {
|
|||||||
sendMessageToJava({
|
sendMessageToJava({
|
||||||
type: "Webapps:InstallApk",
|
type: "Webapps:InstallApk",
|
||||||
filePath: filePath,
|
filePath: filePath,
|
||||||
data: JSON.stringify(aMessage),
|
data: aMessage,
|
||||||
|
}, (data, error) => {
|
||||||
|
if (!!error) {
|
||||||
|
aMessage.error = error;
|
||||||
|
aMessageManager.sendAsyncMessage("Webapps:Install:Return:KO", aMessage);
|
||||||
|
debug("error downloading APK: " + error);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}).bind(this)); },
|
}).bind(this)); },
|
||||||
|
|
||||||
@ -242,8 +248,8 @@ this.WebappManager = {
|
|||||||
message.app.manifest = aData.manifest;
|
message.app.manifest = aData.manifest;
|
||||||
message.app.apkPackageName = aData.apkPackageName;
|
message.app.apkPackageName = aData.apkPackageName;
|
||||||
message.profilePath = aData.profilePath;
|
message.profilePath = aData.profilePath;
|
||||||
message.autoInstall = true;
|
|
||||||
message.mm = mm;
|
message.mm = mm;
|
||||||
|
message.apkInstall = true;
|
||||||
|
|
||||||
DOMApplicationRegistry.registryReady.then(() => {
|
DOMApplicationRegistry.registryReady.then(() => {
|
||||||
switch (aData.type) { // can be hosted or packaged.
|
switch (aData.type) { // can be hosted or packaged.
|
||||||
@ -493,7 +499,7 @@ this.WebappManager = {
|
|||||||
sendMessageToJava({
|
sendMessageToJava({
|
||||||
type: "Webapps:InstallApk",
|
type: "Webapps:InstallApk",
|
||||||
filePath: apk.filePath,
|
filePath: apk.filePath,
|
||||||
data: JSON.stringify(msg),
|
data: msg,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -57,6 +57,8 @@ this.getFrameWorkerHandle =
|
|||||||
existingWorker.browserPromise.then(browser => {
|
existingWorker.browserPromise.then(browser => {
|
||||||
browser.messageManager.sendAsyncMessage("frameworker:connect",
|
browser.messageManager.sendAsyncMessage("frameworker:connect",
|
||||||
{ portId: portid });
|
{ portId: portid });
|
||||||
|
}).then(null, (ex) => {
|
||||||
|
Cu.reportError("Could not send frameworker:connect: " + ex);
|
||||||
});
|
});
|
||||||
// return the pseudo worker object.
|
// return the pseudo worker object.
|
||||||
let port = new ParentPort(portid, existingWorker.browserPromise, clientWindow);
|
let port = new ParentPort(portid, existingWorker.browserPromise, clientWindow);
|
||||||
|
@ -473,6 +473,10 @@ LayoutHelpers.prototype = {
|
|||||||
|
|
||||||
// Else, need to get margin/padding/border distances
|
// Else, need to get margin/padding/border distances
|
||||||
let style = node.ownerDocument.defaultView.getComputedStyle(node);
|
let style = node.ownerDocument.defaultView.getComputedStyle(node);
|
||||||
|
if (!style) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
let camel = s => s.substring(0, 1).toUpperCase() + s.substring(1);
|
let camel = s => s.substring(0, 1).toUpperCase() + s.substring(1);
|
||||||
let distances = {border:{}, padding:{}, margin: {}};
|
let distances = {border:{}, padding:{}, margin: {}};
|
||||||
|
|
||||||
|
@ -62,6 +62,8 @@ const {Unknown} = require("sdk/platform/xpcom");
|
|||||||
const {Class} = require("sdk/core/heritage");
|
const {Class} = require("sdk/core/heritage");
|
||||||
const {PageStyleActor} = require("devtools/server/actors/styles");
|
const {PageStyleActor} = require("devtools/server/actors/styles");
|
||||||
const {HighlighterActor} = require("devtools/server/actors/highlighter");
|
const {HighlighterActor} = require("devtools/server/actors/highlighter");
|
||||||
|
const {getLayoutChangesObserver, releaseLayoutChangesObserver} =
|
||||||
|
require("devtools/server/actors/layout");
|
||||||
|
|
||||||
const FONT_FAMILY_PREVIEW_TEXT = "The quick brown fox jumps over the lazy dog";
|
const FONT_FAMILY_PREVIEW_TEXT = "The quick brown fox jumps over the lazy dog";
|
||||||
const FONT_FAMILY_PREVIEW_TEXT_SIZE = 20;
|
const FONT_FAMILY_PREVIEW_TEXT_SIZE = 20;
|
||||||
@ -177,6 +179,10 @@ var NodeActor = exports.NodeActor = protocol.ActorClass({
|
|||||||
protocol.Actor.prototype.initialize.call(this, null);
|
protocol.Actor.prototype.initialize.call(this, null);
|
||||||
this.walker = walker;
|
this.walker = walker;
|
||||||
this.rawNode = node;
|
this.rawNode = node;
|
||||||
|
|
||||||
|
// Storing the original display of the node, to track changes when reflows
|
||||||
|
// occur
|
||||||
|
this.wasDisplayed = this.isDisplayed;
|
||||||
},
|
},
|
||||||
|
|
||||||
toString: function() {
|
toString: function() {
|
||||||
@ -227,6 +233,8 @@ var NodeActor = exports.NodeActor = protocol.ActorClass({
|
|||||||
attrs: this.writeAttrs(),
|
attrs: this.writeAttrs(),
|
||||||
|
|
||||||
pseudoClassLocks: this.writePseudoClassLocks(),
|
pseudoClassLocks: this.writePseudoClassLocks(),
|
||||||
|
|
||||||
|
isDisplayed: this.isDisplayed,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (this.isDocumentElement()) {
|
if (this.isDocumentElement()) {
|
||||||
@ -247,6 +255,28 @@ var NodeActor = exports.NodeActor = protocol.ActorClass({
|
|||||||
return form;
|
return form;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
get computedStyle() {
|
||||||
|
if (Cu.isDeadWrapper(this.rawNode) ||
|
||||||
|
this.rawNode.nodeType !== Ci.nsIDOMNode.ELEMENT_NODE ||
|
||||||
|
!this.rawNode.ownerDocument) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return this.rawNode.ownerDocument.defaultView.getComputedStyle(this.rawNode);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is the node's display computed style value other than "none"
|
||||||
|
*/
|
||||||
|
get isDisplayed() {
|
||||||
|
let style = this.computedStyle;
|
||||||
|
if (!style) {
|
||||||
|
// Consider all non-element nodes as displayed
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return style.display !== "none";
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
writeAttrs: function() {
|
writeAttrs: function() {
|
||||||
if (!this.rawNode.attributes) {
|
if (!this.rawNode.attributes) {
|
||||||
return undefined;
|
return undefined;
|
||||||
@ -548,6 +578,12 @@ let NodeFront = protocol.FrontClass(NodeActor, {
|
|||||||
return this.pseudoClassLocks.some(locked => locked === pseudo);
|
return this.pseudoClassLocks.some(locked => locked === pseudo);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
get isDisplayed() {
|
||||||
|
// The NodeActor's form contains the isDisplayed information as a boolean
|
||||||
|
// starting from FF32. Before that, the property is missing
|
||||||
|
return "isDisplayed" in this._form ? this._form.isDisplayed : true;
|
||||||
|
},
|
||||||
|
|
||||||
getNodeValue: protocol.custom(function() {
|
getNodeValue: protocol.custom(function() {
|
||||||
if (!this.incompleteValue) {
|
if (!this.incompleteValue) {
|
||||||
return delayedResolve(new ShortLongString(this.shortValue));
|
return delayedResolve(new ShortLongString(this.shortValue));
|
||||||
@ -836,6 +872,10 @@ var WalkerActor = protocol.ActorClass({
|
|||||||
},
|
},
|
||||||
"highlighter-hide" : {
|
"highlighter-hide" : {
|
||||||
type: "highlighter-hide"
|
type: "highlighter-hide"
|
||||||
|
},
|
||||||
|
"display-change" : {
|
||||||
|
type: "display-change",
|
||||||
|
nodes: Arg(0, "array:domnode")
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -875,6 +915,10 @@ var WalkerActor = protocol.ActorClass({
|
|||||||
// Ensure that the root document node actor is ready and
|
// Ensure that the root document node actor is ready and
|
||||||
// managed.
|
// managed.
|
||||||
this.rootNode = this.document();
|
this.rootNode = this.document();
|
||||||
|
|
||||||
|
this.reflowObserver = getLayoutChangesObserver(this.tabActor);
|
||||||
|
this._onReflows = this._onReflows.bind(this);
|
||||||
|
this.reflowObserver.on("reflows", this._onReflows);
|
||||||
},
|
},
|
||||||
|
|
||||||
// Returns the JSON representation of this object over the wire.
|
// Returns the JSON representation of this object over the wire.
|
||||||
@ -894,6 +938,11 @@ var WalkerActor = protocol.ActorClass({
|
|||||||
this.clearPseudoClassLocks();
|
this.clearPseudoClassLocks();
|
||||||
this._activePseudoClassLocks = null;
|
this._activePseudoClassLocks = null;
|
||||||
this.rootDoc = null;
|
this.rootDoc = null;
|
||||||
|
|
||||||
|
this.reflowObserver.off("reflows", this._onReflows);
|
||||||
|
this.reflowObserver = null;
|
||||||
|
releaseLayoutChangesObserver(this.tabActor);
|
||||||
|
|
||||||
events.emit(this, "destroyed");
|
events.emit(this, "destroyed");
|
||||||
protocol.Actor.prototype.destroy.call(this);
|
protocol.Actor.prototype.destroy.call(this);
|
||||||
},
|
},
|
||||||
@ -904,7 +953,7 @@ var WalkerActor = protocol.ActorClass({
|
|||||||
if (actor instanceof NodeActor) {
|
if (actor instanceof NodeActor) {
|
||||||
if (this._activePseudoClassLocks &&
|
if (this._activePseudoClassLocks &&
|
||||||
this._activePseudoClassLocks.has(actor)) {
|
this._activePseudoClassLocks.has(actor)) {
|
||||||
this.clearPsuedoClassLocks(actor);
|
this.clearPseudoClassLocks(actor);
|
||||||
}
|
}
|
||||||
this._refMap.delete(actor.rawNode);
|
this._refMap.delete(actor.rawNode);
|
||||||
}
|
}
|
||||||
@ -928,6 +977,24 @@ var WalkerActor = protocol.ActorClass({
|
|||||||
return actor;
|
return actor;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
_onReflows: function(reflows) {
|
||||||
|
// Going through the nodes the walker knows about, see which ones have
|
||||||
|
// had their display changed and send a display-change event if any
|
||||||
|
let changes = [];
|
||||||
|
for (let [node, actor] of this._refMap) {
|
||||||
|
let isDisplayed = actor.isDisplayed;
|
||||||
|
if (isDisplayed !== actor.wasDisplayed) {
|
||||||
|
changes.push(actor);
|
||||||
|
// Updating the original value
|
||||||
|
actor.wasDisplayed = isDisplayed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (changes.length) {
|
||||||
|
events.emit(this, "display-change", changes);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is kept for backward-compatibility reasons with older remote targets.
|
* This is kept for backward-compatibility reasons with older remote targets.
|
||||||
* Targets prior to bug 916443.
|
* Targets prior to bug 916443.
|
||||||
|
@ -59,8 +59,8 @@ ProfileEntry::ProfileEntry(char aTagName, Address aTagAddress)
|
|||||||
, mTagName(aTagName)
|
, mTagName(aTagName)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
ProfileEntry::ProfileEntry(char aTagName, int aTagLine)
|
ProfileEntry::ProfileEntry(char aTagName, int aTagInt)
|
||||||
: mTagLine(aTagLine)
|
: mTagInt(aTagInt)
|
||||||
, mTagName(aTagName)
|
, mTagName(aTagName)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
@ -94,7 +94,7 @@ void ProfileEntry::log()
|
|||||||
// mTagMarker (ProfilerMarker*) m
|
// mTagMarker (ProfilerMarker*) m
|
||||||
// mTagData (const char*) c,s
|
// mTagData (const char*) c,s
|
||||||
// mTagPtr (void*) d,l,L,B (immediate backtrace), S(start-of-stack)
|
// mTagPtr (void*) d,l,L,B (immediate backtrace), S(start-of-stack)
|
||||||
// mTagLine (int) n,f
|
// mTagInt (int) n,f,y
|
||||||
// mTagChar (char) h
|
// mTagChar (char) h
|
||||||
// mTagFloat (double) r,t,p,R (resident memory)
|
// mTagFloat (double) r,t,p,R (resident memory)
|
||||||
switch (mTagName) {
|
switch (mTagName) {
|
||||||
@ -104,8 +104,8 @@ void ProfileEntry::log()
|
|||||||
LOGF("%c \"%s\"", mTagName, mTagData); break;
|
LOGF("%c \"%s\"", mTagName, mTagData); break;
|
||||||
case 'd': case 'l': case 'L': case 'B': case 'S':
|
case 'd': case 'l': case 'L': case 'B': case 'S':
|
||||||
LOGF("%c %p", mTagName, mTagPtr); break;
|
LOGF("%c %p", mTagName, mTagPtr); break;
|
||||||
case 'n': case 'f':
|
case 'n': case 'f': case 'y':
|
||||||
LOGF("%c %d", mTagName, mTagLine); break;
|
LOGF("%c %d", mTagName, mTagInt); break;
|
||||||
case 'h':
|
case 'h':
|
||||||
LOGF("%c \'%c\'", mTagName, mTagChar); break;
|
LOGF("%c \'%c\'", mTagName, mTagChar); break;
|
||||||
case 'r': case 't': case 'p': case 'R':
|
case 'r': case 't': case 'p': case 'R':
|
||||||
@ -362,7 +362,7 @@ void ThreadProfile::StreamJSObject(JSStreamWriter& b)
|
|||||||
case 'f':
|
case 'f':
|
||||||
{
|
{
|
||||||
if (sample) {
|
if (sample) {
|
||||||
b.NameValue("frameNumber", entry.mTagLine);
|
b.NameValue("frameNumber", entry.mTagInt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -399,6 +399,7 @@ void ThreadProfile::StreamJSObject(JSStreamWriter& b)
|
|||||||
while (framePos != mLastFlushPos && frame.mTagName != 's') {
|
while (framePos != mLastFlushPos && frame.mTagName != 's') {
|
||||||
int incBy = 1;
|
int incBy = 1;
|
||||||
frame = mEntries[framePos];
|
frame = mEntries[framePos];
|
||||||
|
|
||||||
// Read ahead to the next tag, if it's a 'd' tag process it now
|
// Read ahead to the next tag, if it's a 'd' tag process it now
|
||||||
const char* tagStringData = frame.mTagData;
|
const char* tagStringData = frame.mTagData;
|
||||||
int readAheadPos = (framePos + 1) % mEntrySize;
|
int readAheadPos = (framePos + 1) % mEntrySize;
|
||||||
@ -413,7 +414,8 @@ void ThreadProfile::StreamJSObject(JSStreamWriter& b)
|
|||||||
|
|
||||||
// Write one frame. It can have either
|
// Write one frame. It can have either
|
||||||
// 1. only location - 'l' containing a memory address
|
// 1. only location - 'l' containing a memory address
|
||||||
// 2. location and line number - 'c' followed by 'd's and an optional 'n'
|
// 2. location and line number - 'c' followed by 'd's,
|
||||||
|
// an optional 'n' and an optional 'y'
|
||||||
if (frame.mTagName == 'l') {
|
if (frame.mTagName == 'l') {
|
||||||
b.BeginObject();
|
b.BeginObject();
|
||||||
// Bug 753041
|
// Bug 753041
|
||||||
@ -429,7 +431,13 @@ void ThreadProfile::StreamJSObject(JSStreamWriter& b)
|
|||||||
readAheadPos = (framePos + incBy) % mEntrySize;
|
readAheadPos = (framePos + incBy) % mEntrySize;
|
||||||
if (readAheadPos != mLastFlushPos &&
|
if (readAheadPos != mLastFlushPos &&
|
||||||
mEntries[readAheadPos].mTagName == 'n') {
|
mEntries[readAheadPos].mTagName == 'n') {
|
||||||
b.NameValue("line", mEntries[readAheadPos].mTagLine);
|
b.NameValue("line", mEntries[readAheadPos].mTagInt);
|
||||||
|
incBy++;
|
||||||
|
}
|
||||||
|
readAheadPos = (framePos + incBy) % mEntrySize;
|
||||||
|
if (readAheadPos != mLastFlushPos &&
|
||||||
|
mEntries[readAheadPos].mTagName == 'y') {
|
||||||
|
b.NameValue("category", mEntries[readAheadPos].mTagInt);
|
||||||
incBy++;
|
incBy++;
|
||||||
}
|
}
|
||||||
b.EndObject();
|
b.EndObject();
|
||||||
|
@ -61,7 +61,7 @@ private:
|
|||||||
float mTagFloat;
|
float mTagFloat;
|
||||||
Address mTagAddress;
|
Address mTagAddress;
|
||||||
uintptr_t mTagOffset;
|
uintptr_t mTagOffset;
|
||||||
int mTagLine;
|
int mTagInt;
|
||||||
char mTagChar;
|
char mTagChar;
|
||||||
};
|
};
|
||||||
char mTagName;
|
char mTagName;
|
||||||
|
@ -362,6 +362,7 @@ public:
|
|||||||
// been written such that mStack is always consistent.
|
// been written such that mStack is always consistent.
|
||||||
entry.setLabel(aName);
|
entry.setLabel(aName);
|
||||||
entry.setCppFrame(aStackAddress, line);
|
entry.setCppFrame(aStackAddress, line);
|
||||||
|
MOZ_ASSERT(entry.flags() == js::ProfileEntry::IS_CPP_ENTRY);
|
||||||
|
|
||||||
uint32_t uint_category = static_cast<uint32_t>(aCategory);
|
uint32_t uint_category = static_cast<uint32_t>(aCategory);
|
||||||
MOZ_ASSERT(
|
MOZ_ASSERT(
|
||||||
|
@ -374,9 +374,18 @@ void addProfileEntry(volatile StackEntry &entry, ThreadProfile &aProfile,
|
|||||||
lineno = entry.line();
|
lineno = entry.line();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lineno != -1) {
|
if (lineno != -1) {
|
||||||
aProfile.addTag(ProfileEntry('n', lineno));
|
aProfile.addTag(ProfileEntry('n', lineno));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t category = entry.category();
|
||||||
|
MOZ_ASSERT(!(category & StackEntry::IS_CPP_ENTRY));
|
||||||
|
MOZ_ASSERT(!(category & StackEntry::FRAME_LABEL_COPY));
|
||||||
|
|
||||||
|
if (category) {
|
||||||
|
aProfile.addTag(ProfileEntry('y', (int)category));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(USE_NS_STACKWALK) || defined(USE_EHABI_STACKWALK)
|
#if defined(USE_NS_STACKWALK) || defined(USE_EHABI_STACKWALK)
|
||||||
|
@ -38,7 +38,7 @@ TEST(ThreadProfile, InsertTagsNoWrap) {
|
|||||||
int readPos = tp.mReadPos;
|
int readPos = tp.mReadPos;
|
||||||
while (readPos != tp.mWritePos) {
|
while (readPos != tp.mWritePos) {
|
||||||
ASSERT_TRUE(tp.mEntries[readPos].mTagName == 't');
|
ASSERT_TRUE(tp.mEntries[readPos].mTagName == 't');
|
||||||
ASSERT_TRUE(tp.mEntries[readPos].mTagLine == readPos);
|
ASSERT_TRUE(tp.mEntries[readPos].mTagInt == readPos);
|
||||||
readPos = (readPos + 1) % tp.mEntrySize;
|
readPos = (readPos + 1) % tp.mEntrySize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -61,7 +61,7 @@ TEST(ThreadProfile, InsertTagsWrap) {
|
|||||||
while (readPos != tp.mWritePos) {
|
while (readPos != tp.mWritePos) {
|
||||||
ASSERT_TRUE(tp.mEntries[readPos].mTagName == 't');
|
ASSERT_TRUE(tp.mEntries[readPos].mTagName == 't');
|
||||||
// the first few tags were discarded when we wrapped
|
// the first few tags were discarded when we wrapped
|
||||||
ASSERT_TRUE(tp.mEntries[readPos].mTagLine == ctr + (test_size - tags));
|
ASSERT_TRUE(tp.mEntries[readPos].mTagInt == ctr + (test_size - tags));
|
||||||
ctr++;
|
ctr++;
|
||||||
readPos = (readPos + 1) % tp.mEntrySize;
|
readPos = (readPos + 1) % tp.mEntrySize;
|
||||||
}
|
}
|
||||||
|
@ -206,6 +206,16 @@ AndroidBridge::Init(JNIEnv *jEnv)
|
|||||||
jEGLSurfacePointerField = 0;
|
jEGLSurfacePointerField = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
jChannels = getClassGlobalRef("java/nio/channels/Channels");
|
||||||
|
jChannelCreate = jEnv->GetStaticMethodID(jChannels, "newChannel", "(Ljava/io/InputStream;)Ljava/nio/channels/ReadableByteChannel;");
|
||||||
|
|
||||||
|
jReadableByteChannel = getClassGlobalRef("java/nio/channels/ReadableByteChannel");
|
||||||
|
jByteBufferRead = jEnv->GetMethodID(jReadableByteChannel, "read", "(Ljava/nio/ByteBuffer;)I");
|
||||||
|
|
||||||
|
jInputStream = getClassGlobalRef("java/io/InputStream");
|
||||||
|
jClose = jEnv->GetMethodID(jInputStream, "close", "()V");
|
||||||
|
jAvailable = jEnv->GetMethodID(jInputStream, "available", "()I");
|
||||||
|
|
||||||
InitAndroidJavaWrappers(jEnv);
|
InitAndroidJavaWrappers(jEnv);
|
||||||
|
|
||||||
// jEnv should NOT be cached here by anything -- the jEnv here
|
// jEnv should NOT be cached here by anything -- the jEnv here
|
||||||
@ -2093,3 +2103,41 @@ AndroidBridge::RunDelayedTasks()
|
|||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
jobject AndroidBridge::ChannelCreate(jobject stream) {
|
||||||
|
JNIEnv *env = GetJNIForThread();
|
||||||
|
env->PushLocalFrame(1);
|
||||||
|
jobject channel = env->CallStaticObjectMethod(sBridge->jReadableByteChannel, sBridge->jChannelCreate, stream);
|
||||||
|
return env->PopLocalFrame(channel);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AndroidBridge::InputStreamClose(jobject obj) {
|
||||||
|
JNIEnv *env = GetJNIForThread();
|
||||||
|
AutoLocalJNIFrame jniFrame(env, 1);
|
||||||
|
env->CallVoidMethod(obj, sBridge->jClose);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t AndroidBridge::InputStreamAvailable(jobject obj) {
|
||||||
|
JNIEnv *env = GetJNIForThread();
|
||||||
|
AutoLocalJNIFrame jniFrame(env, 1);
|
||||||
|
return env->CallIntMethod(obj, sBridge->jAvailable);
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult AndroidBridge::InputStreamRead(jobject obj, char *aBuf, uint32_t aCount, uint32_t *aRead) {
|
||||||
|
JNIEnv *env = GetJNIForThread();
|
||||||
|
AutoLocalJNIFrame jniFrame(env, 1);
|
||||||
|
jobject arr = env->NewDirectByteBuffer(aBuf, aCount);
|
||||||
|
jint read = env->CallIntMethod(obj, sBridge->jByteBufferRead, arr);
|
||||||
|
|
||||||
|
if (env->ExceptionCheck()) {
|
||||||
|
env->ExceptionClear();
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (read <= 0) {
|
||||||
|
*aRead = 0;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
*aRead = read;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
@ -117,7 +117,6 @@ private:
|
|||||||
TimeStamp mRunTime;
|
TimeStamp mRunTime;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class AndroidBridge MOZ_FINAL : public mozilla::layers::GeckoContentController
|
class AndroidBridge MOZ_FINAL : public mozilla::layers::GeckoContentController
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -344,6 +343,13 @@ public:
|
|||||||
static jfieldID GetStaticFieldID(JNIEnv* env, jclass jClass, const char* fieldName, const char* fieldType);
|
static jfieldID GetStaticFieldID(JNIEnv* env, jclass jClass, const char* fieldName, const char* fieldType);
|
||||||
static jmethodID GetMethodID(JNIEnv* env, jclass jClass, const char* methodName, const char* methodType);
|
static jmethodID GetMethodID(JNIEnv* env, jclass jClass, const char* methodName, const char* methodType);
|
||||||
static jmethodID GetStaticMethodID(JNIEnv* env, jclass jClass, const char* methodName, const char* methodType);
|
static jmethodID GetStaticMethodID(JNIEnv* env, jclass jClass, const char* methodName, const char* methodType);
|
||||||
|
|
||||||
|
static jobject ChannelCreate(jobject);
|
||||||
|
|
||||||
|
static void InputStreamClose(jobject obj);
|
||||||
|
static uint32_t InputStreamAvailable(jobject obj);
|
||||||
|
static nsresult InputStreamRead(jobject obj, char *aBuf, uint32_t aCount, uint32_t *aRead);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static StaticRefPtr<AndroidBridge> sBridge;
|
static StaticRefPtr<AndroidBridge> sBridge;
|
||||||
nsTArray<nsCOMPtr<nsIMobileMessageCallback> > mSmsRequests;
|
nsTArray<nsCOMPtr<nsIMobileMessageCallback> > mSmsRequests;
|
||||||
@ -378,6 +384,16 @@ protected:
|
|||||||
|
|
||||||
bool QueueSmsRequest(nsIMobileMessageCallback* aRequest, uint32_t* aRequestIdOut);
|
bool QueueSmsRequest(nsIMobileMessageCallback* aRequest, uint32_t* aRequestIdOut);
|
||||||
|
|
||||||
|
// intput stream
|
||||||
|
jclass jReadableByteChannel;
|
||||||
|
jclass jChannels;
|
||||||
|
jmethodID jChannelCreate;
|
||||||
|
jmethodID jByteBufferRead;
|
||||||
|
|
||||||
|
jclass jInputStream;
|
||||||
|
jmethodID jClose;
|
||||||
|
jmethodID jAvailable;
|
||||||
|
|
||||||
// other things
|
// other things
|
||||||
jmethodID jNotifyAppShellReady;
|
jmethodID jNotifyAppShellReady;
|
||||||
jmethodID jGetOutstandingDrawEvents;
|
jmethodID jGetOutstandingDrawEvents;
|
||||||
|
@ -1011,3 +1011,30 @@ nsJNIString::nsJNIString(jstring jstr, JNIEnv *jenv)
|
|||||||
}
|
}
|
||||||
jni->ReleaseStringChars(jstr, jCharPtr);
|
jni->ReleaseStringChars(jstr, jCharPtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsJNICString::nsJNICString(jstring jstr, JNIEnv *jenv)
|
||||||
|
{
|
||||||
|
if (!jstr) {
|
||||||
|
SetIsVoid(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
JNIEnv *jni = jenv;
|
||||||
|
if (!jni) {
|
||||||
|
jni = AndroidBridge::GetJNIEnv();
|
||||||
|
}
|
||||||
|
const char* jCharPtr = jni->GetStringUTFChars(jstr, nullptr);
|
||||||
|
|
||||||
|
if (!jCharPtr) {
|
||||||
|
SetIsVoid(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
jsize len = jni->GetStringUTFLength(jstr);
|
||||||
|
|
||||||
|
if (len <= 0) {
|
||||||
|
SetIsVoid(true);
|
||||||
|
} else {
|
||||||
|
Assign(jCharPtr, len);
|
||||||
|
}
|
||||||
|
jni->ReleaseStringUTFChars(jstr, jCharPtr);
|
||||||
|
}
|
||||||
|
@ -750,6 +750,12 @@ public:
|
|||||||
nsJNIString(jstring jstr, JNIEnv *jenv);
|
nsJNIString(jstring jstr, JNIEnv *jenv);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class nsJNICString : public nsCString
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
nsJNICString(jstring jstr, JNIEnv *jenv);
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -20,6 +20,8 @@ jmethodID GeckoAppShell::jCheckURIVisited = 0;
|
|||||||
jmethodID GeckoAppShell::jClearMessageList = 0;
|
jmethodID GeckoAppShell::jClearMessageList = 0;
|
||||||
jmethodID GeckoAppShell::jCloseCamera = 0;
|
jmethodID GeckoAppShell::jCloseCamera = 0;
|
||||||
jmethodID GeckoAppShell::jCloseNotification = 0;
|
jmethodID GeckoAppShell::jCloseNotification = 0;
|
||||||
|
jmethodID GeckoAppShell::jConnectionGetMimeType = 0;
|
||||||
|
jmethodID GeckoAppShell::jCreateInputStream = 0;
|
||||||
jmethodID GeckoAppShell::jCreateMessageListWrapper = 0;
|
jmethodID GeckoAppShell::jCreateMessageListWrapper = 0;
|
||||||
jmethodID GeckoAppShell::jCreateShortcut = 0;
|
jmethodID GeckoAppShell::jCreateShortcut = 0;
|
||||||
jmethodID GeckoAppShell::jDeleteMessageWrapper = 0;
|
jmethodID GeckoAppShell::jDeleteMessageWrapper = 0;
|
||||||
@ -34,6 +36,7 @@ jmethodID GeckoAppShell::jEnableNetworkNotifications = 0;
|
|||||||
jmethodID GeckoAppShell::jEnableScreenOrientationNotifications = 0;
|
jmethodID GeckoAppShell::jEnableScreenOrientationNotifications = 0;
|
||||||
jmethodID GeckoAppShell::jEnableSensor = 0;
|
jmethodID GeckoAppShell::jEnableSensor = 0;
|
||||||
jmethodID GeckoAppShell::jGamepadAdded = 0;
|
jmethodID GeckoAppShell::jGamepadAdded = 0;
|
||||||
|
jmethodID GeckoAppShell::jGetConnection = 0;
|
||||||
jmethodID GeckoAppShell::jGetContext = 0;
|
jmethodID GeckoAppShell::jGetContext = 0;
|
||||||
jmethodID GeckoAppShell::jGetCurrentBatteryInformationWrapper = 0;
|
jmethodID GeckoAppShell::jGetCurrentBatteryInformationWrapper = 0;
|
||||||
jmethodID GeckoAppShell::jGetCurrentNetworkInformationWrapper = 0;
|
jmethodID GeckoAppShell::jGetCurrentNetworkInformationWrapper = 0;
|
||||||
@ -102,6 +105,8 @@ void GeckoAppShell::InitStubs(JNIEnv *jEnv) {
|
|||||||
jClearMessageList = getStaticMethod("clearMessageList", "(I)V");
|
jClearMessageList = getStaticMethod("clearMessageList", "(I)V");
|
||||||
jCloseCamera = getStaticMethod("closeCamera", "()V");
|
jCloseCamera = getStaticMethod("closeCamera", "()V");
|
||||||
jCloseNotification = getStaticMethod("closeNotification", "(Ljava/lang/String;)V");
|
jCloseNotification = getStaticMethod("closeNotification", "(Ljava/lang/String;)V");
|
||||||
|
jConnectionGetMimeType = getStaticMethod("connectionGetMimeType", "(Ljava/net/URLConnection;)Ljava/lang/String;");
|
||||||
|
jCreateInputStream = getStaticMethod("createInputStream", "(Ljava/net/URLConnection;)Ljava/io/InputStream;");
|
||||||
jCreateMessageListWrapper = getStaticMethod("createMessageList", "(JJ[Ljava/lang/String;IIZI)V");
|
jCreateMessageListWrapper = getStaticMethod("createMessageList", "(JJ[Ljava/lang/String;IIZI)V");
|
||||||
jCreateShortcut = getStaticMethod("createShortcut", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
|
jCreateShortcut = getStaticMethod("createShortcut", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
|
||||||
jDeleteMessageWrapper = getStaticMethod("deleteMessage", "(II)V");
|
jDeleteMessageWrapper = getStaticMethod("deleteMessage", "(II)V");
|
||||||
@ -116,6 +121,7 @@ void GeckoAppShell::InitStubs(JNIEnv *jEnv) {
|
|||||||
jEnableScreenOrientationNotifications = getStaticMethod("enableScreenOrientationNotifications", "()V");
|
jEnableScreenOrientationNotifications = getStaticMethod("enableScreenOrientationNotifications", "()V");
|
||||||
jEnableSensor = getStaticMethod("enableSensor", "(I)V");
|
jEnableSensor = getStaticMethod("enableSensor", "(I)V");
|
||||||
jGamepadAdded = getStaticMethod("gamepadAdded", "(II)V");
|
jGamepadAdded = getStaticMethod("gamepadAdded", "(II)V");
|
||||||
|
jGetConnection = getStaticMethod("getConnection", "(Ljava/lang/String;)Ljava/net/URLConnection;");
|
||||||
jGetContext = getStaticMethod("getContext", "()Landroid/content/Context;");
|
jGetContext = getStaticMethod("getContext", "()Landroid/content/Context;");
|
||||||
jGetCurrentBatteryInformationWrapper = getStaticMethod("getCurrentBatteryInformation", "()[D");
|
jGetCurrentBatteryInformationWrapper = getStaticMethod("getCurrentBatteryInformation", "()[D");
|
||||||
jGetCurrentNetworkInformationWrapper = getStaticMethod("getCurrentNetworkInformation", "()[D");
|
jGetCurrentNetworkInformationWrapper = getStaticMethod("getCurrentNetworkInformation", "()[D");
|
||||||
@ -295,6 +301,32 @@ void GeckoAppShell::CloseNotification(const nsAString& a0) {
|
|||||||
env->PopLocalFrame(nullptr);
|
env->PopLocalFrame(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
jstring GeckoAppShell::ConnectionGetMimeType(jobject a0) {
|
||||||
|
JNIEnv *env = GetJNIForThread();
|
||||||
|
if (env->PushLocalFrame(2) != 0) {
|
||||||
|
AndroidBridge::HandleUncaughtException(env);
|
||||||
|
MOZ_CRASH("Exception should have caused crash.");
|
||||||
|
}
|
||||||
|
|
||||||
|
jobject temp = env->CallStaticObjectMethod(mGeckoAppShellClass, jConnectionGetMimeType, a0);
|
||||||
|
AndroidBridge::HandleUncaughtException(env);
|
||||||
|
jstring ret = static_cast<jstring>(env->PopLocalFrame(temp));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
jobject GeckoAppShell::CreateInputStream(jobject a0) {
|
||||||
|
JNIEnv *env = GetJNIForThread();
|
||||||
|
if (env->PushLocalFrame(2) != 0) {
|
||||||
|
AndroidBridge::HandleUncaughtException(env);
|
||||||
|
MOZ_CRASH("Exception should have caused crash.");
|
||||||
|
}
|
||||||
|
|
||||||
|
jobject temp = env->CallStaticObjectMethod(mGeckoAppShellClass, jCreateInputStream, a0);
|
||||||
|
AndroidBridge::HandleUncaughtException(env);
|
||||||
|
jobject ret = static_cast<jobject>(env->PopLocalFrame(temp));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
void GeckoAppShell::CreateMessageListWrapper(int64_t a0, int64_t a1, jobjectArray a2, int32_t a3, int32_t a4, bool a5, int32_t a6) {
|
void GeckoAppShell::CreateMessageListWrapper(int64_t a0, int64_t a1, jobjectArray a2, int32_t a3, int32_t a4, bool a5, int32_t a6) {
|
||||||
JNIEnv *env = AndroidBridge::GetJNIEnv();
|
JNIEnv *env = AndroidBridge::GetJNIEnv();
|
||||||
if (env->PushLocalFrame(1) != 0) {
|
if (env->PushLocalFrame(1) != 0) {
|
||||||
@ -478,6 +510,21 @@ void GeckoAppShell::GamepadAdded(int32_t a0, int32_t a1) {
|
|||||||
env->PopLocalFrame(nullptr);
|
env->PopLocalFrame(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
jobject GeckoAppShell::GetConnection(const nsACString& a0) {
|
||||||
|
JNIEnv *env = GetJNIForThread();
|
||||||
|
if (env->PushLocalFrame(2) != 0) {
|
||||||
|
AndroidBridge::HandleUncaughtException(env);
|
||||||
|
MOZ_CRASH("Exception should have caused crash.");
|
||||||
|
}
|
||||||
|
|
||||||
|
jstring j0 = AndroidBridge::NewJavaString(env, a0);
|
||||||
|
|
||||||
|
jobject temp = env->CallStaticObjectMethod(mGeckoAppShellClass, jGetConnection, j0);
|
||||||
|
AndroidBridge::HandleUncaughtException(env);
|
||||||
|
jobject ret = static_cast<jobject>(env->PopLocalFrame(temp));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
jobject GeckoAppShell::GetContext() {
|
jobject GeckoAppShell::GetContext() {
|
||||||
JNIEnv *env = GetJNIForThread();
|
JNIEnv *env = GetJNIForThread();
|
||||||
if (env->PushLocalFrame(1) != 0) {
|
if (env->PushLocalFrame(1) != 0) {
|
||||||
|
@ -27,6 +27,8 @@ public:
|
|||||||
static void ClearMessageList(int32_t a0);
|
static void ClearMessageList(int32_t a0);
|
||||||
static void CloseCamera();
|
static void CloseCamera();
|
||||||
static void CloseNotification(const nsAString& a0);
|
static void CloseNotification(const nsAString& a0);
|
||||||
|
static jstring ConnectionGetMimeType(jobject a0);
|
||||||
|
static jobject CreateInputStream(jobject a0);
|
||||||
static void CreateMessageListWrapper(int64_t a0, int64_t a1, jobjectArray a2, int32_t a3, int32_t a4, bool a5, int32_t a6);
|
static void CreateMessageListWrapper(int64_t a0, int64_t a1, jobjectArray a2, int32_t a3, int32_t a4, bool a5, int32_t a6);
|
||||||
static void CreateShortcut(const nsAString& a0, const nsAString& a1, const nsAString& a2, const nsAString& a3);
|
static void CreateShortcut(const nsAString& a0, const nsAString& a1, const nsAString& a2, const nsAString& a3);
|
||||||
static void DeleteMessageWrapper(int32_t a0, int32_t a1);
|
static void DeleteMessageWrapper(int32_t a0, int32_t a1);
|
||||||
@ -41,6 +43,7 @@ public:
|
|||||||
static void EnableScreenOrientationNotifications();
|
static void EnableScreenOrientationNotifications();
|
||||||
static void EnableSensor(int32_t a0);
|
static void EnableSensor(int32_t a0);
|
||||||
static void GamepadAdded(int32_t a0, int32_t a1);
|
static void GamepadAdded(int32_t a0, int32_t a1);
|
||||||
|
static jobject GetConnection(const nsACString& a0);
|
||||||
static jobject GetContext();
|
static jobject GetContext();
|
||||||
static jdoubleArray GetCurrentBatteryInformationWrapper();
|
static jdoubleArray GetCurrentBatteryInformationWrapper();
|
||||||
static jdoubleArray GetCurrentNetworkInformationWrapper();
|
static jdoubleArray GetCurrentNetworkInformationWrapper();
|
||||||
@ -108,6 +111,8 @@ protected:
|
|||||||
static jmethodID jClearMessageList;
|
static jmethodID jClearMessageList;
|
||||||
static jmethodID jCloseCamera;
|
static jmethodID jCloseCamera;
|
||||||
static jmethodID jCloseNotification;
|
static jmethodID jCloseNotification;
|
||||||
|
static jmethodID jConnectionGetMimeType;
|
||||||
|
static jmethodID jCreateInputStream;
|
||||||
static jmethodID jCreateMessageListWrapper;
|
static jmethodID jCreateMessageListWrapper;
|
||||||
static jmethodID jCreateShortcut;
|
static jmethodID jCreateShortcut;
|
||||||
static jmethodID jDeleteMessageWrapper;
|
static jmethodID jDeleteMessageWrapper;
|
||||||
@ -122,6 +127,7 @@ protected:
|
|||||||
static jmethodID jEnableScreenOrientationNotifications;
|
static jmethodID jEnableScreenOrientationNotifications;
|
||||||
static jmethodID jEnableSensor;
|
static jmethodID jEnableSensor;
|
||||||
static jmethodID jGamepadAdded;
|
static jmethodID jGamepadAdded;
|
||||||
|
static jmethodID jGetConnection;
|
||||||
static jmethodID jGetContext;
|
static jmethodID jGetContext;
|
||||||
static jmethodID jGetCurrentBatteryInformationWrapper;
|
static jmethodID jGetCurrentBatteryInformationWrapper;
|
||||||
static jmethodID jGetCurrentNetworkInformationWrapper;
|
static jmethodID jGetCurrentNetworkInformationWrapper;
|
||||||
|
@ -27,6 +27,7 @@ SOURCES += [
|
|||||||
'GeneratedJNIWrappers.cpp',
|
'GeneratedJNIWrappers.cpp',
|
||||||
'GfxInfo.cpp',
|
'GfxInfo.cpp',
|
||||||
'NativeJSContainer.cpp',
|
'NativeJSContainer.cpp',
|
||||||
|
'nsAndroidProtocolHandler.cpp',
|
||||||
'nsAppShell.cpp',
|
'nsAppShell.cpp',
|
||||||
'nsClipboard.cpp',
|
'nsClipboard.cpp',
|
||||||
'nsDeviceContextAndroid.cpp',
|
'nsDeviceContextAndroid.cpp',
|
||||||
@ -51,6 +52,7 @@ LOCAL_INCLUDES += [
|
|||||||
'/docshell/base',
|
'/docshell/base',
|
||||||
'/dom/base',
|
'/dom/base',
|
||||||
'/dom/system/android',
|
'/dom/system/android',
|
||||||
|
'/netwerk/base/src',
|
||||||
'/netwerk/cache',
|
'/netwerk/cache',
|
||||||
'/widget/android/android',
|
'/widget/android/android',
|
||||||
'/widget/shared',
|
'/widget/shared',
|
||||||
|
170
widget/android/nsAndroidProtocolHandler.cpp
Normal file
170
widget/android/nsAndroidProtocolHandler.cpp
Normal file
@ -0,0 +1,170 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||||
|
/* vim:set ts=4 sw=4 sts=4 et cin: */
|
||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
#include "nsAndroidProtocolHandler.h"
|
||||||
|
#include "nsCOMPtr.h"
|
||||||
|
#include "nsIChannel.h"
|
||||||
|
#include "nsIIOService.h"
|
||||||
|
#include "nsNetUtil.h"
|
||||||
|
#include "android/log.h"
|
||||||
|
#include "nsBaseChannel.h"
|
||||||
|
#include "AndroidBridge.h"
|
||||||
|
#include "GeneratedJNIWrappers.h"
|
||||||
|
|
||||||
|
using namespace mozilla;
|
||||||
|
using namespace mozilla::widget::android;
|
||||||
|
|
||||||
|
class AndroidInputStream : public nsIInputStream
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
AndroidInputStream(jobject connection) {
|
||||||
|
JNIEnv *env = GetJNIForThread();
|
||||||
|
mBridgeInputStream = env->NewGlobalRef(GeckoAppShell::CreateInputStream(connection));
|
||||||
|
mBridgeChannel = env->NewGlobalRef(AndroidBridge::ChannelCreate(mBridgeInputStream));
|
||||||
|
}
|
||||||
|
virtual ~AndroidInputStream() {
|
||||||
|
JNIEnv *env = GetJNIForThread();
|
||||||
|
env->DeleteGlobalRef(mBridgeInputStream);
|
||||||
|
env->DeleteGlobalRef(mBridgeChannel);
|
||||||
|
}
|
||||||
|
NS_DECL_THREADSAFE_ISUPPORTS
|
||||||
|
NS_DECL_NSIINPUTSTREAM
|
||||||
|
|
||||||
|
private:
|
||||||
|
jobject mBridgeInputStream;
|
||||||
|
jobject mBridgeChannel;
|
||||||
|
};
|
||||||
|
|
||||||
|
NS_IMPL_ISUPPORTS(AndroidInputStream, nsIInputStream)
|
||||||
|
|
||||||
|
NS_IMETHODIMP AndroidInputStream::Close(void) {
|
||||||
|
mozilla::AndroidBridge::InputStreamClose(mBridgeInputStream);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP AndroidInputStream::Available(uint64_t *_retval) {
|
||||||
|
*_retval = mozilla::AndroidBridge::InputStreamAvailable(mBridgeInputStream);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP AndroidInputStream::Read(char *aBuf, uint32_t aCount, uint32_t *_retval) {
|
||||||
|
return mozilla::AndroidBridge::InputStreamRead(mBridgeChannel, aBuf, aCount, _retval);
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP AndroidInputStream::ReadSegments(nsWriteSegmentFun aWriter, void *aClosure, uint32_t aCount, uint32_t *_retval) {
|
||||||
|
return NS_ERROR_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP AndroidInputStream::IsNonBlocking(bool *_retval) {
|
||||||
|
*_retval = false;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class AndroidChannel : public nsBaseChannel
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
AndroidChannel(nsIURI *aURI, jobject aConnection) {
|
||||||
|
JNIEnv *env = GetJNIForThread();
|
||||||
|
mConnection = env->NewGlobalRef(aConnection);
|
||||||
|
mURI = aURI;
|
||||||
|
nsCString type;
|
||||||
|
jstring jtype = GeckoAppShell::ConnectionGetMimeType(mConnection);
|
||||||
|
if (jtype)
|
||||||
|
SetContentType(nsJNICString(jtype, env));
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
static AndroidChannel* CreateChannel(nsIURI *aURI) {
|
||||||
|
nsCString spec;
|
||||||
|
aURI->GetSpec(spec);
|
||||||
|
jobject connection = GeckoAppShell::GetConnection(spec);
|
||||||
|
if (!connection)
|
||||||
|
return NULL;
|
||||||
|
return new AndroidChannel(aURI, connection);
|
||||||
|
}
|
||||||
|
~AndroidChannel() {
|
||||||
|
JNIEnv *env = GetJNIForThread();
|
||||||
|
env->DeleteGlobalRef(mConnection);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual nsresult OpenContentStream(bool async, nsIInputStream **result,
|
||||||
|
nsIChannel** channel) {
|
||||||
|
nsCOMPtr<nsIInputStream> stream = new AndroidInputStream(mConnection);
|
||||||
|
NS_ADDREF(*result = stream);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
jobject mConnection;
|
||||||
|
};
|
||||||
|
|
||||||
|
NS_IMPL_ISUPPORTS(nsAndroidProtocolHandler,
|
||||||
|
nsIProtocolHandler,
|
||||||
|
nsISupportsWeakReference)
|
||||||
|
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsAndroidProtocolHandler::GetScheme(nsACString &result)
|
||||||
|
{
|
||||||
|
result.AssignLiteral("android");
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsAndroidProtocolHandler::GetDefaultPort(int32_t *result)
|
||||||
|
{
|
||||||
|
*result = -1; // no port for android: URLs
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsAndroidProtocolHandler::AllowPort(int32_t port, const char *scheme, bool *_retval)
|
||||||
|
{
|
||||||
|
// don't override anything.
|
||||||
|
*_retval = false;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsAndroidProtocolHandler::GetProtocolFlags(uint32_t *result)
|
||||||
|
{
|
||||||
|
*result = URI_STD | URI_IS_UI_RESOURCE | URI_IS_LOCAL_RESOURCE | URI_NORELATIVE | URI_DANGEROUS_TO_LOAD;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsAndroidProtocolHandler::NewURI(const nsACString &aSpec,
|
||||||
|
const char *aCharset,
|
||||||
|
nsIURI *aBaseURI,
|
||||||
|
nsIURI **result)
|
||||||
|
{
|
||||||
|
nsresult rv;
|
||||||
|
|
||||||
|
nsCOMPtr<nsIStandardURL> surl(do_CreateInstance(NS_STANDARDURL_CONTRACTID, &rv));
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
rv = surl->Init(nsIStandardURL::URLTYPE_STANDARD, -1, aSpec, aCharset, aBaseURI);
|
||||||
|
if (NS_FAILED(rv))
|
||||||
|
return rv;
|
||||||
|
|
||||||
|
nsCOMPtr<nsIURL> url(do_QueryInterface(surl, &rv));
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
surl->SetMutable(false);
|
||||||
|
|
||||||
|
NS_ADDREF(*result = url);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsAndroidProtocolHandler::NewChannel(nsIURI* aURI,
|
||||||
|
nsIChannel* *aResult)
|
||||||
|
{
|
||||||
|
nsCOMPtr<nsIChannel> channel = AndroidChannel::CreateChannel(aURI);
|
||||||
|
if (!channel)
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
NS_ADDREF(*aResult = channel);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
35
widget/android/nsAndroidProtocolHandler.h
Normal file
35
widget/android/nsAndroidProtocolHandler.h
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
#ifndef nsAndroidProtocolHandler_h___
|
||||||
|
#define nsAndroidProtocolHandler_h___
|
||||||
|
|
||||||
|
#include "nsIProtocolHandler.h"
|
||||||
|
#include "nsWeakReference.h"
|
||||||
|
#include "mozilla/Attributes.h"
|
||||||
|
|
||||||
|
#define NS_ANDROIDPROTOCOLHANDLER_CID \
|
||||||
|
{ /* e9cd2b7f-8386-441b-aaf5-0b371846bfd0 */ \
|
||||||
|
0xe9cd2b7f, \
|
||||||
|
0x8386, \
|
||||||
|
0x441b, \
|
||||||
|
{0x0b, 0x37, 0x18, 0x46, 0xbf, 0xd0} \
|
||||||
|
}
|
||||||
|
|
||||||
|
class nsAndroidProtocolHandler MOZ_FINAL : public nsIProtocolHandler,
|
||||||
|
public nsSupportsWeakReference
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NS_DECL_THREADSAFE_ISUPPORTS
|
||||||
|
|
||||||
|
// nsIProtocolHandler methods:
|
||||||
|
NS_DECL_NSIPROTOCOLHANDLER
|
||||||
|
|
||||||
|
// nsAndroidProtocolHandler methods:
|
||||||
|
nsAndroidProtocolHandler() {}
|
||||||
|
~nsAndroidProtocolHandler() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* nsAndroidProtocolHandler_h___ */
|
@ -25,6 +25,7 @@
|
|||||||
#include "nsHTMLFormatConverter.h"
|
#include "nsHTMLFormatConverter.h"
|
||||||
#include "nsIMEPicker.h"
|
#include "nsIMEPicker.h"
|
||||||
#include "nsXULAppAPI.h"
|
#include "nsXULAppAPI.h"
|
||||||
|
#include "nsAndroidProtocolHandler.h"
|
||||||
|
|
||||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsWindow)
|
NS_GENERIC_FACTORY_CONSTRUCTOR(nsWindow)
|
||||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsScreenManagerAndroid)
|
NS_GENERIC_FACTORY_CONSTRUCTOR(nsScreenManagerAndroid)
|
||||||
@ -38,6 +39,7 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsDeviceContextSpecAndroid)
|
|||||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsHTMLFormatConverter)
|
NS_GENERIC_FACTORY_CONSTRUCTOR(nsHTMLFormatConverter)
|
||||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsIMEPicker)
|
NS_GENERIC_FACTORY_CONSTRUCTOR(nsIMEPicker)
|
||||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsAndroidBridge)
|
NS_GENERIC_FACTORY_CONSTRUCTOR(nsAndroidBridge)
|
||||||
|
NS_GENERIC_FACTORY_CONSTRUCTOR(nsAndroidProtocolHandler)
|
||||||
|
|
||||||
#include "GfxInfo.h"
|
#include "GfxInfo.h"
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
@ -62,6 +64,7 @@ NS_DEFINE_NAMED_CID(NS_HTMLFORMATCONVERTER_CID);
|
|||||||
NS_DEFINE_NAMED_CID(NS_IMEPICKER_CID);
|
NS_DEFINE_NAMED_CID(NS_IMEPICKER_CID);
|
||||||
NS_DEFINE_NAMED_CID(NS_GFXINFO_CID);
|
NS_DEFINE_NAMED_CID(NS_GFXINFO_CID);
|
||||||
NS_DEFINE_NAMED_CID(NS_ANDROIDBRIDGE_CID);
|
NS_DEFINE_NAMED_CID(NS_ANDROIDBRIDGE_CID);
|
||||||
|
NS_DEFINE_NAMED_CID(NS_ANDROIDPROTOCOLHANDLER_CID);
|
||||||
|
|
||||||
static const mozilla::Module::CIDEntry kWidgetCIDs[] = {
|
static const mozilla::Module::CIDEntry kWidgetCIDs[] = {
|
||||||
{ &kNS_WINDOW_CID, false, nullptr, nsWindowConstructor },
|
{ &kNS_WINDOW_CID, false, nullptr, nsWindowConstructor },
|
||||||
@ -79,6 +82,7 @@ static const mozilla::Module::CIDEntry kWidgetCIDs[] = {
|
|||||||
{ &kNS_IMEPICKER_CID, false, nullptr, nsIMEPickerConstructor },
|
{ &kNS_IMEPICKER_CID, false, nullptr, nsIMEPickerConstructor },
|
||||||
{ &kNS_GFXINFO_CID, false, nullptr, mozilla::widget::GfxInfoConstructor },
|
{ &kNS_GFXINFO_CID, false, nullptr, mozilla::widget::GfxInfoConstructor },
|
||||||
{ &kNS_ANDROIDBRIDGE_CID, false, nullptr, nsAndroidBridgeConstructor },
|
{ &kNS_ANDROIDBRIDGE_CID, false, nullptr, nsAndroidBridgeConstructor },
|
||||||
|
{ &kNS_ANDROIDPROTOCOLHANDLER_CID, false, nullptr, nsAndroidProtocolHandlerConstructor },
|
||||||
{ nullptr }
|
{ nullptr }
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -98,6 +102,7 @@ static const mozilla::Module::ContractIDEntry kWidgetContracts[] = {
|
|||||||
{ "@mozilla.org/imepicker;1", &kNS_IMEPICKER_CID },
|
{ "@mozilla.org/imepicker;1", &kNS_IMEPICKER_CID },
|
||||||
{ "@mozilla.org/gfx/info;1", &kNS_GFXINFO_CID },
|
{ "@mozilla.org/gfx/info;1", &kNS_GFXINFO_CID },
|
||||||
{ "@mozilla.org/android/bridge;1", &kNS_ANDROIDBRIDGE_CID },
|
{ "@mozilla.org/android/bridge;1", &kNS_ANDROIDBRIDGE_CID },
|
||||||
|
{ NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "android", &kNS_ANDROIDPROTOCOLHANDLER_CID },
|
||||||
{ nullptr }
|
{ nullptr }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -259,7 +259,6 @@ HwcComposer2D::PrepareLayerList(Layer* aLayer,
|
|||||||
|
|
||||||
LayerRenderState state = aLayer->GetRenderState();
|
LayerRenderState state = aLayer->GetRenderState();
|
||||||
nsIntSize surfaceSize;
|
nsIntSize surfaceSize;
|
||||||
bool skipLayer = false;
|
|
||||||
|
|
||||||
if (state.mSurface.get()) {
|
if (state.mSurface.get()) {
|
||||||
surfaceSize = state.mSize;
|
surfaceSize = state.mSize;
|
||||||
@ -268,11 +267,7 @@ HwcComposer2D::PrepareLayerList(Layer* aLayer,
|
|||||||
fillColor = true;
|
fillColor = true;
|
||||||
} else {
|
} else {
|
||||||
LOGD("%s Layer doesn't have a gralloc buffer", aLayer->Name());
|
LOGD("%s Layer doesn't have a gralloc buffer", aLayer->Name());
|
||||||
#if ANDROID_VERSION >= 18
|
|
||||||
skipLayer = true;
|
|
||||||
#else
|
|
||||||
return false;
|
return false;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Buffer rotation is not to be confused with the angled rotation done by a transform matrix
|
// Buffer rotation is not to be confused with the angled rotation done by a transform matrix
|
||||||
@ -340,8 +335,8 @@ HwcComposer2D::PrepareLayerList(Layer* aLayer,
|
|||||||
buffer_handle_t handle = fillColor ? nullptr : state.mSurface->getNativeBuffer()->handle;
|
buffer_handle_t handle = fillColor ? nullptr : state.mSurface->getNativeBuffer()->handle;
|
||||||
hwcLayer.handle = handle;
|
hwcLayer.handle = handle;
|
||||||
|
|
||||||
|
hwcLayer.flags = 0;
|
||||||
hwcLayer.hints = 0;
|
hwcLayer.hints = 0;
|
||||||
hwcLayer.flags = skipLayer ? HWC_SKIP_LAYER : 0;
|
|
||||||
hwcLayer.blending = isOpaque ? HWC_BLENDING_NONE : HWC_BLENDING_PREMULT;
|
hwcLayer.blending = isOpaque ? HWC_BLENDING_NONE : HWC_BLENDING_PREMULT;
|
||||||
#if ANDROID_VERSION >= 17
|
#if ANDROID_VERSION >= 17
|
||||||
hwcLayer.compositionType = HWC_FRAMEBUFFER;
|
hwcLayer.compositionType = HWC_FRAMEBUFFER;
|
||||||
|
Loading…
Reference in New Issue
Block a user