зеркало из https://github.com/mozilla/gecko-dev.git
Merge autoland to m-c. a=merge
This commit is contained in:
Коммит
4ed4898e21
|
@ -15,8 +15,10 @@ async function calcMaximumAvailSize(aChromeWidth, aChromeHeight) {
|
|||
|
||||
// If the chrome UI dimensions is not given, we will calculate it.
|
||||
if (!aChromeWidth || !aChromeHeight) {
|
||||
let win = await BrowserTestUtils.openNewBrowserWindow();
|
||||
|
||||
let tab = await BrowserTestUtils.openNewForegroundTab(
|
||||
gBrowser, testPath + "file_dummy.html");
|
||||
win.gBrowser, testPath + "file_dummy.html");
|
||||
|
||||
let contentSize = await ContentTask.spawn(tab.linkedBrowser, null, async function() {
|
||||
let result = {
|
||||
|
@ -29,10 +31,11 @@ async function calcMaximumAvailSize(aChromeWidth, aChromeHeight) {
|
|||
|
||||
// Calculate the maximum available window size which is depending on the
|
||||
// available screen space.
|
||||
chromeUIWidth = window.outerWidth - contentSize.width;
|
||||
chromeUIHeight = window.outerHeight - contentSize.height;
|
||||
chromeUIWidth = win.outerWidth - contentSize.width;
|
||||
chromeUIHeight = win.outerHeight - contentSize.height;
|
||||
|
||||
await BrowserTestUtils.removeTab(tab);
|
||||
await BrowserTestUtils.closeWindow(win);
|
||||
} else {
|
||||
chromeUIWidth = aChromeWidth;
|
||||
chromeUIHeight = aChromeHeight;
|
||||
|
|
|
@ -41,6 +41,16 @@ add_UITour_task(async function test_block_target() {
|
|||
async function checkToggleTarget(targetID) {
|
||||
let popup = document.getElementById("UITourTooltip");
|
||||
|
||||
let trackerOpened = new Promise(function(resolve, reject) {
|
||||
Services.obs.addObserver(function onopen(subject) {
|
||||
let asciiSpec = subject.QueryInterface(Ci.nsIHttpChannel).URI.asciiSpec;
|
||||
if (asciiSpec === "https://tracking.example.com/") {
|
||||
Services.obs.removeObserver(onopen, "http-on-opening-request");
|
||||
resolve();
|
||||
}
|
||||
}, "http-on-opening-request");
|
||||
});
|
||||
|
||||
await ContentTask.spawn(gBrowser.selectedBrowser, {}, function() {
|
||||
let doc = content.document;
|
||||
let iframe = doc.createElement("iframe");
|
||||
|
@ -49,6 +59,8 @@ async function checkToggleTarget(targetID) {
|
|||
doc.body.insertBefore(iframe, doc.body.firstChild);
|
||||
});
|
||||
|
||||
await trackerOpened;
|
||||
|
||||
let testTargetAvailability = async function(expectedAvailable) {
|
||||
let data = await getConfigurationPromise("availableTargets");
|
||||
let available = (data.targets.indexOf(targetID) != -1);
|
||||
|
|
|
@ -8,4 +8,6 @@ DIRS += ['communicator']
|
|||
|
||||
JAR_MANIFESTS += ['jar.mn']
|
||||
|
||||
DEFINES['MENUBAR_CAN_AUTOHIDE'] = 1
|
||||
|
||||
include('../tab-svgs.mozbuild')
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
|
||||
%include shared.inc
|
||||
%define toolbarButtonPressed :hover:active:not([disabled="true"]):not([cui-areatype="menu-panel"])
|
||||
%define windowButtonMarginTop 11px
|
||||
|
||||
@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
|
||||
@namespace html url("http://www.w3.org/1999/xhtml");
|
||||
|
@ -15,7 +14,6 @@
|
|||
%include ../shared/browser.inc.css
|
||||
|
||||
:root {
|
||||
--space-above-tabbar: 9px;
|
||||
--tabs-toolbar-color: #333;
|
||||
|
||||
--toolbarbutton-vertical-text-padding: calc(var(--toolbarbutton-inner-padding) + 1px);
|
||||
|
@ -23,6 +21,8 @@
|
|||
%ifdef MOZ_PHOTON_THEME
|
||||
--toolbarbutton-border-radius: 4px;
|
||||
%else
|
||||
--space-above-tabbar: 9px;
|
||||
|
||||
--toolbarbutton-border-radius: 3px;
|
||||
|
||||
--toolbarbutton-hover-background: hsla(0,0%,100%,.1) linear-gradient(hsla(0,0%,100%,.3), hsla(0,0%,100%,.1)) padding-box;
|
||||
|
@ -134,7 +134,11 @@ toolbar:-moz-lwtheme {
|
|||
* tabstrip can overlap it.
|
||||
*/
|
||||
#main-window[tabsintitlebar] > #titlebar {
|
||||
%ifndef MOZ_PHOTON_THEME
|
||||
min-height: calc(var(--tab-min-height) + var(--space-above-tabbar) - var(--tab-toolbar-navbar-overlap));
|
||||
%else
|
||||
min-height: calc(var(--tab-min-height) - var(--tab-toolbar-navbar-overlap));
|
||||
%endif
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -146,7 +150,11 @@ toolbar:-moz-lwtheme {
|
|||
|
||||
#main-window[tabsintitlebar] > #titlebar > #titlebar-content > #titlebar-buttonbox-container,
|
||||
#main-window[tabsintitlebar] > #titlebar > #titlebar-content > #titlebar-secondary-buttonbox > #titlebar-fullscreen-button {
|
||||
margin-top: @windowButtonMarginTop@;
|
||||
%ifdef MOZ_PHOTON_THEME
|
||||
margin-top: 6px;
|
||||
%else
|
||||
margin-top: 11px;
|
||||
%endif
|
||||
}
|
||||
|
||||
#main-window:not([tabsintitlebar]) > #titlebar > #titlebar-content > #titlebar-buttonbox-container,
|
||||
|
@ -1535,10 +1543,11 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker {
|
|||
text-shadow: @loweredShadow@;
|
||||
}
|
||||
|
||||
%ifndef MOZ_PHOTON_THEME
|
||||
#navigator-toolbox[inFullscreen] > #TabsToolbar {
|
||||
padding-top: var(--space-above-tabbar);
|
||||
}
|
||||
|
||||
%endif
|
||||
#tabbrowser-tabs {
|
||||
-moz-box-align: stretch;
|
||||
}
|
||||
|
@ -2210,7 +2219,9 @@ html|*.addon-webext-perm-list {
|
|||
}
|
||||
|
||||
#TabsToolbar > .private-browsing-indicator {
|
||||
%ifndef MOZ_PHOTON_THEME
|
||||
transform: translateY(calc(-1 * var(--space-above-tabbar)));
|
||||
%endif
|
||||
/* We offset by 38px for mask graphic, plus 4px to account for the
|
||||
* margin-left, which sums to 42px.
|
||||
*/
|
||||
|
|
|
@ -28,12 +28,13 @@
|
|||
background: var(--chrome-background-color);
|
||||
}
|
||||
|
||||
%ifndef MOZ_PHOTON_THEME
|
||||
/* Resize things so that the native titlebar is in line with the tabs */
|
||||
#main-window[tabsintitlebar] > #titlebar > #titlebar-content > #titlebar-buttonbox-container,
|
||||
#main-window[tabsintitlebar] > #titlebar > #titlebar-content > #titlebar-secondary-buttonbox > #titlebar-fullscreen-button {
|
||||
margin-top: 6px;
|
||||
}
|
||||
|
||||
%endif
|
||||
/* Prevent the hover styling from on the identity icon from overlapping the
|
||||
urlbar border. */
|
||||
#identity-box {
|
||||
|
|
|
@ -3,6 +3,19 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
%ifdef MOZ_PHOTON_THEME
|
||||
%ifdef CAN_DRAW_IN_TITLEBAR
|
||||
/* Add space for dragging the window */
|
||||
%ifdef MENUBAR_CAN_AUTOHIDE
|
||||
:root[tabsintitlebar] #toolbar-menubar[autohide=true] ~ #TabsToolbar {
|
||||
padding-inline-start: 40px;
|
||||
}
|
||||
%else
|
||||
:root[tabsintitlebar] #TabsToolbar {
|
||||
padding-inline-start: 40px;
|
||||
}
|
||||
%endif
|
||||
%endif
|
||||
|
||||
/* Go button */
|
||||
.urlbar-go-button {
|
||||
padding: 0 3px;
|
||||
|
|
|
@ -9,7 +9,9 @@
|
|||
:root {
|
||||
--tab-toolbar-navbar-overlap: 0px;
|
||||
--navbar-tab-toolbar-highlight-overlap: 0px;
|
||||
%ifndef MOZ_PHOTON_THEME
|
||||
--space-above-tabbar: 0px;
|
||||
%endif
|
||||
--toolbarbutton-text-shadow: none;
|
||||
--backbutton-urlbar-overlap: 0px;
|
||||
/* 18px icon + 2 * 5px padding + 1 * 1px border */
|
||||
|
@ -98,12 +100,13 @@ toolbar:-moz-lwtheme-darktext {
|
|||
--toolbarbutton-checkedhover-backgroundcolor: #d7d7d8;
|
||||
}
|
||||
|
||||
%ifndef MOZ_PHOTON_THEME
|
||||
/* Give some space to drag the window around while customizing
|
||||
(normal space to left and right of tabs doesn't work in this case) */
|
||||
#main-window[tabsintitlebar][customizing] {
|
||||
--space-above-tabbar: 9px;
|
||||
}
|
||||
|
||||
%endif
|
||||
/* Override @tabCurveHalfWidth@ and @tabCurveWidth@. XXX: Switch to a CSS variable once the perf is sorted out - bug 1088771 */
|
||||
.tab-background-middle {
|
||||
border-left-width: 0;
|
||||
|
|
|
@ -338,11 +338,12 @@
|
|||
}
|
||||
}
|
||||
|
||||
%ifndef MOZ_PHOTON_THEME
|
||||
#main-window[sizemode=normal] #TabsToolbar {
|
||||
padding-left: 1px;
|
||||
padding-right: 1px;
|
||||
}
|
||||
|
||||
%endif
|
||||
#appcontent:not(:-moz-lwtheme) {
|
||||
background-color: -moz-dialog;
|
||||
}
|
||||
|
|
|
@ -17,13 +17,13 @@
|
|||
:root {
|
||||
--titlebar-text-color: inherit;
|
||||
|
||||
--space-above-tabbar: 15px;
|
||||
|
||||
--toolbarbutton-vertical-text-padding: calc(var(--toolbarbutton-inner-padding) - 1px);
|
||||
|
||||
%ifdef MOZ_PHOTON_THEME
|
||||
--toolbarbutton-border-radius: 2px;
|
||||
%else
|
||||
--space-above-tabbar: 15px;
|
||||
|
||||
--toolbarbutton-border-radius: 1px;
|
||||
|
||||
--toolbarbutton-hover-background: rgba(0,0,0,.1);
|
||||
|
@ -89,6 +89,7 @@ toolbar[brighttext] {
|
|||
display: none;
|
||||
}
|
||||
|
||||
%ifndef MOZ_PHOTON_THEME
|
||||
/* We want a 4px gap between the TabsToolbar and the toolbar-menubar when the
|
||||
toolbar-menu is displayed, and a 16px gap when it is not. 1px is taken care
|
||||
of by the (light) outer shadow of the tab, the remaining 3/15 are these margins. */
|
||||
|
@ -101,7 +102,7 @@ toolbar[brighttext] {
|
|||
#main-window[tabsintitlebar][sizemode="normal"]:not([inFullscreen]) #toolbar-menubar[autohide="true"][inactive] ~ #TabsToolbar {
|
||||
margin-top: var(--space-above-tabbar);
|
||||
}
|
||||
|
||||
%endif
|
||||
#navigator-toolbox,
|
||||
#navigator-toolbox > toolbar {
|
||||
-moz-appearance: none;
|
||||
|
|
|
@ -72,10 +72,11 @@
|
|||
|
||||
@media (-moz-os-version: windows-win7),
|
||||
(-moz-os-version: windows-win8) {
|
||||
%ifndef MOZ_PHOTON_THEME
|
||||
:root {
|
||||
--space-above-tabbar: 15px;
|
||||
}
|
||||
|
||||
%endif
|
||||
/* It'd be nice if there was an element in the scrollbox's inner content
|
||||
that collapsed to the current width of the tabs. Since there isn't we
|
||||
need to handle overflowing and non-overflowing tabs separately.
|
||||
|
|
|
@ -9,5 +9,6 @@ DIRS += ['communicator']
|
|||
JAR_MANIFESTS += ['jar.mn']
|
||||
|
||||
DEFINES['CAN_DRAW_IN_TITLEBAR'] = 1
|
||||
DEFINES['MENUBAR_CAN_AUTOHIDE'] = 1
|
||||
|
||||
include('../tab-svgs.mozbuild')
|
||||
|
|
|
@ -857,6 +857,9 @@ var gDevToolsBrowser = exports.gDevToolsBrowser = {
|
|||
gDevToolsBrowser._forgetBrowserWindow(win);
|
||||
}
|
||||
|
||||
// Remove scripts loaded in content process to support the Browser Content Toolbox.
|
||||
DebuggerServer.removeContentServerScript();
|
||||
|
||||
gDevTools.destroy({ shuttingDown });
|
||||
},
|
||||
};
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
/* 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/. */
|
||||
|
||||
/* global addMessageListener, removeMessageListener */
|
||||
|
||||
"use strict";
|
||||
|
||||
const { utils: Cu } = Components;
|
||||
const { Services } = Cu.import("resource://gre/modules/Services.jsm", {});
|
||||
|
||||
function onInit(message) {
|
||||
// Only reply if we are in a real content process
|
||||
if (Services.appinfo.processType == Services.appinfo.PROCESS_TYPE_CONTENT) {
|
||||
let {init} = Cu.import("resource://devtools/server/content-server.jsm", {});
|
||||
init(message);
|
||||
}
|
||||
}
|
||||
|
||||
function onClose() {
|
||||
removeMessageListener("debug:init-content-server", onInit);
|
||||
removeMessageListener("debug:close-content-server", onClose);
|
||||
}
|
||||
|
||||
addMessageListener("debug:init-content-server", onInit);
|
||||
addMessageListener("debug:close-content-server", onClose);
|
|
@ -69,6 +69,9 @@ if (isWorker) {
|
|||
Services.prefs.getBoolPref(VERBOSE_PREF);
|
||||
}
|
||||
|
||||
const CONTENT_PROCESS_DBG_SERVER_SCRIPT =
|
||||
"resource://devtools/server/content-process-debugger-server.js";
|
||||
|
||||
function loadSubScript(url) {
|
||||
try {
|
||||
let loader = Cc["@mozilla.org/moz/jssubscript-loader;1"]
|
||||
|
@ -149,6 +152,8 @@ function ModuleAPI() {
|
|||
var DebuggerServer = {
|
||||
_listeners: [],
|
||||
_initialized: false,
|
||||
// Flag to check if the content process debugger server script was already loaded.
|
||||
_contentProcessScriptLoaded: false,
|
||||
// Map of global actor names to actor constructors provided by extensions.
|
||||
globalActorFactories: {},
|
||||
// Map of tab actor names to actor constructors provided by extensions.
|
||||
|
@ -755,7 +760,16 @@ var DebuggerServer = {
|
|||
deferred.resolve(actor);
|
||||
});
|
||||
|
||||
mm.sendAsyncMessage("DevTools:InitDebuggerServer", {
|
||||
// Load the content process debugger server script only once.
|
||||
if (!this._contentProcessScriptLoaded) {
|
||||
// Load the process script that will receive the debug:init-content-server message
|
||||
Services.ppmm.loadProcessScript(CONTENT_PROCESS_DBG_SERVER_SCRIPT, true);
|
||||
this._contentProcessScriptLoaded = true;
|
||||
}
|
||||
|
||||
// Send a message to the content process debugger server script to forward it the
|
||||
// prefix.
|
||||
mm.sendAsyncMessage("debug:init-content-server", {
|
||||
prefix: prefix
|
||||
});
|
||||
|
||||
|
@ -1368,6 +1382,20 @@ var DebuggerServer = {
|
|||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Called when DevTools are unloaded to remove the contend process server script for the
|
||||
* list of scripts loaded for each new content process. Will also remove message
|
||||
* listeners from already loaded scripts.
|
||||
*/
|
||||
removeContentServerScript() {
|
||||
Services.ppmm.removeDelayedProcessScript(CONTENT_PROCESS_DBG_SERVER_SCRIPT);
|
||||
try {
|
||||
Services.ppmm.broadcastAsyncMessage("debug:close-content-server");
|
||||
} catch (e) {
|
||||
// Nothing to do
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* ⚠ TESTING ONLY! ⚠ Searches all active connections for an actor matching an ID.
|
||||
* This is helpful for some tests which depend on reaching into the server to check some
|
||||
|
|
|
@ -18,6 +18,7 @@ XPCSHELL_TESTS_MANIFESTS += ['tests/unit/xpcshell.ini']
|
|||
|
||||
DevToolsModules(
|
||||
'child.js',
|
||||
'content-process-debugger-server.js',
|
||||
'content-server.jsm',
|
||||
'css-logic.js',
|
||||
'event-parsers.js',
|
||||
|
|
|
@ -34,6 +34,11 @@ H264Converter::H264Converter(PlatformDecoderModule* aPDM,
|
|||
, mDecoderOptions(aParams.mOptions)
|
||||
{
|
||||
CreateDecoder(mOriginalConfig, aParams.mDiagnostics);
|
||||
if (mDecoder) {
|
||||
MOZ_ASSERT(mp4_demuxer::AnnexB::HasSPS(mOriginalConfig.mExtraData));
|
||||
// The video metadata contains out of band SPS/PPS (AVC1) store it.
|
||||
mOriginalExtraData = mOriginalConfig.mExtraData;
|
||||
}
|
||||
}
|
||||
|
||||
H264Converter::~H264Converter()
|
||||
|
@ -79,6 +84,15 @@ H264Converter::Decode(MediaRawData* aSample)
|
|||
return DecodePromise::CreateAndResolve(DecodedData(), __func__);
|
||||
}
|
||||
} else {
|
||||
// Initialize the members that we couldn't if the extradata was given during
|
||||
// H264Converter's construction.
|
||||
if (!mNeedAVCC) {
|
||||
mNeedAVCC =
|
||||
Some(mDecoder->NeedsConversion() == ConversionRequired::kNeedAVCC);
|
||||
}
|
||||
if (!mCanRecycleDecoder) {
|
||||
mCanRecycleDecoder = Some(CanRecycleDecoder());
|
||||
}
|
||||
rv = CheckForSPSChange(aSample);
|
||||
}
|
||||
|
||||
|
@ -99,11 +113,6 @@ H264Converter::Decode(MediaRawData* aSample)
|
|||
return DecodePromise::CreateAndResolve(DecodedData(), __func__);
|
||||
}
|
||||
|
||||
if (!mNeedAVCC) {
|
||||
mNeedAVCC =
|
||||
Some(mDecoder->NeedsConversion() == ConversionRequired::kNeedAVCC);
|
||||
}
|
||||
|
||||
if (!*mNeedAVCC
|
||||
&& !mp4_demuxer::AnnexB::ConvertSampleToAnnexB(aSample, mNeedKeyframe)) {
|
||||
return DecodePromise::CreateAndReject(
|
||||
|
@ -260,6 +269,11 @@ H264Converter::OnDecoderInitDone(const TrackType aTrackType)
|
|||
{
|
||||
mInitPromiseRequest.Complete();
|
||||
RefPtr<MediaRawData> sample = mPendingSample.forget();
|
||||
|
||||
mNeedAVCC =
|
||||
Some(mDecoder->NeedsConversion() == ConversionRequired::kNeedAVCC);
|
||||
mCanRecycleDecoder = Some(CanRecycleDecoder());
|
||||
|
||||
DecodeFirstSample(sample);
|
||||
}
|
||||
|
||||
|
@ -289,9 +303,6 @@ H264Converter::DecodeFirstSample(MediaRawData* aSample)
|
|||
return;
|
||||
}
|
||||
|
||||
mNeedAVCC =
|
||||
Some(mDecoder->NeedsConversion() == ConversionRequired::kNeedAVCC);
|
||||
|
||||
if (!*mNeedAVCC
|
||||
&& !mp4_demuxer::AnnexB::ConvertSampleToAnnexB(aSample, mNeedKeyframe)) {
|
||||
mDecodePromise.Reject(
|
||||
|
@ -322,15 +333,30 @@ H264Converter::CheckForSPSChange(MediaRawData* aSample)
|
|||
{
|
||||
RefPtr<MediaByteBuffer> extra_data =
|
||||
mp4_demuxer::AnnexB::ExtractExtraData(aSample);
|
||||
if (!mp4_demuxer::AnnexB::HasSPS(extra_data)
|
||||
|| mp4_demuxer::AnnexB::CompareExtraData(extra_data,
|
||||
mCurrentConfig.mExtraData)) {
|
||||
return NS_OK;
|
||||
}
|
||||
if (!mp4_demuxer::AnnexB::HasSPS(extra_data)) {
|
||||
MOZ_ASSERT(mCanRecycleDecoder.isSome());
|
||||
if (!*mCanRecycleDecoder) {
|
||||
// If the decoder can't be recycled, the out of band extradata will never
|
||||
// change as the H264Converter will be recreated by the MediaFormatReader
|
||||
// instead. So there's no point in testing for changes.
|
||||
return NS_OK;
|
||||
}
|
||||
// This sample doesn't contain inband SPS/PPS
|
||||
// We now check if the out of band one has changed.
|
||||
if (mp4_demuxer::AnnexB::HasSPS(aSample->mExtraData) &&
|
||||
!mp4_demuxer::AnnexB::CompareExtraData(aSample->mExtraData,
|
||||
mOriginalExtraData)) {
|
||||
extra_data = mOriginalExtraData = aSample->mExtraData;
|
||||
}
|
||||
}
|
||||
if (mp4_demuxer::AnnexB::CompareExtraData(extra_data,
|
||||
mCurrentConfig.mExtraData)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
RefPtr<MediaRawData> sample = aSample;
|
||||
|
||||
if (CanRecycleDecoder()) {
|
||||
MOZ_ASSERT(mCanRecycleDecoder.isSome());
|
||||
if (*mCanRecycleDecoder) {
|
||||
// Do not recreate the decoder, reuse it.
|
||||
UpdateConfigFromExtraData(extra_data);
|
||||
if (!sample->mTrackInfo) {
|
||||
|
|
|
@ -81,6 +81,8 @@ private:
|
|||
RefPtr<PlatformDecoderModule> mPDM;
|
||||
const VideoInfo mOriginalConfig;
|
||||
VideoInfo mCurrentConfig;
|
||||
// Current out of band extra data (as found in metadata's VideoInfo).
|
||||
RefPtr<MediaByteBuffer> mOriginalExtraData;
|
||||
RefPtr<layers::KnowsCompositor> mKnowsCompositor;
|
||||
RefPtr<layers::ImageContainer> mImageContainer;
|
||||
const RefPtr<TaskQueue> mTaskQueue;
|
||||
|
@ -100,6 +102,7 @@ private:
|
|||
const TrackInfo::TrackType mType;
|
||||
MediaEventProducer<TrackInfo::TrackType>* const mOnWaitingForKeyEvent;
|
||||
const CreateDecoderParams::OptionSet mDecoderOptions;
|
||||
Maybe<bool> mCanRecycleDecoder;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include "mozilla/ipc/PChildToParentStreamChild.h"
|
||||
#include "mozilla/ipc/PParentToChildStreamChild.h"
|
||||
#include "mozilla/layout/VsyncChild.h"
|
||||
#include "mozilla/net/HttpBackgroundChannelChild.h"
|
||||
#include "mozilla/net/PUDPSocketChild.h"
|
||||
#include "mozilla/dom/network/UDPSocketChild.h"
|
||||
#include "mozilla/dom/WebAuthnTransactionChild.h"
|
||||
|
@ -559,6 +560,24 @@ BackgroundChildImpl::DeallocPWebAuthnTransactionChild(PWebAuthnTransactionChild*
|
|||
return true;
|
||||
}
|
||||
|
||||
net::PHttpBackgroundChannelChild*
|
||||
BackgroundChildImpl::AllocPHttpBackgroundChannelChild(const uint64_t& aChannelId)
|
||||
{
|
||||
MOZ_CRASH("PHttpBackgroundChannelChild actor should be manually constructed!");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool
|
||||
BackgroundChildImpl::DeallocPHttpBackgroundChannelChild(PHttpBackgroundChannelChild* aActor)
|
||||
{
|
||||
// The reference is increased in BackgroundChannelCreateCallback::ActorCreated
|
||||
// of HttpBackgroundChannelChild.cpp. We should decrease it after IPC
|
||||
// destroyed.
|
||||
RefPtr<net::HttpBackgroundChannelChild> child =
|
||||
dont_AddRef(static_cast<net::HttpBackgroundChannelChild*>(aActor));
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace ipc
|
||||
} // namespace mozilla
|
||||
|
||||
|
|
|
@ -202,6 +202,12 @@ protected:
|
|||
|
||||
virtual bool
|
||||
DeallocPWebAuthnTransactionChild(PWebAuthnTransactionChild* aActor) override;
|
||||
|
||||
virtual PHttpBackgroundChannelChild*
|
||||
AllocPHttpBackgroundChannelChild(const uint64_t& aChannelId) override;
|
||||
|
||||
virtual bool
|
||||
DeallocPHttpBackgroundChannelChild(PHttpBackgroundChannelChild* aActor) override;
|
||||
};
|
||||
|
||||
class BackgroundChildImpl::ThreadLocal final
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include "mozilla/ipc/PChildToParentStreamParent.h"
|
||||
#include "mozilla/ipc/PParentToChildStreamParent.h"
|
||||
#include "mozilla/layout/VsyncParent.h"
|
||||
#include "mozilla/net/HttpBackgroundChannelParent.h"
|
||||
#include "mozilla/dom/network/UDPSocketParent.h"
|
||||
#include "mozilla/dom/WebAuthnTransactionParent.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
|
@ -872,6 +873,53 @@ BackgroundParentImpl::DeallocPWebAuthnTransactionParent(dom::PWebAuthnTransactio
|
|||
return true;
|
||||
}
|
||||
|
||||
net::PHttpBackgroundChannelParent*
|
||||
BackgroundParentImpl::AllocPHttpBackgroundChannelParent(const uint64_t& aChannelId)
|
||||
{
|
||||
AssertIsInMainProcess();
|
||||
AssertIsOnBackgroundThread();
|
||||
|
||||
RefPtr<net::HttpBackgroundChannelParent> actor =
|
||||
new net::HttpBackgroundChannelParent();
|
||||
|
||||
// hold extra refcount for IPDL
|
||||
return actor.forget().take();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
BackgroundParentImpl::RecvPHttpBackgroundChannelConstructor(
|
||||
net::PHttpBackgroundChannelParent *aActor,
|
||||
const uint64_t& aChannelId)
|
||||
{
|
||||
MOZ_ASSERT(aActor);
|
||||
AssertIsInMainProcess();
|
||||
AssertIsOnBackgroundThread();
|
||||
|
||||
net::HttpBackgroundChannelParent* aParent =
|
||||
static_cast<net::HttpBackgroundChannelParent*>(aActor);
|
||||
|
||||
if (NS_WARN_IF(NS_FAILED(aParent->Init(aChannelId)))) {
|
||||
return IPC_FAIL_NO_REASON(this);
|
||||
}
|
||||
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
bool
|
||||
BackgroundParentImpl::DeallocPHttpBackgroundChannelParent(
|
||||
net::PHttpBackgroundChannelParent *aActor)
|
||||
{
|
||||
MOZ_ASSERT(aActor);
|
||||
AssertIsInMainProcess();
|
||||
AssertIsOnBackgroundThread();
|
||||
|
||||
// release extra refcount hold by AllocPHttpBackgroundChannelParent
|
||||
RefPtr<net::HttpBackgroundChannelParent> actor =
|
||||
dont_AddRef(static_cast<net::HttpBackgroundChannelParent*>(aActor));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace ipc
|
||||
} // namespace mozilla
|
||||
|
||||
|
|
|
@ -226,6 +226,15 @@ protected:
|
|||
|
||||
virtual bool
|
||||
DeallocPWebAuthnTransactionParent(PWebAuthnTransactionParent* aActor) override;
|
||||
|
||||
virtual PHttpBackgroundChannelParent*
|
||||
AllocPHttpBackgroundChannelParent(const uint64_t& aChannelId) override;
|
||||
|
||||
virtual mozilla::ipc::IPCResult
|
||||
RecvPHttpBackgroundChannelConstructor(PHttpBackgroundChannelParent *aActor,
|
||||
const uint64_t& aChannelId) override;
|
||||
virtual bool
|
||||
DeallocPHttpBackgroundChannelParent(PHttpBackgroundChannelParent *aActor) override;
|
||||
};
|
||||
|
||||
} // namespace ipc
|
||||
|
|
|
@ -14,6 +14,7 @@ include protocol PFileDescriptorSet;
|
|||
include protocol PFileSystemRequest;
|
||||
include protocol PGamepadEventChannel;
|
||||
include protocol PGamepadTestChannel;
|
||||
include protocol PHttpBackgroundChannel;
|
||||
include protocol PIPCBlobInputStream;
|
||||
include protocol PPendingIPCBlob;
|
||||
include protocol PMessagePort;
|
||||
|
@ -61,6 +62,7 @@ sync protocol PBackground
|
|||
manages PFileSystemRequest;
|
||||
manages PGamepadEventChannel;
|
||||
manages PGamepadTestChannel;
|
||||
manages PHttpBackgroundChannel;
|
||||
manages PIPCBlobInputStream;
|
||||
manages PPendingIPCBlob;
|
||||
manages PMessagePort;
|
||||
|
@ -115,6 +117,8 @@ parent:
|
|||
|
||||
async PGamepadTestChannel();
|
||||
|
||||
async PHttpBackgroundChannel(uint64_t channelId);
|
||||
|
||||
async PWebAuthnTransaction();
|
||||
|
||||
child:
|
||||
|
|
|
@ -355,15 +355,18 @@ CSSStyleSheet::CSSStyleSheet(const CSSStyleSheet& aCopy,
|
|||
dom::CSSImportRule* aOwnerRuleToUse,
|
||||
nsIDocument* aDocumentToUse,
|
||||
nsINode* aOwningNodeToUse)
|
||||
: StyleSheet(aCopy, aOwnerRuleToUse, aDocumentToUse, aOwningNodeToUse),
|
||||
mInRuleProcessorCache(false),
|
||||
mScopeElement(nullptr),
|
||||
mRuleProcessors(nullptr)
|
||||
: StyleSheet(aCopy,
|
||||
aParentToUse,
|
||||
aOwnerRuleToUse,
|
||||
aDocumentToUse,
|
||||
aOwningNodeToUse)
|
||||
, mInRuleProcessorCache(false)
|
||||
, mScopeElement(nullptr)
|
||||
, mRuleProcessors(nullptr)
|
||||
{
|
||||
mParent = aParentToUse;
|
||||
|
||||
if (mDirty) { // CSSOM's been there, force full copy now
|
||||
NS_ASSERTION(mInner->mComplete, "Why have rules been accessed on an incomplete sheet?");
|
||||
NS_ASSERTION(mInner->mComplete,
|
||||
"Why have rules been accessed on an incomplete sheet?");
|
||||
// FIXME: handle failure?
|
||||
//
|
||||
// NOTE: It's important to call this from the subclass, since it could
|
||||
|
|
|
@ -84,12 +84,15 @@ ServoStyleSheet::ServoStyleSheet(const ServoStyleSheet& aCopy,
|
|||
dom::CSSImportRule* aOwnerRuleToUse,
|
||||
nsIDocument* aDocumentToUse,
|
||||
nsINode* aOwningNodeToUse)
|
||||
: StyleSheet(aCopy, aOwnerRuleToUse, aDocumentToUse, aOwningNodeToUse)
|
||||
: StyleSheet(aCopy,
|
||||
aParentToUse,
|
||||
aOwnerRuleToUse,
|
||||
aDocumentToUse,
|
||||
aOwningNodeToUse)
|
||||
{
|
||||
mParent = aParentToUse;
|
||||
|
||||
if (mDirty) { // CSSOM's been there, force full copy now
|
||||
NS_ASSERTION(mInner->mComplete, "Why have rules been accessed on an incomplete sheet?");
|
||||
NS_ASSERTION(mInner->mComplete,
|
||||
"Why have rules been accessed on an incomplete sheet?");
|
||||
// FIXME: handle failure?
|
||||
//
|
||||
// NOTE: It's important to call this from the subclass, since this could
|
||||
|
|
|
@ -34,10 +34,11 @@ StyleSheet::StyleSheet(StyleBackendType aType, css::SheetParsingMode aParsingMod
|
|||
}
|
||||
|
||||
StyleSheet::StyleSheet(const StyleSheet& aCopy,
|
||||
StyleSheet* aParentToUse,
|
||||
dom::CSSImportRule* aOwnerRuleToUse,
|
||||
nsIDocument* aDocumentToUse,
|
||||
nsINode* aOwningNodeToUse)
|
||||
: mParent(nullptr)
|
||||
: mParent(aParentToUse)
|
||||
, mTitle(aCopy.mTitle)
|
||||
, mDocument(aDocumentToUse)
|
||||
, mOwningNode(aOwningNodeToUse)
|
||||
|
@ -45,8 +46,8 @@ StyleSheet::StyleSheet(const StyleSheet& aCopy,
|
|||
, mParsingMode(aCopy.mParsingMode)
|
||||
, mType(aCopy.mType)
|
||||
, mDisabled(aCopy.mDisabled)
|
||||
// We only use this constructor during cloning. It's the cloner's
|
||||
// responsibility to notify us if we end up being owned by a document.
|
||||
// We only use this constructor during cloning. It's the cloner's
|
||||
// responsibility to notify us if we end up being owned by a document.
|
||||
, mDocumentAssociationMode(NotOwnedByDocument)
|
||||
, mInner(aCopy.mInner) // Shallow copy, but concrete subclasses will fix up.
|
||||
, mDirty(aCopy.mDirty)
|
||||
|
|
|
@ -53,6 +53,7 @@ class StyleSheet : public nsIDOMCSSStyleSheet
|
|||
protected:
|
||||
StyleSheet(StyleBackendType aType, css::SheetParsingMode aParsingMode);
|
||||
StyleSheet(const StyleSheet& aCopy,
|
||||
StyleSheet* aParentToUse,
|
||||
dom::CSSImportRule* aOwnerRuleToUse,
|
||||
nsIDocument* aDocumentToUse,
|
||||
nsINode* aOwningNodeToUse);
|
||||
|
|
|
@ -277,11 +277,6 @@ AnnexB::ExtractExtraData(const mozilla::MediaRawData* aSample)
|
|||
MOZ_ASSERT(IsAVCC(aSample));
|
||||
|
||||
RefPtr<mozilla::MediaByteBuffer> extradata = new mozilla::MediaByteBuffer;
|
||||
if (HasSPS(aSample->mExtraData)) {
|
||||
// We already have an explicit extradata, re-use it.
|
||||
extradata = aSample->mExtraData;
|
||||
return extradata.forget();
|
||||
}
|
||||
|
||||
// SPS content
|
||||
mozilla::Vector<uint8_t> sps;
|
||||
|
@ -293,7 +288,20 @@ AnnexB::ExtractExtraData(const mozilla::MediaRawData* aSample)
|
|||
int numPps = 0;
|
||||
|
||||
int nalLenSize = ((*aSample->mExtraData)[4] & 3) + 1;
|
||||
ByteReader reader(aSample->Data(), aSample->Size());
|
||||
|
||||
size_t sampleSize = aSample->Size();
|
||||
if (aSample->mCrypto.mValid) {
|
||||
// The content is encrypted, we can only parse the non-encrypted data.
|
||||
MOZ_ASSERT(aSample->mCrypto.mPlainSizes.Length() > 0);
|
||||
if (aSample->mCrypto.mPlainSizes.Length() == 0 ||
|
||||
aSample->mCrypto.mPlainSizes[0] > sampleSize) {
|
||||
// This is invalid content.
|
||||
return nullptr;
|
||||
}
|
||||
sampleSize = aSample->mCrypto.mPlainSizes[0];
|
||||
}
|
||||
|
||||
ByteReader reader(aSample->Data(), sampleSize);
|
||||
|
||||
// Find SPS and PPS NALUs in AVCC data
|
||||
while (reader.Remaining() > nalLenSize) {
|
||||
|
@ -365,47 +373,6 @@ AnnexB::HasSPS(const mozilla::MediaByteBuffer* aExtraData)
|
|||
return numSps > 0;
|
||||
}
|
||||
|
||||
bool
|
||||
AnnexB::HasPPS(const mozilla::MediaRawData* aSample)
|
||||
{
|
||||
return HasPPS(aSample->mExtraData);
|
||||
}
|
||||
|
||||
bool
|
||||
AnnexB::HasPPS(const mozilla::MediaByteBuffer* aExtraData)
|
||||
{
|
||||
if (!aExtraData) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ByteReader reader(aExtraData);
|
||||
const uint8_t* ptr = reader.Read(5);
|
||||
if (!ptr || !reader.CanRead8()) {
|
||||
return false;
|
||||
}
|
||||
uint8_t numSps = reader.ReadU8() & 0x1f;
|
||||
// Skip over the included SPS.
|
||||
for (uint8_t i = 0; i < numSps; i++) {
|
||||
if (reader.Remaining() < 3) {
|
||||
return false;
|
||||
}
|
||||
uint16_t length = reader.ReadU16();
|
||||
if ((reader.PeekU8() & 0x1f) != 7) {
|
||||
// Not an SPS NAL type.
|
||||
return false;
|
||||
}
|
||||
if (!reader.Read(length)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (!reader.CanRead8()) {
|
||||
return false;
|
||||
}
|
||||
uint8_t numPps = reader.ReadU8();
|
||||
|
||||
return numPps > 0;
|
||||
}
|
||||
|
||||
bool
|
||||
AnnexB::ConvertSampleTo4BytesAVCC(mozilla::MediaRawData* aSample)
|
||||
{
|
||||
|
|
|
@ -181,27 +181,6 @@ SPSData::SPSData()
|
|||
memset(scaling_matrix8x8, 16, sizeof(scaling_matrix8x8));
|
||||
}
|
||||
|
||||
PPSData::PPSData()
|
||||
{
|
||||
PodZero(this);
|
||||
memset(scaling_matrix4x4, 16, sizeof(scaling_matrix4x4));
|
||||
memset(scaling_matrix8x8, 16, sizeof(scaling_matrix8x8));
|
||||
}
|
||||
|
||||
const uint8_t H264::ZZ_SCAN[16] = { 0, 1, 4, 8,
|
||||
5, 2, 3, 6,
|
||||
9, 12, 13, 10,
|
||||
7, 11, 14, 15 };
|
||||
|
||||
const uint8_t H264::ZZ_SCAN8[64] = { 0, 1, 8, 16, 9, 2, 3, 10,
|
||||
17, 24, 32, 25, 18, 11, 4, 5,
|
||||
12, 19, 26, 33, 40, 48, 41, 34,
|
||||
27, 20, 13, 6, 7, 14, 21, 28,
|
||||
35, 42, 49, 56, 57, 50, 43, 36,
|
||||
29, 22, 15, 23, 30, 37, 44, 51,
|
||||
58, 59, 52, 45, 38, 31, 39, 46,
|
||||
53, 60, 61, 54, 47, 55, 62, 63 };
|
||||
|
||||
/* static */ already_AddRefed<mozilla::MediaByteBuffer>
|
||||
H264::DecodeNALUnit(const mozilla::MediaByteBuffer* aNAL)
|
||||
{
|
||||
|
@ -606,26 +585,6 @@ H264::vui_parameters(BitReader& aBr, SPSData& aDest)
|
|||
/* static */ bool
|
||||
H264::DecodeSPSFromExtraData(const mozilla::MediaByteBuffer* aExtraData,
|
||||
SPSData& aDest)
|
||||
{
|
||||
H264ParametersSet ps;
|
||||
if (!DecodeSPSDataSetFromExtraData(aExtraData, ps.SPSes)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint16_t spsId = 0;
|
||||
if (DecodePPSDataSetFromExtraData(aExtraData, ps.SPSes, ps.PPSes)) {
|
||||
// We can't know which PPS is in use without parsing slice header if we
|
||||
// have multiple PPSes, so we always use the first one.
|
||||
spsId = ps.PPSes[0].seq_parameter_set_id;
|
||||
}
|
||||
|
||||
aDest = Move(ps.SPSes[spsId]);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
H264::DecodeSPSDataSetFromExtraData(const mozilla::MediaByteBuffer* aExtraData,
|
||||
SPSDataSet& aDest)
|
||||
{
|
||||
if (!AnnexB::HasSPS(aExtraData)) {
|
||||
return false;
|
||||
|
@ -642,34 +601,31 @@ H264::DecodeSPSDataSetFromExtraData(const mozilla::MediaByteBuffer* aExtraData,
|
|||
return false;
|
||||
}
|
||||
|
||||
for (uint32_t idx = 0; idx < numSps; idx++) {
|
||||
uint16_t length = reader.ReadU16();
|
||||
|
||||
if ((reader.PeekU8() & 0x1f) != H264_NAL_SPS) {
|
||||
// Not a SPS NAL type.
|
||||
return false;
|
||||
}
|
||||
const uint8_t* ptr = reader.Read(length);
|
||||
if (!ptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RefPtr<mozilla::MediaByteBuffer> rawNAL = new mozilla::MediaByteBuffer;
|
||||
rawNAL->AppendElements(ptr, length);
|
||||
|
||||
RefPtr<mozilla::MediaByteBuffer> sps = DecodeNALUnit(rawNAL);
|
||||
|
||||
if (!sps) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SPSData spsData;
|
||||
if (!DecodeSPS(sps, spsData)) {
|
||||
return false;
|
||||
}
|
||||
aDest.AppendElement(spsData);
|
||||
if (numSps > 1) {
|
||||
NS_WARNING("Multiple SPS, only decoding the first one");
|
||||
}
|
||||
return true;
|
||||
|
||||
uint16_t length = reader.ReadU16();
|
||||
|
||||
if ((reader.PeekU8() & 0x1f) != H264_NAL_SPS) {
|
||||
// Not a SPS NAL type.
|
||||
return false;
|
||||
}
|
||||
const uint8_t* ptr = reader.Read(length);
|
||||
if (!ptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RefPtr<mozilla::MediaByteBuffer> rawNAL = new mozilla::MediaByteBuffer;
|
||||
rawNAL->AppendElements(ptr, length);
|
||||
|
||||
RefPtr<mozilla::MediaByteBuffer> sps = DecodeNALUnit(rawNAL);
|
||||
|
||||
if (!sps) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return DecodeSPS(sps, aDest);
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
|
@ -694,213 +650,6 @@ H264::EnsureSPSIsSane(SPSData& aSPS)
|
|||
return valid;
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
H264::DecodePPSDataSetFromExtraData(const mozilla::MediaByteBuffer* aExtraData,
|
||||
const SPSDataSet& aSPSes, PPSDataSet& aDest)
|
||||
{
|
||||
if (!AnnexB::HasPPS(aExtraData)) {
|
||||
return false;
|
||||
}
|
||||
ByteReader reader(aExtraData);
|
||||
|
||||
if (!reader.Read(5)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t numSps = reader.ReadU8() & 0x1f;
|
||||
if (!numSps) {
|
||||
// No SPS.
|
||||
return false;
|
||||
}
|
||||
NS_ASSERTION(numSps == 1, "More than one SPS in extradata");
|
||||
for (uint8_t i = 0; i < numSps; i++) {
|
||||
uint16_t length = reader.ReadU16();
|
||||
|
||||
if ((reader.PeekU8() & 0x1f) != H264_NAL_SPS) {
|
||||
// Not a SPS NAL type.
|
||||
return false;
|
||||
}
|
||||
const uint8_t* ptr = reader.Read(length);
|
||||
if (!ptr) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
uint8_t numPps = reader.ReadU8();
|
||||
if (!numPps) {
|
||||
// No PPs.
|
||||
return false;
|
||||
}
|
||||
|
||||
for (uint32_t idx = 0; idx < numPps; idx++) {
|
||||
uint16_t length = reader.ReadU16();
|
||||
|
||||
if ((reader.PeekU8() & 0x1f) != H264_NAL_PPS) {
|
||||
// Not a PPS NAL type.
|
||||
return false;
|
||||
}
|
||||
const uint8_t* ptr = reader.Read(length);
|
||||
if (!ptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RefPtr<mozilla::MediaByteBuffer> rawNAL = new mozilla::MediaByteBuffer;
|
||||
rawNAL->AppendElements(ptr, length);
|
||||
|
||||
RefPtr<mozilla::MediaByteBuffer> pps = DecodeNALUnit(rawNAL);
|
||||
|
||||
if (!pps) {
|
||||
return false;
|
||||
}
|
||||
|
||||
PPSData ppsData;
|
||||
if (!DecodePPS(pps, aSPSes, ppsData)) {
|
||||
return false;
|
||||
}
|
||||
if (ppsData.pic_parameter_set_id >= aDest.Length()) {
|
||||
aDest.SetLength(ppsData.pic_parameter_set_id + 1);
|
||||
}
|
||||
aDest[ppsData.pic_parameter_set_id] = Move(ppsData);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
H264::DecodePPS(const mozilla::MediaByteBuffer* aPPS, const SPSDataSet& aSPSes,
|
||||
PPSData& aDest)
|
||||
{
|
||||
if (!aPPS) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (aSPSes.IsEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
BitReader br(aPPS, GetBitLength(aPPS));
|
||||
|
||||
READUE(pic_parameter_set_id, MAX_PPS_COUNT - 1);
|
||||
READUE(seq_parameter_set_id, MAX_SPS_COUNT - 1);
|
||||
|
||||
if (aDest.seq_parameter_set_id >= aSPSes.Length()) {
|
||||
// Invalid SPS id.
|
||||
return false;
|
||||
}
|
||||
const SPSData& sps = aSPSes[aDest.seq_parameter_set_id];
|
||||
|
||||
memcpy(aDest.scaling_matrix4x4, sps.scaling_matrix4x4,
|
||||
sizeof(aDest.scaling_matrix4x4));
|
||||
memcpy(aDest.scaling_matrix8x8, sps.scaling_matrix8x8,
|
||||
sizeof(aDest.scaling_matrix8x8));
|
||||
|
||||
aDest.entropy_coding_mode_flag = br.ReadBit();
|
||||
aDest.bottom_field_pic_order_in_frame_present_flag = br.ReadBit();
|
||||
READUE(num_slice_groups_minus1, 7);
|
||||
if (aDest.num_slice_groups_minus1 > 0) {
|
||||
READUE(slice_group_map_type, 6);
|
||||
switch (aDest.slice_group_map_type) {
|
||||
case 0:
|
||||
for (uint8_t iGroup = 0; iGroup <= aDest.num_slice_groups_minus1;
|
||||
iGroup++) {
|
||||
aDest.run_length_minus1[iGroup] = br.ReadUE();
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
for (uint8_t iGroup = 0; iGroup < aDest.num_slice_groups_minus1;
|
||||
iGroup++) {
|
||||
aDest.top_left[iGroup] = br.ReadUE();
|
||||
aDest.bottom_right[iGroup] = br.ReadUE();
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
case 4:
|
||||
case 5:
|
||||
aDest.slice_group_change_direction_flag = br.ReadBit();
|
||||
aDest.slice_group_change_rate_minus1 = br.ReadUE();
|
||||
break;
|
||||
case 6:
|
||||
aDest.pic_size_in_map_units_minus1 = br.ReadUE();
|
||||
for (uint32_t i = 0; i <= aDest.pic_size_in_map_units_minus1; i++) {
|
||||
/* slice_group_id[ i ] identifies a slice group of the i-th slice group map
|
||||
unit in raster scan order. The length of the slice_group_id[i] syntax
|
||||
element is Ceil(Log2(num_slice_groups_minus1+1)) bits. The value of
|
||||
slice_group_id[i] shall be in the range of 0 to num_slice_groups_minus1,
|
||||
inclusive. */
|
||||
br.ReadBits(std::ceil(std::log2(aDest.num_slice_groups_minus1 + 1)));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
READUE(num_ref_idx_l0_default_active_minus1, 31);
|
||||
READUE(num_ref_idx_l1_default_active_minus1, 31);
|
||||
aDest.weighted_pred_flag = br.ReadBit();
|
||||
aDest.weighted_bipred_idc = br.ReadBits(2);
|
||||
READSE(pic_init_qp_minus26, -(26 + 6 * sps.bit_depth_luma_minus8), 25);
|
||||
READSE(pic_init_qs_minus26, -26, 26);
|
||||
READSE(chroma_qp_index_offset, -12, 12);
|
||||
aDest.deblocking_filter_control_present_flag = br.ReadBit();
|
||||
aDest.constrained_intra_pred_flag = br.ReadBit();
|
||||
aDest.redundant_pic_cnt_present_flag = br.ReadBit();
|
||||
if (br.BitsLeft()) {
|
||||
aDest.transform_8x8_mode_flag = br.ReadBit();
|
||||
if (br.ReadBit()) { // pic_scaling_matrix_present_flag
|
||||
if (sps.seq_scaling_matrix_present_flag) {
|
||||
scaling_list(br, aDest.scaling_matrix4x4[0], Default_4x4_Intra);
|
||||
scaling_list(br, aDest.scaling_matrix4x4[1], Default_4x4_Intra,
|
||||
aDest.scaling_matrix4x4[0]);
|
||||
scaling_list(br, aDest.scaling_matrix4x4[2], Default_4x4_Intra,
|
||||
aDest.scaling_matrix4x4[1]);
|
||||
scaling_list(br, aDest.scaling_matrix4x4[3], Default_4x4_Inter);
|
||||
} else {
|
||||
scaling_list(br, aDest.scaling_matrix4x4[0], Default_4x4_Intra,
|
||||
Default_4x4_Intra);
|
||||
scaling_list(br, aDest.scaling_matrix4x4[1], Default_4x4_Intra,
|
||||
aDest.scaling_matrix4x4[0]);
|
||||
scaling_list(br, aDest.scaling_matrix4x4[2], Default_4x4_Intra,
|
||||
aDest.scaling_matrix4x4[1]);
|
||||
scaling_list(br, aDest.scaling_matrix4x4[3], Default_4x4_Inter,
|
||||
Default_4x4_Inter);
|
||||
}
|
||||
scaling_list(br, aDest.scaling_matrix4x4[4], Default_4x4_Inter,
|
||||
aDest.scaling_matrix4x4[3]);
|
||||
scaling_list(br, aDest.scaling_matrix4x4[5], Default_4x4_Inter,
|
||||
aDest.scaling_matrix4x4[4]);
|
||||
if (aDest.transform_8x8_mode_flag) {
|
||||
if (sps.seq_scaling_matrix_present_flag) {
|
||||
scaling_list(br, aDest.scaling_matrix8x8[0], Default_8x8_Intra);
|
||||
scaling_list(br, aDest.scaling_matrix8x8[1], Default_8x8_Inter);
|
||||
} else {
|
||||
scaling_list(br, aDest.scaling_matrix8x8[0], Default_8x8_Intra,
|
||||
Default_8x8_Intra);
|
||||
scaling_list(br, aDest.scaling_matrix8x8[1], Default_8x8_Inter,
|
||||
Default_8x8_Inter);
|
||||
}
|
||||
if (sps.chroma_format_idc == 3) {
|
||||
scaling_list(br, aDest.scaling_matrix8x8[2], Default_8x8_Intra,
|
||||
aDest.scaling_matrix8x8[0]);
|
||||
scaling_list(br, aDest.scaling_matrix8x8[3], Default_8x8_Inter,
|
||||
aDest.scaling_matrix8x8[1]);
|
||||
scaling_list(br, aDest.scaling_matrix8x8[4], Default_8x8_Intra,
|
||||
aDest.scaling_matrix8x8[2]);
|
||||
scaling_list(br, aDest.scaling_matrix8x8[5], Default_8x8_Inter,
|
||||
aDest.scaling_matrix8x8[3]);
|
||||
}
|
||||
}
|
||||
}
|
||||
READSE(second_chroma_qp_index_offset, -12, 12);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
H264::DecodeParametersSet(const mozilla::MediaByteBuffer* aExtraData,
|
||||
H264ParametersSet& aDest)
|
||||
{
|
||||
return DecodeSPSDataSetFromExtraData(aExtraData, aDest.SPSes) &&
|
||||
DecodePPSDataSetFromExtraData(aExtraData, aDest.SPSes, aDest.PPSes);
|
||||
}
|
||||
|
||||
/* static */ uint32_t
|
||||
H264::ComputeMaxRefFrames(const mozilla::MediaByteBuffer* aExtraData)
|
||||
{
|
||||
|
|
|
@ -29,15 +29,12 @@ public:
|
|||
// Parse an AVCC extradata and construct the Annex B sample header.
|
||||
static already_AddRefed<mozilla::MediaByteBuffer> ConvertExtraDataToAnnexB(
|
||||
const mozilla::MediaByteBuffer* aExtraData);
|
||||
// Extract SPS and PPS NALs from aSample, aSample must be in AVCC format.
|
||||
// If aSample already contains an extradata with an SPS, it will be returned
|
||||
// otherwise the SPS/PPS NALs are searched in-band.
|
||||
// Extract SPS and PPS NALs from aSample by looking into each NALs.
|
||||
// aSample must be in AVCC format.
|
||||
static already_AddRefed<mozilla::MediaByteBuffer> ExtractExtraData(
|
||||
const mozilla::MediaRawData* aSample);
|
||||
static bool HasSPS(const mozilla::MediaRawData* aSample);
|
||||
static bool HasSPS(const mozilla::MediaByteBuffer* aExtraData);
|
||||
static bool HasPPS(const mozilla::MediaRawData* aSample);
|
||||
static bool HasPPS(const mozilla::MediaByteBuffer* aExtraData);
|
||||
// Returns true if format is AVCC and sample has valid extradata.
|
||||
static bool IsAVCC(const mozilla::MediaRawData* aSample);
|
||||
// Returns true if format is AnnexB.
|
||||
|
|
|
@ -403,202 +403,6 @@ struct SPSData
|
|||
SPSData();
|
||||
};
|
||||
|
||||
struct PPSData
|
||||
{
|
||||
/*
|
||||
H264 decoding parameters according to ITU-T H.264 (T-REC-H.264-201402-I/en)
|
||||
http://www.itu.int/rec/T-REC-H.264-201402-I/en
|
||||
7.3.2.2 Picture parameter set RBSP syntax
|
||||
*/
|
||||
/* pic_parameter_set_id identifies the picture parameter set that is referred
|
||||
to in the slice header. The value of pic_parameter_set_id shall be in the
|
||||
range of 0 to 255, inclusive. */
|
||||
uint8_t pic_parameter_set_id;
|
||||
|
||||
/* seq_parameter_set_id refers to the active sequence parameter set. The value
|
||||
of seq_parameter_set_id shall be in the range of 0 to 31, inclusive. */
|
||||
uint8_t seq_parameter_set_id;
|
||||
|
||||
/* entropy_coding_mode_flag selects the entropy decoding method to be applied
|
||||
for the syntax elements for which two descriptors appear in the syntax tables
|
||||
as follows:
|
||||
– If entropy_coding_mode_flag is equal to 0, the method specified by the
|
||||
left descriptor in the syntax table is applied (Exp-Golomb coded, see
|
||||
clause 9.1 or CAVLC, see clause 9.2).
|
||||
– Otherwise (entropy_coding_mode_flag is equal to 1), the method specified
|
||||
by the right descriptor in the syntax table is applied (CABAC, see clause
|
||||
9.3) */
|
||||
bool entropy_coding_mode_flag;
|
||||
|
||||
/* bottom_field_pic_order_in_frame_present_flag equal to 1 specifies that the
|
||||
syntax elements delta_pic_order_cnt_bottom (when pic_order_cnt_type is
|
||||
equal to 0) or delta_pic_order_cnt[ 1 ] (when pic_order_cnt_type is equal to
|
||||
1), which are related to picture order counts for the bottom field of a
|
||||
coded frame, are present in the slice headers for coded frames as specified
|
||||
in clause 7.3.3. bottom_field_pic_order_in_frame_present_flag equal to 0
|
||||
specifies that the syntax elements delta_pic_order_cnt_bottom and
|
||||
delta_pic_order_cnt[ 1 ] are not present in the slice headers.
|
||||
Also known has pic_order_present_flag. */
|
||||
bool bottom_field_pic_order_in_frame_present_flag;
|
||||
|
||||
/* num_slice_groups_minus1 plus 1 specifies the number of slice groups for a
|
||||
picture. When num_slice_groups_minus1 is equal to 0, all slices of the
|
||||
picture belong to the same slice group. The allowed range of
|
||||
num_slice_groups_minus1 is specified in Annex A. */
|
||||
uint8_t num_slice_groups_minus1;
|
||||
|
||||
/* slice_group_map_type specifies how the mapping of slice group map units to
|
||||
slice groups is coded. The value of slice_group_map_type shall be in the
|
||||
range of 0 to 6, inclusive. */
|
||||
uint8_t slice_group_map_type;
|
||||
|
||||
/* run_length_minus1[i] is used to specify the number of consecutive slice
|
||||
group map units to be assigned to the i-th slice group in raster scan order
|
||||
of slice group map units. The value of run_length_minus1[ i ] shall be in
|
||||
the range of 0 to PicSizeInMapUnits − 1, inclusive. */
|
||||
uint32_t run_length_minus1[8];
|
||||
|
||||
/* top_left[i] and bottom_right[i] specify the top-left and bottom-right
|
||||
corners of a rectangle, respectively. top_left[i] and bottom_right[i] are
|
||||
slice group map unit positions in a raster scan of the picture for the slice
|
||||
group map units. For each rectangle i, all of the following constraints
|
||||
shall be obeyed by the values of the syntax elements top_left[i] and
|
||||
bottom_right[i]:
|
||||
– top_left[ i ] shall be less than or equal to bottom_right[i] and
|
||||
bottom_right[i] shall be less than PicSizeInMapUnits.
|
||||
– (top_left[i] % PicWidthInMbs) shall be less than or equal to the value
|
||||
of (bottom_right[i] % PicWidthInMbs). */
|
||||
uint32_t top_left[8];
|
||||
uint32_t bottom_right[8];
|
||||
|
||||
/* slice_group_change_direction_flag is used with slice_group_map_type to
|
||||
specify the refined map type when slice_group_map_type is 3, 4, or 5. */
|
||||
bool slice_group_change_direction_flag;
|
||||
|
||||
/* slice_group_change_rate_minus1 is used to specify the variable
|
||||
SliceGroupChangeRate. SliceGroupChangeRate specifies the multiple in number
|
||||
of slice group map units by which the size of a slice group can change from
|
||||
one picture to the next. The value of slice_group_change_rate_minus1 shall
|
||||
be in the range of 0 to PicSizeInMapUnits − 1, inclusive.
|
||||
The SliceGroupChangeRate variable is specified as follows:
|
||||
SliceGroupChangeRate = slice_group_change_rate_minus1 + 1 */
|
||||
uint32_t slice_group_change_rate_minus1;
|
||||
|
||||
/* pic_size_in_map_units_minus1 is used to specify the number of slice group
|
||||
map units in the picture. pic_size_in_map_units_minus1 shall be equal to
|
||||
PicSizeInMapUnits − 1. */
|
||||
uint32_t pic_size_in_map_units_minus1;
|
||||
|
||||
/* num_ref_idx_l0_default_active_minus1 specifies how
|
||||
num_ref_idx_l0_active_minus1 is inferred for P, SP, and B slices
|
||||
with num_ref_idx_active_override_flag equal to 0. The value of
|
||||
num_ref_idx_l0_default_active_minus1 shall be in the
|
||||
range of 0 to 31, inclusive. */
|
||||
uint8_t num_ref_idx_l0_default_active_minus1;
|
||||
|
||||
/* num_ref_idx_l1_default_active_minus1 specifies how
|
||||
num_ref_idx_l1_active_minus1 is inferred for B slices with
|
||||
num_ref_idx_active_override_flag equal to 0. The value of
|
||||
num_ref_idx_l1_default_active_minus1 shall be in the range
|
||||
of 0 to 31, inclusive. */
|
||||
uint8_t num_ref_idx_l1_default_active_minus1;
|
||||
|
||||
/* weighted_pred_flag equal to 0 specifies that the default weighted
|
||||
prediction shall be applied to P and SP slices.
|
||||
weighted_pred_flag equal to 1 specifies that explicit weighted prediction
|
||||
shall be applied to P and SP slices.weighted_pred_flag 1 */
|
||||
bool weighted_pred_flag;
|
||||
|
||||
/* weighted_bipred_idc equal to 0 specifies that the default weighted
|
||||
prediction shall be applied to B slices.
|
||||
weighted_bipred_idc equal to 1 specifies that explicit weighted prediction
|
||||
shall be applied to B slices. weighted_bipred_idc equal to 2 specifies that
|
||||
implicit weighted prediction shall be applied to B slices. The value of
|
||||
weighted_bipred_idc shall be in the range of 0 to 2, inclusive. */
|
||||
uint8_t weighted_bipred_idc;
|
||||
|
||||
/* pic_init_qp_minus26 specifies the initial value minus 26 of SliceQP Y for
|
||||
each slice. The initial value is modified at the slice layer when a
|
||||
non-zero value of slice_qp_delta is decoded, and is modified further when a
|
||||
non-zero value of mb_qp_delta is decoded at the macroblock layer.
|
||||
The value of pic_init_qp_minus26 shall be in the range of
|
||||
−(26 + QpBdOffset Y ) to +25, inclusive. */
|
||||
int8_t pic_init_qp_minus26;
|
||||
|
||||
/* pic_init_qs_minus26 specifies the initial value minus 26 of SliceQS Y for
|
||||
all macroblocks in SP or SI slices. The initial value is modified at the
|
||||
slice layer when a non-zero value of slice_qs_delta is decoded.
|
||||
The value of pic_init_qs_minus26 shall be in the range of −26 to +25,
|
||||
inclusive. */
|
||||
int8_t pic_init_qs_minus26;
|
||||
|
||||
/* chroma_qp_index_offset specifies the offset that shall be added to QP Y and
|
||||
QS Y for addressing the table of QP C values for the Cb chroma component.
|
||||
The value of chroma_qp_index_offset shall be in the range of −12 to +12,
|
||||
inclusive. */
|
||||
int8_t chroma_qp_index_offset;
|
||||
|
||||
/* deblocking_filter_control_present_flag equal to 1 specifies that a set of
|
||||
syntax elements controlling the characteristics of the deblocking filter is
|
||||
present in the slice header. deblocking_filter_control_present_flag equal to
|
||||
0 specifies that the set of syntax elements controlling the characteristics
|
||||
of the deblocking filter is not present in the slice headers and their
|
||||
inferred values are in effect. */
|
||||
bool deblocking_filter_control_present_flag;
|
||||
|
||||
/* constrained_intra_pred_flag equal to 0 specifies that intra prediction
|
||||
allows usage of residual data and decoded samples of neighbouring
|
||||
macroblocks coded using Inter macroblock prediction modes for the prediction
|
||||
of macroblocks coded using Intra macroblock prediction modes.
|
||||
constrained_intra_pred_flag equal to 1 specifies constrained intra
|
||||
prediction, in which case prediction of macroblocks coded using Intra
|
||||
macroblock prediction modes only uses residual data and decoded samples from
|
||||
I or SI macroblock types. */
|
||||
bool constrained_intra_pred_flag;
|
||||
|
||||
/* redundant_pic_cnt_present_flag equal to 0 specifies that the
|
||||
redundant_pic_cnt syntax element is not present in slice headers, coded
|
||||
slice data partition B NAL units, and coded slice data partition C NAL units
|
||||
that refer (either directly or by association with a corresponding coded
|
||||
slice data partition A NAL unit) to the picture parameter set.
|
||||
redundant_pic_cnt_present_flag equal to 1 specifies that the
|
||||
redundant_pic_cnt syntax element is present in all slice headers, coded
|
||||
slice data partition B NAL units, and coded slice data partition C NAL units
|
||||
that refer (either directly or by association with a corresponding coded
|
||||
slice data partition A NAL unit) to the picture parameter set. */
|
||||
bool redundant_pic_cnt_present_flag;
|
||||
|
||||
/* transform_8x8_mode_flag equal to 1 specifies that the 8x8 transform
|
||||
decoding process may be in use (see clause 8.5).
|
||||
transform_8x8_mode_flag equal to 0 specifies that the 8x8 transform decoding
|
||||
process is not in use. When transform_8x8_mode_flag is not present, it shall
|
||||
be inferred to be 0. */
|
||||
bool transform_8x8_mode_flag;
|
||||
|
||||
/* second_chroma_qp_index_offset specifies the offset that shall be added to
|
||||
QP Y and QS Y for addressing the table of QP C values for the Cr chroma
|
||||
component.
|
||||
The value of second_chroma_qp_index_offset shall be in the range of
|
||||
−12 to +12, inclusive.
|
||||
When second_chroma_qp_index_offset is not present, it shall be inferred to
|
||||
be equal to chroma_qp_index_offset. */
|
||||
int8_t second_chroma_qp_index_offset;
|
||||
|
||||
uint8_t scaling_matrix4x4[6][16];
|
||||
uint8_t scaling_matrix8x8[6][64];
|
||||
|
||||
PPSData();
|
||||
};
|
||||
|
||||
typedef AutoTArray<SPSData, MAX_SPS_COUNT> SPSDataSet;
|
||||
typedef AutoTArray<PPSData, MAX_PPS_COUNT> PPSDataSet;
|
||||
|
||||
struct H264ParametersSet
|
||||
{
|
||||
SPSDataSet SPSes;
|
||||
PPSDataSet PPSes;
|
||||
};
|
||||
|
||||
class H264
|
||||
{
|
||||
public:
|
||||
|
@ -616,9 +420,6 @@ public:
|
|||
static bool DecodeSPSFromExtraData(const mozilla::MediaByteBuffer* aExtraData,
|
||||
SPSData& aDest);
|
||||
|
||||
static bool DecodeParametersSet(const mozilla::MediaByteBuffer* aExtraData,
|
||||
H264ParametersSet& aDest);
|
||||
|
||||
// If the given aExtraData is valid, return the aExtraData.max_num_ref_frames
|
||||
// clamped to be in the range of [4, 16]; otherwise return 4.
|
||||
static uint32_t ComputeMaxRefFrames(
|
||||
|
@ -635,27 +436,9 @@ public:
|
|||
// (Instantaneous Decoding Refresh) Picture.
|
||||
static FrameType GetFrameType(const mozilla::MediaRawData* aSample);
|
||||
|
||||
// ZigZag index taBles.
|
||||
// Some hardware requires the tables to be in zigzag order.
|
||||
// Use ZZ_SCAN table for the scaling_matrix4x4.
|
||||
// Use ZZ_SCAN8 table for the scaling_matrix8x8.
|
||||
// e.g. dest_scaling_matrix4x4[i,j] = scaling_matrix4x4[ZZ_SCAN(i,j)]
|
||||
static const uint8_t ZZ_SCAN[16];
|
||||
static const uint8_t ZZ_SCAN8[64];
|
||||
|
||||
private:
|
||||
static bool DecodeSPSDataSetFromExtraData(const mozilla::MediaByteBuffer* aExtraData,
|
||||
SPSDataSet& aDest);
|
||||
|
||||
static bool DecodePPSDataSetFromExtraData(const mozilla::MediaByteBuffer* aExtraData,
|
||||
const SPSDataSet& aPS,
|
||||
PPSDataSet& aDest);
|
||||
|
||||
/* Decode SPS NAL RBSP and fill SPSData structure */
|
||||
static bool DecodeSPS(const mozilla::MediaByteBuffer* aSPS, SPSData& aDest);
|
||||
/* Decode PPS NAL RBSP and fill PPSData structure */
|
||||
static bool DecodePPS(const mozilla::MediaByteBuffer* aPPS,
|
||||
const SPSDataSet& aSPSs, PPSData& aDest);
|
||||
static bool vui_parameters(BitReader& aBr, SPSData& aDest);
|
||||
// Read HRD parameters, all data is ignored.
|
||||
static void hrd_parameters(BitReader& aBr);
|
||||
|
|
|
@ -67,10 +67,7 @@ struct MOZ_MUST_USE_TYPE MOZ_NON_AUTOABLE already_AddRefed
|
|||
*/
|
||||
already_AddRefed() : mRawPtr(nullptr) {}
|
||||
|
||||
// The return and argument types here are arbitrarily selected so no
|
||||
// corresponding member function exists.
|
||||
typedef void (already_AddRefed::* MatchNullptr)(double, float);
|
||||
MOZ_IMPLICIT already_AddRefed(MatchNullptr aRawPtr) : mRawPtr(nullptr) {}
|
||||
MOZ_IMPLICIT already_AddRefed(decltype(nullptr)) : mRawPtr(nullptr) {}
|
||||
|
||||
explicit already_AddRefed(T* aRawPtr) : mRawPtr(aRawPtr) {}
|
||||
|
||||
|
|
|
@ -391,6 +391,7 @@ ProxyAutoConfig::ProxyAutoConfig()
|
|||
, mJSNeedsSetup(false)
|
||||
, mShutdown(false)
|
||||
, mIncludePath(false)
|
||||
, mExtraHeapSize(0)
|
||||
{
|
||||
MOZ_COUNT_CTOR(ProxyAutoConfig);
|
||||
}
|
||||
|
@ -551,9 +552,9 @@ static const JSFunctionSpec PACGlobalFunctions[] = {
|
|||
class JSContextWrapper
|
||||
{
|
||||
public:
|
||||
static JSContextWrapper *Create()
|
||||
static JSContextWrapper *Create(uint32_t aExtraHeapSize)
|
||||
{
|
||||
JSContext* cx = JS_NewContext(sContextHeapSize);
|
||||
JSContext* cx = JS_NewContext(sContextHeapSize + aExtraHeapSize);
|
||||
if (NS_WARN_IF(!cx))
|
||||
return nullptr;
|
||||
|
||||
|
@ -598,7 +599,7 @@ class JSContextWrapper
|
|||
}
|
||||
|
||||
private:
|
||||
static const unsigned sContextHeapSize = 4 << 20; // 4 MB
|
||||
static const uint32_t sContextHeapSize = 4 << 20; // 4 MB
|
||||
|
||||
JSContext *mContext;
|
||||
JS::PersistentRooted<JSObject*> mGlobal;
|
||||
|
@ -676,12 +677,14 @@ ProxyAutoConfig::SetThreadLocalIndex(uint32_t index)
|
|||
nsresult
|
||||
ProxyAutoConfig::Init(const nsCString &aPACURI,
|
||||
const nsCString &aPACScript,
|
||||
bool aIncludePath)
|
||||
bool aIncludePath,
|
||||
uint32_t aExtraHeapSize)
|
||||
{
|
||||
mPACURI = aPACURI;
|
||||
mPACScript = sPacUtils;
|
||||
mPACScript.Append(aPACScript);
|
||||
mIncludePath = aIncludePath;
|
||||
mExtraHeapSize = aExtraHeapSize;
|
||||
|
||||
if (!GetRunning())
|
||||
return SetupJS();
|
||||
|
@ -704,7 +707,7 @@ ProxyAutoConfig::SetupJS()
|
|||
|
||||
NS_GetCurrentThread()->SetCanInvokeJS(true);
|
||||
|
||||
mJSContext = JSContextWrapper::Create();
|
||||
mJSContext = JSContextWrapper::Create(mExtraHeapSize);
|
||||
if (!mJSContext)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
|
|
|
@ -31,7 +31,8 @@ public:
|
|||
|
||||
nsresult Init(const nsCString &aPACURI,
|
||||
const nsCString &aPACScript,
|
||||
bool aIncludePath);
|
||||
bool aIncludePath,
|
||||
uint32_t aExtraHeapSize);
|
||||
void SetThreadLocalIndex(uint32_t index);
|
||||
void Shutdown();
|
||||
void GC();
|
||||
|
@ -94,6 +95,7 @@ private:
|
|||
nsCString mPACScript;
|
||||
nsCString mPACURI;
|
||||
bool mIncludePath;
|
||||
uint32_t mExtraHeapSize;
|
||||
nsCString mRunningHost;
|
||||
nsCOMPtr<nsITimer> mTimer;
|
||||
};
|
||||
|
|
|
@ -8,6 +8,20 @@ interface nsITabParent;
|
|||
interface nsIChannel;
|
||||
interface nsIAsyncVerifyRedirectCallback;
|
||||
|
||||
[builtinclass, uuid(01987690-48cf-45de-bae3-e143c2adc2a8)]
|
||||
interface nsIAsyncVerifyRedirectReadyCallback : nsISupports
|
||||
{
|
||||
/**
|
||||
* Asynchronous callback when redirected channel finishes the preparation for
|
||||
* completing the verification procedure.
|
||||
*
|
||||
* @param result
|
||||
* SUCCEEDED if preparation for redirection verification succceed.
|
||||
* If FAILED the redirection must be aborted.
|
||||
*/
|
||||
void readyToVerify(in nsresult result);
|
||||
};
|
||||
|
||||
/**
|
||||
* Implemented by chrome side of IPC protocols that support redirect responses.
|
||||
*/
|
||||
|
@ -33,6 +47,17 @@ interface nsIParentRedirectingChannel : nsIParentChannel
|
|||
in uint32_t redirectFlags,
|
||||
in nsIAsyncVerifyRedirectCallback callback);
|
||||
|
||||
/**
|
||||
* Called to new channel when the original channel got Redirect2Verify
|
||||
* response from child. Callback will be invoked when the new channel
|
||||
* finishes the preparation for Redirect2Verify and can be called immediately.
|
||||
*
|
||||
* @param callback
|
||||
* redirect ready callback, will be called when redirect verification
|
||||
* procedure can proceed.
|
||||
*/
|
||||
void continueVerification(in nsIAsyncVerifyRedirectReadyCallback callback);
|
||||
|
||||
/**
|
||||
* Called after we are done with redirecting process and we know if to
|
||||
* redirect or not. Forward the redirect result to the child process. From
|
||||
|
|
|
@ -50,6 +50,32 @@ HttpRequestSucceeded(nsIStreamLoader *loader)
|
|||
return result;
|
||||
}
|
||||
|
||||
// Read preference setting of extra JavaScript context heap size.
|
||||
// PrefService tends to be run on main thread, where ProxyAutoConfig runs on
|
||||
// ProxyResolution thread, so it's read here and passed to ProxyAutoConfig.
|
||||
static uint32_t
|
||||
GetExtraJSContextHeapSize()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
static int32_t extraSize = -1;
|
||||
|
||||
if (extraSize < 0) {
|
||||
nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
|
||||
int32_t value;
|
||||
|
||||
if (prefs && NS_SUCCEEDED(prefs->GetIntPref(
|
||||
"network.proxy.autoconfig_extra_jscontext_heap_size", &value))) {
|
||||
LOG(("autoconfig_extra_jscontext_heap_size: %d\n", value));
|
||||
|
||||
extraSize = value;
|
||||
}
|
||||
}
|
||||
|
||||
return extraSize < 0 ? 0 : extraSize;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// The ExecuteCallback runnable is triggered by
|
||||
|
@ -180,6 +206,7 @@ public:
|
|||
, mCancel(false)
|
||||
, mCancelStatus(NS_OK)
|
||||
, mSetupPAC(false)
|
||||
, mExtraHeapSize(0)
|
||||
{ }
|
||||
|
||||
void CancelQueue (nsresult status)
|
||||
|
@ -188,11 +215,15 @@ public:
|
|||
mCancelStatus = status;
|
||||
}
|
||||
|
||||
void SetupPAC (const char *text, uint32_t datalen, nsCString &pacURI)
|
||||
void SetupPAC (const char *text,
|
||||
uint32_t datalen,
|
||||
nsCString &pacURI,
|
||||
uint32_t extraHeapSize)
|
||||
{
|
||||
mSetupPAC = true;
|
||||
mSetupPACData.Assign(text, datalen);
|
||||
mSetupPACURI = pacURI;
|
||||
mExtraHeapSize = extraHeapSize;
|
||||
}
|
||||
|
||||
NS_IMETHOD Run() override
|
||||
|
@ -209,7 +240,8 @@ public:
|
|||
|
||||
mPACMan->mPAC.Init(mSetupPACURI,
|
||||
mSetupPACData,
|
||||
mPACMan->mIncludePath);
|
||||
mPACMan->mIncludePath,
|
||||
mExtraHeapSize);
|
||||
|
||||
RefPtr<PACLoadComplete> runnable = new PACLoadComplete(mPACMan);
|
||||
NS_DispatchToMainThread(runnable);
|
||||
|
@ -227,6 +259,7 @@ private:
|
|||
nsresult mCancelStatus;
|
||||
|
||||
bool mSetupPAC;
|
||||
uint32_t mExtraHeapSize;
|
||||
nsCString mSetupPACData;
|
||||
nsCString mSetupPACURI;
|
||||
};
|
||||
|
@ -671,7 +704,7 @@ nsPACMan::OnStreamComplete(nsIStreamLoader *loader,
|
|||
|
||||
RefPtr<ExecutePACThreadAction> pending =
|
||||
new ExecutePACThreadAction(this);
|
||||
pending->SetupPAC(text, dataLen, pacURI);
|
||||
pending->SetupPAC(text, dataLen, pacURI, GetExtraJSContextHeapSize());
|
||||
if (mPACThread)
|
||||
mPACThread->Dispatch(pending, nsIEventTarget::DISPATCH_NORMAL);
|
||||
|
||||
|
|
|
@ -637,6 +637,18 @@
|
|||
{0x97, 0xa7, 0x06, 0xaf, 0x5e, 0x6d, 0x84, 0xc4} \
|
||||
}
|
||||
|
||||
// Background channel registrar used for pairing HttpChannelParent
|
||||
// and its background channel
|
||||
#define NS_BACKGROUNDCHANNELREGISTRAR_CONTRACTID \
|
||||
"@mozilla.org/network/background-channel-registrar;1"
|
||||
#define NS_BACKGROUNDCHANNELREGISTRAR_CID \
|
||||
{ /* 6907788a-17cc-4c2a-a7c5-59ad2d9cc079 */ \
|
||||
0x6907788a, \
|
||||
0x17cc, \
|
||||
0x4c2a, \
|
||||
{ 0xa7, 0xc5, 0x59, 0xad, 0x2d, 0x9c, 0xc0, 0x79} \
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* netwerk/protocol/ftp/ classes
|
||||
*/
|
||||
|
|
|
@ -267,6 +267,7 @@ NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsFtpProtocolHandler, Init)
|
|||
#include "nsHttpNTLMAuth.h"
|
||||
#include "nsHttpActivityDistributor.h"
|
||||
#include "ThrottleQueue.h"
|
||||
#include "BackgroundChannelRegistrar.h"
|
||||
#undef LOG
|
||||
#undef LOG_ENABLED
|
||||
namespace mozilla {
|
||||
|
@ -280,6 +281,7 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsHttpActivityDistributor)
|
|||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsHttpBasicAuth)
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsHttpDigestAuth)
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(ThrottleQueue)
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(BackgroundChannelRegistrar)
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
||||
#endif // !NECKO_PROTOCOL_http
|
||||
|
@ -805,6 +807,7 @@ NS_DEFINE_NAMED_CID(NS_HTTPAUTHMANAGER_CID);
|
|||
NS_DEFINE_NAMED_CID(NS_HTTPCHANNELAUTHPROVIDER_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_HTTPACTIVITYDISTRIBUTOR_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_THROTTLEQUEUE_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_BACKGROUNDCHANNELREGISTRAR_CID);
|
||||
#endif // !NECKO_PROTOCOL_http
|
||||
#ifdef NECKO_PROTOCOL_ftp
|
||||
NS_DEFINE_NAMED_CID(NS_FTPPROTOCOLHANDLER_CID);
|
||||
|
@ -956,6 +959,7 @@ static const mozilla::Module::CIDEntry kNeckoCIDs[] = {
|
|||
{ &kNS_HTTPCHANNELAUTHPROVIDER_CID, false, nullptr, mozilla::net::nsHttpChannelAuthProviderConstructor },
|
||||
{ &kNS_HTTPACTIVITYDISTRIBUTOR_CID, false, nullptr, mozilla::net::nsHttpActivityDistributorConstructor },
|
||||
{ &kNS_THROTTLEQUEUE_CID, false, nullptr, mozilla::net::ThrottleQueueConstructor },
|
||||
{ &kNS_BACKGROUNDCHANNELREGISTRAR_CID, false, nullptr, mozilla::net::BackgroundChannelRegistrarConstructor },
|
||||
#endif // !NECKO_PROTOCOL_http
|
||||
#ifdef NECKO_PROTOCOL_ftp
|
||||
{ &kNS_FTPPROTOCOLHANDLER_CID, false, nullptr, nsFtpProtocolHandlerConstructor },
|
||||
|
@ -1117,6 +1121,7 @@ static const mozilla::Module::ContractIDEntry kNeckoContracts[] = {
|
|||
{ NS_HTTPCHANNELAUTHPROVIDER_CONTRACTID, &kNS_HTTPCHANNELAUTHPROVIDER_CID },
|
||||
{ NS_HTTPACTIVITYDISTRIBUTOR_CONTRACTID, &kNS_HTTPACTIVITYDISTRIBUTOR_CID },
|
||||
{ NS_THROTTLEQUEUE_CONTRACTID, &kNS_THROTTLEQUEUE_CID },
|
||||
{ NS_BACKGROUNDCHANNELREGISTRAR_CONTRACTID, &kNS_BACKGROUNDCHANNELREGISTRAR_CID },
|
||||
#endif // !NECKO_PROTOCOL_http
|
||||
#ifdef NECKO_PROTOCOL_ftp
|
||||
{ NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "ftp", &kNS_FTPPROTOCOLHANDLER_CID },
|
||||
|
|
|
@ -0,0 +1,97 @@
|
|||
/* -*- 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 "BackgroundChannelRegistrar.h"
|
||||
|
||||
#include "HttpBackgroundChannelParent.h"
|
||||
#include "HttpChannelParent.h"
|
||||
#include "nsIInterfaceRequestor.h"
|
||||
#include "nsXULAppAPI.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
NS_IMPL_ISUPPORTS(BackgroundChannelRegistrar, nsIBackgroundChannelRegistrar)
|
||||
|
||||
BackgroundChannelRegistrar::BackgroundChannelRegistrar()
|
||||
{
|
||||
// BackgroundChannelRegistrar is a main-thread-only object.
|
||||
// All the operations should be run on main thread.
|
||||
// It should be used on chrome process only.
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
}
|
||||
|
||||
BackgroundChannelRegistrar::~BackgroundChannelRegistrar()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
}
|
||||
|
||||
void
|
||||
BackgroundChannelRegistrar::NotifyChannelLinked(
|
||||
HttpChannelParent* aChannelParent,
|
||||
HttpBackgroundChannelParent* aBgParent)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(aChannelParent);
|
||||
MOZ_ASSERT(aBgParent);
|
||||
|
||||
aBgParent->LinkToChannel(aChannelParent);
|
||||
aChannelParent->OnBackgroundParentReady(aBgParent);
|
||||
}
|
||||
|
||||
// nsIBackgroundChannelRegistrar
|
||||
void
|
||||
BackgroundChannelRegistrar::DeleteChannel(uint64_t aKey)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
mChannels.Remove(aKey);
|
||||
mBgChannels.Remove(aKey);
|
||||
}
|
||||
|
||||
void
|
||||
BackgroundChannelRegistrar::LinkHttpChannel(
|
||||
uint64_t aKey,
|
||||
HttpChannelParent* aChannel)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(aChannel);
|
||||
|
||||
RefPtr<HttpBackgroundChannelParent> bgParent;
|
||||
bool found = mBgChannels.Remove(aKey, getter_AddRefs(bgParent));
|
||||
|
||||
if (!found) {
|
||||
mChannels.Put(aKey, aChannel);
|
||||
return;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(bgParent);
|
||||
NotifyChannelLinked(aChannel, bgParent);
|
||||
}
|
||||
|
||||
void
|
||||
BackgroundChannelRegistrar::LinkBackgroundChannel(
|
||||
uint64_t aKey,
|
||||
HttpBackgroundChannelParent* aBgChannel)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(aBgChannel);
|
||||
|
||||
RefPtr<HttpChannelParent> parent;
|
||||
bool found = mChannels.Remove(aKey, getter_AddRefs(parent));
|
||||
|
||||
if (!found) {
|
||||
mBgChannels.Put(aKey, aBgChannel);
|
||||
return;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(parent);
|
||||
NotifyChannelLinked(parent, aBgChannel);
|
||||
}
|
||||
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
|
@ -0,0 +1,52 @@
|
|||
/* -*- 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_net_BackgroundChannelRegistrar_h__
|
||||
#define mozilla_net_BackgroundChannelRegistrar_h__
|
||||
|
||||
#include "nsIBackgroundChannelRegistrar.h"
|
||||
#include "nsRefPtrHashtable.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
class HttpBackgroundChannelParent;
|
||||
class HttpChannelParent;
|
||||
|
||||
class BackgroundChannelRegistrar final : public nsIBackgroundChannelRegistrar
|
||||
{
|
||||
typedef nsRefPtrHashtable<nsUint64HashKey, HttpChannelParent>
|
||||
ChannelHashtable;
|
||||
typedef nsRefPtrHashtable<nsUint64HashKey, HttpBackgroundChannelParent>
|
||||
BackgroundChannelHashtable;
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIBACKGROUNDCHANNELREGISTRAR
|
||||
|
||||
explicit BackgroundChannelRegistrar();
|
||||
|
||||
private:
|
||||
virtual ~BackgroundChannelRegistrar();
|
||||
|
||||
// A helper function for BackgroundChannelRegistrar itself to callback
|
||||
// HttpChannelParent and HttpBackgroundChannelParent when both objects are
|
||||
// ready. aChannelParent and aBgParent is the pair of HttpChannelParent and
|
||||
// HttpBackgroundChannelParent that should be linked together.
|
||||
void NotifyChannelLinked(HttpChannelParent* aChannelParent,
|
||||
HttpBackgroundChannelParent* aBgParent);
|
||||
|
||||
// Store unlinked HttpChannelParent objects.
|
||||
ChannelHashtable mChannels;
|
||||
|
||||
// Store unlinked HttpBackgroundChannelParent objects.
|
||||
BackgroundChannelHashtable mBgChannels;
|
||||
|
||||
};
|
||||
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_net_BackgroundChannelRegistrar_h__
|
|
@ -3,6 +3,7 @@
|
|||
/* 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 "HttpLog.h"
|
||||
|
||||
#include "nsHttp.h"
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "nsIInterfaceRequestor.h"
|
||||
#include "nsIStreamListener.h"
|
||||
#include "nsIThreadRetargetableStreamListener.h"
|
||||
#include "nsITimer.h"
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
|
||||
|
|
|
@ -997,7 +997,7 @@ Http2Session::VerifyStream(Http2Stream *aStream, uint32_t aOptionalID = 0)
|
|||
#ifndef DEBUG
|
||||
// Only do the real verification in debug builds
|
||||
return true;
|
||||
#endif
|
||||
#else //DEBUG
|
||||
|
||||
if (!aStream)
|
||||
return true;
|
||||
|
@ -1043,6 +1043,7 @@ Http2Session::VerifyStream(Http2Stream *aStream, uint32_t aOptionalID = 0)
|
|||
|
||||
MOZ_ASSERT(false, "VerifyStream");
|
||||
return false;
|
||||
#endif //DEBUG
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -0,0 +1,443 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set sw=2 ts=8 et 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/. */
|
||||
|
||||
// HttpLog.h should generally be included first
|
||||
#include "HttpLog.h"
|
||||
|
||||
#include "HttpBackgroundChannelChild.h"
|
||||
|
||||
#include "HttpChannelChild.h"
|
||||
#include "MainThreadUtils.h"
|
||||
#include "mozilla/ipc/BackgroundChild.h"
|
||||
#include "mozilla/ipc/PBackgroundChild.h"
|
||||
#include "mozilla/IntegerPrintfMacros.h"
|
||||
#include "mozilla/Unused.h"
|
||||
#include "nsIIPCBackgroundChildCreateCallback.h"
|
||||
|
||||
using mozilla::ipc::BackgroundChild;
|
||||
using mozilla::ipc::IPCResult;
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
// Callbacks for PBackgroundChild creation
|
||||
class BackgroundChannelCreateCallback final
|
||||
: public nsIIPCBackgroundChildCreateCallback
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIIPCBACKGROUNDCHILDCREATECALLBACK
|
||||
|
||||
explicit BackgroundChannelCreateCallback(HttpBackgroundChannelChild* aBgChild)
|
||||
: mBgChild(aBgChild)
|
||||
{
|
||||
MOZ_ASSERT(aBgChild);
|
||||
}
|
||||
|
||||
private:
|
||||
virtual ~BackgroundChannelCreateCallback() { }
|
||||
|
||||
RefPtr<HttpBackgroundChannelChild> mBgChild;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS(BackgroundChannelCreateCallback,
|
||||
nsIIPCBackgroundChildCreateCallback)
|
||||
|
||||
void
|
||||
BackgroundChannelCreateCallback::ActorCreated(PBackgroundChild* aActor)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(aActor);
|
||||
MOZ_ASSERT(mBgChild);
|
||||
|
||||
if (!mBgChild->mChannelChild) {
|
||||
// HttpChannelChild is closed during PBackground creation,
|
||||
// abort the rest of steps.
|
||||
return;
|
||||
}
|
||||
|
||||
const uint64_t channelId = mBgChild->mChannelChild->ChannelId();
|
||||
if (!aActor->SendPHttpBackgroundChannelConstructor(mBgChild,
|
||||
channelId)) {
|
||||
ActorFailed();
|
||||
return;
|
||||
}
|
||||
|
||||
// hold extra reference for IPDL
|
||||
RefPtr<HttpBackgroundChannelChild> child = mBgChild;
|
||||
Unused << child.forget().take();
|
||||
}
|
||||
|
||||
void
|
||||
BackgroundChannelCreateCallback::ActorFailed()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(mBgChild);
|
||||
|
||||
mBgChild->OnBackgroundChannelCreationFailed();
|
||||
}
|
||||
|
||||
// HttpBackgroundChannelChild
|
||||
HttpBackgroundChannelChild::HttpBackgroundChannelChild()
|
||||
{
|
||||
}
|
||||
|
||||
HttpBackgroundChannelChild::~HttpBackgroundChannelChild()
|
||||
{
|
||||
}
|
||||
|
||||
nsresult
|
||||
HttpBackgroundChannelChild::Init(HttpChannelChild* aChannelChild)
|
||||
{
|
||||
LOG(("HttpBackgroundChannelChild::Init [this=%p httpChannel=%p channelId=%"
|
||||
PRIu64 "]\n", this, aChannelChild, aChannelChild->ChannelId()));
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
NS_ENSURE_ARG(aChannelChild);
|
||||
|
||||
mChannelChild = aChannelChild;
|
||||
|
||||
if (NS_WARN_IF(!CreateBackgroundChannel())) {
|
||||
mChannelChild = nullptr;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
HttpBackgroundChannelChild::OnChannelClosed()
|
||||
{
|
||||
LOG(("HttpBackgroundChannelChild::OnChannelClosed [this=%p]\n", this));
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
// HttpChannelChild is not going to handle any incoming message.
|
||||
mChannelChild = nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
HttpBackgroundChannelChild::OnStartRequestReceived()
|
||||
{
|
||||
LOG(("HttpBackgroundChannelChild::OnStartRequestReceived [this=%p]\n", this));
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(mChannelChild);
|
||||
MOZ_ASSERT(!mStartReceived); // Should only be called once.
|
||||
|
||||
mStartReceived = true;
|
||||
|
||||
nsTArray<nsCOMPtr<nsIRunnable>> runnables;
|
||||
runnables.SwapElements(mQueuedRunnables);
|
||||
|
||||
for (auto event : runnables) {
|
||||
// Note: these runnables call Recv* methods on HttpBackgroundChannelChild
|
||||
// but not the Process* methods on HttpChannelChild.
|
||||
event->Run();
|
||||
}
|
||||
|
||||
// Ensure no new message is enqueued.
|
||||
MOZ_ASSERT(mQueuedRunnables.IsEmpty());
|
||||
}
|
||||
|
||||
void
|
||||
HttpBackgroundChannelChild::OnBackgroundChannelCreationFailed()
|
||||
{
|
||||
LOG(("HttpBackgroundChannelChild::OnBackgroundChannelCreationFailed"
|
||||
" [this=%p]\n", this));
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (mChannelChild) {
|
||||
RefPtr<HttpChannelChild> channelChild = mChannelChild.forget();
|
||||
channelChild->FailedAsyncOpen(NS_ERROR_UNEXPECTED);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
HttpBackgroundChannelChild::CreateBackgroundChannel()
|
||||
{
|
||||
LOG(("HttpBackgroundChannelChild::CreateBackgroundChannel [this=%p]\n", this));
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
RefPtr<BackgroundChannelCreateCallback> callback =
|
||||
new BackgroundChannelCreateCallback(this);
|
||||
|
||||
return BackgroundChild::GetOrCreateForCurrentThread(callback);
|
||||
}
|
||||
|
||||
bool
|
||||
HttpBackgroundChannelChild::IsWaitingOnStartRequest()
|
||||
{
|
||||
// Need to wait for OnStartRequest if it is sent by
|
||||
// parent process but not received by content process.
|
||||
return (mStartSent && !mStartReceived);
|
||||
}
|
||||
|
||||
// PHttpBackgroundChannelChild
|
||||
IPCResult
|
||||
HttpBackgroundChannelChild::RecvOnStartRequestSent()
|
||||
{
|
||||
LOG(("HttpBackgroundChannelChild::RecvOnStartRequestSent [this=%p]\n", this));
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(!mStartSent); // Should only receive this message once.
|
||||
|
||||
mStartSent = true;
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
IPCResult
|
||||
HttpBackgroundChannelChild::RecvOnTransportAndData(
|
||||
const nsresult& aChannelStatus,
|
||||
const nsresult& aTransportStatus,
|
||||
const uint64_t& aOffset,
|
||||
const uint32_t& aCount,
|
||||
const nsCString& aData)
|
||||
{
|
||||
LOG(("HttpBackgroundChannelChild::RecvOnTransportAndData [this=%p]\n", this));
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (NS_WARN_IF(!mChannelChild)) {
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
if (IsWaitingOnStartRequest()) {
|
||||
LOG((" > pending until OnStartRequest [offset=%" PRIu64 " count=%" PRIu32
|
||||
"]\n", aOffset, aCount));
|
||||
|
||||
mQueuedRunnables.AppendElement(
|
||||
NewRunnableMethod<const nsresult, const nsresult, const uint64_t,
|
||||
const uint32_t, const nsCString>(
|
||||
this, &HttpBackgroundChannelChild::RecvOnTransportAndData,
|
||||
aChannelStatus, aTransportStatus, aOffset,
|
||||
aCount, aData));
|
||||
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mChannelChild->ProcessOnTransportAndData(aChannelStatus,
|
||||
aTransportStatus,
|
||||
aOffset,
|
||||
aCount,
|
||||
aData);
|
||||
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
IPCResult
|
||||
HttpBackgroundChannelChild::RecvOnStopRequest(
|
||||
const nsresult& aChannelStatus,
|
||||
const ResourceTimingStruct& aTiming)
|
||||
{
|
||||
LOG(("HttpBackgroundChannelChild::RecvOnStopRequest [this=%p]\n", this));
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (NS_WARN_IF(!mChannelChild)) {
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
if (IsWaitingOnStartRequest()) {
|
||||
LOG((" > pending until OnStartRequest [status=%" PRIx32 "]\n",
|
||||
static_cast<uint32_t>(aChannelStatus)));
|
||||
|
||||
mQueuedRunnables.AppendElement(
|
||||
NewRunnableMethod<const nsresult, const ResourceTimingStruct>(
|
||||
this, &HttpBackgroundChannelChild::RecvOnStopRequest,
|
||||
aChannelStatus, aTiming));
|
||||
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mChannelChild->ProcessOnStopRequest(aChannelStatus, aTiming);
|
||||
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
IPCResult
|
||||
HttpBackgroundChannelChild::RecvOnProgress(const int64_t& aProgress,
|
||||
const int64_t& aProgressMax)
|
||||
{
|
||||
LOG(("HttpBackgroundChannelChild::RecvOnProgress [this=%p progress=%"
|
||||
PRId64 " max=%" PRId64 "]\n", this, aProgress, aProgressMax));
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (NS_WARN_IF(!mChannelChild)) {
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
if (IsWaitingOnStartRequest()) {
|
||||
LOG((" > pending until OnStartRequest [progress=%" PRId64 " max=%"
|
||||
PRId64 "]\n", aProgress, aProgressMax));
|
||||
|
||||
mQueuedRunnables.AppendElement(
|
||||
NewRunnableMethod<const int64_t, const int64_t>(
|
||||
this, &HttpBackgroundChannelChild::RecvOnProgress,
|
||||
aProgress, aProgressMax));
|
||||
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mChannelChild->ProcessOnProgress(aProgress, aProgressMax);
|
||||
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
IPCResult
|
||||
HttpBackgroundChannelChild::RecvOnStatus(const nsresult& aStatus)
|
||||
{
|
||||
LOG(("HttpBackgroundChannelChild::RecvOnStatus [this=%p status=%"
|
||||
PRIx32 "]\n", this, static_cast<uint32_t>(aStatus)));
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (NS_WARN_IF(!mChannelChild)) {
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
if (IsWaitingOnStartRequest()) {
|
||||
LOG((" > pending until OnStartRequest [status=%" PRIx32 "]\n",
|
||||
static_cast<uint32_t>(aStatus)));
|
||||
|
||||
mQueuedRunnables.AppendElement(
|
||||
NewRunnableMethod<const nsresult>(
|
||||
this, &HttpBackgroundChannelChild::RecvOnStatus, aStatus));
|
||||
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mChannelChild->ProcessOnStatus(aStatus);
|
||||
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
IPCResult
|
||||
HttpBackgroundChannelChild::RecvFlushedForDiversion()
|
||||
{
|
||||
LOG(("HttpBackgroundChannelChild::RecvFlushedForDiversion [this=%p]\n", this));
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (NS_WARN_IF(!mChannelChild)) {
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
if (IsWaitingOnStartRequest()) {
|
||||
LOG((" > pending until OnStartRequest\n"));
|
||||
|
||||
mQueuedRunnables.AppendElement(
|
||||
NewRunnableMethod(this, &HttpBackgroundChannelChild::RecvFlushedForDiversion));
|
||||
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mChannelChild->ProcessFlushedForDiversion();
|
||||
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
IPCResult
|
||||
HttpBackgroundChannelChild::RecvDivertMessages()
|
||||
{
|
||||
LOG(("HttpBackgroundChannelChild::RecvDivertMessages [this=%p]\n", this));
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (NS_WARN_IF(!mChannelChild)) {
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
if (IsWaitingOnStartRequest()) {
|
||||
LOG((" > pending until OnStartRequest\n"));
|
||||
|
||||
mQueuedRunnables.AppendElement(
|
||||
NewRunnableMethod(this, &HttpBackgroundChannelChild::RecvDivertMessages));
|
||||
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mChannelChild->ProcessDivertMessages();
|
||||
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
IPCResult
|
||||
HttpBackgroundChannelChild::RecvNotifyTrackingProtectionDisabled()
|
||||
{
|
||||
LOG(("HttpBackgroundChannelChild::RecvNotifyTrackingProtectionDisabled [this=%p]\n", this));
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (NS_WARN_IF(!mChannelChild)) {
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
// NotifyTrackingProtectionDisabled has no order dependency to OnStartRequest.
|
||||
// It this be handled as soon as possible
|
||||
mChannelChild->ProcessNotifyTrackingProtectionDisabled();
|
||||
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
IPCResult
|
||||
HttpBackgroundChannelChild::RecvNotifyTrackingResource()
|
||||
{
|
||||
LOG(("HttpBackgroundChannelChild::RecvNotifyTrackingResource [this=%p]\n", this));
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (NS_WARN_IF(!mChannelChild)) {
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
// NotifyTrackingResource has no order dependency to OnStartRequest.
|
||||
// It this be handled as soon as possible
|
||||
mChannelChild->ProcessNotifyTrackingResource();
|
||||
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
IPCResult
|
||||
HttpBackgroundChannelChild::RecvSetClassifierMatchedInfo(const ClassifierInfo& info)
|
||||
{
|
||||
LOG(("HttpBackgroundChannelChild::RecvSetClassifierMatchedInfo [this=%p]\n", this));
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (NS_WARN_IF(!mChannelChild)) {
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
// SetClassifierMatchedInfo has no order dependency to OnStartRequest.
|
||||
// It this be handled as soon as possible
|
||||
mChannelChild->ProcessSetClassifierMatchedInfo(info.list(), info.provider(), info.prefix());
|
||||
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
void
|
||||
HttpBackgroundChannelChild::ActorDestroy(ActorDestroyReason aWhy)
|
||||
{
|
||||
LOG(("HttpBackgroundChannelChild::ActorDestroy[this=%p]\n", this));
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
// Ensure all IPC messages received before ActorDestroy can be
|
||||
// handled correctly. If there is any pending IPC message, destroyed
|
||||
// mChannelChild until those messages are flushed.
|
||||
if (!mQueuedRunnables.IsEmpty()) {
|
||||
LOG((" > pending until queued messages are flushed\n"));
|
||||
RefPtr<HttpBackgroundChannelChild> self = this;
|
||||
mQueuedRunnables.AppendElement(
|
||||
NS_NewRunnableFunction([self]() {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
RefPtr<HttpChannelChild> channelChild = self->mChannelChild.forget();
|
||||
|
||||
if (channelChild) {
|
||||
channelChild->OnBackgroundChildDestroyed();
|
||||
}
|
||||
}));
|
||||
return;
|
||||
}
|
||||
|
||||
if (mChannelChild) {
|
||||
RefPtr<HttpChannelChild> channelChild = mChannelChild.forget();
|
||||
|
||||
channelChild->OnBackgroundChildDestroyed();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
|
@ -0,0 +1,111 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set sw=2 ts=8 et 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_net_HttpBackgroundChannelChild_h
|
||||
#define mozilla_net_HttpBackgroundChannelChild_h
|
||||
|
||||
#include "mozilla/net/PHttpBackgroundChannelChild.h"
|
||||
#include "nsIRunnable.h"
|
||||
#include "nsTArray.h"
|
||||
|
||||
using mozilla::ipc::IPCResult;
|
||||
using mozilla::dom::ClassifierInfo;
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
class HttpChannelChild;
|
||||
|
||||
class HttpBackgroundChannelChild final : public PHttpBackgroundChannelChild
|
||||
{
|
||||
friend class BackgroundChannelCreateCallback;
|
||||
public:
|
||||
explicit HttpBackgroundChannelChild();
|
||||
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(HttpBackgroundChannelChild)
|
||||
|
||||
// Associate this background channel with a HttpChannelChild and
|
||||
// initiate the createion of the PBackground IPC channel.
|
||||
nsresult Init(HttpChannelChild* aChannelChild);
|
||||
|
||||
// Callback while the associated HttpChannelChild is not going to
|
||||
// handle any incoming messages over background channel.
|
||||
void OnChannelClosed();
|
||||
|
||||
// Callback when OnStartRequest is received and handled by HttpChannelChild.
|
||||
// Enqueued messages in background channel will be flushed.
|
||||
void OnStartRequestReceived();
|
||||
|
||||
// Callback while failed to create PBackground IPC channel.
|
||||
void OnBackgroundChannelCreationFailed();
|
||||
|
||||
protected:
|
||||
IPCResult RecvOnTransportAndData(const nsresult& aChannelStatus,
|
||||
const nsresult& aTransportStatus,
|
||||
const uint64_t& aOffset,
|
||||
const uint32_t& aCount,
|
||||
const nsCString& aData) override;
|
||||
|
||||
IPCResult RecvOnStopRequest(const nsresult& aChannelStatus,
|
||||
const ResourceTimingStruct& aTiming) override;
|
||||
|
||||
IPCResult RecvOnProgress(const int64_t& aProgress,
|
||||
const int64_t& aProgressMax) override;
|
||||
|
||||
IPCResult RecvOnStatus(const nsresult& aStatus) override;
|
||||
|
||||
IPCResult RecvFlushedForDiversion() override;
|
||||
|
||||
IPCResult RecvDivertMessages() override;
|
||||
|
||||
IPCResult RecvOnStartRequestSent() override;
|
||||
|
||||
IPCResult RecvNotifyTrackingProtectionDisabled() override;
|
||||
|
||||
IPCResult RecvNotifyTrackingResource() override;
|
||||
|
||||
IPCResult RecvSetClassifierMatchedInfo(const ClassifierInfo& info) override;
|
||||
|
||||
void ActorDestroy(ActorDestroyReason aWhy) override;
|
||||
|
||||
private:
|
||||
virtual ~HttpBackgroundChannelChild();
|
||||
|
||||
// Initiate the creation of the PBckground IPC channel.
|
||||
// Return false if failed.
|
||||
bool CreateBackgroundChannel();
|
||||
|
||||
// Check OnStartRequest is sent by parent process over main thread IPC
|
||||
// but not yet received on child process.
|
||||
// return true before RecvOnStartRequestSent is invoked.
|
||||
// return false if RecvOnStartRequestSent is invoked but not
|
||||
// OnStartRequestReceived.
|
||||
// return true after both RecvOnStartRequestSend and OnStartRequestReceived
|
||||
// are invoked.
|
||||
bool IsWaitingOnStartRequest();
|
||||
|
||||
// Associated HttpChannelChild for handling the channel events.
|
||||
// Will be removed while failed to create background channel,
|
||||
// destruction of the background channel, or explicitly dissociation
|
||||
// via OnChannelClosed callback.
|
||||
RefPtr<HttpChannelChild> mChannelChild;
|
||||
|
||||
// True if OnStartRequest is received by HttpChannelChild.
|
||||
bool mStartReceived = false;
|
||||
|
||||
// True if OnStartRequest is sent by HttpChannelParent.
|
||||
bool mStartSent = false;
|
||||
|
||||
// Store pending messages that require to be handled after OnStartRequest.
|
||||
// Should be flushed after OnStartRequest is received and handled.
|
||||
nsTArray<nsCOMPtr<nsIRunnable>> mQueuedRunnables;
|
||||
};
|
||||
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_net_HttpBackgroundChannelChild_h
|
|
@ -0,0 +1,411 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set sw=2 ts=8 et 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/. */
|
||||
|
||||
// HttpLog.h should generally be included first
|
||||
#include "HttpLog.h"
|
||||
|
||||
#include "HttpBackgroundChannelParent.h"
|
||||
|
||||
#include "HttpChannelParent.h"
|
||||
#include "mozilla/ipc/BackgroundParent.h"
|
||||
#include "mozilla/IntegerPrintfMacros.h"
|
||||
#include "mozilla/Unused.h"
|
||||
#include "nsIBackgroundChannelRegistrar.h"
|
||||
#include "nsNetCID.h"
|
||||
#include "nsQueryObject.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
using mozilla::dom::ContentParent;
|
||||
using mozilla::ipc::AssertIsInMainProcess;
|
||||
using mozilla::ipc::AssertIsOnBackgroundThread;
|
||||
using mozilla::ipc::BackgroundParent;
|
||||
using mozilla::ipc::IPCResult;
|
||||
using mozilla::ipc::IsOnBackgroundThread;
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
/*
|
||||
* Helper class for continuing the AsyncOpen procedure on main thread.
|
||||
*/
|
||||
class ContinueAsyncOpenRunnable final : public Runnable
|
||||
{
|
||||
public:
|
||||
ContinueAsyncOpenRunnable(HttpBackgroundChannelParent* aActor,
|
||||
const uint64_t& aChannelId)
|
||||
: mActor(aActor)
|
||||
, mChannelId(aChannelId)
|
||||
{
|
||||
AssertIsInMainProcess();
|
||||
AssertIsOnBackgroundThread();
|
||||
MOZ_ASSERT(mActor);
|
||||
}
|
||||
|
||||
NS_IMETHOD Run() override
|
||||
{
|
||||
LOG(("HttpBackgroundChannelParent::ContinueAsyncOpen [this=%p channelId=%"
|
||||
PRIu64 "]\n", mActor.get(), mChannelId));
|
||||
AssertIsInMainProcess();
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
nsCOMPtr<nsIBackgroundChannelRegistrar> registrar =
|
||||
do_GetService(NS_BACKGROUNDCHANNELREGISTRAR_CONTRACTID);
|
||||
MOZ_ASSERT(registrar);
|
||||
|
||||
registrar->LinkBackgroundChannel(mChannelId, mActor);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
RefPtr<HttpBackgroundChannelParent> mActor;
|
||||
const uint64_t mChannelId;
|
||||
};
|
||||
|
||||
HttpBackgroundChannelParent::HttpBackgroundChannelParent()
|
||||
: mIPCOpened(true)
|
||||
, mBackgroundThread(NS_GetCurrentThread())
|
||||
{
|
||||
AssertIsInMainProcess();
|
||||
AssertIsOnBackgroundThread();
|
||||
}
|
||||
|
||||
HttpBackgroundChannelParent::~HttpBackgroundChannelParent()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread() || IsOnBackgroundThread());
|
||||
MOZ_ASSERT(!mIPCOpened);
|
||||
}
|
||||
|
||||
nsresult
|
||||
HttpBackgroundChannelParent::Init(const uint64_t& aChannelId)
|
||||
{
|
||||
LOG(("HttpBackgroundChannelParent::Init [this=%p channelId=%" PRIu64 "]\n",
|
||||
this, aChannelId));
|
||||
AssertIsInMainProcess();
|
||||
AssertIsOnBackgroundThread();
|
||||
|
||||
RefPtr<ContinueAsyncOpenRunnable> runnable =
|
||||
new ContinueAsyncOpenRunnable(this, aChannelId);
|
||||
|
||||
return NS_DispatchToMainThread(runnable);
|
||||
}
|
||||
|
||||
void
|
||||
HttpBackgroundChannelParent::LinkToChannel(HttpChannelParent* aChannelParent)
|
||||
{
|
||||
LOG(("HttpBackgroundChannelParent::LinkToChannel [this=%p channel=%p]\n",
|
||||
this, aChannelParent));
|
||||
AssertIsInMainProcess();
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
MOZ_DIAGNOSTIC_ASSERT(mIPCOpened);
|
||||
if (!mIPCOpened) {
|
||||
return;
|
||||
}
|
||||
|
||||
mChannelParent = aChannelParent;
|
||||
}
|
||||
|
||||
void
|
||||
HttpBackgroundChannelParent::OnChannelClosed()
|
||||
{
|
||||
LOG(("HttpBackgroundChannelParent::OnChannelClosed [this=%p]\n", this));
|
||||
AssertIsInMainProcess();
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (!mIPCOpened) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
|
||||
RefPtr<HttpBackgroundChannelParent> self = this;
|
||||
rv = mBackgroundThread->Dispatch(NS_NewRunnableFunction([self]() {
|
||||
LOG(("HttpBackgroundChannelParent::DeleteRunnable [this=%p]\n", self.get()));
|
||||
AssertIsOnBackgroundThread();
|
||||
|
||||
if (!self->mIPCOpened.compareExchange(true, false)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Unused << self->Send__delete__(self);
|
||||
}), NS_DISPATCH_NORMAL);
|
||||
|
||||
Unused << NS_WARN_IF(NS_FAILED(rv));
|
||||
}
|
||||
|
||||
bool
|
||||
HttpBackgroundChannelParent::OnStartRequestSent()
|
||||
{
|
||||
LOG(("HttpBackgroundChannelParent::OnStartRequestSent [this=%p]\n", this));
|
||||
AssertIsInMainProcess();
|
||||
|
||||
if (NS_WARN_IF(!mIPCOpened)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!IsOnBackgroundThread()) {
|
||||
nsresult rv = mBackgroundThread->Dispatch(
|
||||
NewRunnableMethod(this, &HttpBackgroundChannelParent::OnStartRequestSent),
|
||||
NS_DISPATCH_NORMAL);
|
||||
|
||||
MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
|
||||
|
||||
return NS_SUCCEEDED(rv);
|
||||
}
|
||||
|
||||
return SendOnStartRequestSent();
|
||||
}
|
||||
|
||||
bool
|
||||
HttpBackgroundChannelParent::OnTransportAndData(
|
||||
const nsresult& aChannelStatus,
|
||||
const nsresult& aTransportStatus,
|
||||
const uint64_t& aOffset,
|
||||
const uint32_t& aCount,
|
||||
const nsCString& aData)
|
||||
{
|
||||
LOG(("HttpBackgroundChannelParent::OnTransportAndData [this=%p]\n", this));
|
||||
AssertIsInMainProcess();
|
||||
|
||||
if (NS_WARN_IF(!mIPCOpened)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!IsOnBackgroundThread()) {
|
||||
nsresult rv = mBackgroundThread->Dispatch(
|
||||
NewRunnableMethod<const nsresult, const nsresult, const uint64_t,
|
||||
const uint32_t, const nsCString>
|
||||
(this, &HttpBackgroundChannelParent::OnTransportAndData,
|
||||
aChannelStatus, aTransportStatus, aOffset, aCount, aData),
|
||||
NS_DISPATCH_NORMAL);
|
||||
|
||||
MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
|
||||
|
||||
return NS_SUCCEEDED(rv);
|
||||
}
|
||||
|
||||
return SendOnTransportAndData(aChannelStatus, aTransportStatus,
|
||||
aOffset, aCount, aData);
|
||||
}
|
||||
|
||||
bool
|
||||
HttpBackgroundChannelParent::OnStopRequest(const nsresult& aChannelStatus,
|
||||
const ResourceTimingStruct& aTiming)
|
||||
{
|
||||
LOG(("HttpBackgroundChannelParent::OnStopRequest [this=%p "
|
||||
"status=%" PRIx32 "]\n", this, static_cast<uint32_t>(aChannelStatus)));
|
||||
AssertIsInMainProcess();
|
||||
|
||||
if (NS_WARN_IF(!mIPCOpened)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!IsOnBackgroundThread()) {
|
||||
nsresult rv = mBackgroundThread->Dispatch(
|
||||
NewRunnableMethod<const nsresult, const ResourceTimingStruct>
|
||||
(this, &HttpBackgroundChannelParent::OnStopRequest,
|
||||
aChannelStatus, aTiming),
|
||||
NS_DISPATCH_NORMAL);
|
||||
|
||||
MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
|
||||
|
||||
return NS_SUCCEEDED(rv);
|
||||
}
|
||||
|
||||
return SendOnStopRequest(aChannelStatus, aTiming);
|
||||
}
|
||||
|
||||
bool
|
||||
HttpBackgroundChannelParent::OnProgress(const int64_t& aProgress,
|
||||
const int64_t& aProgressMax)
|
||||
{
|
||||
LOG(("HttpBackgroundChannelParent::OnProgress [this=%p progress=%" PRId64
|
||||
" max=%" PRId64 "]\n", this, aProgress, aProgressMax));
|
||||
AssertIsInMainProcess();
|
||||
|
||||
if (NS_WARN_IF(!mIPCOpened)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!IsOnBackgroundThread()) {
|
||||
nsresult rv = mBackgroundThread->Dispatch(
|
||||
NewRunnableMethod<const int64_t, const int64_t>
|
||||
(this, &HttpBackgroundChannelParent::OnProgress,
|
||||
aProgress, aProgressMax),
|
||||
NS_DISPATCH_NORMAL);
|
||||
|
||||
MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
|
||||
|
||||
return NS_SUCCEEDED(rv);
|
||||
}
|
||||
|
||||
return SendOnProgress(aProgress, aProgressMax);
|
||||
}
|
||||
|
||||
bool
|
||||
HttpBackgroundChannelParent::OnStatus(const nsresult& aStatus)
|
||||
{
|
||||
LOG(("HttpBackgroundChannelParent::OnStatus [this=%p stauts=%" PRIx32
|
||||
"]\n", this, static_cast<uint32_t>(aStatus)));
|
||||
AssertIsInMainProcess();
|
||||
|
||||
if (NS_WARN_IF(!mIPCOpened)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!IsOnBackgroundThread()) {
|
||||
nsresult rv = mBackgroundThread->Dispatch(
|
||||
NewRunnableMethod<const nsresult>
|
||||
(this, &HttpBackgroundChannelParent::OnStatus, aStatus),
|
||||
NS_DISPATCH_NORMAL);
|
||||
|
||||
MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
|
||||
|
||||
return NS_SUCCEEDED(rv);
|
||||
}
|
||||
|
||||
return SendOnStatus(aStatus);
|
||||
}
|
||||
|
||||
bool
|
||||
HttpBackgroundChannelParent::OnDiversion()
|
||||
{
|
||||
LOG(("HttpBackgroundChannelParent::OnDiversion [this=%p]\n", this));
|
||||
AssertIsInMainProcess();
|
||||
|
||||
if (NS_WARN_IF(!mIPCOpened)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!IsOnBackgroundThread()) {
|
||||
nsresult rv = mBackgroundThread->Dispatch(
|
||||
NewRunnableMethod(this, &HttpBackgroundChannelParent::OnDiversion),
|
||||
NS_DISPATCH_NORMAL);
|
||||
|
||||
MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
|
||||
|
||||
return NS_SUCCEEDED(rv);
|
||||
}
|
||||
|
||||
if (!SendFlushedForDiversion()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// The listener chain should now be setup; tell HttpChannelChild to divert
|
||||
// the OnDataAvailables and OnStopRequest to associated HttpChannelParent.
|
||||
if (!SendDivertMessages()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
HttpBackgroundChannelParent::OnNotifyTrackingProtectionDisabled()
|
||||
{
|
||||
LOG(("HttpBackgroundChannelParent::OnNotifyTrackingProtectionDisabled [this=%p]\n", this));
|
||||
AssertIsInMainProcess();
|
||||
|
||||
if (NS_WARN_IF(!mIPCOpened)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!IsOnBackgroundThread()) {
|
||||
nsresult rv = mBackgroundThread->Dispatch(
|
||||
NewRunnableMethod(this, &HttpBackgroundChannelParent::OnNotifyTrackingProtectionDisabled),
|
||||
NS_DISPATCH_NORMAL);
|
||||
|
||||
MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
|
||||
|
||||
return NS_SUCCEEDED(rv);
|
||||
}
|
||||
|
||||
return SendNotifyTrackingProtectionDisabled();
|
||||
}
|
||||
|
||||
bool
|
||||
HttpBackgroundChannelParent::OnNotifyTrackingResource()
|
||||
{
|
||||
LOG(("HttpBackgroundChannelParent::OnNotifyTrackingResource [this=%p]\n", this));
|
||||
AssertIsInMainProcess();
|
||||
|
||||
if (NS_WARN_IF(!mIPCOpened)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!IsOnBackgroundThread()) {
|
||||
nsresult rv = mBackgroundThread->Dispatch(
|
||||
NewRunnableMethod(this, &HttpBackgroundChannelParent::OnNotifyTrackingResource),
|
||||
NS_DISPATCH_NORMAL);
|
||||
|
||||
MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
|
||||
|
||||
return NS_SUCCEEDED(rv);
|
||||
}
|
||||
|
||||
return SendNotifyTrackingResource();
|
||||
}
|
||||
|
||||
bool
|
||||
HttpBackgroundChannelParent::OnSetClassifierMatchedInfo(
|
||||
const nsACString& aList,
|
||||
const nsACString& aProvider,
|
||||
const nsACString& aPrefix)
|
||||
{
|
||||
LOG(("HttpBackgroundChannelParent::OnSetClassifierMatchedInfo [this=%p]\n", this));
|
||||
AssertIsInMainProcess();
|
||||
|
||||
if (NS_WARN_IF(!mIPCOpened)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!IsOnBackgroundThread()) {
|
||||
nsresult rv = mBackgroundThread->Dispatch(
|
||||
NewRunnableMethod<const nsCString, const nsCString, const nsCString>
|
||||
(this, &HttpBackgroundChannelParent::OnSetClassifierMatchedInfo,
|
||||
aList, aProvider, aPrefix),
|
||||
NS_DISPATCH_NORMAL);
|
||||
|
||||
MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
|
||||
|
||||
return NS_SUCCEEDED(rv);
|
||||
}
|
||||
|
||||
ClassifierInfo info;
|
||||
info.list() = aList;
|
||||
info.prefix() = aPrefix;
|
||||
info.provider() = aProvider;
|
||||
|
||||
return SendSetClassifierMatchedInfo(info);
|
||||
}
|
||||
|
||||
void
|
||||
HttpBackgroundChannelParent::ActorDestroy(ActorDestroyReason aWhy)
|
||||
{
|
||||
LOG(("HttpBackgroundChannelParent::ActorDestroy [this=%p]\n", this));
|
||||
AssertIsInMainProcess();
|
||||
AssertIsOnBackgroundThread();
|
||||
|
||||
mIPCOpened = false;
|
||||
|
||||
RefPtr<HttpBackgroundChannelParent> self = this;
|
||||
DebugOnly<nsresult> rv =
|
||||
NS_DispatchToMainThread(NS_NewRunnableFunction([self]() {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
RefPtr<HttpChannelParent> channelParent =
|
||||
self->mChannelParent.forget();
|
||||
|
||||
if (channelParent) {
|
||||
channelParent->OnBackgroundParentDestroyed();
|
||||
}
|
||||
}));
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
||||
}
|
||||
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
|
@ -0,0 +1,95 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set sw=2 ts=8 et 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_net_HttpBackgroundChannelParent_h
|
||||
#define mozilla_net_HttpBackgroundChannelParent_h
|
||||
|
||||
#include "mozilla/net/PHttpBackgroundChannelParent.h"
|
||||
#include "mozilla/Atomics.h"
|
||||
#include "nsID.h"
|
||||
#include "nsISupportsImpl.h"
|
||||
|
||||
class nsIEventTarget;
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
class HttpChannelParent;
|
||||
|
||||
class HttpBackgroundChannelParent final : public PHttpBackgroundChannelParent
|
||||
{
|
||||
public:
|
||||
explicit HttpBackgroundChannelParent();
|
||||
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(HttpBackgroundChannelParent)
|
||||
|
||||
// Try to find associated HttpChannelParent with the same
|
||||
// channel Id.
|
||||
nsresult Init(const uint64_t& aChannelId);
|
||||
|
||||
// Callbacks for BackgroundChannelRegistrar to notify
|
||||
// the associated HttpChannelParent is found.
|
||||
void LinkToChannel(HttpChannelParent* aChannelParent);
|
||||
|
||||
// Callbacks for HttpChannelParent to close the background
|
||||
// IPC channel.
|
||||
void OnChannelClosed();
|
||||
|
||||
// To send OnStartRequestSend message over background channel.
|
||||
bool OnStartRequestSent();
|
||||
|
||||
// To send OnTransportAndData message over background channel.
|
||||
bool OnTransportAndData(const nsresult& aChannelStatus,
|
||||
const nsresult& aTransportStatus,
|
||||
const uint64_t& aOffset,
|
||||
const uint32_t& aCount,
|
||||
const nsCString& aData);
|
||||
|
||||
// To send OnStopRequest message over background channel.
|
||||
bool OnStopRequest(const nsresult& aChannelStatus,
|
||||
const ResourceTimingStruct& aTiming);
|
||||
|
||||
// To send OnProgress message over background channel.
|
||||
bool OnProgress(const int64_t& aProgress,
|
||||
const int64_t& aProgressMax);
|
||||
|
||||
// To send OnStatus message over background channel.
|
||||
bool OnStatus(const nsresult& aStatus);
|
||||
|
||||
// To send FlushedForDiversion and DivertMessages messages
|
||||
// over background channel.
|
||||
bool OnDiversion();
|
||||
|
||||
// To send NotifyTrackingProtectionDisabled message over background channel.
|
||||
bool OnNotifyTrackingProtectionDisabled();
|
||||
|
||||
// To send NotifyTrackingResource message over background channel.
|
||||
bool OnNotifyTrackingResource();
|
||||
|
||||
// To send SetClassifierMatchedInfo message over background channel.
|
||||
bool OnSetClassifierMatchedInfo(const nsACString& aList,
|
||||
const nsACString& aProvider,
|
||||
const nsACString& aPrefix);
|
||||
|
||||
protected:
|
||||
void ActorDestroy(ActorDestroyReason aWhy) override;
|
||||
|
||||
private:
|
||||
virtual ~HttpBackgroundChannelParent();
|
||||
|
||||
Atomic<bool> mIPCOpened;
|
||||
|
||||
nsCOMPtr<nsIEventTarget> mBackgroundThread;
|
||||
|
||||
// associated HttpChannelParent for generating the channel events
|
||||
RefPtr<HttpChannelParent> mChannelParent;
|
||||
};
|
||||
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_net_HttpBackgroundChannelParent_h
|
|
@ -62,6 +62,7 @@
|
|||
#include "nsIXULRuntime.h"
|
||||
#include "nsICacheInfoChannel.h"
|
||||
#include "nsIDOMWindowUtils.h"
|
||||
#include "nsHttpChannel.h"
|
||||
#include "nsRedirectHistoryEntry.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
|
|
@ -364,6 +364,11 @@ public: /* Necko internal use only... */
|
|||
mIsTrackingResource = true;
|
||||
}
|
||||
|
||||
const uint64_t& ChannelId() const
|
||||
{
|
||||
return mChannelId;
|
||||
}
|
||||
|
||||
protected:
|
||||
// Handle notifying listener, removing from loadgroup if request failed.
|
||||
void DoNotifyListener();
|
||||
|
|
|
@ -20,11 +20,14 @@
|
|||
#include "mozilla/net/NeckoChild.h"
|
||||
#include "mozilla/net/HttpChannelChild.h"
|
||||
|
||||
#include "AltDataOutputStreamChild.h"
|
||||
#include "HttpBackgroundChannelChild.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsISupportsPrimitives.h"
|
||||
#include "nsChannelClassifier.h"
|
||||
#include "nsGlobalWindow.h"
|
||||
#include "nsStringStream.h"
|
||||
#include "nsHttpChannel.h"
|
||||
#include "nsHttpHandler.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsSerializationHelper.h"
|
||||
|
@ -46,13 +49,10 @@
|
|||
#include "nsIDOMDocument.h"
|
||||
#include "nsIDOMWindowUtils.h"
|
||||
#include "nsIEventTarget.h"
|
||||
#include "nsRedirectHistoryEntry.h"
|
||||
#include "nsStreamUtils.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
#ifdef OS_POSIX
|
||||
#include "chrome/common/file_descriptor_set_posix.h"
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_TASK_TRACER
|
||||
#include "GeckoTaskTracer.h"
|
||||
#endif
|
||||
|
@ -63,19 +63,6 @@ using namespace mozilla::ipc;
|
|||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
namespace {
|
||||
|
||||
const uint32_t kMaxFileDescriptorsPerMessage = 250;
|
||||
|
||||
#ifdef OS_POSIX
|
||||
// Keep this in sync with other platforms.
|
||||
static_assert(FileDescriptorSet::MAX_DESCRIPTORS_PER_MESSAGE == 250,
|
||||
"MAX_DESCRIPTORS_PER_MESSAGE mismatch!");
|
||||
#endif
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
NS_IMPL_ISUPPORTS(InterceptStreamListener,
|
||||
nsIStreamListener,
|
||||
nsIRequestObserver,
|
||||
|
@ -286,6 +273,26 @@ HttpChannelChild::ReleaseIPDLReference()
|
|||
Release();
|
||||
}
|
||||
|
||||
void
|
||||
HttpChannelChild::OnBackgroundChildReady(HttpBackgroundChannelChild* aBgChild)
|
||||
{
|
||||
LOG(("HttpChannelChild::OnBackgroundChildReady [this=%p, bgChild=%p]\n",
|
||||
this, aBgChild));
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(mBgChild);
|
||||
|
||||
MOZ_ASSERT(mBgChild == aBgChild);
|
||||
}
|
||||
|
||||
void
|
||||
HttpChannelChild::OnBackgroundChildDestroyed()
|
||||
{
|
||||
LOG(("HttpChannelChild::OnBackgroundChildDestroyed [this=%p]\n", this));
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
mBgChild = nullptr;
|
||||
}
|
||||
|
||||
class AssociateApplicationCacheEvent : public ChannelEvent
|
||||
{
|
||||
public:
|
||||
|
@ -439,6 +446,12 @@ HttpChannelChild::RecvOnStartRequest(const nsresult& channelStatus,
|
|||
securityInfoSerialization,
|
||||
selfAddr, peerAddr, cacheKey,
|
||||
altDataType, altDataLen));
|
||||
|
||||
MOZ_ASSERT(mBgChild);
|
||||
if (mBgChild) {
|
||||
mBgChild->OnStartRequestReceived();
|
||||
}
|
||||
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
|
@ -660,22 +673,21 @@ class TransportAndDataEvent : public ChannelEvent
|
|||
uint32_t mCount;
|
||||
};
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
HttpChannelChild::RecvOnTransportAndData(const nsresult& channelStatus,
|
||||
const nsresult& transportStatus,
|
||||
const uint64_t& offset,
|
||||
const uint32_t& count,
|
||||
const nsCString& data)
|
||||
void
|
||||
HttpChannelChild::ProcessOnTransportAndData(const nsresult& aChannelStatus,
|
||||
const nsresult& aTransportStatus,
|
||||
const uint64_t& aOffset,
|
||||
const uint32_t& aCount,
|
||||
const nsCString& aData)
|
||||
{
|
||||
LOG(("HttpChannelChild::RecvOnTransportAndData [this=%p]\n", this));
|
||||
LOG(("HttpChannelChild::ProcessOnTransportAndData [this=%p]\n", this));
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_RELEASE_ASSERT(!mFlushedForDiversion,
|
||||
"Should not be receiving any more callbacks from parent!");
|
||||
|
||||
mEventQ->RunOrEnqueue(new TransportAndDataEvent(this, channelStatus,
|
||||
transportStatus, data, offset,
|
||||
count),
|
||||
mEventQ->RunOrEnqueue(new TransportAndDataEvent(this, aChannelStatus,
|
||||
aTransportStatus, aData,
|
||||
aOffset, aCount),
|
||||
mDivertingToParent);
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
class MaybeDivertOnDataHttpEvent : public ChannelEvent
|
||||
|
@ -903,17 +915,17 @@ class StopRequestEvent : public ChannelEvent
|
|||
ResourceTimingStruct mTiming;
|
||||
};
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
HttpChannelChild::RecvOnStopRequest(const nsresult& channelStatus,
|
||||
const ResourceTimingStruct& timing)
|
||||
void
|
||||
HttpChannelChild::ProcessOnStopRequest(const nsresult& aChannelStatus,
|
||||
const ResourceTimingStruct& aTiming)
|
||||
{
|
||||
LOG(("HttpChannelChild::RecvOnStopRequest [this=%p]\n", this));
|
||||
LOG(("HttpChannelChild::ProcessOnStopRequest [this=%p]\n", this));
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_RELEASE_ASSERT(!mFlushedForDiversion,
|
||||
"Should not be receiving any more callbacks from parent!");
|
||||
|
||||
mEventQ->RunOrEnqueue(new StopRequestEvent(this, channelStatus, timing),
|
||||
mEventQ->RunOrEnqueue(new StopRequestEvent(this, aChannelStatus, aTiming),
|
||||
mDivertingToParent);
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
class MaybeDivertOnStopHttpEvent : public ChannelEvent
|
||||
|
@ -1044,6 +1056,8 @@ HttpChannelChild::OnStopRequest(const nsresult& channelStatus,
|
|||
// DoOnStopRequest() calls ReleaseListeners()
|
||||
}
|
||||
|
||||
CleanupBackgroundChannel();
|
||||
|
||||
// DocumentChannelCleanup actually nulls out mCacheEntry in the parent, which
|
||||
// we might need later to open the Alt-Data output stream, so just return here
|
||||
if (!mPreferredCachedAltDataType.IsEmpty()) {
|
||||
|
@ -1142,12 +1156,13 @@ class ProgressEvent : public ChannelEvent
|
|||
int64_t mProgress, mProgressMax;
|
||||
};
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
HttpChannelChild::RecvOnProgress(const int64_t& progress,
|
||||
const int64_t& progressMax)
|
||||
void
|
||||
HttpChannelChild::ProcessOnProgress(const int64_t& aProgress,
|
||||
const int64_t& aProgressMax)
|
||||
{
|
||||
mEventQ->RunOrEnqueue(new ProgressEvent(this, progress, progressMax));
|
||||
return IPC_OK();
|
||||
LOG(("HttpChannelChild::ProcessOnProgress [this=%p]\n", this));
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
mEventQ->RunOrEnqueue(new ProgressEvent(this, aProgress, aProgressMax));
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1197,11 +1212,12 @@ class StatusEvent : public ChannelEvent
|
|||
nsresult mStatus;
|
||||
};
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
HttpChannelChild::RecvOnStatus(const nsresult& status)
|
||||
void
|
||||
HttpChannelChild::ProcessOnStatus(const nsresult& aStatus)
|
||||
{
|
||||
mEventQ->RunOrEnqueue(new StatusEvent(this, status));
|
||||
return IPC_OK();
|
||||
LOG(("HttpChannelChild::ProcessOnStatus [this=%p]\n", this));
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
mEventQ->RunOrEnqueue(new StatusEvent(this, aStatus));
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1266,6 +1282,9 @@ void
|
|||
HttpChannelChild::HandleAsyncAbort()
|
||||
{
|
||||
HttpAsyncAborter<HttpChannelChild>::HandleAsyncAbort();
|
||||
|
||||
// Ignore all the messages from background channel after channel aborted.
|
||||
CleanupBackgroundChannel();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1273,6 +1292,14 @@ HttpChannelChild::FailedAsyncOpen(const nsresult& status)
|
|||
{
|
||||
LOG(("HttpChannelChild::FailedAsyncOpen [this=%p status=%" PRIx32 "]\n",
|
||||
this, static_cast<uint32_t>(status)));
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
// Might be called twice in race condition in theory.
|
||||
// (one by RecvFailedAsyncOpen, another by
|
||||
// HttpBackgroundChannelChild::ActorFailed)
|
||||
if (NS_WARN_IF(NS_FAILED(mStatus))) {
|
||||
return;
|
||||
}
|
||||
|
||||
mStatus = status;
|
||||
|
||||
|
@ -1284,6 +1311,27 @@ HttpChannelChild::FailedAsyncOpen(const nsresult& status)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
HttpChannelChild::CleanupBackgroundChannel()
|
||||
{
|
||||
LOG(("HttpChannelChild::CleanupBackgroundChannel [this=%p bgChild=%p]\n",
|
||||
this, mBgChild.get()));
|
||||
if (!mBgChild) {
|
||||
return;
|
||||
}
|
||||
|
||||
RefPtr<HttpBackgroundChannelChild> bgChild = mBgChild.forget();
|
||||
|
||||
if (!NS_IsMainThread()) {
|
||||
SystemGroup::Dispatch(
|
||||
"HttpChannelChild::CleanupBackgroundChannel",
|
||||
TaskCategory::Other,
|
||||
NewRunnableMethod(bgChild, &HttpBackgroundChannelChild::OnChannelClosed));
|
||||
} else {
|
||||
bgChild->OnChannelClosed();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
HttpChannelChild::DoNotifyListenerCleanup()
|
||||
{
|
||||
|
@ -1673,29 +1721,32 @@ class HttpFlushedForDiversionEvent : public ChannelEvent
|
|||
HttpChannelChild* mChild;
|
||||
};
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
HttpChannelChild::RecvFlushedForDiversion()
|
||||
void
|
||||
HttpChannelChild::ProcessFlushedForDiversion()
|
||||
{
|
||||
LOG(("HttpChannelChild::RecvFlushedForDiversion [this=%p]\n", this));
|
||||
LOG(("HttpChannelChild::ProcessFlushedForDiversion [this=%p]\n", this));
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_RELEASE_ASSERT(mDivertingToParent);
|
||||
|
||||
mEventQ->RunOrEnqueue(new HttpFlushedForDiversionEvent(this), true);
|
||||
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
HttpChannelChild::RecvNotifyTrackingProtectionDisabled()
|
||||
void
|
||||
HttpChannelChild::ProcessNotifyTrackingProtectionDisabled()
|
||||
{
|
||||
LOG(("HttpChannelChild::ProcessNotifyTrackingProtectionDisabled [this=%p]\n", this));
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
nsChannelClassifier::NotifyTrackingProtectionDisabled(this);
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
HttpChannelChild::RecvNotifyTrackingResource()
|
||||
void
|
||||
HttpChannelChild::ProcessNotifyTrackingResource()
|
||||
{
|
||||
LOG(("HttpChannelChild::ProcessNotifyTrackingResource [this=%p]\n", this));
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
SetIsTrackingResource();
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1712,26 +1763,28 @@ HttpChannelChild::FlushedForDiversion()
|
|||
SendDivertComplete();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
HttpChannelChild::RecvSetClassifierMatchedInfo(const ClassifierInfo& aInfo)
|
||||
void
|
||||
HttpChannelChild::ProcessSetClassifierMatchedInfo(const nsCString& aList,
|
||||
const nsCString& aProvider,
|
||||
const nsCString& aPrefix)
|
||||
{
|
||||
SetMatchedInfo(aInfo.list(), aInfo.provider(), aInfo.prefix());
|
||||
return IPC_OK();
|
||||
LOG(("HttpChannelChild::ProcessSetClassifierMatchedInfo [this=%p]\n", this));
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
SetMatchedInfo(aList, aProvider, aPrefix);
|
||||
}
|
||||
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
HttpChannelChild::RecvDivertMessages()
|
||||
void
|
||||
HttpChannelChild::ProcessDivertMessages()
|
||||
{
|
||||
LOG(("HttpChannelChild::RecvDivertMessages [this=%p]\n", this));
|
||||
LOG(("HttpChannelChild::ProcessDivertMessages [this=%p]\n", this));
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_RELEASE_ASSERT(mDivertingToParent);
|
||||
MOZ_RELEASE_ASSERT(mSuspendCount > 0);
|
||||
|
||||
// DivertTo() has been called on parent, so we can now start sending queued
|
||||
// IPDL messages back to parent listener.
|
||||
MOZ_RELEASE_ASSERT(NS_SUCCEEDED(Resume()));
|
||||
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
// Returns true if has actually completed the redirect and cleaned up the
|
||||
|
@ -1849,6 +1902,20 @@ HttpChannelChild::ConnectParent(uint32_t registrarId)
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
{
|
||||
MOZ_ASSERT(!mBgChild);
|
||||
|
||||
RefPtr<HttpBackgroundChannelChild> bgChild =
|
||||
new HttpBackgroundChannelChild();
|
||||
|
||||
nsresult rv = bgChild->Init(this);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
mBgChild = bgChild.forget();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -2477,6 +2544,26 @@ HttpChannelChild::ContinueAsyncOpen()
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
{
|
||||
// Service worker might use the same HttpChannelChild to do async open
|
||||
// twice. Need to disconnect with previous background channel before
|
||||
// creating the new one.
|
||||
if (mBgChild) {
|
||||
RefPtr<HttpBackgroundChannelChild> prevBgChild = mBgChild.forget();
|
||||
prevBgChild->OnChannelClosed();
|
||||
}
|
||||
|
||||
RefPtr<HttpBackgroundChannelChild> bgChild =
|
||||
new HttpBackgroundChannelChild();
|
||||
|
||||
rv = bgChild->Init(this);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
mBgChild = bgChild.forget();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -39,6 +39,7 @@ class nsInputStreamPump;
|
|||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
class HttpBackgroundChannelChild;
|
||||
class InterceptedChannelContent;
|
||||
class InterceptStreamListener;
|
||||
|
||||
|
@ -110,13 +111,15 @@ public:
|
|||
|
||||
MOZ_MUST_USE bool IsSuspended();
|
||||
|
||||
mozilla::ipc::IPCResult RecvNotifyTrackingProtectionDisabled() override;
|
||||
mozilla::ipc::IPCResult RecvNotifyTrackingResource() override;
|
||||
void FlushedForDiversion();
|
||||
mozilla::ipc::IPCResult RecvSetClassifierMatchedInfo(const ClassifierInfo& aInfo) override;
|
||||
|
||||
void OnCopyComplete(nsresult aStatus) override;
|
||||
|
||||
// Callback while background channel is ready.
|
||||
void OnBackgroundChildReady(HttpBackgroundChannelChild* aBgChild);
|
||||
// Callback while background channel is destroyed.
|
||||
void OnBackgroundChildDestroyed();
|
||||
|
||||
protected:
|
||||
mozilla::ipc::IPCResult RecvOnStartRequest(const nsresult& channelStatus,
|
||||
const nsHttpResponseHead& responseHead,
|
||||
|
@ -133,14 +136,6 @@ protected:
|
|||
const uint32_t& cacheKey,
|
||||
const nsCString& altDataType,
|
||||
const int64_t& altDataLen) override;
|
||||
mozilla::ipc::IPCResult RecvOnTransportAndData(const nsresult& channelStatus,
|
||||
const nsresult& status,
|
||||
const uint64_t& offset,
|
||||
const uint32_t& count,
|
||||
const nsCString& data) override;
|
||||
mozilla::ipc::IPCResult RecvOnStopRequest(const nsresult& statusCode, const ResourceTimingStruct& timing) override;
|
||||
mozilla::ipc::IPCResult RecvOnProgress(const int64_t& progress, const int64_t& progressMax) override;
|
||||
mozilla::ipc::IPCResult RecvOnStatus(const nsresult& status) override;
|
||||
mozilla::ipc::IPCResult RecvFailedAsyncOpen(const nsresult& status) override;
|
||||
mozilla::ipc::IPCResult RecvRedirect1Begin(const uint32_t& registrarId,
|
||||
const URIParams& newURI,
|
||||
|
@ -152,8 +147,6 @@ protected:
|
|||
mozilla::ipc::IPCResult RecvRedirect3Complete() override;
|
||||
mozilla::ipc::IPCResult RecvAssociateApplicationCache(const nsCString& groupID,
|
||||
const nsCString& clientID) override;
|
||||
mozilla::ipc::IPCResult RecvFlushedForDiversion() override;
|
||||
mozilla::ipc::IPCResult RecvDivertMessages() override;
|
||||
mozilla::ipc::IPCResult RecvDeleteSelf() override;
|
||||
mozilla::ipc::IPCResult RecvFinishInterceptedRedirect() override;
|
||||
|
||||
|
@ -217,6 +210,26 @@ private:
|
|||
|
||||
MOZ_MUST_USE nsresult ContinueAsyncOpen();
|
||||
|
||||
// Callbacks while receiving OnTransportAndData/OnStopRequest/OnProgress/
|
||||
// OnStatus/FlushedForDiversion/DivertMessages on background IPC channel.
|
||||
void ProcessOnTransportAndData(const nsresult& aChannelStatus,
|
||||
const nsresult& aStatus,
|
||||
const uint64_t& aOffset,
|
||||
const uint32_t& aCount,
|
||||
const nsCString& aData);
|
||||
void ProcessOnStopRequest(const nsresult& aStatusCode,
|
||||
const ResourceTimingStruct& aTiming);
|
||||
void ProcessOnProgress(const int64_t& aProgress, const int64_t& aProgressMax);
|
||||
void ProcessOnStatus(const nsresult& aStatus);
|
||||
void ProcessFlushedForDiversion();
|
||||
void ProcessDivertMessages();
|
||||
void ProcessNotifyTrackingProtectionDisabled();
|
||||
void ProcessNotifyTrackingResource();
|
||||
void ProcessSetClassifierMatchedInfo(const nsCString& aList,
|
||||
const nsCString& aProvider,
|
||||
const nsCString& aPrefix);
|
||||
|
||||
|
||||
void DoOnStartRequest(nsIRequest* aRequest, nsISupports* aContext);
|
||||
void DoOnStatus(nsIRequest* aRequest, nsresult status);
|
||||
void DoOnProgress(nsIRequest* aRequest, int64_t progress, int64_t progressMax);
|
||||
|
@ -312,6 +325,12 @@ private:
|
|||
// is synthesized.
|
||||
bool mSuspendParentAfterSynthesizeResponse;
|
||||
|
||||
RefPtr<HttpBackgroundChannelChild> mBgChild;
|
||||
|
||||
// Remove the association with background channel after OnStopRequest
|
||||
// or AsyncAbort.
|
||||
void CleanupBackgroundChannel();
|
||||
|
||||
// Needed to call AsyncOpen in FinishInterceptedRedirect
|
||||
nsCOMPtr<nsIStreamListener> mInterceptedRedirectListener;
|
||||
nsCOMPtr<nsISupports> mInterceptedRedirectContext;
|
||||
|
@ -403,6 +422,7 @@ private:
|
|||
friend class HttpAsyncAborter<HttpChannelChild>;
|
||||
friend class InterceptStreamListener;
|
||||
friend class InterceptedChannelContent;
|
||||
friend class HttpBackgroundChannelChild;
|
||||
};
|
||||
|
||||
// A stream listener interposed between the nsInputStreamPump used for intercepted channels
|
||||
|
|
|
@ -8,17 +8,23 @@
|
|||
#include "HttpLog.h"
|
||||
|
||||
#include "mozilla/ipc/FileDescriptorSetParent.h"
|
||||
#include "mozilla/ipc/IPCStreamUtils.h"
|
||||
#include "mozilla/net/HttpChannelParent.h"
|
||||
#include "mozilla/dom/ContentParent.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "mozilla/dom/TabParent.h"
|
||||
#include "mozilla/net/NeckoParent.h"
|
||||
#include "mozilla/IntegerPrintfMacros.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
#include "mozilla/Unused.h"
|
||||
#include "HttpBackgroundChannelParent.h"
|
||||
#include "HttpChannelParentListener.h"
|
||||
#include "nsHttpHandler.h"
|
||||
#include "nsNetCID.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsISupportsPriority.h"
|
||||
#include "nsIAuthPromptProvider.h"
|
||||
#include "nsIBackgroundChannelRegistrar.h"
|
||||
#include "nsSerializationHelper.h"
|
||||
#include "nsISerializable.h"
|
||||
#include "nsIAssociatedContentSecurity.h"
|
||||
|
@ -37,12 +43,14 @@
|
|||
#include "nsCORSListenerProxy.h"
|
||||
#include "nsIIPCSerializableInputStream.h"
|
||||
#include "nsIPrompt.h"
|
||||
#include "nsIRedirectChannelRegistrar.h"
|
||||
#include "nsIWindowWatcher.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsStreamUtils.h"
|
||||
#include "nsStringStream.h"
|
||||
#include "nsIStorageStream.h"
|
||||
#include "nsQueryObject.h"
|
||||
#include "nsIURIClassifier.h"
|
||||
#include "mozilla/dom/ContentParent.h"
|
||||
|
||||
using mozilla::BasePrincipal;
|
||||
using namespace mozilla::dom;
|
||||
|
@ -56,7 +64,6 @@ HttpChannelParent::HttpChannelParent(const PBrowserOrId& iframeEmbedding,
|
|||
PBOverrideStatus aOverrideStatus)
|
||||
: mIPCClosed(false)
|
||||
, mIgnoreProgress(false)
|
||||
, mSentRedirect1Begin(false)
|
||||
, mSentRedirect1BeginFailed(false)
|
||||
, mReceivedRedirect2Verify(false)
|
||||
, mPBOverride(aOverrideStatus)
|
||||
|
@ -91,6 +98,7 @@ HttpChannelParent::HttpChannelParent(const PBrowserOrId& iframeEmbedding,
|
|||
HttpChannelParent::~HttpChannelParent()
|
||||
{
|
||||
LOG(("Destroying HttpChannelParent [this=%p]\n", this));
|
||||
CleanupBackgroundChannel();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -106,6 +114,8 @@ HttpChannelParent::ActorDestroy(ActorDestroyReason why)
|
|||
if (mParentListener) {
|
||||
mParentListener->ClearInterceptedChannel();
|
||||
}
|
||||
|
||||
CleanupBackgroundChannel();
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -151,6 +161,101 @@ HttpChannelParent::Init(const HttpChannelCreationArgs& aArgs)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
HttpChannelParent::TryInvokeAsyncOpen(nsresult aRv)
|
||||
{
|
||||
LOG(("HttpChannelParent::TryInvokeAsyncOpen [this=%p barrier=%u rv=%" PRIx32
|
||||
"]\n", this, mAsyncOpenBarrier, static_cast<uint32_t>(aRv)));
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
// TryInvokeAsyncOpen is called more than we expected.
|
||||
// Assert in nightly build but ignore it in release channel.
|
||||
MOZ_DIAGNOSTIC_ASSERT(mAsyncOpenBarrier > 0);
|
||||
if (NS_WARN_IF(!mAsyncOpenBarrier)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (--mAsyncOpenBarrier > 0 && NS_SUCCEEDED(aRv)) {
|
||||
// Need to wait for more events.
|
||||
return;
|
||||
}
|
||||
|
||||
InvokeAsyncOpen(aRv);
|
||||
}
|
||||
|
||||
void
|
||||
HttpChannelParent::OnBackgroundParentReady(
|
||||
HttpBackgroundChannelParent* aBgParent)
|
||||
{
|
||||
LOG(("HttpChannelParent::OnBackgroundParentReady [this=%p bgParent=%p]\n",
|
||||
this, aBgParent));
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(!mBgParent);
|
||||
|
||||
mBgParent = aBgParent;
|
||||
|
||||
mPromise.ResolveIfExists(true, __func__);
|
||||
}
|
||||
|
||||
void
|
||||
HttpChannelParent::OnBackgroundParentDestroyed()
|
||||
{
|
||||
LOG(("HttpChannelParent::OnBackgroundParentDestroyed [this=%p]\n", this));
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (!mPromise.IsEmpty()) {
|
||||
MOZ_ASSERT(!mBgParent);
|
||||
mPromise.Reject(NS_ERROR_FAILURE, __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mBgParent) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Background channel is closed unexpectly, abort PHttpChannel operation.
|
||||
mBgParent = nullptr;
|
||||
Delete();
|
||||
}
|
||||
|
||||
void
|
||||
HttpChannelParent::CleanupBackgroundChannel()
|
||||
{
|
||||
LOG(("HttpChannelParent::CleanupBackgroundChannel [this=%p bgParent=%p]\n",
|
||||
this, mBgParent.get()));
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (mBgParent) {
|
||||
RefPtr<HttpBackgroundChannelParent> bgParent = mBgParent.forget();
|
||||
bgParent->OnChannelClosed();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mPromise.IsEmpty()) {
|
||||
mRequest.DisconnectIfExists();
|
||||
mPromise.Reject(NS_ERROR_FAILURE, __func__);
|
||||
|
||||
if (!mChannel) {
|
||||
return;
|
||||
}
|
||||
|
||||
// This HttpChannelParent might still have a reference from
|
||||
// BackgroundChannelRegistrar.
|
||||
nsCOMPtr<nsIBackgroundChannelRegistrar> registrar =
|
||||
do_GetService(NS_BACKGROUNDCHANNELREGISTRAR_CONTRACTID);
|
||||
MOZ_ASSERT(registrar);
|
||||
|
||||
registrar->DeleteChannel(mChannel->ChannelId());
|
||||
|
||||
// If mAsyncOpenBarrier is greater than zero, it means AsyncOpen procedure
|
||||
// is still on going. we need to abort AsyncOpen with failure to destroy
|
||||
// PHttpChannel actor.
|
||||
if (mAsyncOpenBarrier) {
|
||||
TryInvokeAsyncOpen(NS_ERROR_FAILURE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// HttpChannelParent::nsISupports
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -166,6 +271,7 @@ NS_INTERFACE_MAP_BEGIN(HttpChannelParent)
|
|||
NS_INTERFACE_MAP_ENTRY(nsIAuthPromptProvider)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIParentRedirectingChannel)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDeprecationWarner)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIAsyncVerifyRedirectReadyCallback)
|
||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIParentRedirectingChannel)
|
||||
if (aIID.Equals(NS_GET_IID(HttpChannelParent))) {
|
||||
foundInterface = static_cast<nsIInterfaceRequestor*>(this);
|
||||
|
@ -232,18 +338,38 @@ HttpChannelParent::GetInterface(const nsIID& aIID, void **result)
|
|||
// HttpChannelParent::PHttpChannelParent
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void
|
||||
HttpChannelParent::AsyncOpenFailed(nsresult aRv)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(NS_FAILED(aRv));
|
||||
|
||||
// Break the reference cycle among HttpChannelParent,
|
||||
// HttpChannelParentListener, and nsHttpChannel to avoid memory leakage.
|
||||
mChannel = nullptr;
|
||||
mParentListener = nullptr;
|
||||
|
||||
if (!mIPCClosed) {
|
||||
Unused << SendFailedAsyncOpen(aRv);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
HttpChannelParent::InvokeAsyncOpen(nsresult rv)
|
||||
{
|
||||
LOG(("HttpChannelParent::InvokeAsyncOpen [this=%p rv=%" PRIx32 "]\n",
|
||||
this, static_cast<uint32_t>(rv)));
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
Unused << SendFailedAsyncOpen(rv);
|
||||
AsyncOpenFailed(rv);
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsILoadInfo> loadInfo;
|
||||
rv = mChannel->GetLoadInfo(getter_AddRefs(loadInfo));
|
||||
if (NS_FAILED(rv)) {
|
||||
Unused << SendFailedAsyncOpen(rv);
|
||||
AsyncOpenFailed(rv);
|
||||
return;
|
||||
}
|
||||
if (loadInfo && loadInfo->GetEnforceSecurity()) {
|
||||
|
@ -253,7 +379,7 @@ HttpChannelParent::InvokeAsyncOpen(nsresult rv)
|
|||
rv = mChannel->AsyncOpen(mParentListener, nullptr);
|
||||
}
|
||||
if (NS_FAILED(rv)) {
|
||||
Unused << SendFailedAsyncOpen(rv);
|
||||
AsyncOpenFailed(rv);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -273,7 +399,7 @@ public:
|
|||
NS_IMETHOD Run()
|
||||
{
|
||||
RefPtr<HttpChannelParent> channel = do_QueryObject(mChannel.get());
|
||||
channel->InvokeAsyncOpen(mStatus);
|
||||
channel->TryInvokeAsyncOpen(mStatus);
|
||||
return NS_OK;
|
||||
}
|
||||
};
|
||||
|
@ -384,64 +510,62 @@ HttpChannelParent::DoAsyncOpen( const URIParams& aURI,
|
|||
return SendFailedAsyncOpen(rv);
|
||||
}
|
||||
|
||||
mChannel = do_QueryObject(channel, &rv);
|
||||
RefPtr<nsHttpChannel> httpChannel = do_QueryObject(channel, &rv);
|
||||
if (NS_FAILED(rv)) {
|
||||
return SendFailedAsyncOpen(rv);
|
||||
}
|
||||
|
||||
// Set the channelId allocated in child to the parent instance
|
||||
mChannel->SetChannelId(aChannelId);
|
||||
mChannel->SetTopLevelContentWindowId(aContentWindowId);
|
||||
mChannel->SetTopLevelOuterContentWindowId(aTopLevelOuterContentWindowId);
|
||||
httpChannel->SetChannelId(aChannelId);
|
||||
httpChannel->SetTopLevelContentWindowId(aContentWindowId);
|
||||
httpChannel->SetTopLevelOuterContentWindowId(aTopLevelOuterContentWindowId);
|
||||
|
||||
mChannel->SetWarningReporter(this);
|
||||
mChannel->SetTimingEnabled(true);
|
||||
httpChannel->SetWarningReporter(this);
|
||||
httpChannel->SetTimingEnabled(true);
|
||||
if (mPBOverride != kPBOverride_Unset) {
|
||||
mChannel->SetPrivate(mPBOverride == kPBOverride_Private ? true : false);
|
||||
httpChannel->SetPrivate(mPBOverride == kPBOverride_Private ? true : false);
|
||||
}
|
||||
|
||||
if (doResumeAt)
|
||||
mChannel->ResumeAt(startPos, entityID);
|
||||
httpChannel->ResumeAt(startPos, entityID);
|
||||
|
||||
if (originalUri)
|
||||
mChannel->SetOriginalURI(originalUri);
|
||||
httpChannel->SetOriginalURI(originalUri);
|
||||
if (docUri)
|
||||
mChannel->SetDocumentURI(docUri);
|
||||
httpChannel->SetDocumentURI(docUri);
|
||||
if (referrerUri) {
|
||||
rv = mChannel->SetReferrerWithPolicyInternal(referrerUri, aReferrerPolicy);
|
||||
rv = httpChannel->SetReferrerWithPolicyInternal(referrerUri, aReferrerPolicy);
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
||||
}
|
||||
if (apiRedirectToUri)
|
||||
mChannel->RedirectTo(apiRedirectToUri);
|
||||
httpChannel->RedirectTo(apiRedirectToUri);
|
||||
if (topWindowUri) {
|
||||
rv = mChannel->SetTopWindowURI(topWindowUri);
|
||||
rv = httpChannel->SetTopWindowURI(topWindowUri);
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
||||
}
|
||||
if (aLoadFlags != nsIRequest::LOAD_NORMAL)
|
||||
mChannel->SetLoadFlags(aLoadFlags);
|
||||
httpChannel->SetLoadFlags(aLoadFlags);
|
||||
|
||||
for (uint32_t i = 0; i < requestHeaders.Length(); i++) {
|
||||
if (requestHeaders[i].mEmpty) {
|
||||
mChannel->SetEmptyRequestHeader(requestHeaders[i].mHeader);
|
||||
httpChannel->SetEmptyRequestHeader(requestHeaders[i].mHeader);
|
||||
} else {
|
||||
mChannel->SetRequestHeader(requestHeaders[i].mHeader,
|
||||
httpChannel->SetRequestHeader(requestHeaders[i].mHeader,
|
||||
requestHeaders[i].mValue,
|
||||
requestHeaders[i].mMerge);
|
||||
}
|
||||
}
|
||||
|
||||
mParentListener = new HttpChannelParentListener(this);
|
||||
RefPtr<HttpChannelParentListener> parentListener
|
||||
= new HttpChannelParentListener(this);
|
||||
|
||||
mChannel->SetNotificationCallbacks(mParentListener);
|
||||
|
||||
mChannel->SetRequestMethod(nsDependentCString(requestMethod.get()));
|
||||
httpChannel->SetRequestMethod(nsDependentCString(requestMethod.get()));
|
||||
|
||||
if (aCorsPreflightArgs.type() == OptionalCorsPreflightArgs::TCorsPreflightArgs) {
|
||||
const CorsPreflightArgs& args = aCorsPreflightArgs.get_CorsPreflightArgs();
|
||||
mChannel->SetCorsPreflightParameters(args.unsafeHeaders());
|
||||
httpChannel->SetCorsPreflightParameters(args.unsafeHeaders());
|
||||
}
|
||||
|
||||
bool delayAsyncOpen = false;
|
||||
nsCOMPtr<nsIInputStream> stream = DeserializeIPCStream(uploadStream);
|
||||
if (stream) {
|
||||
// FIXME: The fast path of using the existing stream currently only applies to streams
|
||||
|
@ -449,7 +573,8 @@ HttpChannelParent::DoAsyncOpen( const URIParams& aURI,
|
|||
// Once bug 1294446 and bug 1294450 are fixed it is worth revisiting this heuristic.
|
||||
nsCOMPtr<nsIIPCSerializableInputStream> completeStream = do_QueryInterface(stream);
|
||||
if (!completeStream) {
|
||||
delayAsyncOpen = true;
|
||||
// Wait for completion of async copying IPC upload stream to a local input stream.
|
||||
++mAsyncOpenBarrier;
|
||||
|
||||
// buffer size matches PChildToParentStream transfer size.
|
||||
const uint32_t kBufferSize = 32768;
|
||||
|
@ -494,29 +619,29 @@ HttpChannelParent::DoAsyncOpen( const URIParams& aURI,
|
|||
return SendFailedAsyncOpen(rv);
|
||||
}
|
||||
|
||||
mChannel->InternalSetUploadStream(newUploadStream);
|
||||
httpChannel->InternalSetUploadStream(newUploadStream);
|
||||
} else {
|
||||
mChannel->InternalSetUploadStream(stream);
|
||||
httpChannel->InternalSetUploadStream(stream);
|
||||
}
|
||||
mChannel->SetUploadStreamHasHeaders(uploadStreamHasHeaders);
|
||||
httpChannel->SetUploadStreamHasHeaders(uploadStreamHasHeaders);
|
||||
}
|
||||
|
||||
if (aSynthesizedResponseHead.type() == OptionalHttpResponseHead::TnsHttpResponseHead) {
|
||||
mParentListener->SetupInterception(aSynthesizedResponseHead.get_nsHttpResponseHead());
|
||||
parentListener->SetupInterception(aSynthesizedResponseHead.get_nsHttpResponseHead());
|
||||
mWillSynthesizeResponse = true;
|
||||
mChannel->SetCouldBeSynthesized();
|
||||
httpChannel->SetCouldBeSynthesized();
|
||||
|
||||
if (!aSecurityInfoSerialization.IsEmpty()) {
|
||||
nsCOMPtr<nsISupports> secInfo;
|
||||
NS_DeserializeObject(aSecurityInfoSerialization, getter_AddRefs(secInfo));
|
||||
rv = mChannel->OverrideSecurityInfo(secInfo);
|
||||
rv = httpChannel->OverrideSecurityInfo(secInfo);
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
||||
}
|
||||
} else {
|
||||
nsLoadFlags newLoadFlags;
|
||||
mChannel->GetLoadFlags(&newLoadFlags);
|
||||
httpChannel->GetLoadFlags(&newLoadFlags);
|
||||
newLoadFlags |= nsIChannel::LOAD_BYPASS_SERVICE_WORKER;
|
||||
mChannel->SetLoadFlags(newLoadFlags);
|
||||
httpChannel->SetLoadFlags(newLoadFlags);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsISupportsPRUint32> cacheKey =
|
||||
|
@ -530,37 +655,37 @@ HttpChannelParent::DoAsyncOpen( const URIParams& aURI,
|
|||
return SendFailedAsyncOpen(rv);
|
||||
}
|
||||
|
||||
mChannel->SetCacheKey(cacheKey);
|
||||
mChannel->PreferAlternativeDataType(aPreferredAlternativeType);
|
||||
httpChannel->SetCacheKey(cacheKey);
|
||||
httpChannel->PreferAlternativeDataType(aPreferredAlternativeType);
|
||||
|
||||
mChannel->SetAllowStaleCacheContent(aAllowStaleCacheContent);
|
||||
httpChannel->SetAllowStaleCacheContent(aAllowStaleCacheContent);
|
||||
|
||||
mChannel->SetContentType(aContentTypeHint);
|
||||
httpChannel->SetContentType(aContentTypeHint);
|
||||
|
||||
if (priority != nsISupportsPriority::PRIORITY_NORMAL) {
|
||||
mChannel->SetPriority(priority);
|
||||
httpChannel->SetPriority(priority);
|
||||
}
|
||||
if (classOfService) {
|
||||
mChannel->SetClassFlags(classOfService);
|
||||
httpChannel->SetClassFlags(classOfService);
|
||||
}
|
||||
mChannel->SetRedirectionLimit(redirectionLimit);
|
||||
mChannel->SetAllowSTS(allowSTS);
|
||||
mChannel->SetThirdPartyFlags(thirdPartyFlags);
|
||||
mChannel->SetAllowSpdy(allowSpdy);
|
||||
mChannel->SetAllowAltSvc(allowAltSvc);
|
||||
mChannel->SetBeConservative(beConservative);
|
||||
mChannel->SetInitialRwin(aInitialRwin);
|
||||
mChannel->SetBlockAuthPrompt(aBlockAuthPrompt);
|
||||
httpChannel->SetRedirectionLimit(redirectionLimit);
|
||||
httpChannel->SetAllowSTS(allowSTS);
|
||||
httpChannel->SetThirdPartyFlags(thirdPartyFlags);
|
||||
httpChannel->SetAllowSpdy(allowSpdy);
|
||||
httpChannel->SetAllowAltSvc(allowAltSvc);
|
||||
httpChannel->SetBeConservative(beConservative);
|
||||
httpChannel->SetInitialRwin(aInitialRwin);
|
||||
httpChannel->SetBlockAuthPrompt(aBlockAuthPrompt);
|
||||
|
||||
mChannel->SetLaunchServiceWorkerStart(aLaunchServiceWorkerStart);
|
||||
mChannel->SetLaunchServiceWorkerEnd(aLaunchServiceWorkerEnd);
|
||||
mChannel->SetDispatchFetchEventStart(aDispatchFetchEventStart);
|
||||
mChannel->SetDispatchFetchEventEnd(aDispatchFetchEventEnd);
|
||||
mChannel->SetHandleFetchEventStart(aHandleFetchEventStart);
|
||||
mChannel->SetHandleFetchEventEnd(aHandleFetchEventEnd);
|
||||
httpChannel->SetLaunchServiceWorkerStart(aLaunchServiceWorkerStart);
|
||||
httpChannel->SetLaunchServiceWorkerEnd(aLaunchServiceWorkerEnd);
|
||||
httpChannel->SetDispatchFetchEventStart(aDispatchFetchEventStart);
|
||||
httpChannel->SetDispatchFetchEventEnd(aDispatchFetchEventEnd);
|
||||
httpChannel->SetHandleFetchEventStart(aHandleFetchEventStart);
|
||||
httpChannel->SetHandleFetchEventEnd(aHandleFetchEventEnd);
|
||||
|
||||
nsCOMPtr<nsIApplicationCacheChannel> appCacheChan =
|
||||
do_QueryObject(mChannel);
|
||||
do_QueryObject(httpChannel);
|
||||
nsCOMPtr<nsIApplicationCacheService> appCacheService =
|
||||
do_GetService(NS_APPLICATIONCACHESERVICE_CONTRACTID);
|
||||
|
||||
|
@ -582,7 +707,7 @@ HttpChannelParent::DoAsyncOpen( const URIParams& aURI,
|
|||
|
||||
if (setChooseApplicationCache) {
|
||||
OriginAttributes attrs;
|
||||
NS_GetOriginAttributes(mChannel, attrs);
|
||||
NS_GetOriginAttributes(httpChannel, attrs);
|
||||
|
||||
nsCOMPtr<nsIPrincipal> principal =
|
||||
BasePrincipal::CreateCodebasePrincipal(uri, attrs);
|
||||
|
@ -596,17 +721,61 @@ HttpChannelParent::DoAsyncOpen( const URIParams& aURI,
|
|||
}
|
||||
}
|
||||
|
||||
mChannel->SetRequestContextID(aRequestContextID);
|
||||
httpChannel->SetRequestContextID(aRequestContextID);
|
||||
|
||||
// Store the strong reference of channel and parent listener object until
|
||||
// all the initialization procedure is complete without failure, to remove
|
||||
// cycle reference in fail case and to avoid memory leakage.
|
||||
mChannel = httpChannel.forget();
|
||||
mParentListener = parentListener.forget();
|
||||
mChannel->SetNotificationCallbacks(mParentListener);
|
||||
|
||||
|
||||
mSuspendAfterSynthesizeResponse = aSuspendAfterSynthesizeResponse;
|
||||
|
||||
if (!delayAsyncOpen) {
|
||||
InvokeAsyncOpen(NS_OK);
|
||||
}
|
||||
MOZ_ASSERT(!mBgParent);
|
||||
MOZ_ASSERT(mPromise.IsEmpty());
|
||||
// Wait for HttpBackgrounChannel to continue the async open procedure.
|
||||
++mAsyncOpenBarrier;
|
||||
RefPtr<GenericPromise> promise = WaitForBgParent();
|
||||
RefPtr<HttpChannelParent> self = this;
|
||||
promise->Then(AbstractThread::MainThread(), __func__,
|
||||
[self]() {
|
||||
self->mRequest.Complete();
|
||||
self->TryInvokeAsyncOpen(NS_OK);
|
||||
},
|
||||
[self](nsresult aStatus) {
|
||||
self->mRequest.Complete();
|
||||
self->TryInvokeAsyncOpen(aStatus);
|
||||
})
|
||||
->Track(mRequest);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
already_AddRefed<GenericPromise>
|
||||
HttpChannelParent::WaitForBgParent()
|
||||
{
|
||||
LOG(("HttpChannelParent::WaitForBgParent [this=%p]\n", this));
|
||||
MOZ_ASSERT(!mBgParent);
|
||||
MOZ_ASSERT(mChannel);
|
||||
|
||||
|
||||
nsCOMPtr<nsIBackgroundChannelRegistrar> registrar =
|
||||
do_GetService(NS_BACKGROUNDCHANNELREGISTRAR_CONTRACTID);
|
||||
MOZ_ASSERT(registrar);
|
||||
registrar->LinkHttpChannel(mChannel->ChannelId(), this);
|
||||
|
||||
if (mBgParent) {
|
||||
already_AddRefed<GenericPromise> promise = mPromise.Ensure(__func__);
|
||||
// resolve promise immediatedly if bg channel is ready.
|
||||
mPromise.Resolve(true, __func__);
|
||||
return promise;
|
||||
}
|
||||
|
||||
return mPromise.Ensure(__func__);;
|
||||
}
|
||||
|
||||
bool
|
||||
HttpChannelParent::ConnectChannel(const uint32_t& registrarId, const bool& shouldIntercept)
|
||||
{
|
||||
|
@ -647,6 +816,20 @@ HttpChannelParent::ConnectChannel(const uint32_t& registrarId, const bool& shoul
|
|||
}
|
||||
}
|
||||
|
||||
MOZ_ASSERT(!mBgParent);
|
||||
MOZ_ASSERT(mPromise.IsEmpty());
|
||||
// Waiting for background channel
|
||||
RefPtr<GenericPromise> promise = WaitForBgParent();
|
||||
RefPtr<HttpChannelParent> self = this;
|
||||
promise->Then(AbstractThread::MainThread(), __func__,
|
||||
[self]() {
|
||||
self->mRequest.Complete();
|
||||
},
|
||||
[self](const nsresult& aResult) {
|
||||
NS_ERROR("failed to establish the background channel");
|
||||
self->mRequest.Complete();
|
||||
})
|
||||
->Track(mRequest);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -803,15 +986,89 @@ HttpChannelParent::RecvRedirect2Verify(const nsresult& result,
|
|||
}
|
||||
}
|
||||
|
||||
// Continue the verification procedure if child has veto the redirection.
|
||||
if (NS_FAILED(result)) {
|
||||
ContinueRedirect2Verify(result);
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
// Wait for background channel ready on target channel
|
||||
nsCOMPtr<nsIRedirectChannelRegistrar> redirectReg =
|
||||
do_GetService(NS_REDIRECTCHANNELREGISTRAR_CONTRACTID);
|
||||
MOZ_ASSERT(redirectReg);
|
||||
|
||||
nsCOMPtr<nsIParentChannel> redirectParentChannel;
|
||||
rv = redirectReg->GetParentChannel(mRedirectRegistrarId,
|
||||
getter_AddRefs(redirectParentChannel));
|
||||
MOZ_ASSERT(redirectParentChannel);
|
||||
if (!redirectParentChannel) {
|
||||
ContinueRedirect2Verify(rv);
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIParentRedirectingChannel> redirectedParent =
|
||||
do_QueryInterface(redirectParentChannel);
|
||||
if (!redirectedParent) {
|
||||
// Continue verification procedure if redirecting to non-Http protocol
|
||||
ContinueRedirect2Verify(result);
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
// Ask redirected channel if verification can proceed.
|
||||
// ContinueRedirect2Verify will be invoked when redirected channel is ready.
|
||||
redirectedParent->ContinueVerification(this);
|
||||
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
// from nsIParentRedirectingChannel
|
||||
NS_IMETHODIMP
|
||||
HttpChannelParent::ContinueVerification(nsIAsyncVerifyRedirectReadyCallback* aCallback)
|
||||
{
|
||||
LOG(("HttpChannelParent::ContinueVerification [this=%p callback=%p]\n",
|
||||
this, aCallback));
|
||||
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(aCallback);
|
||||
|
||||
// Continue the verification procedure if background channel is ready.
|
||||
if (mBgParent) {
|
||||
aCallback->ReadyToVerify(NS_OK);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// ConnectChannel must be received before Redirect2Verify.
|
||||
MOZ_ASSERT(!mPromise.IsEmpty());
|
||||
|
||||
// Otherwise, wait for the background channel.
|
||||
RefPtr<GenericPromise> promise = WaitForBgParent();
|
||||
nsCOMPtr<nsIAsyncVerifyRedirectReadyCallback> callback = aCallback;
|
||||
promise->Then(AbstractThread::MainThread(), __func__,
|
||||
[callback]() {
|
||||
callback->ReadyToVerify(NS_OK);
|
||||
},
|
||||
[callback](const nsresult& aResult) {
|
||||
NS_ERROR("failed to establish the background channel");
|
||||
callback->ReadyToVerify(aResult);
|
||||
});
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
HttpChannelParent::ContinueRedirect2Verify(const nsresult& aResult)
|
||||
{
|
||||
LOG(("HttpChannelParent::ContinueRedirect2Verify [this=%p result=%" PRIx32 "]\n",
|
||||
this, static_cast<uint32_t>(aResult)));
|
||||
|
||||
if (!mRedirectCallback) {
|
||||
// This should according the logic never happen, log the situation.
|
||||
if (mReceivedRedirect2Verify)
|
||||
LOG(("RecvRedirect2Verify[%p]: Duplicate fire", this));
|
||||
if (mSentRedirect1BeginFailed)
|
||||
LOG(("RecvRedirect2Verify[%p]: Send to child failed", this));
|
||||
if (mSentRedirect1Begin && NS_FAILED(result))
|
||||
if ((mRedirectRegistrarId > 0) && NS_FAILED(aResult))
|
||||
LOG(("RecvRedirect2Verify[%p]: Redirect failed", this));
|
||||
if (mSentRedirect1Begin && NS_SUCCEEDED(result))
|
||||
if ((mRedirectRegistrarId > 0) && NS_SUCCEEDED(aResult))
|
||||
LOG(("RecvRedirect2Verify[%p]: Redirect succeeded", this));
|
||||
if (!mRedirectChannel)
|
||||
LOG(("RecvRedirect2Verify[%p]: Missing redirect channel", this));
|
||||
|
@ -823,20 +1080,19 @@ HttpChannelParent::RecvRedirect2Verify(const nsresult& result,
|
|||
mReceivedRedirect2Verify = true;
|
||||
|
||||
if (mRedirectCallback) {
|
||||
LOG(("HttpChannelParent::RecvRedirect2Verify call OnRedirectVerifyCallback"
|
||||
LOG(("HttpChannelParent::ContinueRedirect2Verify call OnRedirectVerifyCallback"
|
||||
" [this=%p result=%" PRIx32 ", mRedirectCallback=%p]\n",
|
||||
this, static_cast<uint32_t>(result), mRedirectCallback.get()));
|
||||
mRedirectCallback->OnRedirectVerifyCallback(result);
|
||||
this, static_cast<uint32_t>(aResult), mRedirectCallback.get()));
|
||||
mRedirectCallback->OnRedirectVerifyCallback(aResult);
|
||||
mRedirectCallback = nullptr;
|
||||
}
|
||||
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
HttpChannelParent::RecvDocumentChannelCleanup()
|
||||
{
|
||||
// From now on only using mAssociatedContentSecurity. Free everything else.
|
||||
CleanupBackgroundChannel(); // Background channel can be closed.
|
||||
mChannel = nullptr; // Reclaim some memory sooner.
|
||||
mCacheEntry = nullptr; // Else we'll block other channels reading same URI
|
||||
return IPC_OK();
|
||||
|
@ -1128,6 +1384,7 @@ HttpChannelParent::OnStartRequest(nsIRequest *aRequest, nsISupports *aContext)
|
|||
{
|
||||
LOG(("HttpChannelParent::OnStartRequest [this=%p, aRequest=%p]\n",
|
||||
this, aRequest));
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
MOZ_RELEASE_ASSERT(!mDivertingFromChild,
|
||||
"Cannot call OnStartRequest if diverting is set!");
|
||||
|
@ -1236,6 +1493,17 @@ HttpChannelParent::OnStartRequest(nsIRequest *aRequest, nsISupports *aContext)
|
|||
rv = NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
requestHead->Exit();
|
||||
|
||||
// OnStartRequest is sent to content process successfully.
|
||||
// Notify PHttpBackgroundChannelChild that all following IPC mesasges
|
||||
// should be run after OnStartRequest is handled.
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
MOZ_ASSERT(mBgParent);
|
||||
if (!mBgParent->OnStartRequestSent()) {
|
||||
rv = NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -1246,6 +1514,7 @@ HttpChannelParent::OnStopRequest(nsIRequest *aRequest,
|
|||
{
|
||||
LOG(("HttpChannelParent::OnStopRequest: [this=%p aRequest=%p status=%" PRIx32 "]\n",
|
||||
this, aRequest, static_cast<uint32_t>(aStatusCode)));
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
MOZ_RELEASE_ASSERT(!mDivertingFromChild,
|
||||
"Cannot call OnStopRequest if diverting is set!");
|
||||
|
@ -1269,8 +1538,15 @@ HttpChannelParent::OnStopRequest(nsIRequest *aRequest,
|
|||
mChannel->GetCacheReadStart(&timing.cacheReadStart);
|
||||
mChannel->GetCacheReadEnd(&timing.cacheReadEnd);
|
||||
|
||||
if (mIPCClosed || !SendOnStopRequest(aStatusCode, timing))
|
||||
// Either IPC channel is closed or background channel
|
||||
// is ready to send OnStopRequest.
|
||||
MOZ_ASSERT(mIPCClosed || mBgParent);
|
||||
|
||||
if (mIPCClosed ||
|
||||
!mBgParent || !mBgParent->OnStopRequest(aStatusCode, timing)) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -1285,8 +1561,9 @@ HttpChannelParent::OnDataAvailable(nsIRequest *aRequest,
|
|||
uint64_t aOffset,
|
||||
uint32_t aCount)
|
||||
{
|
||||
LOG(("HttpChannelParent::OnDataAvailable [this=%p aRequest=%p]\n",
|
||||
this, aRequest));
|
||||
LOG(("HttpChannelParent::OnDataAvailable [this=%p aRequest=%p offset=%" PRIu64
|
||||
" count=%" PRIu32 "]\n", this, aRequest, aOffset, aCount));
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
MOZ_RELEASE_ASSERT(!mDivertingFromChild,
|
||||
"Cannot call OnDataAvailable if diverting is set!");
|
||||
|
@ -1313,8 +1590,13 @@ HttpChannelParent::OnDataAvailable(nsIRequest *aRequest,
|
|||
return rv;
|
||||
}
|
||||
|
||||
if (mIPCClosed || !SendOnTransportAndData(channelStatus, transportStatus,
|
||||
aOffset, toRead, data)) {
|
||||
// Either IPC channel is closed or background channel
|
||||
// is ready to send OnTransportAndData.
|
||||
MOZ_ASSERT(mIPCClosed || mBgParent);
|
||||
|
||||
if (mIPCClosed || !mBgParent ||
|
||||
!mBgParent->OnTransportAndData(channelStatus, transportStatus,
|
||||
aOffset, toRead, data)) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
|
@ -1336,16 +1618,25 @@ HttpChannelParent::OnProgress(nsIRequest *aRequest,
|
|||
int64_t aProgress,
|
||||
int64_t aProgressMax)
|
||||
{
|
||||
LOG(("HttpChannelParent::OnStatus [this=%p progress=%" PRId64 "max=%" PRId64
|
||||
"]\n", this, aProgress, aProgressMax));
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
// If it indicates this precedes OnDataAvailable, child can derive the value in ODA.
|
||||
if (mIgnoreProgress) {
|
||||
mIgnoreProgress = false;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Either IPC channel is closed or background channel
|
||||
// is ready to send OnProgress.
|
||||
MOZ_ASSERT(mIPCClosed || mBgParent);
|
||||
|
||||
// Send OnProgress events to the child for data upload progress notifications
|
||||
// (i.e. status == NS_NET_STATUS_SENDING_TO) or if the channel has
|
||||
// LOAD_BACKGROUND set.
|
||||
if (mIPCClosed || !SendOnProgress(aProgress, aProgressMax)) {
|
||||
if (mIPCClosed || !mBgParent
|
||||
|| !mBgParent->OnProgress(aProgress, aProgressMax)) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
|
@ -1358,6 +1649,10 @@ HttpChannelParent::OnStatus(nsIRequest *aRequest,
|
|||
nsresult aStatus,
|
||||
const char16_t *aStatusArg)
|
||||
{
|
||||
LOG(("HttpChannelParent::OnStatus [this=%p status=%" PRIx32 "]\n",
|
||||
this, static_cast<uint32_t>(aStatus)));
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
// If this precedes OnDataAvailable, transportStatus will be derived in ODA.
|
||||
if (aStatus == NS_NET_STATUS_RECEIVING_FROM ||
|
||||
aStatus == NS_NET_STATUS_READING) {
|
||||
|
@ -1368,8 +1663,12 @@ HttpChannelParent::OnStatus(nsIRequest *aRequest,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
// Either IPC channel is closed or background channel
|
||||
// is ready to send OnStatus.
|
||||
MOZ_ASSERT(mIPCClosed || mBgParent);
|
||||
|
||||
// Otherwise, send to child now
|
||||
if (mIPCClosed || !SendOnStatus(aStatus)) {
|
||||
if (mIPCClosed || !mBgParent || !mBgParent->OnStatus(aStatus)) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
|
@ -1396,8 +1695,11 @@ HttpChannelParent::SetParentListener(HttpChannelParentListener* aListener)
|
|||
NS_IMETHODIMP
|
||||
HttpChannelParent::NotifyTrackingProtectionDisabled()
|
||||
{
|
||||
if (!mIPCClosed)
|
||||
Unused << SendNotifyTrackingProtectionDisabled();
|
||||
LOG(("HttpChannelParent::NotifyTrackingProtectionDisabled [this=%p]\n", this));
|
||||
if (!mIPCClosed) {
|
||||
MOZ_ASSERT(mBgParent);
|
||||
Unused << mBgParent->OnNotifyTrackingProtectionDisabled();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -1406,13 +1708,10 @@ HttpChannelParent::SetClassifierMatchedInfo(const nsACString& aList,
|
|||
const nsACString& aProvider,
|
||||
const nsACString& aPrefix)
|
||||
{
|
||||
LOG(("HttpChannelParent::SetClassifierMatchedInfo [this=%p]\n", this));
|
||||
if (!mIPCClosed) {
|
||||
ClassifierInfo info;
|
||||
info.list() = aList;
|
||||
info.prefix() = aPrefix;
|
||||
info.provider() = aProvider;
|
||||
|
||||
Unused << SendSetClassifierMatchedInfo(info);
|
||||
MOZ_ASSERT(mBgParent);
|
||||
Unused << mBgParent->OnSetClassifierMatchedInfo(aList, aProvider, aPrefix);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -1420,8 +1719,11 @@ HttpChannelParent::SetClassifierMatchedInfo(const nsACString& aList,
|
|||
NS_IMETHODIMP
|
||||
HttpChannelParent::NotifyTrackingResource()
|
||||
{
|
||||
if (!mIPCClosed)
|
||||
Unused << SendNotifyTrackingResource();
|
||||
LOG(("HttpChannelParent::NotifyTrackingResource [this=%p]\n", this));
|
||||
if (!mIPCClosed) {
|
||||
MOZ_ASSERT(mBgParent);
|
||||
Unused << mBgParent->OnNotifyTrackingResource();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -1487,7 +1789,9 @@ HttpChannelParent::StartRedirect(uint32_t registrarId,
|
|||
}
|
||||
|
||||
// Bug 621446 investigation
|
||||
mSentRedirect1Begin = true;
|
||||
// Store registrar Id of the new channel to find the redirect
|
||||
// HttpChannelParent later in verification phase.
|
||||
mRedirectRegistrarId = registrarId;
|
||||
|
||||
// Result is handled in RecvRedirect2Verify above
|
||||
|
||||
|
@ -1704,14 +2008,11 @@ HttpChannelParent::StartDiversion()
|
|||
MOZ_ASSERT(NS_SUCCEEDED(rvdbg));
|
||||
mDivertListener = nullptr;
|
||||
|
||||
if (NS_WARN_IF(mIPCClosed || !SendFlushedForDiversion())) {
|
||||
FailDiversion(NS_ERROR_UNEXPECTED);
|
||||
return;
|
||||
}
|
||||
// Either IPC channel is closed or background channel
|
||||
// is ready to send FlushedForDiversion and DivertMessages.
|
||||
MOZ_ASSERT(mIPCClosed || mBgParent);
|
||||
|
||||
// The listener chain should now be setup; tell HttpChannelChild to divert
|
||||
// the OnDataAvailables and OnStopRequest to this HttpChannelParent.
|
||||
if (NS_WARN_IF(mIPCClosed || !SendDivertMessages())) {
|
||||
if (NS_WARN_IF(mIPCClosed || !mBgParent || !mBgParent->OnDiversion())) {
|
||||
FailDiversion(NS_ERROR_UNEXPECTED);
|
||||
return;
|
||||
}
|
||||
|
@ -1789,12 +2090,16 @@ HttpChannelParent::NotifyDiversionFailed(nsresult aErrorCode,
|
|||
if (!isPending) {
|
||||
mParentListener->OnStopRequest(mChannel, nullptr, aErrorCode);
|
||||
}
|
||||
mParentListener = nullptr;
|
||||
mChannel = nullptr;
|
||||
|
||||
if (!mIPCClosed) {
|
||||
Unused << DoSendDeleteSelf();
|
||||
}
|
||||
|
||||
// DoSendDeleteSelf will need channel Id to remove the strong reference in
|
||||
// BackgroundChannelRegistrar if channel pairing is aborted.
|
||||
// Thus we need to keep mChannel until DoSendDeleteSelf is done.
|
||||
mParentListener = nullptr;
|
||||
mChannel = nullptr;
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -1837,6 +2142,9 @@ HttpChannelParent::DoSendDeleteSelf()
|
|||
{
|
||||
bool rv = SendDeleteSelf();
|
||||
mIPCClosed = true;
|
||||
|
||||
CleanupBackgroundChannel();
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -1887,6 +2195,22 @@ HttpChannelParent::IssueWarning(uint32_t aWarning, bool aAsError)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// nsIAsyncVerifyRedirectReadyCallback
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
NS_IMETHODIMP
|
||||
HttpChannelParent::ReadyToVerify(nsresult aResult)
|
||||
{
|
||||
LOG(("HttpChannelParent::RecvRedirect2Verify [this=%p result=%" PRIx32 "]\n",
|
||||
this, static_cast<uint32_t>(aResult)));
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
ContinueRedirect2Verify(aResult);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
HttpChannelParent::DoSendSetPriority(int16_t aValue)
|
||||
{
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "mozilla/net/PHttpChannelParent.h"
|
||||
#include "mozilla/net/NeckoCommon.h"
|
||||
#include "mozilla/net/NeckoParent.h"
|
||||
#include "mozilla/MozPromise.h"
|
||||
#include "nsIObserver.h"
|
||||
#include "nsIParentRedirectingChannel.h"
|
||||
#include "nsIProgressEventSink.h"
|
||||
|
@ -37,6 +38,7 @@ class PBrowserOrId;
|
|||
|
||||
namespace net {
|
||||
|
||||
class HttpBackgroundChannelParent;
|
||||
class HttpChannelParentListener;
|
||||
class ChannelEventQueue;
|
||||
|
||||
|
@ -52,6 +54,7 @@ class HttpChannelParent final : public nsIInterfaceRequestor
|
|||
, public nsIAuthPromptProvider
|
||||
, public nsIDeprecationWarner
|
||||
, public HttpChannelSecurityWarningReporter
|
||||
, public nsIAsyncVerifyRedirectReadyCallback
|
||||
{
|
||||
virtual ~HttpChannelParent();
|
||||
|
||||
|
@ -65,6 +68,7 @@ public:
|
|||
NS_DECL_NSIINTERFACEREQUESTOR
|
||||
NS_DECL_NSIAUTHPROMPTPROVIDER
|
||||
NS_DECL_NSIDEPRECATIONWARNER
|
||||
NS_DECL_NSIASYNCVERIFYREDIRECTREADYCALLBACK
|
||||
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(HTTP_CHANNEL_PARENT_IID)
|
||||
|
||||
|
@ -99,10 +103,22 @@ public:
|
|||
MOZ_MUST_USE nsresult OpenAlternativeOutputStream(const nsACString & type,
|
||||
nsIOutputStream * *_retval);
|
||||
|
||||
// Callbacks for each asynchronous tasks required in AsyncOpen
|
||||
// procedure, will call InvokeAsyncOpen when all the expected
|
||||
// tasks is finished successfully or when any failure happened.
|
||||
// @see mAsyncOpenBarrier.
|
||||
void TryInvokeAsyncOpen(nsresult aRv);
|
||||
|
||||
void InvokeAsyncOpen(nsresult rv);
|
||||
|
||||
// Calls SendSetPriority if mIPCClosed is false.
|
||||
void DoSendSetPriority(int16_t aValue);
|
||||
|
||||
// Callback while background channel is ready.
|
||||
void OnBackgroundParentReady(HttpBackgroundChannelParent* aBgParent);
|
||||
// Callback while background channel is destroyed.
|
||||
void OnBackgroundParentDestroyed();
|
||||
|
||||
protected:
|
||||
// used to connect redirected-to channel in parent with just created
|
||||
// ChildChannel. Used during redirects.
|
||||
|
@ -217,6 +233,26 @@ private:
|
|||
void MaybeFlushPendingDiversion();
|
||||
void ResponseSynthesized();
|
||||
|
||||
// final step for Redirect2Verify procedure, will be invoked while both
|
||||
// redirecting and redirected channel are ready or any error happened.
|
||||
// OnRedirectVerifyCallback will be invoked for finishing the async
|
||||
// redirect verification procedure.
|
||||
void ContinueRedirect2Verify(const nsresult& aResult);
|
||||
|
||||
void AsyncOpenFailed(nsresult aRv);
|
||||
|
||||
// Request to pair with a HttpBackgroundChannelParent with the same channel
|
||||
// id, a promise will be returned so the caller can append callbacks on it.
|
||||
// If called multiple times before mBgParent is available, the same promise
|
||||
// will be returned and the callbacks will be invoked in order.
|
||||
already_AddRefed<GenericPromise> WaitForBgParent();
|
||||
|
||||
// Remove the association with background channel after main-thread IPC
|
||||
// is about to be destroyed or no further event is going to be sent, i.e.,
|
||||
// DocumentChannelCleanup.
|
||||
void CleanupBackgroundChannel();
|
||||
|
||||
friend class HttpBackgroundChannelParent;
|
||||
friend class DivertDataAvailableEvent;
|
||||
friend class DivertStopRequestEvent;
|
||||
friend class DivertCompleteEvent;
|
||||
|
@ -236,7 +272,6 @@ private:
|
|||
// since the information can be recontructed from ODA.
|
||||
bool mIgnoreProgress : 1;
|
||||
|
||||
bool mSentRedirect1Begin : 1;
|
||||
bool mSentRedirect1BeginFailed : 1;
|
||||
bool mReceivedRedirect2Verify : 1;
|
||||
|
||||
|
@ -272,6 +307,20 @@ private:
|
|||
dom::TabId mNestedFrameId;
|
||||
|
||||
RefPtr<ChannelEventQueue> mEventQ;
|
||||
|
||||
RefPtr<HttpBackgroundChannelParent> mBgParent;
|
||||
|
||||
// Number of events to wait before actually invoking AsyncOpen on the main
|
||||
// channel. For each asynchronous step required before InvokeAsyncOpen, should
|
||||
// increase 1 to mAsyncOpenBarrier and invoke TryInvokeAsyncOpen after
|
||||
// finished. This attribute is main thread only.
|
||||
uint8_t mAsyncOpenBarrier = 0;
|
||||
|
||||
// Corresponding redirect channel registrar Id. 0 means redirection is not started.
|
||||
uint32_t mRedirectRegistrarId = 0;
|
||||
|
||||
MozPromiseHolder<GenericPromise> mPromise;
|
||||
MozPromiseRequestHolder<GenericPromise> mRequest;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(HttpChannelParent,
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "nsIHttpHeaderVisitor.h"
|
||||
#include "nsIRedirectChannelRegistrar.h"
|
||||
#include "nsIPromptFactory.h"
|
||||
#include "nsIWindowWatcher.h"
|
||||
#include "nsQueryObject.h"
|
||||
|
||||
using mozilla::Unused;
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set sw=2 ts=8 et tw=80 ft=cpp : */
|
||||
|
||||
/* 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 protocol PBackground;
|
||||
include NeckoChannelParams;
|
||||
include PURLClassifierInfo;
|
||||
|
||||
include "mozilla/net/NeckoMessageUtils.h";
|
||||
|
||||
using struct mozilla::net::ResourceTimingStruct from "mozilla/net/TimingStruct.h";
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
async protocol PHttpBackgroundChannel
|
||||
{
|
||||
manager PBackground;
|
||||
|
||||
child:
|
||||
// OnStartRequest is sent over main thread IPC. The following
|
||||
// OnTransportAndData/OnStopRequest/OnProgress/OnStatus/FlushForDiversion/
|
||||
// DivertMessages needs to wait in content process until OnStartRequest
|
||||
// is processed. For synchronizing the event sequence.
|
||||
async OnStartRequestSent();
|
||||
|
||||
// Combines a single OnDataAvailable and its associated OnProgress &
|
||||
// OnStatus calls into one IPDL message
|
||||
async OnTransportAndData(nsresult channelStatus,
|
||||
nsresult transportStatus,
|
||||
uint64_t offset,
|
||||
uint32_t count,
|
||||
nsCString data);
|
||||
|
||||
async OnStopRequest(nsresult channelStatus, ResourceTimingStruct timing);
|
||||
|
||||
async OnProgress(int64_t progress, int64_t progressMax);
|
||||
|
||||
async OnStatus(nsresult status);
|
||||
|
||||
// Parent has been suspended for diversion; no more events to be enqueued.
|
||||
async FlushedForDiversion();
|
||||
|
||||
// Child should resume processing the ChannelEventQueue, i.e. diverting any
|
||||
// OnDataAvailable and OnStopRequest messages in the queue back to the parent.
|
||||
async DivertMessages();
|
||||
|
||||
// Tell the child that tracking protection was disabled for this load.
|
||||
async NotifyTrackingProtectionDisabled();
|
||||
|
||||
// Tell the child that the resource being loaded is on the tracking
|
||||
// protection list.
|
||||
async NotifyTrackingResource();
|
||||
|
||||
// Tell the child information of matched URL againts SafeBrowsing list
|
||||
async SetClassifierMatchedInfo(ClassifierInfo info);
|
||||
|
||||
async __delete__();
|
||||
|
||||
};
|
||||
|
||||
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
|
@ -10,7 +10,6 @@ include InputStreamParams;
|
|||
include URIParams;
|
||||
include PBackgroundSharedTypes;
|
||||
include NeckoChannelParams;
|
||||
include PURLClassifierInfo;
|
||||
|
||||
include "mozilla/net/NeckoMessageUtils.h";
|
||||
|
||||
|
@ -109,20 +108,6 @@ child:
|
|||
nsCString altDataType,
|
||||
int64_t altDataLength);
|
||||
|
||||
// Combines a single OnDataAvailable and its associated OnProgress &
|
||||
// OnStatus calls into one IPDL message
|
||||
async OnTransportAndData(nsresult channelStatus,
|
||||
nsresult transportStatus,
|
||||
uint64_t offset,
|
||||
uint32_t count,
|
||||
nsCString data);
|
||||
|
||||
async OnStopRequest(nsresult channelStatus, ResourceTimingStruct timing);
|
||||
|
||||
async OnProgress(int64_t progress, int64_t progressMax);
|
||||
|
||||
async OnStatus(nsresult status);
|
||||
|
||||
// Used to cancel child channel if we hit errors during creating and
|
||||
// AsyncOpen of nsHttpChannel on the parent.
|
||||
async FailedAsyncOpen(nsresult status);
|
||||
|
@ -144,20 +129,6 @@ child:
|
|||
async AssociateApplicationCache(nsCString groupID,
|
||||
nsCString clientID);
|
||||
|
||||
// Tell the child that tracking protection was disabled for this load.
|
||||
async NotifyTrackingProtectionDisabled();
|
||||
|
||||
// Tell the child that the resource being loaded is on the tracking
|
||||
// protection list.
|
||||
async NotifyTrackingResource();
|
||||
|
||||
// Parent has been suspended for diversion; no more events to be enqueued.
|
||||
async FlushedForDiversion();
|
||||
|
||||
// Child should resume processing the ChannelEventQueue, i.e. diverting any
|
||||
// OnDataAvailable and OnStopRequest messages in the queue back to the parent.
|
||||
async DivertMessages();
|
||||
|
||||
// Report a security message to the console associated with this
|
||||
// channel.
|
||||
async ReportSecurityMessage(nsString messageTag, nsString messageCategory);
|
||||
|
@ -169,9 +140,6 @@ child:
|
|||
// Tell the child to issue a deprecation warning.
|
||||
async IssueDeprecationWarning(uint32_t warning, bool asError);
|
||||
|
||||
// Tell the child information of matched URL againts SafeBrowsing list
|
||||
async SetClassifierMatchedInfo(ClassifierInfo info);
|
||||
|
||||
both:
|
||||
// After receiving this message, the parent also calls
|
||||
// SendFinishInterceptedRedirect, and makes sure not to send any more messages
|
||||
|
|
|
@ -8,6 +8,7 @@ with Files('**'):
|
|||
BUG_COMPONENT = ('Core', 'Networking: HTTP')
|
||||
|
||||
XPIDL_SOURCES += [
|
||||
'nsIBackgroundChannelRegistrar.idl',
|
||||
'nsIHstsPrimingCallback.idl',
|
||||
'nsIHttpActivityObserver.idl',
|
||||
'nsIHttpAuthenticableChannel.idl',
|
||||
|
@ -39,6 +40,8 @@ EXPORTS.mozilla.net += [
|
|||
'AltDataOutputStreamChild.h',
|
||||
'AltDataOutputStreamParent.h',
|
||||
'HttpAuthUtils.h',
|
||||
'HttpBackgroundChannelChild.h',
|
||||
'HttpBackgroundChannelParent.h',
|
||||
'HttpBaseChannel.h',
|
||||
'HttpChannelChild.h',
|
||||
'HttpChannelParent.h',
|
||||
|
@ -58,6 +61,7 @@ UNIFIED_SOURCES += [
|
|||
'AltDataOutputStreamParent.cpp',
|
||||
'AlternateServices.cpp',
|
||||
'ASpdySession.cpp',
|
||||
'BackgroundChannelRegistrar.cpp',
|
||||
'CacheControlParser.cpp',
|
||||
'ConnectionDiagnostics.cpp',
|
||||
'HSTSPrimerListener.cpp',
|
||||
|
@ -66,6 +70,8 @@ UNIFIED_SOURCES += [
|
|||
'Http2Session.cpp',
|
||||
'Http2Stream.cpp',
|
||||
'HttpAuthUtils.cpp',
|
||||
'HttpBackgroundChannelChild.cpp',
|
||||
'HttpBackgroundChannelParent.cpp',
|
||||
'HttpBaseChannel.cpp',
|
||||
'HttpChannelChild.cpp',
|
||||
'HttpChannelParent.cpp',
|
||||
|
@ -101,6 +107,7 @@ SOURCES += [
|
|||
|
||||
IPDL_SOURCES += [
|
||||
'PAltDataOutputStream.ipdl',
|
||||
'PHttpBackgroundChannel.ipdl',
|
||||
'PHttpChannel.ipdl',
|
||||
]
|
||||
|
||||
|
|
|
@ -64,6 +64,7 @@
|
|||
#include "nsIClassOfService.h"
|
||||
#include "nsIPermissionManager.h"
|
||||
#include "nsIPrincipal.h"
|
||||
#include "nsIScriptError.h"
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
#include "nsISSLStatus.h"
|
||||
#include "nsISSLStatusProvider.h"
|
||||
|
|
|
@ -5,11 +5,14 @@
|
|||
|
||||
// HttpLog.h should generally be included first
|
||||
#include "HttpLog.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include "nsHttpChunkedDecoder.h"
|
||||
#include <algorithm>
|
||||
#include "plstr.h"
|
||||
|
||||
#include "mozilla/Unused.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include "nsISocketTransportService.h"
|
||||
#include <algorithm>
|
||||
#include "mozilla/ChaosMode.h"
|
||||
#include "mozilla/SizePrintfMacros.h"
|
||||
#include "mozilla/Unused.h"
|
||||
#include "nsIURI.h"
|
||||
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
/* -*- 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 "nsISupports.idl"
|
||||
|
||||
%{ C++
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
class HttpBackgroundChannelParent;
|
||||
class HttpChannelParent;
|
||||
}
|
||||
}
|
||||
%}
|
||||
|
||||
[ptr] native HttpChannelParent(mozilla::net::HttpChannelParent);
|
||||
[ptr] native HttpBackgroundChannelParent(mozilla::net::HttpBackgroundChannelParent);
|
||||
|
||||
/*
|
||||
* Registrar for pairing HttpChannelParent and HttpBackgroundChannelParent via
|
||||
* channel Id. HttpChannelParent::OnBackgroundParentReady and
|
||||
* HttpBackgroundChannelParent::LinkToChannel will be invoked to notify the
|
||||
* existence of associated channel object.
|
||||
*/
|
||||
[builtinclass, uuid(8acaa9b1-f0c4-4ade-baeb-39b0d4b96e5b)]
|
||||
interface nsIBackgroundChannelRegistrar : nsISupports
|
||||
{
|
||||
/*
|
||||
* Link the provided channel parent actor with the given channel Id.
|
||||
* callbacks will be invoked immediately when the HttpBackgroundChannelParent
|
||||
* associated with the same channel Id is found. Store the HttpChannelParent
|
||||
* until a matched linkBackgroundChannel is invoked.
|
||||
*
|
||||
* @param aKey the channel Id
|
||||
* @param aChannel the channel parent actor to be paired
|
||||
*/
|
||||
[noscript,notxpcom,nostdcall] void linkHttpChannel(in uint64_t aKey,
|
||||
in HttpChannelParent aChannel);
|
||||
|
||||
/*
|
||||
* Link the provided background channel with the given channel Id.
|
||||
* callbacks will be invoked immediately when the HttpChannelParent associated
|
||||
* with the same channel Id is found. Store the HttpBackgroundChannelParent
|
||||
* until a matched linkHttpChannel is invoked.
|
||||
*
|
||||
* @param aKey the channel Id
|
||||
* @param aBgChannel the background channel to be paired
|
||||
*/
|
||||
[noscript,notxpcom,nostdcall] void linkBackgroundChannel(in uint64_t aKey,
|
||||
in HttpBackgroundChannelParent aBgChannel);
|
||||
|
||||
/*
|
||||
* Delete previous stored HttpChannelParent or HttpBackgroundChannelParent
|
||||
* if no need to wait for the paired channel object, e.g. background channel
|
||||
* is destroyed before pairing is completed.
|
||||
*
|
||||
* @param aKey the channel Id
|
||||
*/
|
||||
[noscript,notxpcom,nostdcall] void deleteChannel(in uint64_t aKey);
|
||||
|
||||
};
|
|
@ -60,6 +60,16 @@ ExtensionPreferencesManager.addSetting("network.networkPredictionEnabled", {
|
|||
},
|
||||
});
|
||||
|
||||
ExtensionPreferencesManager.addSetting("network.peerConnectionEnabled", {
|
||||
prefNames: [
|
||||
"media.peerconnection.enabled",
|
||||
],
|
||||
|
||||
setCallback(value) {
|
||||
return {[this.prefNames[0]]: value};
|
||||
},
|
||||
});
|
||||
|
||||
ExtensionPreferencesManager.addSetting("network.webRTCIPHandlingPolicy", {
|
||||
prefNames: [
|
||||
"media.peerconnection.ice.default_address_only",
|
||||
|
@ -119,6 +129,11 @@ this.privacy = class extends ExtensionAPI {
|
|||
Preferences.get("network.http.speculative-parallel-limit") > 0 &&
|
||||
!Preferences.get("network.dns.disablePrefetch");
|
||||
}),
|
||||
peerConnectionEnabled: getAPI(extension,
|
||||
"network.peerConnectionEnabled",
|
||||
() => {
|
||||
return Preferences.get("media.peerconnection.enabled");
|
||||
}),
|
||||
webRTCIPHandlingPolicy: getAPI(extension,
|
||||
"network.webRTCIPHandlingPolicy",
|
||||
() => {
|
||||
|
|
|
@ -38,6 +38,10 @@
|
|||
"$ref": "types.Setting",
|
||||
"description": "If enabled, the browser attempts to speed up your web browsing experience by pre-resolving DNS entries, prerendering sites (<code><link rel='prefetch' ...></code>), and preemptively opening TCP and SSL connections to servers. This preference's value is a boolean, defaulting to <code>true</code>."
|
||||
},
|
||||
"peerConnectionEnabled": {
|
||||
"$ref": "types.Setting",
|
||||
"description": "Allow users to enable and disable RTCPeerConnections (aka WebRTC)."
|
||||
},
|
||||
"webRTCIPHandlingPolicy": {
|
||||
"$ref": "types.Setting",
|
||||
"description": "Allow users to specify the media performance/privacy tradeoffs which impacts how WebRTC traffic will be routed and how much local address information is exposed. This preference's value is of type IPHandlingPolicy, defaulting to <code>default</code>."
|
||||
|
|
|
@ -214,46 +214,60 @@ add_task(async function test_privacy() {
|
|||
await promiseShutdownManager();
|
||||
});
|
||||
|
||||
add_task(async function test_privacy_webRTCIPHandlingPolicy() {
|
||||
// Create a object to hold the default values of all the prefs.
|
||||
const PREF_DEFAULTS = {
|
||||
"media.peerconnection.ice.default_address_only": null,
|
||||
"media.peerconnection.ice.no_host": null,
|
||||
"media.peerconnection.ice.proxy_only": null,
|
||||
// This test can be used for any settings that are added which utilize only
|
||||
// boolean prefs.
|
||||
add_task(async function test_privacy_boolean_prefs() {
|
||||
// Create an object to hold the values to which we will initialize the prefs.
|
||||
const SETTINGS = {
|
||||
"network.webRTCIPHandlingPolicy": {
|
||||
"media.peerconnection.ice.default_address_only": false,
|
||||
"media.peerconnection.ice.no_host": false,
|
||||
"media.peerconnection.ice.proxy_only": false,
|
||||
},
|
||||
"network.peerConnectionEnabled": {
|
||||
"media.peerconnection.enabled": true,
|
||||
},
|
||||
};
|
||||
|
||||
// Store the default values of each pref.
|
||||
for (let pref in PREF_DEFAULTS) {
|
||||
PREF_DEFAULTS[pref] = ExtensionPreferencesManager.getDefaultValue(pref);
|
||||
async function background() {
|
||||
browser.test.onMessage.addListener(async (msg, ...args) => {
|
||||
let data = args[0];
|
||||
// The second argument is the end of the api name,
|
||||
// e.g., "network.webRTCIPHandlingPolicy".
|
||||
let apiObj = args[1].split(".").reduce((o, i) => o[i], browser.privacy);
|
||||
let settingData;
|
||||
switch (msg) {
|
||||
case "set":
|
||||
await apiObj.set(data);
|
||||
settingData = await apiObj.get({});
|
||||
browser.test.sendMessage("settingData", settingData);
|
||||
break;
|
||||
|
||||
case "clear":
|
||||
await apiObj.clear(data);
|
||||
settingData = await apiObj.get({});
|
||||
browser.test.sendMessage("settingData", settingData);
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Set prefs to our initial values.
|
||||
for (let setting in SETTINGS) {
|
||||
for (let pref in SETTINGS[setting]) {
|
||||
Preferences.set(pref, SETTINGS[setting][pref]);
|
||||
}
|
||||
}
|
||||
|
||||
do_register_cleanup(() => {
|
||||
// Reset the prefs.
|
||||
for (let pref in PREF_DEFAULTS) {
|
||||
Preferences.reset(pref);
|
||||
for (let setting in SETTINGS) {
|
||||
for (let pref in SETTINGS[setting]) {
|
||||
Preferences.reset(pref);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
async function background() {
|
||||
browser.test.onMessage.addListener(async (msg, value) => {
|
||||
let rtcData;
|
||||
switch (msg) {
|
||||
case "set":
|
||||
await browser.privacy.network.webRTCIPHandlingPolicy.set({value});
|
||||
rtcData = await browser.privacy.network.webRTCIPHandlingPolicy.get({});
|
||||
browser.test.sendMessage("rtcData", rtcData);
|
||||
break;
|
||||
|
||||
case "clear":
|
||||
await browser.privacy.network.webRTCIPHandlingPolicy.clear({});
|
||||
rtcData = await browser.privacy.network.webRTCIPHandlingPolicy.get({});
|
||||
browser.test.sendMessage("rtcData", rtcData);
|
||||
break;
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
let extension = ExtensionTestUtils.loadExtension({
|
||||
background,
|
||||
manifest: {
|
||||
|
@ -265,33 +279,35 @@ add_task(async function test_privacy_webRTCIPHandlingPolicy() {
|
|||
await promiseStartupManager();
|
||||
await extension.startup();
|
||||
|
||||
async function testSetting(value, truePrefs) {
|
||||
extension.sendMessage("set", value);
|
||||
let data = await extension.awaitMessage("rtcData");
|
||||
async function testSetting(setting, value, truePrefs) {
|
||||
extension.sendMessage("set", {value: value}, setting);
|
||||
let data = await extension.awaitMessage("settingData");
|
||||
equal(data.value, value);
|
||||
for (let pref in PREF_DEFAULTS) {
|
||||
for (let pref in SETTINGS[setting]) {
|
||||
let prefValue = Preferences.get(pref);
|
||||
if (truePrefs.includes(pref)) {
|
||||
ok(prefValue, `${pref} set correctly for ${value}`);
|
||||
} else {
|
||||
equal(prefValue, PREF_DEFAULTS[pref], `${pref} contains default value for ${value}`);
|
||||
}
|
||||
equal(prefValue, truePrefs.includes(pref), `${pref} set correctly for ${value}`);
|
||||
}
|
||||
}
|
||||
|
||||
await testSetting(
|
||||
"network.webRTCIPHandlingPolicy",
|
||||
"default_public_and_private_interfaces",
|
||||
["media.peerconnection.ice.default_address_only"]);
|
||||
|
||||
await testSetting(
|
||||
"network.webRTCIPHandlingPolicy",
|
||||
"default_public_interface_only",
|
||||
["media.peerconnection.ice.default_address_only", "media.peerconnection.ice.no_host"]);
|
||||
|
||||
await testSetting(
|
||||
"network.webRTCIPHandlingPolicy",
|
||||
"disable_non_proxied_udp",
|
||||
["media.peerconnection.ice.proxy_only"]);
|
||||
|
||||
await testSetting("default", []);
|
||||
await testSetting("network.webRTCIPHandlingPolicy", "default", []);
|
||||
|
||||
await testSetting("network.peerConnectionEnabled", false, []);
|
||||
await testSetting("network.peerConnectionEnabled", true, ["media.peerconnection.enabled"]);
|
||||
|
||||
await extension.unload();
|
||||
|
||||
|
|
|
@ -49,7 +49,6 @@ ContentProcessSingleton.prototype = {
|
|||
case "app-startup": {
|
||||
Services.obs.addObserver(this, "console-api-log-event");
|
||||
Services.obs.addObserver(this, "xpcom-shutdown");
|
||||
cpmm.addMessageListener("DevTools:InitDebuggerServer", this);
|
||||
TelemetryController.observe(null, topic, null);
|
||||
break;
|
||||
}
|
||||
|
@ -103,19 +102,9 @@ ContentProcessSingleton.prototype = {
|
|||
case "xpcom-shutdown":
|
||||
Services.obs.removeObserver(this, "console-api-log-event");
|
||||
Services.obs.removeObserver(this, "xpcom-shutdown");
|
||||
cpmm.removeMessageListener("DevTools:InitDebuggerServer", this);
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
receiveMessage(message) {
|
||||
// load devtools component on-demand
|
||||
// Only reply if we are in a real content process
|
||||
if (Services.appinfo.processType == Services.appinfo.PROCESS_TYPE_CONTENT) {
|
||||
let {init} = Cu.import("resource://devtools/server/content-server.jsm", {});
|
||||
init(message);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([ContentProcessSingleton]);
|
||||
|
|
|
@ -517,6 +517,7 @@ STUB(gdk_display_get_device_manager)
|
|||
STUB(gdk_error_trap_pop_ignored)
|
||||
STUB(gdk_event_get_source_device)
|
||||
STUB(gdk_window_get_type)
|
||||
STUB(gdk_window_get_window_type)
|
||||
STUB(gdk_x11_window_get_xid)
|
||||
STUB(gdk_x11_display_get_type)
|
||||
STUB(gtk_box_new)
|
||||
|
|
|
@ -220,6 +220,8 @@ static void theme_changed_cb (GtkSettings *settings,
|
|||
nsWindow *data);
|
||||
static void check_resize_cb (GtkContainer* container,
|
||||
gpointer user_data);
|
||||
static void composited_changed_cb (GtkWidget* widget,
|
||||
gpointer user_data);
|
||||
|
||||
#if (MOZ_WIDGET_GTK == 3)
|
||||
static void scale_changed_cb (GtkWidget* widget,
|
||||
|
@ -3369,6 +3371,19 @@ nsWindow::OnCheckResize()
|
|||
mPendingConfigures++;
|
||||
}
|
||||
|
||||
void
|
||||
nsWindow::OnCompositedChanged()
|
||||
{
|
||||
if (mWidgetListener) {
|
||||
nsIPresShell* presShell = mWidgetListener->GetPresShell();
|
||||
if (presShell) {
|
||||
// Update CSD after the change in alpha visibility
|
||||
presShell->ThemeChanged();
|
||||
}
|
||||
}
|
||||
CleanLayerManagerRecursive();
|
||||
}
|
||||
|
||||
void
|
||||
nsWindow::DispatchDragEvent(EventMessage aMsg, const LayoutDeviceIntPoint& aRefPoint,
|
||||
guint aTime)
|
||||
|
@ -3604,6 +3619,31 @@ nsWindow::Create(nsIWidget* aParent,
|
|||
GTK_WINDOW_TOPLEVEL : GTK_WINDOW_POPUP;
|
||||
mShell = gtk_window_new(type);
|
||||
|
||||
bool useAlphaVisual = (mWindowType == eWindowType_popup &&
|
||||
aInitData->mSupportTranslucency);
|
||||
|
||||
// mozilla.widget.use-argb-visuals is a hidden pref defaulting to false
|
||||
// to allow experimentation
|
||||
if (Preferences::GetBool("mozilla.widget.use-argb-visuals", false))
|
||||
useAlphaVisual = true;
|
||||
|
||||
// We need to select an ARGB visual here instead of in
|
||||
// SetTransparencyMode() because it has to be done before the
|
||||
// widget is realized. An ARGB visual is only useful if we
|
||||
// are on a compositing window manager.
|
||||
if (useAlphaVisual) {
|
||||
GdkScreen *screen = gtk_widget_get_screen(mShell);
|
||||
if (gdk_screen_is_composited(screen)) {
|
||||
#if (MOZ_WIDGET_GTK == 2)
|
||||
GdkColormap *colormap = gdk_screen_get_rgba_colormap(screen);
|
||||
gtk_widget_set_colormap(mShell, colormap);
|
||||
#else
|
||||
GdkVisual *visual = gdk_screen_get_rgba_visual(screen);
|
||||
gtk_widget_set_visual(mShell, visual);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// We only move a general managed toplevel window if someone has
|
||||
// actually placed the window somewhere. If no placement has taken
|
||||
// place, we just let the window manager Do The Right Thing.
|
||||
|
@ -3627,23 +3667,6 @@ nsWindow::Create(nsIWidget* aParent,
|
|||
gtk_window_set_wmclass(GTK_WINDOW(mShell), "Popup",
|
||||
gdk_get_program_class());
|
||||
|
||||
if (aInitData->mSupportTranslucency) {
|
||||
// We need to select an ARGB visual here instead of in
|
||||
// SetTransparencyMode() because it has to be done before the
|
||||
// widget is realized. An ARGB visual is only useful if we
|
||||
// are on a compositing window manager.
|
||||
GdkScreen *screen = gtk_widget_get_screen(mShell);
|
||||
if (gdk_screen_is_composited(screen)) {
|
||||
#if (MOZ_WIDGET_GTK == 2)
|
||||
GdkColormap *colormap =
|
||||
gdk_screen_get_rgba_colormap(screen);
|
||||
gtk_widget_set_colormap(mShell, colormap);
|
||||
#else
|
||||
GdkVisual *visual = gdk_screen_get_rgba_visual(screen);
|
||||
gtk_widget_set_visual(mShell, visual);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
if (aInitData->mNoAutoHide) {
|
||||
// ... but the window manager does not decorate this window,
|
||||
// nor provide a separate taskbar icon.
|
||||
|
@ -3829,6 +3852,8 @@ nsWindow::Create(nsIWidget* aParent,
|
|||
G_CALLBACK(window_state_event_cb), nullptr);
|
||||
g_signal_connect(mShell, "check-resize",
|
||||
G_CALLBACK(check_resize_cb), nullptr);
|
||||
g_signal_connect(mShell, "composited-changed",
|
||||
G_CALLBACK(composited_changed_cb), nullptr);
|
||||
|
||||
GtkSettings* default_settings = gtk_settings_get_default();
|
||||
g_signal_connect_after(default_settings,
|
||||
|
@ -4345,6 +4370,33 @@ nsWindow::GetTransparencyMode()
|
|||
return mIsTransparent ? eTransparencyTransparent : eTransparencyOpaque;
|
||||
}
|
||||
|
||||
#if (MOZ_WIDGET_GTK >= 3)
|
||||
void nsWindow::UpdateOpaqueRegion(const LayoutDeviceIntRegion& aOpaqueRegion)
|
||||
{
|
||||
// Available as of GTK 3.10+
|
||||
static auto sGdkWindowSetOpaqueRegion =
|
||||
(void (*)(GdkWindow*, cairo_region_t*))
|
||||
dlsym(RTLD_DEFAULT, "gdk_window_set_opaque_region");
|
||||
|
||||
if (sGdkWindowSetOpaqueRegion && mGdkWindow &&
|
||||
gdk_window_get_window_type(mGdkWindow) == GDK_WINDOW_TOPLEVEL) {
|
||||
if (aOpaqueRegion.IsEmpty()) {
|
||||
(*sGdkWindowSetOpaqueRegion)(mGdkWindow, nullptr);
|
||||
} else {
|
||||
cairo_region_t *region = cairo_region_create();
|
||||
for (auto iter = aOpaqueRegion.RectIter(); !iter.Done();
|
||||
iter.Next()) {
|
||||
const LayoutDeviceIntRect &r = iter.Get();
|
||||
cairo_rectangle_int_t rect = { r.x, r.y, r.width, r.height };
|
||||
cairo_region_union_rectangle(region, &rect);
|
||||
}
|
||||
(*sGdkWindowSetOpaqueRegion)(mGdkWindow, region);
|
||||
cairo_region_destroy(region);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
nsresult
|
||||
nsWindow::ConfigureChildren(const nsTArray<Configuration>& aConfigurations)
|
||||
{
|
||||
|
@ -5836,6 +5888,16 @@ check_resize_cb (GtkContainer* container, gpointer user_data)
|
|||
window->OnCheckResize();
|
||||
}
|
||||
|
||||
static void
|
||||
composited_changed_cb (GtkWidget* widget, gpointer user_data)
|
||||
{
|
||||
RefPtr<nsWindow> window = get_window_for_gtk_widget(widget);
|
||||
if (!window) {
|
||||
return;
|
||||
}
|
||||
window->OnCompositedChanged();
|
||||
}
|
||||
|
||||
#if (MOZ_WIDGET_GTK == 3)
|
||||
static void
|
||||
scale_changed_cb (GtkWidget* widget, GParamSpec* aPSpec, gpointer aPointer)
|
||||
|
@ -6436,7 +6498,10 @@ nsWindow::GetLayerManager(PLayerTransactionChild* aShadowManager,
|
|||
// during shutdown. Just return what we currently have, which is most likely null.
|
||||
return mLayerManager;
|
||||
}
|
||||
if (!mLayerManager && eTransparencyTransparent == GetTransparencyMode()) {
|
||||
|
||||
if (!mLayerManager &&
|
||||
eTransparencyTransparent == GetTransparencyMode())
|
||||
{
|
||||
mLayerManager = CreateBasicLayerManager();
|
||||
}
|
||||
|
||||
|
@ -6745,3 +6810,17 @@ void nsWindow::GetCompositorWidgetInitData(mozilla::widget::CompositorWidgetInit
|
|||
GetClientSize());
|
||||
#endif
|
||||
}
|
||||
|
||||
bool
|
||||
nsWindow::IsComposited() const
|
||||
{
|
||||
if (!mGdkWindow) {
|
||||
NS_WARNING("nsWindow::HasARGBVisual called before realization!");
|
||||
return false;
|
||||
}
|
||||
|
||||
GdkScreen* gdkScreen = gdk_screen_get_default();
|
||||
return gdk_screen_is_composited(gdkScreen) &&
|
||||
(gdk_window_get_visual(mGdkWindow)
|
||||
== gdk_screen_get_rgba_visual(gdkScreen));
|
||||
}
|
||||
|
|
|
@ -251,6 +251,7 @@ public:
|
|||
void ThemeChanged(void);
|
||||
void OnDPIChanged(void);
|
||||
void OnCheckResize(void);
|
||||
void OnCompositedChanged(void);
|
||||
|
||||
#ifdef MOZ_X11
|
||||
Window mOldFocusWindow;
|
||||
|
@ -307,6 +308,9 @@ public:
|
|||
|
||||
virtual void SetTransparencyMode(nsTransparencyMode aMode) override;
|
||||
virtual nsTransparencyMode GetTransparencyMode() override;
|
||||
#if (MOZ_WIDGET_GTK >= 3)
|
||||
virtual void UpdateOpaqueRegion(const LayoutDeviceIntRegion& aOpaqueRegion) override;
|
||||
#endif
|
||||
virtual nsresult ConfigureChildren(const nsTArray<Configuration>& aConfigurations) override;
|
||||
nsresult UpdateTranslucentWindowAlphaInternal(const nsIntRect& aRect,
|
||||
uint8_t* aAlphas, int32_t aStride);
|
||||
|
@ -430,6 +434,8 @@ private:
|
|||
gint* aRootX, gint* aRootY);
|
||||
void ClearCachedResources();
|
||||
nsIWidgetListener* GetListener();
|
||||
bool IsComposited() const;
|
||||
|
||||
|
||||
GtkWidget *mShell;
|
||||
MozContainer *mContainer;
|
||||
|
|
Загрузка…
Ссылка в новой задаче