mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge m-c to inbound, a=merge
This commit is contained in:
commit
691cc3853f
@ -249,6 +249,7 @@ EXTRA_JS_MODULES.commonjs.sdk.content += [
|
||||
'source/lib/sdk/content/loader.js',
|
||||
'source/lib/sdk/content/mod.js',
|
||||
'source/lib/sdk/content/page-mod.js',
|
||||
'source/lib/sdk/content/page-worker.js',
|
||||
'source/lib/sdk/content/sandbox.js',
|
||||
'source/lib/sdk/content/tab-events.js',
|
||||
'source/lib/sdk/content/thumbnail.js',
|
||||
|
@ -11,6 +11,7 @@ const { Ci } = require("chrome");
|
||||
const core = require("../l10n/core");
|
||||
const { loadSheet, removeSheet } = require("../stylesheet/utils");
|
||||
const { process, frames } = require("../remote/child");
|
||||
const { Services } = require("resource://gre/modules/Services.jsm");
|
||||
|
||||
const assetsURI = require('../self').data.url();
|
||||
|
||||
@ -80,7 +81,7 @@ function onDocumentReady2Translate(event) {
|
||||
}
|
||||
}
|
||||
|
||||
function onContentWindow({ target: document }) {
|
||||
function onContentWindow(document) {
|
||||
// Accept only HTML documents
|
||||
if (!(document instanceof Ci.nsIDOMHTMLDocument))
|
||||
return;
|
||||
@ -109,13 +110,20 @@ function onContentWindow({ target: document }) {
|
||||
|
||||
// Listen to creation of content documents in order to translate them as soon
|
||||
// as possible in their loading process
|
||||
const ON_CONTENT = "DOMDocElementInserted";
|
||||
const ON_CONTENT = "document-element-inserted";
|
||||
let enabled = false;
|
||||
function enable() {
|
||||
frames.addEventListener(ON_CONTENT, onContentWindow, true);
|
||||
if (enabled)
|
||||
return;
|
||||
Services.obs.addObserver(onContentWindow, ON_CONTENT, false);
|
||||
enabled = true;
|
||||
}
|
||||
process.port.on("sdk/l10n/html/enable", enable);
|
||||
|
||||
function disable() {
|
||||
frames.removeEventListener(ON_CONTENT, onContentWindow, true);
|
||||
if (!enabled)
|
||||
return;
|
||||
Services.obs.removeObserver(onContentWindow, ON_CONTENT);
|
||||
enabled = false;
|
||||
}
|
||||
process.port.on("sdk/l10n/html/disable", disable);
|
||||
|
153
addon-sdk/source/lib/sdk/content/page-worker.js
Normal file
153
addon-sdk/source/lib/sdk/content/page-worker.js
Normal file
@ -0,0 +1,153 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
"use strict";
|
||||
|
||||
const { frames } = require("../remote/child");
|
||||
const { Class } = require("../core/heritage");
|
||||
const { Disposable } = require('../core/disposable');
|
||||
const { data } = require("../self");
|
||||
const { once } = require("../dom/events");
|
||||
const { getAttachEventType } = require("./utils");
|
||||
const { Rules } = require('../util/rules');
|
||||
const { uuid } = require('../util/uuid');
|
||||
const { WorkerChild } = require("./worker-child");
|
||||
const { Cc, Ci, Cu } = require("chrome");
|
||||
const { observe } = require("../event/chrome");
|
||||
const { on } = require("../event/core");
|
||||
|
||||
const appShell = Cc["@mozilla.org/appshell/appShellService;1"].getService(Ci.nsIAppShellService);
|
||||
|
||||
const { XPCOMUtils } = require("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
const pages = new Map();
|
||||
|
||||
const DOC_INSERTED = "document-element-inserted";
|
||||
|
||||
function isValidURL(page, url) {
|
||||
return !page.rules || page.rules.matchesAny(url);
|
||||
}
|
||||
|
||||
const ChildPage = Class({
|
||||
implements: [ Disposable ],
|
||||
setup: function(frame, id, options) {
|
||||
this.id = id;
|
||||
this.frame = frame;
|
||||
this.options = options;
|
||||
|
||||
this.webNav = appShell.createWindowlessBrowser(false);
|
||||
this.docShell.allowJavascript = this.options.allow.script;
|
||||
|
||||
// Accessing the browser's window forces the initial about:blank document to
|
||||
// be created before we start listening for notifications
|
||||
this.contentWindow;
|
||||
|
||||
this.webProgress.addProgressListener(this, Ci.nsIWebProgress.NOTIFY_LOCATION);
|
||||
|
||||
pages.set(this.id, this);
|
||||
|
||||
this.contentURL = options.contentURL;
|
||||
|
||||
if (options.include) {
|
||||
this.rules = Rules();
|
||||
this.rules.add.apply(this.rules, [].concat(options.include));
|
||||
}
|
||||
},
|
||||
|
||||
dispose: function() {
|
||||
pages.delete(this.id);
|
||||
this.webProgress.removeProgressListener(this);
|
||||
this.webNav = null;
|
||||
},
|
||||
|
||||
attachWorker: function() {
|
||||
if (!isValidURL(this, this.contentWindow.location.href))
|
||||
return;
|
||||
|
||||
this.options.id = uuid().toString();
|
||||
this.options.window = this.contentWindow;
|
||||
this.frame.port.emit("sdk/frame/connect", this.id, {
|
||||
id: this.options.id,
|
||||
url: this.contentWindow.document.documentURIObject.spec
|
||||
});
|
||||
new WorkerChild(this.options);
|
||||
},
|
||||
|
||||
get docShell() {
|
||||
return this.webNav.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDocShell);
|
||||
},
|
||||
|
||||
get webProgress() {
|
||||
return this.docShell.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebProgress);
|
||||
},
|
||||
|
||||
get contentWindow() {
|
||||
return this.docShell.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindow);
|
||||
},
|
||||
|
||||
get contentURL() {
|
||||
return this.options.contentURL;
|
||||
},
|
||||
set contentURL(url) {
|
||||
this.options.contentURL = url;
|
||||
|
||||
url = this.options.contentURL ? data.url(this.options.contentURL) : "about:blank";
|
||||
this.webNav.loadURI(url, Ci.nsIWebNavigation.LOAD_FLAGS_NONE, null, null, null);
|
||||
},
|
||||
|
||||
onLocationChange: function(progress, request, location, flags) {
|
||||
// Ignore inner-frame events
|
||||
if (progress != this.webProgress)
|
||||
return;
|
||||
// Ignore events that don't change the document
|
||||
if (flags & Ci.nsIWebProgressListener.LOCATION_CHANGE_SAME_DOCUMENT)
|
||||
return;
|
||||
|
||||
let event = getAttachEventType(this.options);
|
||||
// Attaching at the start of the load is handled by the
|
||||
// document-element-inserted listener.
|
||||
if (event == DOC_INSERTED)
|
||||
return;
|
||||
|
||||
once(this.contentWindow, event, () => {
|
||||
this.attachWorker();
|
||||
}, false);
|
||||
},
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI(["nsIWebProgressListener", "nsISupportsWeakReference"])
|
||||
});
|
||||
|
||||
on(observe(DOC_INSERTED), "data", ({ target }) => {
|
||||
let page = Array.from(pages.values()).find(p => p.contentWindow.document === target);
|
||||
if (!page)
|
||||
return;
|
||||
|
||||
if (getAttachEventType(page.options) == DOC_INSERTED)
|
||||
page.attachWorker();
|
||||
});
|
||||
|
||||
frames.port.on("sdk/frame/create", (frame, id, options) => {
|
||||
new ChildPage(frame, id, options);
|
||||
});
|
||||
|
||||
frames.port.on("sdk/frame/set", (frame, id, params) => {
|
||||
let page = pages.get(id);
|
||||
if (!page)
|
||||
return;
|
||||
|
||||
if ("allowScript" in params)
|
||||
page.docShell.allowJavascript = params.allowScript;
|
||||
if ("contentURL" in params)
|
||||
page.contentURL = params.contentURL;
|
||||
});
|
||||
|
||||
frames.port.on("sdk/frame/destroy", (frame, id) => {
|
||||
let page = pages.get(id);
|
||||
if (!page)
|
||||
return;
|
||||
|
||||
page.destroy();
|
||||
});
|
@ -53,7 +53,7 @@ function isWindowInTab(window) {
|
||||
if (isChildLoader) {
|
||||
let { frames } = require('../remote/child');
|
||||
let frame = frames.getFrameForWindow(window.top);
|
||||
return frame.isTab;
|
||||
return frame && frame.isTab;
|
||||
}
|
||||
else {
|
||||
// The deprecated sync worker API still does everything in the main process
|
||||
|
@ -51,7 +51,9 @@ const WorkerChild = Class({
|
||||
|
||||
this.sandbox = WorkerSandbox(this, this.window);
|
||||
|
||||
this.frozen = false;
|
||||
// If the document is still loading wait for it to finish before passing on
|
||||
// received messages
|
||||
this.frozen = this.window.document.readyState == "loading";
|
||||
this.frozenMessages = [];
|
||||
this.on('pageshow', () => {
|
||||
this.frozen = false;
|
||||
|
@ -57,38 +57,31 @@ function create(target, options) {
|
||||
frame.setAttribute('type', options.type || 'content');
|
||||
frame.setAttribute('src', options.uri || 'about:blank');
|
||||
|
||||
// Must set the remote attribute before attaching the frame to the document
|
||||
if (remote && isXUL) {
|
||||
// We remove XBL binding to avoid execution of code that is not going to
|
||||
// work because browser has no docShell attribute in remote mode
|
||||
// (for example)
|
||||
frame.setAttribute('style', '-moz-binding: none;');
|
||||
frame.setAttribute('remote', 'true');
|
||||
}
|
||||
|
||||
target.appendChild(frame);
|
||||
|
||||
// Load in separate process if `options.remote` is `true`.
|
||||
// http://mxr.mozilla.org/mozilla-central/source/content/base/src/nsFrameLoader.cpp#1347
|
||||
if (remote) {
|
||||
if (isXUL) {
|
||||
// We remove XBL binding to avoid execution of code that is not going to
|
||||
// work because browser has no docShell attribute in remote mode
|
||||
// (for example)
|
||||
frame.setAttribute('style', '-moz-binding: none;');
|
||||
frame.setAttribute('remote', 'true');
|
||||
}
|
||||
else {
|
||||
frame.QueryInterface(Ci.nsIMozBrowserFrame);
|
||||
frame.createRemoteFrameLoader(null);
|
||||
}
|
||||
if (remote && !isXUL) {
|
||||
frame.QueryInterface(Ci.nsIMozBrowserFrame);
|
||||
frame.createRemoteFrameLoader(null);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// If browser is remote it won't have a `docShell`.
|
||||
if (!remote) {
|
||||
let docShell = getDocShell(frame);
|
||||
docShell.allowAuth = options.allowAuth || false;
|
||||
docShell.allowJavascript = options.allowJavascript || false;
|
||||
docShell.allowPlugins = options.allowPlugins || false;
|
||||
|
||||
// Control whether the document can move/resize the window. Requires
|
||||
// recently added platform capability, so we test to avoid exceptions
|
||||
// in cases where capability is not present yet.
|
||||
if ("allowWindowControl" in docShell && "allowWindowControl" in options)
|
||||
docShell.allowWindowControl = !!options.allowWindowControl;
|
||||
docShell.allowWindowControl = options.allowWindowControl || false;
|
||||
}
|
||||
|
||||
return frame;
|
||||
|
@ -8,48 +8,58 @@ module.metadata = {
|
||||
};
|
||||
|
||||
const { Class } = require('./core/heritage');
|
||||
const { on, emit, off, setListeners } = require('./event/core');
|
||||
const { filter, pipe, map, merge: streamMerge, stripListeners } = require('./event/utils');
|
||||
const { detach, attach, destroy, WorkerHost } = require('./content/utils');
|
||||
const { Worker } = require('./deprecated/sync-worker');
|
||||
const { ns } = require('./core/namespace');
|
||||
const { pipe, stripListeners } = require('./event/utils');
|
||||
const { connect, destroy, WorkerHost } = require('./content/utils');
|
||||
const { Worker } = require('./content/worker');
|
||||
const { Disposable } = require('./core/disposable');
|
||||
const { WeakReference } = require('./core/reference');
|
||||
const { EventTarget } = require('./event/target');
|
||||
const { unload } = require('./system/unload');
|
||||
const { events, streamEventsFrom } = require('./content/events');
|
||||
const { getAttachEventType } = require('./content/utils');
|
||||
const { setListeners } = require('./event/core');
|
||||
const { window } = require('./addon/window');
|
||||
const { getParentWindow } = require('./window/utils');
|
||||
const { create: makeFrame, getDocShell } = require('./frame/utils');
|
||||
const { contract } = require('./util/contract');
|
||||
const { contract: loaderContract } = require('./content/loader');
|
||||
const { has } = require('./util/array');
|
||||
const { Rules } = require('./util/rules');
|
||||
const { merge } = require('./util/object');
|
||||
const { data } = require('./self');
|
||||
const { getActiveView } = require("./view/core");
|
||||
const { uuid } = require('./util/uuid');
|
||||
const { useRemoteProcesses, remoteRequire, frames } = require("./remote/parent");
|
||||
remoteRequire("sdk/content/page-worker");
|
||||
|
||||
const views = new WeakMap();
|
||||
const workers = new WeakMap();
|
||||
const pages = new WeakMap();
|
||||
const pages = new Map();
|
||||
|
||||
const readyEventNames = [
|
||||
'DOMContentLoaded',
|
||||
'document-element-inserted',
|
||||
'load'
|
||||
];
|
||||
const internal = ns();
|
||||
|
||||
function workerFor(page) {
|
||||
return workers.get(page);
|
||||
}
|
||||
function pageFor(view) {
|
||||
return pages.get(view);
|
||||
}
|
||||
function viewFor(page) {
|
||||
return views.get(page);
|
||||
}
|
||||
function isDisposed (page) {
|
||||
return !views.get(page, false);
|
||||
let workerFor = (page) => workers.get(page);
|
||||
let isDisposed = (page) => !pages.has(internal(page).id);
|
||||
|
||||
// The frame is used to ensure we have a remote process to load workers in
|
||||
let remoteFrame = null;
|
||||
let framePromise = null;
|
||||
function getFrame() {
|
||||
if (framePromise)
|
||||
return framePromise;
|
||||
|
||||
framePromise = new Promise(resolve => {
|
||||
let view = makeFrame(window.document, {
|
||||
namespaceURI: "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul",
|
||||
nodeName: "iframe",
|
||||
type: "content",
|
||||
remote: useRemoteProcesses,
|
||||
uri: "about:blank"
|
||||
});
|
||||
|
||||
// Wait for the remote side to connect
|
||||
let listener = (frame) => {
|
||||
if (frame.frameElement != view)
|
||||
return;
|
||||
frames.off("attach", listener);
|
||||
remoteFrame = frame;
|
||||
resolve(frame);
|
||||
}
|
||||
frames.on("attach", listener);
|
||||
});
|
||||
return framePromise;
|
||||
}
|
||||
|
||||
var pageContract = contract(merge({
|
||||
@ -64,7 +74,8 @@ var pageContract = contract(merge({
|
||||
is: ['string', 'array', 'regexp', 'undefined']
|
||||
},
|
||||
contentScriptWhen: {
|
||||
is: ['string', 'undefined']
|
||||
is: ['string', 'undefined'],
|
||||
map: (when) => when || "end"
|
||||
}
|
||||
}, loaderContract.rules));
|
||||
|
||||
@ -78,16 +89,18 @@ function disableScript (page) {
|
||||
|
||||
function Allow (page) {
|
||||
return {
|
||||
get script() { return getDocShell(viewFor(page)).allowJavascript; },
|
||||
set script(value) { return value ? enableScript(page) : disableScript(page); }
|
||||
};
|
||||
}
|
||||
get script() {
|
||||
return internal(page).options.allow.script;
|
||||
},
|
||||
set script(value) {
|
||||
internal(page).options.allow.script = value;
|
||||
|
||||
function injectWorker ({page}) {
|
||||
let worker = workerFor(page);
|
||||
let view = viewFor(page);
|
||||
if (isValidURL(page, view.contentDocument.URL))
|
||||
attach(worker, view.contentWindow);
|
||||
if (isDisposed(page))
|
||||
return;
|
||||
|
||||
remoteFrame.port.emit("sdk/frame/set", internal(page).id, { allowScript: value });
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function isValidURL(page, url) {
|
||||
@ -97,31 +110,23 @@ function isValidURL(page, url) {
|
||||
const Page = Class({
|
||||
implements: [
|
||||
EventTarget,
|
||||
Disposable,
|
||||
WeakReference
|
||||
Disposable
|
||||
],
|
||||
extends: WorkerHost(workerFor),
|
||||
setup: function Page(options) {
|
||||
let page = this;
|
||||
options = pageContract(options);
|
||||
// Sanitize the options
|
||||
if ("contentScriptOptions" in options)
|
||||
options.contentScriptOptions = JSON.stringify(options.contentScriptOptions);
|
||||
|
||||
let uri = options.contentURL;
|
||||
internal(this).id = uuid().toString();
|
||||
internal(this).options = options;
|
||||
|
||||
let view = makeFrame(window.document, {
|
||||
nodeName: 'iframe',
|
||||
type: 'content',
|
||||
uri: uri ? data.url(uri) : '',
|
||||
allowJavascript: options.allow.script,
|
||||
allowPlugins: true,
|
||||
allowAuth: true
|
||||
});
|
||||
view.setAttribute('data-src', uri);
|
||||
for (let prop of ['contentScriptFile', 'contentScript', 'contentScriptWhen']) {
|
||||
this[prop] = options[prop];
|
||||
}
|
||||
|
||||
['contentScriptFile', 'contentScript', 'contentScriptWhen']
|
||||
.forEach(prop => page[prop] = options[prop]);
|
||||
|
||||
views.set(this, view);
|
||||
pages.set(view, this);
|
||||
pages.set(internal(this).id, this);
|
||||
|
||||
// Set listeners on the {Page} object itself, not the underlying worker,
|
||||
// like `onMessage`, as it gets piped
|
||||
@ -130,68 +135,60 @@ const Page = Class({
|
||||
workers.set(this, worker);
|
||||
pipe(worker, this);
|
||||
|
||||
if (this.include || options.include) {
|
||||
if (options.include) {
|
||||
this.rules = Rules();
|
||||
this.rules.add.apply(this.rules, [].concat(this.include || options.include));
|
||||
this.rules.add.apply(this.rules, [].concat(options.include));
|
||||
}
|
||||
|
||||
getFrame().then(frame => {
|
||||
if (isDisposed(this))
|
||||
return;
|
||||
|
||||
frame.port.emit("sdk/frame/create", internal(this).id, stripListeners(options));
|
||||
});
|
||||
},
|
||||
get allow() { return Allow(this); },
|
||||
set allow(value) {
|
||||
let allowJavascript = pageContract({ allow: value }).allow.script;
|
||||
return allowJavascript ? enableScript(this) : disableScript(this);
|
||||
if (isDisposed(this))
|
||||
return;
|
||||
this.allow.script = pageContract({ allow: value }).allow.script;
|
||||
},
|
||||
get contentURL() {
|
||||
return internal(this).options.contentURL;
|
||||
},
|
||||
get contentURL() { return viewFor(this).getAttribute("data-src") },
|
||||
set contentURL(value) {
|
||||
if (!isValidURL(this, value)) return;
|
||||
let view = viewFor(this);
|
||||
let contentURL = pageContract({ contentURL: value }).contentURL;
|
||||
if (!isValidURL(this, value))
|
||||
return;
|
||||
internal(this).options.contentURL = value;
|
||||
if (isDisposed(this))
|
||||
return;
|
||||
|
||||
// page-worker doesn't have a model like other APIs, so to be consitent
|
||||
// with the behavior "what you set is what you get", we need to store
|
||||
// the original `contentURL` given.
|
||||
// Even if XUL elements doesn't support `dataset`, properties, to
|
||||
// indicate that is a custom attribute the syntax "data-*" is used.
|
||||
view.setAttribute('data-src', contentURL);
|
||||
view.setAttribute('src', data.url(contentURL));
|
||||
remoteFrame.port.emit("sdk/frame/set", internal(this).id, { contentURL: value });
|
||||
},
|
||||
dispose: function () {
|
||||
if (isDisposed(this)) return;
|
||||
let view = viewFor(this);
|
||||
if (view.parentNode) view.parentNode.removeChild(view);
|
||||
views.delete(this);
|
||||
destroy(workers.get(this));
|
||||
if (isDisposed(this))
|
||||
return;
|
||||
pages.delete(internal(this).id);
|
||||
let worker = workerFor(this);
|
||||
if (worker)
|
||||
destroy(worker);
|
||||
remoteFrame.port.emit("sdk/frame/destroy", internal(this).id);
|
||||
|
||||
// Destroy the remote frame if all the pages have been destroyed
|
||||
if (pages.size == 0) {
|
||||
framePromise = null;
|
||||
remoteFrame.frameElement.remove();
|
||||
remoteFrame = null;
|
||||
}
|
||||
},
|
||||
toString: function () { return '[object Page]' }
|
||||
});
|
||||
|
||||
exports.Page = Page;
|
||||
|
||||
var pageEvents = streamMerge([events, streamEventsFrom(window)]);
|
||||
var readyEvents = filter(pageEvents, isReadyEvent);
|
||||
var formattedEvents = map(readyEvents, function({target, type}) {
|
||||
return { type: type, page: pageFromDoc(target) };
|
||||
frames.port.on("sdk/frame/connect", (frame, id, params) => {
|
||||
let page = pages.get(id);
|
||||
if (!page)
|
||||
return;
|
||||
connect(workerFor(page), frame, params);
|
||||
});
|
||||
var pageReadyEvents = filter(formattedEvents, function({page, type}) {
|
||||
return getAttachEventType(page) === type});
|
||||
on(pageReadyEvents, 'data', injectWorker);
|
||||
|
||||
function isReadyEvent ({type}) {
|
||||
return has(readyEventNames, type);
|
||||
}
|
||||
|
||||
/*
|
||||
* Takes a document, finds its doc shell tree root and returns the
|
||||
* matching Page instance if found
|
||||
*/
|
||||
function pageFromDoc(doc) {
|
||||
let parentWindow = getParentWindow(doc.defaultView), page;
|
||||
if (!parentWindow) return;
|
||||
|
||||
let frames = parentWindow.document.getElementsByTagName('iframe');
|
||||
for (let i = frames.length; i--;)
|
||||
if (frames[i].contentDocument === doc && (page = pageFor(frames[i])))
|
||||
return page;
|
||||
return null;
|
||||
}
|
||||
|
||||
getActiveView.define(Page, viewFor);
|
||||
|
@ -29,6 +29,11 @@ const options = require('@loader/options');
|
||||
const loaderModule = require('toolkit/loader');
|
||||
const { getTabForBrowser } = require('../tabs/utils');
|
||||
|
||||
const appInfo = Cc["@mozilla.org/xre/app-info;1"].
|
||||
getService(Ci.nsIXULRuntime);
|
||||
|
||||
exports.useRemoteProcesses = appInfo.browserTabsRemoteAutostart;
|
||||
|
||||
// Chose the right function for resolving relative a module id
|
||||
var moduleResolve;
|
||||
if (options.isNative) {
|
||||
@ -174,7 +179,10 @@ const Frame = Class({
|
||||
|
||||
this.port = new EventTarget();
|
||||
this.port.emit = (...args) => {
|
||||
ns(this).messageManager.sendAsyncMessage('sdk/remote/frame/message', {
|
||||
let manager = ns(this).messageManager;
|
||||
if (!manager)
|
||||
return;
|
||||
manager.sendAsyncMessage('sdk/remote/frame/message', {
|
||||
loaderID,
|
||||
args
|
||||
});
|
||||
|
@ -3,7 +3,7 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
'use strict'
|
||||
|
||||
const { Cc, Ci } = require('chrome');
|
||||
const { Cc, Ci, Cu } = require('chrome');
|
||||
const bmsrv = Cc['@mozilla.org/browser/nav-bookmarks-service;1'].
|
||||
getService(Ci.nsINavBookmarksService);
|
||||
const hsrv = Cc['@mozilla.org/browser/nav-history-service;1'].
|
||||
@ -26,6 +26,11 @@ const {
|
||||
MENU, TOOLBAR, UNSORTED
|
||||
} = require('sdk/places/bookmarks');
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
|
||||
"resource://gre/modules/PlacesUtils.jsm");
|
||||
|
||||
function invalidResolve (assert) {
|
||||
return function (e) {
|
||||
assert.fail('Resolve state should not be called: ' + e);
|
||||
@ -45,8 +50,7 @@ function clearAllBookmarks () {
|
||||
}
|
||||
|
||||
function clearHistory (done) {
|
||||
hsrv.removeAllPages();
|
||||
once('places-expiration-finished', done);
|
||||
PlacesUtils.history.clear().catch(Cu.reportError).then(done);
|
||||
}
|
||||
|
||||
// Cleans bookmarks and history and disables maintanance
|
||||
|
@ -63,107 +63,6 @@ exports["test changing result from addon extras in panel"] = function(assert, do
|
||||
panel.port.emit("get-result");
|
||||
}
|
||||
|
||||
exports["test window result from addon extras in panel"] = function*(assert) {
|
||||
let loader = Loader(module, null, null, {
|
||||
modules: {
|
||||
"sdk/self": merge({}, self, {
|
||||
data: merge({}, self.data, {url: fixtures.url})
|
||||
})
|
||||
}
|
||||
});
|
||||
|
||||
const { Panel } = loader.require('sdk/panel');
|
||||
const { Page } = loader.require('sdk/page-worker');
|
||||
const { getActiveView } = loader.require("sdk/view/core");
|
||||
const { getDocShell } = loader.require('sdk/frame/utils');
|
||||
const { events } = loader.require("sdk/content/sandbox/events");
|
||||
const { on } = loader.require("sdk/event/core");
|
||||
const { isAddonContent } = loader.require("sdk/content/utils");
|
||||
|
||||
// make a page worker and wait for it to load
|
||||
var page = yield new Promise(resolve => {
|
||||
assert.pass("Creating the background page");
|
||||
|
||||
let page = Page({
|
||||
contentURL: "./test.html",
|
||||
contentScriptWhen: "end",
|
||||
contentScript: "self.port.emit('end', unsafeWindow.getTestURL() + '')"
|
||||
});
|
||||
|
||||
page.port.once("end", (url) => {
|
||||
assert.equal(url, fixtures.url("./test.html"), "url is correct");
|
||||
resolve(page);
|
||||
});
|
||||
});
|
||||
assert.pass("Created the background page");
|
||||
|
||||
var extrasVal = {
|
||||
test: function() {
|
||||
assert.pass("start test function");
|
||||
let frame = getActiveView(page);
|
||||
let window = getUnsafeWindow(frame.contentWindow);
|
||||
assert.equal(typeof window.getTestURL, "function", "window.getTestURL is a function");
|
||||
return window;
|
||||
}
|
||||
};
|
||||
|
||||
on(events, "content-script-before-inserted", ({ window, worker }) => {
|
||||
let url = window.location.href;
|
||||
assert.pass("content-script-before-inserted " + url);
|
||||
|
||||
if (isAddonContent({ contentURL: url })) {
|
||||
let extraStuff = Cu.cloneInto(extrasVal, window, {
|
||||
cloneFunctions: true
|
||||
});
|
||||
getUnsafeWindow(window).extras = extraStuff;
|
||||
|
||||
assert.pass("content-script-before-inserted done!");
|
||||
}
|
||||
});
|
||||
|
||||
let panel = Panel({
|
||||
contentURL: "./test-addon-extras-window.html"
|
||||
});
|
||||
|
||||
|
||||
yield new Promise(resolve => {
|
||||
panel.port.once("result1", (result) => {
|
||||
assert.equal(result, fixtures.url("./test.html"), "result1 is a window");
|
||||
resolve();
|
||||
});
|
||||
|
||||
assert.pass("emit get-result");
|
||||
panel.port.emit("get-result");
|
||||
});
|
||||
|
||||
page.destroy();
|
||||
|
||||
|
||||
page = yield new Promise(resolve => {
|
||||
let page = Page({
|
||||
contentURL: "./index.html",
|
||||
contentScriptWhen: "end",
|
||||
contentScript: "self.port.emit('end')"
|
||||
});
|
||||
page.port.once("end", () => resolve(page));
|
||||
});
|
||||
|
||||
|
||||
yield new Promise(resolve => {
|
||||
panel.port.once("result2", (result) => {
|
||||
assert.equal(result, fixtures.url("./index.html"), "result2 is a window");
|
||||
resolve();
|
||||
});
|
||||
|
||||
assert.pass("emit get-result");
|
||||
panel.port.emit("get-result");
|
||||
});
|
||||
|
||||
loader.unload();
|
||||
}
|
||||
|
||||
|
||||
|
||||
function getUnsafeWindow (win) {
|
||||
return win.wrappedJSObject || win;
|
||||
}
|
||||
|
@ -327,19 +327,6 @@ exports.testAllowScript = function(assert, done) {
|
||||
" document.documentElement.getAttribute('foo') == 3)",
|
||||
contentScriptWhen: "ready"
|
||||
});
|
||||
|
||||
let frame = getActiveView(page);
|
||||
assert.equal(getDocShell(frame).allowJavascript, true, "allowJavascript is true");
|
||||
}
|
||||
|
||||
exports.testGetActiveViewAndDestroy = function(assert) {
|
||||
let page = Page({
|
||||
contentURL: "data:text/html;charset=utf-8,<title>test</title>"
|
||||
});
|
||||
let frame = getActiveView(page);
|
||||
assert.ok(frame.parentNode, "there is a parent node");
|
||||
page.destroy();
|
||||
assert.ok(!frame.parentNode, "there is not a parent node");
|
||||
}
|
||||
|
||||
exports.testPingPong = function(assert, done) {
|
||||
|
@ -24,7 +24,7 @@
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="valgrind" path="external/valgrind" remote="b2g" revision="5f931350fbc87c3df9db8b0ceb37734b8b471593"/>
|
||||
<project name="vex" path="external/VEX" remote="b2g" revision="48d8c7c950745f1b166b42125e6f0d3293d71636"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="95bc959ff0e4ce73e1c9ed5e6916d84922d0a3cc"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="21f7fdaf4ee341022a0416e9186e7b07218cc4b1"/>
|
||||
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
|
||||
<!-- Stock Android things -->
|
||||
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="95bb5b66b3ec5769c3de8d3f25d681787418e7d2"/>
|
||||
|
@ -24,7 +24,7 @@
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="valgrind" path="external/valgrind" remote="b2g" revision="5f931350fbc87c3df9db8b0ceb37734b8b471593"/>
|
||||
<project name="vex" path="external/VEX" remote="b2g" revision="48d8c7c950745f1b166b42125e6f0d3293d71636"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="95bc959ff0e4ce73e1c9ed5e6916d84922d0a3cc"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="21f7fdaf4ee341022a0416e9186e7b07218cc4b1"/>
|
||||
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
|
||||
<!-- Stock Android things -->
|
||||
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="95bb5b66b3ec5769c3de8d3f25d681787418e7d2"/>
|
||||
|
@ -20,7 +20,7 @@
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="91cac94948094cfdcd00cba5c6483e27e80cb3b0"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="956700d9754349b630a34551750ae6353614b6aa"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="27de93fe66c3e80e157d157bd52ca99565351669"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="95bc959ff0e4ce73e1c9ed5e6916d84922d0a3cc"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="21f7fdaf4ee341022a0416e9186e7b07218cc4b1"/>
|
||||
<project name="valgrind" path="external/valgrind" remote="b2g" revision="5f931350fbc87c3df9db8b0ceb37734b8b471593"/>
|
||||
<project name="vex" path="external/VEX" remote="b2g" revision="48d8c7c950745f1b166b42125e6f0d3293d71636"/>
|
||||
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
|
||||
|
@ -23,7 +23,7 @@
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="valgrind" path="external/valgrind" remote="b2g" revision="5f931350fbc87c3df9db8b0ceb37734b8b471593"/>
|
||||
<project name="vex" path="external/VEX" remote="b2g" revision="48d8c7c950745f1b166b42125e6f0d3293d71636"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="95bc959ff0e4ce73e1c9ed5e6916d84922d0a3cc"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="21f7fdaf4ee341022a0416e9186e7b07218cc4b1"/>
|
||||
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
|
||||
<!-- Stock Android things -->
|
||||
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="f92a936f2aa97526d4593386754bdbf02db07a12"/>
|
||||
|
@ -23,7 +23,7 @@
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="valgrind" path="external/valgrind" remote="b2g" revision="5f931350fbc87c3df9db8b0ceb37734b8b471593"/>
|
||||
<project name="vex" path="external/VEX" remote="b2g" revision="48d8c7c950745f1b166b42125e6f0d3293d71636"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="95bc959ff0e4ce73e1c9ed5e6916d84922d0a3cc"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="21f7fdaf4ee341022a0416e9186e7b07218cc4b1"/>
|
||||
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
|
||||
<!-- Stock Android things -->
|
||||
<project groups="pdk,linux" name="platform/prebuilts/clang/linux-x86/host/3.5" path="prebuilts/clang/linux-x86/host/3.5" revision="ffc05a232799fe8fcb3e47b7440b52b1fb4244c0"/>
|
||||
|
@ -24,7 +24,7 @@
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="valgrind" path="external/valgrind" remote="b2g" revision="5f931350fbc87c3df9db8b0ceb37734b8b471593"/>
|
||||
<project name="vex" path="external/VEX" remote="b2g" revision="48d8c7c950745f1b166b42125e6f0d3293d71636"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="95bc959ff0e4ce73e1c9ed5e6916d84922d0a3cc"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="21f7fdaf4ee341022a0416e9186e7b07218cc4b1"/>
|
||||
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
|
||||
<!-- Stock Android things -->
|
||||
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="95bb5b66b3ec5769c3de8d3f25d681787418e7d2"/>
|
||||
|
@ -24,7 +24,7 @@
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="valgrind" path="external/valgrind" remote="b2g" revision="5f931350fbc87c3df9db8b0ceb37734b8b471593"/>
|
||||
<project name="vex" path="external/VEX" remote="b2g" revision="48d8c7c950745f1b166b42125e6f0d3293d71636"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="95bc959ff0e4ce73e1c9ed5e6916d84922d0a3cc"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="21f7fdaf4ee341022a0416e9186e7b07218cc4b1"/>
|
||||
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
|
||||
<!-- Stock Android things -->
|
||||
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="f92a936f2aa97526d4593386754bdbf02db07a12"/>
|
||||
|
@ -21,7 +21,7 @@
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="91cac94948094cfdcd00cba5c6483e27e80cb3b0"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="956700d9754349b630a34551750ae6353614b6aa"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="27de93fe66c3e80e157d157bd52ca99565351669"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="95bc959ff0e4ce73e1c9ed5e6916d84922d0a3cc"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="21f7fdaf4ee341022a0416e9186e7b07218cc4b1"/>
|
||||
<project name="valgrind" path="external/valgrind" remote="b2g" revision="5f931350fbc87c3df9db8b0ceb37734b8b471593"/>
|
||||
<project name="vex" path="external/VEX" remote="b2g" revision="48d8c7c950745f1b166b42125e6f0d3293d71636"/>
|
||||
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
|
||||
|
@ -24,7 +24,7 @@
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="valgrind" path="external/valgrind" remote="b2g" revision="5f931350fbc87c3df9db8b0ceb37734b8b471593"/>
|
||||
<project name="vex" path="external/VEX" remote="b2g" revision="48d8c7c950745f1b166b42125e6f0d3293d71636"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="95bc959ff0e4ce73e1c9ed5e6916d84922d0a3cc"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="21f7fdaf4ee341022a0416e9186e7b07218cc4b1"/>
|
||||
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
|
||||
<!-- Stock Android things -->
|
||||
<project groups="pdk,linux" name="platform/prebuilts/clang/linux-x86/host/3.5" path="prebuilts/clang/linux-x86/host/3.5" revision="ffc05a232799fe8fcb3e47b7440b52b1fb4244c0"/>
|
||||
|
@ -1430,6 +1430,13 @@ pref("dom.identity.enabled", false);
|
||||
// Block insecure active content on https pages
|
||||
pref("security.mixed_content.block_active_content", true);
|
||||
|
||||
// Show degraded UI for http pages with password fields
|
||||
#ifdef NIGHTLY_BUILD
|
||||
pref("security.insecure_password.ui.enabled", true);
|
||||
#else
|
||||
pref("security.insecure_password.ui.enabled", false);
|
||||
#endif
|
||||
|
||||
// 1 = allow MITM for certificate pinning checks.
|
||||
pref("security.cert_pinning.enforcement_level", 1);
|
||||
|
||||
|
@ -18,7 +18,7 @@
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>&certerror.pagetitle;</title>
|
||||
<title>&certerror.pagetitle1;</title>
|
||||
<link rel="stylesheet" href="chrome://browser/skin/aboutCertError.css" type="text/css" media="all" />
|
||||
<link rel="stylesheet" href="chrome://browser/content/certerror/aboutCertError.css" type="text/css" media="all" />
|
||||
<!-- This page currently uses the same favicon as neterror.xhtml.
|
||||
@ -51,6 +51,22 @@
|
||||
return decodeURIComponent(matches[1]);
|
||||
}
|
||||
|
||||
function goBack(buttonEl)
|
||||
{
|
||||
if (history.length > 1) {
|
||||
history.back();
|
||||
} else {
|
||||
location.href = "about:home";
|
||||
}
|
||||
buttonEl.disabled = true;
|
||||
}
|
||||
|
||||
function toggleVisibility(id)
|
||||
{
|
||||
var node = document.getElementById(id);
|
||||
node.style.visibility = node.style.visibility == "" ? "hidden" : "";
|
||||
}
|
||||
|
||||
function getDescription()
|
||||
{
|
||||
var url = document.documentURI;
|
||||
@ -66,31 +82,20 @@
|
||||
|
||||
function initPage()
|
||||
{
|
||||
// Replace the "#1" string in the intro with the hostname. Trickier
|
||||
// than it might seem since we want to preserve the <b> tags, but
|
||||
// not allow for any injection by just using innerHTML. Instead,
|
||||
// just find the right target text node.
|
||||
var intro = document.getElementById('introContentP1');
|
||||
function replaceWithHost(node) {
|
||||
if (node.textContent == "#1")
|
||||
node.textContent = location.host;
|
||||
else
|
||||
for(var i = 0; i < node.childNodes.length; i++)
|
||||
replaceWithHost(node.childNodes[i]);
|
||||
};
|
||||
replaceWithHost(intro);
|
||||
for (let host of document.querySelectorAll(".hostname")) {
|
||||
host.textContent = document.location.hostname;
|
||||
}
|
||||
|
||||
var cssClass = getCSSClass();
|
||||
if (cssClass == "expertBadCert") {
|
||||
toggle('technicalContent');
|
||||
toggle('expertContent');
|
||||
toggleVisibility('advancedPanel');
|
||||
}
|
||||
|
||||
// Disallow overrides if this is a Strict-Transport-Security
|
||||
// host and the cert is bad (STS Spec section 7.3) or if the
|
||||
// certerror is in a frame (bug 633691).
|
||||
if (cssClass == "badStsCert" || window != top) {
|
||||
document.getElementById("expertContent").setAttribute("hidden", "true");
|
||||
document.getElementById("advancedPanel").setAttribute("hidden", "true");
|
||||
}
|
||||
if (cssClass != "badStsCert") {
|
||||
document.getElementById("badStsCertExplanation").setAttribute("hidden", "true");
|
||||
@ -167,7 +172,7 @@
|
||||
* domain names are famous for having '.' characters in them,
|
||||
* which would allow spurious and possibly hostile matches.
|
||||
*/
|
||||
if (endsWith(okHost, "." + thisHost))
|
||||
if (okHost.endsWith("." + thisHost))
|
||||
link.href = proto + okHost;
|
||||
|
||||
/* case #2:
|
||||
@ -175,68 +180,46 @@
|
||||
*
|
||||
* The certificate is only valid for garage.maemo.org
|
||||
*/
|
||||
if (endsWith(thisHost, "." + okHost))
|
||||
if (thisHost.endsWith("." + okHost))
|
||||
link.href = proto + okHost;
|
||||
|
||||
// If we set a link, meaning there's something helpful for
|
||||
// the user here, expand the section by default
|
||||
if (link.href && getCSSClass() != "expertBadCert")
|
||||
toggle("technicalContent");
|
||||
}
|
||||
|
||||
function endsWith(haystack, needle) {
|
||||
return haystack.slice(-needle.length) == needle;
|
||||
}
|
||||
|
||||
function toggle(id) {
|
||||
var el = document.getElementById(id);
|
||||
if (el.getAttribute("collapsed"))
|
||||
el.removeAttribute("collapsed");
|
||||
else
|
||||
el.setAttribute("collapsed", true);
|
||||
toggleVisibility("advancedPanel");
|
||||
}
|
||||
]]></script>
|
||||
</head>
|
||||
|
||||
<body dir="&locale.dir;">
|
||||
|
||||
<!-- PAGE CONTAINER (for styling purposes only) -->
|
||||
<div id="errorPageContainer">
|
||||
|
||||
<!-- Error Title -->
|
||||
<div id="errorTitle">
|
||||
<h1 id="errorTitleText">&certerror.longpagetitle;</h1>
|
||||
<h1 id="errorTitleText">&certerror.longpagetitle1;</h1>
|
||||
</div>
|
||||
|
||||
<!-- LONG CONTENT (the section most likely to require scrolling) -->
|
||||
<div id="errorLongContent">
|
||||
<div id="introContent">
|
||||
<p id="introContentP1">&certerror.introPara1;</p>
|
||||
<p>&certerror.introPara2;</p>
|
||||
|
||||
<!-- Short Description -->
|
||||
<div id="errorShortDesc">
|
||||
<p>&certerror.introPara;</p>
|
||||
</div>
|
||||
|
||||
<div id="whatShouldIDoContent">
|
||||
<h2>&certerror.whatShouldIDo.heading;</h2>
|
||||
<div id="whatShouldIDoContentText">
|
||||
<p>&certerror.whatShouldIDo.content;</p>
|
||||
<p id="badStsCertExplanation">&certerror.whatShouldIDo.badStsCertExplanation;</p>
|
||||
<button id='getMeOutOfHereButton'>&certerror.getMeOutOfHere.label;</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- The following sections can be unhidden by default by setting the
|
||||
"browser.xul.error_pages.expert_bad_cert" pref to true -->
|
||||
<h2 id="technicalContent" class="expander" collapsed="true">
|
||||
<button onclick="toggle('technicalContent');">&certerror.technical.heading;</button>
|
||||
</h2>
|
||||
<p id="technicalContentText"/>
|
||||
|
||||
<h2 id="expertContent" class="expander" collapsed="true">
|
||||
<button onclick="toggle('expertContent');">&certerror.expert.heading;</button>
|
||||
</h2>
|
||||
<p id="badStsCertExplanation">&certerror.whatShouldIDo.badStsCertExplanation;</p>
|
||||
<div>
|
||||
<p>&certerror.expert.content;</p>
|
||||
<p>&certerror.expert.contentPara2;</p>
|
||||
<p><a href="https://support.mozilla.org/kb/tls-error-reports" id="learnMoreLink" target="new">&certerror.learnMore;</a></p>
|
||||
</div>
|
||||
|
||||
<div id="buttonContainer">
|
||||
<button id="returnButton" autocomplete="off" onclick="goBack(this);" autofocus="true">&certerror.returnToPreviousPage.label;</button>
|
||||
<div id="buttonSpacer"></div>
|
||||
<button id="advancedButton" autocomplete="off" onclick="toggleVisibility('advancedPanel');" autofocus="true">&certerror.advanced.label;</button>
|
||||
</div>
|
||||
<!-- Advanced panel, which is hidden by default -->
|
||||
<div id="advancedPanel" style="visibility: hidden;">
|
||||
<p id="technicalContentText"/>
|
||||
<button id='exceptionDialogButton'>&certerror.addException.label;</button>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -6927,6 +6927,13 @@ var gIdentityHandler = {
|
||||
return this._state & Ci.nsIWebProgressListener.STATE_LOADED_MIXED_DISPLAY_CONTENT;
|
||||
},
|
||||
|
||||
get _hasInsecureLoginForms() {
|
||||
// checks if the page has been flagged for an insecure login. Also checks
|
||||
// if the pref to degrade the UI is set to true
|
||||
return LoginManagerParent.hasInsecureLoginForms(gBrowser.selectedBrowser) &&
|
||||
Services.prefs.getBoolPref("security.insecure_password.ui.enabled");
|
||||
},
|
||||
|
||||
// smart getters
|
||||
get _identityPopup () {
|
||||
delete this._identityPopup;
|
||||
@ -7257,7 +7264,7 @@ var gIdentityHandler = {
|
||||
this._identityBox.classList.add("weakCipher");
|
||||
}
|
||||
}
|
||||
if (LoginManagerParent.hasInsecureLoginForms(gBrowser.selectedBrowser)) {
|
||||
if (this._hasInsecureLoginForms) {
|
||||
// Insecure login forms can only be present on "unknown identity"
|
||||
// pages, either already insecure or with mixed active content loaded.
|
||||
this._identityBox.classList.add("insecureLoginForms");
|
||||
@ -7301,7 +7308,7 @@ var gIdentityHandler = {
|
||||
|
||||
// Determine if there are insecure login forms.
|
||||
let loginforms = "secure";
|
||||
if (LoginManagerParent.hasInsecureLoginForms(gBrowser.selectedBrowser)) {
|
||||
if (this._hasInsecureLoginForms) {
|
||||
loginforms = "insecure";
|
||||
}
|
||||
|
||||
|
@ -99,7 +99,7 @@ var handleContentContextMenu = function (event) {
|
||||
Services.obs.notifyObservers(subject, "content-contextmenu", null);
|
||||
|
||||
let doc = event.target.ownerDocument;
|
||||
let docLocation = doc.location.href;
|
||||
let docLocation = doc.location ? doc.location.href : undefined;
|
||||
let charSet = doc.characterSet;
|
||||
let baseURI = doc.baseURI;
|
||||
let referrer = doc.referrer;
|
||||
|
@ -1,11 +1,13 @@
|
||||
[DEFAULT]
|
||||
support-files =
|
||||
head.js
|
||||
file_dom_notifications.html
|
||||
|
||||
[browser_notification_close.js]
|
||||
[browser_notification_do_not_disturb.js]
|
||||
[browser_notification_open_settings.js]
|
||||
[browser_notification_remove_permission.js]
|
||||
[browser_notification_permission_migration.js]
|
||||
|
||||
[browser_notification_tab_switching.js]
|
||||
skip-if = buildapp == 'mulet' || e10s # Bug 1100662 - content access causing uncaught exception - Error: cannot ipc non-cpow object at chrome://mochitests/content/browser/browser/base/content/test/general/browser_notification_tab_switching.js:32 (or in RemoteAddonsChild.jsm)
|
||||
|
@ -2,17 +2,6 @@
|
||||
|
||||
var notificationURL = "http://example.org/browser/browser/base/content/test/alerts/file_dom_notifications.html";
|
||||
|
||||
function waitForCloseWindow(window) {
|
||||
return new Promise(function(resolve) {
|
||||
Services.ww.registerNotification(function observer(subject, topic, data) {
|
||||
if (topic == "domwindowclosed" && subject == window) {
|
||||
Services.ww.unregisterNotification(observer);
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
add_task(function* test_settingsOpen_observer() {
|
||||
info("Opening a dummy tab so openPreferences=>switchToTabHavingURI doesn't use the blank tab.");
|
||||
yield BrowserTestUtils.withNewTab({
|
||||
@ -52,7 +41,7 @@ add_task(function* test_settingsOpen_button() {
|
||||
return;
|
||||
}
|
||||
|
||||
let closePromise = waitForCloseWindow(alertWindow);
|
||||
let closePromise = promiseWindowClosed(alertWindow);
|
||||
let tabPromise = BrowserTestUtils.waitForNewTab(gBrowser, "about:preferences#content");
|
||||
let openSettingsMenuItem = alertWindow.document.getElementById("openSettingsMenuItem");
|
||||
openSettingsMenuItem.click();
|
||||
|
@ -0,0 +1,43 @@
|
||||
const UI_VERSION = 32;
|
||||
|
||||
var gBrowserGlue = Cc["@mozilla.org/browser/browserglue;1"]
|
||||
.getService(Ci.nsIObserver);
|
||||
var notificationURI = makeURI("http://example.org");
|
||||
var pm = Services.perms;
|
||||
var currentUIVersion;
|
||||
|
||||
add_task(function* setup() {
|
||||
currentUIVersion = Services.prefs.getIntPref("browser.migration.version");
|
||||
Services.prefs.setIntPref("browser.migration.version", UI_VERSION - 1);
|
||||
pm.add(notificationURI, "desktop-notification", pm.ALLOW_ACTION);
|
||||
});
|
||||
|
||||
add_task(function* test_permissionMigration() {
|
||||
if ("@mozilla.org/system-alerts-service;1" in Cc) {
|
||||
ok(true, "Notifications don't use XUL windows on all platforms.");
|
||||
return;
|
||||
}
|
||||
|
||||
info("Waiting for migration notification");
|
||||
let alertWindowPromise = promiseAlertWindow();
|
||||
gBrowserGlue.observe(null, "browser-glue-test", "force-ui-migration");
|
||||
let alertWindow = yield alertWindowPromise;
|
||||
|
||||
info("Clicking on notification");
|
||||
let url = Services.urlFormatter.formatURLPref("browser.push.warning.infoURL");
|
||||
let closePromise = promiseWindowClosed(alertWindow);
|
||||
let tabPromise = BrowserTestUtils.waitForNewTab(gBrowser, url);
|
||||
EventUtils.synthesizeMouseAtCenter(alertWindow.document.getElementById("alertTitleLabel"), {}, alertWindow);
|
||||
|
||||
info("Waiting for migration info tab");
|
||||
let tab = yield tabPromise;
|
||||
ok(tab, "The migration info tab opened");
|
||||
|
||||
yield closePromise;
|
||||
yield BrowserTestUtils.removeTab(tab);
|
||||
});
|
||||
|
||||
add_task(function* cleanup() {
|
||||
Services.prefs.setIntPref("browser.migration.version", currentUIVersion);
|
||||
pm.remove(notificationURI, "desktop-notification");
|
||||
});
|
31
browser/base/content/test/alerts/head.js
Normal file
31
browser/base/content/test/alerts/head.js
Normal file
@ -0,0 +1,31 @@
|
||||
function promiseAlertWindow() {
|
||||
return new Promise(function(resolve) {
|
||||
let listener = {
|
||||
onOpenWindow(window) {
|
||||
let alertWindow = window.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindow);
|
||||
alertWindow.addEventListener("load", function onLoad() {
|
||||
alertWindow.removeEventListener("load", onLoad);
|
||||
let windowType = alertWindow.document.documentElement.getAttribute("windowtype");
|
||||
if (windowType == "alert:alert") {
|
||||
Services.wm.removeListener(listener);
|
||||
resolve(alertWindow);
|
||||
}
|
||||
});
|
||||
},
|
||||
};
|
||||
Services.wm.addListener(listener);
|
||||
});
|
||||
}
|
||||
|
||||
// `promiseWindowClosed` is similar to `BrowserTestUtils.closeWindow`, but
|
||||
// doesn't call `window.close()`.
|
||||
function promiseWindowClosed(window) {
|
||||
return new Promise(function(resolve) {
|
||||
Services.ww.registerNotification(function observer(subject, topic, data) {
|
||||
if (topic == "domwindowclosed" && subject == window) {
|
||||
Services.ww.unregisterNotification(observer);
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
@ -122,6 +122,7 @@ skip-if = (os == "linux" || os == "mac") && debug # bug 970052, bug 970053
|
||||
skip-if = os == "linux" # Bug 958026
|
||||
support-files =
|
||||
content_aboutAccounts.js
|
||||
[browser_aboutCertError.js]
|
||||
[browser_aboutSupport_newtab_security_state.js]
|
||||
[browser_aboutHealthReport.js]
|
||||
skip-if = os == "linux" # Bug 924307
|
||||
|
79
browser/base/content/test/general/browser_aboutCertError.js
Normal file
79
browser/base/content/test/general/browser_aboutCertError.js
Normal file
@ -0,0 +1,79 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
// This is testing the aboutCertError page (Bug 1207107). It's a start,
|
||||
// but should be expanded to include cert_domain_link / badStsCert
|
||||
|
||||
const GOOD_PAGE = "https://example.com/";
|
||||
const BAD_CERT = "https://expired.example.com/";
|
||||
|
||||
add_task(function* checkReturnToAboutHome() {
|
||||
info("Loading a bad cert page directly and making sure 'return to previous page' goes to about:home");
|
||||
let browser;
|
||||
let certErrorLoaded;
|
||||
let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, () => {
|
||||
gBrowser.selectedTab = gBrowser.addTab(BAD_CERT);
|
||||
browser = gBrowser.selectedBrowser;
|
||||
certErrorLoaded = waitForCertErrorLoad(browser);
|
||||
}, false);
|
||||
|
||||
info("Loading and waiting for the cert error");
|
||||
yield certErrorLoaded;
|
||||
|
||||
is(browser.webNavigation.canGoBack, false, "!webNavigation.canGoBack");
|
||||
is(browser.webNavigation.canGoForward, false, "!webNavigation.canGoForward");
|
||||
|
||||
info("Clicking the go back button on about:certerror");
|
||||
let pageshowPromise = promiseWaitForEvent(browser, "pageshow");
|
||||
yield ContentTask.spawn(browser, null, function* () {
|
||||
let doc = content.document;
|
||||
let returnButton = doc.getElementById("returnButton");
|
||||
returnButton.click();
|
||||
});
|
||||
yield pageshowPromise;
|
||||
|
||||
is(browser.webNavigation.canGoBack, true, "webNavigation.canGoBack");
|
||||
is(browser.webNavigation.canGoForward, false, "!webNavigation.canGoForward");
|
||||
is(gBrowser.currentURI.spec, "about:home", "Went back");
|
||||
|
||||
gBrowser.removeCurrentTab();
|
||||
});
|
||||
|
||||
add_task(function* checkReturnToPreviousPage() {
|
||||
info("Loading a bad cert page and making sure 'return to previous page' goes back");
|
||||
let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, GOOD_PAGE);
|
||||
let browser = gBrowser.selectedBrowser;
|
||||
|
||||
info("Loading and waiting for the cert error");
|
||||
let certErrorLoaded = waitForCertErrorLoad(browser);
|
||||
BrowserTestUtils.loadURI(browser, BAD_CERT);
|
||||
yield certErrorLoaded;
|
||||
|
||||
is(browser.webNavigation.canGoBack, true, "webNavigation.canGoBack");
|
||||
is(browser.webNavigation.canGoForward, false, "!webNavigation.canGoForward");
|
||||
|
||||
info("Clicking the go back button on about:certerror");
|
||||
let pageshowPromise = promiseWaitForEvent(browser, "pageshow");
|
||||
yield ContentTask.spawn(browser, null, function* () {
|
||||
let doc = content.document;
|
||||
let returnButton = doc.getElementById("returnButton");
|
||||
returnButton.click();
|
||||
});
|
||||
yield pageshowPromise;
|
||||
|
||||
is(browser.webNavigation.canGoBack, false, "!webNavigation.canGoBack");
|
||||
is(browser.webNavigation.canGoForward, true, "webNavigation.canGoForward");
|
||||
is(gBrowser.currentURI.spec, GOOD_PAGE, "Went back");
|
||||
|
||||
gBrowser.removeCurrentTab();
|
||||
});
|
||||
|
||||
function waitForCertErrorLoad(browser) {
|
||||
return new Promise(resolve => {
|
||||
info("Waiting for DOMContentLoaded event");
|
||||
browser.addEventListener("DOMContentLoaded", function load() {
|
||||
browser.removeEventListener("DOMContentLoaded", load, false, true);
|
||||
resolve();
|
||||
}, false, true);
|
||||
});
|
||||
}
|
@ -99,7 +99,8 @@ var gTests = [
|
||||
|
||||
let engine = yield promiseNewEngine("searchSuggestionEngine.xml");
|
||||
// Make this actually work in healthreport by giving it an ID:
|
||||
engine.wrappedJSObject._identifier = 'org.mozilla.testsearchsuggestions';
|
||||
Object.defineProperty(engine.wrappedJSObject, "identifier",
|
||||
{value: "org.mozilla.testsearchsuggestions"});
|
||||
|
||||
let p = promiseContentSearchChange(engine.name);
|
||||
Services.search.currentEngine = engine;
|
||||
|
@ -9,15 +9,17 @@ function test() {
|
||||
}
|
||||
|
||||
function testBrokenCert() {
|
||||
if (gBrowser.contentDocument.documentURI === "about:blank")
|
||||
return;
|
||||
window.removeEventListener("DOMContentLoaded", testBrokenCert, true);
|
||||
|
||||
// Confirm that we are displaying the contributed error page, not the default
|
||||
ok(gBrowser.contentDocument.documentURI.startsWith("about:certerror"), "Broken page should go to about:certerror, not about:neterror");
|
||||
|
||||
// Confirm that the expert section is collapsed
|
||||
var expertDiv = gBrowser.contentDocument.getElementById("expertContent");
|
||||
ok(expertDiv, "Expert content div should exist");
|
||||
ok(expertDiv.hasAttribute("collapsed"), "Expert content should be collapsed by default");
|
||||
var advancedDiv = gBrowser.contentDocument.getElementById("advancedPanel");
|
||||
ok(advancedDiv, "Advanced content div should exist");
|
||||
is_element_hidden(advancedDiv, "Advanced content should not be visible by default");
|
||||
|
||||
// Tweak the expert mode pref
|
||||
gPrefService.setBoolPref("browser.xul.error_pages.expert_bad_cert", true);
|
||||
@ -28,10 +30,9 @@ function testBrokenCert() {
|
||||
|
||||
function testExpertPref() {
|
||||
window.removeEventListener("DOMContentLoaded", testExpertPref, true);
|
||||
var expertDiv = gBrowser.contentDocument.getElementById("expertContent");
|
||||
var technicalDiv = gBrowser.contentDocument.getElementById("technicalContent");
|
||||
ok(!expertDiv.hasAttribute("collapsed"), "Expert content should not be collapsed with the expert mode pref set");
|
||||
ok(!technicalDiv.hasAttribute("collapsed"), "Technical content should not be collapsed with the expert mode pref set");
|
||||
var advancedDiv = gBrowser.contentDocument.getElementById("advancedPanel");
|
||||
ok(advancedDiv, "Advanced content div should exist");
|
||||
is_element_visible(advancedDiv, "Advanced content should be visible by default");
|
||||
|
||||
// Clean up
|
||||
gBrowser.removeCurrentTab();
|
||||
|
@ -17,12 +17,12 @@ function testIframeCert(e) {
|
||||
gBrowser.selectedBrowser.removeEventListener("load", testIframeCert, true);
|
||||
// Confirm that the expert section is hidden
|
||||
var doc = gBrowser.contentDocument.getElementsByTagName('iframe')[0].contentDocument;
|
||||
var eC = doc.getElementById("expertContent");
|
||||
ok(eC, "Expert content should exist")
|
||||
ok(eC.hasAttribute("hidden"), "Expert content should be hidded by default");
|
||||
var aP = doc.getElementById("advancedPanel");
|
||||
ok(aP, "Advanced content should exist");
|
||||
is_element_hidden(aP, "Advanced content should not be visible by default")
|
||||
|
||||
// Clean up
|
||||
gBrowser.removeCurrentTab();
|
||||
|
||||
|
||||
finish();
|
||||
}
|
||||
|
@ -18,6 +18,10 @@ function waitForInsecureLoginFormsStateChange(browser, count) {
|
||||
* Checks the insecure login forms logic for the identity block.
|
||||
*/
|
||||
add_task(function* test_simple() {
|
||||
yield new Promise(resolve => SpecialPowers.pushPrefEnv({
|
||||
"set": [["security.insecure_password.ui.enabled", true]],
|
||||
}, resolve));
|
||||
|
||||
for (let scheme of ["http", "https"]) {
|
||||
let tab = gBrowser.addTab(scheme + testUrlPath + "form_basic.html");
|
||||
let browser = tab.linkedBrowser;
|
||||
|
@ -815,7 +815,7 @@ loop.roomViews = (function(mozL10n) {
|
||||
renderRemoteVideo: this.shouldRenderRemoteVideo(),
|
||||
screenShareMediaElement: this.state.screenShareMediaElement,
|
||||
screenSharePosterUrl: null,
|
||||
showContextRoomName: false,
|
||||
showInitialContext: false,
|
||||
useDesktopPaths: true},
|
||||
React.createElement(sharedViews.ConversationToolbar, {
|
||||
audio: { enabled: !this.state.audioMuted, visible: true},
|
||||
|
@ -815,7 +815,7 @@ loop.roomViews = (function(mozL10n) {
|
||||
renderRemoteVideo={this.shouldRenderRemoteVideo()}
|
||||
screenShareMediaElement={this.state.screenShareMediaElement}
|
||||
screenSharePosterUrl={null}
|
||||
showContextRoomName={false}
|
||||
showInitialContext={false}
|
||||
useDesktopPaths={true}>
|
||||
<sharedViews.ConversationToolbar
|
||||
audio={{ enabled: !this.state.audioMuted, visible: true }}
|
||||
|
@ -545,14 +545,13 @@ html[dir="rtl"] .context-content {
|
||||
}
|
||||
|
||||
.context-wrapper {
|
||||
border: 1px solid #5cccee;
|
||||
border: 2px solid #ebebeb;
|
||||
border-radius: 4px;
|
||||
background: #fff;
|
||||
padding: .8em;
|
||||
background: #fafafa;
|
||||
padding: 1.1rem .8rem;
|
||||
/* Use the flex row mode to position the elements next to each other. */
|
||||
display: flex;
|
||||
flex-flow: row nowrap;
|
||||
line-height: 1.1em;
|
||||
/* No underline for the text in the context view. */
|
||||
text-decoration: none;
|
||||
}
|
||||
@ -590,9 +589,6 @@ html[dir="rtl"] .context-wrapper > .context-preview {
|
||||
|
||||
.clicks-allowed.context-wrapper:hover {
|
||||
border: 2px solid #5cccee;
|
||||
/* Due to the increased border width, reduce the padding accordingly so that
|
||||
the text doesn't move. */
|
||||
padding: calc(.8em - 1px);
|
||||
}
|
||||
|
||||
/* Only underline the url, not the associated text */
|
||||
|
@ -529,14 +529,8 @@ body[platform="win"] .share-service-dropdown.overflow > .dropdown-menu-item {
|
||||
background-image: url("../img/icons-16x16.svg#add-active");
|
||||
}
|
||||
|
||||
.context-url-view-wrapper {
|
||||
padding: 14px 15px;
|
||||
background-color: #dbf7ff;
|
||||
}
|
||||
|
||||
.showing-room-name > .text-chat-entries > .text-chat-scroller > .context-url-view-wrapper {
|
||||
padding-top: 0;
|
||||
margin-bottom: 0;
|
||||
.context-url-view-wrapper > .context-content {
|
||||
margin: 0 1rem 1.5rem 1rem;
|
||||
}
|
||||
|
||||
.room-context {
|
||||
@ -947,6 +941,7 @@ body[platform="win"] .share-service-dropdown.overflow > .dropdown-menu-item {
|
||||
|
||||
.text-chat-entries {
|
||||
overflow: auto;
|
||||
padding-top: .6rem;
|
||||
}
|
||||
|
||||
.text-chat-entry,
|
||||
@ -965,20 +960,16 @@ body[platform="win"] .share-service-dropdown.overflow > .dropdown-menu-item {
|
||||
text-align: start;
|
||||
}
|
||||
|
||||
.text-chat-scroller div:nth-child(2) {
|
||||
margin-top: .5em;
|
||||
}
|
||||
|
||||
/* Sent text chat entries should be on the right */
|
||||
.text-chat-entry.sent {
|
||||
/* aligns paragraph to right side */
|
||||
justify-content: flex-end;
|
||||
margin-left: 0;
|
||||
margin-right: 5px;
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
.text-chat-entry.received {
|
||||
margin-left: 4px;
|
||||
margin-left: 2px;
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
@ -1126,20 +1117,16 @@ html[dir="rtl"] .text-chat-entry.received .text-chat-arrow {
|
||||
}
|
||||
|
||||
.text-chat-header.special.room-name {
|
||||
color: black;
|
||||
color: #666;
|
||||
font-weight: bold;
|
||||
text-align: start;
|
||||
background-color: #dbf7ff;
|
||||
margin-bottom: 0;
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.text-chat-header.special.room-name p {
|
||||
background: #dbf7ff;
|
||||
max-width: 100%;
|
||||
/* 18px for indent of .text-chat-arrow, 1px for border of .text-chat-entry > p,
|
||||
0.5rem for padding of .text-chat-entry > p */
|
||||
padding: calc(18px - 1px - 0.5rem);
|
||||
width: 100%;
|
||||
padding: 0.8rem 1rem 1.4rem;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.text-chat-header.special > p {
|
||||
|
@ -118,7 +118,8 @@ loop.store.TextChatStore = (function() {
|
||||
|
||||
// Notify MozLoopService if appropriate that a message has been appended
|
||||
// and it should therefore check if we need a different sized window or not.
|
||||
if (message.contentType !== CHAT_CONTENT_TYPES.ROOM_NAME) {
|
||||
if (message.contentType !== CHAT_CONTENT_TYPES.ROOM_NAME &&
|
||||
message.contentType !== CHAT_CONTENT_TYPES.CONTEXT) {
|
||||
if (this._storeState.textChatEnabled) {
|
||||
window.dispatchEvent(new CustomEvent("LoopChatMessageAppended"));
|
||||
} else {
|
||||
|
@ -106,6 +106,7 @@ loop.shared.views.chat = (function(mozL10n) {
|
||||
propTypes: {
|
||||
dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
|
||||
messageList: React.PropTypes.arrayOf(React.PropTypes.object).isRequired,
|
||||
showInitialContext: React.PropTypes.bool.isRequired,
|
||||
useDesktopPaths: React.PropTypes.bool.isRequired
|
||||
},
|
||||
|
||||
@ -174,6 +175,7 @@ loop.shared.views.chat = (function(mozL10n) {
|
||||
|
||||
this.props.messageList.map(function(entry, i) {
|
||||
if (entry.type === CHAT_MESSAGE_TYPES.SPECIAL) {
|
||||
if (!this.props.showInitialContext) { return null; }
|
||||
switch (entry.contentType) {
|
||||
case CHAT_CONTENT_TYPES.ROOM_NAME:
|
||||
return (
|
||||
@ -188,7 +190,6 @@ loop.shared.views.chat = (function(mozL10n) {
|
||||
allowClick: true,
|
||||
description: entry.message,
|
||||
dispatcher: this.props.dispatcher,
|
||||
showContextTitle: true,
|
||||
thumbnail: entry.extraData.thumbnail,
|
||||
url: entry.extraData.location,
|
||||
useDesktopPaths: this.props.useDesktopPaths})
|
||||
@ -357,8 +358,8 @@ loop.shared.views.chat = (function(mozL10n) {
|
||||
* as a field for entering new messages.
|
||||
*
|
||||
* @property {loop.Dispatcher} dispatcher
|
||||
* @property {Boolean} showRoomName Set to true to show the room name
|
||||
* special list item.
|
||||
* @property {Boolean} showInitialContext Set to true to show the room name
|
||||
* and initial context tile for linker clicker's special list items
|
||||
*/
|
||||
var TextChatView = React.createClass({displayName: "TextChatView",
|
||||
mixins: [
|
||||
@ -368,7 +369,7 @@ loop.shared.views.chat = (function(mozL10n) {
|
||||
|
||||
propTypes: {
|
||||
dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
|
||||
showRoomName: React.PropTypes.bool.isRequired,
|
||||
showInitialContext: React.PropTypes.bool.isRequired,
|
||||
useDesktopPaths: React.PropTypes.bool.isRequired
|
||||
},
|
||||
|
||||
@ -377,18 +378,15 @@ loop.shared.views.chat = (function(mozL10n) {
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var messageList;
|
||||
var showingRoomName = false;
|
||||
var messageList = this.state.messageList;
|
||||
|
||||
if (this.props.showRoomName) {
|
||||
messageList = this.state.messageList;
|
||||
showingRoomName = this.state.messageList.some(function(item) {
|
||||
return item.contentType === CHAT_CONTENT_TYPES.ROOM_NAME;
|
||||
});
|
||||
} else {
|
||||
messageList = this.state.messageList.filter(function(item) {
|
||||
// Filter out items not displayed when showing initial context.
|
||||
// We do this here so that we can set the classes correctly on the view.
|
||||
if (!this.props.showInitialContext) {
|
||||
messageList = messageList.filter(function(item) {
|
||||
return item.type !== CHAT_MESSAGE_TYPES.SPECIAL ||
|
||||
item.contentType !== CHAT_CONTENT_TYPES.ROOM_NAME;
|
||||
(item.contentType !== CHAT_CONTENT_TYPES.ROOM_NAME &&
|
||||
item.contentType !== CHAT_CONTENT_TYPES.CONTEXT);
|
||||
});
|
||||
}
|
||||
|
||||
@ -398,10 +396,9 @@ loop.shared.views.chat = (function(mozL10n) {
|
||||
});
|
||||
|
||||
var textChatViewClasses = React.addons.classSet({
|
||||
"showing-room-name": showingRoomName,
|
||||
"text-chat-view": true,
|
||||
"text-chat-disabled": !this.state.textChatEnabled,
|
||||
"text-chat-entries-empty": !messageList.length
|
||||
"text-chat-entries-empty": !messageList.length,
|
||||
"text-chat-disabled": !this.state.textChatEnabled
|
||||
});
|
||||
|
||||
return (
|
||||
@ -409,6 +406,7 @@ loop.shared.views.chat = (function(mozL10n) {
|
||||
React.createElement(TextChatEntriesView, {
|
||||
dispatcher: this.props.dispatcher,
|
||||
messageList: messageList,
|
||||
showInitialContext: this.props.showInitialContext,
|
||||
useDesktopPaths: this.props.useDesktopPaths}),
|
||||
React.createElement(TextChatInputView, {
|
||||
dispatcher: this.props.dispatcher,
|
||||
|
@ -106,6 +106,7 @@ loop.shared.views.chat = (function(mozL10n) {
|
||||
propTypes: {
|
||||
dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
|
||||
messageList: React.PropTypes.arrayOf(React.PropTypes.object).isRequired,
|
||||
showInitialContext: React.PropTypes.bool.isRequired,
|
||||
useDesktopPaths: React.PropTypes.bool.isRequired
|
||||
},
|
||||
|
||||
@ -174,6 +175,7 @@ loop.shared.views.chat = (function(mozL10n) {
|
||||
{
|
||||
this.props.messageList.map(function(entry, i) {
|
||||
if (entry.type === CHAT_MESSAGE_TYPES.SPECIAL) {
|
||||
if (!this.props.showInitialContext) { return null; }
|
||||
switch (entry.contentType) {
|
||||
case CHAT_CONTENT_TYPES.ROOM_NAME:
|
||||
return (
|
||||
@ -188,7 +190,6 @@ loop.shared.views.chat = (function(mozL10n) {
|
||||
allowClick={true}
|
||||
description={entry.message}
|
||||
dispatcher={this.props.dispatcher}
|
||||
showContextTitle={true}
|
||||
thumbnail={entry.extraData.thumbnail}
|
||||
url={entry.extraData.location}
|
||||
useDesktopPaths={this.props.useDesktopPaths} />
|
||||
@ -357,8 +358,8 @@ loop.shared.views.chat = (function(mozL10n) {
|
||||
* as a field for entering new messages.
|
||||
*
|
||||
* @property {loop.Dispatcher} dispatcher
|
||||
* @property {Boolean} showRoomName Set to true to show the room name
|
||||
* special list item.
|
||||
* @property {Boolean} showInitialContext Set to true to show the room name
|
||||
* and initial context tile for linker clicker's special list items
|
||||
*/
|
||||
var TextChatView = React.createClass({
|
||||
mixins: [
|
||||
@ -368,7 +369,7 @@ loop.shared.views.chat = (function(mozL10n) {
|
||||
|
||||
propTypes: {
|
||||
dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
|
||||
showRoomName: React.PropTypes.bool.isRequired,
|
||||
showInitialContext: React.PropTypes.bool.isRequired,
|
||||
useDesktopPaths: React.PropTypes.bool.isRequired
|
||||
},
|
||||
|
||||
@ -377,18 +378,15 @@ loop.shared.views.chat = (function(mozL10n) {
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var messageList;
|
||||
var showingRoomName = false;
|
||||
var messageList = this.state.messageList;
|
||||
|
||||
if (this.props.showRoomName) {
|
||||
messageList = this.state.messageList;
|
||||
showingRoomName = this.state.messageList.some(function(item) {
|
||||
return item.contentType === CHAT_CONTENT_TYPES.ROOM_NAME;
|
||||
});
|
||||
} else {
|
||||
messageList = this.state.messageList.filter(function(item) {
|
||||
// Filter out items not displayed when showing initial context.
|
||||
// We do this here so that we can set the classes correctly on the view.
|
||||
if (!this.props.showInitialContext) {
|
||||
messageList = messageList.filter(function(item) {
|
||||
return item.type !== CHAT_MESSAGE_TYPES.SPECIAL ||
|
||||
item.contentType !== CHAT_CONTENT_TYPES.ROOM_NAME;
|
||||
(item.contentType !== CHAT_CONTENT_TYPES.ROOM_NAME &&
|
||||
item.contentType !== CHAT_CONTENT_TYPES.CONTEXT);
|
||||
});
|
||||
}
|
||||
|
||||
@ -398,10 +396,9 @@ loop.shared.views.chat = (function(mozL10n) {
|
||||
});
|
||||
|
||||
var textChatViewClasses = React.addons.classSet({
|
||||
"showing-room-name": showingRoomName,
|
||||
"text-chat-view": true,
|
||||
"text-chat-disabled": !this.state.textChatEnabled,
|
||||
"text-chat-entries-empty": !messageList.length
|
||||
"text-chat-entries-empty": !messageList.length,
|
||||
"text-chat-disabled": !this.state.textChatEnabled
|
||||
});
|
||||
|
||||
return (
|
||||
@ -409,6 +406,7 @@ loop.shared.views.chat = (function(mozL10n) {
|
||||
<TextChatEntriesView
|
||||
dispatcher={this.props.dispatcher}
|
||||
messageList={messageList}
|
||||
showInitialContext={this.props.showInitialContext}
|
||||
useDesktopPaths={this.props.useDesktopPaths} />
|
||||
<TextChatInputView
|
||||
dispatcher={this.props.dispatcher}
|
||||
|
@ -810,7 +810,6 @@ loop.shared.views = (function(_, mozL10n) {
|
||||
* is specified, then 'dispatcher' is also required.
|
||||
* @property {String} description The description for the context url.
|
||||
* @property {loop.Dispatcher} dispatcher
|
||||
* @property {Boolean} showContextTitle Whether or not to show the "Let's talk about" title.
|
||||
* @property {String} thumbnail The thumbnail url (expected to be a data url) to
|
||||
* display. If not specified, a fallback url will be
|
||||
* shown.
|
||||
@ -826,7 +825,6 @@ loop.shared.views = (function(_, mozL10n) {
|
||||
allowClick: React.PropTypes.bool.isRequired,
|
||||
description: React.PropTypes.string.isRequired,
|
||||
dispatcher: React.PropTypes.instanceOf(loop.Dispatcher),
|
||||
showContextTitle: React.PropTypes.bool.isRequired,
|
||||
thumbnail: React.PropTypes.string,
|
||||
url: React.PropTypes.string,
|
||||
useDesktopPaths: React.PropTypes.bool.isRequired
|
||||
@ -845,17 +843,6 @@ loop.shared.views = (function(_, mozL10n) {
|
||||
}));
|
||||
},
|
||||
|
||||
/**
|
||||
* Renders the context title ("Let's talk about") if necessary.
|
||||
*/
|
||||
renderContextTitle: function() {
|
||||
if (!this.props.showContextTitle) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return React.createElement("p", null, mozL10n.get("context_inroom_label2"));
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var hostname;
|
||||
|
||||
@ -880,7 +867,6 @@ loop.shared.views = (function(_, mozL10n) {
|
||||
|
||||
return (
|
||||
React.createElement("div", {className: "context-content"},
|
||||
this.renderContextTitle(),
|
||||
React.createElement("a", {className: wrapperClasses,
|
||||
href: this.props.allowClick ? this.props.url : null,
|
||||
onClick: this.handleLinkClick,
|
||||
@ -1031,7 +1017,7 @@ loop.shared.views = (function(_, mozL10n) {
|
||||
renderRemoteVideo: React.PropTypes.bool.isRequired,
|
||||
screenShareMediaElement: React.PropTypes.object,
|
||||
screenSharePosterUrl: React.PropTypes.string,
|
||||
showContextRoomName: React.PropTypes.bool.isRequired,
|
||||
showInitialContext: React.PropTypes.bool.isRequired,
|
||||
useDesktopPaths: React.PropTypes.bool.isRequired
|
||||
},
|
||||
|
||||
@ -1135,7 +1121,7 @@ loop.shared.views = (function(_, mozL10n) {
|
||||
),
|
||||
React.createElement(loop.shared.views.chat.TextChatView, {
|
||||
dispatcher: this.props.dispatcher,
|
||||
showRoomName: this.props.showContextRoomName,
|
||||
showInitialContext: this.props.showInitialContext,
|
||||
useDesktopPaths: this.props.useDesktopPaths}),
|
||||
this.state.localMediaAboslutelyPositioned ?
|
||||
null : this.renderLocalVideo()
|
||||
|
@ -810,7 +810,6 @@ loop.shared.views = (function(_, mozL10n) {
|
||||
* is specified, then 'dispatcher' is also required.
|
||||
* @property {String} description The description for the context url.
|
||||
* @property {loop.Dispatcher} dispatcher
|
||||
* @property {Boolean} showContextTitle Whether or not to show the "Let's talk about" title.
|
||||
* @property {String} thumbnail The thumbnail url (expected to be a data url) to
|
||||
* display. If not specified, a fallback url will be
|
||||
* shown.
|
||||
@ -826,7 +825,6 @@ loop.shared.views = (function(_, mozL10n) {
|
||||
allowClick: React.PropTypes.bool.isRequired,
|
||||
description: React.PropTypes.string.isRequired,
|
||||
dispatcher: React.PropTypes.instanceOf(loop.Dispatcher),
|
||||
showContextTitle: React.PropTypes.bool.isRequired,
|
||||
thumbnail: React.PropTypes.string,
|
||||
url: React.PropTypes.string,
|
||||
useDesktopPaths: React.PropTypes.bool.isRequired
|
||||
@ -845,17 +843,6 @@ loop.shared.views = (function(_, mozL10n) {
|
||||
}));
|
||||
},
|
||||
|
||||
/**
|
||||
* Renders the context title ("Let's talk about") if necessary.
|
||||
*/
|
||||
renderContextTitle: function() {
|
||||
if (!this.props.showContextTitle) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return <p>{mozL10n.get("context_inroom_label2")}</p>;
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var hostname;
|
||||
|
||||
@ -880,7 +867,6 @@ loop.shared.views = (function(_, mozL10n) {
|
||||
|
||||
return (
|
||||
<div className="context-content">
|
||||
{this.renderContextTitle()}
|
||||
<a className={wrapperClasses}
|
||||
href={this.props.allowClick ? this.props.url : null}
|
||||
onClick={this.handleLinkClick}
|
||||
@ -1031,7 +1017,7 @@ loop.shared.views = (function(_, mozL10n) {
|
||||
renderRemoteVideo: React.PropTypes.bool.isRequired,
|
||||
screenShareMediaElement: React.PropTypes.object,
|
||||
screenSharePosterUrl: React.PropTypes.string,
|
||||
showContextRoomName: React.PropTypes.bool.isRequired,
|
||||
showInitialContext: React.PropTypes.bool.isRequired,
|
||||
useDesktopPaths: React.PropTypes.bool.isRequired
|
||||
},
|
||||
|
||||
@ -1135,7 +1121,7 @@ loop.shared.views = (function(_, mozL10n) {
|
||||
</div>
|
||||
<loop.shared.views.chat.TextChatView
|
||||
dispatcher={this.props.dispatcher}
|
||||
showRoomName={this.props.showContextRoomName}
|
||||
showInitialContext={this.props.showInitialContext}
|
||||
useDesktopPaths={this.props.useDesktopPaths} />
|
||||
{this.state.localMediaAboslutelyPositioned ?
|
||||
null : this.renderLocalVideo()}
|
||||
|
@ -42,9 +42,9 @@
|
||||
*
|
||||
*/
|
||||
function require(url) {
|
||||
var devTimeUrl = url.replace(/^script!/, '');
|
||||
var devTimeUrl = devTimeUrl.replace(/^imports.*!/, '');
|
||||
var devTimeUrl = devTimeUrl.replace(/^exports.*!/, '');
|
||||
// strip off everything up to and including the last !, as those are
|
||||
// all directives to webpack
|
||||
var devTimeUrl = url.replace(/^.*!/, '');
|
||||
insertScript(devTimeUrl, true);
|
||||
}
|
||||
|
||||
@ -174,16 +174,60 @@
|
||||
// We don't use the SDK's CSS. This will prevent spurious 404 errors.
|
||||
window.OTProperties.cssURL = "about:blank";
|
||||
</script>
|
||||
|
||||
<script>
|
||||
// Explicitly create this here so that it's deterministic and easier to
|
||||
// understand, rather than having it created as a side-effect of loading
|
||||
// one of our faux-modules.
|
||||
var loop = {};
|
||||
</script>
|
||||
|
||||
<script type="text/javascript" src="config.js"></script>
|
||||
|
||||
<!-- note that for 'make dist', webappEntryPoint.js is replaced by -->
|
||||
<!-- the standalone.js bundle -->
|
||||
<script>
|
||||
// Wait for both "localized" to fire and webapp.js to finish executing.
|
||||
// This needs to be available ahead of either of those things happening,
|
||||
// so we declare it here.
|
||||
//
|
||||
// The localized event fires asynchronously after l10n.js loads,
|
||||
// so it could happen before or after loop.webapp.init has been
|
||||
// defined.
|
||||
//
|
||||
// This means at least in the (current) dev setup where our
|
||||
// require shim injects script tags dynamically. The race could conceivably
|
||||
// happen in production as well, after l10n.js loads and before webpack.js
|
||||
// is loaded.
|
||||
//
|
||||
// Fortunately, that dev setup nastiness will go away once we get to a
|
||||
// single build setup using real modules and obsolete build-jsx.
|
||||
var localizedHasFired = false;
|
||||
function initIfReady() {
|
||||
if (localizedHasFired && "webapp" in loop) {
|
||||
loop.webapp.init();
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- We'd like to bundle/minify this at some point, but we need to work
|
||||
out how to configure webpack to run this in a module container
|
||||
rather than directly in the global scope. -->
|
||||
|
||||
<!-- Note that as long as the various closures in the files loaded by
|
||||
webppEntryPoint.js take navigator.mozL10n as an argument, this
|
||||
JS must run to completion before that file loads, so this one must be
|
||||
loaded synchronously first -->
|
||||
<script type="text/javascript" src="libs/l10n-gaia-02ca67948fe8.js">
|
||||
</script>
|
||||
|
||||
<!-- Note that for 'make dist', webappEntryPoint.js is replaced by
|
||||
the standalone.js bundle -->
|
||||
<script type="text/javascript" src="webappEntryPoint.js"></script>
|
||||
|
||||
<script>
|
||||
// Wait for all the localization notes to load
|
||||
window.addEventListener("localized", function() {
|
||||
loop.webapp.init();
|
||||
// see the initIfReady() comments in this file for details
|
||||
localizedHasFired = true;
|
||||
initIfReady();
|
||||
}, false);
|
||||
</script>
|
||||
|
||||
|
@ -619,7 +619,7 @@ loop.standaloneRoomViews = (function(mozL10n) {
|
||||
renderRemoteVideo: this.shouldRenderRemoteVideo(),
|
||||
screenShareMediaElement: this.state.screenShareMediaElement,
|
||||
screenSharePosterUrl: this.props.screenSharePosterUrl,
|
||||
showContextRoomName: true,
|
||||
showInitialContext: true,
|
||||
useDesktopPaths: false},
|
||||
React.createElement(StandaloneOverlayWrapper, {dispatcher: this.props.dispatcher}),
|
||||
React.createElement(StandaloneRoomInfoArea, {activeRoomStore: this.props.activeRoomStore,
|
||||
|
@ -619,7 +619,7 @@ loop.standaloneRoomViews = (function(mozL10n) {
|
||||
renderRemoteVideo={this.shouldRenderRemoteVideo()}
|
||||
screenShareMediaElement={this.state.screenShareMediaElement}
|
||||
screenSharePosterUrl={this.props.screenSharePosterUrl}
|
||||
showContextRoomName={true}
|
||||
showInitialContext={true}
|
||||
useDesktopPaths={false}>
|
||||
<StandaloneOverlayWrapper dispatcher={this.props.dispatcher} />
|
||||
<StandaloneRoomInfoArea activeRoomStore={this.props.activeRoomStore}
|
||||
|
@ -246,3 +246,10 @@ loop.webapp = (function(_, OT, mozL10n) {
|
||||
WebappRootView: WebappRootView
|
||||
};
|
||||
})(_, window.OT, navigator.mozL10n);
|
||||
|
||||
// This should only be available when this file is loaded into index.html,
|
||||
// where it's used to actually start the app.
|
||||
/* global initIfReady */
|
||||
if (typeof initIfReady === "function") {
|
||||
initIfReady();
|
||||
}
|
||||
|
@ -246,3 +246,10 @@ loop.webapp = (function(_, OT, mozL10n) {
|
||||
WebappRootView: WebappRootView
|
||||
};
|
||||
})(_, window.OT, navigator.mozL10n);
|
||||
|
||||
// This should only be available when this file is loaded into index.html,
|
||||
// where it's used to actually start the app.
|
||||
/* global initIfReady */
|
||||
if (typeof initIfReady === "function") {
|
||||
initIfReady();
|
||||
}
|
||||
|
@ -81,9 +81,3 @@ status_error=Something went wrong
|
||||
# Text chat strings
|
||||
|
||||
chat_textbox_placeholder=Type here…
|
||||
# LOCALIZATION NOTE (context_inroom_label2): this string is followed by the
|
||||
# title/domain of the website you are having a conversation about, displayed on a
|
||||
# separate line. If this structure doesn't work for your locale, you might want
|
||||
# to consider this as a stand-alone title. See example screenshot:
|
||||
# https://bug1084991.bugzilla.mozilla.org/attachment.cgi?id=8614721
|
||||
context_inroom_label2=Let's Talk About:
|
||||
|
@ -19,8 +19,6 @@
|
||||
// we turn that off by forcing require to false in that context.
|
||||
require("imports?require=>false!shared/libs/sdk.js");
|
||||
|
||||
require("script!./libs/l10n-gaia-02ca67948fe8.js");
|
||||
|
||||
// Ultimately, we'll likely want to pull the vendor libraries from npm, as that
|
||||
// makes upgrading easier, and it's generally better practice to minify the
|
||||
// "source" versions of libraries rather than built artifacts. We probably do
|
||||
@ -28,29 +26,64 @@ require("script!./libs/l10n-gaia-02ca67948fe8.js");
|
||||
// elimination, but that can be a bit of judgement call.
|
||||
require("exports?_!shared/libs/lodash-3.9.3.js");
|
||||
|
||||
// Note that anything that uses the script loader doesn't get minified, so
|
||||
// these need to be shimmed to use to other loaders (easiest first cut) or
|
||||
// turned into real modules:
|
||||
require("script!shared/libs/backbone-1.2.1.js");
|
||||
require("script!shared/libs/react-0.12.2.js");
|
||||
// Disable Backbone's AMD auto-detection, as described at:
|
||||
//
|
||||
// https://github.com/jashkenas/backbone/wiki/Using-Backbone-without-jQuery
|
||||
//
|
||||
require("expose?Backbone!imports?define=>false!shared/libs/backbone-1.2.1.js");
|
||||
|
||||
require("script!shared/js/utils.js");
|
||||
require("script!shared/js/crypto.js");
|
||||
require("script!shared/js/mixins.js");
|
||||
require("script!shared/js/actions.js");
|
||||
require("script!shared/js/validate.js");
|
||||
require("script!shared/js/dispatcher.js");
|
||||
require("script!shared/js/otSdkDriver.js");
|
||||
require("script!shared/js/store.js");
|
||||
require("script!shared/js/activeRoomStore.js");
|
||||
require("script!shared/js/views.js");
|
||||
require("script!shared/js/urlRegExps.js");
|
||||
require("script!shared/js/textChatStore.js");
|
||||
require("script!shared/js/textChatView.js");
|
||||
require("script!shared/js/linkifiedTextView.js");
|
||||
/* global: __PROD__ */
|
||||
if (typeof __PROD__ !== "undefined") {
|
||||
// webpack warns if we try to minify some prebuilt libraries, so we
|
||||
// pull in the unbuilt version from node_modules
|
||||
require("expose?React!react");
|
||||
require("expose?React!react/addons");
|
||||
} else {
|
||||
// our development server setup doesn't yet handle real modules, so for now...
|
||||
require("shared/libs/react-0.12.2.js");
|
||||
}
|
||||
|
||||
require("script!./js/standaloneAppStore.js");
|
||||
require("script!./js/standaloneMozLoop.js");
|
||||
require("script!./js/standaloneRoomViews.js");
|
||||
require("script!./js/standaloneMetricsStore.js");
|
||||
require("script!./js/webapp.js");
|
||||
|
||||
// Someday, these will be real modules. For now, we're chaining loaders
|
||||
// to teach webpack how to treat them like modules anyway.
|
||||
//
|
||||
// We do it in this file rather than globally in webpack.config.js
|
||||
// because:
|
||||
//
|
||||
// * it's easiest to understand magic (like loader chaining
|
||||
// interactions) when it's explicit and in one place
|
||||
// * migrating stuff over to real modules is easier to do gradually
|
||||
//
|
||||
// The strategy works like this (webpack loaders chain from right to left):
|
||||
//
|
||||
// In standalone, loop is defined for the first time in index.html.
|
||||
//
|
||||
// The exports?loop loader sets up webpack to ensure that exports is
|
||||
// actually exposed to outside world, rather than held privately.
|
||||
//
|
||||
// The imports=?loop=>window.loop loader puts the existing window.loop
|
||||
// reference into that exported container for further modification.
|
||||
//
|
||||
// See https://webpack.github.io/docs/shimming-modules.html for more
|
||||
// context.
|
||||
//
|
||||
require("imports?loop=>window.loop!exports?loop!shared/js/utils.js");
|
||||
require("imports?this=>window,loop=>window.loop!exports?loop!shared/js/crypto.js");
|
||||
require("imports?loop=>window.loop!exports?loop!shared/js/mixins.js");
|
||||
require("imports?loop=>window.loop!exports?loop!shared/js/actions.js");
|
||||
require("imports?loop=>window.loop!exports?loop!shared/js/validate.js");
|
||||
require("imports?loop=>window.loop!exports?loop!shared/js/dispatcher.js");
|
||||
require("imports?loop=>window.loop!exports?loop!shared/js/otSdkDriver.js");
|
||||
require("imports?loop=>window.loop!exports?loop!shared/js/store.js");
|
||||
require("imports?loop=>window.loop!exports?loop!shared/js/activeRoomStore.js");
|
||||
require("imports?loop=>window.loop!exports?loop!shared/js/views.js");
|
||||
require("imports?loop=>window.loop!exports?loop!shared/js/urlRegExps.js");
|
||||
require("imports?loop=>window.loop!exports?loop!shared/js/textChatStore.js");
|
||||
require("imports?loop=>window.loop!exports?loop!shared/js/textChatView.js");
|
||||
require("imports?loop=>window.loop!exports?loop!shared/js/linkifiedTextView.js");
|
||||
|
||||
require("imports?loop=>window.loop!exports?loop!./js/standaloneAppStore.js");
|
||||
require("imports?loop=>window.loop!exports?loop!./js/standaloneMozLoop.js");
|
||||
require("imports?loop=>window.loop!exports?loop!./js/standaloneRoomViews.js");
|
||||
require("imports?loop=>window.loop!exports?loop!./js/standaloneMetricsStore.js");
|
||||
require("imports?loop=>window.loop!exports?loop!./js/webapp.js");
|
||||
|
@ -17,8 +17,10 @@
|
||||
"eslint-plugin-mozilla": "../../../../testing/eslint-plugin-mozilla",
|
||||
"eslint-plugin-react": "3.5.x",
|
||||
"exports-loader": "0.6.x",
|
||||
"expose-loader": "0.7.x",
|
||||
"express": "4.x",
|
||||
"imports-loader": "0.6.x",
|
||||
"react": "0.12.x",
|
||||
"script-loader": "0.6.x",
|
||||
"webpack": "1.12.x"
|
||||
},
|
||||
|
@ -37,8 +37,17 @@ function getSharedDir() {
|
||||
module.exports = {
|
||||
entry: "./content/webappEntryPoint.js",
|
||||
|
||||
// These symbols come in either via <script> tags or the expose loader,
|
||||
// so we tell webpack to allow them to be unresolved
|
||||
externals: {
|
||||
"Backbone": "Backbone",
|
||||
"navigator.mozL10n": "navigator.mozL10n",
|
||||
"React": "React",
|
||||
"underscore": "_"
|
||||
},
|
||||
|
||||
// We want the shared modules to be available without the requirer needing
|
||||
// to know the path to them, especially that path is different in
|
||||
// to know the path to them, especially since that path is different in
|
||||
// mozilla-central and loop-client.
|
||||
resolve: {
|
||||
alias: {
|
||||
@ -55,6 +64,21 @@ module.exports = {
|
||||
},
|
||||
|
||||
plugins: [
|
||||
// This is a soft-dependency for Backbone, and since we don't use it,
|
||||
// we need to tell webpack to ignore the unresolved reference. Cribbed
|
||||
// from
|
||||
// https://github.com/jashkenas/backbone/wiki/Using-Backbone-without-jQuery
|
||||
new webpack.IgnorePlugin(/^jquery$/),
|
||||
|
||||
// definePlugin takes raw strings and inserts them, so we can put a
|
||||
// JS string for evaluation at build time. Right now, we test NODE_ENV
|
||||
// to so we can do different things at build time based on whether we're
|
||||
// in production mode.
|
||||
new webpack.DefinePlugin({
|
||||
__PROD__: JSON.stringify(JSON.parse(
|
||||
process.env.NODE_ENV && process.env.NODE_ENV === "production"))
|
||||
}),
|
||||
|
||||
new webpack.optimize.UglifyJsPlugin({
|
||||
compress: {
|
||||
// XXX I'd _like_ to only suppress the warnings for vendor code, since
|
||||
|
@ -248,23 +248,6 @@ describe("loop.store.TextChatStore", function() {
|
||||
}]);
|
||||
});
|
||||
|
||||
it("should dispatch a LoopChatDisabledMessageAppended event", function() {
|
||||
store.setStoreState({ textChatEnabled: false });
|
||||
store.updateRoomInfo(new sharedActions.UpdateRoomInfo({
|
||||
roomName: "Let's share!",
|
||||
roomUrl: "fake",
|
||||
roomContextUrls: [{
|
||||
description: "A wonderful event2",
|
||||
location: "http://wonderful.invalid2",
|
||||
thumbnail: "fake2"
|
||||
}]
|
||||
}));
|
||||
|
||||
sinon.assert.calledOnce(window.dispatchEvent);
|
||||
sinon.assert.calledWithExactly(window.dispatchEvent,
|
||||
new CustomEvent("LoopChatDisabledMessageAppended"));
|
||||
});
|
||||
|
||||
it("should not dispatch a LoopChatMessageAppended event", function() {
|
||||
store.updateRoomInfo(new sharedActions.UpdateRoomInfo({
|
||||
roomName: "Let's share!",
|
||||
|
@ -46,6 +46,7 @@ describe("loop.shared.views.TextChatView", function() {
|
||||
var basicProps = {
|
||||
dispatcher: dispatcher,
|
||||
messageList: [],
|
||||
showInitialContext: true,
|
||||
useDesktopPaths: false
|
||||
};
|
||||
|
||||
@ -58,6 +59,7 @@ describe("loop.shared.views.TextChatView", function() {
|
||||
var basicProps = {
|
||||
dispatcher: dispatcher,
|
||||
messageList: [],
|
||||
showInitialContext: true,
|
||||
useDesktopPaths: false
|
||||
};
|
||||
|
||||
@ -396,7 +398,7 @@ describe("loop.shared.views.TextChatView", function() {
|
||||
function mountTestComponent(extraProps) {
|
||||
var props = _.extend({
|
||||
dispatcher: dispatcher,
|
||||
showRoomName: false,
|
||||
showInitialContext: true,
|
||||
useDesktopPaths: false,
|
||||
showAlways: true
|
||||
}, extraProps);
|
||||
@ -453,40 +455,6 @@ describe("loop.shared.views.TextChatView", function() {
|
||||
expect(view.getDOMNode().classList.contains("text-chat-entries-empty")).eql(false);
|
||||
});
|
||||
|
||||
it("should add a showing room name class when the view shows room names and it has a room name", function() {
|
||||
view = mountTestComponent({
|
||||
showRoomName: true
|
||||
});
|
||||
|
||||
store.updateRoomInfo(new sharedActions.UpdateRoomInfo({
|
||||
roomName: "Study",
|
||||
roomUrl: "Fake"
|
||||
}));
|
||||
|
||||
expect(view.getDOMNode().classList.contains("showing-room-name")).eql(true);
|
||||
});
|
||||
|
||||
it("shouldn't add a showing room name class when the view doesn't show room names", function() {
|
||||
view = mountTestComponent({
|
||||
showRoomName: false
|
||||
});
|
||||
|
||||
store.updateRoomInfo(new sharedActions.UpdateRoomInfo({
|
||||
roomName: "Study",
|
||||
roomUrl: "Fake"
|
||||
}));
|
||||
|
||||
expect(view.getDOMNode().classList.contains("showing-room-name")).eql(false);
|
||||
});
|
||||
|
||||
it("shouldn't add a showing room name class when the view doesn't have a name", function() {
|
||||
view = mountTestComponent({
|
||||
showRoomName: true
|
||||
});
|
||||
|
||||
expect(view.getDOMNode().classList.contains("showing-room-name")).eql(false);
|
||||
});
|
||||
|
||||
it("should show timestamps from msgs sent more than 1 min apart", function() {
|
||||
view = mountTestComponent();
|
||||
|
||||
@ -569,7 +537,7 @@ describe("loop.shared.views.TextChatView", function() {
|
||||
|
||||
it("should render a room name special entry", function() {
|
||||
view = mountTestComponent({
|
||||
showRoomName: true
|
||||
showInitialContext: true
|
||||
});
|
||||
|
||||
store.updateRoomInfo(new sharedActions.UpdateRoomInfo({
|
||||
@ -605,6 +573,27 @@ describe("loop.shared.views.TextChatView", function() {
|
||||
expect(node.querySelector(".context-url-view-wrapper")).to.not.eql(null);
|
||||
});
|
||||
|
||||
it("should not render a room title and context url when show initial context is false", function() {
|
||||
view = mountTestComponent({
|
||||
showInitialContext: false
|
||||
});
|
||||
|
||||
store.updateRoomInfo(new sharedActions.UpdateRoomInfo({
|
||||
roomName: "A Very Long Conversation Name",
|
||||
roomUrl: "http://showcase",
|
||||
roomContextUrls: [{
|
||||
description: "A wonderful page!",
|
||||
location: "http://wonderful.invalid"
|
||||
// use the fallback thumbnail
|
||||
}]
|
||||
}));
|
||||
|
||||
var node = view.getDOMNode();
|
||||
|
||||
expect(node.querySelector(".showing-room-name")).to.eql(null);
|
||||
expect(node.querySelector(".context-url-view-wrapper")).to.eql(null);
|
||||
});
|
||||
|
||||
it("should dispatch SendTextChatMessage action when enter is pressed", function() {
|
||||
view = mountTestComponent();
|
||||
|
||||
|
@ -837,15 +837,6 @@ describe("loop.shared.views", function() {
|
||||
expect(view.getDOMNode().querySelector(".context-content > p")).eql(null);
|
||||
});
|
||||
|
||||
it("should display a title if required", function() {
|
||||
view = mountTestComponent({
|
||||
showContextTitle: true,
|
||||
url: "http://wonderful.invalid"
|
||||
});
|
||||
|
||||
expect(view.getDOMNode().querySelector(".context-content > p")).not.eql(null);
|
||||
});
|
||||
|
||||
it("should set the href on the link if clicks are allowed", function() {
|
||||
view = mountTestComponent({
|
||||
allowClick: true,
|
||||
@ -1024,7 +1015,7 @@ describe("loop.shared.views", function() {
|
||||
localVideoMuted: false,
|
||||
matchMedia: window.matchMedia,
|
||||
renderRemoteVideo: false,
|
||||
showContextRoomName: false,
|
||||
showInitialContext: false,
|
||||
useDesktopPaths: false
|
||||
};
|
||||
|
||||
|
@ -1288,7 +1288,7 @@
|
||||
width: 298},
|
||||
React.createElement("div", {className: "fx-embedded"},
|
||||
React.createElement(TextChatView, {dispatcher: dispatcher,
|
||||
showRoomName: false,
|
||||
showInitialContext: false,
|
||||
useDesktopPaths: false})
|
||||
)
|
||||
),
|
||||
@ -1302,7 +1302,7 @@
|
||||
React.createElement("div", {className: "media-wrapper"},
|
||||
React.createElement(TextChatView, {
|
||||
dispatcher: dispatcher,
|
||||
showRoomName: true,
|
||||
showInitialContext: true,
|
||||
useDesktopPaths: false})
|
||||
)
|
||||
)
|
||||
|
@ -1288,7 +1288,7 @@
|
||||
width={298}>
|
||||
<div className="fx-embedded">
|
||||
<TextChatView dispatcher={dispatcher}
|
||||
showRoomName={false}
|
||||
showInitialContext={false}
|
||||
useDesktopPaths={false} />
|
||||
</div>
|
||||
</FramedExample>
|
||||
@ -1302,7 +1302,7 @@
|
||||
<div className="media-wrapper">
|
||||
<TextChatView
|
||||
dispatcher={dispatcher}
|
||||
showRoomName={true}
|
||||
showInitialContext={true}
|
||||
useDesktopPaths={false} />
|
||||
</div>
|
||||
</div>
|
||||
|
@ -582,11 +582,53 @@ this.MigrationUtils = Object.freeze({
|
||||
}
|
||||
#endif
|
||||
|
||||
// nsIWindowWatcher doesn't deal with raw arrays, so we convert the input
|
||||
let params;
|
||||
if (Array.isArray(aParams)) {
|
||||
params = Cc["@mozilla.org/array;1"].createInstance(Ci.nsIMutableArray);
|
||||
for (let item of aParams) {
|
||||
let comtaminatedVal;
|
||||
if (item && item instanceof Ci.nsISupports) {
|
||||
comtaminatedVal = item;
|
||||
} else {
|
||||
switch (typeof item) {
|
||||
case "boolean":
|
||||
comtaminatedVal = Cc["@mozilla.org/supports-PRBool;1"].
|
||||
createInstance(Ci.nsISupportsPRBool);
|
||||
comtaminatedVal.data = item;
|
||||
break;
|
||||
case "number":
|
||||
comtaminatedVal = Cc["@mozilla.org/supports-PRUint32;1"].
|
||||
createInstance(Ci.nsISupportsPRUint32);
|
||||
comtaminatedVal.data = item;
|
||||
break;
|
||||
case "string":
|
||||
comtaminatedVal = Cc["@mozilla.org/supports-cstring;1"].
|
||||
createInstance(Ci.nsISupportsCString);
|
||||
comtaminatedVal.data = item;
|
||||
break;
|
||||
|
||||
case "undefined":
|
||||
case "object":
|
||||
if (!item) {
|
||||
comtaminatedVal = null;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw new Error("Unexpected parameter type " + (typeof item) + ": " + item);
|
||||
}
|
||||
}
|
||||
params.appendElement(comtaminatedVal, false);
|
||||
}
|
||||
} else {
|
||||
params = aParams;
|
||||
}
|
||||
|
||||
Services.ww.openWindow(aOpener,
|
||||
"chrome://browser/content/migration/migration.xul",
|
||||
"_blank",
|
||||
features,
|
||||
aParams);
|
||||
params);
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -31,7 +31,7 @@ var MigrationWizard = {
|
||||
|
||||
this._wiz = document.documentElement;
|
||||
|
||||
let args = (window.arguments && window.arguments[0]) || [];
|
||||
let args = window.arguments;
|
||||
let entryPointId = args[0] || MigrationUtils.MIGRATION_ENTRYPOINT_UNKNOWN;
|
||||
Services.telemetry.getHistogramById("FX_MIGRATION_ENTRY_POINT").add(entryPointId);
|
||||
|
||||
|
@ -22,6 +22,8 @@ XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
|
||||
"resource://gre/modules/NetUtil.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "RemoteNewTabUtils",
|
||||
"resource:///modules/RemoteNewTabUtils.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "PlacesTestUtils",
|
||||
"resource://testing-common/PlacesTestUtils.jsm");
|
||||
|
||||
do_get_profile();
|
||||
|
||||
@ -1285,8 +1287,7 @@ add_task(function test_RemoteDirectoryLinksProvider_ClickRemoval() {
|
||||
|
||||
testObserver = new UrlDeletionTester();
|
||||
RemoteDirectoryLinksProvider.addObserver(testObserver);
|
||||
// remove all hostory
|
||||
PlacesUtils.bhistory.removeAllPages();
|
||||
yield PlacesTestUtils.clearHistory();
|
||||
|
||||
yield testObserver.promise;
|
||||
RemoteDirectoryLinksProvider.removeObserver(testObserver);
|
||||
|
@ -187,6 +187,9 @@ XPCOMUtils.defineLazyModuleGetter(this, "AppConstants",
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "WindowsUIUtils",
|
||||
"@mozilla.org/windows-ui-utils;1", "nsIWindowsUIUtils");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "AlertsService",
|
||||
"@mozilla.org/alerts-service;1", "nsIAlertsService");
|
||||
|
||||
const ABOUT_NEWTAB = "about:newtab";
|
||||
|
||||
const PREF_PLUGINS_NOTIFYUSER = "plugins.update.notifyUser";
|
||||
@ -1564,16 +1567,6 @@ BrowserGlue.prototype = {
|
||||
if (actions.indexOf("showAlert") == -1)
|
||||
return;
|
||||
|
||||
let notifier;
|
||||
try {
|
||||
notifier = Cc["@mozilla.org/alerts-service;1"].
|
||||
getService(Ci.nsIAlertsService);
|
||||
}
|
||||
catch (e) {
|
||||
// nsIAlertsService is not available for this platform
|
||||
return;
|
||||
}
|
||||
|
||||
let title = getNotifyString({propName: "alertTitle",
|
||||
stringName: "puAlertTitle",
|
||||
stringParams: [appName]});
|
||||
@ -1594,10 +1587,11 @@ BrowserGlue.prototype = {
|
||||
try {
|
||||
// This will throw NS_ERROR_NOT_AVAILABLE if the notification cannot
|
||||
// be displayed per the idl.
|
||||
notifier.showAlertNotification(null, title, text,
|
||||
true, url, clickCallback);
|
||||
AlertsService.showAlertNotification(null, title, text,
|
||||
true, url, clickCallback);
|
||||
}
|
||||
catch (e) {
|
||||
Cu.reportError(e);
|
||||
}
|
||||
},
|
||||
|
||||
@ -1877,7 +1871,7 @@ BrowserGlue.prototype = {
|
||||
},
|
||||
|
||||
_migrateUI: function BG__migrateUI() {
|
||||
const UI_VERSION = 31;
|
||||
const UI_VERSION = 32;
|
||||
const BROWSER_DOCURL = "chrome://browser/content/browser.xul";
|
||||
let currentUIVersion = 0;
|
||||
try {
|
||||
@ -2218,10 +2212,49 @@ BrowserGlue.prototype = {
|
||||
xulStore.removeValue(BROWSER_DOCURL, "home-button", "class");
|
||||
}
|
||||
|
||||
if (currentUIVersion < 32) {
|
||||
this._notifyNotificationsUpgrade();
|
||||
}
|
||||
|
||||
// Update the migration version.
|
||||
Services.prefs.setIntPref("browser.migration.version", UI_VERSION);
|
||||
},
|
||||
|
||||
_hasExistingNotificationPermission: function BG__hasExistingNotificationPermission() {
|
||||
let enumerator = Services.perms.enumerator;
|
||||
while (enumerator.hasMoreElements()) {
|
||||
let permission = enumerator.getNext().QueryInterface(Ci.nsIPermission);
|
||||
if (permission.type == "desktop-notification") {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
_notifyNotificationsUpgrade: function BG__notifyNotificationsUpgrade() {
|
||||
if (!this._hasExistingNotificationPermission()) {
|
||||
return;
|
||||
}
|
||||
function clickCallback(subject, topic, data) {
|
||||
if (topic != "alertclickcallback")
|
||||
return;
|
||||
let win = RecentWindow.getMostRecentBrowserWindow();
|
||||
win.openUILinkIn(data, "tab");
|
||||
}
|
||||
let imageURL = "chrome://browser/skin/web-notifications-icon.svg";
|
||||
let title = gBrowserBundle.GetStringFromName("webNotifications.upgradeTitle");
|
||||
let text = gBrowserBundle.GetStringFromName("webNotifications.upgradeInfo");
|
||||
let url = Services.urlFormatter.formatURLPref("browser.push.warning.infoURL");
|
||||
|
||||
try {
|
||||
AlertsService.showAlertNotification(imageURL, title, text,
|
||||
true, url, clickCallback);
|
||||
}
|
||||
catch (e) {
|
||||
Cu.reportError(e);
|
||||
}
|
||||
},
|
||||
|
||||
// ------------------------------
|
||||
// public nsIBrowserGlue members
|
||||
// ------------------------------
|
||||
|
@ -74,6 +74,10 @@ var gContentPane = {
|
||||
setEventListener("notificationsDoNotDisturb", "command",
|
||||
gContentPane.toggleDoNotDisturbNotifications);
|
||||
|
||||
let notificationInfoURL = Services.urlFormatter.formatURLPref("browser.push.warning.infoURL");
|
||||
document.getElementById("notificationsPolicyLearnMore").setAttribute("href",
|
||||
notificationInfoURL);
|
||||
|
||||
let drmInfoURL =
|
||||
Services.urlFormatter.formatURLPref("app.support.baseURL") + "drm-content";
|
||||
document.getElementById("playDRMContentLink").setAttribute("href", drmInfoURL);
|
||||
|
@ -68,10 +68,13 @@
|
||||
<column/>
|
||||
</columns>
|
||||
<rows>
|
||||
<row id="notificationsPolicyRow">
|
||||
<vbox align="start">
|
||||
<row id="notificationsPolicyRow" align="center">
|
||||
<hbox align="start">
|
||||
<label id="notificationsPolicy">¬ificationsPolicyDesc2.label;</label>
|
||||
</vbox>
|
||||
<label id="notificationsPolicyLearnMore"
|
||||
class="text-link"
|
||||
value="¬ificationsPolicyLearnMore.label;"/>
|
||||
</hbox>
|
||||
<hbox pack="end">
|
||||
<button id="notificationsPolicyButton" label="¬ificationsPolicyButton.label;"
|
||||
accesskey="¬ificationsPolicyButton.accesskey;"/>
|
||||
|
@ -211,13 +211,16 @@
|
||||
</vbox>
|
||||
</hbox>
|
||||
<label class="fxaMobilePromo">
|
||||
&mobilePromo.start;<!-- We put these comments to avoid inserting white spaces
|
||||
--><image class="androidLogo"/><!--
|
||||
--><label class="androidLink text-link" href="https://www.mozilla.org/firefox/android/"><!--
|
||||
-->&mobilePromo.androidLink;</label><!--
|
||||
-->&mobilePromo.end;
|
||||
&mobilePromo2.start;<!-- We put these comments to avoid inserting white spaces
|
||||
--><label class="androidLink text-link"
|
||||
href="https://www.mozilla.org/firefox/android/?utm_source=firefox-browser&utm_medium=firefox-browser&utm_campaign=sync-preferences"><!--
|
||||
-->&mobilePromo2.androidLink;</label><!--
|
||||
-->&mobilePromo2.iOSBefore;<!--
|
||||
--><label class="iOSLink text-link"
|
||||
href="https://www.mozilla.org/firefox/ios/?utm_source=firefox-browser&utm_medium=firefox-browser&utm_campaign=sync-preferences"><!--
|
||||
-->&mobilePromo2.iOSLink;</label><!--
|
||||
-->&mobilePromo2.end;
|
||||
</label>
|
||||
<label class="androidAttribution">&androidAttribution;</label>
|
||||
</vbox>
|
||||
|
||||
<vbox id="hasFxaAccount">
|
||||
@ -342,15 +345,18 @@
|
||||
</hbox>
|
||||
</hbox>
|
||||
</groupbox>
|
||||
<spacer class="separator"/>
|
||||
<label class="fxaMobilePromo">
|
||||
&mobilePromo.start;<!-- We put these comments to avoid inserting white spaces
|
||||
--><image class="androidLogo"/><!--
|
||||
--><label class="androidLink text-link" href="https://www.mozilla.org/firefox/android/"><!--
|
||||
-->&mobilePromo.androidLink;</label><!--
|
||||
-->&mobilePromo.end;
|
||||
&mobilePromo2.start;<!-- We put these comments to avoid inserting white spaces
|
||||
--><label class="androidLink text-link"
|
||||
href="https://www.mozilla.org/firefox/android/?utm_source=firefox-browser&utm_medium=firefox-browser&utm_campaign=sync-preferences"><!--
|
||||
-->&mobilePromo2.androidLink;</label><!--
|
||||
-->&mobilePromo2.iOSBefore;<!--
|
||||
--><label class="iOSLink text-link"
|
||||
href="https://www.mozilla.org/firefox/ios/?utm_source=firefox-browser&utm_medium=firefox-browser&utm_campaign=sync-preferences"><!--
|
||||
-->&mobilePromo2.iOSLink;</label><!--
|
||||
-->&mobilePromo2.end;
|
||||
</label>
|
||||
<spacer flex="1"/>
|
||||
<spacer class="separator" flex="1"/>
|
||||
<vbox id="tosPP-small" align="start">
|
||||
<label id="tosPP-small-ToS" class="text-link">
|
||||
&prefs.tosLink.label;
|
||||
@ -359,6 +365,5 @@
|
||||
&fxaPrivacyNotice.link.label;
|
||||
</label>
|
||||
</vbox>
|
||||
<label class="androidAttribution">&androidAttribution;</label>
|
||||
</vbox>
|
||||
</deck>
|
||||
|
@ -11,12 +11,25 @@ function test() {
|
||||
const ENGINE_NAME = "Foo";
|
||||
var contextMenu;
|
||||
|
||||
let envService = Cc["@mozilla.org/process/environment;1"].getService(Ci.nsIEnvironment);
|
||||
let originalValue = envService.get("XPCSHELL_TEST_PROFILE_DIR");
|
||||
envService.set("XPCSHELL_TEST_PROFILE_DIR", "1");
|
||||
|
||||
let url = "chrome://mochitests/content/browser/browser/components/search/test/";
|
||||
let resProt = Services.io.getProtocolHandler("resource")
|
||||
.QueryInterface(Ci.nsIResProtocolHandler);
|
||||
let originalSubstitution = resProt.getSubstitution("search-plugins");
|
||||
resProt.setSubstitution("search-plugins",
|
||||
Services.io.newURI(url, null, null));
|
||||
|
||||
function observer(aSub, aTopic, aData) {
|
||||
switch (aData) {
|
||||
case "engine-added":
|
||||
var engine = ss.getEngineByName(ENGINE_NAME);
|
||||
ok(engine, "Engine was added.");
|
||||
ss.currentEngine = engine;
|
||||
envService.set("XPCSHELL_TEST_PROFILE_DIR", originalValue);
|
||||
resProt.setSubstitution("search-plugins", originalSubstitution);
|
||||
break;
|
||||
case "engine-current":
|
||||
is(ss.currentEngine.name, ENGINE_NAME, "currentEngine set");
|
||||
@ -30,7 +43,7 @@ function test() {
|
||||
}
|
||||
|
||||
Services.obs.addObserver(observer, "browser-search-engine-modified", false);
|
||||
ss.addEngine("http://mochi.test:8888/browser/browser/components/search/test/testEngine_mozsearch.xml",
|
||||
ss.addEngine("resource://search-plugins/testEngine_mozsearch.xml",
|
||||
null, "data:image/x-icon,%00", false);
|
||||
|
||||
function startTest() {
|
||||
|
@ -32,7 +32,9 @@ function test() {
|
||||
|
||||
// Runs tests after all 'load' event handlers have fired off
|
||||
window.addEventListener("documentload", function() {
|
||||
runTests(document, window, tab, finish);
|
||||
runTests(document, window, tab, function () {
|
||||
closePDFViewer(window, finish);
|
||||
});
|
||||
}, false, true);
|
||||
}, true);
|
||||
}
|
||||
@ -45,6 +47,8 @@ function runTests(document, window, tab, callback) {
|
||||
//
|
||||
ok(document.querySelector('div#viewer'), "document content has viewer UI");
|
||||
ok('PDFJS' in window.wrappedJSObject, "window content has PDFJS object");
|
||||
ok('PDFViewerApplication' in window.wrappedJSObject,
|
||||
"window content has viewer object");
|
||||
|
||||
//
|
||||
// Browser Find
|
||||
@ -84,3 +88,11 @@ function runTests(document, window, tab, callback) {
|
||||
|
||||
callback();
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroys PDF.js viewer opened document.
|
||||
*/
|
||||
function closePDFViewer(window, callback) {
|
||||
var viewer = window.wrappedJSObject.PDFViewerApplication;
|
||||
viewer.close().then(callback);
|
||||
}
|
||||
|
@ -32,7 +32,9 @@ function test() {
|
||||
|
||||
// Runs tests after all 'load' event handlers have fired off
|
||||
window.addEventListener("documentload", function() {
|
||||
runTests(document, window, finish);
|
||||
runTests(document, window, function () {
|
||||
closePDFViewer(window, finish);
|
||||
});
|
||||
}, false, true);
|
||||
}, true);
|
||||
}
|
||||
@ -74,3 +76,11 @@ function runTests(document, window, callback) {
|
||||
|
||||
callback();
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroys PDF.js viewer opened document.
|
||||
*/
|
||||
function closePDFViewer(window, callback) {
|
||||
var viewer = window.wrappedJSObject.PDFViewerApplication;
|
||||
viewer.close().then(callback);
|
||||
}
|
||||
|
@ -90,7 +90,9 @@ function test() {
|
||||
window.addEventListener("documentload", function() {
|
||||
initialWidth = parseInt(document.querySelector("div#pageContainer1").style.width);
|
||||
previousWidth = initialWidth;
|
||||
runTests(document, window, finish);
|
||||
runTests(document, window, function () {
|
||||
closePDFViewer(window, finish);
|
||||
});
|
||||
}, false, true);
|
||||
}, true);
|
||||
}
|
||||
@ -102,7 +104,7 @@ function runTests(document, window, callback) {
|
||||
|
||||
// Start the zooming tests after the document is loaded
|
||||
waitForDocumentLoad(document).then(function () {
|
||||
zoomPDF(document, window, TESTS.shift(), finish);
|
||||
zoomPDF(document, window, TESTS.shift(), callback);
|
||||
});
|
||||
}
|
||||
|
||||
@ -173,3 +175,11 @@ function zoomPDF(document, window, test, endCallback) {
|
||||
EventUtils.synthesizeKey(test.action.event, { ctrlKey: true });
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroys PDF.js viewer opened document.
|
||||
*/
|
||||
function closePDFViewer(window, callback) {
|
||||
var viewer = window.wrappedJSObject.PDFViewerApplication;
|
||||
viewer.close().then(callback);
|
||||
}
|
||||
|
@ -10,23 +10,9 @@
|
||||
a replacement for the standard security certificate errors produced
|
||||
by NSS/PSM via netError.xhtml. -->
|
||||
|
||||
<!ENTITY certerror.pagetitle "Untrusted Connection">
|
||||
<!ENTITY certerror.longpagetitle "This Connection is Untrusted">
|
||||
|
||||
<!-- These are going to be used for the updated design in Bug 1207107 -->
|
||||
<!ENTITY certerror.pagetitle1 "Insecure Connection">
|
||||
<!ENTITY certerror.longpagetitle1 "Your connection is not secure">
|
||||
|
||||
<!-- Localization note (certerror.introPara1) - The string "#1" will
|
||||
be replaced at runtime with the name of the server to which the user
|
||||
was trying to connect. -->
|
||||
<!ENTITY certerror.introPara1 "You have asked &brandShortName; to connect
|
||||
securely to <b>#1</b>, but we can't confirm that your connection is secure.">
|
||||
<!ENTITY certerror.introPara2 "Normally, when you try to connect securely,
|
||||
sites will present trusted identification to prove that you are
|
||||
going to the right place. However, this site's identity can't be verified.">
|
||||
|
||||
<!-- These are going to be used for the udpated design in Bug 1207107 -->
|
||||
<!-- Localization note (certerror.introPara) - The text content of the span tag
|
||||
will be replaced at runtime with the name of the server to which the user
|
||||
was trying to connect. -->
|
||||
@ -35,17 +21,11 @@ was trying to connect. -->
|
||||
<!ENTITY certerror.learnMore "Learn more…">
|
||||
<!ENTITY certerror.advanced.label "Advanced">
|
||||
|
||||
<!ENTITY certerror.whatShouldIDo.heading "What Should I Do?">
|
||||
<!ENTITY certerror.whatShouldIDo.content "If you usually connect to
|
||||
this site without problems, this error could mean that someone is
|
||||
trying to impersonate the site, and you shouldn't continue.">
|
||||
<!ENTITY certerror.whatShouldIDo.badStsCertExplanation "This site uses HTTP
|
||||
Strict Transport Security (HSTS) to specify that &brandShortName; only connect
|
||||
to it securely. As a result, it is not possible to add an exception for this
|
||||
certificate.">
|
||||
<!ENTITY certerror.getMeOutOfHere.label "Get me out of here!">
|
||||
|
||||
<!ENTITY certerror.expert.heading "I Understand the Risks">
|
||||
<!ENTITY certerror.expert.content "If you understand what's going on, you
|
||||
can tell &brandShortName; to start trusting this site's identification.
|
||||
<b>Even if you trust the site, this error could mean that someone is
|
||||
@ -53,5 +33,3 @@ tampering with your connection.</b>">
|
||||
<!ENTITY certerror.expert.contentPara2 "Don't add an exception unless
|
||||
you know there's a good reason why this site doesn't use trusted identification.">
|
||||
<!ENTITY certerror.addException.label "Add Exception…">
|
||||
|
||||
<!ENTITY certerror.technical.heading "Technical Details">
|
||||
|
@ -382,6 +382,8 @@ webNotifications.alwaysReceive.accesskey=A
|
||||
webNotifications.neverShow=Always Block Notifications
|
||||
webNotifications.neverShow.accesskey=N
|
||||
webNotifications.receiveFromSite=Would you like to receive notifications from this site?
|
||||
webNotifications.upgradeTitle=Upgraded notifications
|
||||
webNotifications.upgradeInfo=You will receive notifications from sites, even those not open in a tab. Click to learn more.
|
||||
|
||||
# Pointer lock UI
|
||||
|
||||
|
@ -61,6 +61,9 @@ tree-item.nostack=(no stack available)
|
||||
# that represents the root of the tree when inverted.
|
||||
tree-item.root=(root)
|
||||
|
||||
# LOCALIZATION NOTE (tree-item.percent): A percent of bytes or count displayed in the tree view.
|
||||
tree-item.percent=%S%
|
||||
|
||||
# LOCALIZATION NOTE (snapshot.state.saving.full): The label describing the snapshot
|
||||
# state SAVING, used in the main heap view.
|
||||
snapshot.state.saving.full=Saving snapshot…
|
||||
@ -114,3 +117,8 @@ heapview.field.totalcount=Total Count
|
||||
|
||||
# LOCALIZATION NOTE (heapview.field.name): The name of the column in the heap view for name.
|
||||
heapview.field.name=Name
|
||||
|
||||
# LOCALIZATION NOTE (unknownSource): When we do not know the source filename of
|
||||
# a frame in the allocation stack breakdown tree view, we use this string
|
||||
# instead.
|
||||
unknownSource=(unknown)
|
||||
|
@ -219,12 +219,6 @@ no_conversations_start_message2=Start a new one!
|
||||
# conversation window when the user edits context. It is a header to the edit
|
||||
# section.
|
||||
context_inroom_header=Let's Talk About…
|
||||
# LOCALIZATION NOTE (context_inroom_label2): this string is followed by the
|
||||
# title and domain of the website you are having a conversation about, displayed on a
|
||||
# separate line. If this structure doesn't work for your locale, you might want
|
||||
# to consider this as a stand-alone title. See example screenshot:
|
||||
# https://bug1115342.bugzilla.mozilla.org/attachment.cgi?id=8563677
|
||||
context_inroom_label2=Let's Talk About:
|
||||
context_edit_name_placeholder=Conversation Name
|
||||
context_edit_comments_placeholder=Comments
|
||||
context_cancel_label=Cancel
|
||||
|
@ -8,7 +8,8 @@
|
||||
<!ENTITY blockPopups.accesskey "B">
|
||||
|
||||
<!ENTITY notificationsPolicy.label "Notifications">
|
||||
<!ENTITY notificationsPolicyDesc2.label "Choose which sites are allowed to receive notifications">
|
||||
<!ENTITY notificationsPolicyLearnMore.label "Learn more">
|
||||
<!ENTITY notificationsPolicyDesc2.label "Choose which sites are allowed to receive notifications">
|
||||
<!ENTITY notificationsPolicyButton.accesskey "h">
|
||||
<!ENTITY notificationsPolicyButton.label "Choose…">
|
||||
<!ENTITY notificationsDoNotDisturb.label "Do not disturb me">
|
||||
|
@ -91,8 +91,18 @@ both, to better adapt this sentence to their language.
|
||||
|
||||
<!ENTITY signedIn.engines.label "Sync across all devices">
|
||||
|
||||
<!ENTITY mobilePromo.start "Download Firefox for ">
|
||||
<!-- LOCALIZATION NOTE (mobilePromo.androidLink): This is a link title that links to https://www.mozilla.org/firefox/android/ -->
|
||||
<!ENTITY mobilePromo.androidLink "Android™">
|
||||
<!ENTITY mobilePromo.end " to sync with your mobile device.">
|
||||
<!ENTITY androidAttribution "Android is a trademark of Google Inc.">
|
||||
<!-- LOCALIZATION NOTE (mobilePromo2.*): the following strings will be used to
|
||||
create a single sentence with active links.
|
||||
The resulting sentence in English is: "Sync to your mobile device.
|
||||
Download Firefox for Android or Firefox for iOS." -->
|
||||
|
||||
<!ENTITY mobilePromo2.start "Sync to your mobile device. Download ">
|
||||
<!-- LOCALIZATION NOTE (mobilePromo2.androidLink): This is a link title that links to https://www.mozilla.org/firefox/android/ -->
|
||||
<!ENTITY mobilePromo2.androidLink "Firefox for Android">
|
||||
|
||||
<!-- LOCALIZATION NOTE (mobilePromo2.iOSBefore): This is text displayed between mobilePromo2.androidLink and mobilePromo2.iosLink -->
|
||||
<!ENTITY mobilePromo2.iOSBefore " or ">
|
||||
<!-- LOCALIZATION NOTE (mobilePromo2.iOSLink): This is a link title that links to https://www.mozilla.org/firefox/ios/ -->
|
||||
<!ENTITY mobilePromo2.iOSLink "Firefox for iOS">
|
||||
|
||||
<!ENTITY mobilePromo2.end ".">
|
||||
|
@ -22,6 +22,8 @@ XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
|
||||
"resource://gre/modules/NetUtil.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "NewTabUtils",
|
||||
"resource://gre/modules/NewTabUtils.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "PlacesTestUtils",
|
||||
"resource://testing-common/PlacesTestUtils.jsm");
|
||||
|
||||
do_get_profile();
|
||||
|
||||
@ -1687,8 +1689,7 @@ add_task(function test_DirectoryLinksProvider_ClickRemoval() {
|
||||
|
||||
testObserver = new UrlDeletionTester();
|
||||
DirectoryLinksProvider.addObserver(testObserver);
|
||||
// remove all hostory
|
||||
PlacesUtils.bhistory.removeAllPages();
|
||||
yield PlacesTestUtils.clearHistory();
|
||||
|
||||
yield testObserver.promise;
|
||||
DirectoryLinksProvider.removeObserver(testObserver);
|
||||
|
@ -2,71 +2,97 @@
|
||||
* 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/. */
|
||||
|
||||
|
||||
html {
|
||||
background: -moz-Dialog;
|
||||
}
|
||||
@import url("chrome://global/skin/in-content/common.css");
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0 1em;
|
||||
color: -moz-FieldText;
|
||||
font: message-box;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin: 0 0 .6em 0;
|
||||
border-bottom: 1px solid ThreeDLightShadow;
|
||||
font-size: 160%;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 130%;
|
||||
display: flex;
|
||||
box-sizing: border-box;
|
||||
min-height: 100vh;
|
||||
padding: 0 48px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
#errorPageContainer {
|
||||
position: relative;
|
||||
min-width: 13em;
|
||||
max-width: 52em;
|
||||
margin: 4em auto;
|
||||
border: 1px solid #FFBD09; /* pale yellow extracted from yellow passport icon */
|
||||
border-radius: 10px;
|
||||
padding: 3em;
|
||||
-moz-padding-start: 30px;
|
||||
background: url("chrome://global/skin/icons/sslWarning.png") left 0 no-repeat -moz-Field;
|
||||
background-origin: content-box;
|
||||
}
|
||||
|
||||
#errorPageContainer:-moz-dir(rtl) {
|
||||
background-position: right 0;
|
||||
min-width: 320px;
|
||||
max-width: 512px;
|
||||
}
|
||||
|
||||
#errorTitle {
|
||||
-moz-margin-start: 80px;
|
||||
background: url("chrome://browser/skin/cert-error.svg") left 0 no-repeat;
|
||||
background-size: 3em;
|
||||
margin-inline-start: -5em;
|
||||
padding-inline-start: 5em;
|
||||
}
|
||||
|
||||
#errorLongContent {
|
||||
-moz-margin-start: 80px;
|
||||
#errorTitle:-moz-dir(rtl) {
|
||||
background-position: right 0;
|
||||
}
|
||||
|
||||
.expander > button {
|
||||
-moz-padding-start: 20px;
|
||||
-moz-margin-start: -20px;
|
||||
background: url("chrome://browser/skin/aboutCertError_sectionExpanded.png") left center no-repeat;
|
||||
border: none;
|
||||
font: inherit;
|
||||
color: inherit;
|
||||
#errorTitleText {
|
||||
border-bottom: 1px solid #C1C1C1;
|
||||
padding-bottom: 0.4em;
|
||||
}
|
||||
|
||||
@media (max-width: 675px) {
|
||||
#errorTitle {
|
||||
padding-top: 0;
|
||||
background-image: none;
|
||||
margin-inline-start: 0;
|
||||
padding-inline-start: 0;
|
||||
}
|
||||
}
|
||||
|
||||
#buttonContainer {
|
||||
display: flex;
|
||||
flex-flow: row wrap;
|
||||
}
|
||||
|
||||
#buttonSpacer {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
/* Pressing the retry button will cause the cursor to flicker from a pointer to
|
||||
* not-allowed. Override the disabled cursor behaviour since we will never show
|
||||
* the button disabled as the initial state. Remove this in Bug 1219861. */
|
||||
button:disabled {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.expander > button:-moz-dir(rtl) {
|
||||
background-position: right center;
|
||||
#returnButton {
|
||||
background-color: var(--in-content-primary-button-background);
|
||||
border: none;
|
||||
color: var(--in-content-selected-text);
|
||||
min-width: 250px;
|
||||
margin-inline-start: 0;
|
||||
}
|
||||
|
||||
.expander[collapsed] > button {
|
||||
background-image: url("chrome://browser/skin/aboutCertError_sectionCollapsed.png");
|
||||
#returnButton:hover {
|
||||
background-color: var(--in-content-primary-button-background-hover) !important;
|
||||
}
|
||||
|
||||
.expander[collapsed] > button:-moz-dir(rtl) {
|
||||
background-image: url("chrome://browser/skin/aboutCertError_sectionCollapsed-rtl.png");
|
||||
#returnButton:hover:active {
|
||||
background-color: var(--in-content-primary-button-background-active) !important;
|
||||
}
|
||||
|
||||
#advancedButton {
|
||||
min-width: 150px;
|
||||
}
|
||||
|
||||
/* Advanced section is hidden via inline styles until the link is clicked */
|
||||
#advancedPanel {
|
||||
background-color: white;
|
||||
color: var(--in-content-text-color);
|
||||
border: 1px lightgray solid;
|
||||
/* Don't use top padding because the default p style has top padding, and it
|
||||
* makes the overall div look uneven */
|
||||
padding: 0 12px 10px;
|
||||
margin-top: 10px;
|
||||
box-shadow: 0 0 4px #ddd;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
.hostname {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
43
browser/themes/shared/incontent-icons/cert-error.svg
Normal file
43
browser/themes/shared/incontent-icons/cert-error.svg
Normal file
@ -0,0 +1,43 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
|
||||
<svg version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
width="45"
|
||||
height="45"
|
||||
viewBox="0 0 45 45">
|
||||
|
||||
<style>
|
||||
.icon-default {
|
||||
fill: #999;
|
||||
}
|
||||
</style>
|
||||
|
||||
<defs>
|
||||
<rect id="shape-lock-clasp-outer" x="8" y="2" width="28" height="40" rx="14" ry="14" />
|
||||
<rect id="shape-lock-clasp-inner" x="14" y="8" width="16" height="28" rx="8" ry="8" />
|
||||
<rect id="shape-lock-base" x="4" y="18" width="36" height="24" rx="3" ry="3" />
|
||||
|
||||
<mask id="mask-clasp-cutout">
|
||||
<rect width="48" height="48" fill="#000" />
|
||||
<use xlink:href="#shape-lock-clasp-outer" fill="#fff" />
|
||||
<use xlink:href="#shape-lock-clasp-inner" fill="#000" />
|
||||
<line x1="4" y1="38" x2="41" y2="3" stroke="#000" stroke-width="5.5" />
|
||||
<line x1="4" y1="46" x2="41" y2="11" stroke="#000" stroke-width="5.5" />
|
||||
<rect x="4" y="18" width="36" height="26" rx="6" ry="6" />
|
||||
</mask>
|
||||
|
||||
<mask id="mask-base-cutout">
|
||||
<rect width="45" height="45" fill="#000" />
|
||||
<use xlink:href="#shape-lock-base" fill="#fff" />
|
||||
<line x1="2.5" y1="41.5" x2="41" y2="5" stroke="#000" stroke-width="8.5" />
|
||||
</mask>
|
||||
</defs>
|
||||
|
||||
<use xlink:href="#shape-lock-clasp-outer" mask="url(#mask-clasp-cutout)" fill="#999" />
|
||||
<use xlink:href="#shape-lock-base" mask="url(#mask-base-cutout)" fill="#999" />
|
||||
|
||||
<line x1="2.5" y1="41.5" x2="41" y2="5" stroke="#d92d21" stroke-width="5.5" />
|
||||
|
||||
</svg>
|
After Width: | Height: | Size: 1.6 KiB |
@ -171,6 +171,10 @@ treecol {
|
||||
margin-right: 4px !important;
|
||||
}
|
||||
|
||||
#notificationsPolicyLearnMore {
|
||||
-moz-margin-start: 1.5em !important;
|
||||
}
|
||||
|
||||
#defaultFontSizeLabel {
|
||||
/* !important needed to override common !important rule */
|
||||
-moz-margin-start: 4px !important;
|
||||
@ -620,8 +624,7 @@ description > html|a {
|
||||
}
|
||||
|
||||
.fxaMobilePromo {
|
||||
margin-top: 14px;
|
||||
margin-bottom: 41px;
|
||||
margin-bottom: 31px;
|
||||
}
|
||||
|
||||
#fxaLoginRejectedWarning {
|
||||
@ -634,28 +637,16 @@ description > html|a {
|
||||
margin-bottom: 27.5px;
|
||||
}
|
||||
|
||||
.androidLogo {
|
||||
list-style-image: url(chrome://browser/skin/fxa/android.png);
|
||||
max-width: 24px;
|
||||
position: relative;
|
||||
top: 8px;
|
||||
margin: 0px;
|
||||
margin-inline-end: 5px;
|
||||
}
|
||||
|
||||
.androidLink {
|
||||
.androidLink,
|
||||
.iOSLink {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#tosPP-small {
|
||||
margin-top: 20px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.androidAttribution {
|
||||
font-size: 12px;
|
||||
color: #D1D2D3;
|
||||
}
|
||||
|
||||
@media (min-resolution: 1.1dppx) {
|
||||
.fxaSyncIllustration {
|
||||
list-style-image: url(chrome://browser/skin/fxa/sync-illustration@2x.png)
|
||||
@ -663,9 +654,6 @@ description > html|a {
|
||||
.fxaFirefoxLogo {
|
||||
list-style-image: url(chrome://browser/skin/fxa/logo@2x.png);
|
||||
}
|
||||
.androidLogo {
|
||||
list-style-image: url(chrome://browser/skin/fxa/android@2x.png);
|
||||
}
|
||||
#fxaProfileImage {
|
||||
list-style-image: url(chrome://browser/skin/fxa/default-avatar@2x.png);
|
||||
}
|
||||
|
@ -114,6 +114,7 @@
|
||||
skin/classic/browser/urlbar-arrow.png (../shared/urlbar-arrow.png)
|
||||
skin/classic/browser/urlbar-arrow@2x.png (../shared/urlbar-arrow@2x.png)
|
||||
skin/classic/browser/warning.svg (../shared/warning.svg)
|
||||
skin/classic/browser/cert-error.svg (../shared/incontent-icons/cert-error.svg)
|
||||
skin/classic/browser/session-restore.svg (../shared/incontent-icons/session-restore.svg)
|
||||
skin/classic/browser/tab-crashed.svg (../shared/incontent-icons/tab-crashed.svg)
|
||||
skin/classic/browser/welcome-back.svg (../shared/incontent-icons/welcome-back.svg)
|
||||
|
@ -102,11 +102,12 @@ idea {
|
||||
// Exclude them. Convention is that object directories start with obj.
|
||||
// IntelliJ is clever and will not exclude the parts of the object
|
||||
// directory that are referenced, if there are any.
|
||||
// In practice, indexing the entirety of the tree is taking too long.
|
||||
def topsrcdirURI = file(topsrcdir).toURI()
|
||||
excludeDirs += files(file(topsrcdir)
|
||||
.listFiles({it.isDirectory()} as FileFilter)
|
||||
.collect({topsrcdirURI.relativize(it.toURI()).toString()}) // Relative paths.
|
||||
.findAll({it.startsWith('obj')}))
|
||||
.findAll({it.startsWith('obj') && !it.startsWith('.') && !it.equals('mobile/')}))
|
||||
|
||||
// If topobjdir is below topsrcdir, hide only some portions of that tree.
|
||||
def topobjdirURI = file(topobjdir).toURI()
|
||||
|
@ -17,6 +17,8 @@ loader.lazyRequireGetter(this, "DebuggerClient",
|
||||
"devtools/shared/client/main", true);
|
||||
loader.lazyRequireGetter(this, "DebuggerServer",
|
||||
"devtools/server/main", true);
|
||||
loader.lazyRequireGetter(this, "Telemetry",
|
||||
"devtools/client/shared/telemetry");
|
||||
loader.lazyRequireGetter(this, "WorkersComponent",
|
||||
"devtools/client/aboutdebugging/components/workers", true);
|
||||
loader.lazyRequireGetter(this, "Services");
|
||||
@ -56,6 +58,9 @@ var AboutDebugging = {
|
||||
},
|
||||
|
||||
init() {
|
||||
let telemetry = this._telemetry = new Telemetry();
|
||||
telemetry.toolOpened("aboutdebugging");
|
||||
|
||||
// Show the first available tab.
|
||||
this.showTab();
|
||||
window.addEventListener("hashchange", () => this.showTab());
|
||||
@ -89,9 +94,20 @@ var AboutDebugging = {
|
||||
document.querySelector("#workers"));
|
||||
});
|
||||
},
|
||||
|
||||
destroy() {
|
||||
let telemetry = this._telemetry;
|
||||
telemetry.toolClosed("aboutdebugging");
|
||||
telemetry.destroy();
|
||||
},
|
||||
};
|
||||
|
||||
window.addEventListener("DOMContentLoaded", function load() {
|
||||
window.removeEventListener("DOMContentLoaded", load);
|
||||
AboutDebugging.init();
|
||||
});
|
||||
|
||||
window.addEventListener("unload", function unload() {
|
||||
window.removeEventListener("unload", unload);
|
||||
AboutDebugging.destroy();
|
||||
});
|
||||
|
@ -12,6 +12,12 @@
|
||||
// rate changed have a delay = delay/rate and a duration = duration/rate.
|
||||
|
||||
add_task(function*() {
|
||||
yield new Promise(resolve => {
|
||||
SpecialPowers.pushPrefEnv({"set": [
|
||||
["dom.animations-api.core.enabled", true]
|
||||
]}, resolve);
|
||||
});
|
||||
|
||||
yield addTab(TEST_URL_ROOT + "doc_modify_playbackRate.html");
|
||||
|
||||
let {panel} = yield openAnimationInspector();
|
||||
|
@ -33,7 +33,7 @@ var ArrayRep = React.createClass({
|
||||
var items;
|
||||
|
||||
if (mode == "tiny") {
|
||||
items = object.length;
|
||||
items = DOM.span({className: "length"}, object.length);
|
||||
} else {
|
||||
var max = (mode == "short") ? 3 : 300;
|
||||
items = this.arrayIterator(object, max);
|
||||
|
@ -44,7 +44,8 @@
|
||||
.objectBox-number,
|
||||
.objectLink-styleRule,
|
||||
.objectLink-element,
|
||||
.objectLink-textNode {
|
||||
.objectLink-textNode,
|
||||
.objectBox-array > .length {
|
||||
color: #000088;
|
||||
}
|
||||
|
||||
@ -54,7 +55,7 @@
|
||||
|
||||
.objectLink-function,
|
||||
.objectBox-stackTrace,
|
||||
.objectLink-profile {
|
||||
.objectLink-profile {
|
||||
color: DarkGreen;
|
||||
}
|
||||
|
||||
@ -177,6 +178,8 @@
|
||||
color: var(--theme-highlight-bluegrey);
|
||||
}
|
||||
|
||||
.theme-dark .objectBox-array .length,
|
||||
.theme-light .objectBox-array .length,
|
||||
.theme-dark .objectBox-number,
|
||||
.theme-light .objectBox-number {
|
||||
color: var(--theme-highlight-green);
|
||||
@ -184,7 +187,7 @@
|
||||
|
||||
.theme-dark .objectBox-string,
|
||||
.theme-light .objectBox-string {
|
||||
color: var(--theme-highlight-orange)
|
||||
color: var(--theme-highlight-orange);
|
||||
}
|
||||
|
||||
.theme-dark .objectBox-null,
|
||||
@ -195,6 +198,11 @@
|
||||
color: var(--theme-comment);
|
||||
}
|
||||
|
||||
.theme-dark .objectBox-array,
|
||||
.theme-light .objectBox-array {
|
||||
color: var(--theme-body-color);
|
||||
}
|
||||
|
||||
.theme-dark .objectBox-object,
|
||||
.theme-light .objectBox-object {
|
||||
font-family: Lucida Grande, sans-serif;
|
||||
|
@ -7,7 +7,7 @@
|
||||
define(function(require, exports, module) {
|
||||
|
||||
// ReactJS
|
||||
const React = require("react");
|
||||
const ReactDOM = require("react-dom");
|
||||
|
||||
// RDP Inspector
|
||||
const { createFactories } = require("./components/reps/rep-utils");
|
||||
@ -79,7 +79,7 @@ input.actions = {
|
||||
* at the top of the window. This component also represents ReacJS root.
|
||||
*/
|
||||
var content = document.getElementById("content");
|
||||
var theApp = React.render(MainTabbedArea(input), content);
|
||||
var theApp = ReactDOM.render(MainTabbedArea(input), content);
|
||||
|
||||
var onResize = event => {
|
||||
window.document.body.style.height = window.innerHeight + "px";
|
||||
|
@ -23,7 +23,8 @@ require.config({
|
||||
"react": [
|
||||
"resource://devtools/client/shared/vendor/react-dev",
|
||||
"resource://devtools/client/shared/vendor/react"
|
||||
]
|
||||
],
|
||||
"react-dom": "resource://devtools/client/shared/vendor/react-dom"
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -3,8 +3,7 @@
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
const { DOM: dom, createClass, PropTypes } = require("devtools/client/shared/vendor/react");
|
||||
const { L10N } = require("../utils");
|
||||
const { URL } = require("sdk/url");
|
||||
const { L10N, parseSource } = require("../utils");
|
||||
|
||||
const Frame = module.exports = createClass({
|
||||
displayName: "frame-view",
|
||||
@ -16,25 +15,24 @@ const Frame = module.exports = createClass({
|
||||
|
||||
render() {
|
||||
let { toolbox, frame } = this.props;
|
||||
const { short, long, host } = parseSource(frame.source);
|
||||
|
||||
let url = new URL(frame.source);
|
||||
let spec = url.toString();
|
||||
let func = frame.functionDisplayName || "";
|
||||
let tooltip = `${func} (${spec}:${frame.line}:${frame.column})`;
|
||||
let viewTooltip = L10N.getFormatStr("viewsourceindebugger", `${spec}:${frame.line}:${frame.column}`);
|
||||
let onClick = () => toolbox.viewSourceInDebugger(spec, frame.line);
|
||||
let tooltip = `${func} (${long}:${frame.line}:${frame.column})`;
|
||||
let viewTooltip = L10N.getFormatStr("viewsourceindebugger", `${long}:${frame.line}:${frame.column}`);
|
||||
let onClick = () => toolbox.viewSourceInDebugger(long, frame.line);
|
||||
|
||||
let fields = [
|
||||
dom.span({ className: "frame-link-function-display-name" }, func),
|
||||
dom.a({ className: "frame-link-filename", onClick, title: viewTooltip }, url.fileName),
|
||||
dom.a({ className: "frame-link-filename", onClick, title: viewTooltip }, short),
|
||||
dom.span({ className: "frame-link-colon" }, ":"),
|
||||
dom.span({ className: "frame-link-line" }, frame.line),
|
||||
dom.span({ className: "frame-link-colon" }, ":"),
|
||||
dom.span({ className: "frame-link-column" }, frame.column)
|
||||
];
|
||||
|
||||
if (url.scheme === "http" || url.scheme === "https" || url.scheme === "ftp") {
|
||||
fields.push(dom.span({ className: "frame-link-host" }, url.host));
|
||||
if (host) {
|
||||
fields.push(dom.span({ className: "frame-link-host" }, host));
|
||||
}
|
||||
|
||||
return dom.span({ className: "frame-link", title: tooltip }, ...fields);
|
||||
|
@ -6,7 +6,7 @@ const { DOM: dom, createClass, PropTypes, createFactory } = require("devtools/cl
|
||||
const { safeErrorString } = require("devtools/shared/DevToolsUtils");
|
||||
const Tree = createFactory(require("./tree"));
|
||||
const TreeItem = createFactory(require("./tree-item"));
|
||||
const { getSnapshotStatusTextFull, L10N } = require("../utils");
|
||||
const { getSnapshotStatusTextFull, getSnapshotTotals, L10N } = require("../utils");
|
||||
const { snapshotState: states } = require("../constants");
|
||||
const { snapshot: snapshotModel } = require("../models");
|
||||
// If HEAP_TREE_ROW_HEIGHT changes, be sure to change `var(--heap-tree-row-height)`
|
||||
@ -36,13 +36,27 @@ function createParentMap (node, aggregator=Object.create(null)) {
|
||||
* @param {CensusTreeNode} census
|
||||
* @return {Object}
|
||||
*/
|
||||
function createTreeProperties (census, toolbox) {
|
||||
function createTreeProperties (snapshot, toolbox) {
|
||||
const census = snapshot.census;
|
||||
let map = createParentMap(census);
|
||||
const totals = getSnapshotTotals(snapshot);
|
||||
|
||||
return {
|
||||
getParent: node => map[node.id],
|
||||
getParent: node => {
|
||||
const parent = map[node.id];
|
||||
return parent === census ? null : parent;
|
||||
},
|
||||
getChildren: node => node.children || [],
|
||||
renderItem: (item, depth, focused, arrow) => new TreeItem({ toolbox, item, depth, focused, arrow }),
|
||||
renderItem: (item, depth, focused, arrow) =>
|
||||
new TreeItem({
|
||||
toolbox,
|
||||
item,
|
||||
depth,
|
||||
focused,
|
||||
arrow,
|
||||
getPercentBytes: bytes => bytes / totals.bytes * 100,
|
||||
getPercentCount: count => count / totals.count * 100,
|
||||
}),
|
||||
getRoots: () => census.children,
|
||||
getKey: node => node.id,
|
||||
itemHeight: HEAP_TREE_ROW_HEIGHT,
|
||||
@ -115,7 +129,7 @@ const Heap = module.exports = createClass({
|
||||
dom.span({ className: "heap-tree-item-total-count" }, L10N.getStr("heapview.field.totalcount")),
|
||||
dom.span({ className: "heap-tree-item-name" }, L10N.getStr("heapview.field.name"))
|
||||
),
|
||||
Tree(createTreeProperties(snapshot.census, toolbox))
|
||||
Tree(createTreeProperties(snapshot, toolbox))
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
@ -44,4 +44,3 @@ const SnapshotListItem = module.exports = createClass({
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -16,6 +16,7 @@ depth.
|
||||
<script type="application/javascript;version=1.8">
|
||||
window.onload = Task.async(function* () {
|
||||
try {
|
||||
let ReactDOM = bRequire("devtools/client/shared/vendor/react-dom");
|
||||
let React = bRequire("devtools/client/shared/vendor/react");
|
||||
let Tree = React.createFactory(bRequire("devtools/client/memory/components/tree"));
|
||||
|
||||
@ -25,7 +26,7 @@ window.onload = Task.async(function* () {
|
||||
const t = Tree(TEST_TREE_INTERFACE);
|
||||
ok(t, "Should be able to create Tree instances");
|
||||
|
||||
const tree = React.render(t, window.document.body);
|
||||
const tree = ReactDOM.render(t, window.document.body);
|
||||
ok(tree, "Should be able to mount Tree instances");
|
||||
|
||||
yield setState(tree, {
|
||||
|
@ -15,10 +15,11 @@ Test that collapsed subtrees aren't rendered.
|
||||
<script type="application/javascript;version=1.8">
|
||||
window.onload = Task.async(function* () {
|
||||
try {
|
||||
let ReactDOM = bRequire("devtools/client/shared/vendor/react-dom");
|
||||
let React = bRequire("devtools/client/shared/vendor/react");
|
||||
let Tree = React.createFactory(bRequire("devtools/client/memory/components/tree"));
|
||||
|
||||
const tree = React.render(Tree(TEST_TREE_INTERFACE), window.document.body);
|
||||
const tree = ReactDOM.render(Tree(TEST_TREE_INTERFACE), window.document.body);
|
||||
|
||||
yield setState(tree, {
|
||||
expanded: new Set("MNO".split(""))
|
||||
|
@ -15,10 +15,11 @@ Test Tree's autoExpandDepth.
|
||||
<script type="application/javascript;version=1.8">
|
||||
window.onload = Task.async(function* () {
|
||||
try {
|
||||
let ReactDOM = bRequire("devtools/client/shared/vendor/react-dom");
|
||||
let React = bRequire("devtools/client/shared/vendor/react");
|
||||
let Tree = React.createFactory(bRequire("devtools/client/memory/components/tree"));
|
||||
|
||||
const tree = React.render(Tree(TEST_TREE_INTERFACE), window.document.body);
|
||||
const tree = ReactDOM.render(Tree(TEST_TREE_INTERFACE), window.document.body);
|
||||
|
||||
yield setProps(tree, {
|
||||
autoExpandDepth: 1
|
||||
|
@ -15,9 +15,10 @@ Test that we only render visible tree items.
|
||||
<script type="application/javascript;version=1.8">
|
||||
window.onload = Task.async(function* () {
|
||||
try {
|
||||
const ReactDOM = bRequire("devtools/client/shared/vendor/react-dom");
|
||||
const React = bRequire("devtools/client/shared/vendor/react");
|
||||
const Tree = React.createFactory(bRequire("devtools/client/memory/components/tree"));
|
||||
const tree = React.render(Tree(TEST_TREE_INTERFACE), window.document.body);
|
||||
const tree = ReactDOM.render(Tree(TEST_TREE_INTERFACE), window.document.body);
|
||||
|
||||
yield setState(tree, {
|
||||
expanded: new Set("ABCDEFGHIJKLMNO".split("")),
|
||||
|
@ -16,10 +16,11 @@ Test focusing with the Tree component.
|
||||
|
||||
window.onload = Task.async(function* () {
|
||||
try {
|
||||
const ReactDOM = bRequire("devtools/client/shared/vendor/react-dom");
|
||||
const React = bRequire("devtools/client/shared/vendor/react");
|
||||
const { Simulate } = React.addons.TestUtils;
|
||||
const Tree = React.createFactory(bRequire("devtools/client/memory/components/tree"));
|
||||
const tree = React.render(Tree(TEST_TREE_INTERFACE), window.document.body);
|
||||
const tree = ReactDOM.render(Tree(TEST_TREE_INTERFACE), window.document.body);
|
||||
|
||||
yield setState(tree, {
|
||||
focused: "G",
|
||||
|
@ -15,10 +15,11 @@ Test keyboard navigation with the Tree component.
|
||||
<script type="application/javascript;version=1.8">
|
||||
window.onload = Task.async(function* () {
|
||||
try {
|
||||
const ReactDOM = bRequire("devtools/client/shared/vendor/react-dom");
|
||||
const React = bRequire("devtools/client/shared/vendor/react");
|
||||
const { Simulate } = React.addons.TestUtils;
|
||||
const Tree = React.createFactory(bRequire("devtools/client/memory/components/tree"));
|
||||
const tree = React.render(Tree(TEST_TREE_INTERFACE), window.document.body);
|
||||
const tree = ReactDOM.render(Tree(TEST_TREE_INTERFACE), window.document.body);
|
||||
|
||||
yield setState(tree, {
|
||||
expanded: new Set("ABCDEFGHIJKLMNO".split(""))
|
||||
|
@ -16,9 +16,10 @@ Test that arrows get the open attribute when their item's children are expanded.
|
||||
<script type="application/javascript;version=1.8">
|
||||
window.onload = Task.async(function* () {
|
||||
try {
|
||||
const ReactDOM = bRequire("devtools/client/shared/vendor/react-dom");
|
||||
const React = bRequire("devtools/client/shared/vendor/react");
|
||||
const Tree = React.createFactory(bRequire("devtools/client/memory/components/tree"));
|
||||
const tree = React.render(Tree(TEST_TREE_INTERFACE), window.document.body);
|
||||
const tree = ReactDOM.render(Tree(TEST_TREE_INTERFACE), window.document.body);
|
||||
|
||||
yield setProps(tree, {
|
||||
renderItem: (item, depth, focused, arrow) => {
|
||||
|
@ -17,10 +17,11 @@ other inputs.
|
||||
<script type="application/javascript;version=1.8">
|
||||
window.onload = Task.async(function* () {
|
||||
try {
|
||||
const ReactDOM = bRequire("devtools/client/shared/vendor/react-dom");
|
||||
const React = bRequire("devtools/client/shared/vendor/react");
|
||||
const { Simulate } = React.addons.TestUtils;
|
||||
const Tree = React.createFactory(bRequire("devtools/client/memory/components/tree"));
|
||||
const tree = React.render(Tree(TEST_TREE_INTERFACE), window.document.body);
|
||||
const tree = ReactDOM.render(Tree(TEST_TREE_INTERFACE), window.document.body);
|
||||
|
||||
const input = document.createElement("input");
|
||||
document.body.appendChild(input);
|
||||
|
@ -40,33 +40,35 @@ const Toolbar = module.exports = createClass({
|
||||
title: L10N.getStr("take-snapshot")
|
||||
}),
|
||||
|
||||
dom.label({},
|
||||
L10N.getStr("toolbar.breakdownBy"),
|
||||
dom.select({
|
||||
id: "select-breakdown",
|
||||
className: `select-breakdown`,
|
||||
onChange: e => onBreakdownChange(e.target.value),
|
||||
}, ...breakdowns.map(({ name, displayName }) => dom.option({ key: name, value: name }, displayName)))
|
||||
),
|
||||
dom.div({ className: "toolbar-group" },
|
||||
dom.label({ className: "breakdown-by" },
|
||||
L10N.getStr("toolbar.breakdownBy"),
|
||||
dom.select({
|
||||
id: "select-breakdown",
|
||||
className: `select-breakdown`,
|
||||
onChange: e => onBreakdownChange(e.target.value),
|
||||
}, ...breakdowns.map(({ name, displayName }) => dom.option({ key: name, value: name }, displayName)))
|
||||
),
|
||||
|
||||
dom.label({},
|
||||
dom.input({
|
||||
id: "invert-tree-checkbox",
|
||||
type: "checkbox",
|
||||
checked: inverted,
|
||||
onChange: onToggleInverted,
|
||||
}),
|
||||
L10N.getStr("checkbox.invertTree")
|
||||
),
|
||||
dom.label({},
|
||||
dom.input({
|
||||
id: "invert-tree-checkbox",
|
||||
type: "checkbox",
|
||||
checked: inverted,
|
||||
onChange: onToggleInverted,
|
||||
}),
|
||||
L10N.getStr("checkbox.invertTree")
|
||||
),
|
||||
|
||||
dom.label({},
|
||||
dom.input({
|
||||
type: "checkbox",
|
||||
checked: allocations.recording,
|
||||
disabled: allocations.togglingInProgress,
|
||||
onChange: onToggleRecordAllocationStacks,
|
||||
}),
|
||||
L10N.getStr("checkbox.recordAllocationStacks")
|
||||
dom.label({},
|
||||
dom.input({
|
||||
type: "checkbox",
|
||||
checked: allocations.recording,
|
||||
disabled: allocations.togglingInProgress,
|
||||
onChange: onToggleRecordAllocationStacks,
|
||||
}),
|
||||
L10N.getStr("checkbox.recordAllocationStacks")
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
@ -18,14 +18,39 @@ const MAX_SOURCE_LENGTH = 200;
|
||||
const TreeItem = module.exports = createClass({
|
||||
displayName: "tree-item",
|
||||
|
||||
formatPercent(percent) {
|
||||
return L10N.getFormatStr("tree-item.percent", Math.round(percent));
|
||||
},
|
||||
|
||||
render() {
|
||||
let { item, depth, arrow, focused, toolbox } = this.props;
|
||||
let {
|
||||
item,
|
||||
depth,
|
||||
arrow,
|
||||
focused,
|
||||
toolbox,
|
||||
getPercentBytes,
|
||||
getPercentCount,
|
||||
} = this.props;
|
||||
|
||||
const percentBytes = this.formatPercent(getPercentBytes(item.bytes));
|
||||
const percentCount = this.formatPercent(getPercentCount(item.count));
|
||||
const percentTotalBytes = this.formatPercent(getPercentBytes(item.totalBytes));
|
||||
const percentTotalCount = this.formatPercent(getPercentBytes(item.totalCount));
|
||||
|
||||
return dom.div({ className: `heap-tree-item ${focused ? "focused" :""}` },
|
||||
dom.span({ className: "heap-tree-item-field heap-tree-item-bytes" }, item.bytes),
|
||||
dom.span({ className: "heap-tree-item-field heap-tree-item-count" }, item.count),
|
||||
dom.span({ className: "heap-tree-item-field heap-tree-item-total-bytes" }, item.totalBytes),
|
||||
dom.span({ className: "heap-tree-item-field heap-tree-item-total-count" }, item.totalCount),
|
||||
dom.span({ className: "heap-tree-item-field heap-tree-item-bytes" },
|
||||
dom.span({ className: "heap-tree-number" }, item.bytes),
|
||||
dom.span({ className: "heap-tree-percent" }, percentBytes)),
|
||||
dom.span({ className: "heap-tree-item-field heap-tree-item-count" },
|
||||
dom.span({ className: "heap-tree-number" }, item.count),
|
||||
dom.span({ className: "heap-tree-percent" }, percentCount)),
|
||||
dom.span({ className: "heap-tree-item-field heap-tree-item-total-bytes" },
|
||||
dom.span({ className: "heap-tree-number" }, item.totalBytes),
|
||||
dom.span({ className: "heap-tree-percent" }, percentTotalBytes)),
|
||||
dom.span({ className: "heap-tree-item-field heap-tree-item-total-count" },
|
||||
dom.span({ className: "heap-tree-number" }, item.totalCount),
|
||||
dom.span({ className: "heap-tree-percent" }, percentTotalCount)),
|
||||
dom.span({ className: "heap-tree-item-field heap-tree-item-name", style: { marginLeft: depth * INDENT }},
|
||||
arrow,
|
||||
this.toLabel(item.name, toolbox)
|
||||
|
@ -51,7 +51,7 @@ const breakdowns = exports.breakdowns = {
|
||||
displayName: "Coarse Type",
|
||||
breakdown: {
|
||||
by: "coarseType",
|
||||
objects: ALLOCATION_STACK,
|
||||
objects: OBJECT_CLASS,
|
||||
strings: COUNT,
|
||||
scripts: INTERNAL_TYPE,
|
||||
other: INTERNAL_TYPE,
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user