Merge mozilla-central to inbound. a=merge CLOSED TREE

This commit is contained in:
Oana Pop Rus 2019-01-16 11:40:36 +02:00
Родитель 20e053aca1 bee8cf15c9
Коммит bd4d528ac8
58 изменённых файлов: 974 добавлений и 320 удалений

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

@ -32,7 +32,7 @@ let whitelist = [
errorMessage: /Expected media feature name but found \u2018-moz.*/i,
isFromDevTools: false},
{sourceName: /\b(contenteditable|EditorOverride|svg|forms|html|mathml|ua)\.css$/i,
{sourceName: /\b(contenteditable|EditorOverride|svg|forms|html|mathml|ua|pluginproblem)\.css$/i,
errorMessage: /Unknown pseudo-class.*-moz-/i,
isFromDevTools: false},
{sourceName: /\b(html|mathml|ua)\.css$/i,

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

@ -472,9 +472,11 @@ var gPrivacyPane = {
let contentBlockingUrl = Services.urlFormatter.formatURLPref("app.support.baseURL") + "content-blocking";
link.setAttribute("href", contentBlockingUrl);
let contentBlockingTour = Services.urlFormatter.formatURLPref("privacy.trackingprotection.introURL")
+ `?step=3&newtab=true`;
let warningLinks = document.getElementsByClassName("content-blocking-warning-learn-how");
for (let warningLink of warningLinks) {
warningLink.setAttribute("href", contentBlockingUrl);
warningLink.setAttribute("href", contentBlockingTour);
}
},

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

@ -235,7 +235,6 @@
@RESPATH@/components/nsUpdateTimerManager.js
@RESPATH@/components/utils.manifest
@RESPATH@/components/simpleServices.js
@RESPATH@/components/pluginGlue.manifest
@RESPATH@/components/ProcessSingleton.manifest
@RESPATH@/components/MainProcessSingleton.js
@RESPATH@/components/ContentProcessSingleton.js

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

@ -79,6 +79,15 @@
!define AccessibleHandlerCLSID "{4A195748-DCA2-45FB-9295-0A139E76A9E7}"
!endif
#ifdef MOZ_LAUNCHER_PROCESS
!define MOZ_LAUNCHER_PROCESS
!define MOZ_LAUNCHER_SUBKEY "Software\Mozilla\${AppName}\Launcher"
#endif
#ifdef RELEASE_OR_BETA
!define RELEASE_OR_BETA
#endif
# Due to official and beta using the same branding this is needed to
# differentiante between the url used by the stub for downloading.
!if "@MOZ_UPDATE_CHANNEL@" == "beta"

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

@ -489,6 +489,12 @@ Section "-Application" APP_IDX
${SetAppLSPCategories} ${LSP_CATEGORIES}
${EndIf}
!ifdef MOZ_LAUNCHER_PROCESS
!ifdef RELEASE_OR_BETA
${DisableLauncherProcessByDefault}
!endif
!endif
; Create shortcuts
${LogHeader} "Adding Shortcuts"

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

@ -162,6 +162,13 @@
${EndIf}
${EndIf}
!endif
!ifdef MOZ_LAUNCHER_PROCESS
!ifdef RELEASE_OR_BETA
${DisableLauncherProcessByDefault}
!endif
!endif
!macroend
!define PostUpdate "!insertmacro PostUpdate"
@ -1607,3 +1614,22 @@ FunctionEnd
!define SetAsDefaultAppUser "Call SetAsDefaultAppUser"
!endif ; NO_LOG
!ifdef MOZ_LAUNCHER_PROCESS
!ifdef RELEASE_OR_BETA
!macro DisableLauncherProcessByDefault
ClearErrors
${ReadRegQWORD} $0 HKCU ${MOZ_LAUNCHER_SUBKEY} "$INSTDIR\${FileMainEXE}|Launcher"
${If} ${Errors}
ClearErrors
${ReadRegQWORD} $0 HKCU ${MOZ_LAUNCHER_SUBKEY} "$INSTDIR\${FileMainEXE}|Browser"
${If} ${Errors}
ClearErrors
; New install that hasn't seen this yet; disable by default
${WriteRegQWORD} HKCU ${MOZ_LAUNCHER_SUBKEY} "$INSTDIR\${FileMainEXE}|Browser" 0
${EndIf}
${EndIf}
!macroend
!define DisableLauncherProcessByDefault "!insertmacro DisableLauncherProcessByDefault"
!endif
!endif

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

@ -411,6 +411,12 @@ Section "Uninstall"
${UnregisterDLL} "$INSTDIR\AccessibleHandler.dll"
${EndIf}
!ifdef MOZ_LAUNCHER_PROCESS
DeleteRegValue HKCU ${MOZ_LAUNCHER_SUBKEY} "$INSTDIR\${FileMainEXE}|Launcher"
DeleteRegValue HKCU ${MOZ_LAUNCHER_SUBKEY} "$INSTDIR\${FileMainEXE}|Browser"
DeleteRegValue HKCU ${MOZ_LAUNCHER_SUBKEY} "$INSTDIR\${FileMainEXE}|Image"
!endif
${un.RemovePrecompleteEntries} "false"
${If} ${FileExists} "$INSTDIR\defaults\pref\channel-prefs.js"

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

@ -55,7 +55,7 @@ runTest(async () => {
// Test gUM in sandboxed vs. regular iframe.
for (const origin of ["http://mochi.test:8888", "https://example.com", "http://test1.mochi.test:8888"]) {
for (const origin of ["http://mochi.test:8888", "http://test1.mochi.test:8888"]) {
const src = origin + path;
is(await iframeGum({ src, sandbox: "allow-scripts" }),
"NotAllowedError", "gUM fails in sandboxed iframe " + origin);

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

@ -113,7 +113,7 @@ TEST(PrioEncoder, VerifyFull) {
snprintf((char*)batchIDStr, sizeof batchIDStr, "%d", rand());
bool dataItems[ndata];
unsigned long output[ndata];
unsigned long long output[ndata];
// The client's data submission is an arbitrary boolean vector.
for (int i = 0; i < ndata; i++) {
@ -133,12 +133,13 @@ TEST(PrioEncoder, VerifyFull) {
ASSERT_TRUE(prioRv == SECSuccess);
// Export public keys to hex and print to stdout
unsigned char pkHexA[CURVE25519_KEY_LEN_HEX + 1];
unsigned char pkHexB[CURVE25519_KEY_LEN_HEX + 1];
prioRv = PublicKey_export_hex(pkA, pkHexA);
const int keyLength = CURVE25519_KEY_LEN_HEX + 1;
unsigned char pkHexA[keyLength];
unsigned char pkHexB[keyLength];
prioRv = PublicKey_export_hex(pkA, pkHexA, keyLength);
ASSERT_TRUE(prioRv == SECSuccess);
prioRv = PublicKey_export_hex(pkB, pkHexB);
prioRv = PublicKey_export_hex(pkB, pkHexB, keyLength);
ASSERT_TRUE(prioRv == SECSuccess);
// Use the default configuration parameters.

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

@ -57,7 +57,6 @@ LayerTransactionParent::LayerTransactionParent(
mChildEpoch{0},
mParentEpoch{0},
mVsyncRate(aVsyncRate),
mPendingTransaction{0},
mDestroyed(false),
mIPCOpen(false),
mUpdateHitTestingTree(false) {
@ -884,39 +883,52 @@ bool LayerTransactionParent::IsSameProcess() const {
return OtherPid() == base::GetCurrentProcId();
}
void LayerTransactionParent::SetPendingTransactionId(
TransactionId aId, const VsyncId& aVsyncId,
const TimeStamp& aVsyncStartTime, const TimeStamp& aRefreshStartTime,
const TimeStamp& aTxnStartTime, const TimeStamp& aTxnEndTime, bool aContainsSVG,
const nsCString& aURL, const TimeStamp& aFwdTime) {
mPendingTransactions.AppendElement(
PendingTransaction{aId, aVsyncId, aVsyncStartTime, aRefreshStartTime,
aTxnStartTime, aTxnEndTime, aFwdTime, aURL, aContainsSVG});
}
TransactionId LayerTransactionParent::FlushTransactionId(
const VsyncId& aId, TimeStamp& aCompositeEnd) {
if (mId.IsValid() && mPendingTransaction.IsValid() && !mVsyncRate.IsZero()) {
RecordContentFrameTime(mTxnVsyncId, mVsyncStartTime, mTxnStartTime, aId,
aCompositeEnd, mTxnEndTime - mTxnStartTime,
mVsyncRate, mContainsSVG, false);
}
const VsyncId& aCompositeId, TimeStamp& aCompositeEnd) {
TransactionId id;
for (auto& transaction : mPendingTransactions) {
id = transaction.mId;
if (mId.IsValid() && transaction.mId.IsValid() && !mVsyncRate.IsZero()) {
RecordContentFrameTime(
transaction.mTxnVsyncId, transaction.mVsyncStartTime,
transaction.mTxnStartTime, aCompositeId, aCompositeEnd,
transaction.mTxnEndTime - transaction.mTxnStartTime, mVsyncRate,
transaction.mContainsSVG, false);
}
#if defined(ENABLE_FRAME_LATENCY_LOG)
if (mPendingTransaction.IsValid()) {
if (mRefreshStartTime) {
int32_t latencyMs =
lround((aCompositeEnd - mRefreshStartTime).ToMilliseconds());
printf_stderr(
"From transaction start to end of generate frame latencyMs %d this "
"%p\n",
latencyMs, this);
if (transaction.mId.IsValid()) {
if (transaction.mRefreshStartTime) {
int32_t latencyMs = lround(
(aCompositeEnd - transaction.mRefreshStartTime).ToMilliseconds());
printf_stderr(
"From transaction start to end of generate frame latencyMs %d this "
"%p\n",
latencyMs, this);
}
if (transaction.mFwdTime) {
int32_t latencyMs =
lround((aCompositeEnd - transaction.mFwdTime).ToMilliseconds());
printf_stderr(
"From forwarding transaction to end of generate frame latencyMs %d "
"this %p\n",
latencyMs, this);
}
}
if (mFwdTime) {
int32_t latencyMs = lround((aCompositeEnd - mFwdTime).ToMilliseconds());
printf_stderr(
"From forwarding transaction to end of generate frame latencyMs %d "
"this %p\n",
latencyMs, this);
}
}
#endif
}
mRefreshStartTime = TimeStamp();
mTxnStartTime = TimeStamp();
mFwdTime = TimeStamp();
TransactionId id = mPendingTransaction;
mPendingTransaction = TransactionId{0};
mPendingTransactions.Clear();
return id;
}

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

@ -71,24 +71,13 @@ class LayerTransactionParent final : public PLayerTransactionParent,
bool IsSameProcess() const override;
const TransactionId& GetPendingTransactionId() { return mPendingTransaction; }
void SetPendingTransactionId(TransactionId aId, const VsyncId& aVsyncId,
const TimeStamp& aVsyncStartTime,
const TimeStamp& aRefreshStartTime,
const TimeStamp& aTxnStartTime,
const TimeStamp& aTxnEndTime, bool aContainsSVG,
const nsCString& aURL,
const TimeStamp& aFwdTime) {
mPendingTransaction = aId;
mTxnVsyncId = aVsyncId;
mVsyncStartTime = aVsyncStartTime;
mRefreshStartTime = aRefreshStartTime;
mTxnStartTime = aTxnStartTime;
mTxnEndTime = aTxnEndTime;
mContainsSVG = aContainsSVG;
mTxnURL = aURL;
mFwdTime = aFwdTime;
}
const TimeStamp& aFwdTime);
TransactionId FlushTransactionId(const VsyncId& aId,
TimeStamp& aCompositeEnd);
@ -208,15 +197,18 @@ class LayerTransactionParent final : public PLayerTransactionParent,
TimeDuration mVsyncRate;
TransactionId mPendingTransaction;
VsyncId mTxnVsyncId;
TimeStamp mVsyncStartTime;
TimeStamp mRefreshStartTime;
TimeStamp mTxnStartTime;
TimeStamp mTxnEndTime;
TimeStamp mFwdTime;
nsCString mTxnURL;
bool mContainsSVG;
struct PendingTransaction {
TransactionId mId;
VsyncId mTxnVsyncId;
TimeStamp mVsyncStartTime;
TimeStamp mRefreshStartTime;
TimeStamp mTxnStartTime;
TimeStamp mTxnEndTime;
TimeStamp mFwdTime;
nsCString mTxnURL;
bool mContainsSVG;
};
AutoTArray<PendingTransaction, 2> mPendingTransactions;
// When the widget/frame/browser stuff in this process begins its
// destruction process, we need to Disconnect() all the currently

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

@ -39,6 +39,7 @@ use scene_builder::{DocumentResources, InternerMut};
use spatial_node::{StickyFrameInfo, ScrollFrameKind, SpatialNodeType};
use std::{f32, mem, usize};
use std::collections::vec_deque::VecDeque;
use std::sync::Arc;
use tiling::{CompositeOps};
use util::{MaxRect, VecHelper};
@ -2363,7 +2364,7 @@ impl<'a> DisplayListFlattener<'a> {
.collect();
TextRun {
glyphs,
glyphs: Arc::new(glyphs),
font,
offset,
shadow: false,

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

@ -2,6 +2,37 @@
* 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/. */
//! The interning module provides a generic data structure
//! interning container. It is similar in concept to a
//! traditional string interning container, but it is
//! specialized to the WR thread model.
//!
//! There is an Interner structure, that lives in the
//! scene builder thread, and a DataStore structure
//! that lives in the frame builder thread.
//!
//! Hashing, interning and handle creation is done by
//! the interner structure during scene building.
//!
//! Delta changes for the interner are pushed during
//! a transaction to the frame builder. The frame builder
//! is then able to access the content of the interned
//! handles quickly, via array indexing.
//!
//! Epoch tracking ensures that the garbage collection
//! step which the interner uses to remove items is
//! only invoked on items that the frame builder thread
//! is no longer referencing.
//!
//! Items in the data store are stored in a traditional
//! free-list structure, for content access and memory
//! usage efficiency.
//!
//! The epoch is incremented each time a scene is
//! built. The most recently used scene epoch is
//! stored inside each handle. This is then used for
//! cache invalidation.
use api::{LayoutPrimitiveInfo};
use internal_types::FastHashMap;
use malloc_size_of::MallocSizeOf;
@ -13,55 +44,14 @@ use std::{mem, ops, u64};
use std::sync::atomic::{AtomicUsize, Ordering};
use util::VecHelper;
/*
The interning module provides a generic data structure
interning container. It is similar in concept to a
traditional string interning container, but it is
specialized to the WR thread model.
There is an Interner structure, that lives in the
scene builder thread, and a DataStore structure
that lives in the frame builder thread.
Hashing, interning and handle creation is done by
the interner structure during scene building.
Delta changes for the interner are pushed during
a transaction to the frame builder. The frame builder
is then able to access the content of the interned
handles quickly, via array indexing.
Epoch tracking ensures that the garbage collection
step which the interner uses to remove items is
only invoked on items that the frame builder thread
is no longer referencing.
Items in the data store are stored in a traditional
free-list structure, for content access and memory
usage efficiency.
*/
/// The epoch is incremented each time a scene is
/// built. The most recently used scene epoch is
/// stored inside each item and handle. This is
/// then used for cache invalidation (item) and
/// correctness validation (handle).
#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
#[derive(Debug, Copy, Clone, MallocSizeOf, PartialEq)]
struct Epoch(u64);
impl Epoch {
pub const INVALID: Self = Epoch(u64::MAX);
}
/// A list of updates to be applied to the data store,
/// provided by the interning structure.
pub struct UpdateList<S> {
/// The current epoch of the scene builder.
epoch: Epoch,
/// The additions and removals to apply.
updates: Vec<Update>,
/// Actual new data to insert.
@ -109,7 +99,6 @@ impl <M> Handle<M> where M: Copy {
pub enum UpdateKind {
Insert,
Remove,
UpdateEpoch,
}
#[cfg_attr(feature = "capture", derive(Serialize))]
@ -120,16 +109,6 @@ pub struct Update {
kind: UpdateKind,
}
/// The data item is stored with an epoch, for validating
/// correct access patterns.
#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
#[derive(MallocSizeOf)]
struct Item<T: MallocSizeOf> {
epoch: Epoch,
data: T,
}
pub trait InternDebug {
fn on_interned(&self, _uid: ItemUid) {}
}
@ -140,7 +119,7 @@ pub trait InternDebug {
#[cfg_attr(feature = "replay", derive(Deserialize))]
#[derive(MallocSizeOf)]
pub struct DataStore<S, T: MallocSizeOf, M> {
items: Vec<Item<T>>,
items: Vec<Option<T>>,
_source: PhantomData<S>,
_marker: PhantomData<M>,
}
@ -177,16 +156,11 @@ where
for update in update_list.updates {
match update.kind {
UpdateKind::Insert => {
self.items.entry(update.index).set(Item {
data: T::from(data_iter.next().unwrap()),
epoch: update_list.epoch,
});
self.items.entry(update.index).
set(Some(T::from(data_iter.next().unwrap())));
}
UpdateKind::Remove => {
self.items[update.index].epoch = Epoch::INVALID;
}
UpdateKind::UpdateEpoch => {
self.items[update.index].epoch = update_list.epoch;
self.items[update.index] = None;
}
}
}
@ -207,9 +181,7 @@ where
{
type Output = T;
fn index(&self, handle: Handle<M>) -> &T {
let item = &self.items[handle.index as usize];
assert_eq!(item.epoch, handle.epoch);
&item.data
self.items[handle.index as usize].as_ref().expect("Bad datastore lookup")
}
}
@ -222,9 +194,7 @@ where
M: Copy
{
fn index_mut(&mut self, handle: Handle<M>) -> &mut T {
let item = &mut self.items[handle.index as usize];
assert_eq!(item.epoch, handle.epoch);
&mut item.data
self.items[handle.index as usize].as_mut().expect("Bad datastore lookup")
}
}
@ -254,7 +224,7 @@ where
current_epoch: Epoch,
/// The information associated with each interned
/// item that can be accessed by the interner.
local_data: Vec<Item<D>>,
local_data: Vec<D>,
}
impl<S, D, M> ::std::default::Default for Interner<S, D, M>
@ -297,17 +267,6 @@ where
// cloning the (sometimes large) key in the common
// case, where the data already exists in the interner.
if let Some(handle) = self.map.get_mut(data) {
// Update the epoch in the data store. This
// is not strictly needed for correctness, but
// is used to ensure items are only accessed
// via valid handles.
if handle.epoch != self.current_epoch {
self.updates.push(Update {
index: handle.index as usize,
kind: UpdateKind::UpdateEpoch,
});
self.local_data[handle.index as usize].epoch = self.current_epoch;
}
handle.epoch = self.current_epoch;
return *handle;
}
@ -344,10 +303,7 @@ where
// Create the local data for this item that is
// being interned.
self.local_data.entry(index).set(Item {
epoch: self.current_epoch,
data: f(),
});
self.local_data.entry(index).set(f());
handle
}
@ -389,7 +345,6 @@ where
let updates = UpdateList {
updates,
data,
epoch: self.current_epoch,
};
// Begin the next epoch
@ -408,9 +363,7 @@ where
{
type Output = D;
fn index(&self, handle: Handle<M>) -> &D {
let item = &self.local_data[handle.index as usize];
assert_eq!(item.epoch, handle.epoch);
&item.data
&self.local_data[handle.index as usize]
}
}

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

@ -36,6 +36,7 @@ use scene_builder::DocumentResources;
use smallvec::SmallVec;
use surface::{SurfaceDescriptor};
use std::{mem, u16};
use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
use texture_cache::{Eviction, TextureCacheHandle};
use tiling::RenderTargetKind;
use util::{ComparableVec, TransformedRectKind, MatrixHelpers, MaxRect};
@ -78,6 +79,7 @@ impl RetainedTiles {
/// Merge items from one retained tiles into another.
pub fn merge(&mut self, other: RetainedTiles) {
assert!(self.tiles.is_empty() || other.tiles.is_empty());
self.tiles.extend(other.tiles);
self.ref_prims.extend(other.ref_prims);
}
@ -110,12 +112,13 @@ const MAX_CACHE_SIZE: f32 = 2048.0;
const MAX_SURFACE_SIZE: f32 = 4096.0;
/// The number of primitives to search for, trying to correlate
/// the offset between one display list and another.
const MAX_PRIMS_TO_CORRELATE: usize = 64;
/// The minmum number of primitives we need to correlate in
/// order to consider it a success.
const MIN_PRIMS_TO_CORRELATE: usize = MAX_PRIMS_TO_CORRELATE / 4;
/// The maximum number of primitives to look for in a display
/// list, trying to find unique primitives.
const MAX_PRIMS_TO_SEARCH: usize = 128;
/// Used to get unique tile IDs, even when the tile cache is
/// destroyed between display lists / scenes.
static NEXT_TILE_ID: AtomicUsize = ATOMIC_USIZE_INIT;
/// Information about the state of an opacity binding.
#[derive(Debug)]
@ -213,17 +216,23 @@ impl Tile {
self.potential_clips.clear();
}
/// Update state related to whether a tile has the same
/// content and is valid to use.
fn update_validity(&mut self, tile_bounding_rect: &WorldRect) {
/// Invalidate a tile based on change in content. This
/// muct be called even if the tile is not currently
/// visible on screen. We might be able to improve this
/// later by changing how ComparableVec is used.
fn update_content_validity(&mut self) {
// Check if the contents of the primitives, clips, and
// other dependencies are the same.
self.is_same_content &= self.descriptor.is_same_content();
self.is_valid &= self.is_same_content;
}
/// Update state related to whether a tile has a valid rect that
/// covers the required visible part of the tile.
fn update_rect_validity(&mut self, tile_bounding_rect: &WorldRect) {
// The tile is only valid if:
// - The content is the same *and*
// - The valid part of the tile includes the needed part.
self.is_valid &= self.is_same_content;
self.is_valid &= self.valid_rect.contains_rect(tile_bounding_rect);
// Update count of how many times this tile has had the same content.
@ -362,33 +371,70 @@ pub struct TileCache {
/// scroll bars in gecko, when the content overflows under the
/// scroll bar).
world_bounding_rect: WorldRect,
/// Counter for the next id to assign for a new tile.
next_id: usize,
/// List of reference primitive information used for
/// correlating the position between display lists.
reference_prims: Vec<ReferencePrimitive>,
reference_prims: ReferencePrimitiveList,
/// The root clip chain for this tile cache.
root_clip_chain_id: ClipChainId,
}
/// Stores information about a primitive in the cache that we will
/// try to use to correlate positions between display lists.
#[derive(Clone)]
struct ReferencePrimitive {
uid: ItemUid,
local_pos: LayoutPoint,
spatial_node_index: SpatialNodeIndex,
ref_count: usize,
}
/// A list of primitive with uids that only exist once in a display
/// list. Used to obtain reference points to correlate the offset
/// between two similar display lists.
struct ReferencePrimitiveList {
ref_prims: Vec<ReferencePrimitive>,
}
impl ReferencePrimitiveList {
fn new(
prim_instances: &[PrimitiveInstance],
pictures: &[PicturePrimitive],
) -> Self {
let mut map = FastHashMap::default();
let mut search_count = 0;
// Collect a set of primitives that we can
// potentially use for correlation.
collect_ref_prims(
prim_instances,
pictures,
&mut map,
&mut search_count,
);
// Select only primitives where the uid is unique
// in the display list, giving the best chance
// of finding correct correlations.
let ref_prims = map.values().filter(|prim| {
prim.ref_count == 1
}).cloned().collect();
ReferencePrimitiveList {
ref_prims,
}
}
}
/// Collect a sample of primitives from the prim list that can
/// be used to correlate positions.
// TODO(gw): Investigate best how to select which primitives to select.
fn collect_ref_prims(
prim_instances: &[PrimitiveInstance],
ref_prims: &mut Vec<ReferencePrimitive>,
pictures: &[PicturePrimitive],
map: &mut FastHashMap<ItemUid, ReferencePrimitive>,
search_count: &mut usize,
) {
for prim_instance in prim_instances {
if ref_prims.len() >= MAX_PRIMS_TO_CORRELATE {
if *search_count > MAX_PRIMS_TO_SEARCH {
return;
}
@ -396,16 +442,25 @@ fn collect_ref_prims(
PrimitiveInstanceKind::Picture { pic_index, .. } => {
collect_ref_prims(
&pictures[pic_index.0].prim_list.prim_instances,
ref_prims,
pictures,
map,
search_count,
);
}
_ => {
ref_prims.push(ReferencePrimitive {
uid: prim_instance.uid(),
local_pos: prim_instance.prim_origin,
spatial_node_index: prim_instance.spatial_node_index,
let uid = prim_instance.uid();
let entry = map.entry(uid).or_insert_with(|| {
ReferencePrimitive {
uid,
local_pos: prim_instance.prim_origin,
spatial_node_index: prim_instance.spatial_node_index,
ref_count: 0,
}
});
entry.ref_count += 1;
*search_count = *search_count + 1;
}
}
}
@ -420,10 +475,8 @@ impl TileCache {
) -> Self {
// Build the list of reference primitives
// for this picture cache.
let mut reference_prims = Vec::with_capacity(MAX_PRIMS_TO_CORRELATE);
collect_ref_prims(
let reference_prims = ReferencePrimitiveList::new(
prim_instances,
&mut reference_prims,
pictures,
);
@ -444,18 +497,11 @@ impl TileCache {
scroll_offset: None,
pending_blits: Vec::new(),
world_bounding_rect: WorldRect::zero(),
next_id: 0,
reference_prims,
root_clip_chain_id,
}
}
fn next_id(&mut self) -> TileId {
let id = TileId(self.next_id);
self.next_id += 1;
id
}
/// Get the tile coordinates for a given rectangle.
fn get_tile_coords_for_rect(
&self,
@ -512,7 +558,7 @@ impl TileCache {
// new display list.
let mut new_prim_map = FastHashMap::default();
build_ref_prims(
&self.reference_prims,
&self.reference_prims.ref_prims,
&mut new_prim_map,
frame_context.clip_scroll_tree,
);
@ -656,7 +702,10 @@ impl TileCache {
let mut tile = match old_tiles.remove(&key) {
Some(tile) => tile,
None => Tile::new(self.next_id()),
None => {
let next_id = TileId(NEXT_TILE_ID.fetch_add(1, Ordering::Relaxed));
Tile::new(next_id)
}
};
tile.world_rect = WorldRect::new(
@ -1107,18 +1156,21 @@ impl TileCache {
tile.is_valid = false;
}
// Invalidate the tile based on the content changing.
tile.update_content_validity();
let visible_rect = match tile.visible_rect {
Some(rect) => rect,
None => continue,
};
// Check the content of the tile is the same
// Check the valid rect of the primitive is sufficient.
let tile_bounding_rect = match visible_rect.intersection(&self.world_bounding_rect) {
Some(rect) => rect.translate(&-tile.world_rect.origin.to_vector()),
None => continue,
};
tile.update_validity(&tile_bounding_rect);
tile.update_rect_validity(&tile_bounding_rect);
// If there are no primitives there is no need to draw or cache it.
if tile.descriptor.prims.is_empty() {
@ -1140,13 +1192,13 @@ impl TileCache {
);
_scratch.push_debug_string(
label_pos,
debug_colors::WHITE,
format!("{:?}", tile.id),
debug_colors::RED,
format!("{:?} {:?}", tile.id, tile.handle),
);
label_pos.y += 20.0;
_scratch.push_debug_string(
label_pos,
debug_colors::WHITE,
debug_colors::RED,
format!("same: {} frames", tile.same_frames),
);
}
@ -1751,7 +1803,7 @@ impl PicturePrimitive {
// Calculate and store positions of the reference
// primitives for this tile cache.
build_ref_prims(
&tile_cache.reference_prims,
&tile_cache.reference_prims.ref_prims,
&mut retained_tiles.ref_prims,
clip_scroll_tree,
);
@ -2873,17 +2925,11 @@ fn correlate_prim_maps(
map.into_iter()
.max_by_key(|&(_, count)| count)
.and_then(|(offset, count)| {
// We will assume we can use the calculated offset if:
// (a) We found more than one quarter of the selected
// reference primitives to have the same offset.
// (b) The display lists both had the same number of
// primitives, and we exactly matched. This handles
// edge cases like scenes where there are very
// few primitives, while excluding edge cases like
// dl_mutate that have thousands of primitives with
// the same uid.
if (count >= MIN_PRIMS_TO_CORRELATE) ||
(count == old_prims.len() && count == new_prims.len()) {
// We will assume we can use the calculated offset if we
// found more than one quarter of the selected reference
// primitives to have the same offset.
let prims_available = new_prims.len().min(old_prims.len());
if count >= prims_available / 4 {
Some(offset.into())
} else {
None

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

@ -18,7 +18,9 @@ use resource_cache::{ResourceCache};
use util::{MatrixHelpers};
use prim_store::PrimitiveInstanceKind;
use std::ops;
use std::sync::Arc;
use storage;
use util::PrimaryArc;
/// A run of glyphs, with associated font information.
#[cfg_attr(feature = "capture", derive(Serialize))]
@ -28,7 +30,7 @@ pub struct TextRunKey {
pub common: PrimKeyCommonData,
pub font: FontInstance,
pub offset: VectorKey,
pub glyphs: Vec<GlyphInstance>,
pub glyphs: PrimaryArc<Vec<GlyphInstance>>,
pub shadow: bool,
}
@ -43,7 +45,7 @@ impl TextRunKey {
),
font: text_run.font,
offset: text_run.offset.into(),
glyphs: text_run.glyphs,
glyphs: PrimaryArc(text_run.glyphs),
shadow: text_run.shadow,
}
}
@ -76,7 +78,8 @@ pub struct TextRunTemplate {
pub common: PrimTemplateCommonData,
pub font: FontInstance,
pub offset: LayoutVector2D,
pub glyphs: Vec<GlyphInstance>,
#[ignore_malloc_size_of = "Measured via PrimaryArc"]
pub glyphs: Arc<Vec<GlyphInstance>>,
}
impl ops::Deref for TextRunTemplate {
@ -99,7 +102,7 @@ impl From<TextRunKey> for TextRunTemplate {
common,
font: item.font,
offset: item.offset.into(),
glyphs: item.glyphs,
glyphs: item.glyphs.0,
}
}
}
@ -171,7 +174,7 @@ pub type TextRunDataInterner = intern::Interner<TextRunKey, PrimitiveSceneData,
pub struct TextRun {
pub font: FontInstance,
pub offset: LayoutVector2D,
pub glyphs: Vec<GlyphInstance>,
pub glyphs: Arc<Vec<GlyphInstance>>,
pub shadow: bool,
}
@ -336,8 +339,8 @@ fn test_struct_sizes() {
// test expectations and move on.
// (b) You made a structure larger. This is not necessarily a problem, but should only
// be done with care, and after checking if talos performance regresses badly.
assert_eq!(mem::size_of::<TextRun>(), 112, "TextRun size changed");
assert_eq!(mem::size_of::<TextRunTemplate>(), 128, "TextRunTemplate size changed");
assert_eq!(mem::size_of::<TextRunKey>(), 120, "TextRunKey size changed");
assert_eq!(mem::size_of::<TextRun>(), 96, "TextRun size changed");
assert_eq!(mem::size_of::<TextRunTemplate>(), 112, "TextRunTemplate size changed");
assert_eq!(mem::size_of::<TextRunKey>(), 104, "TextRunKey size changed");
assert_eq!(mem::size_of::<TextRunPrimitive>(), 88, "TextRunPrimitive size changed");
}

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

@ -4251,7 +4251,7 @@ impl Renderer {
for item in items {
match item {
DebugItem::Rect { rect, color } => {
let inner_color = color.scale_alpha(0.2).into();
let inner_color = color.scale_alpha(0.1).into();
let outer_color = (*color).into();
debug_renderer.add_quad(

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

@ -6,10 +6,13 @@ use api::{BorderRadius, DeviceIntPoint, DeviceIntRect, DeviceIntSize, DevicePixe
use api::{LayoutPixel, DeviceRect, WorldPixel, RasterRect};
use euclid::{Point2D, Rect, Size2D, TypedPoint2D, TypedRect, TypedSize2D, Vector2D};
use euclid::{TypedTransform2D, TypedTransform3D, TypedVector2D, TypedScale};
use malloc_size_of::{MallocShallowSizeOf, MallocSizeOf, MallocSizeOfOps};
use num_traits::Zero;
use plane_split::{Clipper, Polygon};
use std::{i32, f32, fmt, ptr};
use std::borrow::Cow;
use std::os::raw::c_void;
use std::sync::Arc;
// Matches the definition of SK_ScalarNearlyZero in Skia.
@ -977,3 +980,48 @@ impl<T> ComparableVec<T> where T: PartialEq + Clone + fmt::Debug {
self.is_same && self.prev_len == self.current_index
}
}
/// Arc wrapper to support measurement via MallocSizeOf.
///
/// Memory reporting for Arcs is tricky because of the risk of double-counting.
/// One way to measure them is to keep a table of pointers that have already been
/// traversed. The other way is to use knowledge of the program structure to
/// identify which Arc instances should be measured and which should be skipped to
/// avoid double-counting.
///
/// This struct implements the second approach. It identifies the "main" pointer
/// to the Arc-ed resource, and measures the buffer as if it were an owned pointer.
/// The programmer should ensure that there is at most one PrimaryArc for a given
/// underlying ArcInner.
#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub struct PrimaryArc<T>(pub Arc<T>);
impl<T> ::std::ops::Deref for PrimaryArc<T> {
type Target = Arc<T>;
#[inline]
fn deref(&self) -> &Arc<T> {
&self.0
}
}
impl<T> MallocShallowSizeOf for PrimaryArc<T> {
fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
unsafe {
// This is a bit sketchy, but std::sync::Arc doesn't expose the
// base pointer.
let raw_arc_ptr: *const Arc<T> = &self.0;
let raw_ptr_ptr: *const *const c_void = raw_arc_ptr as _;
let raw_ptr = *raw_ptr_ptr;
(ops.size_of_op)(raw_ptr)
}
}
}
impl<T: MallocSizeOf> MallocSizeOf for PrimaryArc<T> {
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
self.shallow_size_of(ops) + (**self).size_of(ops)
}
}

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

@ -1540,6 +1540,9 @@ static MOZ_MUST_USE JSObject* ReadableStreamCreateReadResult(
? cx->realm()->getOrCreateIterResultTemplateObject(cx)
: cx->realm()->getOrCreateIterResultWithoutPrototypeTemplateObject(
cx));
if (!templateObject) {
return nullptr;
}
// Step 3: Assert: Type(done) is Boolean (implicit).

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

@ -0,0 +1,17 @@
// |jit-test| --no-ion; --no-baseline; skip-if: !('oomAfterAllocations' in this)
// Don't crash on OOM in ReadableStreamDefaultReader.prototype.read().
for (let n = 1; n < 1000; n++) {
let stream = new ReadableStream({
start(controller) {
controller.enqueue(7);
}
});
let reader = stream.getReader();
oomAfterAllocations(n);
try {
reader.read();
n = 1000;
} catch {}
resetOOMFailure();
}

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

@ -2347,9 +2347,9 @@ UniquePtr<ServoStyleSet> nsDocumentViewer::CreateStyleSet(Document* aDocument) {
styleSet->AppendStyleSheet(SheetType::Agent, cache->XULSheet());
}
// Append chrome sheets (scrollbars + forms).
styleSet->AppendStyleSheet(SheetType::Agent, cache->FormsSheet());
styleSet->AppendStyleSheet(SheetType::Agent, cache->ScrollbarsSheet());
styleSet->AppendStyleSheet(SheetType::Agent, cache->PluginProblemSheet());
for (StyleSheet* sheet : *sheetService->AgentStyleSheets()) {
styleSet->AppendStyleSheet(SheetType::Agent, sheet);

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

@ -28,6 +28,7 @@ STYLE_SHEET(MathML, "resource://gre-resources/mathml.css", true)
STYLE_SHEET(MinimalXUL, "chrome://global/content/minimal-xul.css", false)
STYLE_SHEET(NoFrames, "resource://gre-resources/noframes.css", true)
STYLE_SHEET(NoScript, "resource://gre-resources/noscript.css", true)
STYLE_SHEET(PluginProblem, "resource://gre-resources/pluginproblem.css", true)
STYLE_SHEET(Quirk, "resource://gre-resources/quirk.css", false)
STYLE_SHEET(Scrollbars, "chrome://global/skin/scrollbars.css", true)
STYLE_SHEET(SVG, "resource://gre/res/svg.css", false)

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

@ -10,6 +10,7 @@ toolkit.jar:
res/noscript.css (res/noscript.css)
res/noframes.css (res/noframes.css)
* res/forms.css (res/forms.css)
res/pluginproblem.css (res/pluginproblem.css)
res/arrow.gif (res/arrow.gif)
res/arrow-left.gif (res/arrow-left.gif)
res/arrow-right.gif (res/arrow-right.gif)

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

@ -167,7 +167,6 @@
@BINPATH@/components/nsUpdateTimerManager.manifest
@BINPATH@/components/nsUpdateTimerManager.js
@BINPATH@/components/pluginGlue.manifest
@BINPATH@/components/ProcessSingleton.manifest
@BINPATH@/components/MainProcessSingleton.js
@BINPATH@/components/ContentProcessSingleton.js

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

@ -9,18 +9,104 @@
#include <windows.h>
#include "mozilla/Atomics.h"
#include "mozilla/Attributes.h"
namespace mozilla {
namespace glue {
class MOZ_RAII AutoSharedLock final {
#ifdef DEBUG
class MOZ_STATIC_CLASS Win32SRWLock final {
public:
explicit AutoSharedLock(SRWLOCK& aLock) : mLock(aLock) {
::AcquireSRWLockShared(&aLock);
// Microsoft guarantees that '0' is never a valid thread id
// https://docs.microsoft.com/en-ca/windows/desktop/ProcThread/thread-handles-and-identifiers
static const DWORD kInvalidThreadId = 0;
constexpr Win32SRWLock()
: mExclusiveThreadId(kInvalidThreadId), mLock(SRWLOCK_INIT) {}
~Win32SRWLock() { MOZ_ASSERT(mExclusiveThreadId == kInvalidThreadId); }
void LockShared() {
MOZ_ASSERT(
mExclusiveThreadId != GetCurrentThreadId(),
"Deadlock detected - A thread attempted to acquire a shared lock on "
"a SRWLOCK when it already owns the exclusive lock on it.");
::AcquireSRWLockShared(&mLock);
}
~AutoSharedLock() { ::ReleaseSRWLockShared(&mLock); }
void UnlockShared() { ::ReleaseSRWLockShared(&mLock); }
void LockExclusive() {
MOZ_ASSERT(
mExclusiveThreadId != GetCurrentThreadId(),
"Deadlock detected - A thread attempted to acquire an exclusive lock "
"on a SRWLOCK when it already owns the exclusive lock on it.");
::AcquireSRWLockExclusive(&mLock);
mExclusiveThreadId = GetCurrentThreadId();
}
void UnlockExclusive() {
MOZ_ASSERT(mExclusiveThreadId == GetCurrentThreadId());
mExclusiveThreadId = kInvalidThreadId;
::ReleaseSRWLockExclusive(&mLock);
}
Win32SRWLock(const Win32SRWLock&) = delete;
Win32SRWLock(Win32SRWLock&&) = delete;
Win32SRWLock& operator=(const Win32SRWLock&) = delete;
Win32SRWLock& operator=(Win32SRWLock&&) = delete;
private:
// "Relaxed" memory ordering is fine. Threads will see other thread IDs
// appear here in some non-deterministic ordering (or not at all) and simply
// ignore them.
//
// But a thread will only read its own ID if it previously wrote it, and a
// single thread doesn't need a memory barrier to read its own write.
Atomic<DWORD, Relaxed> mExclusiveThreadId;
SRWLOCK mLock;
};
#else // DEBUG
class MOZ_STATIC_CLASS Win32SRWLock final {
public:
constexpr Win32SRWLock() : mLock(SRWLOCK_INIT) {}
void LockShared() { ::AcquireSRWLockShared(&mLock); }
void UnlockShared() { ::ReleaseSRWLockShared(&mLock); }
void LockExclusive() { ::AcquireSRWLockExclusive(&mLock); }
void UnlockExclusive() { ::ReleaseSRWLockExclusive(&mLock); }
~Win32SRWLock() = default;
Win32SRWLock(const Win32SRWLock&) = delete;
Win32SRWLock(Win32SRWLock&&) = delete;
Win32SRWLock& operator=(const Win32SRWLock&) = delete;
Win32SRWLock& operator=(Win32SRWLock&&) = delete;
private:
SRWLOCK mLock;
};
#endif
class MOZ_RAII AutoSharedLock final {
public:
explicit AutoSharedLock(Win32SRWLock& aLock) : mLock(aLock) {
mLock.LockShared();
}
~AutoSharedLock() { mLock.UnlockShared(); }
AutoSharedLock(const AutoSharedLock&) = delete;
AutoSharedLock(AutoSharedLock&&) = delete;
@ -28,16 +114,16 @@ class MOZ_RAII AutoSharedLock final {
AutoSharedLock& operator=(AutoSharedLock&&) = delete;
private:
SRWLOCK& mLock;
Win32SRWLock& mLock;
};
class MOZ_RAII AutoExclusiveLock final {
public:
explicit AutoExclusiveLock(SRWLOCK& aLock) : mLock(aLock) {
::AcquireSRWLockExclusive(&aLock);
explicit AutoExclusiveLock(Win32SRWLock& aLock) : mLock(aLock) {
mLock.LockExclusive();
}
~AutoExclusiveLock() { ::ReleaseSRWLockExclusive(&mLock); }
~AutoExclusiveLock() { mLock.UnlockExclusive(); }
AutoExclusiveLock(const AutoExclusiveLock&) = delete;
AutoExclusiveLock(AutoExclusiveLock&&) = delete;
@ -45,7 +131,7 @@ class MOZ_RAII AutoExclusiveLock final {
AutoExclusiveLock& operator=(AutoExclusiveLock&&) = delete;
private:
SRWLOCK& mLock;
Win32SRWLock& mLock;
};
} // namespace glue

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

@ -47,7 +47,7 @@ using namespace mozilla;
using CrashReporter::Annotation;
using CrashReporter::AnnotationToString;
static SRWLOCK gDllServicesLock = SRWLOCK_INIT;
static glue::Win32SRWLock gDllServicesLock;
static glue::detail::DllServicesBase* gDllServices;
#define DLL_BLOCKLIST_ENTRY(name, ...) {name, __VA_ARGS__},

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

@ -224,6 +224,11 @@ interface nsINetUtil : nsISupports
*/
ACString getReferrerPolicyString(in unsigned long aPolicy);
/**
* This is test-only. Send an IPC message to let socket process send a
* telemetry.
*/
void socketProcessTelemetryPing();
/**
* This is a void method that is C++ implemented and always

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

@ -507,6 +507,15 @@ RefPtr<MemoryReportingProcess> nsIOService::GetSocketProcessMemoryReporter() {
return new SocketProcessMemoryReporter();
}
NS_IMETHODIMP
nsIOService::SocketProcessTelemetryPing() {
CallOrWaitForSocketProcess([]() {
Unused << gIOService->mSocketProcess->GetActor()
->SendSocketProcessTelemetryPing();
});
return NS_OK;
}
NS_IMPL_ISUPPORTS(nsIOService, nsIIOService, nsINetUtil, nsISpeculativeConnect,
nsIObserver, nsIIOServiceInternal, nsISupportsWeakReference)

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

@ -43,6 +43,8 @@ child:
async SetOffline(bool offline);
async InitSocketProcessBridgeParent(ProcessId processId, Endpoint<PSocketProcessBridgeParent> endpoint);
async InitProfiler(Endpoint<PProfilerChild> aEndpoint);
// test-only
async SocketProcessTelemetryPing();
};
} // namespace net

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

@ -151,6 +151,13 @@ mozilla::ipc::IPCResult SocketProcessChild::RecvInitProfiler(
return IPC_OK();
}
mozilla::ipc::IPCResult SocketProcessChild::RecvSocketProcessTelemetryPing() {
const uint32_t kExpectedUintValue = 42;
Telemetry::ScalarSet(Telemetry::ScalarID::TELEMETRY_TEST_SOCKET_ONLY_UINT,
kExpectedUintValue);
return IPC_OK();
}
void SocketProcessChild::DestroySocketProcessBridgeParent(ProcessId aId) {
MOZ_ASSERT(NS_IsMainThread());

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

@ -42,6 +42,7 @@ class SocketProcessChild final : public PSocketProcessChild {
Endpoint<mozilla::net::PSocketProcessBridgeParent>&& aEndpoint) override;
mozilla::ipc::IPCResult RecvInitProfiler(
Endpoint<mozilla::PProfilerChild>&& aEndpoint) override;
mozilla::ipc::IPCResult RecvSocketProcessTelemetryPing() override;
void CleanUp();
void DestroySocketProcessBridgeParent(ProcessId aId);

2
third_party/prio/README-mozilla поставляемый
Просмотреть файл

@ -1,7 +1,7 @@
This directory contains the Prio source from the upstream repo:
https://github.com/mozilla/libprio
Current version: 1.2 [commit 02a81fb652d385d0f4f10989d051317097ab55fb]
Current version: 1.4 [commit a95cfdd5eaf7104582709c54ef23395d24d7f7fd]
UPDATING:

90
third_party/prio/include/mprio.h поставляемый
Просмотреть файл

@ -77,6 +77,9 @@ void Prio_clear();
* (2) the modulus we use for modular arithmetic.
* The default configuration uses an 87-bit modulus.
*
* The value `nFields` must be in the range `0 < nFields <= max`, where `max`
* is the value returned by the function `PrioConfig_maxDataFields()` below.
*
* The `batch_id` field specifies which "batch" of aggregate statistics we are
* computing. For example, if the aggregate statistics are computed every 24
* hours, the `batch_id` might be set to an encoding of the date. The clients
@ -87,18 +90,23 @@ void Prio_clear();
* caller passes in, so you may free the `batch_id` string as soon as
* `PrioConfig_new` returns.
*/
PrioConfig PrioConfig_new(int n_fields, PublicKey server_a, PublicKey server_b,
const unsigned char* batch_id,
unsigned int batch_id_len);
PrioConfig PrioConfig_new(int nFields, PublicKey serverA, PublicKey serverB,
const unsigned char* batchId,
unsigned int batchIdLen);
void PrioConfig_clear(PrioConfig cfg);
int PrioConfig_numDataFields(const_PrioConfig cfg);
/*
* Return the maximum number of data fields that the implementation supports.
*/
int PrioConfig_maxDataFields(void);
/*
* Create a PrioConfig object with no encryption keys. This routine is
* useful for testing, but PrioClient_encode() will always fail when used with
* this config.
*/
PrioConfig PrioConfig_newTest(int n_fields);
PrioConfig PrioConfig_newTest(int nFields);
/*
* We use the PublicKey and PrivateKey objects for public-key encryption. Each
@ -108,34 +116,57 @@ PrioConfig PrioConfig_newTest(int n_fields);
SECStatus Keypair_new(PrivateKey* pvtkey, PublicKey* pubkey);
/*
* Import a new curve25519 public key from the raw bytes given. The key passed
* in
* as `data` should be of length `CURVE25519_KEY_LEN`. This function allocates
* a new PublicKey object, which the caller must free using `PublicKey_clear`.
* Import a new curve25519 public/private key from the raw bytes given. When
* importing a private key, you must pass in the corresponding public key as
* well. The byte arrays given as input should be of length
* `CURVE25519_KEY_LEN`.
*
* These functions will allocate a new `PublicKey`/`PrivateKey` object, which
* the caller must free using `PublicKey_clear`/`PrivateKey_clear`.
*/
SECStatus PublicKey_import(PublicKey* pk, const unsigned char* data,
unsigned int dataLen);
SECStatus PrivateKey_import(PrivateKey* sk, const unsigned char* privData,
unsigned int privDataLen,
const unsigned char* pubData,
unsigned int pubDataLen);
/*
* Import a new curve25519 public key from a hex string that contains only the
* characters 0-9a-fA-F. The hex string passed in as `hex_data` should be of
* length `CURVE25519_KEY_LEN_HEX`. This function allocates a new PublicKey
* object, which the caller must free using `PublicKey_clear`.
* Import a new curve25519 public/private key from a hex string that contains
* only the characters 0-9a-fA-F.
*
* The hex strings passed in must each be of length `CURVE25519_KEY_LEN_HEX`.
* These functions will allocate a new `PublicKey`/`PrivateKey` object, which
* the caller must free using `PublicKey_clear`/`PrivateKey_clear`.
*/
SECStatus PublicKey_import_hex(PublicKey* pk, const unsigned char* hex_data,
SECStatus PublicKey_import_hex(PublicKey* pk, const unsigned char* hexData,
unsigned int dataLen);
SECStatus PrivateKey_import_hex(PrivateKey* sk,
const unsigned char* privHexData,
unsigned int privDataLen,
const unsigned char* pubHexData,
unsigned int pubDataLen);
/*
* Export a curve25519 public key as a raw byte-array.
* Export a curve25519 key as a raw byte-array.
*
* The output buffer `data` must have length exactly `CURVE25519_KEY_LEN`.
*/
SECStatus PublicKey_export(const_PublicKey pk,
unsigned char data[CURVE25519_KEY_LEN]);
SECStatus PublicKey_export(const_PublicKey pk, unsigned char* data,
unsigned int dataLen);
SECStatus PrivateKey_export(PrivateKey sk, unsigned char* data,
unsigned int dataLen);
/*
* Export a curve25519 public key as a NULL-terminated hex string.
* Export a curve25519 key as a NULL-terminated hex string.
*
* The output buffer `data` must have length exactly `CURVE25519_KEY_LEN_HEX +
* 1`.
*/
SECStatus PublicKey_export_hex(const_PublicKey pk,
unsigned char data[CURVE25519_KEY_LEN_HEX + 1]);
SECStatus PublicKey_export_hex(const_PublicKey pk, unsigned char* data,
unsigned int dataLen);
SECStatus PrivateKey_export_hex(PrivateKey sk, unsigned char* data,
unsigned int dataLen);
void PublicKey_clear(PublicKey pubkey);
void PrivateKey_clear(PrivateKey pvtkey);
@ -152,8 +183,8 @@ void PrivateKey_clear(PrivateKey pvtkey);
* `for_server_b` to avoid memory leaks.
*/
SECStatus PrioClient_encode(const_PrioConfig cfg, const bool* data_in,
unsigned char** for_server_a, unsigned int* aLen,
unsigned char** for_server_b, unsigned int* bLen);
unsigned char** forServerA, unsigned int* aLen,
unsigned char** forServerB, unsigned int* bLen);
/*
* Generate a new PRG seed using the NSS global randomness source.
@ -167,9 +198,9 @@ SECStatus PrioPRGSeed_randomize(PrioPRGSeed* seed);
* Pass in the _same_ secret PRGSeed when initializing the two servers.
* The PRGSeed must remain secret to the two servers.
*/
PrioServer PrioServer_new(const_PrioConfig cfg, PrioServerId server_idx,
PrivateKey server_priv,
const PrioPRGSeed server_shared_secret);
PrioServer PrioServer_new(const_PrioConfig cfg, PrioServerId serverIdx,
PrivateKey serverPriv,
const PrioPRGSeed serverSharedSecret);
void PrioServer_clear(PrioServer s);
/*
@ -255,11 +286,14 @@ SECStatus PrioTotalShare_read(PrioTotalShare t, msgpack_unpacker* upk,
/*
* Read the output data into an array of unsigned longs. You should
* be sure that each data value can fit into a single long and that
* the pointer `output` points to a buffer large enough to store
* one long per data field.
* be sure that each data value can fit into a single `unsigned long`
* and that the pointer `output` points to a buffer large enough to
* store one long per data field.
*
* This function returns failure if some final data value is too
* long to fit in an `unsigned long`.
*/
SECStatus PrioTotalShare_final(const_PrioConfig cfg, unsigned long* output,
SECStatus PrioTotalShare_final(const_PrioConfig cfg, unsigned long long* output,
const_PrioTotalShare tA,
const_PrioTotalShare tB);

13
third_party/prio/prio/config.c поставляемый
Просмотреть файл

@ -51,6 +51,13 @@ initialize_roots(MPArray arr, const char values[], bool inverted)
return SECSuccess;
}
int
PrioConfig_maxDataFields(void)
{
const int n_roots = 1 << Generator2Order;
return (n_roots >> 1) - 1;
}
PrioConfig
PrioConfig_new(int n_fields, PublicKey server_a, PublicKey server_b,
const unsigned char* batch_id, unsigned int batch_id_len)
@ -71,10 +78,8 @@ PrioConfig_new(int n_fields, PublicKey server_a, PublicKey server_b,
cfg->roots = NULL;
cfg->rootsInv = NULL;
if (cfg->num_data_fields >= cfg->n_roots) {
rv = SECFailure;
goto cleanup;
}
P_CHECKCB(cfg->n_roots > 1);
P_CHECKCB(cfg->num_data_fields <= PrioConfig_maxDataFields());
P_CHECKA(cfg->batch_id = malloc(batch_id_len));
strncpy((char*)cfg->batch_id, (char*)batch_id, batch_id_len);

247
third_party/prio/prio/encrypt.c поставляемый
Просмотреть файл

@ -26,7 +26,10 @@
#define PRIO_TAG "PrioPacket"
#define AAD_LEN (strlen(PRIO_TAG) + CURVE25519_KEY_LEN + GCM_IV_LEN_BYTES)
// The all-zeros curve25519 public key, as DER-encoded SKPI blob.
// For an example of NSS curve25519 import/export code, see:
// https://searchfox.org/nss/rev/cfd5fcba7efbfe116e2c08848075240ec3a92718/gtests/pk11_gtest/pk11_curve25519_unittest.cc#66
// The all-zeros curve25519 public key, as DER-encoded SPKI blob.
static const uint8_t curve25519_spki_zeros[] = {
0x30, 0x39, 0x30, 0x14, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02,
0x01, 0x06, 0x09, 0x2b, 0x06, 0x01, 0x04, 0x01, 0xda, 0x47, 0x0f, 0x01,
@ -35,6 +38,35 @@ static const uint8_t curve25519_spki_zeros[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
// The all-zeros curve25519 private key, as a PKCS#8 blob.
static const uint8_t curve25519_priv_zeros[] = {
0x30, 0x67, 0x02, 0x01, 0x00, 0x30, 0x14, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce,
0x3d, 0x02, 0x01, 0x06, 0x09, 0x2b, 0x06, 0x01, 0x04, 0x01, 0xda, 0x47, 0x0f,
0x01, 0x04, 0x4c, 0x30, 0x4a, 0x02, 0x01, 0x01, 0x04, 0x20,
/* Byte index 36: 32 bytes of curve25519 private key. */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* misc type fields */
0xa1, 0x23, 0x03, 0x21,
/* Byte index 73: 32 bytes of curve25519 public key. */
0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
// Index into `curve25519_priv_zeros` at which the private key begins.
static const size_t curve25519_priv_sk_offset = 36;
// Index into `curve25519_priv_zeros` at which the public key begins.
static const size_t curve25519_priv_pk_offset = 73;
static SECStatus key_from_hex(
unsigned char key_out[CURVE25519_KEY_LEN],
const unsigned char hex_in[CURVE25519_KEY_LEN_HEX]);
// Note that we do not use isxdigit because it is locale-dependent
// See: https://github.com/mozilla/libprio/issues/20
static inline char
@ -106,6 +138,7 @@ PublicKey_import(PublicKey* pk, const unsigned char* data, unsigned int dataLen)
const int spki_len = sizeof(curve25519_spki_zeros);
P_CHECKA(spki_data = calloc(spki_len, sizeof(uint8_t)));
memcpy(spki_data, curve25519_spki_zeros, spki_len);
SECItem spki_item = { siBuffer, spki_data, spki_len };
@ -131,59 +164,205 @@ cleanup:
}
SECStatus
PublicKey_import_hex(PublicKey* pk, const unsigned char* hex_data,
PrivateKey_import(PrivateKey* sk, const unsigned char* sk_data,
unsigned int sk_data_len, const unsigned char* pk_data,
unsigned int pk_data_len)
{
if (sk_data_len != CURVE25519_KEY_LEN || !sk_data) {
return SECFailure;
}
if (pk_data_len != CURVE25519_KEY_LEN || !pk_data) {
return SECFailure;
}
SECStatus rv = SECSuccess;
PK11SlotInfo* slot = NULL;
uint8_t* zero_priv_data = NULL;
*sk = NULL;
const int zero_priv_len = sizeof(curve25519_priv_zeros);
P_CHECKA(slot = PK11_GetInternalSlot());
P_CHECKA(zero_priv_data = calloc(zero_priv_len, sizeof(uint8_t)));
SECItem zero_priv_item = { siBuffer, zero_priv_data, zero_priv_len };
// Copy the PKCS#8-encoded keypair into writable buffer.
memcpy(zero_priv_data, curve25519_priv_zeros, zero_priv_len);
// Copy private key into bytes beginning at index `curve25519_priv_sk_offset`.
memcpy(zero_priv_data + curve25519_priv_sk_offset, sk_data, sk_data_len);
// Copy private key into bytes beginning at index `curve25519_priv_pk_offset`.
memcpy(zero_priv_data + curve25519_priv_pk_offset, pk_data, pk_data_len);
P_CHECKC(PK11_ImportDERPrivateKeyInfoAndReturnKey(
slot, &zero_priv_item, NULL, NULL, PR_FALSE, PR_FALSE, KU_ALL, sk, NULL));
cleanup:
if (slot) {
PK11_FreeSlot(slot);
}
if (zero_priv_data) {
free(zero_priv_data);
}
if (rv != SECSuccess) {
PrivateKey_clear(*sk);
}
return rv;
}
SECStatus
PublicKey_import_hex(PublicKey* pk, const unsigned char* hexData,
unsigned int dataLen)
{
unsigned char raw_bytes[CURVE25519_KEY_LEN];
if (dataLen != CURVE25519_KEY_LEN_HEX)
if (dataLen != CURVE25519_KEY_LEN_HEX || !hexData) {
return SECFailure;
for (unsigned int i = 0; i < dataLen; i++) {
if (!is_hex_digit(hex_data[i]))
return SECFailure;
}
const unsigned char* p = hex_data;
for (unsigned int i = 0; i < CURVE25519_KEY_LEN; i++) {
uint8_t d0 = hex_to_int(p[0]);
uint8_t d1 = hex_to_int(p[1]);
raw_bytes[i] = (d0 << 4) | d1;
p += 2;
if (key_from_hex(raw_bytes, hexData) != SECSuccess) {
return SECFailure;
}
return PublicKey_import(pk, raw_bytes, CURVE25519_KEY_LEN);
}
SECStatus
PublicKey_export(const_PublicKey pk, unsigned char data[CURVE25519_KEY_LEN])
PrivateKey_import_hex(PrivateKey* sk, const unsigned char* privHexData,
unsigned int privDataLen, const unsigned char* pubHexData,
unsigned int pubDataLen)
{
if (pk == NULL)
return SECFailure;
SECStatus rv = SECSuccess;
unsigned char raw_priv[CURVE25519_KEY_LEN];
unsigned char raw_pub[CURVE25519_KEY_LEN];
memcpy(data, pk->u.ec.publicValue.data, CURVE25519_KEY_LEN);
if (privDataLen != CURVE25519_KEY_LEN_HEX ||
pubDataLen != CURVE25519_KEY_LEN_HEX) {
return SECFailure;
}
if (!privHexData || !pubHexData) {
return SECFailure;
}
P_CHECK(key_from_hex(raw_priv, privHexData));
P_CHECK(key_from_hex(raw_pub, pubHexData));
return PrivateKey_import(sk, raw_priv, CURVE25519_KEY_LEN, raw_pub,
CURVE25519_KEY_LEN);
}
SECStatus
PublicKey_export(const_PublicKey pk, unsigned char* data, unsigned int dataLen)
{
if (pk == NULL || dataLen != CURVE25519_KEY_LEN) {
return SECFailure;
}
const SECItem* key = &pk->u.ec.publicValue;
if (key->len != CURVE25519_KEY_LEN) {
return SECFailure;
}
memcpy(data, key->data, key->len);
return SECSuccess;
}
SECStatus
PrivateKey_export(PrivateKey sk, unsigned char* data, unsigned int dataLen)
{
if (sk == NULL || dataLen != CURVE25519_KEY_LEN) {
return SECFailure;
}
SECStatus rv = SECSuccess;
SECItem item = { siBuffer, NULL, 0 };
P_CHECKC(PK11_ReadRawAttribute(PK11_TypePrivKey, sk, CKA_VALUE, &item));
// If the leading bytes of the key are '\0', then this string can be
// shorter than `CURVE25519_KEY_LEN` bytes.
memset(data, 0, CURVE25519_KEY_LEN);
P_CHECKCB(item.len <= CURVE25519_KEY_LEN);
// Copy into the low-order bytes of the output.
const size_t leading_zeros = CURVE25519_KEY_LEN - item.len;
memcpy(data + leading_zeros, item.data, item.len);
cleanup:
if (item.data != NULL) {
SECITEM_ZfreeItem(&item, PR_FALSE);
}
return rv;
}
static void
key_to_hex(const unsigned char key_in[CURVE25519_KEY_LEN],
unsigned char hex_out[(2 * CURVE25519_KEY_LEN) + 1])
{
const unsigned char* p = key_in;
for (unsigned int i = 0; i < CURVE25519_KEY_LEN; i++) {
unsigned char bytel = p[0] & 0x0f;
unsigned char byteu = (p[0] & 0xf0) >> 4;
hex_out[2 * i] = int_to_hex(byteu);
hex_out[2 * i + 1] = int_to_hex(bytel);
p++;
}
hex_out[2 * CURVE25519_KEY_LEN] = '\0';
}
static SECStatus
key_from_hex(unsigned char key_out[CURVE25519_KEY_LEN],
const unsigned char hex_in[CURVE25519_KEY_LEN_HEX])
{
for (unsigned int i = 0; i < CURVE25519_KEY_LEN_HEX; i++) {
if (!is_hex_digit(hex_in[i]))
return SECFailure;
}
const unsigned char* p = hex_in;
for (unsigned int i = 0; i < CURVE25519_KEY_LEN; i++) {
uint8_t d0 = hex_to_int(p[0]);
uint8_t d1 = hex_to_int(p[1]);
key_out[i] = (d0 << 4) | d1;
p += 2;
}
return SECSuccess;
}
SECStatus
PublicKey_export_hex(const_PublicKey pk,
unsigned char data[(2 * CURVE25519_KEY_LEN) + 1])
PublicKey_export_hex(const_PublicKey pk, unsigned char* data,
unsigned int dataLen)
{
unsigned char raw_data[CURVE25519_KEY_LEN];
if (PublicKey_export(pk, raw_data) != SECSuccess)
if (dataLen != CURVE25519_KEY_LEN_HEX + 1) {
return SECFailure;
const unsigned char* p = raw_data;
for (unsigned int i = 0; i < CURVE25519_KEY_LEN; i++) {
unsigned char bytel = p[0] & 0x0f;
unsigned char byteu = (p[0] & 0xf0) >> 4;
data[2 * i] = int_to_hex(byteu);
data[2 * i + 1] = int_to_hex(bytel);
p++;
}
data[2 * CURVE25519_KEY_LEN] = '\0';
unsigned char raw_data[CURVE25519_KEY_LEN];
if (PublicKey_export(pk, raw_data, sizeof(raw_data)) != SECSuccess) {
return SECFailure;
}
key_to_hex(raw_data, data);
return SECSuccess;
}
SECStatus
PrivateKey_export_hex(PrivateKey sk, unsigned char* data, unsigned int dataLen)
{
if (dataLen != CURVE25519_KEY_LEN_HEX + 1) {
return SECFailure;
}
unsigned char raw_data[CURVE25519_KEY_LEN];
if (PrivateKey_export(sk, raw_data, sizeof(raw_data)) != SECSuccess) {
return SECFailure;
}
key_to_hex(raw_data, data);
return SECSuccess;
}
@ -220,11 +399,13 @@ Keypair_new(PrivateKey* pvtkey, PublicKey* pubkey)
P_CHECKA(*pvtkey = PK11_GenerateKeyPair(slot, CKM_EC_KEY_PAIR_GEN, &ecp,
(SECKEYPublicKey**)pubkey, PR_FALSE,
PR_FALSE, NULL));
PK11_FreeSlot(slot);
cleanup:
if (ecp.data)
if (slot) {
PK11_FreeSlot(slot);
}
if (ecp.data) {
free(ecp.data);
}
if (rv != SECSuccess) {
PublicKey_clear(*pubkey);
PrivateKey_clear(*pvtkey);

4
third_party/prio/prio/poly.c поставляемый
Просмотреть файл

@ -74,8 +74,8 @@ fft_interpolate_raw(mp_int* out, const mp_int* ys, int nPoints,
mp_int n_inverse;
MP_DIGITS(&n_inverse) = NULL;
MP_CHECK(fft_recurse(out, mod, nPoints, roots, ys, tmp->data, ySub->data,
rootsSub->data));
MP_CHECKC(fft_recurse(out, mod, nPoints, roots, ys, tmp->data, ySub->data,
rootsSub->data));
if (invert) {
MP_CHECKC(mp_init(&n_inverse));

26
third_party/prio/prio/prg.c поставляемый
Просмотреть файл

@ -119,6 +119,32 @@ PRG_get_int(PRG prg, mp_int* out, const mp_int* max)
return rand_int_rng(out, max, &PRG_get_bytes_internal, (void*)prg);
}
SECStatus
PRG_get_int_range(PRG prg, mp_int* out, const mp_int* lower, const mp_int* max)
{
SECStatus rv;
mp_int width;
MP_DIGITS(&width) = NULL;
MP_CHECKC(mp_init(&width));
// Compute
// width = max - lower
MP_CHECKC(mp_sub(max, lower, &width));
// Get an integer x in the range [0, width)
P_CHECKC(PRG_get_int(prg, out, &width));
// Set
// out = lower + x
// which is in the range [lower, width+lower),
// which is [lower, max).
MP_CHECKC(mp_add(lower, out, out));
cleanup:
mp_clear(&width);
return rv;
}
SECStatus
PRG_get_array(PRG prg, MPArray dst, const mp_int* mod)
{

7
third_party/prio/prio/prg.h поставляемый
Просмотреть файл

@ -35,6 +35,13 @@ SECStatus PRG_get_bytes(PRG prg, unsigned char* bytes, size_t len);
*/
SECStatus PRG_get_int(PRG prg, mp_int* out, const mp_int* max);
/*
* Use the PRG output to sample a big integer x in the range
* lower <= x < max.
*/
SECStatus PRG_get_int_range(PRG prg, mp_int* out, const mp_int* lower,
const mp_int* max);
/*
* Use secret sharing to split the int src into two shares.
* Use PRG to generate the value `shareB`.

25
third_party/prio/prio/server.c поставляемый
Просмотреть файл

@ -18,6 +18,13 @@
#include "server.h"
#include "util.h"
/* In `PrioTotalShare_final`, we need to be able to store
* an `mp_digit` in an `unsigned long long`.
*/
#if (MP_DIGIT_MAX > ULLONG_MAX)
#error "Unsigned long long is not long enough to hold an MP digit"
#endif
PrioServer
PrioServer_new(const_PrioConfig cfg, PrioServerId server_idx,
PrivateKey server_priv, const PrioPRGSeed seed)
@ -112,7 +119,7 @@ PrioTotalShare_set_data(PrioTotalShare t, const_PrioServer s)
}
SECStatus
PrioTotalShare_final(const_PrioConfig cfg, unsigned long* output,
PrioTotalShare_final(const_PrioConfig cfg, unsigned long long* output,
const_PrioTotalShare tA, const_PrioTotalShare tB)
{
if (tA->data_shares->len != cfg->num_data_fields)
@ -132,7 +139,10 @@ PrioTotalShare_final(const_PrioConfig cfg, unsigned long* output,
MP_CHECKC(mp_addmod(&tA->data_shares->data[i], &tB->data_shares->data[i],
&cfg->modulus, &tmp));
output[i] = tmp.dp[0];
if (MP_USED(&tmp) > 1) {
P_CHECKCB(false);
}
output[i] = MP_DIGIT(&tmp, 0);
}
cleanup:
@ -178,19 +188,25 @@ compute_shares(PrioVerifier v, const_PrioPacketClient p)
const int n = v->s->cfg->num_data_fields + 1;
const int N = next_power_of_two(n);
mp_int eval_at;
mp_int lower;
MP_DIGITS(&eval_at) = NULL;
MP_DIGITS(&lower) = NULL;
MPArray points_f = NULL;
MPArray points_g = NULL;
MPArray points_h = NULL;
MP_CHECKC(mp_init(&eval_at));
MP_CHECKC(mp_init(&lower));
P_CHECKA(points_f = MPArray_new(N));
P_CHECKA(points_g = MPArray_new(N));
P_CHECKA(points_h = MPArray_new(2 * N));
// Use PRG to generate random point
MP_CHECKC(PRG_get_int(v->s->prg, &eval_at, &v->s->cfg->modulus));
// Use PRG to generate random point. Per Appendix D.2 of full version of
// Prio paper, this value must be in the range
// [n+1, modulus).
mp_set(&lower, n + 1);
P_CHECKC(PRG_get_int_range(v->s->prg, &eval_at, &lower, &v->s->cfg->modulus));
// Reduce value into the field we're using. This
// doesn't yield exactly a uniformly random point,
@ -233,6 +249,7 @@ cleanup:
MPArray_clear(points_g);
MPArray_clear(points_h);
mp_clear(&eval_at);
mp_clear(&lower);
return rv;
}

2
third_party/prio/update.sh поставляемый
Просмотреть файл

@ -5,7 +5,7 @@
MY_TEMP_DIR=`mktemp -d -t libprio_update.XXXXXX` || exit 1
COMMIT="02a81fb652d385d0f4f10989d051317097ab55fb"
COMMIT="a95cfdd5eaf7104582709c54ef23395d24d7f7fd"
git clone -n https://github.com/mozilla/libprio ${MY_TEMP_DIR}/libprio
git -C ${MY_TEMP_DIR}/libprio checkout ${COMMIT}

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

@ -0,0 +1,46 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
*/
ChromeUtils.import("resource://gre/modules/Services.jsm");
ChromeUtils.import("resource://gre/modules/TelemetryController.jsm");
ChromeUtils.import("resource://testing-common/ContentTaskUtils.jsm");
const SOCKET_ONLY_UINT_SCALAR = "telemetry.test.socket_only_uint";
/**
* This function waits until socket scalars are reported into the
* scalar snapshot.
*/
async function waitForSocketScalars() {
await ContentTaskUtils.waitForCondition(() => {
const scalars = Telemetry.getSnapshotForScalars("main", false);
return Object.keys(scalars).includes("socket");
});
}
add_task(async function() {
if (!Services.prefs.getBoolPref("network.process.enabled")) {
Assert.ok(true, "Test finished: no point to test telemetry from socket process with lanuching the process");
return;
}
do_test_pending();
do_get_profile(true);
await TelemetryController.testSetup();
Services.netUtils.socketProcessTelemetryPing();
// Once scalars are set by the socket process, they don't immediately get
// sent to the parent process. Wait for the Telemetry IPC Timer to trigger
// and batch send the data back to the parent process.
await waitForSocketScalars();
Assert.equal(Telemetry.getSnapshotForScalars("main", false)
.socket[SOCKET_ONLY_UINT_SCALAR],
42,
`${SOCKET_ONLY_UINT_SCALAR} must have the correct value (socket process).`);
do_test_finished();
});

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

@ -67,6 +67,8 @@ skip-if = os == "android" # Disabled due to crashes (see bug 1331366)
tags = addons
[test_ChildScalars.js]
skip-if = os == "android" # Disabled due to crashes (see bug 1331366)
[test_SocketScalars.js]
skip-if = os == "android"
[test_TelemetryReportingPolicy.js]
skip-if = os == "android" # Disabled due to crashes (see bug 1367762)
tags = addons

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

@ -58,6 +58,19 @@ var snapshotFormatters = {
$("updatechannel-box").textContent = data.updateChannel;
$("profile-dir-box").textContent = Services.dirsvc.get("ProfD", Ci.nsIFile).path;
try {
let launcherStatusTextId = "launcher-process-status-unknown";
switch (data.launcherProcessState) {
case 0:
case 1:
case 2:
launcherStatusTextId = "launcher-process-status-" + data.launcherProcessState;
break;
}
document.l10n.setAttributes($("launcher-process-box"), launcherStatusTextId);
} catch (e) {}
let statusTextId = "multi-process-status-unknown";
// Whitelist of known values with string descriptions:

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

@ -163,6 +163,15 @@
</td>
</tr>
#if defined(XP_WIN) && defined(MOZ_LAUNCHER_PROCESS)
<tr>
<th class="column" data-l10n-id="app-basics-launcher-process-status"/>
<td id="launcher-process-box">
</td>
</tr>
#endif
<tr>
<th class="column" data-l10n-id="app-basics-multi-process-support"/>

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

@ -48,6 +48,7 @@ app-basics-memory-use = Memory Use
app-basics-performance = Performance
app-basics-service-workers = Registered Service Workers
app-basics-profiles = Profiles
app-basics-launcher-process-status = Launcher Process
app-basics-multi-process-support = Multiprocess Windows
app-basics-process-count = Web Content Processes
app-basics-enterprise-policies = Enterprise Policies
@ -260,6 +261,11 @@ sandbox-proc-type-content = content
sandbox-proc-type-file = file content
sandbox-proc-type-media-plugin = media plugin
launcher-process-status-0 = Enabled
launcher-process-status-1 = Disabled due to failure
launcher-process-status-2 = Disabled forcibly
launcher-process-status-unknown = Unknown status
# Variables
# $remoteWindows (integer) - Number of remote windows
# $totalWindows (integer) - Number of total windows

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

@ -197,6 +197,10 @@ var dataProviders = {
}
}
try {
data.launcherProcessState = Services.appinfo.launcherProcessState;
} catch (e) {}
data.remoteAutoStart = Services.appinfo.browserTabsRemoteAutostart;
// Services.ppmm.childCount is a count of how many processes currently

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

@ -125,6 +125,9 @@ const SNAPSHOT_SCHEMA = {
supportURL: {
type: "string",
},
launcherProcessState: {
type: "number",
},
remoteAutoStart: {
type: "boolean",
required: true,

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

@ -8402,3 +8402,71 @@ end:
Pop $1
Pop $0
!macroend
Function WriteRegQWORD
; Stack contents:
; VALUE, VALUE_NAME, SUBKEY, ROOTKEY
Exch $3 ; $3, VALUE_NAME, SUBKEY, ROOTKEY
Exch 1 ; VALUE_NAME, $3, SUBKEY, ROOTKEY
Exch $2 ; $2, $3, SUBKEY, ROOTKEY
Exch 2 ; SUBKEY, $3, $2, ROOTKEY
Exch $1 ; $1, $3, $2, ROOTKEY
Exch 3 ; ROOTKEY, $3, $2, $1
Exch $0 ; $0, $3, $2, $1
System::Call "advapi32::RegSetKeyValueW(p r0, w r1, w r2, i 11, *l r3, i 8) i.r0"
${IfNot} $0 = 0
SetErrors
${EndIf}
Pop $0
Pop $3
Pop $2
Pop $1
FunctionEnd
!macro WriteRegQWORD ROOTKEY SUBKEY VALUE_NAME VALUE
${If} "${ROOTKEY}" == "HKCR"
Push 0x80000000
${ElseIf} "${ROOTKEY}" == "HKCU"
Push 0x80000001
${ElseIf} "${ROOTKEY}" == "HKLM"
Push 0x80000002
${Endif}
Push "${SUBKEY}"
Push "${VALUE_NAME}"
System::Int64Op ${VALUE} + 0 ; The result is pushed on the stack
Call WriteRegQWORD
!macroend
!define WriteRegQWORD "!insertmacro WriteRegQWORD"
Function ReadRegQWORD
; Stack contents:
; VALUE_NAME, SUBKEY, ROOTKEY
Exch $2 ; $2, SUBKEY, ROOTKEY
Exch 1 ; SUBKEY, $2, ROOTKEY
Exch $1 ; $1, $2, ROOTKEY
Exch 2 ; ROOTKEY, $2, $1
Exch $0 ; $0, $2, $1
System::Call "advapi32::RegGetValueW(p r0, w r1, w r2, i 0x48, p 0, *l s, *i 8) i.r0"
${IfNot} $0 = 0
SetErrors
${EndIf}
; VALUE, $0, $2, $1
Exch 3 ; $1, $0, $2, VALUE
Pop $1 ; $0, $2, VALUE
Pop $0 ; $2, VALUE
Pop $2 ; VALUE
FunctionEnd
!macro ReadRegQWORD DEST ROOTKEY SUBKEY VALUE_NAME
${If} "${ROOTKEY}" == "HKCR"
Push 0x80000000
${ElseIf} "${ROOTKEY}" == "HKCU"
Push 0x80000001
${ElseIf} "${ROOTKEY}" == "HKLM"
Push 0x80000002
${Endif}
Push "${SUBKEY}"
Push "${VALUE_NAME}"
Call ReadRegQWORD
Pop ${DEST}
!macroend
!define ReadRegQWORD "!insertmacro ReadRegQWORD"

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

@ -6,4 +6,3 @@ toolkit.jar:
% content pluginproblem %pluginproblem/ contentaccessible=yes
pluginproblem/pluginProblem.xml (content/pluginProblem.xml)
pluginproblem/pluginProblemContent.css (content/pluginProblemContent.css)
pluginproblem/pluginProblemBinding.css (content/pluginProblemBinding.css)

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

@ -4,8 +4,4 @@
# 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/.
EXTRA_COMPONENTS += [
'pluginGlue.manifest',
]
JAR_MANIFESTS += ['jar.mn']

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

@ -1 +0,0 @@
category agent-style-sheets pluginGlue-pluginProblem chrome://pluginproblem/content/pluginProblemBinding.css

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

@ -26,10 +26,10 @@ class LauncherRegistryInfo final {
public:
enum class ProcessType { Launcher, Browser };
enum class EnabledState {
Enabled,
FailDisabled,
ForceDisabled,
enum class EnabledState : uint32_t {
Enabled = 0,
FailDisabled = 1,
ForceDisabled = 2,
};
LauncherRegistryInfo() : mBinPath(GetFullBinaryPath().get()) {}

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

@ -945,6 +945,24 @@ nsXULAppInfo::GetRestartedByOS(bool* aResult) {
return NS_OK;
}
NS_IMETHODIMP
nsXULAppInfo::GetLauncherProcessState(uint32_t* aResult) {
#if defined(XP_WIN) && defined(MOZ_LAUNCHER_PROCESS)
LauncherRegistryInfo launcherInfo;
LauncherResult<LauncherRegistryInfo::EnabledState> state =
launcherInfo.IsEnabled();
if (state.isErr()) {
return NS_ERROR_UNEXPECTED;
}
*aResult = static_cast<uint32_t>(state.unwrap());
return NS_OK;
#else
return NS_ERROR_NOT_AVAILABLE;
#endif
}
#ifdef XP_WIN
// Matches the enum in WinNT.h for the Vista SDK but renamed so that we can
// safely build with the Vista SDK and without it.

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

@ -19,7 +19,6 @@
class nsOSHelperAppService : public nsExternalHelperAppService {
public:
nsOSHelperAppService();
virtual ~nsOSHelperAppService();
// override nsIExternalProtocolService methods
@ -52,9 +51,6 @@ class nsOSHelperAppService : public nsExternalHelperAppService {
MOZ_MUST_USE nsresult OSProtocolHandlerExists(const char* aScheme,
bool* aHandlerExists) override;
private:
uint32_t mPermissions;
};
#endif // nsOSHelperAppService_h__

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

@ -54,13 +54,6 @@ using mozilla::LogLevel;
- (NSArray*)extensionsForMIMEType:(NSString*)aString;
@end
nsOSHelperAppService::nsOSHelperAppService() : nsExternalHelperAppService()
{
mode_t mask = umask(0777);
umask(mask);
mPermissions = 0666 & ~mask;
}
nsOSHelperAppService::~nsOSHelperAppService()
{}

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

@ -49,12 +49,6 @@ static nsresult ParseMIMEType(const nsAString::const_iterator& aStart_iter,
inline bool IsNetscapeFormat(const nsACString& aBuffer);
nsOSHelperAppService::nsOSHelperAppService() : nsExternalHelperAppService() {
mode_t mask = umask(0777);
umask(mask);
mPermissions = 0666 & ~mask;
}
nsOSHelperAppService::~nsOSHelperAppService() {}
/*

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

@ -21,7 +21,6 @@ class nsILineInputStream;
class nsOSHelperAppService : public nsExternalHelperAppService {
public:
nsOSHelperAppService();
virtual ~nsOSHelperAppService();
// method overrides for mime.types and mime.info look up steps
@ -52,8 +51,6 @@ class nsOSHelperAppService : public nsExternalHelperAppService {
already_AddRefed<nsMIMEInfoBase> GetFromExtension(const nsCString& aFileExt);
private:
uint32_t mPermissions;
// Helper methods which have to access static members
static nsresult UnescapeCommand(const nsAString& aEscapedCommand,
const nsAString& aMajorType,

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

@ -202,4 +202,10 @@ interface nsIXULRuntime : nsISupports
* restart mechanism (such as RegisterApplicationRestart on Windows).
*/
readonly attribute boolean restartedByOS;
/**
* Returns a value corresponding to one of the
* |mozilla::LauncherRegistryInfo::EnabledState| values.
*/
readonly attribute uint32_t launcherProcessState;
};