зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to b2g-inbound
This commit is contained in:
Коммит
01f93d64ea
|
@ -17,7 +17,7 @@
|
|||
#include "nsIChannel.h"
|
||||
#include "nsIInterfaceRequestorUtils.h"
|
||||
#include "nsISelectionPrivate.h"
|
||||
#include "nsTraceRefcntImpl.h"
|
||||
#include "nsTraceRefcnt.h"
|
||||
#include "nsIWebProgress.h"
|
||||
#include "prenv.h"
|
||||
#include "nsIDocShellTreeItem.h"
|
||||
|
@ -800,7 +800,7 @@ logging::Stack()
|
|||
{
|
||||
if (IsEnabled(eStack)) {
|
||||
printf(" stack: \n");
|
||||
nsTraceRefcntImpl::WalkTheStack(stdout);
|
||||
nsTraceRefcnt::WalkTheStack(stdout);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -433,6 +433,15 @@ this.Logger = {
|
|||
str += ' (' + stateStrings.item(0) + ')';
|
||||
}
|
||||
|
||||
if (aEvent.eventType == Events.VIRTUALCURSOR_CHANGED) {
|
||||
let event = aEvent.QueryInterface(
|
||||
Ci.nsIAccessibleVirtualCursorChangeEvent);
|
||||
let pivot = aEvent.accessible.QueryInterface(
|
||||
Ci.nsIAccessibleDocument).virtualCursor;
|
||||
str += ' (' + this.accessibleToString(event.oldAccessible) + ' -> ' +
|
||||
this.accessibleToString(pivot.position) + ')';
|
||||
}
|
||||
|
||||
return str;
|
||||
},
|
||||
|
||||
|
|
|
@ -400,6 +400,8 @@ addMessageListener(
|
|||
eventManager = new EventManager(this);
|
||||
}
|
||||
eventManager.start();
|
||||
|
||||
sendAsyncMessage('AccessFu:ContentStarted');
|
||||
});
|
||||
|
||||
addMessageListener(
|
||||
|
|
|
@ -3,8 +3,10 @@ support-files =
|
|||
jsatcommon.js
|
||||
output.js
|
||||
doc_traversal.html
|
||||
doc_content_integration.html
|
||||
|
||||
[test_alive.html]
|
||||
[test_content_integration.html]
|
||||
[test_explicit_names.html]
|
||||
[test_landmarks.html]
|
||||
[test_live_regions.html]
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Traversal Rule test document</title>
|
||||
<meta charset="utf-8" />
|
||||
<script>
|
||||
var frameContents = '<html>' +
|
||||
'<head><title>such app</title></head>' +
|
||||
'<body>' +
|
||||
'<h1>wow</h1>' +
|
||||
'<label><input type="checkbox">many option</label>' +
|
||||
'</body>' +
|
||||
'</html>';
|
||||
|
||||
</script>
|
||||
<style>
|
||||
#windows > iframe {
|
||||
width: 320px;
|
||||
height: 480px;
|
||||
}
|
||||
</style>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div>Phone status bar</div>
|
||||
<div id="windows"></div>
|
||||
<button>Home</button>
|
||||
</body>
|
||||
</html>
|
|
@ -155,3 +155,117 @@ var AccessFuTest = {
|
|||
SpecialPowers.setIntPref("accessibility.accessfu.notify_output", 1);
|
||||
}
|
||||
};
|
||||
|
||||
function AccessFuContentTest(aFuncResultPairs) {
|
||||
this.queue = aFuncResultPairs;
|
||||
}
|
||||
|
||||
AccessFuContentTest.prototype = {
|
||||
currentPair: null,
|
||||
|
||||
start: function(aFinishedCallback) {
|
||||
this.finishedCallback = aFinishedCallback;
|
||||
var self = this;
|
||||
|
||||
// Get top content message manager, and set it up.
|
||||
this.mms = [Utils.getMessageManager(currentBrowser())];
|
||||
this.setupMessageManager(this.mms[0], function () {
|
||||
// Get child message managers and set them up
|
||||
var frames = currentTabDocument().querySelectorAll('iframe');
|
||||
var toSetup = 0;
|
||||
for (var i = 0; i < frames.length; i++ ) {
|
||||
var mm = Utils.getMessageManager(frames[i]);
|
||||
if (mm) {
|
||||
toSetup++;
|
||||
self.mms.push(mm);
|
||||
self.setupMessageManager(mm, function () {
|
||||
if (--toSetup === 0) {
|
||||
// All message managers are loaded and ready to go.
|
||||
self.pump();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
setupMessageManager: function (aMessageManager, aCallback) {
|
||||
function contentScript() {
|
||||
addMessageListener('AccessFuTest:Focus', function (aMessage) {
|
||||
var elem = content.document.querySelector(aMessage.json.selector);
|
||||
if (elem) {
|
||||
if (aMessage.json.blur) {
|
||||
elem.blur();
|
||||
} else {
|
||||
elem.focus();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
aMessageManager.addMessageListener('AccessFu:Present', this);
|
||||
aMessageManager.addMessageListener('AccessFu:Ready', function (aMessage) {
|
||||
aMessageManager.addMessageListener('AccessFu:ContentStarted', aCallback);
|
||||
aMessageManager.sendAsyncMessage('AccessFu:Start', { buildApp: 'browser' });
|
||||
});
|
||||
|
||||
aMessageManager.loadFrameScript(
|
||||
'chrome://global/content/accessibility/content-script.js', false);
|
||||
aMessageManager.loadFrameScript(
|
||||
'data:,(' + contentScript.toString() + ')();', false);
|
||||
},
|
||||
|
||||
pump: function() {
|
||||
this.currentPair = this.queue.shift();
|
||||
|
||||
if (this.currentPair) {
|
||||
if (this.currentPair[0] instanceof Function) {
|
||||
this.currentPair[0](this.mms[0]);
|
||||
} else {
|
||||
this.mms[0].sendAsyncMessage(this.currentPair[0].name,
|
||||
this.currentPair[0].json);
|
||||
}
|
||||
} else if (this.finishedCallback) {
|
||||
for (var mm of this.mms) {
|
||||
mm.sendAsyncMessage('AccessFu:Stop');
|
||||
}
|
||||
this.finishedCallback();
|
||||
}
|
||||
},
|
||||
|
||||
receiveMessage: function(aMessage) {
|
||||
if (!this.currentPair) {
|
||||
return;
|
||||
}
|
||||
|
||||
var expected = this.currentPair[1];
|
||||
|
||||
if (expected) {
|
||||
if (expected.speak !== undefined) {
|
||||
var speech = this.extractUtterance(aMessage.json);
|
||||
if (!speech) {
|
||||
// Probably a visual highlight adjustment after a scroll.
|
||||
return;
|
||||
}
|
||||
var checkFunc = SimpleTest[expected.speak_checkFunc] || is;
|
||||
checkFunc(speech, expected.speak);
|
||||
}
|
||||
}
|
||||
|
||||
this.pump();
|
||||
},
|
||||
|
||||
extractUtterance: function(aData) {
|
||||
for (var output of aData) {
|
||||
if (output && output.type === 'Speech') {
|
||||
for (var action of output.details.actions) {
|
||||
if (action && action.method == 'speak') {
|
||||
return action.data;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -0,0 +1,186 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Tests AccessFu content integration</title>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
|
||||
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js">
|
||||
</script>
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/chrome-harness.js">
|
||||
</script>
|
||||
|
||||
<script type="application/javascript" src="../common.js"></script>
|
||||
<script type="application/javascript" src="../browser.js"></script>
|
||||
<script type="application/javascript" src="../events.js"></script>
|
||||
<script type="application/javascript" src="../role.js"></script>
|
||||
<script type="application/javascript" src="../states.js"></script>
|
||||
<script type="application/javascript" src="../layout.js"></script>
|
||||
<script type="application/javascript" src="jsatcommon.js"></script>
|
||||
|
||||
<script type="application/javascript">
|
||||
function doTest() {
|
||||
var doc = currentTabDocument();
|
||||
var iframe = doc.createElement("iframe");
|
||||
iframe.mozbrowser = true;
|
||||
iframe.addEventListener("mozbrowserloadend", function () {
|
||||
var simpleMoveNext = { name: 'AccessFu:MoveCursor',
|
||||
json: { action: 'moveNext',
|
||||
rule: 'Simple',
|
||||
inputType: 'gesture',
|
||||
origin: 'top' }
|
||||
};
|
||||
|
||||
var simpleMovePrevious = { name: 'AccessFu:MoveCursor',
|
||||
json: { action: 'movePrevious',
|
||||
rule: 'Simple',
|
||||
inputType: 'gesture',
|
||||
origin: 'top' }
|
||||
};
|
||||
|
||||
var activateCurrent = { name: 'AccessFu:Activate',
|
||||
json: { origin: 'top' } };
|
||||
|
||||
var simpleMoveLast = { name: 'AccessFu:MoveCursor',
|
||||
json: { action: 'moveLast',
|
||||
rule: 'Simple',
|
||||
inputType: 'gesture',
|
||||
origin: 'top' }
|
||||
};
|
||||
|
||||
var simpleMoveFirst = { name: 'AccessFu:MoveCursor',
|
||||
json: { action: 'moveFirst',
|
||||
rule: 'Simple',
|
||||
inputType: 'gesture',
|
||||
origin: 'top' }
|
||||
};
|
||||
|
||||
var clearCursor = { name: 'AccessFu:ClearCursor',
|
||||
json: { origin: 'top' }
|
||||
};
|
||||
|
||||
function focusFunc(aSelector, aBlur) {
|
||||
return function (mm) {
|
||||
mm.sendAsyncMessage(
|
||||
'AccessFuTest:Focus', { selector: aSelector, blur: aBlur });
|
||||
};
|
||||
}
|
||||
|
||||
var contentTest = new AccessFuContentTest(
|
||||
[
|
||||
// Simple traversal forward
|
||||
[simpleMoveNext,
|
||||
{ speak: 'Phone status bar Traversal Rule test document' }],
|
||||
[simpleMoveNext,
|
||||
{ speak: 'wow heading level 1 such app' }],
|
||||
[simpleMoveNext,
|
||||
{ speak: 'many option not checked check button' }],
|
||||
// check checkbox
|
||||
[activateCurrent,
|
||||
{ speak: 'checked' }],
|
||||
[null,
|
||||
{ speak: 'checked', speak_checkFunc: 'todo_isnot' }],
|
||||
// uncheck checkbox
|
||||
[simpleMoveNext,
|
||||
{ speak: 'Home button' }],
|
||||
|
||||
// Simple traversal backward
|
||||
[simpleMovePrevious,
|
||||
{ speak: 'many option checked check button such app' }],
|
||||
[activateCurrent,
|
||||
{ speak: 'unchecked' }],
|
||||
[null,
|
||||
{ speak: 'unchecked', speak_checkFunc: 'todo_isnot' }],
|
||||
[simpleMovePrevious,
|
||||
{ speak: 'wow heading level 1' }],
|
||||
[simpleMovePrevious,
|
||||
{ speak: 'Phone status bar' }],
|
||||
|
||||
// Moving to the absolute last item from an embedded document fails.
|
||||
// Bug 972035.
|
||||
[simpleMoveNext,
|
||||
{ speak: 'wow heading level 1 such app' }],
|
||||
// Move from an inner frame to the last element in the parent doc
|
||||
[simpleMoveLast,
|
||||
{ speak: 'Home button', speak_checkFunc: 'todo_is' }],
|
||||
|
||||
[clearCursor, null], // Reset cursors
|
||||
|
||||
// Moving to the absolute first item from an embedded document fails.
|
||||
// Bug 972035.
|
||||
[simpleMoveNext,
|
||||
{ speak: 'Phone status bar Traversal Rule test document' }],
|
||||
[simpleMoveNext,
|
||||
{ speak: 'wow heading level 1 such app' }],
|
||||
[simpleMoveNext,
|
||||
{ speak: 'many option not checked check button' }],
|
||||
[simpleMoveFirst,
|
||||
{ speak: 'Phone status bar', speak_checkFunc: 'todo_is' }],
|
||||
|
||||
// Reset cursors
|
||||
[clearCursor, null],
|
||||
|
||||
// Move cursor with focus in outside document
|
||||
[simpleMoveNext,
|
||||
{ speak: 'Phone status bar Traversal Rule test document' }],
|
||||
[ focusFunc('button', false), { speak: 'Home button' }],
|
||||
|
||||
// Blur button and reset cursor
|
||||
[focusFunc('button', true), null],
|
||||
[clearCursor, null],
|
||||
|
||||
// Set focus on element outside of embedded frame while cursor is in frame
|
||||
[simpleMoveNext,
|
||||
{ speak: 'Phone status bar Traversal Rule test document' }],
|
||||
[simpleMoveNext,
|
||||
{ speak: 'wow heading level 1 such app' }],
|
||||
[focusFunc('button', false), { speak: 'Home button' }]
|
||||
|
||||
// XXX: Set focus on iframe itself.
|
||||
// XXX: Set focus on element in iframe when cursor is outside of it.
|
||||
// XXX: Set focus on element in iframe when cursor is in iframe.
|
||||
]);
|
||||
|
||||
contentTest.start(function () {
|
||||
closeBrowserWindow();
|
||||
SimpleTest.finish();
|
||||
});
|
||||
|
||||
});
|
||||
iframe.src = 'data:text/html;charset=utf-8,' + doc.defaultView.frameContents;
|
||||
doc.querySelector('#windows').appendChild(iframe);
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
addLoadEvent(
|
||||
function () {
|
||||
openBrowserWindow(
|
||||
function () {
|
||||
SpecialPowers.pushPrefEnv({
|
||||
"set": [
|
||||
// TODO: remove this as part of bug 820712
|
||||
["network.disable.ipc.security", true],
|
||||
|
||||
|
||||
["dom.ipc.browser_frames.oop_by_default", true],
|
||||
["dom.mozBrowserFramesEnabled", true],
|
||||
["browser.pagethumbnails.capturing_disabled", true]
|
||||
]
|
||||
}, doTest) },
|
||||
getRootDirectory(window.location.href) + "doc_content_integration.html");
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
<body id="body">
|
||||
|
||||
<a target="_blank"
|
||||
title="Add tests for OOP message handling and general integration"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=972047">Mozilla Bug 933808</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
<pre id="test">
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -26,7 +26,6 @@ LIBS += \
|
|||
-lsuspend \
|
||||
$(NULL)
|
||||
endif
|
||||
OS_LDFLAGS += -Wl,--export-dynamic
|
||||
endif
|
||||
|
||||
STL_FLAGS=
|
||||
|
|
|
@ -39,3 +39,5 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
|
|||
LOCAL_INCLUDES += [
|
||||
'/widget/gonk/libdisplay',
|
||||
]
|
||||
|
||||
LDFLAGS += ['-Wl,--export-dynamic']
|
||||
|
|
|
@ -4,29 +4,36 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
const WIDGET_PANEL_LOG_PREFIX = 'WidgetPanel';
|
||||
const DEVELOPER_HUD_LOG_PREFIX = 'DeveloperHUD';
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, 'devtools', function() {
|
||||
const {devtools} = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
|
||||
return devtools;
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, 'DebuggerClient', function() {
|
||||
return Cu.import('resource://gre/modules/devtools/dbg-client.jsm', {}).DebuggerClient;
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, 'WebConsoleUtils', function() {
|
||||
let {devtools} = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
|
||||
return devtools.require("devtools/toolkit/webconsole/utils").Utils;
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, 'EventLoopLagFront', function() {
|
||||
const {devtools} = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
|
||||
return devtools.require("devtools/server/actors/eventlooplag").EventLoopLagFront;
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, 'MemoryFront', function() {
|
||||
return devtools.require("devtools/server/actors/memory").MemoryFront;
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* The Widget Panel is an on-device developer tool that displays widgets,
|
||||
* The Developer HUD is an on-device developer tool that displays widgets,
|
||||
* showing visual debug information about apps. Each widget corresponds to a
|
||||
* metric as tracked by a metric watcher (e.g. consoleWatcher).
|
||||
*/
|
||||
let devtoolsWidgetPanel = {
|
||||
let developerHUD = {
|
||||
|
||||
_apps: new Map(),
|
||||
_urls: new Map(),
|
||||
|
@ -107,7 +114,7 @@ let devtoolsWidgetPanel = {
|
|||
if (this._apps.has(manifestURL))
|
||||
return;
|
||||
|
||||
// FIXME(Bug 962577) Factor getAppActor and watchApps out of webappsActor.
|
||||
// FIXME(Bug 962577) Factor getAppActor out of webappsActor.
|
||||
this._client.request({
|
||||
to: this._webappsActor,
|
||||
type: 'getAppActor',
|
||||
|
@ -179,7 +186,7 @@ let devtoolsWidgetPanel = {
|
|||
},
|
||||
|
||||
log: function dwp_log(message) {
|
||||
dump(WIDGET_PANEL_LOG_PREFIX + ': ' + message + '\n');
|
||||
dump(DEVELOPER_HUD_LOG_PREFIX + ': ' + message + '\n');
|
||||
}
|
||||
|
||||
};
|
||||
|
@ -208,7 +215,7 @@ App.prototype = {
|
|||
}
|
||||
}
|
||||
|
||||
shell.sendCustomEvent('widget-panel-update', data);
|
||||
shell.sendCustomEvent('developer-hud-update', data);
|
||||
// FIXME(after bug 963239 lands) return event.isDefaultPrevented();
|
||||
return false;
|
||||
}
|
||||
|
@ -238,9 +245,9 @@ let consoleWatcher = {
|
|||
|
||||
for (let key in watching) {
|
||||
let metric = key;
|
||||
SettingsListener.observe('devtools.hud.' + metric, false, value => {
|
||||
SettingsListener.observe('hud.' + metric, false, watch => {
|
||||
// Watch or unwatch the metric.
|
||||
if (watching[metric] = value) {
|
||||
if (watching[metric] = watch) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -356,7 +363,7 @@ let consoleWatcher = {
|
|||
|
||||
if (!app.display()) {
|
||||
// If the information was not displayed, log it.
|
||||
devtoolsWidgetPanel.log(output);
|
||||
developerHUD.log(output);
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -372,11 +379,10 @@ let consoleWatcher = {
|
|||
return source;
|
||||
}
|
||||
};
|
||||
|
||||
devtoolsWidgetPanel.registerWatcher(consoleWatcher);
|
||||
developerHUD.registerWatcher(consoleWatcher);
|
||||
|
||||
|
||||
let jankWatcher = {
|
||||
let eventLoopLagWatcher = {
|
||||
_client: null,
|
||||
_fronts: new Map(),
|
||||
_active: false,
|
||||
|
@ -384,8 +390,7 @@ let jankWatcher = {
|
|||
init: function(client) {
|
||||
this._client = client;
|
||||
|
||||
SettingsListener.observe('devtools.hud.jank', false,
|
||||
this.settingsListener.bind(this));
|
||||
SettingsListener.observe('hud.jank', false, this.settingsListener.bind(this));
|
||||
},
|
||||
|
||||
settingsListener: function(value) {
|
||||
|
@ -417,7 +422,7 @@ let jankWatcher = {
|
|||
app.metrics.set('jank', time);
|
||||
|
||||
if (!app.display()) {
|
||||
devtoolsWidgetPanel.log('jank: ' + time + 'ms');
|
||||
developerHUD.log('jank: ' + time + 'ms');
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -434,5 +439,108 @@ let jankWatcher = {
|
|||
}
|
||||
}
|
||||
};
|
||||
developerHUD.registerWatcher(eventLoopLagWatcher);
|
||||
|
||||
devtoolsWidgetPanel.registerWatcher(jankWatcher);
|
||||
|
||||
/**
|
||||
* The Memory Watcher uses devtools actors to track memory usage.
|
||||
*/
|
||||
let memoryWatcher = {
|
||||
|
||||
_client: null,
|
||||
_fronts: new Map(),
|
||||
_timers: new Map(),
|
||||
_watching: {
|
||||
jsobjects: false,
|
||||
jsstrings: false,
|
||||
jsother: false,
|
||||
dom: false,
|
||||
style: false,
|
||||
other: false
|
||||
},
|
||||
_active: false,
|
||||
|
||||
init: function mw_init(client) {
|
||||
this._client = client;
|
||||
let watching = this._watching;
|
||||
|
||||
for (let key in watching) {
|
||||
let category = key;
|
||||
SettingsListener.observe('hud.' + category, false, watch => {
|
||||
watching[category] = watch;
|
||||
});
|
||||
}
|
||||
|
||||
SettingsListener.observe('hud.appmemory', false, enabled => {
|
||||
if (this._active = enabled) {
|
||||
for (let app of this._fronts.keys()) {
|
||||
this.measure(app);
|
||||
}
|
||||
} else {
|
||||
for (let timer of this._timers.values()) {
|
||||
clearTimeout(this._timers.get(app));
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
measure: function mw_measure(app) {
|
||||
|
||||
// TODO Also track USS (bug #976024).
|
||||
|
||||
let watch = this._watching;
|
||||
let front = this._fronts.get(app);
|
||||
|
||||
front.measure().then((data) => {
|
||||
|
||||
let total = 0;
|
||||
if (watch.jsobjects) {
|
||||
total += parseInt(data.jsObjectsSize);
|
||||
}
|
||||
if (watch.jsstrings) {
|
||||
total += parseInt(data.jsStringsSize);
|
||||
}
|
||||
if (watch.jsother) {
|
||||
total += parseInt(data.jsOtherSize);
|
||||
}
|
||||
if (watch.dom) {
|
||||
total += parseInt(data.domSize);
|
||||
}
|
||||
if (watch.style) {
|
||||
total += parseInt(data.styleSize);
|
||||
}
|
||||
if (watch.other) {
|
||||
total += parseInt(data.otherSize);
|
||||
}
|
||||
// TODO Also count images size (bug #976007).
|
||||
|
||||
app.metrics.set('memory', total);
|
||||
app.display();
|
||||
let duration = parseInt(data.jsMilliseconds) + parseInt(data.nonJSMilliseconds);
|
||||
let timer = setTimeout(() => this.measure(app), 100 * duration);
|
||||
this._timers.set(app, timer);
|
||||
}, (err) => {
|
||||
console.error(err);
|
||||
});
|
||||
},
|
||||
|
||||
trackApp: function mw_trackApp(app) {
|
||||
app.metrics.set('uss', 0);
|
||||
app.metrics.set('memory', 0);
|
||||
this._fronts.set(app, MemoryFront(this._client, app.actor));
|
||||
if (this._active) {
|
||||
this.measure(app);
|
||||
}
|
||||
},
|
||||
|
||||
untrackApp: function mw_untrackApp(app) {
|
||||
let front = this._fronts.get(app);
|
||||
if (front) {
|
||||
front.destroy();
|
||||
clearTimeout(this._timers.get(app));
|
||||
this._fronts.delete(app);
|
||||
this._timers.delete(app);
|
||||
}
|
||||
}
|
||||
};
|
||||
developerHUD.registerWatcher(memoryWatcher);
|
||||
|
|
|
@ -219,18 +219,18 @@ Components.utils.import('resource://gre/modules/ctypes.jsm');
|
|||
|
||||
// =================== DevTools ====================
|
||||
|
||||
let devtoolsWidgetPanel;
|
||||
let developerHUD;
|
||||
SettingsListener.observe('devtools.overlay', false, (value) => {
|
||||
if (value) {
|
||||
if (!devtoolsWidgetPanel) {
|
||||
if (!developerHUD) {
|
||||
let scope = {};
|
||||
Services.scriptloader.loadSubScript('chrome://b2g/content/devtools.js', scope);
|
||||
devtoolsWidgetPanel = scope.devtoolsWidgetPanel;
|
||||
developerHUD = scope.developerHUD;
|
||||
}
|
||||
devtoolsWidgetPanel.init();
|
||||
developerHUD.init();
|
||||
} else {
|
||||
if (devtoolsWidgetPanel) {
|
||||
devtoolsWidgetPanel.uninit();
|
||||
if (developerHUD) {
|
||||
developerHUD.uninit();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -26,6 +26,7 @@ MOZ_WEBSMS_BACKEND=1
|
|||
MOZ_DISABLE_CRYPTOLEGACY=1
|
||||
MOZ_APP_STATIC_INI=1
|
||||
NSS_NO_LIBPKIX=1
|
||||
MOZ_NO_EV_CERTS=1
|
||||
MOZ_DISABLE_EXPORT_JS=1
|
||||
|
||||
if test "$OS_TARGET" = "Android"; then
|
||||
|
|
|
@ -67,22 +67,6 @@ PROGRAMS_DEST = $(DIST)/bin
|
|||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
ifeq ($(OS_ARCH),WINNT) #{
|
||||
#
|
||||
# Control the default heap size.
|
||||
# This is the heap returned by GetProcessHeap().
|
||||
# As we use the CRT heap, the default size is too large and wastes VM.
|
||||
#
|
||||
# The default heap size is 1MB on Win32.
|
||||
# The heap will grow if need be.
|
||||
#
|
||||
# Set it to 256k. See bug 127069.
|
||||
#
|
||||
ifndef GNU_CC #{
|
||||
LDFLAGS += /HEAP:0x40000
|
||||
endif #}
|
||||
endif #}
|
||||
|
||||
ifneq (,$(filter-out WINNT,$(OS_ARCH)))
|
||||
|
||||
ifdef COMPILE_ENVIRONMENT
|
||||
|
|
|
@ -40,3 +40,14 @@ if CONFIG['_MSC_VER']:
|
|||
|
||||
if CONFIG['OS_ARCH'] == 'WINNT':
|
||||
DEFINES['MOZ_PHOENIX'] = True
|
||||
|
||||
# Control the default heap size.
|
||||
# This is the heap returned by GetProcessHeap().
|
||||
# As we use the CRT heap, the default size is too large and wastes VM.
|
||||
#
|
||||
# The default heap size is 1MB on Win32.
|
||||
# The heap will grow if need be.
|
||||
#
|
||||
# Set it to 256k. See bug 127069.
|
||||
if CONFIG['OS_ARCH'] == 'WINNT' and not CONFIG['GNU_CC']:
|
||||
LDFLAGS += ['/HEAP:0x40000']
|
||||
|
|
|
@ -77,13 +77,20 @@ function promiseMessage(aMessage, aAction) {
|
|||
return deferred.promise;
|
||||
}
|
||||
|
||||
function promisePopupNotification(aName) {
|
||||
|
||||
function promisePopupNotification(aName, aShown) {
|
||||
let deferred = Promise.defer();
|
||||
|
||||
waitForCondition(() => PopupNotifications.getNotification(aName),
|
||||
// If aShown is true, the notification is expected to be opened by
|
||||
// default and we wait for the panel to be populated; for dismissed
|
||||
// notifications, we are happy as soon as we find the icon.
|
||||
waitForCondition(() => PopupNotifications.getNotification(aName) &&
|
||||
(!aShown || PopupNotifications.panel.firstChild),
|
||||
() => {
|
||||
ok(!!PopupNotifications.getNotification(aName),
|
||||
aName + " notification appeared");
|
||||
if (aShown)
|
||||
ok(PopupNotifications.panel.firstChild, "notification panel populated");
|
||||
deferred.resolve();
|
||||
}, "timeout waiting for popup notification " + aName);
|
||||
|
||||
|
@ -205,7 +212,7 @@ let gTests = [
|
|||
content.wrappedJSObject.requestDevice(true, true);
|
||||
});
|
||||
|
||||
yield promisePopupNotification("webRTC-shareDevices");
|
||||
yield promisePopupNotification("webRTC-shareDevices", true);
|
||||
checkDeviceSelectors(true, true);
|
||||
|
||||
yield promiseMessage("ok", () => {
|
||||
|
@ -229,7 +236,7 @@ let gTests = [
|
|||
content.wrappedJSObject.requestDevice(true);
|
||||
});
|
||||
|
||||
yield promisePopupNotification("webRTC-shareDevices");
|
||||
yield promisePopupNotification("webRTC-shareDevices", true);
|
||||
checkDeviceSelectors(true);
|
||||
|
||||
yield promiseMessage("ok", () => {
|
||||
|
@ -252,7 +259,7 @@ let gTests = [
|
|||
content.wrappedJSObject.requestDevice(false, true);
|
||||
});
|
||||
|
||||
yield promisePopupNotification("webRTC-shareDevices");
|
||||
yield promisePopupNotification("webRTC-shareDevices", true);
|
||||
checkDeviceSelectors(false, true);
|
||||
|
||||
yield promiseMessage("ok", () => {
|
||||
|
@ -275,7 +282,7 @@ let gTests = [
|
|||
content.wrappedJSObject.requestDevice(true, true);
|
||||
});
|
||||
|
||||
yield promisePopupNotification("webRTC-shareDevices");
|
||||
yield promisePopupNotification("webRTC-shareDevices", true);
|
||||
checkDeviceSelectors(true, true);
|
||||
|
||||
// disable the camera
|
||||
|
@ -306,7 +313,7 @@ let gTests = [
|
|||
content.wrappedJSObject.requestDevice(true, true);
|
||||
});
|
||||
|
||||
yield promisePopupNotification("webRTC-shareDevices");
|
||||
yield promisePopupNotification("webRTC-shareDevices", true);
|
||||
checkDeviceSelectors(true, true);
|
||||
|
||||
// disable the microphone
|
||||
|
@ -337,7 +344,7 @@ let gTests = [
|
|||
content.wrappedJSObject.requestDevice(true, true);
|
||||
});
|
||||
|
||||
yield promisePopupNotification("webRTC-shareDevices");
|
||||
yield promisePopupNotification("webRTC-shareDevices", true);
|
||||
checkDeviceSelectors(true, true);
|
||||
|
||||
// disable the camera and microphone
|
||||
|
@ -366,7 +373,7 @@ let gTests = [
|
|||
content.wrappedJSObject.requestDevice(true, true);
|
||||
});
|
||||
|
||||
yield promisePopupNotification("webRTC-shareDevices");
|
||||
yield promisePopupNotification("webRTC-shareDevices", true);
|
||||
checkDeviceSelectors(true, true);
|
||||
|
||||
yield promiseMessage("error: PERMISSION_DENIED", () => {
|
||||
|
@ -387,7 +394,7 @@ let gTests = [
|
|||
content.wrappedJSObject.requestDevice(true, true);
|
||||
});
|
||||
|
||||
yield promisePopupNotification("webRTC-shareDevices");
|
||||
yield promisePopupNotification("webRTC-shareDevices", true);
|
||||
checkDeviceSelectors(true, true);
|
||||
|
||||
yield promiseMessage("ok", () => {
|
||||
|
@ -424,15 +431,15 @@ let gTests = [
|
|||
{
|
||||
desc: "getUserMedia prompt: Always/Never Share",
|
||||
run: function checkRememberCheckbox() {
|
||||
let elt = id => document.getElementById(id);
|
||||
|
||||
function checkPerm(aRequestAudio, aRequestVideo, aAllowAudio, aAllowVideo,
|
||||
aExpectedAudioPerm, aExpectedVideoPerm, aNever) {
|
||||
yield promiseNotification("getUserMedia:request", () => {
|
||||
content.wrappedJSObject.requestDevice(aRequestAudio, aRequestVideo);
|
||||
});
|
||||
|
||||
yield promisePopupNotification("webRTC-shareDevices");
|
||||
|
||||
let elt = id => document.getElementById(id);
|
||||
yield promisePopupNotification("webRTC-shareDevices", true);
|
||||
|
||||
let noAudio = aAllowAudio === undefined;
|
||||
is(elt("webRTC-selectMicrophone").hidden, noAudio,
|
||||
|
@ -519,6 +526,10 @@ let gTests = [
|
|||
info("audio+video, user denies audio, grants video, " +
|
||||
"expect video perm set to allow, audio perm set to deny.");
|
||||
yield checkPerm(true, true, false, true, false, true);
|
||||
|
||||
// reset the menuitems to have no impact on the following tests.
|
||||
elt("webRTC-selectMicrophone-menulist").value = 0;
|
||||
elt("webRTC-selectCamera-menulist").value = 0;
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -545,7 +556,7 @@ let gTests = [
|
|||
if (aExpectStream === undefined) {
|
||||
// Check that we get a prompt.
|
||||
yield promiseNotification("getUserMedia:request", gum);
|
||||
yield promisePopupNotification("webRTC-shareDevices");
|
||||
yield promisePopupNotification("webRTC-shareDevices", true);
|
||||
|
||||
// Deny the request to cleanup...
|
||||
yield promiseMessage("error: PERMISSION_DENIED", () => {
|
||||
|
|
|
@ -492,24 +492,8 @@ function sendDragEvent(aEventType, aTarget, aData) {
|
|||
* @return The drag event.
|
||||
*/
|
||||
function createDragEvent(aEventType, aData) {
|
||||
let dataTransfer = {
|
||||
mozUserCancelled: false,
|
||||
setData: function () null,
|
||||
setDragImage: function () null,
|
||||
getData: function () aData,
|
||||
|
||||
types: {
|
||||
contains: function (aType) aType == "text/x-moz-url"
|
||||
},
|
||||
|
||||
mozGetDataAt: function (aType, aIndex) {
|
||||
if (aIndex || aType != "text/x-moz-url")
|
||||
return null;
|
||||
|
||||
return aData;
|
||||
}
|
||||
};
|
||||
|
||||
let dataTransfer = new getContentWindow().DataTransfer("dragstart", false);
|
||||
dataTransfer.mozSetDataAt("text/x-moz-url", aData, 0);
|
||||
let event = getContentDocument().createEvent("DragEvents");
|
||||
event.initDragEvent(aEventType, true, true, getContentWindow(), 0, 0, 0, 0, 0,
|
||||
false, false, false, false, 0, null, dataTransfer);
|
||||
|
|
|
@ -678,8 +678,8 @@ const CustomizableWidgets = [{
|
|||
let elem = aDocument.createElementNS(kNSXUL, "toolbarbutton");
|
||||
elem.setAttribute("label", item.label);
|
||||
elem.setAttribute("type", "checkbox");
|
||||
elem.section = aSection == "detectors" ? "detectors" : "charsets";
|
||||
elem.value = item.id;
|
||||
elem.section = aSection;
|
||||
elem.value = item.value;
|
||||
elem.setAttribute("class", "subviewbutton");
|
||||
containerElem.appendChild(elem);
|
||||
}
|
||||
|
@ -687,10 +687,7 @@ const CustomizableWidgets = [{
|
|||
updateCurrentCharset: function(aDocument) {
|
||||
let content = aDocument.defaultView.content;
|
||||
let currentCharset = content && content.document && content.document.characterSet;
|
||||
if (currentCharset) {
|
||||
currentCharset = aDocument.defaultView.FoldCharset(currentCharset);
|
||||
}
|
||||
currentCharset = currentCharset ? ("charset." + currentCharset) : "";
|
||||
currentCharset = CharsetMenu.foldCharset(currentCharset);
|
||||
|
||||
let pinnedContainer = aDocument.getElementById("PanelUI-characterEncodingView-pinned");
|
||||
let charsetContainer = aDocument.getElementById("PanelUI-characterEncodingView-charsets");
|
||||
|
@ -700,13 +697,11 @@ const CustomizableWidgets = [{
|
|||
},
|
||||
updateCurrentDetector: function(aDocument) {
|
||||
let detectorContainer = aDocument.getElementById("PanelUI-characterEncodingView-autodetect");
|
||||
let detectorEnum = CharsetManager.GetCharsetDetectorList();
|
||||
let currentDetector;
|
||||
try {
|
||||
currentDetector = Services.prefs.getComplexValue(
|
||||
"intl.charset.detector", Ci.nsIPrefLocalizedString).data;
|
||||
} catch (e) {}
|
||||
currentDetector = "chardet." + (currentDetector || "off");
|
||||
|
||||
this._updateElements(detectorContainer.childNodes, currentDetector);
|
||||
},
|
||||
|
@ -762,13 +757,8 @@ const CustomizableWidgets = [{
|
|||
// The behavior as implemented here is directly based off of the
|
||||
// `MultiplexHandler()` method in browser.js.
|
||||
if (section != "detectors") {
|
||||
let charset = value.substring(value.indexOf('charset.') + 'charset.'.length);
|
||||
window.BrowserSetForcedCharacterSet(charset);
|
||||
window.BrowserSetForcedCharacterSet(value);
|
||||
} else {
|
||||
value = value.replace(/^chardet\./, "");
|
||||
if (value == "off") {
|
||||
value = "";
|
||||
}
|
||||
// Set the detector pref.
|
||||
try {
|
||||
let str = Cc["@mozilla.org/supports-string;1"]
|
||||
|
|
|
@ -85,7 +85,7 @@ let gSyncPane = {
|
|||
_init: function () {
|
||||
let topics = ["weave:service:login:error",
|
||||
"weave:service:login:finish",
|
||||
"weave:service:start-over",
|
||||
"weave:service:start-over:finish",
|
||||
"weave:service:setup-complete",
|
||||
"weave:service:logout:finish",
|
||||
FxAccountsCommon.ONVERIFIED_NOTIFICATION];
|
||||
|
|
|
@ -3140,12 +3140,8 @@ let SessionStoreInternal = {
|
|||
*/
|
||||
_prepDataForDeferredRestore: function ssi_prepDataForDeferredRestore(state) {
|
||||
// Make sure that we don't modify the global state as provided by
|
||||
// nsSessionStartup.state. Converting the object to a JSON string and
|
||||
// parsing it again is the easiest way to do that, although not the most
|
||||
// efficient one. Deferred sessions that don't have automatic session
|
||||
// restore enabled tend to be a lot smaller though so that this shouldn't
|
||||
// be a big perf hit.
|
||||
state = JSON.parse(JSON.stringify(state));
|
||||
// nsSessionStartup.state.
|
||||
state = Cu.cloneInto(state, {});
|
||||
|
||||
let defaultState = { windows: [], selectedWindow: 1 };
|
||||
|
||||
|
|
|
@ -20,6 +20,8 @@ XPCOMUtils.defineLazyModuleGetter(this, "TabStateCache",
|
|||
"resource:///modules/sessionstore/TabStateCache.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "TabAttributes",
|
||||
"resource:///modules/sessionstore/TabAttributes.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Utils",
|
||||
"resource:///modules/sessionstore/Utils.jsm");
|
||||
|
||||
/**
|
||||
* Module that contains tab state collection methods.
|
||||
|
@ -151,7 +153,7 @@ let TabStateInternal = {
|
|||
// Use the data to be restored when the tab hasn't been
|
||||
// completely loaded. We clone the data, since we're updating it
|
||||
// here and the caller may update it further.
|
||||
tabData = JSON.parse(JSON.stringify(browser.__SS_data));
|
||||
tabData = Utils.shallowCopy(browser.__SS_data);
|
||||
if (tab.pinned)
|
||||
tabData.pinned = true;
|
||||
else
|
||||
|
|
|
@ -41,5 +41,15 @@ this.Utils = Object.freeze({
|
|||
let prevChar = host[index - 1];
|
||||
return (index == (host.length - domain.length)) &&
|
||||
(prevChar == "." || prevChar == "/");
|
||||
},
|
||||
|
||||
shallowCopy: function (obj) {
|
||||
let retval = {};
|
||||
|
||||
for (let key of Object.keys(obj)) {
|
||||
retval[key] = obj[key];
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
});
|
||||
|
|
|
@ -2128,16 +2128,6 @@ Breakpoints.prototype = {
|
|||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets all Promises for the BreakpointActor client objects that are
|
||||
* either enabled (added to the server) or disabled (removed from the server,
|
||||
* but for which some details are preserved).
|
||||
*/
|
||||
get _addedOrDisabled() {
|
||||
for (let [, value] of this._added) yield value;
|
||||
for (let [, value] of this._disabled) yield value;
|
||||
},
|
||||
|
||||
/**
|
||||
* Get a Promise for the BreakpointActor client object which is already added
|
||||
* or currently being added at the given location.
|
||||
|
@ -2180,6 +2170,22 @@ Breakpoints.prototype = {
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets all Promises for the BreakpointActor client objects that are
|
||||
* either enabled (added to the server) or disabled (removed from the server,
|
||||
* but for which some details are preserved).
|
||||
*/
|
||||
Object.defineProperty(Breakpoints.prototype, "_addedOrDisabled", {
|
||||
get: function* () {
|
||||
for (let [, value] of this._added) {
|
||||
yield value;
|
||||
}
|
||||
for (let [, value] of this._disabled) {
|
||||
yield value;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Localization convenience methods.
|
||||
*/
|
||||
|
|
|
@ -22,11 +22,13 @@ The sourceeditor component contains imported CodeMirror tests [3].
|
|||
* Some tests were commented out because we don't use that functionality
|
||||
within Firefox (for example Ruby editing mode). Be careful when updating
|
||||
files test/codemirror.html and test/vimemacs.html; they were modified to
|
||||
co-exist with Mozilla's testing infrastructure.
|
||||
co-exist with Mozilla's testing infrastructure. Basically, vimemacs.html
|
||||
is a copy of codemirror.html but only with VIM and Emacs mode tests
|
||||
enabled.
|
||||
* In cm_comment_test.js comment out fallbackToBlock and fallbackToLine
|
||||
tests.
|
||||
* The search addon (search.js) was slightly modified to make search
|
||||
UI localizable.
|
||||
UI localizable (see patch below).
|
||||
|
||||
Other than that, we don't have any Mozilla-specific patches applied to
|
||||
CodeMirror itself.
|
||||
|
@ -76,6 +78,38 @@ in the LICENSE file:
|
|||
* test/cm_emacs_test.js
|
||||
* test/cm_test.js
|
||||
|
||||
# Localization patches
|
||||
|
||||
diff --git a/browser/devtools/sourceeditor/codemirror/search/search.js b/browser/devtools/sourceeditor/codemirror/sea
|
||||
index 049f72f..df4d95e 100644
|
||||
--- a/browser/devtools/sourceeditor/codemirror/search/search.js
|
||||
+++ b/browser/devtools/sourceeditor/codemirror/search/search.js
|
||||
@@ -58,9 +58,22 @@
|
||||
var isRE = query.match(/^\/(.*)\/([a-z]*)$/);
|
||||
return isRE ? new RegExp(isRE[1], isRE[2].indexOf("i") == -1 ? "" : "i") : query;
|
||||
}
|
||||
- var queryDialog =
|
||||
- 'Search: <input type="text" style="width: 10em"/> <span style="color: #888">(Use /re/ syntax for regexp search)<
|
||||
+ var queryDialog;
|
||||
function doSearch(cm, rev) {
|
||||
+ if (!queryDialog) {
|
||||
+ let doc = cm.getWrapperElement().ownerDocument;
|
||||
+ let inp = doc.createElement("input");
|
||||
+ let txt = doc.createTextNode(cm.l10n("findCmd.promptMessage"));
|
||||
+
|
||||
+ inp.type = "text";
|
||||
+ inp.style.width = "10em";
|
||||
+ inp.style.MozMarginStart = "1em";
|
||||
+
|
||||
+ queryDialog = doc.createElement("div");
|
||||
+ queryDialog.appendChild(txt);
|
||||
+ queryDialog.appendChild(inp);
|
||||
+ }
|
||||
+
|
||||
var state = getSearchState(cm);
|
||||
if (state.query) return findNext(cm, rev);
|
||||
dialog(cm, queryDialog, "Search for:", cm.getSelection(), function(query) {
|
||||
|
||||
# Footnotes
|
||||
|
||||
[1] http://codemirror.net
|
||||
|
|
|
@ -58,9 +58,22 @@
|
|||
var isRE = query.match(/^\/(.*)\/([a-z]*)$/);
|
||||
return isRE ? new RegExp(isRE[1], isRE[2].indexOf("i") == -1 ? "" : "i") : query;
|
||||
}
|
||||
var queryDialog =
|
||||
'Search: <input type="text" style="width: 10em"/> <span style="color: #888">(Use /re/ syntax for regexp search)</span>';
|
||||
var queryDialog;
|
||||
function doSearch(cm, rev) {
|
||||
if (!queryDialog) {
|
||||
let doc = cm.getWrapperElement().ownerDocument;
|
||||
let inp = doc.createElement("input");
|
||||
let txt = doc.createTextNode(cm.l10n("findCmd.promptMessage"));
|
||||
|
||||
inp.type = "text";
|
||||
inp.style.width = "10em";
|
||||
inp.style.MozMarginStart = "1em";
|
||||
|
||||
queryDialog = doc.createElement("div");
|
||||
queryDialog.appendChild(txt);
|
||||
queryDialog.appendChild(inp);
|
||||
}
|
||||
|
||||
var state = getSearchState(cm);
|
||||
if (state.query) return findNext(cm, rev);
|
||||
dialog(cm, queryDialog, "Search for:", cm.getSelection(), function(query) {
|
||||
|
|
|
@ -775,6 +775,7 @@ Editor.prototype = {
|
|||
setFontSize: function (size) {
|
||||
let cm = editors.get(this);
|
||||
cm.getWrapperElement().style.fontSize = parseInt(size, 10) + "px";
|
||||
cm.refresh();
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
|
@ -26,6 +26,7 @@ XPCOMUtils.defineLazyModuleGetter(this, "BrowserUITelemetry",
|
|||
|
||||
const UITOUR_PERMISSION = "uitour";
|
||||
const PREF_PERM_BRANCH = "browser.uitour.";
|
||||
const PREF_SEENPAGEIDS = "browser.uitour.seenPageIDs";
|
||||
const MAX_BUTTONS = 4;
|
||||
|
||||
const BUCKET_NAME = "UITour";
|
||||
|
@ -36,10 +37,12 @@ const BUCKET_TIMESTEPS = [
|
|||
60 * 60 * 1000, // Until 1 hour after tab is closed/inactive.
|
||||
];
|
||||
|
||||
// Time after which seen Page IDs expire.
|
||||
const SEENPAGEID_EXPIRY = 2 * 7 * 24 * 60 * 60 * 1000; // 2 weeks.
|
||||
|
||||
|
||||
this.UITour = {
|
||||
seenPageIDs: new Set(),
|
||||
seenPageIDs: null,
|
||||
pageIDSourceTabs: new WeakMap(),
|
||||
pageIDSourceWindows: new WeakMap(),
|
||||
/* Map from browser windows to a set of tabs in which a tour is open */
|
||||
|
@ -115,10 +118,72 @@ this.UITour = {
|
|||
]),
|
||||
|
||||
init: function() {
|
||||
// Lazy getter is initialized here so it can be replicated any time
|
||||
// in a test.
|
||||
delete this.seenPageIDs;
|
||||
Object.defineProperty(this, "seenPageIDs", {
|
||||
get: this.restoreSeenPageIDs.bind(this),
|
||||
configurable: true,
|
||||
});
|
||||
|
||||
UITelemetry.addSimpleMeasureFunction("UITour",
|
||||
this.getTelemetry.bind(this));
|
||||
},
|
||||
|
||||
restoreSeenPageIDs: function() {
|
||||
delete this.seenPageIDs;
|
||||
|
||||
if (UITelemetry.enabled) {
|
||||
let dateThreshold = Date.now() - SEENPAGEID_EXPIRY;
|
||||
|
||||
try {
|
||||
let data = Services.prefs.getCharPref(PREF_SEENPAGEIDS);
|
||||
data = new Map(JSON.parse(data));
|
||||
|
||||
for (let [pageID, details] of data) {
|
||||
|
||||
if (typeof pageID != "string" ||
|
||||
typeof details != "object" ||
|
||||
typeof details.lastSeen != "number" ||
|
||||
details.lastSeen < dateThreshold) {
|
||||
|
||||
data.delete(pageID);
|
||||
}
|
||||
}
|
||||
|
||||
this.seenPageIDs = data;
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
if (!this.seenPageIDs)
|
||||
this.seenPageIDs = new Map();
|
||||
|
||||
this.persistSeenIDs();
|
||||
|
||||
return this.seenPageIDs;
|
||||
},
|
||||
|
||||
addSeenPageID: function(aPageID) {
|
||||
if (!UITelemetry.enabled)
|
||||
return;
|
||||
|
||||
this.seenPageIDs.set(aPageID, {
|
||||
lastSeen: Date.now(),
|
||||
});
|
||||
|
||||
this.persistSeenIDs();
|
||||
},
|
||||
|
||||
persistSeenIDs: function() {
|
||||
if (this.seenPageIDs.size === 0) {
|
||||
Services.prefs.clearUserPref(PREF_SEENPAGEIDS);
|
||||
return;
|
||||
}
|
||||
|
||||
Services.prefs.setCharPref(PREF_SEENPAGEIDS,
|
||||
JSON.stringify([...this.seenPageIDs]));
|
||||
},
|
||||
|
||||
onPageEvent: function(aEvent) {
|
||||
let contentDocument = null;
|
||||
if (aEvent.target instanceof Ci.nsIDOMHTMLDocument)
|
||||
|
@ -161,11 +226,15 @@ this.UITour = {
|
|||
|
||||
switch (action) {
|
||||
case "registerPageID": {
|
||||
// This is only relevant if Telemtry is enabled.
|
||||
if (!UITelemetry.enabled)
|
||||
break;
|
||||
|
||||
// We don't want to allow BrowserUITelemetry.BUCKET_SEPARATOR in the
|
||||
// pageID, as it could make parsing the telemetry bucket name difficult.
|
||||
if (typeof data.pageID == "string" &&
|
||||
!data.pageID.contains(BrowserUITelemetry.BUCKET_SEPARATOR)) {
|
||||
this.seenPageIDs.add(data.pageID);
|
||||
this.addSeenPageID(data.pageID);
|
||||
|
||||
// Store tabs and windows separately so we don't need to loop over all
|
||||
// tabs when a window is closed.
|
||||
|
@ -444,7 +513,7 @@ this.UITour = {
|
|||
|
||||
getTelemetry: function() {
|
||||
return {
|
||||
seenPageIDs: [...this.seenPageIDs],
|
||||
seenPageIDs: [...this.seenPageIDs.keys()],
|
||||
};
|
||||
},
|
||||
|
||||
|
|
|
@ -8,23 +8,68 @@ let gContentAPI;
|
|||
let gContentWindow;
|
||||
|
||||
Components.utils.import("resource:///modules/UITour.jsm");
|
||||
Components.utils.import("resource://gre/modules/UITelemetry.jsm");
|
||||
Components.utils.import("resource:///modules/BrowserUITelemetry.jsm");
|
||||
|
||||
function test() {
|
||||
UITelemetry._enabled = true;
|
||||
|
||||
registerCleanupFunction(function() {
|
||||
UITour.seenPageIDs.clear();
|
||||
Services.prefs.clearUserPref("browser.uitour.seenPageIDs");
|
||||
resetSeenPageIDsLazyGetter();
|
||||
UITelemetry._enabled = undefined;
|
||||
BrowserUITelemetry.setBucket(null);
|
||||
delete window.UITelemetry;
|
||||
delete window.BrowserUITelemetry;
|
||||
});
|
||||
UITourTest();
|
||||
}
|
||||
|
||||
function resetSeenPageIDsLazyGetter() {
|
||||
delete UITour.seenPageIDs;
|
||||
// This should be kept in sync with how UITour.init() sets this.
|
||||
Object.defineProperty(UITour, "seenPageIDs", {
|
||||
get: UITour.restoreSeenPageIDs.bind(UITour),
|
||||
configurable: true,
|
||||
});
|
||||
}
|
||||
|
||||
function checkExpectedSeenPageIDs(expected) {
|
||||
is(UITour.seenPageIDs.size, expected.length, "Should be " + expected.length + " total seen page IDs");
|
||||
|
||||
for (let id of expected)
|
||||
ok(UITour.seenPageIDs.has(id), "Should have seen '" + id + "' page ID");
|
||||
|
||||
let prefData = Services.prefs.getCharPref("browser.uitour.seenPageIDs");
|
||||
prefData = new Map(JSON.parse(prefData));
|
||||
|
||||
is(prefData.size, expected.length, "Should be " + expected.length + " total seen page IDs persisted");
|
||||
|
||||
for (let id of expected)
|
||||
ok(prefData.has(id), "Should have seen '" + id + "' page ID persisted");
|
||||
}
|
||||
|
||||
let tests = [
|
||||
function test_seenPageIDs_1(done) {
|
||||
function test_seenPageIDs_restore(done) {
|
||||
info("Setting up seenPageIDs to be restored from pref");
|
||||
let data = JSON.stringify([
|
||||
["savedID1", { lastSeen: Date.now() }],
|
||||
["savedID2", { lastSeen: Date.now() }],
|
||||
// 3 weeks ago, should auto expire.
|
||||
["savedID3", { lastSeen: Date.now() - 3 * 7 * 24 * 60 * 60 * 1000 }],
|
||||
]);
|
||||
Services.prefs.setCharPref("browser.uitour.seenPageIDs",
|
||||
data);
|
||||
|
||||
resetSeenPageIDsLazyGetter();
|
||||
checkExpectedSeenPageIDs(["savedID1", "savedID2"]);
|
||||
|
||||
done();
|
||||
},
|
||||
function test_seenPageIDs_set_1(done) {
|
||||
gContentAPI.registerPageID("testpage1");
|
||||
|
||||
is(UITour.seenPageIDs.size, 1, "Should be 1 seen page ID");
|
||||
ok(UITour.seenPageIDs.has("testpage1"), "Should have seen 'testpage1' page ID");
|
||||
checkExpectedSeenPageIDs(["savedID1", "savedID2", "testpage1"]);
|
||||
|
||||
const PREFIX = BrowserUITelemetry.BUCKET_PREFIX;
|
||||
const SEP = BrowserUITelemetry.BUCKET_SEPARATOR;
|
||||
|
@ -42,12 +87,10 @@ let tests = [
|
|||
BrowserUITelemetry.setBucket(null);
|
||||
done();
|
||||
},
|
||||
function test_seenPageIDs_2(done) {
|
||||
function test_seenPageIDs_set_2(done) {
|
||||
gContentAPI.registerPageID("testpage2");
|
||||
|
||||
is(UITour.seenPageIDs.size, 2, "Should be 2 seen page IDs");
|
||||
ok(UITour.seenPageIDs.has("testpage1"), "Should have seen 'testpage1' page ID");
|
||||
ok(UITour.seenPageIDs.has("testpage2"), "Should have seen 'testpage2' page ID");
|
||||
checkExpectedSeenPageIDs(["savedID1", "savedID2", "testpage1", "testpage2"]);
|
||||
|
||||
const PREFIX = BrowserUITelemetry.BUCKET_PREFIX;
|
||||
const SEP = BrowserUITelemetry.BUCKET_SEPARATOR;
|
||||
|
|
|
@ -481,7 +481,7 @@ include $(topsrcdir)/config/static-checking-config.mk
|
|||
|
||||
CFLAGS = $(OS_CPPFLAGS) $(OS_CFLAGS)
|
||||
CXXFLAGS = $(OS_CPPFLAGS) $(OS_CXXFLAGS)
|
||||
LDFLAGS = $(OS_LDFLAGS) $(MOZ_FIX_LINK_PATHS)
|
||||
LDFLAGS = $(OS_LDFLAGS) $(MOZBUILD_LDFLAGS) $(MOZ_FIX_LINK_PATHS)
|
||||
|
||||
# Allow each module to override the *default* optimization settings
|
||||
# by setting MODULE_OPTIMIZE_FLAGS if the developer has not given
|
||||
|
@ -587,10 +587,10 @@ OS_COMPILE_CMMFLAGS += -fobjc-abi-version=2 -fobjc-legacy-dispatch
|
|||
endif
|
||||
endif
|
||||
|
||||
COMPILE_CFLAGS = $(VISIBILITY_FLAGS) $(DEFINES) $(INCLUDES) $(DSO_CFLAGS) $(DSO_PIC_CFLAGS) $(RTL_FLAGS) $(OS_CPPFLAGS) $(OS_COMPILE_CFLAGS) $(CFLAGS) $(EXTRA_COMPILE_FLAGS)
|
||||
COMPILE_CXXFLAGS = $(STL_FLAGS) $(VISIBILITY_FLAGS) $(DEFINES) $(INCLUDES) $(DSO_CFLAGS) $(DSO_PIC_CFLAGS) $(RTL_FLAGS) $(OS_CPPFLAGS) $(OS_COMPILE_CXXFLAGS) $(CXXFLAGS) $(EXTRA_COMPILE_FLAGS)
|
||||
COMPILE_CMFLAGS = $(OS_COMPILE_CMFLAGS) $(EXTRA_COMPILE_FLAGS)
|
||||
COMPILE_CMMFLAGS = $(OS_COMPILE_CMMFLAGS) $(EXTRA_COMPILE_FLAGS)
|
||||
COMPILE_CFLAGS = $(VISIBILITY_FLAGS) $(DEFINES) $(INCLUDES) $(DSO_CFLAGS) $(DSO_PIC_CFLAGS) $(RTL_FLAGS) $(OS_CPPFLAGS) $(OS_COMPILE_CFLAGS) $(CFLAGS) $(MOZBUILD_CFLAGS) $(EXTRA_COMPILE_FLAGS)
|
||||
COMPILE_CXXFLAGS = $(STL_FLAGS) $(VISIBILITY_FLAGS) $(DEFINES) $(INCLUDES) $(DSO_CFLAGS) $(DSO_PIC_CFLAGS) $(RTL_FLAGS) $(OS_CPPFLAGS) $(OS_COMPILE_CXXFLAGS) $(CXXFLAGS) $(MOZBUILD_CXXFLAGS) $(EXTRA_COMPILE_FLAGS)
|
||||
COMPILE_CMFLAGS = $(OS_COMPILE_CMFLAGS) $(MOZBUILD_CMFLAGS) $(EXTRA_COMPILE_FLAGS)
|
||||
COMPILE_CMMFLAGS = $(OS_COMPILE_CMMFLAGS) $(MOZBUILD_CMMFLAGS) $(EXTRA_COMPILE_FLAGS)
|
||||
ASFLAGS += $(EXTRA_ASSEMBLER_FLAGS)
|
||||
|
||||
ifndef CROSS_COMPILE
|
||||
|
|
48
configure.in
48
configure.in
|
@ -1299,16 +1299,6 @@ if test "$GNU_CC"; then
|
|||
CFLAGS="$CFLAGS -fno-strict-aliasing"
|
||||
MKSHLIB='$(CXX) $(CXXFLAGS) $(DSO_PIC_CFLAGS) $(DSO_LDOPTS) -Wl,-h,$(notdir $@) -o $@'
|
||||
MKCSHLIB='$(CC) $(CFLAGS) $(DSO_PIC_CFLAGS) $(DSO_LDOPTS) -Wl,-h,$(notdir $@) -o $@'
|
||||
DSO_LDOPTS='-shared'
|
||||
if test "$GCC_USE_GNU_LD"; then
|
||||
# Some tools like ASan use a runtime library that is only
|
||||
# linked against executables, so we must allow undefined
|
||||
# symbols for shared objects in some cases.
|
||||
if test -z "$MOZ_NO_WLZDEFS"; then
|
||||
# Don't allow undefined symbols in libraries
|
||||
DSO_LDOPTS="$DSO_LDOPTS -Wl,-z,defs"
|
||||
fi
|
||||
fi
|
||||
WARNINGS_AS_ERRORS='-Werror'
|
||||
DSO_CFLAGS=''
|
||||
DSO_PIC_CFLAGS='-fPIC'
|
||||
|
@ -1343,6 +1333,14 @@ if test "$GNU_CC"; then
|
|||
AC_MSG_RESULT([no])
|
||||
LDFLAGS=$_SAVE_LDFLAGS)
|
||||
|
||||
AC_MSG_CHECKING([for --ignore-unresolved-symbol option to ld])
|
||||
HAVE_LINKER_SUPPORT_IGNORE_UNRESOLVED=
|
||||
_SAVE_LDFLAGS=$LDFLAGS
|
||||
LDFLAGS="$LDFLAGS -Wl,--ignore-unresolved-symbol,environ"
|
||||
AC_TRY_LINK(,,AC_MSG_RESULT([yes])
|
||||
[HAVE_LINKER_SUPPORT_IGNORE_UNRESOLVED=1],
|
||||
AC_MSG_RESULT([no]))
|
||||
LDFLAGS=$_SAVE_LDFLAGS
|
||||
|
||||
# Check for -mssse3 on $CC
|
||||
AC_MSG_CHECKING([if toolchain supports -mssse3 option])
|
||||
|
@ -1378,6 +1376,28 @@ if test "$GNU_CC"; then
|
|||
fi
|
||||
esac
|
||||
|
||||
DSO_LDOPTS='-shared'
|
||||
if test "$GCC_USE_GNU_LD"; then
|
||||
# Some tools like ASan use a runtime library that is only
|
||||
# linked against executables, so we must allow undefined
|
||||
# symbols for shared objects in some cases.
|
||||
if test -z "$MOZ_NO_WLZDEFS"; then
|
||||
# Don't allow undefined symbols in libraries
|
||||
DSO_LDOPTS="$DSO_LDOPTS -Wl,-z,defs"
|
||||
|
||||
# BSDs need `environ' exposed for posix_spawn (bug 753046)
|
||||
case "$OS_TARGET" in
|
||||
DragonFly|FreeBSD|NetBSD|OpenBSD)
|
||||
if test -n "$HAVE_LINKER_SUPPORT_IGNORE_UNRESOLVED"; then
|
||||
DSO_LDOPTS="$DSO_LDOPTS -Wl,--ignore-unresolved-symbol,environ"
|
||||
else
|
||||
DSO_LDOPTS="$DSO_LDOPTS -Wl,--warn-unresolved-symbols"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
fi
|
||||
|
||||
# Turn on GNU-specific warnings:
|
||||
# -Wall - turn on a lot of warnings
|
||||
# -Wpointer-arith - good to have
|
||||
|
@ -6270,6 +6290,14 @@ if test -n "$MOZ_DISABLE_CRYPTOLEGACY"; then
|
|||
fi
|
||||
AC_SUBST(MOZ_DISABLE_CRYPTOLEGACY)
|
||||
|
||||
dnl ========================================================
|
||||
dnl = Disable EV certificate verification
|
||||
dnl ========================================================
|
||||
if test -n "$MOZ_NO_EV_CERTS"; then
|
||||
AC_DEFINE(MOZ_NO_EV_CERTS)
|
||||
fi
|
||||
AC_SUBST(MOZ_NO_EV_CERTS)
|
||||
|
||||
dnl ========================================================
|
||||
dnl = Disable libpkix
|
||||
dnl ========================================================
|
||||
|
|
|
@ -1643,20 +1643,31 @@ public:
|
|||
// owning Documents needs it to animate; otherwise it can suspend.
|
||||
virtual void SetImagesNeedAnimating(bool aAnimating) = 0;
|
||||
|
||||
enum SuppressionType {
|
||||
eAnimationsOnly = 0x1,
|
||||
|
||||
// Note that suppressing events also suppresses animation frames, so
|
||||
// there's no need to split out events in its own bitmask.
|
||||
eEvents = 0x3,
|
||||
};
|
||||
|
||||
/**
|
||||
* Prevents user initiated events from being dispatched to the document and
|
||||
* subdocuments.
|
||||
*/
|
||||
virtual void SuppressEventHandling(uint32_t aIncrease = 1) = 0;
|
||||
virtual void SuppressEventHandling(SuppressionType aWhat,
|
||||
uint32_t aIncrease = 1) = 0;
|
||||
|
||||
/**
|
||||
* Unsuppress event handling.
|
||||
* @param aFireEvents If true, delayed events (focus/blur) will be fired
|
||||
* asynchronously.
|
||||
*/
|
||||
virtual void UnsuppressEventHandlingAndFireEvents(bool aFireEvents) = 0;
|
||||
virtual void UnsuppressEventHandlingAndFireEvents(SuppressionType aWhat,
|
||||
bool aFireEvents) = 0;
|
||||
|
||||
uint32_t EventHandlingSuppressed() const { return mEventsSuppressed; }
|
||||
uint32_t AnimationsPaused() const { return mAnimationsPaused; }
|
||||
|
||||
bool IsEventHandlingEnabled() {
|
||||
return !EventHandlingSuppressed() && mScriptGlobalObject;
|
||||
|
@ -2487,6 +2498,8 @@ protected:
|
|||
|
||||
uint32_t mEventsSuppressed;
|
||||
|
||||
uint32_t mAnimationsPaused;
|
||||
|
||||
/**
|
||||
* The number number of external scripts (ones with the src attribute) that
|
||||
* have this document as their owner and that are being evaluated right now.
|
||||
|
|
|
@ -49,13 +49,13 @@
|
|||
#include "nsIMIMEService.h"
|
||||
#include "imgIContainer.h"
|
||||
#include "imgIRequest.h"
|
||||
#include "nsDOMDataTransfer.h"
|
||||
#include "mozilla/dom/DataTransfer.h"
|
||||
#include "nsIMIMEInfo.h"
|
||||
#include "nsRange.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "mozilla/dom/HTMLAreaElement.h"
|
||||
|
||||
using mozilla::dom::HTMLAreaElement;
|
||||
using namespace mozilla::dom;
|
||||
|
||||
class MOZ_STACK_CLASS DragDataProducer
|
||||
{
|
||||
|
@ -64,18 +64,18 @@ public:
|
|||
nsIContent* aTarget,
|
||||
nsIContent* aSelectionTargetNode,
|
||||
bool aIsAltKeyPressed);
|
||||
nsresult Produce(nsDOMDataTransfer* aDataTransfer,
|
||||
nsresult Produce(DataTransfer* aDataTransfer,
|
||||
bool* aCanDrag,
|
||||
nsISelection** aSelection,
|
||||
nsIContent** aDragNode);
|
||||
|
||||
private:
|
||||
void AddString(nsDOMDataTransfer* aDataTransfer,
|
||||
void AddString(DataTransfer* aDataTransfer,
|
||||
const nsAString& aFlavor,
|
||||
const nsAString& aData,
|
||||
nsIPrincipal* aPrincipal);
|
||||
nsresult AddStringsToDataTransfer(nsIContent* aDragNode,
|
||||
nsDOMDataTransfer* aDataTransfer);
|
||||
DataTransfer* aDataTransfer);
|
||||
static nsresult GetDraggableSelectionData(nsISelection* inSelection,
|
||||
nsIContent* inRealTargetNode,
|
||||
nsIContent **outImageOrLinkNode,
|
||||
|
@ -112,7 +112,7 @@ nsContentAreaDragDrop::GetDragData(nsPIDOMWindow* aWindow,
|
|||
nsIContent* aTarget,
|
||||
nsIContent* aSelectionTargetNode,
|
||||
bool aIsAltKeyPressed,
|
||||
nsDOMDataTransfer* aDataTransfer,
|
||||
DataTransfer* aDataTransfer,
|
||||
bool* aCanDrag,
|
||||
nsISelection** aSelection,
|
||||
nsIContent** aDragNode)
|
||||
|
@ -354,7 +354,7 @@ DragDataProducer::GetNodeString(nsIContent* inNode,
|
|||
}
|
||||
|
||||
nsresult
|
||||
DragDataProducer::Produce(nsDOMDataTransfer* aDataTransfer,
|
||||
DragDataProducer::Produce(DataTransfer* aDataTransfer,
|
||||
bool* aCanDrag,
|
||||
nsISelection** aSelection,
|
||||
nsIContent** aDragNode)
|
||||
|
@ -703,7 +703,7 @@ DragDataProducer::Produce(nsDOMDataTransfer* aDataTransfer,
|
|||
}
|
||||
|
||||
void
|
||||
DragDataProducer::AddString(nsDOMDataTransfer* aDataTransfer,
|
||||
DragDataProducer::AddString(DataTransfer* aDataTransfer,
|
||||
const nsAString& aFlavor,
|
||||
const nsAString& aData,
|
||||
nsIPrincipal* aPrincipal)
|
||||
|
@ -717,7 +717,7 @@ DragDataProducer::AddString(nsDOMDataTransfer* aDataTransfer,
|
|||
|
||||
nsresult
|
||||
DragDataProducer::AddStringsToDataTransfer(nsIContent* aDragNode,
|
||||
nsDOMDataTransfer* aDataTransfer)
|
||||
DataTransfer* aDataTransfer)
|
||||
{
|
||||
NS_ASSERTION(aDragNode, "adding strings for null node");
|
||||
|
||||
|
|
|
@ -21,7 +21,12 @@ class nsIContent;
|
|||
class nsIURI;
|
||||
class nsIFile;
|
||||
class nsISimpleEnumerator;
|
||||
class nsDOMDataTransfer;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
class DataTransfer;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// class nsContentAreaDragDrop, used to generate the dragdata
|
||||
|
@ -52,7 +57,7 @@ public:
|
|||
nsIContent* aTarget,
|
||||
nsIContent* aSelectionTargetNode,
|
||||
bool aIsAltKeyPressed,
|
||||
nsDOMDataTransfer* aDataTransfer,
|
||||
mozilla::dom::DataTransfer* aDataTransfer,
|
||||
bool* aCanDrag,
|
||||
nsISelection** aSelection,
|
||||
nsIContent** aDragNode);
|
||||
|
|
|
@ -67,7 +67,7 @@
|
|||
#include "nsDocShellCID.h"
|
||||
#include "nsDocument.h"
|
||||
#include "nsDOMCID.h"
|
||||
#include "nsDOMDataTransfer.h"
|
||||
#include "mozilla/dom/DataTransfer.h"
|
||||
#include "nsDOMJSUtils.h"
|
||||
#include "nsDOMMutationObserver.h"
|
||||
#include "nsDOMTouchEvent.h"
|
||||
|
@ -4974,16 +4974,20 @@ nsContentUtils::SetDataTransferInEvent(WidgetDragEvent* aDragEvent)
|
|||
nsCOMPtr<nsIDragSession> dragSession = GetDragSession();
|
||||
NS_ENSURE_TRUE(dragSession, NS_OK); // no drag in progress
|
||||
|
||||
nsCOMPtr<nsIDOMDataTransfer> initialDataTransfer;
|
||||
dragSession->GetDataTransfer(getter_AddRefs(initialDataTransfer));
|
||||
if (!initialDataTransfer) {
|
||||
nsCOMPtr<nsIDOMDataTransfer> dataTransfer;
|
||||
nsCOMPtr<DataTransfer> initialDataTransfer;
|
||||
dragSession->GetDataTransfer(getter_AddRefs(dataTransfer));
|
||||
if (dataTransfer) {
|
||||
initialDataTransfer = do_QueryInterface(dataTransfer);
|
||||
if (!initialDataTransfer) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
} else {
|
||||
// A dataTransfer won't exist when a drag was started by some other
|
||||
// means, for instance calling the drag service directly, or a drag
|
||||
// from another application. In either case, a new dataTransfer should
|
||||
// be created that reflects the data.
|
||||
initialDataTransfer = new nsDOMDataTransfer(aDragEvent->message, true, -1);
|
||||
|
||||
NS_ENSURE_TRUE(initialDataTransfer, NS_ERROR_OUT_OF_MEMORY);
|
||||
initialDataTransfer = new DataTransfer(aDragEvent->target, aDragEvent->message, true, -1);
|
||||
|
||||
// now set it in the drag session so we don't need to create it again
|
||||
dragSession->SetDataTransfer(initialDataTransfer);
|
||||
|
@ -4996,7 +5000,7 @@ nsContentUtils::SetDataTransferInEvent(WidgetDragEvent* aDragEvent)
|
|||
}
|
||||
|
||||
// each event should use a clone of the original dataTransfer.
|
||||
initialDataTransfer->Clone(aDragEvent->message, aDragEvent->userCancelled,
|
||||
initialDataTransfer->Clone(aDragEvent->target, aDragEvent->message, aDragEvent->userCancelled,
|
||||
isCrossDomainSubFrameDrop,
|
||||
getter_AddRefs(aDragEvent->dataTransfer));
|
||||
NS_ENSURE_TRUE(aDragEvent->dataTransfer, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
#include "nsIPresShell.h"
|
||||
#include "nsFocusManager.h"
|
||||
#include "nsEventDispatcher.h"
|
||||
#include "nsDOMDataTransfer.h"
|
||||
#include "mozilla/dom/DataTransfer.h"
|
||||
|
||||
#include "nsIDocShell.h"
|
||||
#include "nsIContentViewerEdit.h"
|
||||
|
@ -53,6 +53,7 @@
|
|||
#include "mozilla/Preferences.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
|
||||
nsresult NS_NewDomSelection(nsISelection **aDomSelection);
|
||||
|
||||
|
@ -643,9 +644,10 @@ nsCopySupport::FireClipboardEvent(int32_t aType, int32_t aClipboardType, nsIPres
|
|||
|
||||
// next, fire the cut, copy or paste event
|
||||
bool doDefault = true;
|
||||
nsRefPtr<nsDOMDataTransfer> clipboardData;
|
||||
nsRefPtr<DataTransfer> clipboardData;
|
||||
if (chromeShell || Preferences::GetBool("dom.event.clipboardevents.enabled", true)) {
|
||||
clipboardData = new nsDOMDataTransfer(aType, aType == NS_PASTE, aClipboardType);
|
||||
clipboardData =
|
||||
new DataTransfer(piWindow, aType, aType == NS_PASTE, aClipboardType);
|
||||
|
||||
nsEventStatus status = nsEventStatus_eIgnore;
|
||||
InternalClipboardEvent evt(true, aType);
|
||||
|
|
|
@ -9145,22 +9145,41 @@ nsIDocument::GetReadyState(nsAString& aReadyState) const
|
|||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
struct SuppressArgs
|
||||
{
|
||||
nsIDocument::SuppressionType mWhat;
|
||||
uint32_t mIncrease;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
static bool
|
||||
SuppressEventHandlingInDocument(nsIDocument* aDocument, void* aData)
|
||||
{
|
||||
aDocument->SuppressEventHandling(*static_cast<uint32_t*>(aData));
|
||||
SuppressArgs* args = static_cast<SuppressArgs*>(aData);
|
||||
aDocument->SuppressEventHandling(args->mWhat, args->mIncrease);
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
nsDocument::SuppressEventHandling(uint32_t aIncrease)
|
||||
nsDocument::SuppressEventHandling(nsIDocument::SuppressionType aWhat,
|
||||
uint32_t aIncrease)
|
||||
{
|
||||
if (mEventsSuppressed == 0 && aIncrease != 0 && mPresShell &&
|
||||
mScriptGlobalObject) {
|
||||
if (mEventsSuppressed == 0 && mAnimationsPaused == 0 &&
|
||||
aIncrease != 0 && mPresShell && mScriptGlobalObject) {
|
||||
RevokeAnimationFrameNotifications();
|
||||
}
|
||||
mEventsSuppressed += aIncrease;
|
||||
EnumerateSubDocuments(SuppressEventHandlingInDocument, &aIncrease);
|
||||
|
||||
if (aWhat == eAnimationsOnly) {
|
||||
mAnimationsPaused += aIncrease;
|
||||
} else {
|
||||
mEventsSuppressed += aIncrease;
|
||||
}
|
||||
|
||||
SuppressArgs args = { aWhat, aIncrease };
|
||||
EnumerateSubDocuments(SuppressEventHandlingInDocument, &args);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -9314,30 +9333,59 @@ private:
|
|||
nsTArray<nsCOMPtr<nsIDocument> > mDocuments;
|
||||
};
|
||||
|
||||
static bool
|
||||
GetAndUnsuppressSubDocuments(nsIDocument* aDocument, void* aData)
|
||||
namespace {
|
||||
|
||||
struct UnsuppressArgs
|
||||
{
|
||||
uint32_t suppression = aDocument->EventHandlingSuppressed();
|
||||
if (suppression > 0) {
|
||||
static_cast<nsDocument*>(aDocument)->DecreaseEventSuppression();
|
||||
UnsuppressArgs(nsIDocument::SuppressionType aWhat)
|
||||
: mWhat(aWhat)
|
||||
{
|
||||
}
|
||||
nsTArray<nsCOMPtr<nsIDocument> >* docs =
|
||||
static_cast<nsTArray<nsCOMPtr<nsIDocument> >* >(aData);
|
||||
docs->AppendElement(aDocument);
|
||||
aDocument->EnumerateSubDocuments(GetAndUnsuppressSubDocuments, docs);
|
||||
|
||||
nsIDocument::SuppressionType mWhat;
|
||||
nsTArray<nsCOMPtr<nsIDocument>> mDocs;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
static bool
|
||||
GetAndUnsuppressSubDocuments(nsIDocument* aDocument,
|
||||
void* aData)
|
||||
{
|
||||
UnsuppressArgs* args = static_cast<UnsuppressArgs*>(aData);
|
||||
if (args->mWhat != nsIDocument::eAnimationsOnly &&
|
||||
aDocument->EventHandlingSuppressed() > 0) {
|
||||
static_cast<nsDocument*>(aDocument)->DecreaseEventSuppression();
|
||||
} else if (args->mWhat == nsIDocument::eAnimationsOnly &&
|
||||
aDocument->AnimationsPaused()) {
|
||||
static_cast<nsDocument*>(aDocument)->ResumeAnimations();
|
||||
}
|
||||
|
||||
if (args->mWhat != nsIDocument::eAnimationsOnly) {
|
||||
// No need to remember documents if we only care about animation frames.
|
||||
args->mDocs.AppendElement(aDocument);
|
||||
}
|
||||
|
||||
aDocument->EnumerateSubDocuments(GetAndUnsuppressSubDocuments, aData);
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
nsDocument::UnsuppressEventHandlingAndFireEvents(bool aFireEvents)
|
||||
nsDocument::UnsuppressEventHandlingAndFireEvents(nsIDocument::SuppressionType aWhat,
|
||||
bool aFireEvents)
|
||||
{
|
||||
nsTArray<nsCOMPtr<nsIDocument> > documents;
|
||||
GetAndUnsuppressSubDocuments(this, &documents);
|
||||
UnsuppressArgs args(aWhat);
|
||||
GetAndUnsuppressSubDocuments(this, &args);
|
||||
|
||||
if (aWhat == nsIDocument::eAnimationsOnly) {
|
||||
// No need to fire events if we only care about animations here.
|
||||
return;
|
||||
}
|
||||
|
||||
if (aFireEvents) {
|
||||
NS_DispatchToCurrentThread(new nsDelayedEventDispatcher(documents));
|
||||
NS_DispatchToCurrentThread(new nsDelayedEventDispatcher(args.mDocs));
|
||||
} else {
|
||||
FireOrClearDelayedEvents(documents, false);
|
||||
FireOrClearDelayedEvents(args.mDocs, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -980,15 +980,24 @@ public:
|
|||
|
||||
void SetImagesNeedAnimating(bool aAnimating) MOZ_OVERRIDE;
|
||||
|
||||
virtual void SuppressEventHandling(uint32_t aIncrease) MOZ_OVERRIDE;
|
||||
virtual void SuppressEventHandling(SuppressionType aWhat,
|
||||
uint32_t aIncrease) MOZ_OVERRIDE;
|
||||
|
||||
virtual void UnsuppressEventHandlingAndFireEvents(SuppressionType aWhat,
|
||||
bool aFireEvents) MOZ_OVERRIDE;
|
||||
|
||||
virtual void UnsuppressEventHandlingAndFireEvents(bool aFireEvents) MOZ_OVERRIDE;
|
||||
|
||||
void DecreaseEventSuppression() {
|
||||
MOZ_ASSERT(mEventsSuppressed);
|
||||
--mEventsSuppressed;
|
||||
MaybeRescheduleAnimationFrameNotifications();
|
||||
}
|
||||
|
||||
void ResumeAnimations() {
|
||||
MOZ_ASSERT(mAnimationsPaused);
|
||||
--mAnimationsPaused;
|
||||
MaybeRescheduleAnimationFrameNotifications();
|
||||
}
|
||||
|
||||
virtual nsIDocument* GetTemplateContentsOwner() MOZ_OVERRIDE;
|
||||
|
||||
NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS_AMBIGUOUS(nsDocument,
|
||||
|
|
|
@ -1821,6 +1821,7 @@ GK_ATOM(flexContainerFrame, "FlexContainerFrame")
|
|||
GK_ATOM(formControlFrame, "FormControlFrame") // radio or checkbox
|
||||
GK_ATOM(frameSetFrame, "FrameSetFrame")
|
||||
GK_ATOM(gfxButtonControlFrame, "gfxButtonControlFrame")
|
||||
GK_ATOM(gridContainerFrame, "GridContainerFrame")
|
||||
GK_ATOM(HTMLButtonControlFrame, "HTMLButtonControlFrame")
|
||||
GK_ATOM(HTMLCanvasFrame, "HTMLCanvasFrame")
|
||||
GK_ATOM(subDocumentFrame, "subDocumentFrame")
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
#include "nsString.h"
|
||||
#include "nsReadableUtils.h"
|
||||
#include "nsTraceRefcnt.h"
|
||||
#include "nsISupportsImpl.h"
|
||||
|
||||
class nsString;
|
||||
class nsCString;
|
||||
|
|
|
@ -2872,7 +2872,7 @@ nsXMLHttpRequest::Send(nsIVariant* aVariant, const Nullable<RequestBody>& aBody)
|
|||
(suspendedWindow = suspendedWindow->GetCurrentInnerWindow())) {
|
||||
suspendedDoc = suspendedWindow->GetExtantDoc();
|
||||
if (suspendedDoc) {
|
||||
suspendedDoc->SuppressEventHandling();
|
||||
suspendedDoc->SuppressEventHandling(nsIDocument::eEvents);
|
||||
}
|
||||
suspendedWindow->SuspendTimeouts(1, false);
|
||||
resumeTimeoutRunnable = new nsResumeTimeoutsEvent(suspendedWindow);
|
||||
|
@ -2896,7 +2896,8 @@ nsXMLHttpRequest::Send(nsIVariant* aVariant, const Nullable<RequestBody>& aBody)
|
|||
}
|
||||
|
||||
if (suspendedDoc) {
|
||||
suspendedDoc->UnsuppressEventHandlingAndFireEvents(true);
|
||||
suspendedDoc->UnsuppressEventHandlingAndFireEvents(nsIDocument::eEvents,
|
||||
true);
|
||||
}
|
||||
|
||||
if (resumeTimeoutRunnable) {
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
#include <stdint.h>
|
||||
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsTraceRefcnt.h"
|
||||
#include "nsISupportsImpl.h"
|
||||
#include "js/GCAPI.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
|
|
@ -3342,6 +3342,12 @@ WebGLContext::CompressedTexImage2D(GLenum target, GLint level, GLenum internalfo
|
|||
return;
|
||||
}
|
||||
|
||||
if (!ValidateCompTexImageSize(target, level, internalformat, 0, 0,
|
||||
width, height, width, height, func))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
MakeContextCurrent();
|
||||
gl->fCompressedTexImage2D(target, level, internalformat, width, height, border, byteLength, view.Data());
|
||||
WebGLTexture* tex = activeBoundTextureForTarget(target);
|
||||
|
@ -3376,6 +3382,10 @@ WebGLContext::CompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset,
|
|||
MOZ_ASSERT(tex);
|
||||
WebGLTexture::ImageInfo& levelInfo = tex->ImageInfoAt(target, level);
|
||||
|
||||
uint32_t byteLength = view.Length();
|
||||
if (!ValidateCompTexImageDataSize(target, format, width, height, byteLength, func))
|
||||
return;
|
||||
|
||||
if (!ValidateCompTexImageSize(target, level, format,
|
||||
xoffset, yoffset,
|
||||
width, height,
|
||||
|
@ -3385,10 +3395,6 @@ WebGLContext::CompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset,
|
|||
return;
|
||||
}
|
||||
|
||||
uint32_t byteLength = view.Length();
|
||||
if (!ValidateCompTexImageDataSize(target, format, width, height, byteLength, func))
|
||||
return;
|
||||
|
||||
if (levelInfo.HasUninitializedImageData())
|
||||
tex->DoDeferredImageInitialization(target, level);
|
||||
|
||||
|
|
|
@ -776,26 +776,54 @@ WebGLContext::ValidateCompTexImageSize(GLenum target, GLint level, GLenum format
|
|||
|
||||
/* The size must be a multiple of blockWidth and blockHeight,
|
||||
* or must be using offset+size that exactly hits the edge.
|
||||
* Important for small mipmap levels. (s3tc extension appears
|
||||
* to have changed and old code that checks 1x1, 2x2 doesn't
|
||||
* appear necessary anymore)
|
||||
* Important for small mipmap levels.
|
||||
*/
|
||||
if ((width % blockWidth != 0) &&
|
||||
(xoffset + width != (GLint) levelWidth))
|
||||
{
|
||||
ErrorInvalidOperation("%s: width must be multiple of %d or "
|
||||
"xoffset + width must be %d",
|
||||
InfoFrom(func), blockWidth, levelWidth);
|
||||
return false;
|
||||
/* https://www.khronos.org/registry/webgl/extensions/WEBGL_compressed_texture_s3tc/
|
||||
* "When level equals zero width and height must be a multiple of 4. When
|
||||
* level is greater than 0 width and height must be 0, 1, 2 or a multiple of 4.
|
||||
* If they are not an INVALID_OPERATION error is generated."
|
||||
*/
|
||||
if (level == 0) {
|
||||
if (width % blockWidth != 0) {
|
||||
ErrorInvalidOperation("%s: width of level 0 must be multple of %d",
|
||||
InfoFrom(func), blockWidth);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (height % blockHeight != 0) {
|
||||
ErrorInvalidOperation("%s: height of level 0 must be multipel of %d",
|
||||
InfoFrom(func), blockHeight);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (level > 0) {
|
||||
if (width % blockWidth != 0 && width > 2) {
|
||||
ErrorInvalidOperation("%s: width of level %d must be multiple"
|
||||
" of %d or 0, 1, 2",
|
||||
InfoFrom(func), level, blockWidth);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (height % blockHeight != 0 && height > 2) {
|
||||
ErrorInvalidOperation("%s: height of level %d must be multiple"
|
||||
" of %d or 0, 1, 2",
|
||||
InfoFrom(func), level, blockHeight);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if ((height % blockHeight != 0) &&
|
||||
(yoffset + height != (GLint) levelHeight))
|
||||
{
|
||||
ErrorInvalidOperation("%s: height must be multiple of %d or "
|
||||
"yoffset + height must be %d",
|
||||
InfoFrom(func), blockHeight, levelHeight);
|
||||
return false;
|
||||
if (IsSubFunc(func)) {
|
||||
if ((xoffset % blockWidth) != 0) {
|
||||
ErrorInvalidOperation("%s: xoffset must be multiple of %d",
|
||||
InfoFrom(func), blockWidth);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (yoffset % blockHeight != 0) {
|
||||
ErrorInvalidOperation("%s: yoffset must be multiple of %d",
|
||||
InfoFrom(func), blockHeight);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1153,10 +1181,26 @@ WebGLContext::ValidateTexImageFormatAndType(GLenum format, GLenum type, WebGLTex
|
|||
validCombo = (type == LOCAL_GL_UNSIGNED_INT_24_8);
|
||||
break;
|
||||
|
||||
case LOCAL_GL_ATC_RGB:
|
||||
case LOCAL_GL_ATC_RGBA_EXPLICIT_ALPHA:
|
||||
case LOCAL_GL_ATC_RGBA_INTERPOLATED_ALPHA:
|
||||
case LOCAL_GL_COMPRESSED_RGB_PVRTC_2BPPV1:
|
||||
case LOCAL_GL_COMPRESSED_RGB_PVRTC_4BPPV1:
|
||||
case LOCAL_GL_COMPRESSED_RGBA_PVRTC_2BPPV1:
|
||||
case LOCAL_GL_COMPRESSED_RGBA_PVRTC_4BPPV1:
|
||||
case LOCAL_GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
|
||||
case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
|
||||
case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
|
||||
case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
|
||||
validCombo = (type == LOCAL_GL_UNSIGNED_BYTE);
|
||||
break;
|
||||
|
||||
default:
|
||||
// Only valid formats should be passed to the switch stmt.
|
||||
MOZ_ASSERT("Invalid format");
|
||||
return false;
|
||||
MOZ_ASSERT(false, "Unexpected format and type combo. How'd this happen?");
|
||||
validCombo = false;
|
||||
// Fall through to return an InvalidOperations. This will alert us to the
|
||||
// unexpected case that needs fixing in builds without asserts.
|
||||
}
|
||||
|
||||
if (!validCombo)
|
||||
|
|
|
@ -515,12 +515,11 @@ AudioNodeStream::FinishOutput()
|
|||
}
|
||||
}
|
||||
|
||||
TrackTicks
|
||||
AudioNodeStream::TicksFromDestinationTime(MediaStream* aDestination,
|
||||
double aSeconds)
|
||||
double
|
||||
AudioNodeStream::TimeFromDestinationTime(AudioNodeStream* aDestination,
|
||||
double aSeconds)
|
||||
{
|
||||
MOZ_ASSERT(aDestination->AsAudioNodeStream() &&
|
||||
aDestination->AsAudioNodeStream()->SampleRate() == SampleRate());
|
||||
MOZ_ASSERT(aDestination->SampleRate() == SampleRate());
|
||||
|
||||
double destinationSeconds = std::max(0.0, aSeconds);
|
||||
StreamTime streamTime = SecondsToMediaTime(destinationSeconds);
|
||||
|
@ -531,6 +530,17 @@ AudioNodeStream::TicksFromDestinationTime(MediaStream* aDestination,
|
|||
StreamTime thisStreamTime = GraphTimeToStreamTimeOptimistic(graphTime);
|
||||
double thisSeconds = MediaTimeToSeconds(thisStreamTime) + offset;
|
||||
MOZ_ASSERT(thisSeconds >= 0.0);
|
||||
return thisSeconds;
|
||||
}
|
||||
|
||||
TrackTicks
|
||||
AudioNodeStream::TicksFromDestinationTime(MediaStream* aDestination,
|
||||
double aSeconds)
|
||||
{
|
||||
AudioNodeStream* destination = aDestination->AsAudioNodeStream();
|
||||
MOZ_ASSERT(destination);
|
||||
|
||||
double thisSeconds = TimeFromDestinationTime(destination, aSeconds);
|
||||
// Round to nearest
|
||||
TrackTicks ticks = thisSeconds * SampleRate() + 0.5;
|
||||
return ticks;
|
||||
|
|
|
@ -128,6 +128,12 @@ public:
|
|||
AudioNodeEngine* Engine() { return mEngine; }
|
||||
TrackRate SampleRate() const { return mSampleRate; }
|
||||
|
||||
/**
|
||||
* Convert a time in seconds on the destination stream to seconds
|
||||
* on this stream.
|
||||
*/
|
||||
double TimeFromDestinationTime(AudioNodeStream* aDestination,
|
||||
double aSeconds);
|
||||
/**
|
||||
* Convert a time in seconds on the destination stream to TrackTicks
|
||||
* on this stream.
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
#include <algorithm>
|
||||
|
||||
#include "nsISeekableStream.h"
|
||||
#include "nsTraceRefcnt.h"
|
||||
#include "nsISupportsImpl.h"
|
||||
#include "prenv.h"
|
||||
#include "prlog.h"
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
[DEFAULT]
|
||||
support-files = seek.webm
|
||||
support-files = seek.webm seek.webm^headers^
|
||||
|
||||
[test_MediaSource.html]
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Cache-Control: no-store
|
|
@ -14,7 +14,7 @@
|
|||
#include "MediaDecoderReader.h"
|
||||
#include "OggCodecState.h"
|
||||
#include "OggDecoder.h"
|
||||
#include "nsTraceRefcnt.h"
|
||||
#include "nsISupportsImpl.h"
|
||||
#include "VideoUtils.h"
|
||||
#include <algorithm>
|
||||
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Cache-Control: no-store
|
|
@ -0,0 +1 @@
|
|||
Cache-Control: no-store
|
|
@ -0,0 +1 @@
|
|||
Cache-Control: no-store
|
|
@ -0,0 +1 @@
|
|||
Cache-Control: no-store
|
|
@ -0,0 +1 @@
|
|||
Cache-Control: no-store
|
|
@ -0,0 +1 @@
|
|||
Cache-Control: no-store
|
|
@ -0,0 +1 @@
|
|||
Cache-Control: no-store
|
|
@ -0,0 +1 @@
|
|||
Cache-Control: no-store
|
|
@ -0,0 +1 @@
|
|||
Cache-Control: no-store
|
|
@ -0,0 +1 @@
|
|||
Cache-Control: no-store
|
|
@ -0,0 +1 @@
|
|||
Cache-Control: no-store
|
|
@ -0,0 +1 @@
|
|||
Cache-Control: no-store
|
|
@ -0,0 +1 @@
|
|||
Cache-Control: no-store
|
|
@ -0,0 +1 @@
|
|||
Cache-Control: no-store
|
|
@ -0,0 +1 @@
|
|||
Cache-Control: no-store
|
|
@ -0,0 +1 @@
|
|||
Cache-Control: no-store
|
|
@ -0,0 +1 @@
|
|||
Cache-Control: no-store
|
|
@ -0,0 +1 @@
|
|||
Cache-Control: no-store
|
|
@ -0,0 +1 @@
|
|||
Cache-Control: no-store
|
|
@ -0,0 +1 @@
|
|||
Cache-Control: no-store
|
|
@ -0,0 +1 @@
|
|||
Cache-Control: no-store
|
|
@ -0,0 +1 @@
|
|||
Cache-Control: no-store
|
|
@ -1,2 +1,2 @@
|
|||
X-Content-Duration: 1.96
|
||||
|
||||
Cache-Control: no-store
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Cache-Control: no-store
|
|
@ -0,0 +1 @@
|
|||
Cache-Control: no-store
|
|
@ -0,0 +1 @@
|
|||
Cache-Control: no-store
|
|
@ -0,0 +1 @@
|
|||
Cache-Control: no-store
|
|
@ -0,0 +1 @@
|
|||
Cache-Control: no-store
|
|
@ -0,0 +1 @@
|
|||
Cache-Control: no-store
|
|
@ -0,0 +1 @@
|
|||
Cache-Control: no-store
|
|
@ -0,0 +1 @@
|
|||
Cache-Control: no-store
|
|
@ -0,0 +1 @@
|
|||
Cache-Control: no-store
|
|
@ -1,2 +1,2 @@
|
|||
X-Content-Duration: 9000
|
||||
|
||||
Cache-Control: no-store
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Cache-Control: no-store
|
|
@ -0,0 +1 @@
|
|||
Cache-Control: no-store
|
|
@ -0,0 +1 @@
|
|||
Cache-Control: no-store
|
|
@ -0,0 +1 @@
|
|||
Cache-Control: no-store
|
|
@ -0,0 +1 @@
|
|||
Cache-Control: no-store
|
|
@ -0,0 +1 @@
|
|||
Cache-Control: no-store
|
|
@ -0,0 +1 @@
|
|||
Cache-Control: no-store
|
|
@ -0,0 +1 @@
|
|||
Cache-Control: no-store
|
|
@ -0,0 +1 @@
|
|||
Cache-Control: no-store
|
|
@ -0,0 +1 @@
|
|||
Cache-Control: no-store
|
|
@ -0,0 +1 @@
|
|||
Cache-Control: no-store
|
|
@ -0,0 +1 @@
|
|||
Cache-Control: no-store
|
|
@ -0,0 +1 @@
|
|||
Cache-Control: no-store
|
|
@ -0,0 +1 @@
|
|||
Cache-Control: no-store
|
|
@ -0,0 +1 @@
|
|||
Cache-Control: no-store
|
|
@ -0,0 +1 @@
|
|||
Cache-Control: no-store
|
|
@ -0,0 +1 @@
|
|||
Cache-Control: no-store
|
|
@ -0,0 +1 @@
|
|||
Cache-Control: no-store
|
|
@ -0,0 +1 @@
|
|||
Cache-Control: no-store
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче