forked from mirrors/gecko-dev
Merge mozilla-central to autoland
This commit is contained in:
commit
39d63fc827
190 changed files with 3059 additions and 1588 deletions
|
|
@ -318,8 +318,8 @@
|
||||||
];
|
];
|
||||||
|
|
||||||
this.invoke = function insertReferredElm_invoke() {
|
this.invoke = function insertReferredElm_invoke() {
|
||||||
this.containerNode.innerHTML =
|
this.containerNode.unsafeSetInnerHTML(
|
||||||
"<span id='insertReferredElms_span'></span><input aria-labelledby='insertReferredElms_span'>";
|
"<span id='insertReferredElms_span'></span><input aria-labelledby='insertReferredElms_span'>");
|
||||||
};
|
};
|
||||||
|
|
||||||
this.getID = function insertReferredElm_getID() {
|
this.getID = function insertReferredElm_getID() {
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,6 @@
|
||||||
<?xml version='1.0' encoding='UTF-8'?>
|
<?xml version='1.0' encoding='UTF-8'?>
|
||||||
<blocklist lastupdate="1500496563565" xmlns="http://www.mozilla.org/2006/addons-blocklist">
|
<blocklist lastupdate="1500496563565" xmlns="http://www.mozilla.org/2006/addons-blocklist">
|
||||||
<emItems>
|
<emItems>
|
||||||
<emItem blockID="i988" id="{b12785f5-d8d0-4530-a3ea-5c4263b85bef}">
|
|
||||||
<prefs/>
|
|
||||||
<versionRange minVersion="0" maxVersion="*" severity="1"/>
|
|
||||||
</emItem>
|
|
||||||
<emItem blockID="i398" id="{377e5d4d-77e5-476a-8716-7e70a9272da0}">
|
|
||||||
<prefs/>
|
|
||||||
<versionRange minVersion="0" maxVersion="*" severity="1"/>
|
|
||||||
</emItem>
|
|
||||||
<emItem blockID="i698" id="{6b2a75c8-6e2e-4267-b955-43e25b54e575}">
|
|
||||||
<prefs/>
|
|
||||||
<versionRange minVersion="0" maxVersion="*" severity="1"/>
|
|
||||||
</emItem>
|
|
||||||
<emItem blockID="i1231" id="youtube@downloader.yt">
|
<emItem blockID="i1231" id="youtube@downloader.yt">
|
||||||
<prefs/>
|
<prefs/>
|
||||||
<versionRange minVersion="0" maxVersion="*" severity="3"/>
|
<versionRange minVersion="0" maxVersion="*" severity="3"/>
|
||||||
|
|
@ -137,6 +125,10 @@
|
||||||
<prefs/>
|
<prefs/>
|
||||||
<versionRange minVersion="0" maxVersion="*" severity="1"/>
|
<versionRange minVersion="0" maxVersion="*" severity="1"/>
|
||||||
</emItem>
|
</emItem>
|
||||||
|
<emItem blockID="2d4fe65b-6c02-4461-baa8-dda52e688cf6" id="/^({618baeb9-e694-4c7b-9328-69f35b6a8839}|{b91fcda4-88b0-4a10-9015-9365e5340563}|{04150f98-2d7c-4ae2-8979-f5baa198a577}|{4b1050c6-9139-4126-9331-30a836e75db9}|{1e6f5a54-2c4f-4597-aa9e-3e278c617d38}|{e73854da-9503-423b-ab27-fafea2fbf443}|{a2427e23-d349-4b25-b5b8-46960b218079}|{f92c1155-97b3-40f4-9d5b-7efa897524bb}|{c8e14311-4b2d-4eb0-9a6b-062c6912f50e}|{45621564-b408-4c29-8515-4cf1f26e4bc3}|{27380afd-f42a-4c25-b57d-b9012e0d5d48})$/">
|
||||||
|
<prefs/>
|
||||||
|
<versionRange minVersion="0" maxVersion="*" severity="3"/>
|
||||||
|
</emItem>
|
||||||
<emItem blockID="i524" id="/^({4e988b08-8c51-45c1-8d74-73e0c8724579}|{93ec97bf-fe43-4bca-a735-5c5d6a0a40c4}|{aed63b38-7428-4003-a052-ca6834d8bad3}|{0b5130a9-cc50-4ced-99d5-cda8cc12ae48}|{C4CFC0DE-134F-4466-B2A2-FF7C59A8BFAD})$/">
|
<emItem blockID="i524" id="/^({4e988b08-8c51-45c1-8d74-73e0c8724579}|{93ec97bf-fe43-4bca-a735-5c5d6a0a40c4}|{aed63b38-7428-4003-a052-ca6834d8bad3}|{0b5130a9-cc50-4ced-99d5-cda8cc12ae48}|{C4CFC0DE-134F-4466-B2A2-FF7C59A8BFAD})$/">
|
||||||
<prefs/>
|
<prefs/>
|
||||||
<versionRange minVersion="0" maxVersion="*" severity="1"/>
|
<versionRange minVersion="0" maxVersion="*" severity="1"/>
|
||||||
|
|
@ -526,6 +518,10 @@
|
||||||
<prefs/>
|
<prefs/>
|
||||||
<versionRange minVersion="0" maxVersion="2.0.6" severity="1"/>
|
<versionRange minVersion="0" maxVersion="2.0.6" severity="1"/>
|
||||||
</emItem>
|
</emItem>
|
||||||
|
<emItem blockID="750aa293-3742-46b5-8761-51536afecaef" id="/^({30972e0a-f613-4c46-8c87-2e59878e7180}|{0599211f-6314-4bf9-854b-84cb18da97f8}|{4414af84-1e1f-449b-ac85-b79f812eb69b}|{2a8bec00-0ab0-4b4d-bd3d-4f59eada8fd8}|{bea8866f-01f8-49e9-92cd-61e96c05d288}|{046258c9-75c5-429d-8d5b-386cfbadc39d}|{c5d359ff-ae01-4f67-a4f7-bf234b5afd6e}|{fdc0601f-1fbb-40a5-84e1-8bbe96b22502}|{85349ea6-2b5d-496a-9379-d4be82c2c13d}|{640c40e5-a881-4d16-a4d0-6aa788399dd2}|{d42328e1-9749-46ba-b35c-cce85ddd4ace})$/">
|
||||||
|
<prefs/>
|
||||||
|
<versionRange minVersion="0" maxVersion="*" severity="3"/>
|
||||||
|
</emItem>
|
||||||
<emItem blockID="i768" id="{f2548724-373f-45fe-be6a-3a85e87b7711}">
|
<emItem blockID="i768" id="{f2548724-373f-45fe-be6a-3a85e87b7711}">
|
||||||
<prefs>
|
<prefs>
|
||||||
<pref>browser.startup.homepage</pref>
|
<pref>browser.startup.homepage</pref>
|
||||||
|
|
@ -722,6 +718,10 @@
|
||||||
<prefs/>
|
<prefs/>
|
||||||
<versionRange minVersion="2.2" maxVersion="2.2" severity="1"/>
|
<versionRange minVersion="2.2" maxVersion="2.2" severity="1"/>
|
||||||
</emItem>
|
</emItem>
|
||||||
|
<emItem blockID="9a3fd797-0ab8-4286-9a1b-2b6c97f9075b" id="/^({4dac7c77-e117-4cae-a9f0-6bd89e9e26ab}|{cc689da4-203f-4a0c-a7a6-a00a5abe74c5}|{0eb4672d-58a6-4230-b74c-50ca3716c4b0}|{06a71249-ef35-4f61-b2c8-85c3c6ee5617}|{5280684d-f769-43c9-8eaa-fb04f7de9199}|{c2341a34-a3a0-4234-90cf-74df1db0aa49}|{85e31e7e-3e3a-42d3-9b7b-0a2ff1818b33}|{b5a35d05-fa28-41b5-ae22-db1665f93f6b}|{1bd8ba17-b3ed-412e-88db-35bc4d8771d7}|{a18087bb-4980-4349-898c-ca1b7a0e59cd}|{488e190b-d1f6-4de8-bffb-0c90cc805b62})$/">
|
||||||
|
<prefs/>
|
||||||
|
<versionRange minVersion="0" maxVersion="*" severity="3"/>
|
||||||
|
</emItem>
|
||||||
<emItem blockID="i109" id="{392e123b-b691-4a5e-b52f-c4c1027e749c}">
|
<emItem blockID="i109" id="{392e123b-b691-4a5e-b52f-c4c1027e749c}">
|
||||||
<prefs/>
|
<prefs/>
|
||||||
<versionRange minVersion="0" maxVersion="*" severity="3"/>
|
<versionRange minVersion="0" maxVersion="*" severity="3"/>
|
||||||
|
|
@ -1246,6 +1246,10 @@
|
||||||
<prefs/>
|
<prefs/>
|
||||||
<versionRange minVersion="0" maxVersion="*" severity="3"/>
|
<versionRange minVersion="0" maxVersion="*" severity="3"/>
|
||||||
</emItem>
|
</emItem>
|
||||||
|
<emItem blockID="5c092b0d-7205-43a1-aa75-b7a42372fb52" id="/^({2bb68b03-b528-4133-9fc4-4980fbb4e449}|{231e58ac-0f3c-460b-bb08-0e589360bec7}|{a506c5af-0f95-4107-86f8-3de05e2794c9}|{8886a262-1c25-490b-b797-2e750dd9f36b}|{65072bef-041f-492e-8a51-acca2aaeac70}|{6fa41039-572b-44a4-acd4-01fdaebf608d}|{87ba49bd-daba-4071-aedf-4f32a7e63dbe}|{95d58338-ba6a-40c8-93fd-05a34731dc0e}|{4cbef3f0-4205-4165-8871-2844f9737602}|{1855d130-4893-4c79-b4aa-cbdf6fee86d3}|{87dcb9bf-3a3e-4b93-9c85-ba750a55831a})$/">
|
||||||
|
<prefs/>
|
||||||
|
<versionRange minVersion="0" maxVersion="*" severity="3"/>
|
||||||
|
</emItem>
|
||||||
<emItem blockID="8088b39a-3e6d-4a17-a22f-3f95c0464bd6" id="{5b0f6d3c-10fd-414c-a135-dffd26d7de0f}">
|
<emItem blockID="8088b39a-3e6d-4a17-a22f-3f95c0464bd6" id="{5b0f6d3c-10fd-414c-a135-dffd26d7de0f}">
|
||||||
<prefs/>
|
<prefs/>
|
||||||
<versionRange minVersion="0" maxVersion="*" severity="3"/>
|
<versionRange minVersion="0" maxVersion="*" severity="3"/>
|
||||||
|
|
@ -1398,6 +1402,10 @@
|
||||||
<prefs/>
|
<prefs/>
|
||||||
<versionRange minVersion="0" maxVersion="*" severity="1"/>
|
<versionRange minVersion="0" maxVersion="*" severity="1"/>
|
||||||
</emItem>
|
</emItem>
|
||||||
|
<emItem blockID="aae78cd5-6b26-472e-ab2d-db4105911250" id="/^({f6df4ef7-14bd-43b5-90c9-7bd02943789c}|{ccb7b5d6-a567-40a2-9686-a097a8b583dd}|{9b8df895-fcdd-452a-8c46-da5be345b5bc}|{5cf77367-b141-4ba4-ac2a-5b2ca3728e81}|{ada56fe6-f6df-4517-9ed0-b301686a34cc}|{95c7ae97-c87e-4827-a2b7-7b9934d7d642}|{e7b978ae-ffc2-4998-a99d-0f4e2f24da82}|{115a8321-4414-4f4c-aee6-9f812121b446}|{bf153de7-cdf2-4554-af46-29dabfb2aa2d}|{179710ba-0561-4551-8e8d-1809422cb09f}|{9d592fd5-e655-461a-9b28-9eba85d4c97f})$/">
|
||||||
|
<prefs/>
|
||||||
|
<versionRange minVersion="0" maxVersion="*" severity="3"/>
|
||||||
|
</emItem>
|
||||||
<emItem blockID="i77" id="{fa277cfc-1d75-4949-a1f9-4ac8e41b2dfd}">
|
<emItem blockID="i77" id="{fa277cfc-1d75-4949-a1f9-4ac8e41b2dfd}">
|
||||||
<prefs/>
|
<prefs/>
|
||||||
<versionRange minVersion="0" maxVersion="*" severity="3"/>
|
<versionRange minVersion="0" maxVersion="*" severity="3"/>
|
||||||
|
|
@ -1681,6 +1689,10 @@
|
||||||
<prefs/>
|
<prefs/>
|
||||||
<versionRange minVersion="0" maxVersion="*" severity="1"/>
|
<versionRange minVersion="0" maxVersion="*" severity="1"/>
|
||||||
</emItem>
|
</emItem>
|
||||||
|
<emItem blockID="c92f2a05-73eb-454e-9583-f6d2382d8bca" id="/^({abec23c3-478f-4a5b-8a38-68ccd500ec42}|{a83c1cbb-7a41-41e7-a2ae-58efcb4dc2e4}|{62237447-e365-487e-8fc3-64ddf37bdaed}|{b12cfdc7-3c69-43cb-a3fb-38981b68a087}|{1a927d5b-42e7-4407-828a-fdc441d0daae}|{dd1cb0ec-be2a-432b-9c90-d64c824ac371}|{82c8ced2-e08c-4d6c-a12b-3e8227d7fc2a}|{87c552f9-7dbb-421b-8deb-571d4a2d7a21})$/">
|
||||||
|
<prefs/>
|
||||||
|
<versionRange minVersion="0" maxVersion="*" severity="3"/>
|
||||||
|
</emItem>
|
||||||
<emItem blockID="595e0e53-b76b-4188-a160-66f29c636094" id="@68eba425-7a05-4d62-82b1-1d6d5a51716b">
|
<emItem blockID="595e0e53-b76b-4188-a160-66f29c636094" id="@68eba425-7a05-4d62-82b1-1d6d5a51716b">
|
||||||
<prefs/>
|
<prefs/>
|
||||||
<versionRange minVersion="0" maxVersion="*" severity="1"/>
|
<versionRange minVersion="0" maxVersion="*" severity="1"/>
|
||||||
|
|
@ -2024,6 +2036,10 @@
|
||||||
<prefs/>
|
<prefs/>
|
||||||
<versionRange minVersion="0" maxVersion="*" severity="3"/>
|
<versionRange minVersion="0" maxVersion="*" severity="3"/>
|
||||||
</emItem>
|
</emItem>
|
||||||
|
<emItem blockID="a29aed6f-6546-4fa2-8131-df5c9a5427af" id="/^({d03b6b0f-4d44-4666-a6d6-f16ad9483593}|{767d394a-aa77-40c9-9365-c1916b4a2f84}|{a0ce2605-b5fc-4265-aa65-863354e85058}|{b7f366fa-6c66-46bf-8df2-797c5e52859f}|{4ad16913-e5cb-4292-974c-d557ef5ec5bb}|{3c3ef2a3-0440-4e77-9e3c-1ca8d48f895c}|{543f7503-3620-4f41-8f9e-c258fdff07e9}|{98363f8b-d070-47b6-acc6-65b80acac4f3}|{5af74f5a-652b-4b83-a2a9-f3d21c3c0010}|{484e0ba4-a20b-4404-bb1b-b93473782ae0}|{b99847d6-c932-4b52-9650-af83c9dae649})$/">
|
||||||
|
<prefs/>
|
||||||
|
<versionRange minVersion="0" maxVersion="*" severity="3"/>
|
||||||
|
</emItem>
|
||||||
<emItem blockID="i656" id="hdv@vovcacik.addons.mozilla.org">
|
<emItem blockID="i656" id="hdv@vovcacik.addons.mozilla.org">
|
||||||
<prefs/>
|
<prefs/>
|
||||||
<versionRange minVersion="102.0" maxVersion="102.0" severity="3"/>
|
<versionRange minVersion="102.0" maxVersion="102.0" severity="3"/>
|
||||||
|
|
@ -2171,6 +2187,18 @@
|
||||||
</targetApplication>
|
</targetApplication>
|
||||||
</versionRange>
|
</versionRange>
|
||||||
</emItem>
|
</emItem>
|
||||||
|
<emItem blockID="i988" id="{b12785f5-d8d0-4530-a3ea-5c4263b85bef}">
|
||||||
|
<prefs/>
|
||||||
|
<versionRange minVersion="0" maxVersion="*" severity="1"/>
|
||||||
|
</emItem>
|
||||||
|
<emItem blockID="i398" id="{377e5d4d-77e5-476a-8716-7e70a9272da0}">
|
||||||
|
<prefs/>
|
||||||
|
<versionRange minVersion="0" maxVersion="*" severity="1"/>
|
||||||
|
</emItem>
|
||||||
|
<emItem blockID="i698" id="{6b2a75c8-6e2e-4267-b955-43e25b54e575}">
|
||||||
|
<prefs/>
|
||||||
|
<versionRange minVersion="0" maxVersion="*" severity="1"/>
|
||||||
|
</emItem>
|
||||||
</emItems>
|
</emItems>
|
||||||
<pluginItems>
|
<pluginItems>
|
||||||
<pluginItem blockID="p416">
|
<pluginItem blockID="p416">
|
||||||
|
|
@ -2282,7 +2310,7 @@
|
||||||
<versionRange maxVersion="*" minVersion="0"/>
|
<versionRange maxVersion="*" minVersion="0"/>
|
||||||
</pluginItem>
|
</pluginItem>
|
||||||
<pluginItem blockID="33147281-45b2-487e-9fea-f66c6517252d">
|
<pluginItem blockID="33147281-45b2-487e-9fea-f66c6517252d">
|
||||||
<match exp="Java\(TM\) Platform SE 8 U(7[6-9]|[8-9]\d|1([0-3]\d|40))(\s[^\d\._U]|$)" name="name"/>
|
<match exp="Java\(TM\) Platform SE 8 U(7[6-9]|[8-9]\d|1([0-5]\d|60))(\s[^\d\._U]|$)" name="name"/>
|
||||||
<match exp="npjp2\.dll" name="filename"/>
|
<match exp="npjp2\.dll" name="filename"/>
|
||||||
<infoURL>https://java.com/</infoURL>
|
<infoURL>https://java.com/</infoURL>
|
||||||
<versionRange severity="0" vulnerabilitystatus="1"/>
|
<versionRange severity="0" vulnerabilitystatus="1"/>
|
||||||
|
|
@ -2624,7 +2652,7 @@
|
||||||
<versionRange severity="0" vulnerabilitystatus="1"/>
|
<versionRange severity="0" vulnerabilitystatus="1"/>
|
||||||
</pluginItem>
|
</pluginItem>
|
||||||
<pluginItem blockID="ab59635e-2e93-423a-9d57-871dde8ae675">
|
<pluginItem blockID="ab59635e-2e93-423a-9d57-871dde8ae675">
|
||||||
<match exp="Java(\(TM\))? Plug-in 11\.(7[6-9]|[8-9]\d|1([0-3]\d|40))(\.\d+)?([^\d\._]|$)" name="name"/>
|
<match exp="Java(\(TM\))? Plug-in 11\.(7[6-9]|[8-9]\d|1([0-5]\d|60))(\.\d+)?([^\d\._]|$)" name="name"/>
|
||||||
<match exp="libnpjp2\.so" name="filename"/>
|
<match exp="libnpjp2\.so" name="filename"/>
|
||||||
<infoURL>https://java.com/</infoURL>
|
<infoURL>https://java.com/</infoURL>
|
||||||
<versionRange severity="0" vulnerabilitystatus="1"/>
|
<versionRange severity="0" vulnerabilitystatus="1"/>
|
||||||
|
|
@ -2884,7 +2912,7 @@
|
||||||
<pluginItem blockID="f24ffd6f-e02b-4cf4-91d9-d54cd793e4bf">
|
<pluginItem blockID="f24ffd6f-e02b-4cf4-91d9-d54cd793e4bf">
|
||||||
<match exp="JavaAppletPlugin\.plugin" name="filename"/>
|
<match exp="JavaAppletPlugin\.plugin" name="filename"/>
|
||||||
<infoURL>https://java.com/</infoURL>
|
<infoURL>https://java.com/</infoURL>
|
||||||
<versionRange maxVersion="Java 8 Update 140" minVersion="Java 8 Update" severity="0" vulnerabilitystatus="1"/>
|
<versionRange maxVersion="Java 8 Update 160" minVersion="Java 8 Update" severity="0" vulnerabilitystatus="1"/>
|
||||||
</pluginItem>
|
</pluginItem>
|
||||||
<pluginItem blockID="p906">
|
<pluginItem blockID="p906">
|
||||||
<match exp="Java\(TM\) Platform SE 7 U(4[5-9]|(5|6)\d|7[0-8])(\s[^\d\._U]|$)" name="name"/>
|
<match exp="Java\(TM\) Platform SE 7 U(4[5-9]|(5|6)\d|7[0-8])(\s[^\d\._U]|$)" name="name"/>
|
||||||
|
|
|
||||||
|
|
@ -136,7 +136,6 @@ var BrowserPageActions = {
|
||||||
if (action.subview) {
|
if (action.subview) {
|
||||||
buttonNode.classList.add("subviewbutton-nav");
|
buttonNode.classList.add("subviewbutton-nav");
|
||||||
panelViewNode = this._makePanelViewNodeForAction(action, false);
|
panelViewNode = this._makePanelViewNodeForAction(action, false);
|
||||||
this.multiViewNode._panelViews = null;
|
|
||||||
this.multiViewNode.appendChild(panelViewNode);
|
this.multiViewNode.appendChild(panelViewNode);
|
||||||
}
|
}
|
||||||
buttonNode.addEventListener("command", event => {
|
buttonNode.addEventListener("command", event => {
|
||||||
|
|
@ -236,6 +235,7 @@ var BrowserPageActions = {
|
||||||
if (action.subview) {
|
if (action.subview) {
|
||||||
let multiViewNode = document.createElement("panelmultiview");
|
let multiViewNode = document.createElement("panelmultiview");
|
||||||
panelViewNode = this._makePanelViewNodeForAction(action, true);
|
panelViewNode = this._makePanelViewNodeForAction(action, true);
|
||||||
|
multiViewNode.setAttribute("mainViewId", panelViewNode.id);
|
||||||
multiViewNode.appendChild(panelViewNode);
|
multiViewNode.appendChild(panelViewNode);
|
||||||
panelNode.appendChild(multiViewNode);
|
panelNode.appendChild(multiViewNode);
|
||||||
} else if (action.wantsIframe) {
|
} else if (action.wantsIframe) {
|
||||||
|
|
@ -291,11 +291,15 @@ var BrowserPageActions = {
|
||||||
*
|
*
|
||||||
* @param action (PageActions.Action, optional)
|
* @param action (PageActions.Action, optional)
|
||||||
* The action you want to anchor.
|
* The action you want to anchor.
|
||||||
|
* @param event (DOM event, optional)
|
||||||
|
* This is used to display the feedback panel on the right node when
|
||||||
|
* the command can be invoked from both the main panel and another
|
||||||
|
* location, such as an activated action panel or a button.
|
||||||
* @return (DOM node, nonnull) The node to which the action should be
|
* @return (DOM node, nonnull) The node to which the action should be
|
||||||
* anchored.
|
* anchored.
|
||||||
*/
|
*/
|
||||||
panelAnchorNodeForAction(action, event) {
|
panelAnchorNodeForAction(action, event) {
|
||||||
if (event && event.target.closest("panel")) {
|
if (event && event.target.closest("panel") == this.panelNode) {
|
||||||
return this.mainButtonNode;
|
return this.mainButtonNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,7 @@ XPCOMUtils.defineLazyModuleGetters(this, {
|
||||||
NewTabUtils: "resource://gre/modules/NewTabUtils.jsm",
|
NewTabUtils: "resource://gre/modules/NewTabUtils.jsm",
|
||||||
PageActions: "resource:///modules/PageActions.jsm",
|
PageActions: "resource:///modules/PageActions.jsm",
|
||||||
PageThumbs: "resource://gre/modules/PageThumbs.jsm",
|
PageThumbs: "resource://gre/modules/PageThumbs.jsm",
|
||||||
|
PanelView: "resource:///modules/PanelMultiView.jsm",
|
||||||
PluralForm: "resource://gre/modules/PluralForm.jsm",
|
PluralForm: "resource://gre/modules/PluralForm.jsm",
|
||||||
PrivateBrowsingUtils: "resource://gre/modules/PrivateBrowsingUtils.jsm",
|
PrivateBrowsingUtils: "resource://gre/modules/PrivateBrowsingUtils.jsm",
|
||||||
ProcessHangMonitor: "resource:///modules/ProcessHangMonitor.jsm",
|
ProcessHangMonitor: "resource:///modules/ProcessHangMonitor.jsm",
|
||||||
|
|
@ -7144,21 +7145,19 @@ var gIdentityHandler = {
|
||||||
delete this._identityPopupMultiView;
|
delete this._identityPopupMultiView;
|
||||||
return this._identityPopupMultiView = document.getElementById("identity-popup-multiView");
|
return this._identityPopupMultiView = document.getElementById("identity-popup-multiView");
|
||||||
},
|
},
|
||||||
|
get _identityPopupMainView() {
|
||||||
|
delete this._identityPopupMainView;
|
||||||
|
return this._identityPopupMainView = document.getElementById("identity-popup-mainView");
|
||||||
|
},
|
||||||
get _identityPopupContentHosts() {
|
get _identityPopupContentHosts() {
|
||||||
delete this._identityPopupContentHosts;
|
delete this._identityPopupContentHosts;
|
||||||
let selector = ".identity-popup-host";
|
return this._identityPopupContentHosts =
|
||||||
return this._identityPopupContentHosts = [
|
[...document.querySelectorAll(".identity-popup-host")];
|
||||||
...this._identityPopupMultiView._mainView.querySelectorAll(selector),
|
|
||||||
...document.querySelectorAll(selector)
|
|
||||||
];
|
|
||||||
},
|
},
|
||||||
get _identityPopupContentHostless() {
|
get _identityPopupContentHostless() {
|
||||||
delete this._identityPopupContentHostless;
|
delete this._identityPopupContentHostless;
|
||||||
let selector = ".identity-popup-hostless";
|
return this._identityPopupContentHostless =
|
||||||
return this._identityPopupContentHostless = [
|
[...document.querySelectorAll(".identity-popup-hostless")];
|
||||||
...this._identityPopupMultiView._mainView.querySelectorAll(selector),
|
|
||||||
...document.querySelectorAll(selector)
|
|
||||||
];
|
|
||||||
},
|
},
|
||||||
get _identityPopupContentOwner() {
|
get _identityPopupContentOwner() {
|
||||||
delete this._identityPopupContentOwner;
|
delete this._identityPopupContentOwner;
|
||||||
|
|
@ -7400,7 +7399,8 @@ var gIdentityHandler = {
|
||||||
|
|
||||||
if (this._identityPopup.state == "open") {
|
if (this._identityPopup.state == "open") {
|
||||||
this.updateSitePermissions();
|
this.updateSitePermissions();
|
||||||
this._identityPopupMultiView.descriptionHeightWorkaround();
|
PanelView.forNode(this._identityPopupMainView)
|
||||||
|
.descriptionHeightWorkaround();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -8056,7 +8056,8 @@ var gIdentityHandler = {
|
||||||
SitePermissions.remove(gBrowser.currentURI, aPermission.id, browser);
|
SitePermissions.remove(gBrowser.currentURI, aPermission.id, browser);
|
||||||
|
|
||||||
this._permissionReloadHint.removeAttribute("hidden");
|
this._permissionReloadHint.removeAttribute("hidden");
|
||||||
this._identityPopupMultiView.descriptionHeightWorkaround();
|
PanelView.forNode(this._identityPopupMainView)
|
||||||
|
.descriptionHeightWorkaround();
|
||||||
|
|
||||||
// Set telemetry values for clearing a permission
|
// Set telemetry values for clearing a permission
|
||||||
let histogram = Services.telemetry.getKeyedHistogramById("WEB_PERMISSION_CLEARED");
|
let histogram = Services.telemetry.getKeyedHistogramById("WEB_PERMISSION_CLEARED");
|
||||||
|
|
|
||||||
|
|
@ -58,6 +58,7 @@ const EXPECTED_APPMENU_SUBVIEW_REFLOWS = [
|
||||||
{
|
{
|
||||||
stack: [
|
stack: [
|
||||||
"descriptionHeightWorkaround@resource:///modules/PanelMultiView.jsm",
|
"descriptionHeightWorkaround@resource:///modules/PanelMultiView.jsm",
|
||||||
|
"set current@resource:///modules/PanelMultiView.jsm",
|
||||||
"hideAllViewsExcept@resource:///modules/PanelMultiView.jsm",
|
"hideAllViewsExcept@resource:///modules/PanelMultiView.jsm",
|
||||||
],
|
],
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ add_task(async function test_reserved_shortcuts() {
|
||||||
</keyset>`;
|
</keyset>`;
|
||||||
|
|
||||||
let container = document.createElement("box");
|
let container = document.createElement("box");
|
||||||
container.innerHTML = keyset;
|
container.unsafeSetInnerHTML(keyset);
|
||||||
document.documentElement.appendChild(container);
|
document.documentElement.appendChild(container);
|
||||||
/* eslint-enable no-unsanitized/property */
|
/* eslint-enable no-unsanitized/property */
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -131,6 +131,11 @@ add_task(async function copyURLFromPanel() {
|
||||||
// does not appear on about:blank for example.)
|
// does not appear on about:blank for example.)
|
||||||
let url = "http://example.com/";
|
let url = "http://example.com/";
|
||||||
await BrowserTestUtils.withNewTab(url, async () => {
|
await BrowserTestUtils.withNewTab(url, async () => {
|
||||||
|
// Add action to URL bar.
|
||||||
|
let action = PageActions._builtInActions.find(a => a.id == "copyURL");
|
||||||
|
action.pinnedToUrlbar = true;
|
||||||
|
registerCleanupFunction(() => action.pinnedToUrlbar = false);
|
||||||
|
|
||||||
// Open the panel and click Copy URL.
|
// Open the panel and click Copy URL.
|
||||||
await promisePageActionPanelOpen();
|
await promisePageActionPanelOpen();
|
||||||
Assert.ok(true, "page action panel opened");
|
Assert.ok(true, "page action panel opened");
|
||||||
|
|
@ -147,6 +152,8 @@ add_task(async function copyURLFromPanel() {
|
||||||
Assert.equal(feedbackPanel.anchorNode.id, "pageActionButton", "Feedback menu should be anchored on the main Page Action button");
|
Assert.equal(feedbackPanel.anchorNode.id, "pageActionButton", "Feedback menu should be anchored on the main Page Action button");
|
||||||
let feedbackHiddenPromise = promisePanelHidden("pageActionFeedback");
|
let feedbackHiddenPromise = promisePanelHidden("pageActionFeedback");
|
||||||
await feedbackHiddenPromise;
|
await feedbackHiddenPromise;
|
||||||
|
|
||||||
|
action.pinnedToUrlbar = false;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -170,6 +177,8 @@ add_task(async function copyURLFromURLBar() {
|
||||||
Assert.equal(panel.anchorNode.id, "pageAction-urlbar-copyURL", "Feedback menu should be anchored on the main URL bar button");
|
Assert.equal(panel.anchorNode.id, "pageAction-urlbar-copyURL", "Feedback menu should be anchored on the main URL bar button");
|
||||||
let feedbackHiddenPromise = promisePanelHidden("pageActionFeedback");
|
let feedbackHiddenPromise = promisePanelHidden("pageActionFeedback");
|
||||||
await feedbackHiddenPromise;
|
await feedbackHiddenPromise;
|
||||||
|
|
||||||
|
action.pinnedToUrlbar = false;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ Cu.import("resource://gre/modules/AppConstants.jsm");
|
||||||
|
|
||||||
XPCOMUtils.defineLazyModuleGetters(this, {
|
XPCOMUtils.defineLazyModuleGetters(this, {
|
||||||
BrowserUITelemetry: "resource:///modules/BrowserUITelemetry.jsm",
|
BrowserUITelemetry: "resource:///modules/BrowserUITelemetry.jsm",
|
||||||
|
PanelView: "resource:///modules/PanelMultiView.jsm",
|
||||||
PlacesUtils: "resource://gre/modules/PlacesUtils.jsm",
|
PlacesUtils: "resource://gre/modules/PlacesUtils.jsm",
|
||||||
PlacesUIUtils: "resource:///modules/PlacesUIUtils.jsm",
|
PlacesUIUtils: "resource:///modules/PlacesUIUtils.jsm",
|
||||||
RecentlyClosedTabsAndWindowsMenuUtils: "resource:///modules/sessionstore/RecentlyClosedTabsAndWindowsMenuUtils.jsm",
|
RecentlyClosedTabsAndWindowsMenuUtils: "resource:///modules/sessionstore/RecentlyClosedTabsAndWindowsMenuUtils.jsm",
|
||||||
|
|
@ -366,8 +367,8 @@ const CustomizableWidgets = [
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this._tabsList.appendChild(fragment);
|
this._tabsList.appendChild(fragment);
|
||||||
let panelView = this._tabsList.closest("panelview");
|
PanelView.forNode(this._tabsList.closest("panelview"))
|
||||||
panelView.panelMultiView.descriptionHeightWorkaround(panelView);
|
.descriptionHeightWorkaround();
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
Cu.reportError(err);
|
Cu.reportError(err);
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -163,19 +163,6 @@ const PanelUI = {
|
||||||
this.libraryView.removeEventListener("ViewShowing", this);
|
this.libraryView.removeEventListener("ViewShowing", this);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
|
||||||
* Customize mode extracts the mainView and puts it somewhere else while the
|
|
||||||
* user customizes. Upon completion, this function can be called to put the
|
|
||||||
* panel back to where it belongs in normal browsing mode.
|
|
||||||
*
|
|
||||||
* @param aMainView
|
|
||||||
* The mainView node to put back into place.
|
|
||||||
*/
|
|
||||||
setMainView(aMainView) {
|
|
||||||
this._ensureEventListenersAdded();
|
|
||||||
this.multiView.setMainView(aMainView);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Opens the menu panel if it's closed, or closes it if it's
|
* Opens the menu panel if it's closed, or closes it if it's
|
||||||
* open.
|
* open.
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,8 @@
|
||||||
<implementation>
|
<implementation>
|
||||||
<constructor><![CDATA[
|
<constructor><![CDATA[
|
||||||
const {PanelMultiView} = Components.utils.import("resource:///modules/PanelMultiView.jsm", {});
|
const {PanelMultiView} = Components.utils.import("resource:///modules/PanelMultiView.jsm", {});
|
||||||
this.instance = new PanelMultiView(this);
|
this.instance = PanelMultiView.forNode(this);
|
||||||
|
this.instance.connect();
|
||||||
]]></constructor>
|
]]></constructor>
|
||||||
|
|
||||||
<destructor><![CDATA[
|
<destructor><![CDATA[
|
||||||
|
|
|
||||||
|
|
@ -4,20 +4,15 @@
|
||||||
* Test keyboard navigation in the app menu panel.
|
* Test keyboard navigation in the app menu panel.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const {PanelMultiView} = Cu.import("resource:///modules/PanelMultiView.jsm", {});
|
const {PanelView} = Cu.import("resource:///modules/PanelMultiView.jsm", {});
|
||||||
const kHelpButtonId = "appMenu-help-button";
|
const kHelpButtonId = "appMenu-help-button";
|
||||||
let gHelperInstance;
|
|
||||||
|
|
||||||
add_task(async function setup() {
|
|
||||||
gHelperInstance = new PanelMultiView(PanelUI.panel, true);
|
|
||||||
});
|
|
||||||
|
|
||||||
add_task(async function testUpDownKeys() {
|
add_task(async function testUpDownKeys() {
|
||||||
let promise = promisePanelShown(window);
|
let promise = promisePanelShown(window);
|
||||||
PanelUI.show();
|
PanelUI.show();
|
||||||
await promise;
|
await promise;
|
||||||
|
|
||||||
let buttons = gHelperInstance._getNavigableElements(PanelUI.mainView);
|
let buttons = PanelView.forNode(PanelUI.mainView).getNavigableElements();
|
||||||
|
|
||||||
for (let button of buttons) {
|
for (let button of buttons) {
|
||||||
if (button.disabled)
|
if (button.disabled)
|
||||||
|
|
@ -50,7 +45,7 @@ add_task(async function testEnterKeyBehaviors() {
|
||||||
PanelUI.show();
|
PanelUI.show();
|
||||||
await promise;
|
await promise;
|
||||||
|
|
||||||
let buttons = gHelperInstance._getNavigableElements(PanelUI.mainView);
|
let buttons = PanelView.forNode(PanelUI.mainView).getNavigableElements();
|
||||||
|
|
||||||
// Navigate to the 'Help' button, which points to a subview.
|
// Navigate to the 'Help' button, which points to a subview.
|
||||||
EventUtils.synthesizeKey("KEY_ArrowUp", { code: "ArrowUp" });
|
EventUtils.synthesizeKey("KEY_ArrowUp", { code: "ArrowUp" });
|
||||||
|
|
@ -67,7 +62,7 @@ add_task(async function testEnterKeyBehaviors() {
|
||||||
EventUtils.synthesizeKey("VK_RETURN", { code: "Enter" });
|
EventUtils.synthesizeKey("VK_RETURN", { code: "Enter" });
|
||||||
await promise;
|
await promise;
|
||||||
|
|
||||||
let helpButtons = gHelperInstance._getNavigableElements(PanelUI.helpView);
|
let helpButtons = PanelView.forNode(PanelUI.helpView).getNavigableElements();
|
||||||
Assert.ok(helpButtons[0].classList.contains("subviewbutton-back"),
|
Assert.ok(helpButtons[0].classList.contains("subviewbutton-back"),
|
||||||
"First button in help view should be a back button");
|
"First button in help view should be a back button");
|
||||||
|
|
||||||
|
|
@ -147,7 +142,7 @@ add_task(async function testTabKey() {
|
||||||
PanelUI.show();
|
PanelUI.show();
|
||||||
await promise;
|
await promise;
|
||||||
|
|
||||||
let buttons = gHelperInstance._getNavigableElements(PanelUI.mainView);
|
let buttons = PanelView.forNode(PanelUI.mainView).getNavigableElements();
|
||||||
|
|
||||||
for (let button of buttons) {
|
for (let button of buttons) {
|
||||||
if (button.disabled)
|
if (button.disabled)
|
||||||
|
|
@ -184,7 +179,7 @@ add_task(async function testInterleavedTabAndArrowKeys() {
|
||||||
PanelUI.show();
|
PanelUI.show();
|
||||||
await promise;
|
await promise;
|
||||||
|
|
||||||
let buttons = gHelperInstance._getNavigableElements(PanelUI.mainView);
|
let buttons = PanelView.forNode(PanelUI.mainView).getNavigableElements();
|
||||||
let tab = false;
|
let tab = false;
|
||||||
|
|
||||||
for (let button of buttons) {
|
for (let button of buttons) {
|
||||||
|
|
@ -211,7 +206,7 @@ add_task(async function testSpaceDownAfterTabNavigation() {
|
||||||
PanelUI.show();
|
PanelUI.show();
|
||||||
await promise;
|
await promise;
|
||||||
|
|
||||||
let buttons = gHelperInstance._getNavigableElements(PanelUI.mainView);
|
let buttons = PanelView.forNode(PanelUI.mainView).getNavigableElements();
|
||||||
let button;
|
let button;
|
||||||
|
|
||||||
for (button of buttons) {
|
for (button of buttons) {
|
||||||
|
|
|
||||||
|
|
@ -407,13 +407,15 @@ var gPrivacyPane = {
|
||||||
document.getElementById("drmGroup").setAttribute("style", "display: none !important");
|
document.getElementById("drmGroup").setAttribute("style", "display: none !important");
|
||||||
}
|
}
|
||||||
|
|
||||||
this.initDataCollection();
|
if (AppConstants.MOZ_DATA_REPORTING) {
|
||||||
if (AppConstants.MOZ_CRASHREPORTER) {
|
this.initDataCollection();
|
||||||
this.initSubmitCrashes();
|
if (AppConstants.MOZ_CRASHREPORTER) {
|
||||||
|
this.initSubmitCrashes();
|
||||||
|
}
|
||||||
|
this.initSubmitHealthReport();
|
||||||
|
setEventListener("submitHealthReportBox", "command",
|
||||||
|
gPrivacyPane.updateSubmitHealthReport);
|
||||||
}
|
}
|
||||||
this.initSubmitHealthReport();
|
|
||||||
setEventListener("submitHealthReportBox", "command",
|
|
||||||
gPrivacyPane.updateSubmitHealthReport);
|
|
||||||
this._initA11yState();
|
this._initA11yState();
|
||||||
let signonBundle = document.getElementById("signonBundle");
|
let signonBundle = document.getElementById("signonBundle");
|
||||||
let pkiBundle = document.getElementById("pkiBundle");
|
let pkiBundle = document.getElementById("pkiBundle");
|
||||||
|
|
|
||||||
|
|
@ -206,7 +206,6 @@ var SessionStorageInternal = {
|
||||||
let usage = window.QueryInterface(Ci.nsIInterfaceRequestor)
|
let usage = window.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||||
.getInterface(Ci.nsIDOMWindowUtils)
|
.getInterface(Ci.nsIDOMWindowUtils)
|
||||||
.getStorageUsage(storage);
|
.getStorageUsage(storage);
|
||||||
Services.telemetry.getHistogramById("FX_SESSION_RESTORE_DOM_STORAGE_SIZE_ESTIMATE_CHARS").add(usage);
|
|
||||||
if (usage > Services.prefs.getIntPref(DOM_STORAGE_LIMIT_PREF)) {
|
if (usage > Services.prefs.getIntPref(DOM_STORAGE_LIMIT_PREF)) {
|
||||||
return hostData;
|
return hostData;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -620,7 +620,6 @@ var SessionStorageListener = {
|
||||||
let usage = content.QueryInterface(Ci.nsIInterfaceRequestor)
|
let usage = content.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||||
.getInterface(Ci.nsIDOMWindowUtils)
|
.getInterface(Ci.nsIDOMWindowUtils)
|
||||||
.getStorageUsage(event.storageArea);
|
.getStorageUsage(event.storageArea);
|
||||||
Services.telemetry.getHistogramById("FX_SESSION_RESTORE_DOM_STORAGE_SIZE_ESTIMATE_CHARS").add(usage);
|
|
||||||
|
|
||||||
// Don't store any data if we exceed the limit. Wipe any data we previously
|
// Don't store any data if we exceed the limit. Wipe any data we previously
|
||||||
// collected so that we don't confuse websites with partial state.
|
// collected so that we don't confuse websites with partial state.
|
||||||
|
|
|
||||||
|
|
@ -10,47 +10,6 @@ const URL = "http://mochi.test:8888/browser/" +
|
||||||
|
|
||||||
const OUTER_VALUE = "outer-value-" + RAND;
|
const OUTER_VALUE = "outer-value-" + RAND;
|
||||||
|
|
||||||
function getEstimateChars() {
|
|
||||||
let snap;
|
|
||||||
if (gMultiProcessBrowser) {
|
|
||||||
snap = Services.telemetry.snapshotHistograms(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN,
|
|
||||||
false /* subsession */,
|
|
||||||
false /* clear */).content.FX_SESSION_RESTORE_DOM_STORAGE_SIZE_ESTIMATE_CHARS;
|
|
||||||
} else {
|
|
||||||
snap = Services.telemetry.snapshotHistograms(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN,
|
|
||||||
false,
|
|
||||||
false).parent.FX_SESSION_RESTORE_DOM_STORAGE_SIZE_ESTIMATE_CHARS;
|
|
||||||
}
|
|
||||||
if (!snap) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return snap.counts[4];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test that we record the size of messages.
|
|
||||||
add_task(async function test_telemetry() {
|
|
||||||
Services.telemetry.canRecordExtended = true;
|
|
||||||
|
|
||||||
let prev = getEstimateChars();
|
|
||||||
|
|
||||||
let tab = BrowserTestUtils.addTab(gBrowser, URL);
|
|
||||||
let browser = tab.linkedBrowser;
|
|
||||||
await promiseBrowserLoaded(browser);
|
|
||||||
|
|
||||||
// Flush to make sure we submitted telemetry data.
|
|
||||||
await TabStateFlusher.flush(browser);
|
|
||||||
|
|
||||||
// There is no good way to make sure that the parent received the histogram entries from the child processes.
|
|
||||||
// Let's stick to the ugly, spinning the event loop until we have a good approach (Bug 1357509).
|
|
||||||
await BrowserTestUtils.waitForCondition(() => {
|
|
||||||
return getEstimateChars() > prev;
|
|
||||||
});
|
|
||||||
|
|
||||||
Assert.ok(true);
|
|
||||||
await promiseRemoveTab(tab);
|
|
||||||
Services.telemetry.canRecordExtended = false;
|
|
||||||
});
|
|
||||||
|
|
||||||
// Lower the size limit for DOM Storage content. Check that DOM Storage
|
// Lower the size limit for DOM Storage content. Check that DOM Storage
|
||||||
// is not updated, but that other things remain updated.
|
// is not updated, but that other things remain updated.
|
||||||
add_task(async function test_large_content() {
|
add_task(async function test_large_content() {
|
||||||
|
|
|
||||||
|
|
@ -75,7 +75,6 @@
|
||||||
.requests-list-column {
|
.requests-list-column {
|
||||||
display: table-cell;
|
display: table-cell;
|
||||||
cursor: default;
|
cursor: default;
|
||||||
text-align: center;
|
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
|
|
@ -548,9 +547,6 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.requests-list-timings {
|
.requests-list-timings {
|
||||||
display: flex;
|
|
||||||
flex: none;
|
|
||||||
align-items: center;
|
|
||||||
transform: scaleX(var(--timings-scale));
|
transform: scaleX(var(--timings-scale));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -608,6 +604,7 @@
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
/* This node should not be scaled - apply a reversed transformation */
|
/* This node should not be scaled - apply a reversed transformation */
|
||||||
transform: scaleX(var(--timings-rev-scale));
|
transform: scaleX(var(--timings-rev-scale));
|
||||||
|
text-align: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
.requests-list-timings-total:dir(ltr) {
|
.requests-list-timings-total:dir(ltr) {
|
||||||
|
|
|
||||||
|
|
@ -89,11 +89,14 @@ function requestsReducer(state = Requests(), action) {
|
||||||
...request,
|
...request,
|
||||||
...processNetworkUpdates(action.data),
|
...processNetworkUpdates(action.data),
|
||||||
};
|
};
|
||||||
|
let requestEndTime = request.startedMillis +
|
||||||
|
(request.eventTimings ? request.eventTimings.totalTime : 0);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
requests: mapSet(state.requests, action.id, request),
|
requests: mapSet(state.requests, action.id, request),
|
||||||
lastEndedMillis: lastEndedMillis,
|
lastEndedMillis: requestEndTime > lastEndedMillis ?
|
||||||
|
requestEndTime : lastEndedMillis,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,8 +27,11 @@ const getWaterfallScale = createSelector(
|
||||||
timingMarkers.firstDocumentDOMContentLoadedTimestamp,
|
timingMarkers.firstDocumentDOMContentLoadedTimestamp,
|
||||||
timingMarkers.firstDocumentLoadTimestamp);
|
timingMarkers.firstDocumentLoadTimestamp);
|
||||||
const longestWidth = lastEventMillis - requests.firstStartedMillis;
|
const longestWidth = lastEventMillis - requests.firstStartedMillis;
|
||||||
|
|
||||||
|
// Reduce 20px for the last request's requests-list-timings-total
|
||||||
return Math.min(Math.max(
|
return Math.min(Math.max(
|
||||||
(ui.waterfallWidth - REQUESTS_WATERFALL.LABEL_WIDTH) / longestWidth, EPSILON), 1);
|
(ui.waterfallWidth - REQUESTS_WATERFALL.LABEL_WIDTH - 20) / longestWidth,
|
||||||
|
EPSILON), 1);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,12 @@ const { getToplevelWindow } = require("../utils/window");
|
||||||
|
|
||||||
const FRAME_SCRIPT = "resource://devtools/client/responsive.html/browser/content.js";
|
const FRAME_SCRIPT = "resource://devtools/client/responsive.html/browser/content.js";
|
||||||
|
|
||||||
|
// Allow creation of HTML fragments without automatic sanitization, even
|
||||||
|
// though we're in a chrome-privileged document.
|
||||||
|
// This is, unfortunately, necessary in order to React to function
|
||||||
|
// correctly.
|
||||||
|
document.allowUnsafeHTML = true;
|
||||||
|
|
||||||
class Browser extends PureComponent {
|
class Browser extends PureComponent {
|
||||||
/**
|
/**
|
||||||
* This component is not allowed to depend directly on frequently changing
|
* This component is not allowed to depend directly on frequently changing
|
||||||
|
|
|
||||||
|
|
@ -97,6 +97,10 @@ add_task(async function () {
|
||||||
await onPopupClose;
|
await onPopupClose;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function stripNS(text) {
|
||||||
|
return text.replace(RegExp(' xmlns="http://www.w3.org/1999/xhtml"', "g"), "");
|
||||||
|
}
|
||||||
|
|
||||||
function checkActiveDescendant(popup, input) {
|
function checkActiveDescendant(popup, input) {
|
||||||
let activeElement = input.ownerDocument.activeElement;
|
let activeElement = input.ownerDocument.activeElement;
|
||||||
let descendantId = activeElement.getAttribute("aria-activedescendant");
|
let descendantId = activeElement.getAttribute("aria-activedescendant");
|
||||||
|
|
@ -105,6 +109,6 @@ function checkActiveDescendant(popup, input) {
|
||||||
|
|
||||||
ok(popupItem, "Active descendant is found in the popup list");
|
ok(popupItem, "Active descendant is found in the popup list");
|
||||||
ok(cloneItem, "Active descendant is found in the list clone");
|
ok(cloneItem, "Active descendant is found in the list clone");
|
||||||
is(popupItem.outerHTML, cloneItem.outerHTML,
|
is(stripNS(popupItem.outerHTML), cloneItem.outerHTML,
|
||||||
"Cloned item has the same HTML as the original element");
|
"Cloned item has the same HTML as the original element");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -498,10 +498,12 @@ exports.setContents = function(elem, contents) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ('innerHTML' in elem) {
|
if ("unsafeSetInnerHTML" in elem) {
|
||||||
|
// FIXME: Stop relying on unsanitized HTML.
|
||||||
|
elem.unsafeSetInnerHTML(contents);
|
||||||
|
} else if ("innerHTML" in elem) {
|
||||||
elem.innerHTML = contents;
|
elem.innerHTML = contents;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
try {
|
try {
|
||||||
var ns = elem.ownerDocument.documentElement.namespaceURI;
|
var ns = elem.ownerDocument.documentElement.namespaceURI;
|
||||||
if (!ns) {
|
if (!ns) {
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ add_task(function* () {
|
||||||
|
|
||||||
info("Create the test markup");
|
info("Create the test markup");
|
||||||
let div = document.createElement("div");
|
let div = document.createElement("div");
|
||||||
div.innerHTML =
|
div.unsafeSetInnerHTML(
|
||||||
`<div data-localization-bundle="devtools/client/locales/startup.properties">
|
`<div data-localization-bundle="devtools/client/locales/startup.properties">
|
||||||
<div id="d0" data-localization="content=inspector.someInvalidKey"></div>
|
<div id="d0" data-localization="content=inspector.someInvalidKey"></div>
|
||||||
<div id="d1" data-localization="content=inspector.label">Text will disappear</div>
|
<div id="d1" data-localization="content=inspector.label">Text will disappear</div>
|
||||||
|
|
@ -32,7 +32,7 @@ add_task(function* () {
|
||||||
<div id="d5" data-localization="content=toolbox.defaultTitle"></div>
|
<div id="d5" data-localization="content=toolbox.defaultTitle"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`);
|
||||||
|
|
||||||
info("Use localization helper to localize the test markup");
|
info("Use localization helper to localize the test markup");
|
||||||
localizeMarkup(div);
|
localizeMarkup(div);
|
||||||
|
|
|
||||||
|
|
@ -10687,6 +10687,7 @@ nsDocShell::DoURILoad(nsIURI* aURI,
|
||||||
rv = NS_NewChannelInternal(getter_AddRefs(channel),
|
rv = NS_NewChannelInternal(getter_AddRefs(channel),
|
||||||
aURI,
|
aURI,
|
||||||
loadInfo,
|
loadInfo,
|
||||||
|
nullptr, // PerformanceStorage
|
||||||
nullptr, // loadGroup
|
nullptr, // loadGroup
|
||||||
static_cast<nsIInterfaceRequestor*>(this),
|
static_cast<nsIInterfaceRequestor*>(this),
|
||||||
loadFlags);
|
loadFlags);
|
||||||
|
|
|
||||||
|
|
@ -109,6 +109,7 @@ SendPing(void* aClosure, nsIContent* aContent, nsIURI* aURI,
|
||||||
? nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_IS_BLOCKED
|
? nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_IS_BLOCKED
|
||||||
: nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
|
: nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
|
||||||
nsIContentPolicy::TYPE_PING,
|
nsIContentPolicy::TYPE_PING,
|
||||||
|
nullptr, // PerformanceStorage
|
||||||
nullptr, // aLoadGroup
|
nullptr, // aLoadGroup
|
||||||
nullptr, // aCallbacks
|
nullptr, // aCallbacks
|
||||||
nsIRequest::LOAD_NORMAL, // aLoadFlags,
|
nsIRequest::LOAD_NORMAL, // aLoadFlags,
|
||||||
|
|
|
||||||
|
|
@ -284,6 +284,13 @@ Attr::ComputeIndexOf(const nsINode* aPossibleChild) const
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
Attr::InsertChildBefore(nsIContent* aKid, nsIContent* aBeforeThis,
|
||||||
|
bool aNotify)
|
||||||
|
{
|
||||||
|
return NS_ERROR_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
Attr::InsertChildAt_Deprecated(nsIContent* aKid, uint32_t aIndex,
|
Attr::InsertChildAt_Deprecated(nsIContent* aKid, uint32_t aIndex,
|
||||||
bool aNotify)
|
bool aNotify)
|
||||||
|
|
|
||||||
|
|
@ -64,6 +64,8 @@ public:
|
||||||
virtual uint32_t GetChildCount() const override;
|
virtual uint32_t GetChildCount() const override;
|
||||||
virtual nsIContent *GetChildAt_Deprecated(uint32_t aIndex) const override;
|
virtual nsIContent *GetChildAt_Deprecated(uint32_t aIndex) const override;
|
||||||
virtual int32_t ComputeIndexOf(const nsINode* aPossibleChild) const override;
|
virtual int32_t ComputeIndexOf(const nsINode* aPossibleChild) const override;
|
||||||
|
virtual nsresult InsertChildBefore(nsIContent* aKid, nsIContent* aBeforeThis,
|
||||||
|
bool aNotify) override;
|
||||||
virtual nsresult InsertChildAt_Deprecated(nsIContent* aKid, uint32_t aIndex,
|
virtual nsresult InsertChildAt_Deprecated(nsIContent* aKid, uint32_t aIndex,
|
||||||
bool aNotify) override;
|
bool aNotify) override;
|
||||||
virtual void RemoveChildAt_Deprecated(uint32_t aIndex, bool aNotify) override;
|
virtual void RemoveChildAt_Deprecated(uint32_t aIndex, bool aNotify) override;
|
||||||
|
|
|
||||||
|
|
@ -3927,6 +3927,12 @@ Element::SetInnerHTML(const nsAString& aInnerHTML, nsIPrincipal* aSubjectPrincip
|
||||||
SetInnerHTMLInternal(aInnerHTML, aError);
|
SetInnerHTMLInternal(aInnerHTML, aError);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Element::UnsafeSetInnerHTML(const nsAString& aInnerHTML, ErrorResult& aError)
|
||||||
|
{
|
||||||
|
SetInnerHTMLInternal(aInnerHTML, aError, true);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Element::GetOuterHTML(nsAString& aOuterHTML)
|
Element::GetOuterHTML(nsAString& aOuterHTML)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1418,6 +1418,7 @@ public:
|
||||||
|
|
||||||
NS_IMETHOD GetInnerHTML(nsAString& aInnerHTML);
|
NS_IMETHOD GetInnerHTML(nsAString& aInnerHTML);
|
||||||
virtual void SetInnerHTML(const nsAString& aInnerHTML, nsIPrincipal* aSubjectPrincipal, ErrorResult& aError);
|
virtual void SetInnerHTML(const nsAString& aInnerHTML, nsIPrincipal* aSubjectPrincipal, ErrorResult& aError);
|
||||||
|
void UnsafeSetInnerHTML(const nsAString& aInnerHTML, ErrorResult& aError);
|
||||||
void GetOuterHTML(nsAString& aOuterHTML);
|
void GetOuterHTML(nsAString& aOuterHTML);
|
||||||
void SetOuterHTML(const nsAString& aOuterHTML, ErrorResult& aError);
|
void SetOuterHTML(const nsAString& aOuterHTML, ErrorResult& aError);
|
||||||
void InsertAdjacentHTML(const nsAString& aPosition, const nsAString& aText,
|
void InsertAdjacentHTML(const nsAString& aPosition, const nsAString& aText,
|
||||||
|
|
|
||||||
|
|
@ -1036,6 +1036,7 @@ EventSourceImpl::InitChannelAndRequestEventSource()
|
||||||
doc,
|
doc,
|
||||||
securityFlags,
|
securityFlags,
|
||||||
nsIContentPolicy::TYPE_INTERNAL_EVENTSOURCE,
|
nsIContentPolicy::TYPE_INTERNAL_EVENTSOURCE,
|
||||||
|
nullptr, // aPerformanceStorage
|
||||||
loadGroup,
|
loadGroup,
|
||||||
nullptr, // aCallbacks
|
nullptr, // aCallbacks
|
||||||
loadFlags); // aLoadFlags
|
loadFlags); // aLoadFlags
|
||||||
|
|
@ -1046,6 +1047,7 @@ EventSourceImpl::InitChannelAndRequestEventSource()
|
||||||
mPrincipal,
|
mPrincipal,
|
||||||
securityFlags,
|
securityFlags,
|
||||||
nsIContentPolicy::TYPE_INTERNAL_EVENTSOURCE,
|
nsIContentPolicy::TYPE_INTERNAL_EVENTSOURCE,
|
||||||
|
nullptr, // aPerformanceStorage
|
||||||
nullptr, // loadGroup
|
nullptr, // loadGroup
|
||||||
nullptr, // aCallbacks
|
nullptr, // aCallbacks
|
||||||
loadFlags); // aLoadFlags
|
loadFlags); // aLoadFlags
|
||||||
|
|
|
||||||
|
|
@ -1156,6 +1156,19 @@ nsIContent::SetXBLInsertionPoint(nsIContent* aContent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
FragmentOrElement::InsertChildBefore(nsIContent* aKid,
|
||||||
|
nsIContent* aBeforeThis,
|
||||||
|
bool aNotify)
|
||||||
|
{
|
||||||
|
NS_PRECONDITION(aKid, "null ptr");
|
||||||
|
|
||||||
|
int32_t index = aBeforeThis ? ComputeIndexOf(aBeforeThis) : GetChildCount();
|
||||||
|
MOZ_ASSERT(index >= 0);
|
||||||
|
|
||||||
|
return doInsertChildAt(aKid, index, aNotify, mAttrsAndChildren);
|
||||||
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
FragmentOrElement::InsertChildAt_Deprecated(nsIContent* aKid,
|
FragmentOrElement::InsertChildAt_Deprecated(nsIContent* aKid,
|
||||||
uint32_t aIndex,
|
uint32_t aIndex,
|
||||||
|
|
@ -2274,7 +2287,8 @@ ContainsMarkup(const nsAString& aStr)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
FragmentOrElement::SetInnerHTMLInternal(const nsAString& aInnerHTML, ErrorResult& aError)
|
FragmentOrElement::SetInnerHTMLInternal(const nsAString& aInnerHTML, ErrorResult& aError,
|
||||||
|
bool aNeverSanitize)
|
||||||
{
|
{
|
||||||
FragmentOrElement* target = this;
|
FragmentOrElement* target = this;
|
||||||
// Handle template case.
|
// Handle template case.
|
||||||
|
|
@ -2326,6 +2340,9 @@ FragmentOrElement::SetInnerHTMLInternal(const nsAString& aInnerHTML, ErrorResult
|
||||||
contextNameSpaceID = shadowRoot->GetHost()->GetNameSpaceID();
|
contextNameSpaceID = shadowRoot->GetHost()->GetNameSpaceID();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto sanitize = (aNeverSanitize ? nsContentUtils::NeverSanitize
|
||||||
|
: nsContentUtils::SanitizeSystemPrivileged);
|
||||||
|
|
||||||
if (doc->IsHTMLDocument()) {
|
if (doc->IsHTMLDocument()) {
|
||||||
int32_t oldChildCount = target->GetChildCount();
|
int32_t oldChildCount = target->GetChildCount();
|
||||||
aError = nsContentUtils::ParseFragmentHTML(aInnerHTML,
|
aError = nsContentUtils::ParseFragmentHTML(aInnerHTML,
|
||||||
|
|
@ -2334,14 +2351,16 @@ FragmentOrElement::SetInnerHTMLInternal(const nsAString& aInnerHTML, ErrorResult
|
||||||
contextNameSpaceID,
|
contextNameSpaceID,
|
||||||
doc->GetCompatibilityMode() ==
|
doc->GetCompatibilityMode() ==
|
||||||
eCompatibility_NavQuirks,
|
eCompatibility_NavQuirks,
|
||||||
true);
|
true,
|
||||||
|
sanitize);
|
||||||
mb.NodesAdded();
|
mb.NodesAdded();
|
||||||
// HTML5 parser has notified, but not fired mutation events.
|
// HTML5 parser has notified, but not fired mutation events.
|
||||||
nsContentUtils::FireMutationEventsForDirectParsing(doc, target,
|
nsContentUtils::FireMutationEventsForDirectParsing(doc, target,
|
||||||
oldChildCount);
|
oldChildCount);
|
||||||
} else {
|
} else {
|
||||||
RefPtr<DocumentFragment> df =
|
RefPtr<DocumentFragment> df =
|
||||||
nsContentUtils::CreateContextualFragment(target, aInnerHTML, true, aError);
|
nsContentUtils::CreateContextualFragment(target, aInnerHTML, true,
|
||||||
|
sanitize, aError);
|
||||||
if (!aError.Failed()) {
|
if (!aError.Failed()) {
|
||||||
// Suppress assertion about node removal mutation events that can't have
|
// Suppress assertion about node removal mutation events that can't have
|
||||||
// listeners anyway, because no one has had the chance to register mutation
|
// listeners anyway, because no one has had the chance to register mutation
|
||||||
|
|
|
||||||
|
|
@ -120,6 +120,8 @@ public:
|
||||||
virtual uint32_t GetChildCount() const override;
|
virtual uint32_t GetChildCount() const override;
|
||||||
virtual nsIContent *GetChildAt_Deprecated(uint32_t aIndex) const override;
|
virtual nsIContent *GetChildAt_Deprecated(uint32_t aIndex) const override;
|
||||||
virtual int32_t ComputeIndexOf(const nsINode* aPossibleChild) const override;
|
virtual int32_t ComputeIndexOf(const nsINode* aPossibleChild) const override;
|
||||||
|
virtual nsresult InsertChildBefore(nsIContent* aKid, nsIContent* aBeforeThis,
|
||||||
|
bool aNotify) override;
|
||||||
virtual nsresult InsertChildAt_Deprecated(nsIContent* aKid, uint32_t aIndex,
|
virtual nsresult InsertChildAt_Deprecated(nsIContent* aKid, uint32_t aIndex,
|
||||||
bool aNotify) override;
|
bool aNotify) override;
|
||||||
virtual void RemoveChildAt_Deprecated(uint32_t aIndex, bool aNotify) override;
|
virtual void RemoveChildAt_Deprecated(uint32_t aIndex, bool aNotify) override;
|
||||||
|
|
@ -332,7 +334,8 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void GetMarkup(bool aIncludeSelf, nsAString& aMarkup);
|
void GetMarkup(bool aIncludeSelf, nsAString& aMarkup);
|
||||||
void SetInnerHTMLInternal(const nsAString& aInnerHTML, ErrorResult& aError);
|
void SetInnerHTMLInternal(const nsAString& aInnerHTML, ErrorResult& aError,
|
||||||
|
bool aNeverSanitize = false);
|
||||||
|
|
||||||
// Override from nsINode
|
// Override from nsINode
|
||||||
nsIContent::nsContentSlots* CreateSlots() override
|
nsIContent::nsContentSlots* CreateSlots() override
|
||||||
|
|
|
||||||
|
|
@ -1156,6 +1156,7 @@ Navigator::SendBeaconInternal(const nsAString& aUrl,
|
||||||
doc,
|
doc,
|
||||||
securityFlags,
|
securityFlags,
|
||||||
nsIContentPolicy::TYPE_BEACON,
|
nsIContentPolicy::TYPE_BEACON,
|
||||||
|
nullptr, // aPerformanceStorage
|
||||||
nullptr, // aLoadGroup
|
nullptr, // aLoadGroup
|
||||||
nullptr, // aCallbacks
|
nullptr, // aCallbacks
|
||||||
loadFlags);
|
loadFlags);
|
||||||
|
|
|
||||||
|
|
@ -162,6 +162,7 @@
|
||||||
#include "nsIObserverService.h"
|
#include "nsIObserverService.h"
|
||||||
#include "nsIOfflineCacheUpdate.h"
|
#include "nsIOfflineCacheUpdate.h"
|
||||||
#include "nsIParser.h"
|
#include "nsIParser.h"
|
||||||
|
#include "nsIParserUtils.h"
|
||||||
#include "nsIPermissionManager.h"
|
#include "nsIPermissionManager.h"
|
||||||
#include "nsIPluginHost.h"
|
#include "nsIPluginHost.h"
|
||||||
#include "nsIRemoteBrowser.h"
|
#include "nsIRemoteBrowser.h"
|
||||||
|
|
@ -200,6 +201,7 @@
|
||||||
#include "nsTextFragment.h"
|
#include "nsTextFragment.h"
|
||||||
#include "nsTextNode.h"
|
#include "nsTextNode.h"
|
||||||
#include "nsThreadUtils.h"
|
#include "nsThreadUtils.h"
|
||||||
|
#include "nsTreeSanitizer.h"
|
||||||
#include "nsUnicodeProperties.h"
|
#include "nsUnicodeProperties.h"
|
||||||
#include "nsURLHelper.h"
|
#include "nsURLHelper.h"
|
||||||
#include "nsViewManager.h"
|
#include "nsViewManager.h"
|
||||||
|
|
@ -4959,6 +4961,7 @@ already_AddRefed<DocumentFragment>
|
||||||
nsContentUtils::CreateContextualFragment(nsINode* aContextNode,
|
nsContentUtils::CreateContextualFragment(nsINode* aContextNode,
|
||||||
const nsAString& aFragment,
|
const nsAString& aFragment,
|
||||||
bool aPreventScriptExecution,
|
bool aPreventScriptExecution,
|
||||||
|
SanitizeFragments aSanitize,
|
||||||
ErrorResult& aRv)
|
ErrorResult& aRv)
|
||||||
{
|
{
|
||||||
if (!aContextNode) {
|
if (!aContextNode) {
|
||||||
|
|
@ -4994,14 +4997,16 @@ nsContentUtils::CreateContextualFragment(nsINode* aContextNode,
|
||||||
contextAsContent->GetNameSpaceID(),
|
contextAsContent->GetNameSpaceID(),
|
||||||
(document->GetCompatibilityMode() ==
|
(document->GetCompatibilityMode() ==
|
||||||
eCompatibility_NavQuirks),
|
eCompatibility_NavQuirks),
|
||||||
aPreventScriptExecution);
|
aPreventScriptExecution,
|
||||||
|
aSanitize);
|
||||||
} else {
|
} else {
|
||||||
aRv = ParseFragmentHTML(aFragment, frag,
|
aRv = ParseFragmentHTML(aFragment, frag,
|
||||||
nsGkAtoms::body,
|
nsGkAtoms::body,
|
||||||
kNameSpaceID_XHTML,
|
kNameSpaceID_XHTML,
|
||||||
(document->GetCompatibilityMode() ==
|
(document->GetCompatibilityMode() ==
|
||||||
eCompatibility_NavQuirks),
|
eCompatibility_NavQuirks),
|
||||||
aPreventScriptExecution);
|
aPreventScriptExecution,
|
||||||
|
aSanitize);
|
||||||
}
|
}
|
||||||
|
|
||||||
return frag.forget();
|
return frag.forget();
|
||||||
|
|
@ -5065,7 +5070,8 @@ nsContentUtils::CreateContextualFragment(nsINode* aContextNode,
|
||||||
|
|
||||||
nsCOMPtr<nsIDOMDocumentFragment> frag;
|
nsCOMPtr<nsIDOMDocumentFragment> frag;
|
||||||
aRv = ParseFragmentXML(aFragment, document, tagStack,
|
aRv = ParseFragmentXML(aFragment, document, tagStack,
|
||||||
aPreventScriptExecution, getter_AddRefs(frag));
|
aPreventScriptExecution, getter_AddRefs(frag),
|
||||||
|
aSanitize);
|
||||||
return frag.forget().downcast<DocumentFragment>();
|
return frag.forget().downcast<DocumentFragment>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -5092,7 +5098,8 @@ nsContentUtils::ParseFragmentHTML(const nsAString& aSourceBuffer,
|
||||||
nsAtom* aContextLocalName,
|
nsAtom* aContextLocalName,
|
||||||
int32_t aContextNamespace,
|
int32_t aContextNamespace,
|
||||||
bool aQuirks,
|
bool aQuirks,
|
||||||
bool aPreventScriptExecution)
|
bool aPreventScriptExecution,
|
||||||
|
SanitizeFragments aSanitize)
|
||||||
{
|
{
|
||||||
AutoTimelineMarker m(aTargetNode->OwnerDoc()->GetDocShell(), "Parse HTML");
|
AutoTimelineMarker m(aTargetNode->OwnerDoc()->GetDocShell(), "Parse HTML");
|
||||||
|
|
||||||
|
|
@ -5106,13 +5113,39 @@ nsContentUtils::ParseFragmentHTML(const nsAString& aSourceBuffer,
|
||||||
NS_ADDREF(sHTMLFragmentParser = new nsHtml5StringParser());
|
NS_ADDREF(sHTMLFragmentParser = new nsHtml5StringParser());
|
||||||
// Now sHTMLFragmentParser owns the object
|
// Now sHTMLFragmentParser owns the object
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsIContent* target = aTargetNode;
|
||||||
|
|
||||||
|
// If this is a chrome-privileged document, create a fragment first, and
|
||||||
|
// sanitize it before insertion.
|
||||||
|
RefPtr<DocumentFragment> fragment;
|
||||||
|
if (aSanitize != NeverSanitize && !aTargetNode->OwnerDoc()->AllowUnsafeHTML()) {
|
||||||
|
fragment = new DocumentFragment(aTargetNode->OwnerDoc()->NodeInfoManager());
|
||||||
|
target = fragment;
|
||||||
|
}
|
||||||
|
|
||||||
nsresult rv =
|
nsresult rv =
|
||||||
sHTMLFragmentParser->ParseFragment(aSourceBuffer,
|
sHTMLFragmentParser->ParseFragment(aSourceBuffer,
|
||||||
aTargetNode,
|
target,
|
||||||
aContextLocalName,
|
aContextLocalName,
|
||||||
aContextNamespace,
|
aContextNamespace,
|
||||||
aQuirks,
|
aQuirks,
|
||||||
aPreventScriptExecution);
|
aPreventScriptExecution);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
if (fragment) {
|
||||||
|
// Don't fire mutation events for nodes removed by the sanitizer.
|
||||||
|
nsAutoScriptBlockerSuppressNodeRemoved scriptBlocker;
|
||||||
|
|
||||||
|
nsTreeSanitizer sanitizer(nsIParserUtils::SanitizerAllowStyle |
|
||||||
|
nsIParserUtils::SanitizerAllowComments);
|
||||||
|
sanitizer.Sanitize(fragment);
|
||||||
|
|
||||||
|
ErrorResult error;
|
||||||
|
aTargetNode->AppendChild(*fragment, error);
|
||||||
|
rv = error.StealNSResult();
|
||||||
|
}
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -5147,7 +5180,8 @@ nsContentUtils::ParseFragmentXML(const nsAString& aSourceBuffer,
|
||||||
nsIDocument* aDocument,
|
nsIDocument* aDocument,
|
||||||
nsTArray<nsString>& aTagStack,
|
nsTArray<nsString>& aTagStack,
|
||||||
bool aPreventScriptExecution,
|
bool aPreventScriptExecution,
|
||||||
nsIDOMDocumentFragment** aReturn)
|
nsIDOMDocumentFragment** aReturn,
|
||||||
|
SanitizeFragments aSanitize)
|
||||||
{
|
{
|
||||||
AutoTimelineMarker m(aDocument->GetDocShell(), "Parse XML");
|
AutoTimelineMarker m(aDocument->GetDocShell(), "Parse XML");
|
||||||
|
|
||||||
|
|
@ -5187,6 +5221,19 @@ nsContentUtils::ParseFragmentXML(const nsAString& aSourceBuffer,
|
||||||
|
|
||||||
sXMLFragmentParser->Reset();
|
sXMLFragmentParser->Reset();
|
||||||
|
|
||||||
|
// If this is a chrome-privileged document, sanitize the fragment before
|
||||||
|
// returning.
|
||||||
|
if (aSanitize != NeverSanitize && !aDocument->AllowUnsafeHTML()) {
|
||||||
|
// Don't fire mutation events for nodes removed by the sanitizer.
|
||||||
|
nsAutoScriptBlockerSuppressNodeRemoved scriptBlocker;
|
||||||
|
|
||||||
|
RefPtr<DocumentFragment> fragment = static_cast<DocumentFragment*>(*aReturn);
|
||||||
|
|
||||||
|
nsTreeSanitizer sanitizer(nsIParserUtils::SanitizerAllowStyle |
|
||||||
|
nsIParserUtils::SanitizerAllowComments);
|
||||||
|
sanitizer.Sanitize(fragment);
|
||||||
|
}
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1578,6 +1578,11 @@ public:
|
||||||
static bool IsValidNodeName(nsAtom *aLocalName, nsAtom *aPrefix,
|
static bool IsValidNodeName(nsAtom *aLocalName, nsAtom *aPrefix,
|
||||||
int32_t aNamespaceID);
|
int32_t aNamespaceID);
|
||||||
|
|
||||||
|
enum SanitizeFragments {
|
||||||
|
SanitizeSystemPrivileged,
|
||||||
|
NeverSanitize,
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a DocumentFragment from text using a context node to resolve
|
* Creates a DocumentFragment from text using a context node to resolve
|
||||||
* namespaces.
|
* namespaces.
|
||||||
|
|
@ -1591,6 +1596,8 @@ public:
|
||||||
* @param aFragment the string which is parsed to a DocumentFragment
|
* @param aFragment the string which is parsed to a DocumentFragment
|
||||||
* @param aReturn the resulting fragment
|
* @param aReturn the resulting fragment
|
||||||
* @param aPreventScriptExecution whether to mark scripts as already started
|
* @param aPreventScriptExecution whether to mark scripts as already started
|
||||||
|
* @param aSanitize whether the fragment should be sanitized prior to
|
||||||
|
* injection
|
||||||
*/
|
*/
|
||||||
static nsresult CreateContextualFragment(nsINode* aContextNode,
|
static nsresult CreateContextualFragment(nsINode* aContextNode,
|
||||||
const nsAString& aFragment,
|
const nsAString& aFragment,
|
||||||
|
|
@ -1599,7 +1606,16 @@ public:
|
||||||
static already_AddRefed<mozilla::dom::DocumentFragment>
|
static already_AddRefed<mozilla::dom::DocumentFragment>
|
||||||
CreateContextualFragment(nsINode* aContextNode, const nsAString& aFragment,
|
CreateContextualFragment(nsINode* aContextNode, const nsAString& aFragment,
|
||||||
bool aPreventScriptExecution,
|
bool aPreventScriptExecution,
|
||||||
|
SanitizeFragments aSanitize,
|
||||||
mozilla::ErrorResult& aRv);
|
mozilla::ErrorResult& aRv);
|
||||||
|
static already_AddRefed<mozilla::dom::DocumentFragment>
|
||||||
|
CreateContextualFragment(nsINode* aContextNode, const nsAString& aFragment,
|
||||||
|
bool aPreventScriptExecution,
|
||||||
|
mozilla::ErrorResult& aRv)
|
||||||
|
{
|
||||||
|
return CreateContextualFragment(aContextNode, aFragment, aPreventScriptExecution,
|
||||||
|
SanitizeSystemPrivileged, aRv);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invoke the fragment parsing algorithm (innerHTML) using the HTML parser.
|
* Invoke the fragment parsing algorithm (innerHTML) using the HTML parser.
|
||||||
|
|
@ -1612,6 +1628,8 @@ public:
|
||||||
* @param aPreventScriptExecution true to prevent scripts from executing;
|
* @param aPreventScriptExecution true to prevent scripts from executing;
|
||||||
* don't set to false when parsing into a target node that has been
|
* don't set to false when parsing into a target node that has been
|
||||||
* bound to tree.
|
* bound to tree.
|
||||||
|
* @param aSanitize whether the fragment should be sanitized prior to
|
||||||
|
* injection
|
||||||
* @return NS_ERROR_DOM_INVALID_STATE_ERR if a re-entrant attempt to parse
|
* @return NS_ERROR_DOM_INVALID_STATE_ERR if a re-entrant attempt to parse
|
||||||
* fragments is made, NS_ERROR_OUT_OF_MEMORY if aSourceBuffer is too
|
* fragments is made, NS_ERROR_OUT_OF_MEMORY if aSourceBuffer is too
|
||||||
* long and NS_OK otherwise.
|
* long and NS_OK otherwise.
|
||||||
|
|
@ -1621,7 +1639,8 @@ public:
|
||||||
nsAtom* aContextLocalName,
|
nsAtom* aContextLocalName,
|
||||||
int32_t aContextNamespace,
|
int32_t aContextNamespace,
|
||||||
bool aQuirks,
|
bool aQuirks,
|
||||||
bool aPreventScriptExecution);
|
bool aPreventScriptExecution,
|
||||||
|
SanitizeFragments aSanitize = SanitizeSystemPrivileged);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invoke the fragment parsing algorithm (innerHTML) using the XML parser.
|
* Invoke the fragment parsing algorithm (innerHTML) using the XML parser.
|
||||||
|
|
@ -1631,6 +1650,8 @@ public:
|
||||||
* @param aTagStack the namespace mapping context
|
* @param aTagStack the namespace mapping context
|
||||||
* @param aPreventExecution whether to mark scripts as already started
|
* @param aPreventExecution whether to mark scripts as already started
|
||||||
* @param aReturn the result fragment
|
* @param aReturn the result fragment
|
||||||
|
* @param aSanitize whether the fragment should be sanitized prior to
|
||||||
|
* injection
|
||||||
* @return NS_ERROR_DOM_INVALID_STATE_ERR if a re-entrant attempt to parse
|
* @return NS_ERROR_DOM_INVALID_STATE_ERR if a re-entrant attempt to parse
|
||||||
* fragments is made, a return code from the XML parser.
|
* fragments is made, a return code from the XML parser.
|
||||||
*/
|
*/
|
||||||
|
|
@ -1638,7 +1659,8 @@ public:
|
||||||
nsIDocument* aDocument,
|
nsIDocument* aDocument,
|
||||||
nsTArray<nsString>& aTagStack,
|
nsTArray<nsString>& aTagStack,
|
||||||
bool aPreventScriptExecution,
|
bool aPreventScriptExecution,
|
||||||
nsIDOMDocumentFragment** aReturn);
|
nsIDOMDocumentFragment** aReturn,
|
||||||
|
SanitizeFragments aSanitize = SanitizeSystemPrivileged);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse a string into a document using the HTML parser.
|
* Parse a string into a document using the HTML parser.
|
||||||
|
|
|
||||||
|
|
@ -1191,6 +1191,7 @@ nsExternalResourceMap::PendingLoad::StartLoad(nsIURI* aURI,
|
||||||
aRequestingNode,
|
aRequestingNode,
|
||||||
nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_INHERITS,
|
nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_INHERITS,
|
||||||
nsIContentPolicy::TYPE_OTHER,
|
nsIContentPolicy::TYPE_OTHER,
|
||||||
|
nullptr, // aPerformanceStorage
|
||||||
loadGroup);
|
loadGroup);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
|
@ -1483,6 +1484,7 @@ nsIDocument::nsIDocument()
|
||||||
mAllowPaymentRequest(false),
|
mAllowPaymentRequest(false),
|
||||||
mEncodingMenuDisabled(false),
|
mEncodingMenuDisabled(false),
|
||||||
mIsSVGGlyphsDocument(false),
|
mIsSVGGlyphsDocument(false),
|
||||||
|
mAllowUnsafeHTML(false),
|
||||||
mIsScopedStyleEnabled(eScopedStyle_Unknown),
|
mIsScopedStyleEnabled(eScopedStyle_Unknown),
|
||||||
mCompatMode(eCompatibility_FullStandards),
|
mCompatMode(eCompatibility_FullStandards),
|
||||||
mReadyState(ReadyState::READYSTATE_UNINITIALIZED),
|
mReadyState(ReadyState::READYSTATE_UNINITIALIZED),
|
||||||
|
|
@ -4362,6 +4364,21 @@ nsDocument::GetChildCount() const
|
||||||
return mChildren.ChildCount();
|
return mChildren.ChildCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
nsDocument::InsertChildBefore(nsIContent* aKid, nsIContent* aBeforeThis,
|
||||||
|
bool aNotify)
|
||||||
|
{
|
||||||
|
if (aKid->IsElement() && GetRootElement()) {
|
||||||
|
NS_WARNING("Inserting root element when we already have one");
|
||||||
|
return NS_ERROR_DOM_HIERARCHY_REQUEST_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t index = aBeforeThis ? ComputeIndexOf(aBeforeThis) : GetChildCount();
|
||||||
|
MOZ_ASSERT(index >= 0);
|
||||||
|
|
||||||
|
return doInsertChildAt(aKid, index, aNotify, mChildren);
|
||||||
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsDocument::InsertChildAt_Deprecated(nsIContent* aKid, uint32_t aIndex,
|
nsDocument::InsertChildAt_Deprecated(nsIContent* aKid, uint32_t aIndex,
|
||||||
bool aNotify)
|
bool aNotify)
|
||||||
|
|
@ -6187,6 +6204,13 @@ nsIDocument::CreateAttributeNS(const nsAString& aNamespaceURI,
|
||||||
return attribute.forget();
|
return attribute.forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
nsIDocument::AllowUnsafeHTML() const
|
||||||
|
{
|
||||||
|
return (!nsContentUtils::IsSystemPrincipal(NodePrincipal()) ||
|
||||||
|
mAllowUnsafeHTML);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
nsDocument::ScheduleSVGForPresAttrEvaluation(nsSVGElement* aSVG)
|
nsDocument::ScheduleSVGForPresAttrEvaluation(nsSVGElement* aSVG)
|
||||||
{
|
{
|
||||||
|
|
@ -6881,7 +6905,7 @@ nsDocument::SetTitle(const nsAString& aTitle)
|
||||||
if (!title) {
|
if (!title) {
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
rootElement->InsertChildAt_Deprecated(title, 0, true);
|
rootElement->InsertChildBefore(title, rootElement->GetFirstChild(), true);
|
||||||
}
|
}
|
||||||
} else if (rootElement->IsHTMLElement()) {
|
} else if (rootElement->IsHTMLElement()) {
|
||||||
if (!title) {
|
if (!title) {
|
||||||
|
|
|
||||||
|
|
@ -557,6 +557,8 @@ public:
|
||||||
virtual nsIContent *GetChildAt_Deprecated(uint32_t aIndex) const override;
|
virtual nsIContent *GetChildAt_Deprecated(uint32_t aIndex) const override;
|
||||||
virtual int32_t ComputeIndexOf(const nsINode* aPossibleChild) const override;
|
virtual int32_t ComputeIndexOf(const nsINode* aPossibleChild) const override;
|
||||||
virtual uint32_t GetChildCount() const override;
|
virtual uint32_t GetChildCount() const override;
|
||||||
|
virtual nsresult InsertChildBefore(nsIContent* aKid, nsIContent* aBeforeThis,
|
||||||
|
bool aNotify) override;
|
||||||
virtual nsresult InsertChildAt_Deprecated(nsIContent* aKid, uint32_t aIndex,
|
virtual nsresult InsertChildAt_Deprecated(nsIContent* aKid, uint32_t aIndex,
|
||||||
bool aNotify) override;
|
bool aNotify) override;
|
||||||
virtual void RemoveChildAt_Deprecated(uint32_t aIndex, bool aNotify) override;
|
virtual void RemoveChildAt_Deprecated(uint32_t aIndex, bool aNotify) override;
|
||||||
|
|
|
||||||
|
|
@ -651,6 +651,14 @@ nsGenericDOMDataNode::ComputeIndexOf(const nsINode* aPossibleChild) const
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
nsGenericDOMDataNode::InsertChildBefore(nsIContent* aKid,
|
||||||
|
nsIContent* aBeforeThis,
|
||||||
|
bool aNotify)
|
||||||
|
{
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsGenericDOMDataNode::InsertChildAt_Deprecated(nsIContent* aKid,
|
nsGenericDOMDataNode::InsertChildAt_Deprecated(nsIContent* aKid,
|
||||||
uint32_t aIndex,
|
uint32_t aIndex,
|
||||||
|
|
@ -755,11 +763,11 @@ nsGenericDOMDataNode::SplitData(uint32_t aOffset, nsIContent** aReturn,
|
||||||
|
|
||||||
nsCOMPtr<nsINode> parent = GetParentNode();
|
nsCOMPtr<nsINode> parent = GetParentNode();
|
||||||
if (parent) {
|
if (parent) {
|
||||||
int32_t insertionIndex = parent->ComputeIndexOf(this);
|
nsCOMPtr<nsIContent> beforeNode = this;
|
||||||
if (aCloneAfterOriginal) {
|
if (aCloneAfterOriginal) {
|
||||||
++insertionIndex;
|
beforeNode = beforeNode->GetNextSibling();
|
||||||
}
|
}
|
||||||
parent->InsertChildAt_Deprecated(newContent, insertionIndex, true);
|
parent->InsertChildBefore(newContent, beforeNode, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
newContent.swap(*aReturn);
|
newContent.swap(*aReturn);
|
||||||
|
|
|
||||||
|
|
@ -107,6 +107,8 @@ public:
|
||||||
virtual uint32_t GetChildCount() const override;
|
virtual uint32_t GetChildCount() const override;
|
||||||
virtual nsIContent *GetChildAt_Deprecated(uint32_t aIndex) const override;
|
virtual nsIContent *GetChildAt_Deprecated(uint32_t aIndex) const override;
|
||||||
virtual int32_t ComputeIndexOf(const nsINode* aPossibleChild) const override;
|
virtual int32_t ComputeIndexOf(const nsINode* aPossibleChild) const override;
|
||||||
|
virtual nsresult InsertChildBefore(nsIContent* aKid, nsIContent* aBeforeThis,
|
||||||
|
bool aNotify) override;
|
||||||
virtual nsresult InsertChildAt_Deprecated(nsIContent* aKid, uint32_t aIndex,
|
virtual nsresult InsertChildAt_Deprecated(nsIContent* aKid, uint32_t aIndex,
|
||||||
bool aNotify) override;
|
bool aNotify) override;
|
||||||
virtual void RemoveChildAt_Deprecated(uint32_t aIndex, bool aNotify) override;
|
virtual void RemoveChildAt_Deprecated(uint32_t aIndex, bool aNotify) override;
|
||||||
|
|
|
||||||
|
|
@ -2873,6 +2873,8 @@ public:
|
||||||
CreateAttributeNS(const nsAString& aNamespaceURI,
|
CreateAttributeNS(const nsAString& aNamespaceURI,
|
||||||
const nsAString& aQualifiedName,
|
const nsAString& aQualifiedName,
|
||||||
mozilla::ErrorResult& rv);
|
mozilla::ErrorResult& rv);
|
||||||
|
void SetAllowUnsafeHTML(bool aAllow) { mAllowUnsafeHTML = aAllow; }
|
||||||
|
bool AllowUnsafeHTML() const;
|
||||||
void GetInputEncoding(nsAString& aInputEncoding) const;
|
void GetInputEncoding(nsAString& aInputEncoding) const;
|
||||||
already_AddRefed<mozilla::dom::Location> GetLocation() const;
|
already_AddRefed<mozilla::dom::Location> GetLocation() const;
|
||||||
void GetReferrer(nsAString& aReferrer) const;
|
void GetReferrer(nsAString& aReferrer) const;
|
||||||
|
|
@ -3556,6 +3558,10 @@ protected:
|
||||||
// True if this document is for an SVG-in-OpenType font.
|
// True if this document is for an SVG-in-OpenType font.
|
||||||
bool mIsSVGGlyphsDocument : 1;
|
bool mIsSVGGlyphsDocument : 1;
|
||||||
|
|
||||||
|
// True if unsafe HTML fragments should be allowed in chrome-privileged
|
||||||
|
// documents.
|
||||||
|
bool mAllowUnsafeHTML : 1;
|
||||||
|
|
||||||
// Whether <style scoped> support is enabled in this document.
|
// Whether <style scoped> support is enabled in this document.
|
||||||
enum { eScopedStyle_Unknown, eScopedStyle_Disabled, eScopedStyle_Enabled };
|
enum { eScopedStyle_Unknown, eScopedStyle_Disabled, eScopedStyle_Enabled };
|
||||||
unsigned int mIsScopedStyleEnabled : 2;
|
unsigned int mIsScopedStyleEnabled : 2;
|
||||||
|
|
|
||||||
|
|
@ -717,6 +717,29 @@ public:
|
||||||
return isShadowRoot;
|
return isShadowRoot;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Insert a content node before another or at the end.
|
||||||
|
* This method handles calling BindToTree on the child appropriately.
|
||||||
|
*
|
||||||
|
* @param aKid the content to insert
|
||||||
|
* @param aBeforeThis an existing node. Use nullptr if you want to
|
||||||
|
* add aKid at the end.
|
||||||
|
* @param aNotify whether to notify the document (current document for
|
||||||
|
* nsIContent, and |this| for nsIDocument) that the insert has
|
||||||
|
* occurred
|
||||||
|
*
|
||||||
|
* @throws NS_ERROR_DOM_HIERARCHY_REQUEST_ERR if one attempts to have more
|
||||||
|
* than one element node as a child of a document. Doing this will also
|
||||||
|
* assert -- you shouldn't be doing it! Check with
|
||||||
|
* nsIDocument::GetRootElement() first if you're not sure. Apart from this
|
||||||
|
* one constraint, this doesn't do any checking on whether aKid is a valid
|
||||||
|
* child of |this|.
|
||||||
|
*
|
||||||
|
* @throws NS_ERROR_OUT_OF_MEMORY in some cases (from BindToTree).
|
||||||
|
*/
|
||||||
|
virtual nsresult InsertChildBefore(nsIContent* aKid, nsIContent* aBeforeThis,
|
||||||
|
bool aNotify) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Insert a content node at a particular index. This method handles calling
|
* Insert a content node at a particular index. This method handles calling
|
||||||
* BindToTree on the child appropriately.
|
* BindToTree on the child appropriately.
|
||||||
|
|
|
||||||
|
|
@ -2509,6 +2509,7 @@ nsObjectLoadingContent::OpenChannel()
|
||||||
thisContent,
|
thisContent,
|
||||||
securityFlags,
|
securityFlags,
|
||||||
contentPolicyType,
|
contentPolicyType,
|
||||||
|
nullptr, // aPerformanceStorage
|
||||||
group, // aLoadGroup
|
group, // aLoadGroup
|
||||||
shim, // aCallbacks
|
shim, // aCallbacks
|
||||||
nsIChannel::LOAD_CALL_CONTENT_SNIFFERS |
|
nsIChannel::LOAD_CALL_CONTENT_SNIFFERS |
|
||||||
|
|
|
||||||
|
|
@ -321,6 +321,7 @@ nsSyncLoadService::LoadDocument(nsIURI *aURI,
|
||||||
aLoaderPrincipal,
|
aLoaderPrincipal,
|
||||||
aSecurityFlags,
|
aSecurityFlags,
|
||||||
aContentPolicyType,
|
aContentPolicyType,
|
||||||
|
nullptr, // PerformanceStorage
|
||||||
aLoadGroup);
|
aLoadGroup);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ support-files =
|
||||||
[test_copypaste.xul]
|
[test_copypaste.xul]
|
||||||
subsuite = clipboard
|
subsuite = clipboard
|
||||||
[test_domrequesthelper.xul]
|
[test_domrequesthelper.xul]
|
||||||
|
[test_fragment_sanitization.xul]
|
||||||
[test_messagemanager_principal.html]
|
[test_messagemanager_principal.html]
|
||||||
[test_messagemanager_send_principal.html]
|
[test_messagemanager_send_principal.html]
|
||||||
skip-if = buildapp == 'mulet'
|
skip-if = buildapp == 'mulet'
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=683852
|
||||||
/** Test for Bug 683852 **/
|
/** Test for Bug 683852 **/
|
||||||
SimpleTest.waitForExplicitFinish();
|
SimpleTest.waitForExplicitFinish();
|
||||||
|
|
||||||
|
const NS_HTML = "http://www.w3.org/1999/xhtml";
|
||||||
|
|
||||||
function startTest() {
|
function startTest() {
|
||||||
is(document.contains(document), true, "Document should contain itself!");
|
is(document.contains(document), true, "Document should contain itself!");
|
||||||
|
|
||||||
|
|
@ -48,7 +50,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=683852
|
||||||
document.documentElement.appendChild(pi);
|
document.documentElement.appendChild(pi);
|
||||||
document.contains(pi, true, "Document should contain processing instruction");
|
document.contains(pi, true, "Document should contain processing instruction");
|
||||||
|
|
||||||
var df = document.createRange().createContextualFragment("<div>foo</div>");
|
var df = document.createRange().createContextualFragment(`<div xmlns="${NS_HTML}">foo</div>`);
|
||||||
is(df.contains(df.firstChild), true, "Document fragment should contain its child");
|
is(df.contains(df.firstChild), true, "Document fragment should contain its child");
|
||||||
is(df.contains(df.firstChild.firstChild), true,
|
is(df.contains(df.firstChild.firstChild), true,
|
||||||
"Document fragment should contain its descendant");
|
"Document fragment should contain its descendant");
|
||||||
|
|
|
||||||
101
dom/base/test/test_fragment_sanitization.xul
Normal file
101
dom/base/test/test_fragment_sanitization.xul
Normal file
|
|
@ -0,0 +1,101 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
|
||||||
|
<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
|
||||||
|
<!--
|
||||||
|
https://bugzilla.mozilla.org/show_bug.cgi?id=1432966
|
||||||
|
-->
|
||||||
|
<window title="Mozilla Bug 1432966"
|
||||||
|
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||||
|
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
|
||||||
|
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SpawnTask.js"/>
|
||||||
|
|
||||||
|
<script type="application/javascript"><![CDATA[
|
||||||
|
|
||||||
|
var { classes: Cc, interfaces: Ci } = Components;
|
||||||
|
|
||||||
|
const NS_HTML = "http://www.w3.org/1999/xhtml";
|
||||||
|
|
||||||
|
function awaitLoad(frame) {
|
||||||
|
return new Promise(resolve => {
|
||||||
|
frame.addEventListener("load", resolve, {once: true});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function testFrame(frame, html, expected = html) {
|
||||||
|
document.querySelector("body").appendChild(frame);
|
||||||
|
await awaitLoad(frame);
|
||||||
|
|
||||||
|
// Remove the xmlns attributes that will be automatically added when we're
|
||||||
|
// in an XML document, and break the comparison.
|
||||||
|
function unNS(text) {
|
||||||
|
return text.replace(RegExp(` xmlns="${NS_HTML}"`, "g"), "");
|
||||||
|
}
|
||||||
|
|
||||||
|
let doc = frame.contentDocument;
|
||||||
|
let body = doc.body || doc.documentElement;
|
||||||
|
|
||||||
|
let div = doc.createElementNS(NS_HTML, "div");
|
||||||
|
body.appendChild(div);
|
||||||
|
|
||||||
|
div.innerHTML = html;
|
||||||
|
is(unNS(div.innerHTML), expected, "innerHTML value");
|
||||||
|
|
||||||
|
div.innerHTML = "<div></div>";
|
||||||
|
div.firstChild.outerHTML = html;
|
||||||
|
is(unNS(div.innerHTML), expected, "outerHTML value");
|
||||||
|
|
||||||
|
div.textContent = "";
|
||||||
|
div.insertAdjacentHTML("beforeend", html);
|
||||||
|
is(unNS(div.innerHTML), expected, "insertAdjacentHTML('beforeend') value");
|
||||||
|
|
||||||
|
div.innerHTML = "<a>foo</a>";
|
||||||
|
div.firstChild.insertAdjacentHTML("afterend", html);
|
||||||
|
is(unNS(div.innerHTML), "<a>foo</a>" + expected, "insertAdjacentHTML('afterend') value");
|
||||||
|
|
||||||
|
frame.remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
add_task(async function test_fragment_sanitization() {
|
||||||
|
const XUL_URL = "chrome://global/content/win.xul";
|
||||||
|
const HTML_URL = "chrome://mochitests/content/chrome/dom/base/test/file_empty.html";
|
||||||
|
|
||||||
|
const HTML = '<a onclick="foo()" href="javascript:foo"><script>bar()<\/script>Meh.</a><a href="http://foo/"></a>';
|
||||||
|
const SANITIZED = '<a>Meh.</a><a href="http://foo/"></a>';
|
||||||
|
|
||||||
|
info("Test content HTML document");
|
||||||
|
{
|
||||||
|
let frame = document.createElementNS(NS_HTML, "iframe");
|
||||||
|
frame.src = "http://example.com/";
|
||||||
|
|
||||||
|
await testFrame(frame, HTML);
|
||||||
|
}
|
||||||
|
|
||||||
|
info("Test chrome HTML document");
|
||||||
|
{
|
||||||
|
let frame = document.createElementNS(NS_HTML, "iframe");
|
||||||
|
frame.src = HTML_URL;
|
||||||
|
|
||||||
|
await testFrame(frame, HTML, SANITIZED);
|
||||||
|
}
|
||||||
|
|
||||||
|
info("Test chrome XUL document");
|
||||||
|
{
|
||||||
|
let frame = document.createElementNS(NS_HTML, "iframe");
|
||||||
|
frame.src = XUL_URL;
|
||||||
|
|
||||||
|
await testFrame(frame, HTML, SANITIZED);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
]]></script>
|
||||||
|
|
||||||
|
<description style="-moz-user-focus: normal; -moz-user-select: text;"><![CDATA[
|
||||||
|
hello
|
||||||
|
world
|
||||||
|
]]></description>
|
||||||
|
|
||||||
|
<body xmlns="http://www.w3.org/1999/xhtml">
|
||||||
|
<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1432966"
|
||||||
|
target="_blank">Mozilla Bug 1432966</a>
|
||||||
|
</body>
|
||||||
|
</window>
|
||||||
|
|
@ -18,6 +18,7 @@ NS_IMPL_CYCLE_COLLECTING_ADDREF(ConsoleInstance)
|
||||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(ConsoleInstance)
|
NS_IMPL_CYCLE_COLLECTING_RELEASE(ConsoleInstance)
|
||||||
|
|
||||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ConsoleInstance)
|
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ConsoleInstance)
|
||||||
|
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||||
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
|
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
|
||||||
NS_INTERFACE_MAP_END
|
NS_INTERFACE_MAP_END
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -426,7 +426,9 @@ public:
|
||||||
// We don't track if a worker is spawned from a tracking script for now,
|
// We don't track if a worker is spawned from a tracking script for now,
|
||||||
// so pass false as the last argument to FetchDriver().
|
// so pass false as the last argument to FetchDriver().
|
||||||
fetch = new FetchDriver(mRequest, principal, loadGroup,
|
fetch = new FetchDriver(mRequest, principal, loadGroup,
|
||||||
workerPrivate->MainThreadEventTarget(), false);
|
workerPrivate->MainThreadEventTarget(),
|
||||||
|
workerPrivate->GetPerformanceStorage(),
|
||||||
|
false);
|
||||||
nsAutoCString spec;
|
nsAutoCString spec;
|
||||||
if (proxy->GetWorkerPrivate()->GetBaseURI()) {
|
if (proxy->GetWorkerPrivate()->GetBaseURI()) {
|
||||||
proxy->GetWorkerPrivate()->GetBaseURI()->GetAsciiSpec(spec);
|
proxy->GetWorkerPrivate()->GetBaseURI()->GetAsciiSpec(spec);
|
||||||
|
|
@ -530,7 +532,9 @@ FetchRequest(nsIGlobalObject* aGlobal, const RequestOrUSVString& aInput,
|
||||||
new MainThreadFetchResolver(p, observer, signal, request->MozErrors());
|
new MainThreadFetchResolver(p, observer, signal, request->MozErrors());
|
||||||
RefPtr<FetchDriver> fetch =
|
RefPtr<FetchDriver> fetch =
|
||||||
new FetchDriver(r, principal, loadGroup,
|
new FetchDriver(r, principal, loadGroup,
|
||||||
aGlobal->EventTargetFor(TaskCategory::Other), isTrackingFetch);
|
aGlobal->EventTargetFor(TaskCategory::Other),
|
||||||
|
nullptr, // PerformanceStorage
|
||||||
|
isTrackingFetch);
|
||||||
fetch->SetDocument(doc);
|
fetch->SetDocument(doc);
|
||||||
resolver->SetLoadGroup(loadGroup);
|
resolver->SetLoadGroup(loadGroup);
|
||||||
aRv = fetch->Fetch(signal, resolver);
|
aRv = fetch->Fetch(signal, resolver);
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@
|
||||||
#include "nsHttpChannel.h"
|
#include "nsHttpChannel.h"
|
||||||
|
|
||||||
#include "mozilla/dom/File.h"
|
#include "mozilla/dom/File.h"
|
||||||
|
#include "mozilla/dom/PerformanceStorage.h"
|
||||||
#include "mozilla/dom/workers/Workers.h"
|
#include "mozilla/dom/workers/Workers.h"
|
||||||
#include "mozilla/EventStateManager.h"
|
#include "mozilla/EventStateManager.h"
|
||||||
#include "mozilla/ipc/PBackgroundSharedTypes.h"
|
#include "mozilla/ipc/PBackgroundSharedTypes.h"
|
||||||
|
|
@ -325,13 +326,17 @@ NS_IMPL_ISUPPORTS(FetchDriver,
|
||||||
nsIStreamListener, nsIChannelEventSink, nsIInterfaceRequestor,
|
nsIStreamListener, nsIChannelEventSink, nsIInterfaceRequestor,
|
||||||
nsIThreadRetargetableStreamListener)
|
nsIThreadRetargetableStreamListener)
|
||||||
|
|
||||||
FetchDriver::FetchDriver(InternalRequest* aRequest, nsIPrincipal* aPrincipal,
|
FetchDriver::FetchDriver(InternalRequest* aRequest,
|
||||||
nsILoadGroup* aLoadGroup, nsIEventTarget* aMainThreadEventTarget,
|
nsIPrincipal* aPrincipal,
|
||||||
|
nsILoadGroup* aLoadGroup,
|
||||||
|
nsIEventTarget* aMainThreadEventTarget,
|
||||||
|
PerformanceStorage* aPerformanceStorage,
|
||||||
bool aIsTrackingFetch)
|
bool aIsTrackingFetch)
|
||||||
: mPrincipal(aPrincipal)
|
: mPrincipal(aPrincipal)
|
||||||
, mLoadGroup(aLoadGroup)
|
, mLoadGroup(aLoadGroup)
|
||||||
, mRequest(aRequest)
|
, mRequest(aRequest)
|
||||||
, mMainThreadEventTarget(aMainThreadEventTarget)
|
, mMainThreadEventTarget(aMainThreadEventTarget)
|
||||||
|
, mPerformanceStorage(aPerformanceStorage)
|
||||||
, mNeedToObserveOnDataAvailable(false)
|
, mNeedToObserveOnDataAvailable(false)
|
||||||
, mIsTrackingFetch(aIsTrackingFetch)
|
, mIsTrackingFetch(aIsTrackingFetch)
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
|
@ -516,6 +521,7 @@ FetchDriver::HttpFetch(const nsACString& aPreferredAlternativeDataType)
|
||||||
mDocument,
|
mDocument,
|
||||||
secFlags,
|
secFlags,
|
||||||
mRequest->ContentPolicyType(),
|
mRequest->ContentPolicyType(),
|
||||||
|
nullptr, /* aPerformanceStorage */
|
||||||
mLoadGroup,
|
mLoadGroup,
|
||||||
nullptr, /* aCallbacks */
|
nullptr, /* aCallbacks */
|
||||||
loadFlags,
|
loadFlags,
|
||||||
|
|
@ -528,6 +534,7 @@ FetchDriver::HttpFetch(const nsACString& aPreferredAlternativeDataType)
|
||||||
mController,
|
mController,
|
||||||
secFlags,
|
secFlags,
|
||||||
mRequest->ContentPolicyType(),
|
mRequest->ContentPolicyType(),
|
||||||
|
mPerformanceStorage,
|
||||||
mLoadGroup,
|
mLoadGroup,
|
||||||
nullptr, /* aCallbacks */
|
nullptr, /* aCallbacks */
|
||||||
loadFlags,
|
loadFlags,
|
||||||
|
|
@ -538,6 +545,7 @@ FetchDriver::HttpFetch(const nsACString& aPreferredAlternativeDataType)
|
||||||
mPrincipal,
|
mPrincipal,
|
||||||
secFlags,
|
secFlags,
|
||||||
mRequest->ContentPolicyType(),
|
mRequest->ContentPolicyType(),
|
||||||
|
mPerformanceStorage,
|
||||||
mLoadGroup,
|
mLoadGroup,
|
||||||
nullptr, /* aCallbacks */
|
nullptr, /* aCallbacks */
|
||||||
loadFlags,
|
loadFlags,
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@ namespace dom {
|
||||||
|
|
||||||
class InternalRequest;
|
class InternalRequest;
|
||||||
class InternalResponse;
|
class InternalResponse;
|
||||||
|
class PerformanceStorage;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides callbacks to be called when response is available or on error.
|
* Provides callbacks to be called when response is available or on error.
|
||||||
|
|
@ -109,6 +110,7 @@ public:
|
||||||
nsIPrincipal* aPrincipal,
|
nsIPrincipal* aPrincipal,
|
||||||
nsILoadGroup* aLoadGroup,
|
nsILoadGroup* aLoadGroup,
|
||||||
nsIEventTarget* aMainThreadEventTarget,
|
nsIEventTarget* aMainThreadEventTarget,
|
||||||
|
PerformanceStorage* aPerformanceStorage,
|
||||||
bool aIsTrackingFetch);
|
bool aIsTrackingFetch);
|
||||||
|
|
||||||
nsresult Fetch(AbortSignal* aSignal,
|
nsresult Fetch(AbortSignal* aSignal,
|
||||||
|
|
@ -147,6 +149,10 @@ private:
|
||||||
nsCOMPtr<nsIChannel> mChannel;
|
nsCOMPtr<nsIChannel> mChannel;
|
||||||
nsAutoPtr<SRICheckDataVerifier> mSRIDataVerifier;
|
nsAutoPtr<SRICheckDataVerifier> mSRIDataVerifier;
|
||||||
nsCOMPtr<nsIEventTarget> mMainThreadEventTarget;
|
nsCOMPtr<nsIEventTarget> mMainThreadEventTarget;
|
||||||
|
|
||||||
|
// This is set only when Fetch is used in workers.
|
||||||
|
RefPtr<PerformanceStorage> mPerformanceStorage;
|
||||||
|
|
||||||
SRIMetadata mSRIMetadata;
|
SRIMetadata mSRIMetadata;
|
||||||
nsCString mWorkerScript;
|
nsCString mWorkerScript;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -139,6 +139,39 @@ HTMLFieldSetElement::SubmitNamesValues(HTMLFormSubmission* aFormSubmission)
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
HTMLFieldSetElement::InsertChildBefore(nsIContent* aChild,
|
||||||
|
nsIContent* aBeforeThis,
|
||||||
|
bool aNotify)
|
||||||
|
{
|
||||||
|
bool firstLegendHasChanged = false;
|
||||||
|
|
||||||
|
if (aChild->IsHTMLElement(nsGkAtoms::legend)) {
|
||||||
|
if (!mFirstLegend) {
|
||||||
|
mFirstLegend = aChild;
|
||||||
|
// We do not want to notify the first time mFirstElement is set.
|
||||||
|
} else {
|
||||||
|
// If mFirstLegend is before aIndex, we do not change it.
|
||||||
|
// Otherwise, mFirstLegend is now aChild.
|
||||||
|
int32_t index = aBeforeThis ? ComputeIndexOf(aBeforeThis) : GetChildCount();
|
||||||
|
if (index <= ComputeIndexOf(mFirstLegend)) {
|
||||||
|
mFirstLegend = aChild;
|
||||||
|
firstLegendHasChanged = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult rv =
|
||||||
|
nsGenericHTMLFormElement::InsertChildBefore(aChild, aBeforeThis, aNotify);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
if (firstLegendHasChanged) {
|
||||||
|
NotifyElementsForFirstLegendChange(aNotify);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
HTMLFieldSetElement::InsertChildAt_Deprecated(nsIContent* aChild,
|
HTMLFieldSetElement::InsertChildAt_Deprecated(nsIContent* aChild,
|
||||||
uint32_t aIndex,
|
uint32_t aIndex,
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,8 @@ public:
|
||||||
nsIPrincipal* aSubjectPrincipal,
|
nsIPrincipal* aSubjectPrincipal,
|
||||||
bool aNotify) override;
|
bool aNotify) override;
|
||||||
|
|
||||||
|
virtual nsresult InsertChildBefore(nsIContent* aChild, nsIContent* aBeforeThis,
|
||||||
|
bool aNotify) override;
|
||||||
virtual nsresult InsertChildAt_Deprecated(nsIContent* aChild, uint32_t aIndex,
|
virtual nsresult InsertChildAt_Deprecated(nsIContent* aChild, uint32_t aIndex,
|
||||||
bool aNotify) override;
|
bool aNotify) override;
|
||||||
virtual void RemoveChildAt_Deprecated(uint32_t aIndex, bool aNotify) override;
|
virtual void RemoveChildAt_Deprecated(uint32_t aIndex, bool aNotify) override;
|
||||||
|
|
|
||||||
|
|
@ -1218,6 +1218,7 @@ public:
|
||||||
triggeringPrincipal,
|
triggeringPrincipal,
|
||||||
securityFlags,
|
securityFlags,
|
||||||
contentPolicyType,
|
contentPolicyType,
|
||||||
|
nullptr, // aPerformanceStorage
|
||||||
loadGroup,
|
loadGroup,
|
||||||
nullptr, // aCallbacks
|
nullptr, // aCallbacks
|
||||||
nsICachingChannel::LOAD_BYPASS_LOCAL_CACHE_IF_BUSY |
|
nsICachingChannel::LOAD_BYPASS_LOCAL_CACHE_IF_BUSY |
|
||||||
|
|
|
||||||
|
|
@ -74,6 +74,21 @@ HTMLOptGroupElement::GetSelect()
|
||||||
return parent;
|
return parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
HTMLOptGroupElement::InsertChildBefore(nsIContent* aKid,
|
||||||
|
nsIContent* aBeforeThis,
|
||||||
|
bool aNotify)
|
||||||
|
{
|
||||||
|
int32_t index = aBeforeThis ? ComputeIndexOf(aBeforeThis) : GetChildCount();
|
||||||
|
SafeOptionListMutation safeMutation(GetSelect(), this, aKid, index, aNotify);
|
||||||
|
nsresult rv =
|
||||||
|
nsGenericHTMLElement::InsertChildBefore(aKid, aBeforeThis, aNotify);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
safeMutation.MutationFailed();
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
HTMLOptGroupElement::InsertChildAt_Deprecated(nsIContent* aKid,
|
HTMLOptGroupElement::InsertChildAt_Deprecated(nsIContent* aKid,
|
||||||
uint32_t aIndex,
|
uint32_t aIndex,
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,8 @@ public:
|
||||||
NS_DECL_ISUPPORTS_INHERITED
|
NS_DECL_ISUPPORTS_INHERITED
|
||||||
|
|
||||||
// nsINode
|
// nsINode
|
||||||
|
virtual nsresult InsertChildBefore(nsIContent* aKid, nsIContent* aBeforeThis,
|
||||||
|
bool aNotify) override;
|
||||||
virtual nsresult InsertChildAt_Deprecated(nsIContent* aKid, uint32_t aIndex,
|
virtual nsresult InsertChildAt_Deprecated(nsIContent* aKid, uint32_t aIndex,
|
||||||
bool aNotify) override;
|
bool aNotify) override;
|
||||||
virtual void RemoveChildAt_Deprecated(uint32_t aIndex, bool aNotify) override;
|
virtual void RemoveChildAt_Deprecated(uint32_t aIndex, bool aNotify) override;
|
||||||
|
|
|
||||||
|
|
@ -82,6 +82,37 @@ HTMLPictureElement::RemoveChildNode(nsIContent* aKid, bool aNotify)
|
||||||
nsGenericHTMLElement::RemoveChildNode(aKid, aNotify);
|
nsGenericHTMLElement::RemoveChildNode(aKid, aNotify);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
HTMLPictureElement::InsertChildBefore(nsIContent* aKid, nsIContent* aBeforeThis,
|
||||||
|
bool aNotify)
|
||||||
|
{
|
||||||
|
nsresult rv =
|
||||||
|
nsGenericHTMLElement::InsertChildBefore(aKid, aBeforeThis, aNotify);
|
||||||
|
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
NS_ENSURE_TRUE(aKid, rv);
|
||||||
|
|
||||||
|
if (aKid->IsHTMLElement(nsGkAtoms::img)) {
|
||||||
|
HTMLImageElement* img = HTMLImageElement::FromContent(aKid);
|
||||||
|
if (img) {
|
||||||
|
img->PictureSourceAdded(aKid->AsContent());
|
||||||
|
}
|
||||||
|
} else if (aKid->IsHTMLElement(nsGkAtoms::source)) {
|
||||||
|
// Find all img siblings after this <source> to notify them of its insertion
|
||||||
|
nsCOMPtr<nsIContent> nextSibling = aKid->GetNextSibling();
|
||||||
|
if (nextSibling && nextSibling->GetParentNode() == this) {
|
||||||
|
do {
|
||||||
|
HTMLImageElement* img = HTMLImageElement::FromContent(nextSibling);
|
||||||
|
if (img) {
|
||||||
|
img->PictureSourceAdded(aKid->AsContent());
|
||||||
|
}
|
||||||
|
} while ( (nextSibling = nextSibling->GetNextSibling()) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
HTMLPictureElement::InsertChildAt_Deprecated(nsIContent* aKid, uint32_t aIndex, bool aNotify)
|
HTMLPictureElement::InsertChildAt_Deprecated(nsIContent* aKid, uint32_t aIndex, bool aNotify)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,10 @@ public:
|
||||||
bool aPreallocateChildren) const override;
|
bool aPreallocateChildren) const override;
|
||||||
virtual void RemoveChildAt_Deprecated(uint32_t aIndex, bool aNotify) override;
|
virtual void RemoveChildAt_Deprecated(uint32_t aIndex, bool aNotify) override;
|
||||||
virtual void RemoveChildNode(nsIContent* aKid, bool aNotify) override;
|
virtual void RemoveChildNode(nsIContent* aKid, bool aNotify) override;
|
||||||
virtual nsresult InsertChildAt_Deprecated(nsIContent* aKid, uint32_t aIndex, bool aNotify) override;
|
virtual nsresult InsertChildBefore(nsIContent* aKid, nsIContent* aBeforeThis,
|
||||||
|
bool aNotify) override;
|
||||||
|
virtual nsresult InsertChildAt_Deprecated(nsIContent* aKid, uint32_t aIndex,
|
||||||
|
bool aNotify) override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual ~HTMLPictureElement();
|
virtual ~HTMLPictureElement();
|
||||||
|
|
|
||||||
|
|
@ -203,6 +203,22 @@ HTMLSelectElement::GetAutocompleteInfo(AutocompleteInfo& aInfo)
|
||||||
true);
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
HTMLSelectElement::InsertChildBefore(nsIContent* aKid,
|
||||||
|
nsIContent* aBeforeThis,
|
||||||
|
bool aNotify)
|
||||||
|
{
|
||||||
|
int32_t index = aBeforeThis ? ComputeIndexOf(aBeforeThis) : GetChildCount();
|
||||||
|
SafeOptionListMutation safeMutation(this, this, aKid, index, aNotify);
|
||||||
|
nsresult rv =
|
||||||
|
nsGenericHTMLFormElementWithState::InsertChildBefore(aKid, aBeforeThis,
|
||||||
|
aNotify);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
safeMutation.MutationFailed();
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
HTMLSelectElement::InsertChildAt_Deprecated(nsIContent* aKid,
|
HTMLSelectElement::InsertChildAt_Deprecated(nsIContent* aKid,
|
||||||
uint32_t aIndex,
|
uint32_t aIndex,
|
||||||
|
|
|
||||||
|
|
@ -291,6 +291,8 @@ public:
|
||||||
EventChainPostVisitor& aVisitor) override;
|
EventChainPostVisitor& aVisitor) override;
|
||||||
|
|
||||||
virtual bool IsHTMLFocusable(bool aWithMouse, bool* aIsFocusable, int32_t* aTabIndex) override;
|
virtual bool IsHTMLFocusable(bool aWithMouse, bool* aIsFocusable, int32_t* aTabIndex) override;
|
||||||
|
virtual nsresult InsertChildBefore(nsIContent* aKid, nsIContent* aBeforeThis,
|
||||||
|
bool aNotify) override;
|
||||||
virtual nsresult InsertChildAt_Deprecated(nsIContent* aKid, uint32_t aIndex,
|
virtual nsresult InsertChildAt_Deprecated(nsIContent* aKid, uint32_t aIndex,
|
||||||
bool aNotify) override;
|
bool aNotify) override;
|
||||||
virtual void RemoveChildAt_Deprecated(uint32_t aIndex, bool aNotify) override;
|
virtual void RemoveChildAt_Deprecated(uint32_t aIndex, bool aNotify) override;
|
||||||
|
|
|
||||||
|
|
@ -327,6 +327,7 @@ HTMLTrackElement::LoadResource()
|
||||||
static_cast<Element*>(this),
|
static_cast<Element*>(this),
|
||||||
secFlags,
|
secFlags,
|
||||||
nsIContentPolicy::TYPE_INTERNAL_TRACK,
|
nsIContentPolicy::TYPE_INTERNAL_TRACK,
|
||||||
|
nullptr, // PerformanceStorage
|
||||||
loadGroup,
|
loadGroup,
|
||||||
nullptr, // aCallbacks
|
nullptr, // aCallbacks
|
||||||
nsIRequest::LOAD_NORMAL | nsIChannel::LOAD_CLASSIFY_URI);
|
nsIRequest::LOAD_NORMAL | nsIChannel::LOAD_CLASSIFY_URI);
|
||||||
|
|
|
||||||
|
|
@ -175,8 +175,7 @@ protected:
|
||||||
void UpdateChildCounts() override;
|
void UpdateChildCounts() override;
|
||||||
|
|
||||||
void NotifyInsert(nsIContent* aContent,
|
void NotifyInsert(nsIContent* aContent,
|
||||||
nsIContent* aChildContent,
|
nsIContent* aChildContent);
|
||||||
int32_t aIndexInContainer);
|
|
||||||
void NotifyRootInsertion();
|
void NotifyRootInsertion();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -329,10 +328,7 @@ SinkContext::DidAddContent(nsIContent* aContent)
|
||||||
mStack[mStackPos - 1].mNumFlushed <
|
mStack[mStackPos - 1].mNumFlushed <
|
||||||
mStack[mStackPos - 1].mContent->GetChildCount()) {
|
mStack[mStackPos - 1].mContent->GetChildCount()) {
|
||||||
nsIContent* parent = mStack[mStackPos - 1].mContent;
|
nsIContent* parent = mStack[mStackPos - 1].mContent;
|
||||||
int32_t childIndex = mStack[mStackPos - 1].mInsertionPoint - 1;
|
mSink->NotifyInsert(parent, aContent);
|
||||||
NS_ASSERTION(parent->GetChildAt_Deprecated(childIndex) == aContent,
|
|
||||||
"Flushing the wrong child.");
|
|
||||||
mSink->NotifyInsert(parent, aContent, childIndex);
|
|
||||||
mStack[mStackPos - 1].mNumFlushed = parent->GetChildCount();
|
mStack[mStackPos - 1].mNumFlushed = parent->GetChildCount();
|
||||||
} else if (mSink->IsTimeToNotify()) {
|
} else if (mSink->IsTimeToNotify()) {
|
||||||
FlushTags();
|
FlushTags();
|
||||||
|
|
@ -397,7 +393,9 @@ SinkContext::Node::Add(nsIContent *child)
|
||||||
if (mInsertionPoint != -1) {
|
if (mInsertionPoint != -1) {
|
||||||
NS_ASSERTION(mNumFlushed == mContent->GetChildCount(),
|
NS_ASSERTION(mNumFlushed == mContent->GetChildCount(),
|
||||||
"Inserting multiple children without flushing.");
|
"Inserting multiple children without flushing.");
|
||||||
mContent->InsertChildAt_Deprecated(child, mInsertionPoint++, false);
|
nsCOMPtr<nsIContent> nodeToInsertBefore =
|
||||||
|
mContent->GetChildAt_Deprecated(mInsertionPoint++);
|
||||||
|
mContent->InsertChildBefore(child, nodeToInsertBefore, false);
|
||||||
} else {
|
} else {
|
||||||
mContent->AppendChildTo(child, false);
|
mContent->AppendChildTo(child, false);
|
||||||
}
|
}
|
||||||
|
|
@ -529,7 +527,7 @@ SinkContext::FlushTags()
|
||||||
NS_ASSERTION(!(mStackPos > (stackPos + 1)) ||
|
NS_ASSERTION(!(mStackPos > (stackPos + 1)) ||
|
||||||
(child == mStack[stackPos + 1].mContent),
|
(child == mStack[stackPos + 1].mContent),
|
||||||
"Flushing the wrong child.");
|
"Flushing the wrong child.");
|
||||||
mSink->NotifyInsert(content, child, childIndex);
|
mSink->NotifyInsert(content, child);
|
||||||
} else {
|
} else {
|
||||||
mSink->NotifyAppend(content, mStack[stackPos].mNumFlushed);
|
mSink->NotifyAppend(content, mStack[stackPos].mNumFlushed);
|
||||||
}
|
}
|
||||||
|
|
@ -849,7 +847,7 @@ HTMLContentSink::OpenBody()
|
||||||
uint32_t oldUpdates = mUpdatesInNotification;
|
uint32_t oldUpdates = mUpdatesInNotification;
|
||||||
mUpdatesInNotification = 0;
|
mUpdatesInNotification = 0;
|
||||||
if (insertionPoint != -1) {
|
if (insertionPoint != -1) {
|
||||||
NotifyInsert(parent, mBody, insertionPoint - 1);
|
NotifyInsert(parent, mBody);
|
||||||
} else {
|
} else {
|
||||||
NotifyAppend(parent, numFlushed);
|
NotifyAppend(parent, numFlushed);
|
||||||
}
|
}
|
||||||
|
|
@ -947,8 +945,7 @@ HTMLContentSink::CloseHeadContext()
|
||||||
|
|
||||||
void
|
void
|
||||||
HTMLContentSink::NotifyInsert(nsIContent* aContent,
|
HTMLContentSink::NotifyInsert(nsIContent* aContent,
|
||||||
nsIContent* aChildContent,
|
nsIContent* aChildContent)
|
||||||
int32_t aIndexInContainer)
|
|
||||||
{
|
{
|
||||||
if (aContent && aContent->GetUncomposedDoc() != mDocument) {
|
if (aContent && aContent->GetUncomposedDoc() != mDocument) {
|
||||||
// aContent is not actually in our document anymore.... Just bail out of
|
// aContent is not actually in our document anymore.... Just bail out of
|
||||||
|
|
@ -983,9 +980,7 @@ HTMLContentSink::NotifyRootInsertion()
|
||||||
// document; in those cases we just want to put all the attrs on one
|
// document; in those cases we just want to put all the attrs on one
|
||||||
// tag.
|
// tag.
|
||||||
mNotifiedRootInsertion = true;
|
mNotifiedRootInsertion = true;
|
||||||
int32_t index = mDocument->ComputeIndexOf(mRoot);
|
NotifyInsert(nullptr, mRoot);
|
||||||
NS_ASSERTION(index != -1, "mRoot not child of document?");
|
|
||||||
NotifyInsert(nullptr, mRoot, index);
|
|
||||||
|
|
||||||
// Now update the notification information in all our
|
// Now update the notification information in all our
|
||||||
// contexts, since we just inserted the root and notified on
|
// contexts, since we just inserted the root and notified on
|
||||||
|
|
|
||||||
|
|
@ -1630,6 +1630,7 @@ nsHTMLDocument::Open(JSContext* cx,
|
||||||
callerDoc,
|
callerDoc,
|
||||||
nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL,
|
nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL,
|
||||||
nsIContentPolicy::TYPE_OTHER,
|
nsIContentPolicy::TYPE_OTHER,
|
||||||
|
nullptr, // PerformanceStorage
|
||||||
group);
|
group);
|
||||||
|
|
||||||
if (aError.Failed()) {
|
if (aError.Failed()) {
|
||||||
|
|
|
||||||
|
|
@ -726,6 +726,7 @@ ChannelMediaResource::RecreateChannel()
|
||||||
triggeringPrincipal,
|
triggeringPrincipal,
|
||||||
securityFlags,
|
securityFlags,
|
||||||
contentPolicyType,
|
contentPolicyType,
|
||||||
|
nullptr, // aPerformanceStorage
|
||||||
loadGroup,
|
loadGroup,
|
||||||
nullptr, // aCallbacks
|
nullptr, // aCallbacks
|
||||||
loadFlags);
|
loadFlags);
|
||||||
|
|
|
||||||
|
|
@ -237,7 +237,6 @@ Performance::ClearUserEntries(const Optional<nsAString>& aEntryName,
|
||||||
void
|
void
|
||||||
Performance::ClearResourceTimings()
|
Performance::ClearResourceTimings()
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
|
||||||
mResourceEntries.Clear();
|
mResourceEntries.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -431,13 +430,14 @@ void
|
||||||
Performance::InsertResourceEntry(PerformanceEntry* aEntry)
|
Performance::InsertResourceEntry(PerformanceEntry* aEntry)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(aEntry);
|
MOZ_ASSERT(aEntry);
|
||||||
MOZ_ASSERT(mResourceEntries.Length() < mResourceTimingBufferSize);
|
MOZ_ASSERT(mResourceEntries.Length() <= mResourceTimingBufferSize);
|
||||||
|
|
||||||
// We won't add an entry when 'privacy.resistFingerprint' is true.
|
// We won't add an entry when 'privacy.resistFingerprint' is true.
|
||||||
if (nsContentUtils::ShouldResistFingerprinting()) {
|
if (nsContentUtils::ShouldResistFingerprinting()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Don't add the entry if the buffer is full
|
||||||
if (mResourceEntries.Length() >= mResourceTimingBufferSize) {
|
if (mResourceEntries.Length() >= mResourceTimingBufferSize) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,6 @@
|
||||||
#include "nsDOMNavigationTiming.h"
|
#include "nsDOMNavigationTiming.h"
|
||||||
|
|
||||||
class nsITimedChannel;
|
class nsITimedChannel;
|
||||||
class nsIHttpChannel;
|
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
|
||||||
|
|
@ -25,6 +24,7 @@ class PerformanceEntry;
|
||||||
class PerformanceNavigation;
|
class PerformanceNavigation;
|
||||||
class PerformanceObserver;
|
class PerformanceObserver;
|
||||||
class PerformanceService;
|
class PerformanceService;
|
||||||
|
class PerformanceStorage;
|
||||||
class PerformanceTiming;
|
class PerformanceTiming;
|
||||||
|
|
||||||
namespace workers {
|
namespace workers {
|
||||||
|
|
@ -61,8 +61,7 @@ public:
|
||||||
const Optional<nsAString>& aEntryType,
|
const Optional<nsAString>& aEntryType,
|
||||||
nsTArray<RefPtr<PerformanceEntry>>& aRetval);
|
nsTArray<RefPtr<PerformanceEntry>>& aRetval);
|
||||||
|
|
||||||
virtual void AddEntry(nsIHttpChannel* channel,
|
virtual PerformanceStorage* AsPerformanceStorage() = 0;
|
||||||
nsITimedChannel* timedChannel) = 0;
|
|
||||||
|
|
||||||
void ClearResourceTimings();
|
void ClearResourceTimings();
|
||||||
|
|
||||||
|
|
@ -101,11 +100,15 @@ public:
|
||||||
|
|
||||||
virtual nsITimedChannel* GetChannel() const = 0;
|
virtual nsITimedChannel* GetChannel() const = 0;
|
||||||
|
|
||||||
|
virtual TimeStamp CreationTimeStamp() const = 0;
|
||||||
|
|
||||||
void MemoryPressure();
|
void MemoryPressure();
|
||||||
|
|
||||||
size_t SizeOfUserEntries(mozilla::MallocSizeOf aMallocSizeOf) const;
|
size_t SizeOfUserEntries(mozilla::MallocSizeOf aMallocSizeOf) const;
|
||||||
size_t SizeOfResourceEntries(mozilla::MallocSizeOf aMallocSizeOf) const;
|
size_t SizeOfResourceEntries(mozilla::MallocSizeOf aMallocSizeOf) const;
|
||||||
|
|
||||||
|
void InsertResourceEntry(PerformanceEntry* aEntry);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Performance();
|
Performance();
|
||||||
explicit Performance(nsPIDOMWindowInner* aWindow);
|
explicit Performance(nsPIDOMWindowInner* aWindow);
|
||||||
|
|
@ -113,7 +116,6 @@ protected:
|
||||||
virtual ~Performance();
|
virtual ~Performance();
|
||||||
|
|
||||||
virtual void InsertUserEntry(PerformanceEntry* aEntry);
|
virtual void InsertUserEntry(PerformanceEntry* aEntry);
|
||||||
void InsertResourceEntry(PerformanceEntry* aEntry);
|
|
||||||
|
|
||||||
void ClearUserEntries(const Optional<nsAString>& aEntryName,
|
void ClearUserEntries(const Optional<nsAString>& aEntryName,
|
||||||
const nsAString& aEntryType);
|
const nsAString& aEntryType);
|
||||||
|
|
@ -123,8 +125,6 @@ protected:
|
||||||
|
|
||||||
virtual void DispatchBufferFullEvent() = 0;
|
virtual void DispatchBufferFullEvent() = 0;
|
||||||
|
|
||||||
virtual TimeStamp CreationTimeStamp() const = 0;
|
|
||||||
|
|
||||||
virtual DOMHighResTimeStamp CreationTime() const = 0;
|
virtual DOMHighResTimeStamp CreationTime() const = 0;
|
||||||
|
|
||||||
virtual bool IsPerformanceTimingAttribute(const nsAString& aName)
|
virtual bool IsPerformanceTimingAttribute(const nsAString& aName)
|
||||||
|
|
@ -138,11 +138,6 @@ protected:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsResourceEntryLimitReached() const
|
|
||||||
{
|
|
||||||
return mResourceEntries.Length() >= mResourceTimingBufferSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
void LogEntry(PerformanceEntry* aEntry, const nsACString& aOwner) const;
|
void LogEntry(PerformanceEntry* aEntry, const nsACString& aOwner) const;
|
||||||
void TimingNotification(PerformanceEntry* aEntry, const nsACString& aOwner,
|
void TimingNotification(PerformanceEntry* aEntry, const nsACString& aOwner,
|
||||||
uint64_t epoch);
|
uint64_t epoch);
|
||||||
|
|
|
||||||
|
|
@ -118,64 +118,24 @@ PerformanceMainThread::AddEntry(nsIHttpChannel* channel,
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
|
||||||
// Check if resource timing is prefed off.
|
nsAutoString initiatorType;
|
||||||
if (!nsContentUtils::IsResourceTimingEnabled()) {
|
nsAutoString entryName;
|
||||||
|
|
||||||
|
UniquePtr<PerformanceTimingData> performanceTimingData(
|
||||||
|
PerformanceTimingData::Create(timedChannel, channel, 0, initiatorType,
|
||||||
|
entryName));
|
||||||
|
if (!performanceTimingData) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't add the entry if the buffer is full
|
// The PerformanceResourceTiming object will use the PerformanceTimingData
|
||||||
if (IsResourceEntryLimitReached()) {
|
// object to get all the required timings.
|
||||||
return;
|
RefPtr<PerformanceResourceTiming> performanceEntry =
|
||||||
}
|
new PerformanceResourceTiming(Move(performanceTimingData), this,
|
||||||
|
entryName);
|
||||||
|
|
||||||
if (channel && timedChannel) {
|
performanceEntry->SetInitiatorType(initiatorType);
|
||||||
nsAutoCString name;
|
InsertResourceEntry(performanceEntry);
|
||||||
nsAutoString initiatorType;
|
|
||||||
nsCOMPtr<nsIURI> originalURI;
|
|
||||||
|
|
||||||
timedChannel->GetInitiatorType(initiatorType);
|
|
||||||
|
|
||||||
// According to the spec, "The name attribute must return the resolved URL
|
|
||||||
// of the requested resource. This attribute must not change even if the
|
|
||||||
// fetch redirected to a different URL."
|
|
||||||
channel->GetOriginalURI(getter_AddRefs(originalURI));
|
|
||||||
originalURI->GetSpec(name);
|
|
||||||
NS_ConvertUTF8toUTF16 entryName(name);
|
|
||||||
|
|
||||||
bool reportTiming = true;
|
|
||||||
timedChannel->GetReportResourceTiming(&reportTiming);
|
|
||||||
|
|
||||||
if (!reportTiming) {
|
|
||||||
#ifdef DEBUG_jwatt
|
|
||||||
NS_WARNING(
|
|
||||||
nsPrintfCString("Not reporting CORS resource: %s", name.get()).get());
|
|
||||||
#endif
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// The nsITimedChannel argument will be used to gather all the timings.
|
|
||||||
// The nsIHttpChannel argument will be used to check if any cross-origin
|
|
||||||
// redirects occurred.
|
|
||||||
// The last argument is the "zero time" (offset). Since we don't want
|
|
||||||
// any offset for the resource timing, this will be set to "0" - the
|
|
||||||
// resource timing returns a relative timing (no offset).
|
|
||||||
RefPtr<PerformanceTiming> performanceTiming =
|
|
||||||
new PerformanceTiming(this, timedChannel, channel,
|
|
||||||
0);
|
|
||||||
|
|
||||||
// The PerformanceResourceTiming object will use the PerformanceTiming
|
|
||||||
// object to get all the required timings.
|
|
||||||
RefPtr<PerformanceResourceTiming> performanceEntry =
|
|
||||||
new PerformanceResourceTiming(performanceTiming, this, entryName, channel);
|
|
||||||
|
|
||||||
// If the initiator type had no valid value, then set it to the default
|
|
||||||
// ("other") value.
|
|
||||||
if (initiatorType.IsEmpty()) {
|
|
||||||
initiatorType = NS_LITERAL_STRING("other");
|
|
||||||
}
|
|
||||||
performanceEntry->SetInitiatorType(initiatorType);
|
|
||||||
InsertResourceEntry(performanceEntry);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// To be removed once bug 1124165 lands
|
// To be removed once bug 1124165 lands
|
||||||
|
|
@ -325,11 +285,15 @@ void
|
||||||
PerformanceMainThread::EnsureDocEntry()
|
PerformanceMainThread::EnsureDocEntry()
|
||||||
{
|
{
|
||||||
if (!mDocEntry && nsContentUtils::IsPerformanceNavigationTimingEnabled()) {
|
if (!mDocEntry && nsContentUtils::IsPerformanceNavigationTimingEnabled()) {
|
||||||
|
UniquePtr<PerformanceTimingData> timing(
|
||||||
|
new PerformanceTimingData(mChannel, nullptr, 0));
|
||||||
|
|
||||||
nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(mChannel);
|
nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(mChannel);
|
||||||
RefPtr<PerformanceTiming> timing =
|
if (httpChannel) {
|
||||||
new PerformanceTiming(this, mChannel, nullptr, 0);
|
timing->SetPropertiesFromHttpChannel(httpChannel);
|
||||||
mDocEntry = new PerformanceNavigationTiming(timing, this,
|
}
|
||||||
httpChannel);
|
|
||||||
|
mDocEntry = new PerformanceNavigationTiming(Move(timing), this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,11 +8,13 @@
|
||||||
#define mozilla_dom_PerformanceMainThread_h
|
#define mozilla_dom_PerformanceMainThread_h
|
||||||
|
|
||||||
#include "Performance.h"
|
#include "Performance.h"
|
||||||
|
#include "PerformanceStorage.h"
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace dom {
|
namespace dom {
|
||||||
|
|
||||||
class PerformanceMainThread final : public Performance
|
class PerformanceMainThread final : public Performance
|
||||||
|
, public PerformanceStorage
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PerformanceMainThread(nsPIDOMWindowInner* aWindow,
|
PerformanceMainThread(nsPIDOMWindowInner* aWindow,
|
||||||
|
|
@ -23,6 +25,11 @@ public:
|
||||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(PerformanceMainThread,
|
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(PerformanceMainThread,
|
||||||
Performance)
|
Performance)
|
||||||
|
|
||||||
|
PerformanceStorage* AsPerformanceStorage() override
|
||||||
|
{
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
virtual PerformanceTiming* Timing() override;
|
virtual PerformanceTiming* Timing() override;
|
||||||
|
|
||||||
virtual PerformanceNavigation* Navigation() override;
|
virtual PerformanceNavigation* Navigation() override;
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ PerformanceNavigation::WrapObject(JSContext *cx,
|
||||||
uint16_t
|
uint16_t
|
||||||
PerformanceNavigation::RedirectCount() const
|
PerformanceNavigation::RedirectCount() const
|
||||||
{
|
{
|
||||||
return GetPerformanceTiming()->GetRedirectCount();
|
return GetPerformanceTiming()->Data()->GetRedirectCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // dom namespace
|
} // dom namespace
|
||||||
|
|
|
||||||
|
|
@ -24,55 +24,55 @@ PerformanceNavigationTiming::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aG
|
||||||
DOMHighResTimeStamp
|
DOMHighResTimeStamp
|
||||||
PerformanceNavigationTiming::UnloadEventStart() const
|
PerformanceNavigationTiming::UnloadEventStart() const
|
||||||
{
|
{
|
||||||
return mTiming->GetDOMTiming()->GetUnloadEventStartHighRes();
|
return mPerformance->GetDOMTiming()->GetUnloadEventStartHighRes();
|
||||||
}
|
}
|
||||||
|
|
||||||
DOMHighResTimeStamp
|
DOMHighResTimeStamp
|
||||||
PerformanceNavigationTiming::UnloadEventEnd() const
|
PerformanceNavigationTiming::UnloadEventEnd() const
|
||||||
{
|
{
|
||||||
return mTiming->GetDOMTiming()->GetUnloadEventEndHighRes();
|
return mPerformance->GetDOMTiming()->GetUnloadEventEndHighRes();
|
||||||
}
|
}
|
||||||
|
|
||||||
DOMHighResTimeStamp
|
DOMHighResTimeStamp
|
||||||
PerformanceNavigationTiming::DomInteractive() const
|
PerformanceNavigationTiming::DomInteractive() const
|
||||||
{
|
{
|
||||||
return mTiming->GetDOMTiming()->GetDomInteractiveHighRes();
|
return mPerformance->GetDOMTiming()->GetDomInteractiveHighRes();
|
||||||
}
|
}
|
||||||
|
|
||||||
DOMHighResTimeStamp
|
DOMHighResTimeStamp
|
||||||
PerformanceNavigationTiming::DomContentLoadedEventStart() const
|
PerformanceNavigationTiming::DomContentLoadedEventStart() const
|
||||||
{
|
{
|
||||||
return mTiming->GetDOMTiming()->GetDomContentLoadedEventStartHighRes();
|
return mPerformance->GetDOMTiming()->GetDomContentLoadedEventStartHighRes();
|
||||||
}
|
}
|
||||||
|
|
||||||
DOMHighResTimeStamp
|
DOMHighResTimeStamp
|
||||||
PerformanceNavigationTiming::DomContentLoadedEventEnd() const
|
PerformanceNavigationTiming::DomContentLoadedEventEnd() const
|
||||||
{
|
{
|
||||||
return mTiming->GetDOMTiming()->GetDomContentLoadedEventEndHighRes();
|
return mPerformance->GetDOMTiming()->GetDomContentLoadedEventEndHighRes();
|
||||||
}
|
}
|
||||||
|
|
||||||
DOMHighResTimeStamp
|
DOMHighResTimeStamp
|
||||||
PerformanceNavigationTiming::DomComplete() const
|
PerformanceNavigationTiming::DomComplete() const
|
||||||
{
|
{
|
||||||
return mTiming->GetDOMTiming()->GetDomCompleteHighRes();
|
return mPerformance->GetDOMTiming()->GetDomCompleteHighRes();
|
||||||
}
|
}
|
||||||
|
|
||||||
DOMHighResTimeStamp
|
DOMHighResTimeStamp
|
||||||
PerformanceNavigationTiming::LoadEventStart() const
|
PerformanceNavigationTiming::LoadEventStart() const
|
||||||
{
|
{
|
||||||
return mTiming->GetDOMTiming()->GetLoadEventStartHighRes();
|
return mPerformance->GetDOMTiming()->GetLoadEventStartHighRes();
|
||||||
}
|
}
|
||||||
|
|
||||||
DOMHighResTimeStamp
|
DOMHighResTimeStamp
|
||||||
PerformanceNavigationTiming::LoadEventEnd() const
|
PerformanceNavigationTiming::LoadEventEnd() const
|
||||||
{
|
{
|
||||||
return mTiming->GetDOMTiming()->GetLoadEventEndHighRes();
|
return mPerformance->GetDOMTiming()->GetLoadEventEndHighRes();
|
||||||
}
|
}
|
||||||
|
|
||||||
NavigationType
|
NavigationType
|
||||||
PerformanceNavigationTiming::Type() const
|
PerformanceNavigationTiming::Type() const
|
||||||
{
|
{
|
||||||
switch(mTiming->GetDOMTiming()->GetType()) {
|
switch(mPerformance->GetDOMTiming()->GetType()) {
|
||||||
case nsDOMNavigationTiming::TYPE_NAVIGATE:
|
case nsDOMNavigationTiming::TYPE_NAVIGATE:
|
||||||
return NavigationType::Navigate;
|
return NavigationType::Navigate;
|
||||||
break;
|
break;
|
||||||
|
|
@ -92,5 +92,5 @@ PerformanceNavigationTiming::Type() const
|
||||||
uint16_t
|
uint16_t
|
||||||
PerformanceNavigationTiming::RedirectCount() const
|
PerformanceNavigationTiming::RedirectCount() const
|
||||||
{
|
{
|
||||||
return mTiming->GetRedirectCount();
|
return mTimingData->GetRedirectCount();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,11 +29,10 @@ public:
|
||||||
// so that timestamps are relative to startTime, as opposed to the
|
// so that timestamps are relative to startTime, as opposed to the
|
||||||
// performance.timing object for which timestamps are absolute and has a
|
// performance.timing object for which timestamps are absolute and has a
|
||||||
// zeroTime initialized to navigationStart
|
// zeroTime initialized to navigationStart
|
||||||
explicit PerformanceNavigationTiming(PerformanceTiming* aPerformanceTiming,
|
PerformanceNavigationTiming(UniquePtr<PerformanceTimingData>&& aPerformanceTiming,
|
||||||
Performance* aPerformance,
|
Performance* aPerformance)
|
||||||
nsIHttpChannel* aChannel)
|
: PerformanceResourceTiming(Move(aPerformanceTiming), aPerformance,
|
||||||
: PerformanceResourceTiming(aPerformanceTiming, aPerformance,
|
NS_LITERAL_STRING("document")) {
|
||||||
NS_LITERAL_STRING("document"), aChannel) {
|
|
||||||
SetEntryType(NS_LITERAL_STRING("navigation"));
|
SetEntryType(NS_LITERAL_STRING("navigation"));
|
||||||
SetInitiatorType(NS_LITERAL_STRING("navigation"));
|
SetInitiatorType(NS_LITERAL_STRING("navigation"));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ using namespace mozilla::dom;
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_INHERITED(PerformanceResourceTiming,
|
NS_IMPL_CYCLE_COLLECTION_INHERITED(PerformanceResourceTiming,
|
||||||
PerformanceEntry,
|
PerformanceEntry,
|
||||||
mTiming)
|
mPerformance)
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(PerformanceResourceTiming,
|
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(PerformanceResourceTiming,
|
||||||
PerformanceEntry)
|
PerformanceEntry)
|
||||||
|
|
@ -23,45 +23,14 @@ NS_INTERFACE_MAP_END_INHERITING(PerformanceEntry)
|
||||||
NS_IMPL_ADDREF_INHERITED(PerformanceResourceTiming, PerformanceEntry)
|
NS_IMPL_ADDREF_INHERITED(PerformanceResourceTiming, PerformanceEntry)
|
||||||
NS_IMPL_RELEASE_INHERITED(PerformanceResourceTiming, PerformanceEntry)
|
NS_IMPL_RELEASE_INHERITED(PerformanceResourceTiming, PerformanceEntry)
|
||||||
|
|
||||||
PerformanceResourceTiming::PerformanceResourceTiming(PerformanceTiming* aPerformanceTiming,
|
PerformanceResourceTiming::PerformanceResourceTiming(UniquePtr<PerformanceTimingData>&& aPerformanceTiming,
|
||||||
Performance* aPerformance,
|
Performance* aPerformance,
|
||||||
const nsAString& aName,
|
const nsAString& aName)
|
||||||
nsIHttpChannel* aChannel)
|
: PerformanceEntry(aPerformance->GetParentObject(), aName, NS_LITERAL_STRING("resource"))
|
||||||
: PerformanceEntry(aPerformance->GetParentObject(), aName, NS_LITERAL_STRING("resource")),
|
, mTimingData(Move(aPerformanceTiming))
|
||||||
mTiming(aPerformanceTiming),
|
, mPerformance(aPerformance)
|
||||||
mEncodedBodySize(0),
|
|
||||||
mTransferSize(0),
|
|
||||||
mDecodedBodySize(0)
|
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(aPerformance, "Parent performance object should be provided");
|
MOZ_ASSERT(aPerformance, "Parent performance object should be provided");
|
||||||
SetPropertiesFromChannel(aChannel);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
PerformanceResourceTiming::SetPropertiesFromChannel(nsIHttpChannel* aChannel)
|
|
||||||
{
|
|
||||||
if (!aChannel) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsAutoCString protocol;
|
|
||||||
Unused << aChannel->GetProtocolVersion(protocol);
|
|
||||||
SetNextHopProtocol(NS_ConvertUTF8toUTF16(protocol));
|
|
||||||
|
|
||||||
uint64_t encodedBodySize = 0;
|
|
||||||
Unused << aChannel->GetEncodedBodySize(&encodedBodySize);
|
|
||||||
SetEncodedBodySize(encodedBodySize);
|
|
||||||
|
|
||||||
uint64_t transferSize = 0;
|
|
||||||
Unused << aChannel->GetTransferSize(&transferSize);
|
|
||||||
SetTransferSize(transferSize);
|
|
||||||
|
|
||||||
uint64_t decodedBodySize = 0;
|
|
||||||
Unused << aChannel->GetDecodedBodySize(&decodedBodySize);
|
|
||||||
if (decodedBodySize == 0) {
|
|
||||||
decodedBodySize = encodedBodySize;
|
|
||||||
}
|
|
||||||
SetDecodedBodySize(decodedBodySize);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PerformanceResourceTiming::~PerformanceResourceTiming()
|
PerformanceResourceTiming::~PerformanceResourceTiming()
|
||||||
|
|
@ -78,13 +47,14 @@ PerformanceResourceTiming::StartTime() const
|
||||||
// Ignore zero values. The RedirectStart and WorkerStart values
|
// Ignore zero values. The RedirectStart and WorkerStart values
|
||||||
// can come from earlier redirected channels prior to the AsyncOpen
|
// can come from earlier redirected channels prior to the AsyncOpen
|
||||||
// time being recorded.
|
// time being recorded.
|
||||||
DOMHighResTimeStamp redirect = mTiming->RedirectStartHighRes();
|
DOMHighResTimeStamp redirect =
|
||||||
|
mTimingData->RedirectStartHighRes(mPerformance);
|
||||||
redirect = redirect ? redirect : DBL_MAX;
|
redirect = redirect ? redirect : DBL_MAX;
|
||||||
|
|
||||||
DOMHighResTimeStamp worker = mTiming->WorkerStartHighRes();
|
DOMHighResTimeStamp worker = mTimingData->WorkerStartHighRes(mPerformance);
|
||||||
worker = worker ? worker : DBL_MAX;
|
worker = worker ? worker : DBL_MAX;
|
||||||
|
|
||||||
DOMHighResTimeStamp asyncOpen = mTiming->AsyncOpenHighRes();
|
DOMHighResTimeStamp asyncOpen = mTimingData->AsyncOpenHighRes(mPerformance);
|
||||||
|
|
||||||
return std::min(asyncOpen, std::min(redirect, worker));
|
return std::min(asyncOpen, std::min(redirect, worker));
|
||||||
}
|
}
|
||||||
|
|
@ -106,5 +76,7 @@ PerformanceResourceTiming::SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSize
|
||||||
{
|
{
|
||||||
return PerformanceEntry::SizeOfExcludingThis(aMallocSizeOf) +
|
return PerformanceEntry::SizeOfExcludingThis(aMallocSizeOf) +
|
||||||
mInitiatorType.SizeOfExcludingThisIfUnshared(aMallocSizeOf) +
|
mInitiatorType.SizeOfExcludingThisIfUnshared(aMallocSizeOf) +
|
||||||
mNextHopProtocol.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
|
(mTimingData
|
||||||
|
? mTimingData->NextHopProtocol().SizeOfExcludingThisIfUnshared(aMallocSizeOf)
|
||||||
|
: 0);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,9 +7,8 @@
|
||||||
#ifndef mozilla_dom_PerformanceResourceTiming_h___
|
#ifndef mozilla_dom_PerformanceResourceTiming_h___
|
||||||
#define mozilla_dom_PerformanceResourceTiming_h___
|
#define mozilla_dom_PerformanceResourceTiming_h___
|
||||||
|
|
||||||
|
#include "mozilla/UniquePtr.h"
|
||||||
#include "nsCOMPtr.h"
|
#include "nsCOMPtr.h"
|
||||||
#include "nsIChannel.h"
|
|
||||||
#include "nsITimedChannel.h"
|
|
||||||
#include "Performance.h"
|
#include "Performance.h"
|
||||||
#include "PerformanceEntry.h"
|
#include "PerformanceEntry.h"
|
||||||
#include "PerformanceTiming.h"
|
#include "PerformanceTiming.h"
|
||||||
|
|
@ -28,10 +27,9 @@ public:
|
||||||
PerformanceResourceTiming,
|
PerformanceResourceTiming,
|
||||||
PerformanceEntry)
|
PerformanceEntry)
|
||||||
|
|
||||||
PerformanceResourceTiming(PerformanceTiming* aPerformanceTiming,
|
PerformanceResourceTiming(UniquePtr<PerformanceTimingData>&& aPerformanceTimingData,
|
||||||
Performance* aPerformance,
|
Performance* aPerformance,
|
||||||
const nsAString& aName,
|
const nsAString& aName);
|
||||||
nsIHttpChannel* aChannel = nullptr);
|
|
||||||
|
|
||||||
virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
|
virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
|
||||||
|
|
||||||
|
|
@ -55,88 +53,85 @@ public:
|
||||||
|
|
||||||
void GetNextHopProtocol(nsAString& aNextHopProtocol) const
|
void GetNextHopProtocol(nsAString& aNextHopProtocol) const
|
||||||
{
|
{
|
||||||
aNextHopProtocol = mNextHopProtocol;
|
if (mTimingData) {
|
||||||
}
|
aNextHopProtocol = mTimingData->NextHopProtocol();
|
||||||
|
}
|
||||||
void SetNextHopProtocol(const nsAString& aNextHopProtocol)
|
|
||||||
{
|
|
||||||
mNextHopProtocol = aNextHopProtocol;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DOMHighResTimeStamp WorkerStart() const {
|
DOMHighResTimeStamp WorkerStart() const {
|
||||||
return mTiming
|
return mTimingData
|
||||||
? mTiming->WorkerStartHighRes()
|
? mTimingData->WorkerStartHighRes(mPerformance)
|
||||||
: 0;
|
: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
DOMHighResTimeStamp FetchStart() const {
|
DOMHighResTimeStamp FetchStart() const {
|
||||||
return mTiming
|
return mTimingData
|
||||||
? mTiming->FetchStartHighRes()
|
? mTimingData->FetchStartHighRes(mPerformance)
|
||||||
: 0;
|
: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
DOMHighResTimeStamp RedirectStart() const {
|
DOMHighResTimeStamp RedirectStart() const {
|
||||||
// We have to check if all the redirect URIs had the same origin (since
|
// We have to check if all the redirect URIs had the same origin (since
|
||||||
// there is no check in RedirectEndHighRes())
|
// there is no check in RedirectEndHighRes())
|
||||||
return mTiming && mTiming->ShouldReportCrossOriginRedirect()
|
return mTimingData && mTimingData->ShouldReportCrossOriginRedirect()
|
||||||
? mTiming->RedirectStartHighRes()
|
? mTimingData->RedirectStartHighRes(mPerformance)
|
||||||
: 0;
|
: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
DOMHighResTimeStamp RedirectEnd() const {
|
DOMHighResTimeStamp RedirectEnd() const {
|
||||||
// We have to check if all the redirect URIs had the same origin (since
|
// We have to check if all the redirect URIs had the same origin (since
|
||||||
// there is no check in RedirectEndHighRes())
|
// there is no check in RedirectEndHighRes())
|
||||||
return mTiming && mTiming->ShouldReportCrossOriginRedirect()
|
return mTimingData && mTimingData->ShouldReportCrossOriginRedirect()
|
||||||
? mTiming->RedirectEndHighRes()
|
? mTimingData->RedirectEndHighRes(mPerformance)
|
||||||
: 0;
|
: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
DOMHighResTimeStamp DomainLookupStart() const {
|
DOMHighResTimeStamp DomainLookupStart() const {
|
||||||
return mTiming && mTiming->TimingAllowed()
|
return mTimingData && mTimingData->TimingAllowed()
|
||||||
? mTiming->DomainLookupStartHighRes()
|
? mTimingData->DomainLookupStartHighRes(mPerformance)
|
||||||
: 0;
|
: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
DOMHighResTimeStamp DomainLookupEnd() const {
|
DOMHighResTimeStamp DomainLookupEnd() const {
|
||||||
return mTiming && mTiming->TimingAllowed()
|
return mTimingData && mTimingData->TimingAllowed()
|
||||||
? mTiming->DomainLookupEndHighRes()
|
? mTimingData->DomainLookupEndHighRes(mPerformance)
|
||||||
: 0;
|
: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
DOMHighResTimeStamp ConnectStart() const {
|
DOMHighResTimeStamp ConnectStart() const {
|
||||||
return mTiming && mTiming->TimingAllowed()
|
return mTimingData && mTimingData->TimingAllowed()
|
||||||
? mTiming->ConnectStartHighRes()
|
? mTimingData->ConnectStartHighRes(mPerformance)
|
||||||
: 0;
|
: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
DOMHighResTimeStamp ConnectEnd() const {
|
DOMHighResTimeStamp ConnectEnd() const {
|
||||||
return mTiming && mTiming->TimingAllowed()
|
return mTimingData && mTimingData->TimingAllowed()
|
||||||
? mTiming->ConnectEndHighRes()
|
? mTimingData->ConnectEndHighRes(mPerformance)
|
||||||
: 0;
|
: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
DOMHighResTimeStamp RequestStart() const {
|
DOMHighResTimeStamp RequestStart() const {
|
||||||
return mTiming && mTiming->TimingAllowed()
|
return mTimingData && mTimingData->TimingAllowed()
|
||||||
? mTiming->RequestStartHighRes()
|
? mTimingData->RequestStartHighRes(mPerformance)
|
||||||
: 0;
|
: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
DOMHighResTimeStamp ResponseStart() const {
|
DOMHighResTimeStamp ResponseStart() const {
|
||||||
return mTiming && mTiming->TimingAllowed()
|
return mTimingData && mTimingData->TimingAllowed()
|
||||||
? mTiming->ResponseStartHighRes()
|
? mTimingData->ResponseStartHighRes(mPerformance)
|
||||||
: 0;
|
: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
DOMHighResTimeStamp ResponseEnd() const {
|
DOMHighResTimeStamp ResponseEnd() const {
|
||||||
return mTiming
|
return mTimingData
|
||||||
? mTiming->ResponseEndHighRes()
|
? mTimingData->ResponseEndHighRes(mPerformance)
|
||||||
: 0;
|
: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
DOMHighResTimeStamp SecureConnectionStart() const
|
DOMHighResTimeStamp SecureConnectionStart() const
|
||||||
{
|
{
|
||||||
return mTiming && mTiming->TimingAllowed()
|
return mTimingData && mTimingData->TimingAllowed()
|
||||||
? mTiming->SecureConnectionStartHighRes()
|
? mTimingData->SecureConnectionStartHighRes(mPerformance)
|
||||||
: 0;
|
: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -147,32 +142,17 @@ public:
|
||||||
|
|
||||||
uint64_t TransferSize() const
|
uint64_t TransferSize() const
|
||||||
{
|
{
|
||||||
return mTiming && mTiming->TimingAllowed() ? mTransferSize : 0;
|
return mTimingData ? mTimingData->TransferSize() : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t EncodedBodySize() const
|
uint64_t EncodedBodySize() const
|
||||||
{
|
{
|
||||||
return mTiming && mTiming->TimingAllowed() ? mEncodedBodySize : 0;
|
return mTimingData ? mTimingData->EncodedBodySize() : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t DecodedBodySize() const
|
uint64_t DecodedBodySize() const
|
||||||
{
|
{
|
||||||
return mTiming && mTiming->TimingAllowed() ? mDecodedBodySize : 0;
|
return mTimingData ? mTimingData->DecodedBodySize() : 0;
|
||||||
}
|
|
||||||
|
|
||||||
void SetEncodedBodySize(uint64_t aEncodedBodySize)
|
|
||||||
{
|
|
||||||
mEncodedBodySize = aEncodedBodySize;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetTransferSize(uint64_t aTransferSize)
|
|
||||||
{
|
|
||||||
mTransferSize = aTransferSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetDecodedBodySize(uint64_t aDecodedBodySize)
|
|
||||||
{
|
|
||||||
mDecodedBodySize = aDecodedBodySize;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t
|
size_t
|
||||||
|
|
@ -180,17 +160,13 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual ~PerformanceResourceTiming();
|
virtual ~PerformanceResourceTiming();
|
||||||
void SetPropertiesFromChannel(nsIHttpChannel* aChannel);
|
|
||||||
|
|
||||||
size_t
|
size_t
|
||||||
SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const override;
|
SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const override;
|
||||||
|
|
||||||
nsString mInitiatorType;
|
nsString mInitiatorType;
|
||||||
nsString mNextHopProtocol;
|
UniquePtr<PerformanceTimingData> mTimingData;
|
||||||
RefPtr<PerformanceTiming> mTiming;
|
RefPtr<Performance> mPerformance;
|
||||||
uint64_t mEncodedBodySize;
|
|
||||||
uint64_t mTransferSize;
|
|
||||||
uint64_t mDecodedBodySize;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace dom
|
} // namespace dom
|
||||||
|
|
|
||||||
35
dom/performance/PerformanceStorage.h
Normal file
35
dom/performance/PerformanceStorage.h
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||||
|
/* 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 mozilla_dom_PerformanceStorage_h
|
||||||
|
#define mozilla_dom_PerformanceStorage_h
|
||||||
|
|
||||||
|
#include "nsISupportsImpl.h"
|
||||||
|
|
||||||
|
class nsIHttpChannel;
|
||||||
|
class nsITimedChannel;
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
namespace dom {
|
||||||
|
|
||||||
|
class PerformanceTimingData;
|
||||||
|
|
||||||
|
class PerformanceStorage
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NS_INLINE_DECL_PURE_VIRTUAL_REFCOUNTING
|
||||||
|
|
||||||
|
virtual void AddEntry(nsIHttpChannel* aChannel,
|
||||||
|
nsITimedChannel* aTimedChannel) = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual ~PerformanceStorage() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace dom
|
||||||
|
} // namespace mozilla
|
||||||
|
|
||||||
|
#endif // mozilla_dom_PerformanceStorage_h
|
||||||
271
dom/performance/PerformanceStorageWorker.cpp
Normal file
271
dom/performance/PerformanceStorageWorker.cpp
Normal file
|
|
@ -0,0 +1,271 @@
|
||||||
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||||
|
/* 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 "PerformanceStorageWorker.h"
|
||||||
|
#include "WorkerPrivate.h"
|
||||||
|
#include "WorkerHolder.h"
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
namespace dom {
|
||||||
|
|
||||||
|
using namespace workers;
|
||||||
|
|
||||||
|
class PerformanceProxyData
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PerformanceProxyData(UniquePtr<PerformanceTimingData>&& aData,
|
||||||
|
const nsAString& aInitiatorType,
|
||||||
|
const nsAString& aEntryName)
|
||||||
|
: mData(Move(aData))
|
||||||
|
, mInitiatorType(aInitiatorType)
|
||||||
|
, mEntryName(aEntryName)
|
||||||
|
{}
|
||||||
|
|
||||||
|
UniquePtr<PerformanceTimingData> mData;
|
||||||
|
nsString mInitiatorType;
|
||||||
|
nsString mEntryName;
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
// This runnable calls InitializeOnWorker() on the worker thread. Here a
|
||||||
|
// workerHolder is used to monitor when the worker thread is starting the
|
||||||
|
// shutdown procedure.
|
||||||
|
// Here we use control runnable because this code must be executed also when in
|
||||||
|
// a sync event loop.
|
||||||
|
class PerformanceStorageInitializer final : public WorkerControlRunnable
|
||||||
|
{
|
||||||
|
RefPtr<PerformanceStorageWorker> mStorage;
|
||||||
|
|
||||||
|
public:
|
||||||
|
PerformanceStorageInitializer(WorkerPrivate* aWorkerPrivate,
|
||||||
|
PerformanceStorageWorker* aStorage)
|
||||||
|
: WorkerControlRunnable(aWorkerPrivate, WorkerThreadUnchangedBusyCount)
|
||||||
|
, mStorage(aStorage)
|
||||||
|
{}
|
||||||
|
|
||||||
|
bool
|
||||||
|
WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override
|
||||||
|
{
|
||||||
|
mStorage->InitializeOnWorker();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
Cancel() override
|
||||||
|
{
|
||||||
|
mStorage->ShutdownOnWorker();
|
||||||
|
return WorkerRunnable::Cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
PreDispatch(WorkerPrivate* aWorkerPrivate) override
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PostDispatch(WorkerPrivate* aWorkerPrivate, bool aDispatchResult) override
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Here we use control runnable because this code must be executed also when in
|
||||||
|
// a sync event loop
|
||||||
|
class PerformanceEntryAdder final : public WorkerControlRunnable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PerformanceEntryAdder(WorkerPrivate* aWorkerPrivate,
|
||||||
|
PerformanceStorageWorker* aStorage,
|
||||||
|
UniquePtr<PerformanceProxyData>&& aData)
|
||||||
|
: WorkerControlRunnable(aWorkerPrivate, WorkerThreadUnchangedBusyCount)
|
||||||
|
, mStorage(aStorage)
|
||||||
|
, mData(Move(aData))
|
||||||
|
{}
|
||||||
|
|
||||||
|
bool
|
||||||
|
WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override
|
||||||
|
{
|
||||||
|
mStorage->AddEntryOnWorker(Move(mData));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
Cancel() override
|
||||||
|
{
|
||||||
|
mStorage->ShutdownOnWorker();
|
||||||
|
return WorkerRunnable::Cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
PreDispatch(WorkerPrivate* aWorkerPrivate) override
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PostDispatch(WorkerPrivate* aWorkerPrivate, bool aDispatchResult) override
|
||||||
|
{}
|
||||||
|
|
||||||
|
private:
|
||||||
|
RefPtr<PerformanceStorageWorker> mStorage;
|
||||||
|
UniquePtr<PerformanceProxyData> mData;
|
||||||
|
};
|
||||||
|
|
||||||
|
class PerformanceStorageWorkerHolder final : public WorkerHolder
|
||||||
|
{
|
||||||
|
RefPtr<PerformanceStorageWorker> mStorage;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit PerformanceStorageWorkerHolder(PerformanceStorageWorker* aStorage)
|
||||||
|
: WorkerHolder("PerformanceStorageWorkerHolder",
|
||||||
|
WorkerHolder::AllowIdleShutdownStart)
|
||||||
|
, mStorage(aStorage)
|
||||||
|
{}
|
||||||
|
|
||||||
|
bool
|
||||||
|
Notify(Status aStatus) override
|
||||||
|
{
|
||||||
|
if (mStorage) {
|
||||||
|
RefPtr<PerformanceStorageWorker> storage;
|
||||||
|
storage.swap(mStorage);
|
||||||
|
storage->ShutdownOnWorker();
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // anonymous
|
||||||
|
|
||||||
|
/* static */ already_AddRefed<PerformanceStorageWorker>
|
||||||
|
PerformanceStorageWorker::Create(WorkerPrivate* aWorkerPrivate)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
|
||||||
|
RefPtr<PerformanceStorageWorker> storage =
|
||||||
|
new PerformanceStorageWorker(aWorkerPrivate);
|
||||||
|
|
||||||
|
RefPtr<PerformanceStorageInitializer> r =
|
||||||
|
new PerformanceStorageInitializer(aWorkerPrivate, storage);
|
||||||
|
if (NS_WARN_IF(!r->Dispatch())) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return storage.forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
PerformanceStorageWorker::PerformanceStorageWorker(WorkerPrivate* aWorkerPrivate)
|
||||||
|
: mMutex("PerformanceStorageWorker::mMutex")
|
||||||
|
, mWorkerPrivate(aWorkerPrivate)
|
||||||
|
, mState(eInitializing)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
PerformanceStorageWorker::~PerformanceStorageWorker() = default;
|
||||||
|
|
||||||
|
void
|
||||||
|
PerformanceStorageWorker::AddEntry(nsIHttpChannel* aChannel,
|
||||||
|
nsITimedChannel* aTimedChannel)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
|
||||||
|
MutexAutoLock lock(mMutex);
|
||||||
|
|
||||||
|
if (mState == eTerminated) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsAutoString initiatorType;
|
||||||
|
nsAutoString entryName;
|
||||||
|
|
||||||
|
UniquePtr<PerformanceTimingData> performanceTimingData(
|
||||||
|
PerformanceTimingData::Create(aTimedChannel, aChannel, 0, initiatorType,
|
||||||
|
entryName));
|
||||||
|
if (!performanceTimingData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
UniquePtr<PerformanceProxyData> data(
|
||||||
|
new PerformanceProxyData(Move(performanceTimingData), initiatorType,
|
||||||
|
entryName));
|
||||||
|
|
||||||
|
RefPtr<PerformanceEntryAdder> r =
|
||||||
|
new PerformanceEntryAdder(mWorkerPrivate, this, Move(data));
|
||||||
|
Unused << NS_WARN_IF(!r->Dispatch());
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PerformanceStorageWorker::InitializeOnWorker()
|
||||||
|
{
|
||||||
|
MutexAutoLock lock(mMutex);
|
||||||
|
MOZ_ASSERT(mState == eInitializing);
|
||||||
|
MOZ_ASSERT(mWorkerPrivate);
|
||||||
|
mWorkerPrivate->AssertIsOnWorkerThread();
|
||||||
|
|
||||||
|
mWorkerHolder.reset(new PerformanceStorageWorkerHolder(this));
|
||||||
|
if (!mWorkerHolder->HoldWorker(mWorkerPrivate, Canceling)) {
|
||||||
|
MutexAutoUnlock lock(mMutex);
|
||||||
|
ShutdownOnWorker();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We are ready to accept entries.
|
||||||
|
mState = eReady;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PerformanceStorageWorker::ShutdownOnWorker()
|
||||||
|
{
|
||||||
|
MutexAutoLock lock(mMutex);
|
||||||
|
|
||||||
|
if (mState == eTerminated) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
MOZ_ASSERT(mWorkerPrivate);
|
||||||
|
mWorkerPrivate->AssertIsOnWorkerThread();
|
||||||
|
|
||||||
|
mState = eTerminated;
|
||||||
|
mWorkerHolder = nullptr;
|
||||||
|
mWorkerPrivate = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PerformanceStorageWorker::AddEntryOnWorker(UniquePtr<PerformanceProxyData>&& aData)
|
||||||
|
{
|
||||||
|
RefPtr<Performance> performance;
|
||||||
|
UniquePtr<PerformanceProxyData> data = Move(aData);
|
||||||
|
|
||||||
|
{
|
||||||
|
MutexAutoLock lock(mMutex);
|
||||||
|
|
||||||
|
if (mState == eTerminated) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
MOZ_ASSERT(mWorkerPrivate);
|
||||||
|
mWorkerPrivate->AssertIsOnWorkerThread();
|
||||||
|
|
||||||
|
MOZ_ASSERT(mState == eReady);
|
||||||
|
|
||||||
|
WorkerGlobalScope* scope = mWorkerPrivate->GlobalScope();
|
||||||
|
performance = scope->GetPerformance();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (NS_WARN_IF(!performance)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
RefPtr<PerformanceResourceTiming> performanceEntry =
|
||||||
|
new PerformanceResourceTiming(Move(data->mData), performance,
|
||||||
|
data->mEntryName);
|
||||||
|
performanceEntry->SetInitiatorType(data->mInitiatorType);
|
||||||
|
|
||||||
|
performance->InsertResourceEntry(performanceEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace dom
|
||||||
|
} // namespace mozilla
|
||||||
64
dom/performance/PerformanceStorageWorker.h
Normal file
64
dom/performance/PerformanceStorageWorker.h
Normal file
|
|
@ -0,0 +1,64 @@
|
||||||
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||||
|
/* 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 mozilla_dom_PerformanceStorageWorker_h
|
||||||
|
#define mozilla_dom_PerformanceStorageWorker_h
|
||||||
|
|
||||||
|
#include "PerformanceStorage.h"
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
namespace dom {
|
||||||
|
|
||||||
|
namespace workers {
|
||||||
|
class WorkerHolder;
|
||||||
|
class WorkerPrivate;
|
||||||
|
}
|
||||||
|
|
||||||
|
class PerformanceProxyData;
|
||||||
|
|
||||||
|
class PerformanceStorageWorker final : public PerformanceStorage
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(PerformanceStorageWorker, override)
|
||||||
|
|
||||||
|
static already_AddRefed<PerformanceStorageWorker>
|
||||||
|
Create(workers::WorkerPrivate* aWorkerPrivate);
|
||||||
|
|
||||||
|
void InitializeOnWorker();
|
||||||
|
|
||||||
|
void ShutdownOnWorker();
|
||||||
|
|
||||||
|
void AddEntry(nsIHttpChannel* aChannel,
|
||||||
|
nsITimedChannel* aTimedChannel) override;
|
||||||
|
|
||||||
|
void AddEntryOnWorker(UniquePtr<PerformanceProxyData>&& aData);
|
||||||
|
|
||||||
|
private:
|
||||||
|
explicit PerformanceStorageWorker(workers::WorkerPrivate* aWorkerPrivate);
|
||||||
|
~PerformanceStorageWorker();
|
||||||
|
|
||||||
|
Mutex mMutex;
|
||||||
|
|
||||||
|
// Protected by mutex.
|
||||||
|
// This raw pointer is nullified when the WorkerHolder communicates the
|
||||||
|
// shutting down of the worker thread.
|
||||||
|
workers::WorkerPrivate* mWorkerPrivate;
|
||||||
|
|
||||||
|
// Protected by mutex.
|
||||||
|
enum {
|
||||||
|
eInitializing,
|
||||||
|
eReady,
|
||||||
|
eTerminated,
|
||||||
|
} mState;
|
||||||
|
|
||||||
|
// Touched on worker-thread only.
|
||||||
|
UniquePtr<WorkerHolder> mWorkerHolder;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace dom
|
||||||
|
} // namespace mozilla
|
||||||
|
|
||||||
|
#endif // mozilla_dom_PerformanceStorageWorker_h
|
||||||
|
|
@ -20,39 +20,105 @@ NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(PerformanceTiming, mPerformance)
|
||||||
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(PerformanceTiming, AddRef)
|
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(PerformanceTiming, AddRef)
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(PerformanceTiming, Release)
|
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(PerformanceTiming, Release)
|
||||||
|
|
||||||
|
/* static */ PerformanceTimingData*
|
||||||
|
PerformanceTimingData::Create(nsITimedChannel* aTimedChannel,
|
||||||
|
nsIHttpChannel* aChannel,
|
||||||
|
DOMHighResTimeStamp aZeroTime,
|
||||||
|
nsAString& aInitiatorType,
|
||||||
|
nsAString& aEntryName)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
|
||||||
|
// Check if resource timing is prefed off.
|
||||||
|
if (!nsContentUtils::IsResourceTimingEnabled()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!aChannel || !aTimedChannel) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool reportTiming = true;
|
||||||
|
aTimedChannel->GetReportResourceTiming(&reportTiming);
|
||||||
|
|
||||||
|
if (!reportTiming) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
aTimedChannel->GetInitiatorType(aInitiatorType);
|
||||||
|
|
||||||
|
// If the initiator type had no valid value, then set it to the default
|
||||||
|
// ("other") value.
|
||||||
|
if (aInitiatorType.IsEmpty()) {
|
||||||
|
aInitiatorType = NS_LITERAL_STRING("other");
|
||||||
|
}
|
||||||
|
|
||||||
|
// According to the spec, "The name attribute must return the resolved URL
|
||||||
|
// of the requested resource. This attribute must not change even if the
|
||||||
|
// fetch redirected to a different URL."
|
||||||
|
nsCOMPtr<nsIURI> originalURI;
|
||||||
|
aChannel->GetOriginalURI(getter_AddRefs(originalURI));
|
||||||
|
|
||||||
|
nsAutoCString name;
|
||||||
|
originalURI->GetSpec(name);
|
||||||
|
aEntryName = NS_ConvertUTF8toUTF16(name);
|
||||||
|
|
||||||
|
// The nsITimedChannel argument will be used to gather all the timings.
|
||||||
|
// The nsIHttpChannel argument will be used to check if any cross-origin
|
||||||
|
// redirects occurred.
|
||||||
|
// The last argument is the "zero time" (offset). Since we don't want
|
||||||
|
// any offset for the resource timing, this will be set to "0" - the
|
||||||
|
// resource timing returns a relative timing (no offset).
|
||||||
|
return new PerformanceTimingData(aTimedChannel, aChannel, 0);
|
||||||
|
}
|
||||||
|
|
||||||
PerformanceTiming::PerformanceTiming(Performance* aPerformance,
|
PerformanceTiming::PerformanceTiming(Performance* aPerformance,
|
||||||
nsITimedChannel* aChannel,
|
nsITimedChannel* aChannel,
|
||||||
nsIHttpChannel* aHttpChannel,
|
nsIHttpChannel* aHttpChannel,
|
||||||
DOMHighResTimeStamp aZeroTime)
|
DOMHighResTimeStamp aZeroTime)
|
||||||
: mPerformance(aPerformance),
|
: mPerformance(aPerformance)
|
||||||
mFetchStart(0.0),
|
|
||||||
mZeroTime(nsRFPService::ReduceTimePrecisionAsMSecs(aZeroTime)),
|
|
||||||
mRedirectCount(0),
|
|
||||||
mTimingAllowed(true),
|
|
||||||
mAllRedirectsSameOrigin(true),
|
|
||||||
mInitialized(!!aChannel),
|
|
||||||
mReportCrossOriginRedirect(true)
|
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(aPerformance, "Parent performance object should be provided");
|
MOZ_ASSERT(aPerformance, "Parent performance object should be provided");
|
||||||
|
|
||||||
|
mTimingData.reset(new PerformanceTimingData(aChannel, aHttpChannel,
|
||||||
|
aZeroTime));
|
||||||
|
|
||||||
|
// Non-null aHttpChannel implies that this PerformanceTiming object is being
|
||||||
|
// used for subresources, which is irrelevant to this probe.
|
||||||
|
if (!aHttpChannel &&
|
||||||
|
nsContentUtils::IsPerformanceTimingEnabled() &&
|
||||||
|
IsTopLevelContentDocument()) {
|
||||||
|
Telemetry::Accumulate(Telemetry::TIME_TO_RESPONSE_START_MS,
|
||||||
|
mTimingData->ResponseStartHighRes(aPerformance) -
|
||||||
|
mTimingData->ZeroTime());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy the timing info from the channel so we don't need to keep the channel
|
||||||
|
// alive just to get the timestamps.
|
||||||
|
PerformanceTimingData::PerformanceTimingData(nsITimedChannel* aChannel,
|
||||||
|
nsIHttpChannel* aHttpChannel,
|
||||||
|
DOMHighResTimeStamp aZeroTime)
|
||||||
|
: mZeroTime(0.0)
|
||||||
|
, mFetchStart(0.0)
|
||||||
|
, mEncodedBodySize(0)
|
||||||
|
, mTransferSize(0)
|
||||||
|
, mDecodedBodySize(0)
|
||||||
|
, mRedirectCount(0)
|
||||||
|
, mAllRedirectsSameOrigin(true)
|
||||||
|
, mReportCrossOriginRedirect(true)
|
||||||
|
, mSecureConnection(false)
|
||||||
|
, mTimingAllowed(true)
|
||||||
|
, mInitialized(false)
|
||||||
|
{
|
||||||
|
mInitialized = !!aChannel;
|
||||||
|
|
||||||
|
mZeroTime = nsRFPService::ReduceTimePrecisionAsMSecs(aZeroTime);
|
||||||
if (!nsContentUtils::IsPerformanceTimingEnabled() ||
|
if (!nsContentUtils::IsPerformanceTimingEnabled() ||
|
||||||
nsContentUtils::ShouldResistFingerprinting()) {
|
nsContentUtils::ShouldResistFingerprinting()) {
|
||||||
mZeroTime = 0;
|
mZeroTime = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The aHttpChannel argument is null if this PerformanceTiming object is
|
|
||||||
// being used for navigation timing (which is only relevant for documents).
|
|
||||||
// It has a non-null value if this PerformanceTiming object is being used
|
|
||||||
// for resource timing, which can include document loads, both toplevel and
|
|
||||||
// in subframes, and resources linked from a document.
|
|
||||||
if (aHttpChannel) {
|
|
||||||
mTimingAllowed = CheckAllowedOrigin(aHttpChannel, aChannel);
|
|
||||||
bool redirectsPassCheck = false;
|
|
||||||
aChannel->GetAllRedirectsPassTimingAllowCheck(&redirectsPassCheck);
|
|
||||||
mReportCrossOriginRedirect = mTimingAllowed && redirectsPassCheck;
|
|
||||||
}
|
|
||||||
|
|
||||||
mSecureConnection = false;
|
|
||||||
nsCOMPtr<nsIURI> uri;
|
nsCOMPtr<nsIURI> uri;
|
||||||
if (aHttpChannel) {
|
if (aHttpChannel) {
|
||||||
aHttpChannel->GetURI(getter_AddRefs(uri));
|
aHttpChannel->GetURI(getter_AddRefs(uri));
|
||||||
|
|
@ -69,23 +135,7 @@ PerformanceTiming::PerformanceTiming(Performance* aPerformance,
|
||||||
mSecureConnection = false;
|
mSecureConnection = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
InitializeTimingInfo(aChannel);
|
|
||||||
|
|
||||||
// Non-null aHttpChannel implies that this PerformanceTiming object is being
|
|
||||||
// used for subresources, which is irrelevant to this probe.
|
|
||||||
if (!aHttpChannel &&
|
|
||||||
nsContentUtils::IsPerformanceTimingEnabled() &&
|
|
||||||
IsTopLevelContentDocument()) {
|
|
||||||
Telemetry::Accumulate(Telemetry::TIME_TO_RESPONSE_START_MS,
|
|
||||||
ResponseStartHighRes() - mZeroTime);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy the timing info from the channel so we don't need to keep the channel
|
|
||||||
// alive just to get the timestamps.
|
|
||||||
void
|
|
||||||
PerformanceTiming::InitializeTimingInfo(nsITimedChannel* aChannel)
|
|
||||||
{
|
|
||||||
if (aChannel) {
|
if (aChannel) {
|
||||||
aChannel->GetAsyncOpen(&mAsyncOpen);
|
aChannel->GetAsyncOpen(&mAsyncOpen);
|
||||||
aChannel->GetAllRedirectsSameOrigin(&mAllRedirectsSameOrigin);
|
aChannel->GetAllRedirectsSameOrigin(&mAllRedirectsSameOrigin);
|
||||||
|
|
@ -110,11 +160,11 @@ PerformanceTiming::InitializeTimingInfo(nsITimedChannel* aChannel)
|
||||||
aChannel->GetHandleFetchEventEnd(&mWorkerResponseEnd);
|
aChannel->GetHandleFetchEventEnd(&mWorkerResponseEnd);
|
||||||
|
|
||||||
// The performance timing api essentially requires that the event timestamps
|
// The performance timing api essentially requires that the event timestamps
|
||||||
// have a strict relation with each other. The truth, however, is the browser
|
// have a strict relation with each other. The truth, however, is the
|
||||||
// engages in a number of speculative activities that sometimes mean connections
|
// browser engages in a number of speculative activities that sometimes mean
|
||||||
// and lookups begin at different times. Workaround that here by clamping
|
// connections and lookups begin at different times. Workaround that here by
|
||||||
// these values to what we expect FetchStart to be. This means the later of
|
// clamping these values to what we expect FetchStart to be. This means the
|
||||||
// AsyncOpen or WorkerStart times.
|
// later of AsyncOpen or WorkerStart times.
|
||||||
if (!mAsyncOpen.IsNull()) {
|
if (!mAsyncOpen.IsNull()) {
|
||||||
// We want to clamp to the expected FetchStart value. This is later of
|
// We want to clamp to the expected FetchStart value. This is later of
|
||||||
// the AsyncOpen and WorkerStart values.
|
// the AsyncOpen and WorkerStart values.
|
||||||
|
|
@ -145,6 +195,37 @@ PerformanceTiming::InitializeTimingInfo(nsITimedChannel* aChannel)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The aHttpChannel argument is null if this PerformanceTiming object is
|
||||||
|
// being used for navigation timing (which is only relevant for documents).
|
||||||
|
// It has a non-null value if this PerformanceTiming object is being used
|
||||||
|
// for resource timing, which can include document loads, both toplevel and
|
||||||
|
// in subframes, and resources linked from a document.
|
||||||
|
if (aHttpChannel) {
|
||||||
|
mTimingAllowed = CheckAllowedOrigin(aHttpChannel, aChannel);
|
||||||
|
bool redirectsPassCheck = false;
|
||||||
|
aChannel->GetAllRedirectsPassTimingAllowCheck(&redirectsPassCheck);
|
||||||
|
mReportCrossOriginRedirect = mTimingAllowed && redirectsPassCheck;
|
||||||
|
|
||||||
|
SetPropertiesFromHttpChannel(aHttpChannel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PerformanceTimingData::SetPropertiesFromHttpChannel(nsIHttpChannel* aHttpChannel)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(aHttpChannel);
|
||||||
|
|
||||||
|
nsAutoCString protocol;
|
||||||
|
Unused << aHttpChannel->GetProtocolVersion(protocol);
|
||||||
|
mNextHopProtocol = NS_ConvertUTF8toUTF16(protocol);
|
||||||
|
|
||||||
|
Unused << aHttpChannel->GetEncodedBodySize(&mEncodedBodySize);
|
||||||
|
Unused << aHttpChannel->GetTransferSize(&mTransferSize);
|
||||||
|
Unused << aHttpChannel->GetDecodedBodySize(&mDecodedBodySize);
|
||||||
|
if (mDecodedBodySize == 0) {
|
||||||
|
mDecodedBodySize = mEncodedBodySize;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PerformanceTiming::~PerformanceTiming()
|
PerformanceTiming::~PerformanceTiming()
|
||||||
|
|
@ -152,8 +233,10 @@ PerformanceTiming::~PerformanceTiming()
|
||||||
}
|
}
|
||||||
|
|
||||||
DOMHighResTimeStamp
|
DOMHighResTimeStamp
|
||||||
PerformanceTiming::FetchStartHighRes()
|
PerformanceTimingData::FetchStartHighRes(Performance* aPerformance)
|
||||||
{
|
{
|
||||||
|
MOZ_ASSERT(aPerformance);
|
||||||
|
|
||||||
if (!mFetchStart) {
|
if (!mFetchStart) {
|
||||||
if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized() ||
|
if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized() ||
|
||||||
nsContentUtils::ShouldResistFingerprinting()) {
|
nsContentUtils::ShouldResistFingerprinting()) {
|
||||||
|
|
@ -163,9 +246,9 @@ PerformanceTiming::FetchStartHighRes()
|
||||||
"valid if the performance timing is enabled");
|
"valid if the performance timing is enabled");
|
||||||
if (!mAsyncOpen.IsNull()) {
|
if (!mAsyncOpen.IsNull()) {
|
||||||
if (!mWorkerRequestStart.IsNull() && mWorkerRequestStart > mAsyncOpen) {
|
if (!mWorkerRequestStart.IsNull() && mWorkerRequestStart > mAsyncOpen) {
|
||||||
mFetchStart = TimeStampToDOMHighRes(mWorkerRequestStart);
|
mFetchStart = TimeStampToDOMHighRes(aPerformance, mWorkerRequestStart);
|
||||||
} else {
|
} else {
|
||||||
mFetchStart = TimeStampToDOMHighRes(mAsyncOpen);
|
mFetchStart = TimeStampToDOMHighRes(aPerformance, mAsyncOpen);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -175,12 +258,12 @@ PerformanceTiming::FetchStartHighRes()
|
||||||
DOMTimeMilliSec
|
DOMTimeMilliSec
|
||||||
PerformanceTiming::FetchStart()
|
PerformanceTiming::FetchStart()
|
||||||
{
|
{
|
||||||
return static_cast<int64_t>(FetchStartHighRes());
|
return static_cast<int64_t>(mTimingData->FetchStartHighRes(mPerformance));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
PerformanceTiming::CheckAllowedOrigin(nsIHttpChannel* aResourceChannel,
|
PerformanceTimingData::CheckAllowedOrigin(nsIHttpChannel* aResourceChannel,
|
||||||
nsITimedChannel* aChannel)
|
nsITimedChannel* aChannel)
|
||||||
{
|
{
|
||||||
if (!IsInitialized()) {
|
if (!IsInitialized()) {
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -208,14 +291,8 @@ PerformanceTiming::CheckAllowedOrigin(nsIHttpChannel* aResourceChannel,
|
||||||
return aChannel->TimingAllowCheck(principal);
|
return aChannel->TimingAllowCheck(principal);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
|
||||||
PerformanceTiming::TimingAllowed() const
|
|
||||||
{
|
|
||||||
return mTimingAllowed;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t
|
uint8_t
|
||||||
PerformanceTiming::GetRedirectCount() const
|
PerformanceTimingData::GetRedirectCount() const
|
||||||
{
|
{
|
||||||
if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized() ||
|
if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized() ||
|
||||||
nsContentUtils::ShouldResistFingerprinting()) {
|
nsContentUtils::ShouldResistFingerprinting()) {
|
||||||
|
|
@ -228,7 +305,7 @@ PerformanceTiming::GetRedirectCount() const
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
PerformanceTiming::ShouldReportCrossOriginRedirect() const
|
PerformanceTimingData::ShouldReportCrossOriginRedirect() const
|
||||||
{
|
{
|
||||||
if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized() ||
|
if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized() ||
|
||||||
nsContentUtils::ShouldResistFingerprinting()) {
|
nsContentUtils::ShouldResistFingerprinting()) {
|
||||||
|
|
@ -242,23 +319,29 @@ PerformanceTiming::ShouldReportCrossOriginRedirect() const
|
||||||
}
|
}
|
||||||
|
|
||||||
DOMHighResTimeStamp
|
DOMHighResTimeStamp
|
||||||
PerformanceTiming::AsyncOpenHighRes()
|
PerformanceTimingData::AsyncOpenHighRes(Performance* aPerformance)
|
||||||
{
|
{
|
||||||
|
MOZ_ASSERT(aPerformance);
|
||||||
|
|
||||||
if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized() ||
|
if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized() ||
|
||||||
nsContentUtils::ShouldResistFingerprinting() || mAsyncOpen.IsNull()) {
|
nsContentUtils::ShouldResistFingerprinting() || mAsyncOpen.IsNull()) {
|
||||||
return mZeroTime;
|
return mZeroTime;
|
||||||
}
|
}
|
||||||
return nsRFPService::ReduceTimePrecisionAsMSecs(TimeStampToDOMHighRes(mAsyncOpen));
|
return nsRFPService::ReduceTimePrecisionAsMSecs(
|
||||||
|
TimeStampToDOMHighRes(aPerformance, mAsyncOpen));
|
||||||
}
|
}
|
||||||
|
|
||||||
DOMHighResTimeStamp
|
DOMHighResTimeStamp
|
||||||
PerformanceTiming::WorkerStartHighRes()
|
PerformanceTimingData::WorkerStartHighRes(Performance* aPerformance)
|
||||||
{
|
{
|
||||||
|
MOZ_ASSERT(aPerformance);
|
||||||
|
|
||||||
if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized() ||
|
if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized() ||
|
||||||
nsContentUtils::ShouldResistFingerprinting() || mWorkerStart.IsNull()) {
|
nsContentUtils::ShouldResistFingerprinting() || mWorkerStart.IsNull()) {
|
||||||
return mZeroTime;
|
return mZeroTime;
|
||||||
}
|
}
|
||||||
return nsRFPService::ReduceTimePrecisionAsMSecs(TimeStampToDOMHighRes(mWorkerStart));
|
return nsRFPService::ReduceTimePrecisionAsMSecs(
|
||||||
|
TimeStampToDOMHighRes(aPerformance, mWorkerStart));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -272,25 +355,28 @@ PerformanceTiming::WorkerStartHighRes()
|
||||||
* @return a valid timing if the Performance Timing is enabled
|
* @return a valid timing if the Performance Timing is enabled
|
||||||
*/
|
*/
|
||||||
DOMHighResTimeStamp
|
DOMHighResTimeStamp
|
||||||
PerformanceTiming::RedirectStartHighRes()
|
PerformanceTimingData::RedirectStartHighRes(Performance* aPerformance)
|
||||||
{
|
{
|
||||||
|
MOZ_ASSERT(aPerformance);
|
||||||
|
|
||||||
if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized() ||
|
if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized() ||
|
||||||
nsContentUtils::ShouldResistFingerprinting()) {
|
nsContentUtils::ShouldResistFingerprinting()) {
|
||||||
return mZeroTime;
|
return mZeroTime;
|
||||||
}
|
}
|
||||||
return TimeStampToReducedDOMHighResOrFetchStart(mRedirectStart);
|
return TimeStampToReducedDOMHighResOrFetchStart(aPerformance, mRedirectStart);
|
||||||
}
|
}
|
||||||
|
|
||||||
DOMTimeMilliSec
|
DOMTimeMilliSec
|
||||||
PerformanceTiming::RedirectStart()
|
PerformanceTiming::RedirectStart()
|
||||||
{
|
{
|
||||||
if (!IsInitialized()) {
|
if (!mTimingData->IsInitialized()) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
// We have to check if all the redirect URIs had the same origin (since there
|
// We have to check if all the redirect URIs had the same origin (since there
|
||||||
// is no check in RedirectStartHighRes())
|
// is no check in RedirectStartHighRes())
|
||||||
if (mAllRedirectsSameOrigin && mRedirectCount) {
|
if (mTimingData->AllRedirectsSameOrigin() &&
|
||||||
return static_cast<int64_t>(RedirectStartHighRes());
|
mTimingData->RedirectCountReal()) {
|
||||||
|
return static_cast<int64_t>(mTimingData->RedirectStartHighRes(mPerformance));
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -306,85 +392,99 @@ PerformanceTiming::RedirectStart()
|
||||||
* @return a valid timing if the Performance Timing is enabled
|
* @return a valid timing if the Performance Timing is enabled
|
||||||
*/
|
*/
|
||||||
DOMHighResTimeStamp
|
DOMHighResTimeStamp
|
||||||
PerformanceTiming::RedirectEndHighRes()
|
PerformanceTimingData::RedirectEndHighRes(Performance* aPerformance)
|
||||||
{
|
{
|
||||||
|
MOZ_ASSERT(aPerformance);
|
||||||
|
|
||||||
if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized() ||
|
if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized() ||
|
||||||
nsContentUtils::ShouldResistFingerprinting()) {
|
nsContentUtils::ShouldResistFingerprinting()) {
|
||||||
return mZeroTime;
|
return mZeroTime;
|
||||||
}
|
}
|
||||||
return TimeStampToReducedDOMHighResOrFetchStart(mRedirectEnd);
|
return TimeStampToReducedDOMHighResOrFetchStart(aPerformance, mRedirectEnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
DOMTimeMilliSec
|
DOMTimeMilliSec
|
||||||
PerformanceTiming::RedirectEnd()
|
PerformanceTiming::RedirectEnd()
|
||||||
{
|
{
|
||||||
if (!IsInitialized()) {
|
if (!mTimingData->IsInitialized()) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
// We have to check if all the redirect URIs had the same origin (since there
|
// We have to check if all the redirect URIs had the same origin (since there
|
||||||
// is no check in RedirectEndHighRes())
|
// is no check in RedirectEndHighRes())
|
||||||
if (mAllRedirectsSameOrigin && mRedirectCount) {
|
if (mTimingData->AllRedirectsSameOrigin() &&
|
||||||
return static_cast<int64_t>(RedirectEndHighRes());
|
mTimingData->RedirectCountReal()) {
|
||||||
|
return static_cast<int64_t>(mTimingData->RedirectEndHighRes(mPerformance));
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
DOMHighResTimeStamp
|
DOMHighResTimeStamp
|
||||||
PerformanceTiming::DomainLookupStartHighRes()
|
PerformanceTimingData::DomainLookupStartHighRes(Performance* aPerformance)
|
||||||
{
|
{
|
||||||
|
MOZ_ASSERT(aPerformance);
|
||||||
|
|
||||||
if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized() ||
|
if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized() ||
|
||||||
nsContentUtils::ShouldResistFingerprinting()) {
|
nsContentUtils::ShouldResistFingerprinting()) {
|
||||||
return mZeroTime;
|
return mZeroTime;
|
||||||
}
|
}
|
||||||
return TimeStampToReducedDOMHighResOrFetchStart(mDomainLookupStart);
|
return TimeStampToReducedDOMHighResOrFetchStart(aPerformance,
|
||||||
|
mDomainLookupStart);
|
||||||
}
|
}
|
||||||
|
|
||||||
DOMTimeMilliSec
|
DOMTimeMilliSec
|
||||||
PerformanceTiming::DomainLookupStart()
|
PerformanceTiming::DomainLookupStart()
|
||||||
{
|
{
|
||||||
return static_cast<int64_t>(DomainLookupStartHighRes());
|
return static_cast<int64_t>(mTimingData->DomainLookupStartHighRes(mPerformance));
|
||||||
}
|
}
|
||||||
|
|
||||||
DOMHighResTimeStamp
|
DOMHighResTimeStamp
|
||||||
PerformanceTiming::DomainLookupEndHighRes()
|
PerformanceTimingData::DomainLookupEndHighRes(Performance* aPerformance)
|
||||||
{
|
{
|
||||||
|
MOZ_ASSERT(aPerformance);
|
||||||
|
|
||||||
if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized() ||
|
if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized() ||
|
||||||
nsContentUtils::ShouldResistFingerprinting()) {
|
nsContentUtils::ShouldResistFingerprinting()) {
|
||||||
return mZeroTime;
|
return mZeroTime;
|
||||||
}
|
}
|
||||||
// Bug 1155008 - nsHttpTransaction is racy. Return DomainLookupStart when null
|
// Bug 1155008 - nsHttpTransaction is racy. Return DomainLookupStart when null
|
||||||
return mDomainLookupEnd.IsNull() ? DomainLookupStartHighRes()
|
return mDomainLookupEnd.IsNull()
|
||||||
: nsRFPService::ReduceTimePrecisionAsMSecs(
|
? DomainLookupStartHighRes(aPerformance)
|
||||||
TimeStampToDOMHighRes(mDomainLookupEnd));
|
: nsRFPService::ReduceTimePrecisionAsMSecs(
|
||||||
|
TimeStampToDOMHighRes(aPerformance, mDomainLookupEnd));
|
||||||
}
|
}
|
||||||
|
|
||||||
DOMTimeMilliSec
|
DOMTimeMilliSec
|
||||||
PerformanceTiming::DomainLookupEnd()
|
PerformanceTiming::DomainLookupEnd()
|
||||||
{
|
{
|
||||||
return static_cast<int64_t>(DomainLookupEndHighRes());
|
return static_cast<int64_t>(mTimingData->DomainLookupEndHighRes(mPerformance));
|
||||||
}
|
}
|
||||||
|
|
||||||
DOMHighResTimeStamp
|
DOMHighResTimeStamp
|
||||||
PerformanceTiming::ConnectStartHighRes()
|
PerformanceTimingData::ConnectStartHighRes(Performance* aPerformance)
|
||||||
{
|
{
|
||||||
|
MOZ_ASSERT(aPerformance);
|
||||||
|
|
||||||
if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized() ||
|
if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized() ||
|
||||||
nsContentUtils::ShouldResistFingerprinting()) {
|
nsContentUtils::ShouldResistFingerprinting()) {
|
||||||
return mZeroTime;
|
return mZeroTime;
|
||||||
}
|
}
|
||||||
return mConnectStart.IsNull() ? DomainLookupEndHighRes()
|
return mConnectStart.IsNull()
|
||||||
: nsRFPService::ReduceTimePrecisionAsMSecs(
|
? DomainLookupEndHighRes(aPerformance)
|
||||||
TimeStampToDOMHighRes(mConnectStart));
|
: nsRFPService::ReduceTimePrecisionAsMSecs(
|
||||||
|
TimeStampToDOMHighRes(aPerformance, mConnectStart));
|
||||||
}
|
}
|
||||||
|
|
||||||
DOMTimeMilliSec
|
DOMTimeMilliSec
|
||||||
PerformanceTiming::ConnectStart()
|
PerformanceTiming::ConnectStart()
|
||||||
{
|
{
|
||||||
return static_cast<int64_t>(ConnectStartHighRes());
|
return static_cast<int64_t>(mTimingData->ConnectStartHighRes(mPerformance));
|
||||||
}
|
}
|
||||||
|
|
||||||
DOMHighResTimeStamp
|
DOMHighResTimeStamp
|
||||||
PerformanceTiming::SecureConnectionStartHighRes()
|
PerformanceTimingData::SecureConnectionStartHighRes(Performance* aPerformance)
|
||||||
{
|
{
|
||||||
|
MOZ_ASSERT(aPerformance);
|
||||||
|
|
||||||
if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized() ||
|
if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized() ||
|
||||||
nsContentUtils::ShouldResistFingerprinting()) {
|
nsContentUtils::ShouldResistFingerprinting()) {
|
||||||
return mZeroTime;
|
return mZeroTime;
|
||||||
|
|
@ -392,39 +492,45 @@ PerformanceTiming::SecureConnectionStartHighRes()
|
||||||
return !mSecureConnection
|
return !mSecureConnection
|
||||||
? 0 // We use 0 here, because mZeroTime is sometimes set to the navigation
|
? 0 // We use 0 here, because mZeroTime is sometimes set to the navigation
|
||||||
// start time.
|
// start time.
|
||||||
: (mSecureConnectionStart.IsNull() ? mZeroTime
|
: (mSecureConnectionStart.IsNull()
|
||||||
: nsRFPService::ReduceTimePrecisionAsMSecs(
|
? mZeroTime
|
||||||
TimeStampToDOMHighRes(mSecureConnectionStart)));
|
: nsRFPService::ReduceTimePrecisionAsMSecs(
|
||||||
|
TimeStampToDOMHighRes(aPerformance, mSecureConnectionStart)));
|
||||||
}
|
}
|
||||||
|
|
||||||
DOMTimeMilliSec
|
DOMTimeMilliSec
|
||||||
PerformanceTiming::SecureConnectionStart()
|
PerformanceTiming::SecureConnectionStart()
|
||||||
{
|
{
|
||||||
return static_cast<int64_t>(SecureConnectionStartHighRes());
|
return static_cast<int64_t>(mTimingData->SecureConnectionStartHighRes(mPerformance));
|
||||||
}
|
}
|
||||||
|
|
||||||
DOMHighResTimeStamp
|
DOMHighResTimeStamp
|
||||||
PerformanceTiming::ConnectEndHighRes()
|
PerformanceTimingData::ConnectEndHighRes(Performance* aPerformance)
|
||||||
{
|
{
|
||||||
|
MOZ_ASSERT(aPerformance);
|
||||||
|
|
||||||
if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized() ||
|
if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized() ||
|
||||||
nsContentUtils::ShouldResistFingerprinting()) {
|
nsContentUtils::ShouldResistFingerprinting()) {
|
||||||
return mZeroTime;
|
return mZeroTime;
|
||||||
}
|
}
|
||||||
// Bug 1155008 - nsHttpTransaction is racy. Return ConnectStart when null
|
// Bug 1155008 - nsHttpTransaction is racy. Return ConnectStart when null
|
||||||
return mConnectEnd.IsNull() ? ConnectStartHighRes()
|
return mConnectEnd.IsNull()
|
||||||
: nsRFPService::ReduceTimePrecisionAsMSecs(
|
? ConnectStartHighRes(aPerformance)
|
||||||
TimeStampToDOMHighRes(mConnectEnd));
|
: nsRFPService::ReduceTimePrecisionAsMSecs(
|
||||||
|
TimeStampToDOMHighRes(aPerformance, mConnectEnd));
|
||||||
}
|
}
|
||||||
|
|
||||||
DOMTimeMilliSec
|
DOMTimeMilliSec
|
||||||
PerformanceTiming::ConnectEnd()
|
PerformanceTiming::ConnectEnd()
|
||||||
{
|
{
|
||||||
return static_cast<int64_t>(ConnectEndHighRes());
|
return static_cast<int64_t>(mTimingData->ConnectEndHighRes(mPerformance));
|
||||||
}
|
}
|
||||||
|
|
||||||
DOMHighResTimeStamp
|
DOMHighResTimeStamp
|
||||||
PerformanceTiming::RequestStartHighRes()
|
PerformanceTimingData::RequestStartHighRes(Performance* aPerformance)
|
||||||
{
|
{
|
||||||
|
MOZ_ASSERT(aPerformance);
|
||||||
|
|
||||||
if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized() ||
|
if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized() ||
|
||||||
nsContentUtils::ShouldResistFingerprinting()) {
|
nsContentUtils::ShouldResistFingerprinting()) {
|
||||||
return mZeroTime;
|
return mZeroTime;
|
||||||
|
|
@ -434,18 +540,20 @@ PerformanceTiming::RequestStartHighRes()
|
||||||
mRequestStart = mWorkerRequestStart;
|
mRequestStart = mWorkerRequestStart;
|
||||||
}
|
}
|
||||||
|
|
||||||
return TimeStampToReducedDOMHighResOrFetchStart(mRequestStart);
|
return TimeStampToReducedDOMHighResOrFetchStart(aPerformance, mRequestStart);
|
||||||
}
|
}
|
||||||
|
|
||||||
DOMTimeMilliSec
|
DOMTimeMilliSec
|
||||||
PerformanceTiming::RequestStart()
|
PerformanceTiming::RequestStart()
|
||||||
{
|
{
|
||||||
return static_cast<int64_t>(RequestStartHighRes());
|
return static_cast<int64_t>(mTimingData->RequestStartHighRes(mPerformance));
|
||||||
}
|
}
|
||||||
|
|
||||||
DOMHighResTimeStamp
|
DOMHighResTimeStamp
|
||||||
PerformanceTiming::ResponseStartHighRes()
|
PerformanceTimingData::ResponseStartHighRes(Performance* aPerformance)
|
||||||
{
|
{
|
||||||
|
MOZ_ASSERT(aPerformance);
|
||||||
|
|
||||||
if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized() ||
|
if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized() ||
|
||||||
nsContentUtils::ShouldResistFingerprinting()) {
|
nsContentUtils::ShouldResistFingerprinting()) {
|
||||||
return mZeroTime;
|
return mZeroTime;
|
||||||
|
|
@ -459,18 +567,20 @@ PerformanceTiming::ResponseStartHighRes()
|
||||||
(!mRequestStart.IsNull() && mResponseStart < mRequestStart)) {
|
(!mRequestStart.IsNull() && mResponseStart < mRequestStart)) {
|
||||||
mResponseStart = mRequestStart;
|
mResponseStart = mRequestStart;
|
||||||
}
|
}
|
||||||
return TimeStampToReducedDOMHighResOrFetchStart(mResponseStart);
|
return TimeStampToReducedDOMHighResOrFetchStart(aPerformance, mResponseStart);
|
||||||
}
|
}
|
||||||
|
|
||||||
DOMTimeMilliSec
|
DOMTimeMilliSec
|
||||||
PerformanceTiming::ResponseStart()
|
PerformanceTiming::ResponseStart()
|
||||||
{
|
{
|
||||||
return static_cast<int64_t>(ResponseStartHighRes());
|
return static_cast<int64_t>(mTimingData->ResponseStartHighRes(mPerformance));
|
||||||
}
|
}
|
||||||
|
|
||||||
DOMHighResTimeStamp
|
DOMHighResTimeStamp
|
||||||
PerformanceTiming::ResponseEndHighRes()
|
PerformanceTimingData::ResponseEndHighRes(Performance* aPerformance)
|
||||||
{
|
{
|
||||||
|
MOZ_ASSERT(aPerformance);
|
||||||
|
|
||||||
if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized() ||
|
if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized() ||
|
||||||
nsContentUtils::ShouldResistFingerprinting()) {
|
nsContentUtils::ShouldResistFingerprinting()) {
|
||||||
return mZeroTime;
|
return mZeroTime;
|
||||||
|
|
@ -483,21 +593,16 @@ PerformanceTiming::ResponseEndHighRes()
|
||||||
mResponseEnd = mWorkerResponseEnd;
|
mResponseEnd = mWorkerResponseEnd;
|
||||||
}
|
}
|
||||||
// Bug 1155008 - nsHttpTransaction is racy. Return ResponseStart when null
|
// Bug 1155008 - nsHttpTransaction is racy. Return ResponseStart when null
|
||||||
return mResponseEnd.IsNull() ? ResponseStartHighRes()
|
return mResponseEnd.IsNull()
|
||||||
: nsRFPService::ReduceTimePrecisionAsMSecs(
|
? ResponseStartHighRes(aPerformance)
|
||||||
TimeStampToDOMHighRes(mResponseEnd));
|
: nsRFPService::ReduceTimePrecisionAsMSecs(
|
||||||
|
TimeStampToDOMHighRes(aPerformance, mResponseEnd));
|
||||||
}
|
}
|
||||||
|
|
||||||
DOMTimeMilliSec
|
DOMTimeMilliSec
|
||||||
PerformanceTiming::ResponseEnd()
|
PerformanceTiming::ResponseEnd()
|
||||||
{
|
{
|
||||||
return static_cast<int64_t>(ResponseEndHighRes());
|
return static_cast<int64_t>(mTimingData->ResponseEndHighRes(mPerformance));
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
PerformanceTiming::IsInitialized() const
|
|
||||||
{
|
|
||||||
return mInitialized;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JSObject*
|
JSObject*
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,204 @@ class nsITimedChannel;
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace dom {
|
namespace dom {
|
||||||
|
|
||||||
|
class PerformanceTiming;
|
||||||
|
|
||||||
|
class PerformanceTimingData final
|
||||||
|
{
|
||||||
|
friend class PerformanceTiming;
|
||||||
|
|
||||||
|
public:
|
||||||
|
// This can return null.
|
||||||
|
static PerformanceTimingData*
|
||||||
|
Create(nsITimedChannel* aChannel,
|
||||||
|
nsIHttpChannel* aHttpChannel,
|
||||||
|
DOMHighResTimeStamp aZeroTime,
|
||||||
|
nsAString& aInitiatorType,
|
||||||
|
nsAString& aEntryName);
|
||||||
|
|
||||||
|
PerformanceTimingData(nsITimedChannel* aChannel,
|
||||||
|
nsIHttpChannel* aHttpChannel,
|
||||||
|
DOMHighResTimeStamp aZeroTime);
|
||||||
|
|
||||||
|
void
|
||||||
|
SetPropertiesFromHttpChannel(nsIHttpChannel* aHttpChannel);
|
||||||
|
|
||||||
|
bool IsInitialized() const
|
||||||
|
{
|
||||||
|
return mInitialized;
|
||||||
|
}
|
||||||
|
|
||||||
|
const nsString& NextHopProtocol() const
|
||||||
|
{
|
||||||
|
return mNextHopProtocol;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t TransferSize() const
|
||||||
|
{
|
||||||
|
return mTimingAllowed ? mTransferSize : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t EncodedBodySize() const
|
||||||
|
{
|
||||||
|
return mTimingAllowed ? mEncodedBodySize : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t DecodedBodySize() const
|
||||||
|
{
|
||||||
|
return mTimingAllowed ? mDecodedBodySize : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param aStamp
|
||||||
|
* The TimeStamp recorded for a specific event. This TimeStamp can
|
||||||
|
* be null.
|
||||||
|
* @return the duration of an event with a given TimeStamp, relative to the
|
||||||
|
* navigationStart TimeStamp (the moment the user landed on the
|
||||||
|
* page), if the given TimeStamp is valid. Otherwise, it will return
|
||||||
|
* the FetchStart timing value.
|
||||||
|
*/
|
||||||
|
inline DOMHighResTimeStamp
|
||||||
|
TimeStampToReducedDOMHighResOrFetchStart(Performance* aPerformance,
|
||||||
|
TimeStamp aStamp)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(aPerformance);
|
||||||
|
|
||||||
|
return (!aStamp.IsNull())
|
||||||
|
? nsRFPService::ReduceTimePrecisionAsMSecs(
|
||||||
|
TimeStampToDOMHighRes(aPerformance, aStamp))
|
||||||
|
: FetchStartHighRes(aPerformance);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The nsITimedChannel records an absolute timestamp for each event.
|
||||||
|
* The nsDOMNavigationTiming will record the moment when the user landed on
|
||||||
|
* the page. This is a window.performance unique timestamp, so it can be used
|
||||||
|
* for all the events (navigation timing and resource timing events).
|
||||||
|
*
|
||||||
|
* The algorithm operates in 2 steps:
|
||||||
|
* 1. The first step is to subtract the two timestamps: the argument (the
|
||||||
|
* event's timestamp) and the navigation start timestamp. This will result in
|
||||||
|
* a relative timestamp of the event (relative to the navigation start -
|
||||||
|
* window.performance.timing.navigationStart).
|
||||||
|
* 2. The second step is to add any required offset (the mZeroTime). For now,
|
||||||
|
* this offset value is either 0 (for the resource timing), or equal to
|
||||||
|
* "performance.navigationStart" (for navigation timing).
|
||||||
|
* For the resource timing, mZeroTime is set to 0, causing the result to be a
|
||||||
|
* relative time.
|
||||||
|
* For the navigation timing, mZeroTime is set to "performance.navigationStart"
|
||||||
|
* causing the result be an absolute time.
|
||||||
|
*
|
||||||
|
* @param aStamp
|
||||||
|
* The TimeStamp recorded for a specific event. This TimeStamp can't
|
||||||
|
* be null.
|
||||||
|
* @return number of milliseconds value as one of:
|
||||||
|
* - relative to the navigation start time, time the user has landed on the
|
||||||
|
* page
|
||||||
|
* - an absolute wall clock time since the unix epoch
|
||||||
|
*/
|
||||||
|
inline DOMHighResTimeStamp
|
||||||
|
TimeStampToDOMHighRes(Performance* aPerformance, TimeStamp aStamp) const
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(aPerformance);
|
||||||
|
MOZ_ASSERT(!aStamp.IsNull());
|
||||||
|
|
||||||
|
TimeDuration duration = aStamp - aPerformance->CreationTimeStamp();
|
||||||
|
return duration.ToMilliseconds() + mZeroTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The last channel's AsyncOpen time. This may occur before the FetchStart
|
||||||
|
// in some cases.
|
||||||
|
DOMHighResTimeStamp AsyncOpenHighRes(Performance* aPerformance);
|
||||||
|
|
||||||
|
// High resolution (used by resource timing)
|
||||||
|
DOMHighResTimeStamp WorkerStartHighRes(Performance* aPerformance);
|
||||||
|
DOMHighResTimeStamp FetchStartHighRes(Performance* aPerformance);
|
||||||
|
DOMHighResTimeStamp RedirectStartHighRes(Performance* aPerformance);
|
||||||
|
DOMHighResTimeStamp RedirectEndHighRes(Performance* aPerformance);
|
||||||
|
DOMHighResTimeStamp DomainLookupStartHighRes(Performance* aPerformance);
|
||||||
|
DOMHighResTimeStamp DomainLookupEndHighRes(Performance* aPerformance);
|
||||||
|
DOMHighResTimeStamp ConnectStartHighRes(Performance* aPerformance);
|
||||||
|
DOMHighResTimeStamp SecureConnectionStartHighRes(Performance* aPerformance);
|
||||||
|
DOMHighResTimeStamp ConnectEndHighRes(Performance* aPerformance);
|
||||||
|
DOMHighResTimeStamp RequestStartHighRes(Performance* aPerformance);
|
||||||
|
DOMHighResTimeStamp ResponseStartHighRes(Performance* aPerformance);
|
||||||
|
DOMHighResTimeStamp ResponseEndHighRes(Performance* aPerformance);
|
||||||
|
|
||||||
|
DOMHighResTimeStamp ZeroTime() const { return mZeroTime; }
|
||||||
|
|
||||||
|
uint8_t RedirectCountReal() const { return mRedirectCount; }
|
||||||
|
uint8_t GetRedirectCount() const;
|
||||||
|
|
||||||
|
bool AllRedirectsSameOrigin() const { return mAllRedirectsSameOrigin; }
|
||||||
|
|
||||||
|
// If this is false the values of redirectStart/End will be 0 This is false if
|
||||||
|
// no redirects occured, or if any of the responses failed the
|
||||||
|
// timing-allow-origin check in HttpBaseChannel::TimingAllowCheck
|
||||||
|
bool ShouldReportCrossOriginRedirect() const;
|
||||||
|
|
||||||
|
// Cached result of CheckAllowedOrigin. If false, security sensitive
|
||||||
|
// attributes of the resourceTiming object will be set to 0
|
||||||
|
bool TimingAllowed() const
|
||||||
|
{
|
||||||
|
return mTimingAllowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Checks if the resource is either same origin as the page that started
|
||||||
|
// the load, or if the response contains the Timing-Allow-Origin header
|
||||||
|
// with a value of * or matching the domain of the loading Principal
|
||||||
|
bool CheckAllowedOrigin(nsIHttpChannel* aResourceChannel,
|
||||||
|
nsITimedChannel* aChannel);
|
||||||
|
|
||||||
|
nsString mNextHopProtocol;
|
||||||
|
|
||||||
|
TimeStamp mAsyncOpen;
|
||||||
|
TimeStamp mRedirectStart;
|
||||||
|
TimeStamp mRedirectEnd;
|
||||||
|
TimeStamp mDomainLookupStart;
|
||||||
|
TimeStamp mDomainLookupEnd;
|
||||||
|
TimeStamp mConnectStart;
|
||||||
|
TimeStamp mSecureConnectionStart;
|
||||||
|
TimeStamp mConnectEnd;
|
||||||
|
TimeStamp mRequestStart;
|
||||||
|
TimeStamp mResponseStart;
|
||||||
|
TimeStamp mCacheReadStart;
|
||||||
|
TimeStamp mResponseEnd;
|
||||||
|
TimeStamp mCacheReadEnd;
|
||||||
|
|
||||||
|
// ServiceWorker interception timing information
|
||||||
|
TimeStamp mWorkerStart;
|
||||||
|
TimeStamp mWorkerRequestStart;
|
||||||
|
TimeStamp mWorkerResponseEnd;
|
||||||
|
|
||||||
|
// This is an offset that will be added to each timing ([ms] resolution).
|
||||||
|
// There are only 2 possible values: (1) logicaly equal to navigationStart
|
||||||
|
// TimeStamp (results are absolute timstamps - wallclock); (2) "0" (results
|
||||||
|
// are relative to the navigation start).
|
||||||
|
DOMHighResTimeStamp mZeroTime;
|
||||||
|
|
||||||
|
DOMHighResTimeStamp mFetchStart;
|
||||||
|
|
||||||
|
uint64_t mEncodedBodySize;
|
||||||
|
uint64_t mTransferSize;
|
||||||
|
uint64_t mDecodedBodySize;
|
||||||
|
|
||||||
|
uint8_t mRedirectCount;
|
||||||
|
|
||||||
|
bool mAllRedirectsSameOrigin;
|
||||||
|
|
||||||
|
// If the resourceTiming object should have non-zero redirectStart and
|
||||||
|
// redirectEnd attributes. It is false if there were no redirects, or if any
|
||||||
|
// of the responses didn't pass the timing-allow-check
|
||||||
|
bool mReportCrossOriginRedirect;
|
||||||
|
|
||||||
|
bool mSecureConnection;
|
||||||
|
|
||||||
|
bool mTimingAllowed;
|
||||||
|
|
||||||
|
bool mInitialized;
|
||||||
|
};
|
||||||
|
|
||||||
// Script "performance.timing" object
|
// Script "performance.timing" object
|
||||||
class PerformanceTiming final : public nsWrapperCache
|
class PerformanceTiming final : public nsWrapperCache
|
||||||
{
|
{
|
||||||
|
|
@ -60,57 +258,6 @@ public:
|
||||||
return mPerformance;
|
return mPerformance;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param aStamp
|
|
||||||
* The TimeStamp recorded for a specific event. This TimeStamp can
|
|
||||||
* be null.
|
|
||||||
* @return the duration of an event with a given TimeStamp, relative to the
|
|
||||||
* navigationStart TimeStamp (the moment the user landed on the
|
|
||||||
* page), if the given TimeStamp is valid. Otherwise, it will return
|
|
||||||
* the FetchStart timing value.
|
|
||||||
*/
|
|
||||||
inline DOMHighResTimeStamp TimeStampToReducedDOMHighResOrFetchStart(TimeStamp aStamp)
|
|
||||||
{
|
|
||||||
return (!aStamp.IsNull())
|
|
||||||
? nsRFPService::ReduceTimePrecisionAsMSecs(TimeStampToDOMHighRes(aStamp))
|
|
||||||
: FetchStartHighRes();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The nsITimedChannel records an absolute timestamp for each event.
|
|
||||||
* The nsDOMNavigationTiming will record the moment when the user landed on
|
|
||||||
* the page. This is a window.performance unique timestamp, so it can be used
|
|
||||||
* for all the events (navigation timing and resource timing events).
|
|
||||||
*
|
|
||||||
* The algorithm operates in 2 steps:
|
|
||||||
* 1. The first step is to subtract the two timestamps: the argument (the
|
|
||||||
* envet's timesramp) and the navigation start timestamp. This will result in
|
|
||||||
* a relative timestamp of the event (relative to the navigation start -
|
|
||||||
* window.performance.timing.navigationStart).
|
|
||||||
* 2. The second step is to add any required offset (the mZeroTime). For now,
|
|
||||||
* this offset value is either 0 (for the resource timing), or equal to
|
|
||||||
* "performance.navigationStart" (for navigation timing).
|
|
||||||
* For the resource timing, mZeroTime is set to 0, causing the result to be a
|
|
||||||
* relative time.
|
|
||||||
* For the navigation timing, mZeroTime is set to "performance.navigationStart"
|
|
||||||
* causing the result be an absolute time.
|
|
||||||
*
|
|
||||||
* @param aStamp
|
|
||||||
* The TimeStamp recorded for a specific event. This TimeStamp can't
|
|
||||||
* be null.
|
|
||||||
* @return number of milliseconds value as one of:
|
|
||||||
* - relative to the navigation start time, time the user has landed on the
|
|
||||||
* page
|
|
||||||
* - an absolute wall clock time since the unix epoch
|
|
||||||
*/
|
|
||||||
inline DOMHighResTimeStamp TimeStampToDOMHighRes(TimeStamp aStamp) const
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(!aStamp.IsNull());
|
|
||||||
TimeDuration duration =
|
|
||||||
aStamp - GetDOMTiming()->GetNavigationStartTimeStamp();
|
|
||||||
return duration.ToMilliseconds() + mZeroTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual JSObject* WrapObject(JSContext *cx,
|
virtual JSObject* WrapObject(JSContext *cx,
|
||||||
JS::Handle<JSObject*> aGivenProto) override;
|
JS::Handle<JSObject*> aGivenProto) override;
|
||||||
|
|
||||||
|
|
@ -145,40 +292,6 @@ public:
|
||||||
GetDOMTiming()->GetUnloadEventEnd());
|
GetDOMTiming()->GetUnloadEventEnd());
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t GetRedirectCount() const;
|
|
||||||
|
|
||||||
// Checks if the resource is either same origin as the page that started
|
|
||||||
// the load, or if the response contains the Timing-Allow-Origin header
|
|
||||||
// with a value of * or matching the domain of the loading Principal
|
|
||||||
bool CheckAllowedOrigin(nsIHttpChannel* aResourceChannel, nsITimedChannel* aChannel);
|
|
||||||
|
|
||||||
// Cached result of CheckAllowedOrigin. If false, security sensitive
|
|
||||||
// attributes of the resourceTiming object will be set to 0
|
|
||||||
bool TimingAllowed() const;
|
|
||||||
|
|
||||||
// If this is false the values of redirectStart/End will be 0
|
|
||||||
// This is false if no redirects occured, or if any of the responses failed
|
|
||||||
// the timing-allow-origin check in HttpBaseChannel::TimingAllowCheck
|
|
||||||
bool ShouldReportCrossOriginRedirect() const;
|
|
||||||
|
|
||||||
// The last channel's AsyncOpen time. This may occur before the FetchStart
|
|
||||||
// in some cases.
|
|
||||||
DOMHighResTimeStamp AsyncOpenHighRes();
|
|
||||||
|
|
||||||
// High resolution (used by resource timing)
|
|
||||||
DOMHighResTimeStamp WorkerStartHighRes();
|
|
||||||
DOMHighResTimeStamp FetchStartHighRes();
|
|
||||||
DOMHighResTimeStamp RedirectStartHighRes();
|
|
||||||
DOMHighResTimeStamp RedirectEndHighRes();
|
|
||||||
DOMHighResTimeStamp DomainLookupStartHighRes();
|
|
||||||
DOMHighResTimeStamp DomainLookupEndHighRes();
|
|
||||||
DOMHighResTimeStamp ConnectStartHighRes();
|
|
||||||
DOMHighResTimeStamp SecureConnectionStartHighRes();
|
|
||||||
DOMHighResTimeStamp ConnectEndHighRes();
|
|
||||||
DOMHighResTimeStamp RequestStartHighRes();
|
|
||||||
DOMHighResTimeStamp ResponseStartHighRes();
|
|
||||||
DOMHighResTimeStamp ResponseEndHighRes();
|
|
||||||
|
|
||||||
// Low resolution (used by navigation timing)
|
// Low resolution (used by navigation timing)
|
||||||
DOMTimeMilliSec FetchStart();
|
DOMTimeMilliSec FetchStart();
|
||||||
DOMTimeMilliSec RedirectStart();
|
DOMTimeMilliSec RedirectStart();
|
||||||
|
|
@ -272,53 +385,19 @@ public:
|
||||||
GetDOMTiming()->GetTimeToNonBlankPaint());
|
GetDOMTiming()->GetTimeToNonBlankPaint());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PerformanceTimingData* Data() const
|
||||||
|
{
|
||||||
|
return mTimingData.get();
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
~PerformanceTiming();
|
~PerformanceTiming();
|
||||||
|
|
||||||
bool IsInitialized() const;
|
|
||||||
void InitializeTimingInfo(nsITimedChannel* aChannel);
|
|
||||||
|
|
||||||
bool IsTopLevelContentDocument() const;
|
bool IsTopLevelContentDocument() const;
|
||||||
|
|
||||||
RefPtr<Performance> mPerformance;
|
RefPtr<Performance> mPerformance;
|
||||||
DOMHighResTimeStamp mFetchStart;
|
|
||||||
|
|
||||||
// This is an offset that will be added to each timing ([ms] resolution).
|
UniquePtr<PerformanceTimingData> mTimingData;
|
||||||
// There are only 2 possible values: (1) logicaly equal to navigationStart
|
|
||||||
// TimeStamp (results are absolute timstamps - wallclock); (2) "0" (results
|
|
||||||
// are relative to the navigation start).
|
|
||||||
DOMHighResTimeStamp mZeroTime;
|
|
||||||
|
|
||||||
TimeStamp mAsyncOpen;
|
|
||||||
TimeStamp mRedirectStart;
|
|
||||||
TimeStamp mRedirectEnd;
|
|
||||||
TimeStamp mDomainLookupStart;
|
|
||||||
TimeStamp mDomainLookupEnd;
|
|
||||||
TimeStamp mConnectStart;
|
|
||||||
TimeStamp mSecureConnectionStart;
|
|
||||||
TimeStamp mConnectEnd;
|
|
||||||
TimeStamp mRequestStart;
|
|
||||||
TimeStamp mResponseStart;
|
|
||||||
TimeStamp mCacheReadStart;
|
|
||||||
TimeStamp mResponseEnd;
|
|
||||||
TimeStamp mCacheReadEnd;
|
|
||||||
|
|
||||||
// ServiceWorker interception timing information
|
|
||||||
TimeStamp mWorkerStart;
|
|
||||||
TimeStamp mWorkerRequestStart;
|
|
||||||
TimeStamp mWorkerResponseEnd;
|
|
||||||
|
|
||||||
uint8_t mRedirectCount;
|
|
||||||
bool mTimingAllowed;
|
|
||||||
bool mAllRedirectsSameOrigin;
|
|
||||||
bool mInitialized;
|
|
||||||
|
|
||||||
// If the resourceTiming object should have non-zero redirectStart and
|
|
||||||
// redirectEnd attributes. It is false if there were no redirects, or if
|
|
||||||
// any of the responses didn't pass the timing-allow-check
|
|
||||||
bool mReportCrossOriginRedirect;
|
|
||||||
|
|
||||||
bool mSecureConnection;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace dom
|
} // namespace dom
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,12 @@ class PerformanceWorker final : public Performance
|
||||||
public:
|
public:
|
||||||
explicit PerformanceWorker(workers::WorkerPrivate* aWorkerPrivate);
|
explicit PerformanceWorker(workers::WorkerPrivate* aWorkerPrivate);
|
||||||
|
|
||||||
|
PerformanceStorage* AsPerformanceStorage() override
|
||||||
|
{
|
||||||
|
MOZ_CRASH("This should not be called on workers.");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
virtual PerformanceTiming* Timing() override
|
virtual PerformanceTiming* Timing() override
|
||||||
{
|
{
|
||||||
MOZ_CRASH("This should not be called on workers.");
|
MOZ_CRASH("This should not be called on workers.");
|
||||||
|
|
@ -33,12 +39,6 @@ public:
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void AddEntry(nsIHttpChannel* channel,
|
|
||||||
nsITimedChannel* timedChannel) override
|
|
||||||
{
|
|
||||||
MOZ_CRASH("This should not be called on workers.");
|
|
||||||
}
|
|
||||||
|
|
||||||
TimeStamp CreationTimeStamp() const override;
|
TimeStamp CreationTimeStamp() const override;
|
||||||
|
|
||||||
DOMHighResTimeStamp CreationTime() const override;
|
DOMHighResTimeStamp CreationTime() const override;
|
||||||
|
|
@ -68,7 +68,7 @@ protected:
|
||||||
|
|
||||||
void DispatchBufferFullEvent() override
|
void DispatchBufferFullEvent() override
|
||||||
{
|
{
|
||||||
MOZ_CRASH("This should not be called on workers.");
|
// Nothing to do here. See bug 1432758.
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,8 @@ EXPORTS.mozilla.dom += [
|
||||||
'PerformanceObserverEntryList.h',
|
'PerformanceObserverEntryList.h',
|
||||||
'PerformanceResourceTiming.h',
|
'PerformanceResourceTiming.h',
|
||||||
'PerformanceService.h',
|
'PerformanceService.h',
|
||||||
|
'PerformanceStorage.h',
|
||||||
|
'PerformanceStorageWorker.h',
|
||||||
'PerformanceTiming.h',
|
'PerformanceTiming.h',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
@ -33,6 +35,7 @@ UNIFIED_SOURCES += [
|
||||||
'PerformanceObserverEntryList.cpp',
|
'PerformanceObserverEntryList.cpp',
|
||||||
'PerformanceResourceTiming.cpp',
|
'PerformanceResourceTiming.cpp',
|
||||||
'PerformanceService.cpp',
|
'PerformanceService.cpp',
|
||||||
|
'PerformanceStorageWorker.cpp',
|
||||||
'PerformanceTiming.cpp',
|
'PerformanceTiming.cpp',
|
||||||
'PerformanceWorker.cpp',
|
'PerformanceWorker.cpp',
|
||||||
]
|
]
|
||||||
|
|
|
||||||
1
dom/performance/tests/empty.js
Normal file
1
dom/performance/tests/empty.js
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
/* Nothing here */
|
||||||
|
|
@ -6,6 +6,9 @@ support-files =
|
||||||
worker_performance_user_timing.js
|
worker_performance_user_timing.js
|
||||||
worker_performance_observer.js
|
worker_performance_observer.js
|
||||||
sharedworker_performance_user_timing.js
|
sharedworker_performance_user_timing.js
|
||||||
|
test_worker_performance_entries.js
|
||||||
|
test_worker_performance_entries.sjs
|
||||||
|
empty.js
|
||||||
|
|
||||||
[test_performance_observer.html]
|
[test_performance_observer.html]
|
||||||
[test_performance_user_timing.html]
|
[test_performance_user_timing.html]
|
||||||
|
|
@ -14,3 +17,4 @@ support-files =
|
||||||
[test_sharedWorker_performance_user_timing.html]
|
[test_sharedWorker_performance_user_timing.html]
|
||||||
[test_worker_performance_now.html]
|
[test_worker_performance_now.html]
|
||||||
[test_timeOrigin.html]
|
[test_timeOrigin.html]
|
||||||
|
[test_worker_performance_entries.html]
|
||||||
|
|
|
||||||
31
dom/performance/tests/test_worker_performance_entries.html
Normal file
31
dom/performance/tests/test_worker_performance_entries.html
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
<!-- Any copyright is dedicated to the Public Domain.
|
||||||
|
- http://creativecommons.org/publicdomain/zero/1.0/ -->
|
||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>PerformanceResouceTiming in workers</title>
|
||||||
|
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
|
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<script class="testbody" type="text/javascript">
|
||||||
|
|
||||||
|
SimpleTest.waitForExplicitFinish();
|
||||||
|
var worker = new Worker('test_worker_performance_entries.js');
|
||||||
|
worker.onmessage = function(event) {
|
||||||
|
if (event.data.type == "check") {
|
||||||
|
ok(event.data.status, event.data.msg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.data.type == "finish") {
|
||||||
|
SimpleTest.finish();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ok(false, "?!?");
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
102
dom/performance/tests/test_worker_performance_entries.js
Normal file
102
dom/performance/tests/test_worker_performance_entries.js
Normal file
|
|
@ -0,0 +1,102 @@
|
||||||
|
function ok(a, msg) {
|
||||||
|
postMessage({type: "check", status: !!a, msg });
|
||||||
|
}
|
||||||
|
|
||||||
|
function is(a, b, msg) {
|
||||||
|
ok(a === b, msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
function finish(a, msg) {
|
||||||
|
postMessage({type: "finish" });
|
||||||
|
}
|
||||||
|
|
||||||
|
function check(resource, initiatorType, protocol) {
|
||||||
|
let entries = performance.getEntries();
|
||||||
|
ok(entries.length == 1, "We have an entry");
|
||||||
|
|
||||||
|
ok(entries[0] instanceof PerformanceEntry,
|
||||||
|
"The entry is a PerformanceEntry");
|
||||||
|
ok(entries[0].name.endsWith(resource), "The entry has been found!");
|
||||||
|
|
||||||
|
is(entries[0].entryType, "resource", "Correct EntryType");
|
||||||
|
ok(entries[0].startTime > 0, "We have a startTime");
|
||||||
|
ok(entries[0].duration > 0, "We have a duration");
|
||||||
|
|
||||||
|
ok(entries[0] instanceof PerformanceResourceTiming,
|
||||||
|
"The entry is a PerformanceResourceTiming");
|
||||||
|
|
||||||
|
is(entries[0].initiatorType, initiatorType, "Correct initiatorType");
|
||||||
|
is(entries[0].nextHopProtocol, protocol, "Correct protocol");
|
||||||
|
|
||||||
|
performance.clearResourceTimings();
|
||||||
|
}
|
||||||
|
|
||||||
|
function simple_checks() {
|
||||||
|
ok("performance" in self, "We have self.performance");
|
||||||
|
performance.clearResourceTimings();
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
|
||||||
|
function fetch_request() {
|
||||||
|
fetch("test_worker_performance_entries.sjs")
|
||||||
|
.then(r => r.blob())
|
||||||
|
.then(blob => {
|
||||||
|
check("test_worker_performance_entries.sjs", "fetch", "http/1.1");
|
||||||
|
})
|
||||||
|
.then(next);
|
||||||
|
}
|
||||||
|
|
||||||
|
function xhr_request() {
|
||||||
|
let xhr = new XMLHttpRequest();
|
||||||
|
xhr.open("GET", "test_worker_performance_entries.sjs");
|
||||||
|
xhr.send();
|
||||||
|
xhr.onload = () => {
|
||||||
|
check("test_worker_performance_entries.sjs", "xmlhttprequest", "http/1.1");
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function sync_xhr_request() {
|
||||||
|
let xhr = new XMLHttpRequest();
|
||||||
|
xhr.open("GET", "test_worker_performance_entries.sjs", false);
|
||||||
|
xhr.send();
|
||||||
|
check("test_worker_performance_entries.sjs", "xmlhttprequest", "http/1.1");
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
|
||||||
|
function import_script() {
|
||||||
|
importScripts(["empty.js"]);
|
||||||
|
check("empty.js", "other", "http/1.1");
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
|
||||||
|
function redirect() {
|
||||||
|
fetch("test_worker_performance_entries.sjs?redirect")
|
||||||
|
.then(r => r.text())
|
||||||
|
.then(text => {
|
||||||
|
is(text, "Hello world \\o/", "The redirect worked correctly");
|
||||||
|
check("test_worker_performance_entries.sjs?redirect", "fetch", "http/1.1");
|
||||||
|
})
|
||||||
|
.then(next);
|
||||||
|
}
|
||||||
|
|
||||||
|
let tests = [
|
||||||
|
simple_checks,
|
||||||
|
fetch_request,
|
||||||
|
xhr_request,
|
||||||
|
sync_xhr_request,
|
||||||
|
import_script,
|
||||||
|
redirect,
|
||||||
|
];
|
||||||
|
|
||||||
|
function next() {
|
||||||
|
if (!tests.length) {
|
||||||
|
finish();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let test = tests.shift();
|
||||||
|
test();
|
||||||
|
}
|
||||||
|
|
||||||
|
next();
|
||||||
12
dom/performance/tests/test_worker_performance_entries.sjs
Normal file
12
dom/performance/tests/test_worker_performance_entries.sjs
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
function handleRequest(request, response)
|
||||||
|
{
|
||||||
|
response.setHeader("Content-Type", "text/html");
|
||||||
|
|
||||||
|
if (request.queryString == "redirect") {
|
||||||
|
response.setStatusLine(request.httpVersion, 302, "See Other");
|
||||||
|
response.setHeader("Location", "test_worker_performance_entries.sjs?ok");
|
||||||
|
} else {
|
||||||
|
response.setStatusLine(request.httpVersion, 200, "OK");
|
||||||
|
response.write("Hello world \\o/");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -3173,6 +3173,7 @@ nsresult nsPluginHost::NewPluginURLStream(const nsString& aURL,
|
||||||
nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_INHERITS |
|
nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_INHERITS |
|
||||||
nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL,
|
nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL,
|
||||||
nsIContentPolicy::TYPE_OBJECT_SUBREQUEST,
|
nsIContentPolicy::TYPE_OBJECT_SUBREQUEST,
|
||||||
|
nullptr, // aPerformanceStorage
|
||||||
nullptr, // aLoadGroup
|
nullptr, // aLoadGroup
|
||||||
listenerPeer,
|
listenerPeer,
|
||||||
nsIRequest::LOAD_NORMAL | nsIChannel::LOAD_CLASSIFY_URI |
|
nsIRequest::LOAD_NORMAL | nsIChannel::LOAD_CLASSIFY_URI |
|
||||||
|
|
|
||||||
|
|
@ -1065,6 +1065,7 @@ ScriptLoader::StartLoad(ScriptLoadRequest* aRequest)
|
||||||
aRequest->mTriggeringPrincipal,
|
aRequest->mTriggeringPrincipal,
|
||||||
securityFlags,
|
securityFlags,
|
||||||
contentPolicyType,
|
contentPolicyType,
|
||||||
|
nullptr, // aPerformanceStorage
|
||||||
loadGroup,
|
loadGroup,
|
||||||
prompter,
|
prompter,
|
||||||
nsIRequest::LOAD_NORMAL |
|
nsIRequest::LOAD_NORMAL |
|
||||||
|
|
|
||||||
|
|
@ -1073,6 +1073,7 @@ nsCSPContext::SendReports(
|
||||||
doc,
|
doc,
|
||||||
nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
|
nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
|
||||||
nsIContentPolicy::TYPE_CSP_REPORT,
|
nsIContentPolicy::TYPE_CSP_REPORT,
|
||||||
|
nullptr, // aPerformanceStorage
|
||||||
nullptr, // aLoadGroup
|
nullptr, // aLoadGroup
|
||||||
nullptr, // aCallbacks
|
nullptr, // aCallbacks
|
||||||
loadFlags);
|
loadFlags);
|
||||||
|
|
@ -1083,6 +1084,7 @@ nsCSPContext::SendReports(
|
||||||
mLoadingPrincipal,
|
mLoadingPrincipal,
|
||||||
nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
|
nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
|
||||||
nsIContentPolicy::TYPE_CSP_REPORT,
|
nsIContentPolicy::TYPE_CSP_REPORT,
|
||||||
|
nullptr, // PerformanceStorage
|
||||||
nullptr, // aLoadGroup
|
nullptr, // aLoadGroup
|
||||||
nullptr, // aCallbacks
|
nullptr, // aCallbacks
|
||||||
loadFlags);
|
loadFlags);
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,23 @@ namespace dom {
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
// nsISupports methods:
|
// nsISupports methods:
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
SVGDocument::InsertChildBefore(nsIContent* aKid, nsIContent* aBeforeThis,
|
||||||
|
bool aNotify)
|
||||||
|
{
|
||||||
|
if (aKid->IsElement() && !aKid->IsSVGElement()) {
|
||||||
|
// We can get here when well formed XML with a non-SVG root element is
|
||||||
|
// served with the SVG MIME type, for example. In that case we need to load
|
||||||
|
// the non-SVG UA sheets or else we can get bugs like bug 1016145. Note
|
||||||
|
// that we have to do this _before_ the XMLDocument::InsertChildBefore,
|
||||||
|
// since that can try to construct frames, and we need to have the sheets
|
||||||
|
// loaded by then.
|
||||||
|
EnsureNonSVGUserAgentStyleSheetsLoaded();
|
||||||
|
}
|
||||||
|
|
||||||
|
return XMLDocument::InsertChildBefore(aKid, aBeforeThis, aNotify);
|
||||||
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
SVGDocument::InsertChildAt_Deprecated(nsIContent* aKid, uint32_t aIndex,
|
SVGDocument::InsertChildAt_Deprecated(nsIContent* aKid, uint32_t aIndex,
|
||||||
bool aNotify)
|
bool aNotify)
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,8 @@ public:
|
||||||
mType = eSVG;
|
mType = eSVG;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual nsresult InsertChildBefore(nsIContent* aKid, nsIContent* aBeforeThis,
|
||||||
|
bool aNotify) override;
|
||||||
virtual nsresult InsertChildAt_Deprecated(nsIContent* aKid, uint32_t aIndex,
|
virtual nsresult InsertChildAt_Deprecated(nsIContent* aKid, uint32_t aIndex,
|
||||||
bool aNotify) override;
|
bool aNotify) override;
|
||||||
virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
|
virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
|
||||||
|
|
|
||||||
|
|
@ -81,6 +81,18 @@ NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGSwitchElement)
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
// nsINode methods
|
// nsINode methods
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
SVGSwitchElement::InsertChildBefore(nsIContent* aKid, nsIContent* aBeforeThis,
|
||||||
|
bool aNotify)
|
||||||
|
{
|
||||||
|
nsresult rv =
|
||||||
|
SVGSwitchElementBase::InsertChildBefore(aKid, aBeforeThis, aNotify);
|
||||||
|
if (NS_SUCCEEDED(rv)) {
|
||||||
|
MaybeInvalidate();
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
SVGSwitchElement::InsertChildAt_Deprecated(nsIContent* aKid,
|
SVGSwitchElement::InsertChildAt_Deprecated(nsIContent* aKid,
|
||||||
uint32_t aIndex,
|
uint32_t aIndex,
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,8 @@ public:
|
||||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(SVGSwitchElement,
|
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(SVGSwitchElement,
|
||||||
SVGSwitchElementBase)
|
SVGSwitchElementBase)
|
||||||
// nsINode
|
// nsINode
|
||||||
|
virtual nsresult InsertChildBefore(nsIContent* aKid, nsIContent* aBeforeThis,
|
||||||
|
bool aNotify) override;
|
||||||
virtual nsresult InsertChildAt_Deprecated(nsIContent* aKid, uint32_t aIndex,
|
virtual nsresult InsertChildAt_Deprecated(nsIContent* aKid, uint32_t aIndex,
|
||||||
bool aNotify) override;
|
bool aNotify) override;
|
||||||
virtual void RemoveChildAt_Deprecated(uint32_t aIndex, bool aNotify) override;
|
virtual void RemoveChildAt_Deprecated(uint32_t aIndex, bool aNotify) override;
|
||||||
|
|
|
||||||
|
|
@ -1364,6 +1364,7 @@ nsresult nsWebBrowserPersist::SaveURIInternal(
|
||||||
nsContentUtils::GetSystemPrincipal(),
|
nsContentUtils::GetSystemPrincipal(),
|
||||||
nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
|
nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
|
||||||
nsIContentPolicy::TYPE_OTHER,
|
nsIContentPolicy::TYPE_OTHER,
|
||||||
|
nullptr, // aPerformanceStorage
|
||||||
nullptr, // aLoadGroup
|
nullptr, // aLoadGroup
|
||||||
static_cast<nsIInterfaceRequestor*>(this),
|
static_cast<nsIInterfaceRequestor*>(this),
|
||||||
loadFlags);
|
loadFlags);
|
||||||
|
|
|
||||||
|
|
@ -98,6 +98,11 @@ interface Document : Node {
|
||||||
Attr createAttribute(DOMString name);
|
Attr createAttribute(DOMString name);
|
||||||
[NewObject, Throws]
|
[NewObject, Throws]
|
||||||
Attr createAttributeNS(DOMString? namespace, DOMString name);
|
Attr createAttributeNS(DOMString? namespace, DOMString name);
|
||||||
|
|
||||||
|
// Allows setting innerHTML without automatic sanitization.
|
||||||
|
// Do not use this.
|
||||||
|
[ChromeOnly]
|
||||||
|
attribute boolean allowUnsafeHTML;
|
||||||
};
|
};
|
||||||
|
|
||||||
// http://www.whatwg.org/specs/web-apps/current-work/#the-document-object
|
// http://www.whatwg.org/specs/web-apps/current-work/#the-document-object
|
||||||
|
|
|
||||||
|
|
@ -236,6 +236,16 @@ partial interface Element {
|
||||||
attribute DOMString outerHTML;
|
attribute DOMString outerHTML;
|
||||||
[CEReactions, Throws]
|
[CEReactions, Throws]
|
||||||
void insertAdjacentHTML(DOMString position, DOMString text);
|
void insertAdjacentHTML(DOMString position, DOMString text);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Like the innerHTML setter, but does not sanitize its values, even in
|
||||||
|
* chrome-privileged documents.
|
||||||
|
*
|
||||||
|
* If you're thinking about using this, don't. You have many, much better
|
||||||
|
* options.
|
||||||
|
*/
|
||||||
|
[ChromeOnly, Throws]
|
||||||
|
void unsafeSetInnerHTML(DOMString html);
|
||||||
};
|
};
|
||||||
|
|
||||||
// http://www.w3.org/TR/selectors-api/#interface-definitions
|
// http://www.w3.org/TR/selectors-api/#interface-definitions
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ partial interface Performance {
|
||||||
};
|
};
|
||||||
|
|
||||||
// http://www.w3.org/TR/resource-timing/#extensions-performance-interface
|
// http://www.w3.org/TR/resource-timing/#extensions-performance-interface
|
||||||
[Exposed=Window]
|
[Exposed=(Window,Worker)]
|
||||||
partial interface Performance {
|
partial interface Performance {
|
||||||
void clearResourceTimings();
|
void clearResourceTimings();
|
||||||
void setResourceTimingBufferSize(unsigned long maxSize);
|
void setResourceTimingBufferSize(unsigned long maxSize);
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
* liability, trademark and document use rules apply.
|
* liability, trademark and document use rules apply.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
[Exposed=(Window,Worker)]
|
||||||
interface PerformanceResourceTiming : PerformanceEntry
|
interface PerformanceResourceTiming : PerformanceEntry
|
||||||
{
|
{
|
||||||
readonly attribute DOMString initiatorType;
|
readonly attribute DOMString initiatorType;
|
||||||
|
|
|
||||||
|
|
@ -57,6 +57,7 @@
|
||||||
#include "mozilla/dom/InternalResponse.h"
|
#include "mozilla/dom/InternalResponse.h"
|
||||||
#include "mozilla/dom/nsCSPService.h"
|
#include "mozilla/dom/nsCSPService.h"
|
||||||
#include "mozilla/dom/nsCSPUtils.h"
|
#include "mozilla/dom/nsCSPUtils.h"
|
||||||
|
#include "mozilla/dom/PerformanceStorage.h"
|
||||||
#include "mozilla/dom/Promise.h"
|
#include "mozilla/dom/Promise.h"
|
||||||
#include "mozilla/dom/PromiseNativeHandler.h"
|
#include "mozilla/dom/PromiseNativeHandler.h"
|
||||||
#include "mozilla/dom/Response.h"
|
#include "mozilla/dom/Response.h"
|
||||||
|
|
@ -110,6 +111,7 @@ nsresult
|
||||||
ChannelFromScriptURL(nsIPrincipal* principal,
|
ChannelFromScriptURL(nsIPrincipal* principal,
|
||||||
nsIURI* baseURI,
|
nsIURI* baseURI,
|
||||||
nsIDocument* parentDoc,
|
nsIDocument* parentDoc,
|
||||||
|
WorkerPrivate* aWorkerPrivate,
|
||||||
nsILoadGroup* loadGroup,
|
nsILoadGroup* loadGroup,
|
||||||
nsIIOService* ios,
|
nsIIOService* ios,
|
||||||
nsIScriptSecurityManager* secMan,
|
nsIScriptSecurityManager* secMan,
|
||||||
|
|
@ -190,6 +192,7 @@ ChannelFromScriptURL(nsIPrincipal* principal,
|
||||||
parentDoc,
|
parentDoc,
|
||||||
secFlags,
|
secFlags,
|
||||||
contentPolicyType,
|
contentPolicyType,
|
||||||
|
nullptr, // aPerformanceStorage
|
||||||
loadGroup,
|
loadGroup,
|
||||||
nullptr, // aCallbacks
|
nullptr, // aCallbacks
|
||||||
aLoadFlags,
|
aLoadFlags,
|
||||||
|
|
@ -200,6 +203,11 @@ ChannelFromScriptURL(nsIPrincipal* principal,
|
||||||
MOZ_ASSERT(loadGroup);
|
MOZ_ASSERT(loadGroup);
|
||||||
MOZ_ASSERT(NS_LoadGroupMatchesPrincipal(loadGroup, principal));
|
MOZ_ASSERT(NS_LoadGroupMatchesPrincipal(loadGroup, principal));
|
||||||
|
|
||||||
|
RefPtr<PerformanceStorage> performanceStorage;
|
||||||
|
if (aWorkerPrivate && !aIsMainScript) {
|
||||||
|
performanceStorage = aWorkerPrivate->GetPerformanceStorage();
|
||||||
|
}
|
||||||
|
|
||||||
if (aClientInfo.isSome()) {
|
if (aClientInfo.isSome()) {
|
||||||
rv = NS_NewChannel(getter_AddRefs(channel),
|
rv = NS_NewChannel(getter_AddRefs(channel),
|
||||||
uri,
|
uri,
|
||||||
|
|
@ -208,6 +216,7 @@ ChannelFromScriptURL(nsIPrincipal* principal,
|
||||||
aController,
|
aController,
|
||||||
secFlags,
|
secFlags,
|
||||||
contentPolicyType,
|
contentPolicyType,
|
||||||
|
performanceStorage,
|
||||||
loadGroup,
|
loadGroup,
|
||||||
nullptr, // aCallbacks
|
nullptr, // aCallbacks
|
||||||
aLoadFlags,
|
aLoadFlags,
|
||||||
|
|
@ -218,6 +227,7 @@ ChannelFromScriptURL(nsIPrincipal* principal,
|
||||||
principal,
|
principal,
|
||||||
secFlags,
|
secFlags,
|
||||||
contentPolicyType,
|
contentPolicyType,
|
||||||
|
performanceStorage,
|
||||||
loadGroup,
|
loadGroup,
|
||||||
nullptr, // aCallbacks
|
nullptr, // aCallbacks
|
||||||
aLoadFlags,
|
aLoadFlags,
|
||||||
|
|
@ -991,7 +1001,8 @@ private:
|
||||||
// Only top level workers' main script use the document charset for the
|
// Only top level workers' main script use the document charset for the
|
||||||
// script uri encoding. Otherwise, default encoding (UTF-8) is applied.
|
// script uri encoding. Otherwise, default encoding (UTF-8) is applied.
|
||||||
bool useDefaultEncoding = !(!parentWorker && IsMainWorkerScript());
|
bool useDefaultEncoding = !(!parentWorker && IsMainWorkerScript());
|
||||||
rv = ChannelFromScriptURL(principal, baseURI, parentDoc, loadGroup, ios,
|
rv = ChannelFromScriptURL(principal, baseURI, parentDoc, mWorkerPrivate,
|
||||||
|
loadGroup, ios,
|
||||||
secMan, loadInfo.mURL,
|
secMan, loadInfo.mURL,
|
||||||
mClientInfo, mController,
|
mClientInfo, mController,
|
||||||
IsMainWorkerScript(),
|
IsMainWorkerScript(),
|
||||||
|
|
@ -2266,8 +2277,8 @@ ChannelFromScriptURLMainThread(nsIPrincipal* aPrincipal,
|
||||||
nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager();
|
nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager();
|
||||||
NS_ASSERTION(secMan, "This should never be null!");
|
NS_ASSERTION(secMan, "This should never be null!");
|
||||||
|
|
||||||
return ChannelFromScriptURL(aPrincipal, aBaseURI, aParentDoc, aLoadGroup,
|
return ChannelFromScriptURL(aPrincipal, aBaseURI, aParentDoc, nullptr,
|
||||||
ios, secMan, aScriptURL, aClientInfo,
|
aLoadGroup, ios, secMan, aScriptURL, aClientInfo,
|
||||||
Maybe<ServiceWorkerDescriptor>(),
|
Maybe<ServiceWorkerDescriptor>(),
|
||||||
true, WorkerScript, aMainScriptContentPolicyType,
|
true, WorkerScript, aMainScriptContentPolicyType,
|
||||||
nsIRequest::LOAD_NORMAL, aDefaultURIEncoding,
|
nsIRequest::LOAD_NORMAL, aDefaultURIEncoding,
|
||||||
|
|
|
||||||
|
|
@ -730,7 +730,10 @@ CompareNetwork::Initialize(nsIPrincipal* aPrincipal,
|
||||||
// use the TYPE_INTERNAL_SCRIPT content policy types when loading a service
|
// use the TYPE_INTERNAL_SCRIPT content policy types when loading a service
|
||||||
// worker.
|
// worker.
|
||||||
rv = NS_NewChannel(getter_AddRefs(mChannel), uri, aPrincipal, secFlags,
|
rv = NS_NewChannel(getter_AddRefs(mChannel), uri, aPrincipal, secFlags,
|
||||||
contentPolicyType, loadGroup, nullptr /* aCallbacks */,
|
contentPolicyType,
|
||||||
|
nullptr, /* aPerformanceStorage */
|
||||||
|
loadGroup,
|
||||||
|
nullptr /* aCallbacks */,
|
||||||
mLoadFlags);
|
mLoadFlags);
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
return rv;
|
return rv;
|
||||||
|
|
|
||||||
|
|
@ -64,6 +64,7 @@
|
||||||
#include "mozilla/dom/MessagePortBinding.h"
|
#include "mozilla/dom/MessagePortBinding.h"
|
||||||
#include "mozilla/dom/nsCSPUtils.h"
|
#include "mozilla/dom/nsCSPUtils.h"
|
||||||
#include "mozilla/dom/Performance.h"
|
#include "mozilla/dom/Performance.h"
|
||||||
|
#include "mozilla/dom/PerformanceStorageWorker.h"
|
||||||
#include "mozilla/dom/PMessagePort.h"
|
#include "mozilla/dom/PMessagePort.h"
|
||||||
#include "mozilla/dom/Promise.h"
|
#include "mozilla/dom/Promise.h"
|
||||||
#include "mozilla/dom/PromiseDebugging.h"
|
#include "mozilla/dom/PromiseDebugging.h"
|
||||||
|
|
@ -1918,6 +1919,19 @@ WorkerLoadInfo::GetPrincipalAndLoadGroupFromChannel(nsIChannel* aChannel,
|
||||||
nsresult rv = ssm->GetChannelResultPrincipal(aChannel, getter_AddRefs(channelPrincipal));
|
nsresult rv = ssm->GetChannelResultPrincipal(aChannel, getter_AddRefs(channelPrincipal));
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
// Every time we call GetChannelResultPrincipal() it will return a different
|
||||||
|
// null principal for a data URL. We don't want to change the worker's
|
||||||
|
// principal again, though. Instead just keep the original null principal we
|
||||||
|
// first got from the channel.
|
||||||
|
//
|
||||||
|
// Note, we don't do this by setting principalToInherit on the channel's
|
||||||
|
// load info because we don't yet have the first null principal when we
|
||||||
|
// create the channel.
|
||||||
|
if (mPrincipal && mPrincipal->GetIsNullPrincipal() &&
|
||||||
|
channelPrincipal->GetIsNullPrincipal()) {
|
||||||
|
channelPrincipal = mPrincipal;
|
||||||
|
}
|
||||||
|
|
||||||
nsCOMPtr<nsILoadGroup> channelLoadGroup;
|
nsCOMPtr<nsILoadGroup> channelLoadGroup;
|
||||||
rv = aChannel->GetLoadGroup(getter_AddRefs(channelLoadGroup));
|
rv = aChannel->GetLoadGroup(getter_AddRefs(channelLoadGroup));
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
@ -7199,6 +7213,18 @@ WorkerPrivate::DumpCrashInformation(nsACString& aString)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PerformanceStorage*
|
||||||
|
WorkerPrivate::GetPerformanceStorage()
|
||||||
|
{
|
||||||
|
AssertIsOnMainThread();
|
||||||
|
|
||||||
|
if (!mPerformanceStorage) {
|
||||||
|
mPerformanceStorage = PerformanceStorageWorker::Create(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
return mPerformanceStorage;
|
||||||
|
}
|
||||||
|
|
||||||
NS_IMPL_ISUPPORTS_INHERITED0(ExternalRunnableWrapper, WorkerRunnable)
|
NS_IMPL_ISUPPORTS_INHERITED0(ExternalRunnableWrapper, WorkerRunnable)
|
||||||
|
|
||||||
template <class Derived>
|
template <class Derived>
|
||||||
|
|
|
||||||
|
|
@ -68,6 +68,7 @@ class ClientSource;
|
||||||
class Function;
|
class Function;
|
||||||
class MessagePort;
|
class MessagePort;
|
||||||
class MessagePortIdentifier;
|
class MessagePortIdentifier;
|
||||||
|
class PerformanceStorage;
|
||||||
class PromiseNativeHandler;
|
class PromiseNativeHandler;
|
||||||
class StructuredCloneHolder;
|
class StructuredCloneHolder;
|
||||||
class WorkerDebuggerGlobalScope;
|
class WorkerDebuggerGlobalScope;
|
||||||
|
|
@ -1067,6 +1068,8 @@ class WorkerPrivate : public WorkerPrivateParent<WorkerPrivate>
|
||||||
// fired on the main thread if the worker script fails to load
|
// fired on the main thread if the worker script fails to load
|
||||||
nsCOMPtr<nsIRunnable> mLoadFailedRunnable;
|
nsCOMPtr<nsIRunnable> mLoadFailedRunnable;
|
||||||
|
|
||||||
|
RefPtr<PerformanceStorage> mPerformanceStorage;
|
||||||
|
|
||||||
JS::UniqueChars mDefaultLocale; // nulled during worker JSContext init
|
JS::UniqueChars mDefaultLocale; // nulled during worker JSContext init
|
||||||
TimeStamp mKillTime;
|
TimeStamp mKillTime;
|
||||||
uint32_t mErrorHandlerRecursionCount;
|
uint32_t mErrorHandlerRecursionCount;
|
||||||
|
|
@ -1512,6 +1515,9 @@ public:
|
||||||
void
|
void
|
||||||
ExecutionReady();
|
ExecutionReady();
|
||||||
|
|
||||||
|
PerformanceStorage*
|
||||||
|
GetPerformanceStorage();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
WorkerPrivate(WorkerPrivate* aParent,
|
WorkerPrivate(WorkerPrivate* aParent,
|
||||||
const nsAString& aScriptURL, bool aIsChromeWorker,
|
const nsAString& aScriptURL, bool aIsChromeWorker,
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue