зеркало из https://github.com/mozilla/gecko-dev.git
Merge autoland to mozilla-central. a=merge
This commit is contained in:
Коммит
96141919a9
|
@ -1212,6 +1212,12 @@ var gSync = {
|
|||
if (confirm && !(await this._confirmDisconnect(disconnectAccount))) {
|
||||
return false;
|
||||
}
|
||||
// Record telemetry.
|
||||
await fxAccounts.telemetry.recordDisconnection(
|
||||
disconnectAccount ? null : "sync",
|
||||
"ui"
|
||||
);
|
||||
|
||||
await Weave.Service.promiseInitialized;
|
||||
await Weave.Service.startOver();
|
||||
if (disconnectAccount) {
|
||||
|
|
|
@ -81,6 +81,7 @@ skip-if = fission
|
|||
skip-if = (verify && debug && (os == 'win'))
|
||||
[browser_imageCacheIsolation.js]
|
||||
[browser_sharedworker.js]
|
||||
skip-if = fission #Bug 1582318
|
||||
[browser_httpauth.js]
|
||||
[browser_clientAuth.js]
|
||||
skip-if = verify
|
||||
|
|
|
@ -302,7 +302,14 @@ var gSyncPane = {
|
|||
if (!isAlreadySyncing && event.detail.button == "accept") {
|
||||
// We weren't syncing but the user has accepted the dialog - so we
|
||||
// want to start!
|
||||
Weave.Service.configure();
|
||||
fxAccounts.telemetry
|
||||
.recordConnection(["sync"], "ui")
|
||||
.then(() => {
|
||||
return Weave.Service.configure();
|
||||
})
|
||||
.catch(err => {
|
||||
console.error("Failed to enable sync", err);
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
|
|
|
@ -80,16 +80,18 @@ class CompatibilityView {
|
|||
);
|
||||
}
|
||||
|
||||
_isVisible() {
|
||||
_isAvailable() {
|
||||
return (
|
||||
this.inspector &&
|
||||
this.inspector.sidebar &&
|
||||
this.inspector.sidebar.getCurrentTabID() === "compatibilityview"
|
||||
this.inspector.sidebar.getCurrentTabID() === "compatibilityview" &&
|
||||
this.inspector.selection &&
|
||||
this.inspector.selection.isConnected()
|
||||
);
|
||||
}
|
||||
|
||||
_onNewNode() {
|
||||
if (!this._isVisible()) {
|
||||
if (!this._isAvailable()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -5,19 +5,35 @@
|
|||
"use strict";
|
||||
|
||||
const {
|
||||
COMPATIBILITY_UPDATE_SELECTED_NODE,
|
||||
COMPATIBILITY_UPDATE_SELECTED_NODE_START,
|
||||
COMPATIBILITY_UPDATE_SELECTED_NODE_SUCCESS,
|
||||
COMPATIBILITY_UPDATE_SELECTED_NODE_FAILURE,
|
||||
COMPATIBILITY_UPDATE_SELECTED_NODE_COMPLETE,
|
||||
COMPATIBILITY_UPDATE_TARGET_BROWSERS,
|
||||
} = require("./index");
|
||||
|
||||
function updateSelectedNode(nodeFront) {
|
||||
return async ({ dispatch }) => {
|
||||
const pageStyle = nodeFront.inspectorFront.pageStyle;
|
||||
const styles = await pageStyle.getApplied(nodeFront, { skipPseudo: false });
|
||||
const declarationBlocks = styles
|
||||
.map(({ rule }) => rule.declarations.filter(d => !d.commentOffsets))
|
||||
.filter(declarations => declarations.length);
|
||||
dispatch({ type: COMPATIBILITY_UPDATE_SELECTED_NODE_START });
|
||||
|
||||
dispatch({ type: COMPATIBILITY_UPDATE_SELECTED_NODE, declarationBlocks });
|
||||
try {
|
||||
const pageStyle = nodeFront.inspectorFront.pageStyle;
|
||||
const styles = await pageStyle.getApplied(nodeFront, {
|
||||
skipPseudo: false,
|
||||
});
|
||||
const declarationBlocks = styles
|
||||
.map(({ rule }) => rule.declarations.filter(d => !d.commentOffsets))
|
||||
.filter(declarations => declarations.length);
|
||||
|
||||
dispatch({
|
||||
type: COMPATIBILITY_UPDATE_SELECTED_NODE_SUCCESS,
|
||||
declarationBlocks,
|
||||
});
|
||||
} catch (error) {
|
||||
dispatch({ type: COMPATIBILITY_UPDATE_SELECTED_NODE_FAILURE, error });
|
||||
}
|
||||
|
||||
dispatch({ type: COMPATIBILITY_UPDATE_SELECTED_NODE_COMPLETE });
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,10 @@ const { createEnum } = require("devtools/client/shared/enum");
|
|||
createEnum(
|
||||
[
|
||||
// Updates the selected node.
|
||||
"COMPATIBILITY_UPDATE_SELECTED_NODE",
|
||||
"COMPATIBILITY_UPDATE_SELECTED_NODE_START",
|
||||
"COMPATIBILITY_UPDATE_SELECTED_NODE_SUCCESS",
|
||||
"COMPATIBILITY_UPDATE_SELECTED_NODE_FAILURE",
|
||||
"COMPATIBILITY_UPDATE_SELECTED_NODE_COMPLETE",
|
||||
|
||||
// Updates the target browsers.
|
||||
"COMPATIBILITY_UPDATE_TARGET_BROWSERS",
|
||||
|
|
|
@ -11,7 +11,8 @@ loader.lazyGetter(this, "mdnCompatibility", () => {
|
|||
});
|
||||
|
||||
const {
|
||||
COMPATIBILITY_UPDATE_SELECTED_NODE,
|
||||
COMPATIBILITY_UPDATE_SELECTED_NODE_SUCCESS,
|
||||
COMPATIBILITY_UPDATE_SELECTED_NODE_FAILURE,
|
||||
COMPATIBILITY_UPDATE_TARGET_BROWSERS,
|
||||
} = require("../actions/index");
|
||||
|
||||
|
@ -22,9 +23,16 @@ const INITIAL_STATE = {
|
|||
};
|
||||
|
||||
const reducers = {
|
||||
[COMPATIBILITY_UPDATE_SELECTED_NODE](state, data) {
|
||||
[COMPATIBILITY_UPDATE_SELECTED_NODE_SUCCESS](state, data) {
|
||||
return updateSelectedNodeIssues(state, data);
|
||||
},
|
||||
[COMPATIBILITY_UPDATE_SELECTED_NODE_FAILURE](state, { error }) {
|
||||
console.error(
|
||||
`[COMPATIBILITY_UPDATE_SELECTED_NODE_FAILURE] ${error.message}`
|
||||
);
|
||||
console.error(error.stack);
|
||||
return state;
|
||||
},
|
||||
[COMPATIBILITY_UPDATE_TARGET_BROWSERS](state, data) {
|
||||
return updateSelectedNodeIssues(state, data);
|
||||
},
|
||||
|
|
|
@ -12,6 +12,7 @@ support-files =
|
|||
|
||||
[browser_compatibility_css-property_issue.js]
|
||||
[browser_compatibility_event_new-node.js]
|
||||
[browser_compatibility_event_new-node_without-connection.js]
|
||||
[browser_compatibility_event_rule-change.js]
|
||||
[browser_compatibility_preference.js]
|
||||
[browser_compatibility_unsupported-browsers_all.js]
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Test whether no errors occur when reloading the browsing page.
|
||||
|
||||
const {
|
||||
COMPATIBILITY_UPDATE_SELECTED_NODE_FAILURE,
|
||||
} = require("devtools/client/inspector/compatibility/actions/index");
|
||||
|
||||
add_task(async function() {
|
||||
const tab = await addTab("data:text/html;charset=utf-8,test");
|
||||
const { inspector } = await openCompatibilityView();
|
||||
|
||||
let isFailureActionFired = false;
|
||||
waitForDispatch(
|
||||
inspector.store,
|
||||
COMPATIBILITY_UPDATE_SELECTED_NODE_FAILURE
|
||||
).then(() => {
|
||||
isFailureActionFired = true;
|
||||
});
|
||||
|
||||
info("Reload the browsing page");
|
||||
const onReloaded = BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
|
||||
const onUpdateAction = waitForUpdateSelectedNodeAction(inspector.store);
|
||||
gBrowser.reloadTab(tab);
|
||||
await Promise.all([onReloaded, onUpdateAction]);
|
||||
|
||||
info("Check whether the failure action will be fired or not");
|
||||
ok(!isFailureActionFired, "No error occurred");
|
||||
});
|
|
@ -11,6 +11,10 @@ Services.scriptloader.loadSubScript(
|
|||
this
|
||||
);
|
||||
|
||||
const {
|
||||
COMPATIBILITY_UPDATE_SELECTED_NODE_COMPLETE,
|
||||
} = require("devtools/client/inspector/compatibility/actions/index");
|
||||
|
||||
const {
|
||||
toCamelCase,
|
||||
} = require("devtools/client/inspector/compatibility/utils/cases");
|
||||
|
@ -20,6 +24,7 @@ async function openCompatibilityView() {
|
|||
await pushPref("devtools.inspector.compatibility.enabled", true);
|
||||
|
||||
const { inspector } = await openInspectorSidebarTab("compatibilityview");
|
||||
await waitForUpdateSelectedNodeAction(inspector.store);
|
||||
const panel = inspector.panelDoc.querySelector(
|
||||
"#compatibilityview-panel .inspector-tabpanel"
|
||||
);
|
||||
|
@ -66,3 +71,32 @@ async function assertIssueList(panel, expectedIssues) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a promise which waits for COMPATIBILITY_UPDATE_SELECTED_NODE_COMPLETE action.
|
||||
*
|
||||
* @param {Object} store
|
||||
* @return {Promise}
|
||||
*/
|
||||
function waitForUpdateSelectedNodeAction(store) {
|
||||
return waitForDispatch(store, COMPATIBILITY_UPDATE_SELECTED_NODE_COMPLETE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a promise which waits for given action type.
|
||||
*
|
||||
* @param {Object} store
|
||||
* @param {Object} type
|
||||
* @return {Promise}
|
||||
*/
|
||||
function waitForDispatch(store, type) {
|
||||
return new Promise(resolve => {
|
||||
store.dispatch({
|
||||
type: "@@service/waitUntil",
|
||||
predicate: action => action.type === type,
|
||||
run: (dispatch, getState, action) => {
|
||||
resolve(action);
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -140,9 +140,7 @@ void BrowserBridgeParent::Destroy() {
|
|||
IPCResult BrowserBridgeParent::RecvShow(const ScreenIntSize& aSize,
|
||||
const bool& aParentIsActive,
|
||||
const nsSizeMode& aSizeMode) {
|
||||
if (!mBrowserParent->AttachLayerManager()) {
|
||||
MOZ_CRASH();
|
||||
}
|
||||
mBrowserParent->AttachLayerManager();
|
||||
Unused << mBrowserParent->SendShow(aSize, mBrowserParent->GetShowInfo(),
|
||||
aParentIsActive, aSizeMode);
|
||||
return IPC_OK();
|
||||
|
|
|
@ -10,13 +10,18 @@
|
|||
#include <d3d11.h>
|
||||
#include <assert.h>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#define EGL_EGL_PROTOTYPES 1
|
||||
#define EGL_EGLEXT_PROTOTYPES 1
|
||||
#define GL_GLEXT_PROTOTYPES 1
|
||||
#include "EGL/egl.h"
|
||||
#include "EGL/eglext.h"
|
||||
#include "EGL/eglext_angle.h"
|
||||
#include "GL/gl.h"
|
||||
#include "GLES/gl.h"
|
||||
#include "GLES/glext.h"
|
||||
#include "GLES3/gl3.h"
|
||||
|
||||
// The OS compositor representation of a picture cache tile.
|
||||
struct Tile {
|
||||
|
@ -26,6 +31,13 @@ struct Tile {
|
|||
IDCompositionVisual2 *pVisual;
|
||||
};
|
||||
|
||||
struct CachedFrameBuffer {
|
||||
int width;
|
||||
int height;
|
||||
GLuint fboId;
|
||||
GLuint depthRboId;
|
||||
};
|
||||
|
||||
struct Window {
|
||||
// Win32 window details
|
||||
HWND hWnd;
|
||||
|
@ -50,8 +62,9 @@ struct Window {
|
|||
EGLSurface fb_surface;
|
||||
|
||||
// The currently bound surface, valid during bind() and unbind()
|
||||
EGLSurface current_surface;
|
||||
IDCompositionSurface *pCurrentSurface;
|
||||
EGLImage mEGLImage;
|
||||
GLuint mColorRBO;
|
||||
|
||||
// The root of the DC visual tree. Nothing is drawn on this, but
|
||||
// all child tiles are parented to here.
|
||||
|
@ -59,10 +72,50 @@ struct Window {
|
|||
IDCompositionVisualDebug *pVisualDebug;
|
||||
// Maps the WR surface IDs to the DC representation of each tile.
|
||||
std::map<uint64_t, Tile> tiles;
|
||||
std::vector<CachedFrameBuffer> mFrameBuffers;
|
||||
};
|
||||
|
||||
static const wchar_t *CLASS_NAME = L"WR DirectComposite";
|
||||
|
||||
static GLuint GetOrCreateFbo(Window *window, int aWidth, int aHeight) {
|
||||
GLuint fboId = 0;
|
||||
|
||||
// Check if we have a cached FBO with matching dimensions
|
||||
for (auto it = window->mFrameBuffers.begin(); it != window->mFrameBuffers.end(); ++it) {
|
||||
if (it->width == aWidth && it->height == aHeight) {
|
||||
fboId = it->fboId;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If not, create a new FBO with attached depth buffer
|
||||
if (fboId == 0) {
|
||||
// Create the depth buffer
|
||||
GLuint depthRboId;
|
||||
glGenRenderbuffers(1, &depthRboId);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, depthRboId);
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24,
|
||||
aWidth, aHeight);
|
||||
|
||||
// Create the framebuffer and attach the depth buffer to it
|
||||
glGenFramebuffers(1, &fboId);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboId);
|
||||
glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER,
|
||||
GL_DEPTH_ATTACHMENT,
|
||||
GL_RENDERBUFFER, depthRboId);
|
||||
|
||||
// Store this in the cache for future calls.
|
||||
CachedFrameBuffer frame_buffer_info;
|
||||
frame_buffer_info.width = aWidth;
|
||||
frame_buffer_info.height = aHeight;
|
||||
frame_buffer_info.fboId = fboId;
|
||||
frame_buffer_info.depthRboId = depthRboId;
|
||||
window->mFrameBuffers.push_back(frame_buffer_info);
|
||||
}
|
||||
|
||||
return fboId;
|
||||
}
|
||||
|
||||
static LRESULT CALLBACK WndProc(
|
||||
HWND hwnd,
|
||||
UINT message,
|
||||
|
@ -86,6 +139,7 @@ extern "C" {
|
|||
window->width = width;
|
||||
window->height = height;
|
||||
window->enable_compositor = enable_compositor;
|
||||
window->mEGLImage = EGL_NO_IMAGE;
|
||||
|
||||
WNDCLASSEX wcex = { sizeof(WNDCLASSEX) };
|
||||
wcex.style = CS_HREDRAW | CS_VREDRAW;
|
||||
|
@ -284,7 +338,7 @@ extern "C" {
|
|||
delete window;
|
||||
}
|
||||
|
||||
bool com_dc_tick(Window *window) {
|
||||
bool com_dc_tick(Window *) {
|
||||
// Check and dispatch the windows event loop
|
||||
MSG msg;
|
||||
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
|
||||
|
@ -356,7 +410,7 @@ extern "C" {
|
|||
}
|
||||
|
||||
// Bind a DC surface to allow issuing GL commands to it
|
||||
void com_dc_bind_surface(
|
||||
GLuint com_dc_bind_surface(
|
||||
Window *window,
|
||||
uint64_t id,
|
||||
int *x_offset,
|
||||
|
@ -395,35 +449,44 @@ extern "C" {
|
|||
offset.y -= dirty_y0;
|
||||
assert(SUCCEEDED(hr));
|
||||
pTexture->GetDesc(&desc);
|
||||
|
||||
// Construct an EGL off-screen surface that is bound to the DC surface
|
||||
EGLint buffer_attribs[] = {
|
||||
EGL_WIDTH, desc.Width,
|
||||
EGL_HEIGHT, desc.Height,
|
||||
EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE, EGL_TRUE,
|
||||
EGL_NONE
|
||||
};
|
||||
|
||||
window->current_surface = eglCreatePbufferFromClientBuffer(
|
||||
window->EGLDisplay,
|
||||
EGL_D3D_TEXTURE_ANGLE,
|
||||
pTexture,
|
||||
window->config,
|
||||
buffer_attribs
|
||||
);
|
||||
assert(window->current_surface != EGL_NO_SURFACE);
|
||||
|
||||
// Make EGL current on the DC surface
|
||||
EGLBoolean ok = eglMakeCurrent(
|
||||
window->EGLDisplay,
|
||||
window->current_surface,
|
||||
window->current_surface,
|
||||
window->EGLContext
|
||||
);
|
||||
assert(ok);
|
||||
|
||||
*x_offset = offset.x;
|
||||
*y_offset = offset.y;
|
||||
|
||||
// Construct an EGLImage wrapper around the D3D texture for ANGLE.
|
||||
const EGLAttrib attribs[] = { EGL_NONE };
|
||||
window->mEGLImage = eglCreateImage(
|
||||
window->EGLDisplay,
|
||||
EGL_NO_CONTEXT,
|
||||
EGL_D3D11_TEXTURE_ANGLE,
|
||||
static_cast<EGLClientBuffer>(pTexture),
|
||||
attribs
|
||||
);
|
||||
|
||||
// Get the current FBO and RBO id, so we can restore them later
|
||||
GLint currentFboId, currentRboId;
|
||||
glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, ¤tFboId);
|
||||
glGetIntegerv(GL_RENDERBUFFER_BINDING, ¤tRboId);
|
||||
|
||||
// Create a render buffer object that is backed by the EGL image.
|
||||
glGenRenderbuffers(1, &window->mColorRBO);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, window->mColorRBO);
|
||||
glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, window->mEGLImage);
|
||||
|
||||
// Get or create an FBO for the specified dimensions
|
||||
GLuint fboId = GetOrCreateFbo(window, desc.Width, desc.Height);
|
||||
|
||||
// Attach the new renderbuffer to the FBO
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboId);
|
||||
glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER,
|
||||
GL_COLOR_ATTACHMENT0,
|
||||
GL_RENDERBUFFER,
|
||||
window->mColorRBO);
|
||||
|
||||
// Restore previous FBO and RBO bindings
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, currentFboId);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, currentRboId);
|
||||
|
||||
return fboId;
|
||||
}
|
||||
|
||||
// Unbind a currently bound DC surface
|
||||
|
@ -431,7 +494,11 @@ extern "C" {
|
|||
HRESULT hr = window->pCurrentSurface->EndDraw();
|
||||
assert(SUCCEEDED(hr));
|
||||
|
||||
eglDestroySurface(window->EGLDisplay, window->current_surface);
|
||||
glDeleteRenderbuffers(1, &window->mColorRBO);
|
||||
window->mColorRBO = 0;
|
||||
|
||||
eglDestroyImage(window->EGLDisplay, window->mEGLImage);
|
||||
window->mEGLImage = EGL_NO_IMAGE;
|
||||
}
|
||||
|
||||
// At the start of a transaction, remove all visuals from the tree.
|
||||
|
@ -467,8 +534,8 @@ extern "C" {
|
|||
|
||||
// Place the visual - this changes frame to frame based on scroll position
|
||||
// of the slice.
|
||||
int offset_x = x + window->client_rect.left;
|
||||
int offset_y = y + window->client_rect.top;
|
||||
float offset_x = (float) (x + window->client_rect.left);
|
||||
float offset_y = (float) (y + window->client_rect.top);
|
||||
tile.pVisual->SetOffsetX(offset_x);
|
||||
tile.pVisual->SetOffsetY(offset_y);
|
||||
|
||||
|
|
|
@ -50,7 +50,7 @@ extern {
|
|||
dirty_y0: i32,
|
||||
dirty_width: i32,
|
||||
dirty_height: i32,
|
||||
);
|
||||
) -> u32;
|
||||
fn com_dc_unbind_surface(window: *mut Window);
|
||||
|
||||
fn com_dc_begin_transaction(window: *mut Window);
|
||||
|
@ -130,12 +130,12 @@ pub fn bind_surface(
|
|||
dirty_y0: i32,
|
||||
dirty_width: i32,
|
||||
dirty_height: i32,
|
||||
) -> (i32, i32) {
|
||||
) -> (u32, i32, i32) {
|
||||
unsafe {
|
||||
let mut x_offset = 0;
|
||||
let mut y_offset = 0;
|
||||
|
||||
com_dc_bind_surface(
|
||||
let fbo_id = com_dc_bind_surface(
|
||||
window,
|
||||
id,
|
||||
&mut x_offset,
|
||||
|
@ -146,7 +146,7 @@ pub fn bind_surface(
|
|||
dirty_height,
|
||||
);
|
||||
|
||||
(x_offset, y_offset)
|
||||
(fbo_id, x_offset, y_offset)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -65,7 +65,7 @@ impl webrender::Compositor for DirectCompositeInterface {
|
|||
id: webrender::NativeSurfaceId,
|
||||
dirty_rect: DeviceIntRect,
|
||||
) -> webrender::NativeSurfaceInfo {
|
||||
let (x, y) = compositor::bind_surface(
|
||||
let (fbo_id, x, y) = compositor::bind_surface(
|
||||
self.window,
|
||||
id.0,
|
||||
dirty_rect.origin.x,
|
||||
|
@ -76,7 +76,7 @@ impl webrender::Compositor for DirectCompositeInterface {
|
|||
|
||||
webrender::NativeSurfaceInfo {
|
||||
origin: DeviceIntPoint::new(x, y),
|
||||
fbo_id: 0,
|
||||
fbo_id,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -116,7 +116,13 @@ class BinASTSourceMetadata {
|
|||
public:
|
||||
BinASTSourceMetadata() = delete;
|
||||
explicit BinASTSourceMetadata(Type type) : type_(type) {}
|
||||
#ifdef JS_BUILD_BINAST
|
||||
~BinASTSourceMetadata();
|
||||
#else
|
||||
// If JS_BUILD_BINAST isn't defined, BinASTRuntimeSupport.cpp isn't built,
|
||||
// but still the destructor is referred from ScriptSource::BinAST.
|
||||
~BinASTSourceMetadata() {}
|
||||
#endif // JS_BUILD_BINAST
|
||||
|
||||
Type type() const { return type_; }
|
||||
|
||||
|
|
|
@ -10981,7 +10981,7 @@ int main(int argc, char** argv, char** envp) {
|
|||
"Format of BinAST file (multipart/context)") ||
|
||||
#else
|
||||
!op.addMultiStringOption('B', "binast", "", "No-op") ||
|
||||
!op.addStringOption('\0', "binast-format", "No-op") ||
|
||||
!op.addStringOption('\0', "binast-format", "[format]", "No-op") ||
|
||||
#endif // JS_BUILD_BINAST
|
||||
!op.addMultiStringOption('e', "execute", "CODE", "Inline code to run") ||
|
||||
!op.addBoolOption('i', "shell", "Enter prompt after running code") ||
|
||||
|
|
|
@ -4151,6 +4151,12 @@
|
|||
value: false
|
||||
mirror: always
|
||||
|
||||
# Whether we allow advanced layers with fission
|
||||
- name: layers.advanced.fission.enabled
|
||||
type: bool
|
||||
value: false
|
||||
mirror: always
|
||||
|
||||
# Whether we allow AMD switchable graphics.
|
||||
- name: layers.amd-switchable-gfx.enabled
|
||||
type: bool
|
||||
|
|
|
@ -450,6 +450,16 @@ void nsHtml5TreeOpExecutor::RunFlushLoop() {
|
|||
// Now parse content left in the document.write() buffer queue if any.
|
||||
// This may generate tree ops on its own or dequeue a speculation.
|
||||
nsresult rv = GetParser()->ParseUntilBlocked();
|
||||
|
||||
// ParseUntilBlocked flushes operations from the stage to the OpQueue.
|
||||
// Those operations may have accompanying speculative operations.
|
||||
// If so, we have to flush those speculative loads so that we maintain
|
||||
// the invariant that no speculative load starts after the corresponding
|
||||
// normal load for the same URL. See
|
||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=1513292#c80
|
||||
// for a more detailed explanation of why this is necessary.
|
||||
FlushSpeculativeLoads();
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
MarkAsBroken(rv);
|
||||
return;
|
||||
|
|
|
@ -874,7 +874,7 @@ FxAccountsInternal.prototype = {
|
|||
_telemetry: null,
|
||||
get telemetry() {
|
||||
if (!this._telemetry) {
|
||||
this._telemetry = new FxAccountsTelemetry();
|
||||
this._telemetry = new FxAccountsTelemetry(this);
|
||||
}
|
||||
return this._telemetry;
|
||||
},
|
||||
|
|
|
@ -9,13 +9,25 @@
|
|||
// sanely shared (eg, services-common?), but let's wait and see where we end up
|
||||
// first...
|
||||
|
||||
// We use this observers module because we leverage its support for richer
|
||||
// "subject" data.
|
||||
const { Observers } = ChromeUtils.import(
|
||||
"resource://services-common/observers.js"
|
||||
const { XPCOMUtils } = ChromeUtils.import(
|
||||
"resource://gre/modules/XPCOMUtils.jsm"
|
||||
);
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetters(this, {
|
||||
log: "resource://gre/modules/FxAccountsCommon.js",
|
||||
// We use this observers module because we leverage its support for richer
|
||||
// "subject" data.
|
||||
Observers: "resource://services-common/observers.js",
|
||||
Services: "resource://gre/modules/Services.jsm",
|
||||
});
|
||||
|
||||
class FxAccountsTelemetry {
|
||||
constructor(fxai) {
|
||||
this._fxai = fxai;
|
||||
Services.telemetry.setEventRecordingEnabled("fxa", true);
|
||||
}
|
||||
|
||||
// Records an event *in the Fxa/Sync ping*.
|
||||
recordEvent(object, method, value, extra = undefined) {
|
||||
// We need to ensure the telemetry module is loaded.
|
||||
ChromeUtils.import("resource://services-sync/telemetry.js");
|
||||
|
@ -50,6 +62,81 @@ class FxAccountsTelemetry {
|
|||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// Record the connection of FxA or one of its services.
|
||||
// Note that you must call this before performing the actual connection
|
||||
// or we may record incorrect data - for example, we will not be able to
|
||||
// determine whether FxA itself was connected before this call.
|
||||
//
|
||||
// Currently sends an event in the main telemetry event ping rather than the
|
||||
// FxA/Sync ping (although this might change in the future)
|
||||
//
|
||||
// @param services - An array of service names which should be recorded. FxA
|
||||
// itself is not counted as a "service" - ie, an empty array should be passed
|
||||
// if the account is connected without anything else .
|
||||
//
|
||||
// @param how - How the connection was done.
|
||||
async recordConnection(services, how = null) {
|
||||
try {
|
||||
let extra = {};
|
||||
// Record that fxa was connected if it isn't currently - it will be soon.
|
||||
if (!(await this._fxai.getUserAccountData())) {
|
||||
extra.fxa = "true";
|
||||
}
|
||||
// Events.yaml only declares "sync" as a valid service.
|
||||
if (services.includes("sync")) {
|
||||
extra.sync = "true";
|
||||
}
|
||||
Services.telemetry.recordEvent("fxa", "connect", "account", how, extra);
|
||||
} catch (ex) {
|
||||
log.error("Failed to record connection telemetry", ex);
|
||||
console.error("Failed to record connection telemetry", ex);
|
||||
}
|
||||
}
|
||||
|
||||
// Record the disconnection of FxA or one of its services.
|
||||
// Note that you must call this before performing the actual disconnection
|
||||
// or we may record incomplete data - for example, if this is called after
|
||||
// disconnection, we've almost certainly lost the ability to record what
|
||||
// services were enabled prior to disconnection.
|
||||
//
|
||||
// Currently sends an event in the main telemetry event ping rather than the
|
||||
// FxA/Sync ping (although this might change in the future)
|
||||
//
|
||||
// @param service - the service being disconnected. If null, the account
|
||||
// itself is being disconnected, so all connected services are too.
|
||||
//
|
||||
// @param how - how the disconnection was done.
|
||||
async recordDisconnection(service = null, how = null) {
|
||||
try {
|
||||
let extra = {};
|
||||
if (!service) {
|
||||
extra.fxa = "true";
|
||||
// We need a way to enumerate all services - but for now we just hard-code
|
||||
// all possibilities here.
|
||||
if (Services.prefs.prefHasUserValue("services.sync.username")) {
|
||||
extra.sync = "true";
|
||||
}
|
||||
} else if (service == "sync") {
|
||||
extra[service] = "true";
|
||||
} else {
|
||||
// Events.yaml only declares "sync" as a valid service.
|
||||
log.warn(
|
||||
`recordDisconnection has invalid value for service: ${service}`
|
||||
);
|
||||
}
|
||||
Services.telemetry.recordEvent(
|
||||
"fxa",
|
||||
"disconnect",
|
||||
"account",
|
||||
how,
|
||||
extra
|
||||
);
|
||||
} catch (ex) {
|
||||
log.error("Failed to record disconnection telemetry", ex);
|
||||
console.error("Failed to record disconnection telemetry", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var EXPORTED_SYMBOLS = ["FxAccountsTelemetry"];
|
||||
|
|
|
@ -434,6 +434,11 @@ this.FxAccountsWebChannelHelpers.prototype = {
|
|||
// Remember who it was so we can log out next time.
|
||||
this.setPreviousAccountNameHashPref(accountData.email);
|
||||
|
||||
await this._fxAccounts.telemetry.recordConnection(
|
||||
Object.keys(requestedServices || {}),
|
||||
"webchannel"
|
||||
);
|
||||
|
||||
// A sync-specific hack - we want to ensure sync has been initialized
|
||||
// before we set the signed-in user.
|
||||
// XXX - probably not true any more, especially now we have observerPreloads
|
||||
|
@ -479,17 +484,15 @@ this.FxAccountsWebChannelHelpers.prototype = {
|
|||
*
|
||||
* @param the uid of the account which have been logged out
|
||||
*/
|
||||
logout(uid) {
|
||||
return this._fxAccounts._internal
|
||||
.getUserAccountData(["uid"])
|
||||
.then(userData => {
|
||||
if (userData && userData.uid === uid) {
|
||||
// true argument is `localOnly`, because server-side stuff
|
||||
// has already been taken care of by the content server
|
||||
return fxAccounts.signOut(true);
|
||||
}
|
||||
return null;
|
||||
});
|
||||
async logout(uid) {
|
||||
let fxa = this._fxAccounts;
|
||||
let userData = await fxa._internal.getUserAccountData(["uid"]);
|
||||
if (userData && userData.uid === uid) {
|
||||
await fxa.telemetry.recordDisconnection(null, "webchannel");
|
||||
// true argument is `localOnly`, because server-side stuff
|
||||
// has already been taken care of by the content server
|
||||
await fxa.signOut(true);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
|
@ -396,6 +396,9 @@ add_task(async function test_helpers_login_without_customize_sync() {
|
|||
});
|
||||
},
|
||||
},
|
||||
telemetry: {
|
||||
recordConnection: sinon.spy(),
|
||||
},
|
||||
},
|
||||
weaveXPCOM: {
|
||||
whenLoaded() {},
|
||||
|
@ -415,6 +418,9 @@ add_task(async function test_helpers_login_without_customize_sync() {
|
|||
verifiedCanLinkAccount: true,
|
||||
customizeSync: false,
|
||||
});
|
||||
Assert.ok(
|
||||
helpers._fxAccounts.telemetry.recordConnection.calledWith([], "webchannel")
|
||||
);
|
||||
});
|
||||
|
||||
add_task(async function test_helpers_login_with_customize_sync() {
|
||||
|
@ -433,6 +439,9 @@ add_task(async function test_helpers_login_with_customize_sync() {
|
|||
});
|
||||
},
|
||||
},
|
||||
telemetry: {
|
||||
recordConnection: sinon.spy(),
|
||||
},
|
||||
},
|
||||
weaveXPCOM: {
|
||||
whenLoaded() {},
|
||||
|
@ -449,6 +458,9 @@ add_task(async function test_helpers_login_with_customize_sync() {
|
|||
verifiedCanLinkAccount: true,
|
||||
customizeSync: true,
|
||||
});
|
||||
Assert.ok(
|
||||
helpers._fxAccounts.telemetry.recordConnection.calledWith([], "webchannel")
|
||||
);
|
||||
});
|
||||
|
||||
add_task(
|
||||
|
@ -469,6 +481,9 @@ add_task(
|
|||
});
|
||||
},
|
||||
},
|
||||
telemetry: {
|
||||
recordConnection: sinon.spy(),
|
||||
},
|
||||
},
|
||||
weaveXPCOM: {
|
||||
whenLoaded() {},
|
||||
|
@ -542,6 +557,12 @@ add_task(
|
|||
);
|
||||
Assert.equal(Services.prefs.getBoolPref("services.sync.engine.tabs"), true);
|
||||
Assert.ok(configured, "sync was configured");
|
||||
Assert.ok(
|
||||
helpers._fxAccounts.telemetry.recordConnection.calledWith(
|
||||
["sync"],
|
||||
"webchannel"
|
||||
)
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -556,6 +577,9 @@ add_task(async function test_helpers_login_with_offered_sync_engines() {
|
|||
resolve(accountData);
|
||||
},
|
||||
},
|
||||
telemetry: {
|
||||
recordConnection() {},
|
||||
},
|
||||
},
|
||||
weaveXPCOM: {
|
||||
whenLoaded() {},
|
||||
|
@ -610,6 +634,9 @@ add_task(async function test_helpers_login_nothing_offered() {
|
|||
resolve(accountData);
|
||||
},
|
||||
},
|
||||
telemetry: {
|
||||
recordConnection() {},
|
||||
},
|
||||
},
|
||||
weaveXPCOM: {
|
||||
whenLoaded() {},
|
||||
|
|
|
@ -76,11 +76,12 @@ test_valid_value("grid-row", "2 i / auto", "2 i");
|
|||
test_valid_value("grid-row", "1 / auto", "1");
|
||||
test_valid_value("grid-column", "2 j / span 3 k");
|
||||
|
||||
|
||||
// https://github.com/w3c/csswg-drafts/issues/2858
|
||||
// '\\31 st' in Blink, Firefox, '1st' in Edge, '"1st"' in Safari.
|
||||
test_valid_value("grid-column-end", "\\31st", ["\\31 st", "1st", '"1st"']);
|
||||
test_valid_value("grid-column-end", "\\31 st", ["\\31 st", "1st", '"1st"']);
|
||||
// '\\31 st' in Blink, Firefox, EdgeHTML and Safari serialize invalid values.
|
||||
test_valid_value("grid-column-end", "\\31st", ["\\31 st", "\\31st"]);
|
||||
test_valid_value("grid-column-end", "\\31 st", ["\\31 st", "\\31st"]);
|
||||
test_valid_value("grid-column", "\\31st / \\31 st", ["\\31 st", "\\31st"]);
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -656,6 +656,26 @@ pwmgr:
|
|||
release_channel_collection: opt-out
|
||||
expiry_version: never
|
||||
|
||||
fxa:
|
||||
connect:
|
||||
objects: ["account"]
|
||||
methods: ["connect", "disconnect"]
|
||||
description: >
|
||||
Records when a Firefox Account, or a Firefox Account service, is explicitly
|
||||
connected or disconnected from the browser via an intentional user action.
|
||||
extra_keys:
|
||||
fxa: Whether the account itself was connected or disconnected.
|
||||
sync: Whether sync was connected or disconnected.
|
||||
products:
|
||||
- "firefox"
|
||||
- "fennec"
|
||||
- "geckoview"
|
||||
record_in_processes: ["main"]
|
||||
bug_numbers: [1595954]
|
||||
notification_emails: ["sync-dev@mozilla.org"]
|
||||
release_channel_collection: opt-out
|
||||
expiry_version: never
|
||||
|
||||
fxa_avatar_menu:
|
||||
click:
|
||||
objects: [
|
||||
|
|
|
@ -54,6 +54,7 @@
|
|||
#include "mozilla/StaticPrefs_apz.h"
|
||||
#include "mozilla/StaticPrefs_dom.h"
|
||||
#include "mozilla/StaticPrefs_layout.h"
|
||||
#include "mozilla/StaticPrefs_layers.h"
|
||||
#include "mozilla/Unused.h"
|
||||
#include "mozilla/IMEStateManager.h"
|
||||
#include "mozilla/VsyncDispatcher.h"
|
||||
|
@ -72,7 +73,6 @@
|
|||
#include "mozilla/gfx/gfxVars.h"
|
||||
#include "mozilla/Move.h"
|
||||
#include "mozilla/Sprintf.h"
|
||||
#include "mozilla/StaticPrefs_layout.h"
|
||||
#include "mozilla/webrender/WebRenderTypes.h"
|
||||
#include "nsRefPtrHashtable.h"
|
||||
#include "TouchEvents.h"
|
||||
|
@ -172,6 +172,7 @@ nsBaseWidget::nsBaseWidget()
|
|||
mPopupLevel(ePopupLevelTop),
|
||||
mPopupType(ePopupTypeAny),
|
||||
mHasRemoteContent(false),
|
||||
mFissionWindow(false),
|
||||
mUpdateCursor(true),
|
||||
mUseAttachedEvents(false),
|
||||
mIMEHasFocus(false),
|
||||
|
@ -391,6 +392,7 @@ void nsBaseWidget::BaseCreate(nsIWidget* aParent, nsWidgetInitData* aInitData) {
|
|||
mPopupLevel = aInitData->mPopupLevel;
|
||||
mPopupType = aInitData->mPopupHint;
|
||||
mHasRemoteContent = aInitData->mHasRemoteContent;
|
||||
mFissionWindow = aInitData->mFissionWindow;
|
||||
}
|
||||
|
||||
if (aParent) {
|
||||
|
@ -1213,7 +1215,11 @@ already_AddRefed<LayerManager> nsBaseWidget::CreateCompositorSession(
|
|||
bool enableAPZ = UseAPZ();
|
||||
CompositorOptions options(enableAPZ, enableWR);
|
||||
|
||||
bool enableAL = gfx::gfxConfig::IsEnabled(gfx::Feature::ADVANCED_LAYERS);
|
||||
// Bug 1588484 - Advanced Layers is currently disabled for fission windows,
|
||||
// since it doesn't properly support nested RefLayers.
|
||||
bool enableAL =
|
||||
gfx::gfxConfig::IsEnabled(gfx::Feature::ADVANCED_LAYERS) &&
|
||||
(!mFissionWindow || StaticPrefs::layers_advanced_fission_enabled());
|
||||
options.SetUseAdvancedLayers(enableAL);
|
||||
|
||||
#ifdef MOZ_WIDGET_ANDROID
|
||||
|
|
|
@ -691,6 +691,7 @@ class nsBaseWidget : public nsIWidget, public nsSupportsWeakReference {
|
|||
nsPopupType mPopupType;
|
||||
SizeConstraints mSizeConstraints;
|
||||
bool mHasRemoteContent;
|
||||
bool mFissionWindow;
|
||||
|
||||
bool mUpdateCursor;
|
||||
bool mUseAttachedEvents;
|
||||
|
|
|
@ -112,7 +112,8 @@ struct nsWidgetInitData {
|
|||
mMouseTransparent(false),
|
||||
mHasRemoteContent(false),
|
||||
mAlwaysOnTop(false),
|
||||
mPIPWindow(false) {}
|
||||
mPIPWindow(false),
|
||||
mFissionWindow(false) {}
|
||||
|
||||
nsWindowType mWindowType;
|
||||
nsBorderStyle mBorderStyle;
|
||||
|
@ -140,6 +141,8 @@ struct nsWidgetInitData {
|
|||
bool mAlwaysOnTop;
|
||||
// Is PictureInPicture window
|
||||
bool mPIPWindow;
|
||||
// True if fission is enabled for this window
|
||||
bool mFissionWindow;
|
||||
};
|
||||
|
||||
#endif // nsWidgetInitData_h__
|
||||
|
|
|
@ -593,6 +593,9 @@ nsresult nsAppShellService::JustCreateTopWindow(
|
|||
if (aChromeMask & nsIWebBrowserChrome::CHROME_ALWAYS_ON_TOP)
|
||||
widgetInitData.mAlwaysOnTop = true;
|
||||
|
||||
if (aChromeMask & nsIWebBrowserChrome::CHROME_FISSION_WINDOW)
|
||||
widgetInitData.mFissionWindow = true;
|
||||
|
||||
#ifdef MOZ_WIDGET_GTK
|
||||
// Linux/Gtk PIP window support. It's Chrome Toplevel window, always on top
|
||||
// and without any bar.
|
||||
|
|
Загрузка…
Ссылка в новой задаче