Merge mozilla-central to mozilla-inbound. CLOSED TREE

This commit is contained in:
Csoregi Natalia 2018-11-07 11:59:33 +02:00
Родитель b682338978 6e0e603f48
Коммит aca35453cf
326 изменённых файлов: 6003 добавлений и 3829 удалений

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

@ -206,10 +206,10 @@ AccessibleWrap::GetSelectionBounds(int32_t* aStartOffset, int32_t* aEndOffset) {
return false;
}
uint64_t
uint32_t
AccessibleWrap::GetFlags(role aRole, uint64_t aState)
{
uint64_t flags = 0;
uint32_t flags = 0;
if (aState & states::CHECKABLE) {
flags |= java::SessionAccessibility::FLAG_CHECKABLE;
}
@ -388,7 +388,7 @@ AccessibleWrap::ToBundle()
role role = WrapperRole();
uint64_t state = State();
uint64_t flags = GetFlags(role, state);
uint32_t flags = GetFlags(role, state);
GECKOBUNDLE_PUT(nodeInfo, "flags", java::sdk::Integer::ValueOf(flags));
GECKOBUNDLE_PUT(nodeInfo, "className", java::sdk::Integer::ValueOf(AndroidClass()));
@ -539,3 +539,44 @@ AccessibleWrap::ToBundle()
return nodeInfo;
}
mozilla::java::GeckoBundle::LocalRef
AccessibleWrap::ToSmallBundle()
{
return ToSmallBundle(State(), Bounds());
}
mozilla::java::GeckoBundle::LocalRef
AccessibleWrap::ToSmallBundle(const uint64_t aState, const nsIntRect& aBounds)
{
GECKOBUNDLE_START(nodeInfo);
GECKOBUNDLE_PUT(nodeInfo, "id", java::sdk::Integer::ValueOf(VirtualViewID()));
AccessibleWrap* parent = WrapperParent();
GECKOBUNDLE_PUT(nodeInfo, "parentId",
java::sdk::Integer::ValueOf(parent ? parent->VirtualViewID() : 0));
uint32_t flags = GetFlags(WrapperRole(), aState);
GECKOBUNDLE_PUT(nodeInfo, "flags", java::sdk::Integer::ValueOf(flags));
GECKOBUNDLE_PUT(nodeInfo, "className", java::sdk::Integer::ValueOf(AndroidClass()));
const int32_t data[4] = {
aBounds.x, aBounds.y, aBounds.x + aBounds.width, aBounds.y + aBounds.height
};
GECKOBUNDLE_PUT(nodeInfo, "bounds", jni::IntArray::New(data, 4));
auto childCount = ChildCount();
nsTArray<int32_t> children(childCount);
for (uint32_t i = 0; i < childCount; ++i) {
auto child = static_cast<AccessibleWrap*>(GetChildAt(i));
children.AppendElement(child->VirtualViewID());
}
GECKOBUNDLE_PUT(nodeInfo,
"children",
jni::IntArray::New(children.Elements(), children.Length()));
GECKOBUNDLE_FINISH(nodeInfo);
return nodeInfo;
}

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

@ -33,6 +33,10 @@ public:
mozilla::java::GeckoBundle::LocalRef ToBundle();
mozilla::java::GeckoBundle::LocalRef ToSmallBundle(const uint64_t aState, const nsIntRect& aBounds);
mozilla::java::GeckoBundle::LocalRef ToSmallBundle();
int32_t AndroidClass()
{
return mID == kNoID ? java::SessionAccessibility::CLASSNAME_WEBVIEW
@ -65,8 +69,7 @@ private:
static void GetRoleDescription(role aRole,
nsAString& aGeckoRole,
nsAString& aRoleDescription);
static uint64_t GetFlags(role aRole, uint64_t aState);
static uint32_t GetFlags(role aRole, uint64_t aState);
};
static inline AccessibleWrap*

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

@ -6,9 +6,15 @@
#include "DocAccessibleWrap.h"
#include "nsIDocShell.h"
#include "nsLayoutUtils.h"
#include "DocAccessibleChild.h"
#include "nsAccessibilityService.h"
#include "SessionAccessibility.h"
using namespace mozilla::a11y;
const uint32_t kCacheRefreshInterval = 500;
////////////////////////////////////////////////////////////////////////////////
// DocAccessibleWrap
////////////////////////////////////////////////////////////////////////////////
@ -51,3 +57,117 @@ DocAccessibleWrap::GetAccessibleByID(int32_t aID) const
return nullptr;
}
void
DocAccessibleWrap::DoInitialUpdate()
{
DocAccessible::DoInitialUpdate();
CacheViewport();
}
nsresult
DocAccessibleWrap::HandleAccEvent(AccEvent* aEvent)
{
switch(aEvent->GetEventType()) {
case nsIAccessibleEvent::EVENT_SHOW:
case nsIAccessibleEvent::EVENT_HIDE:
case nsIAccessibleEvent::EVENT_SCROLLING_END:
CacheViewport();
break;
default:
break;
}
return DocAccessible::HandleAccEvent(aEvent);
}
void
DocAccessibleWrap::CacheViewportCallback(nsITimer* aTimer, void* aDocAccParam)
{
RefPtr<DocAccessibleWrap> docAcc(dont_AddRef(
reinterpret_cast<DocAccessibleWrap*>(aDocAccParam)));
if (!docAcc) {
return;
}
nsIPresShell *presShell = docAcc->PresShell();
if (!presShell) {
return;
}
nsIFrame* rootFrame = presShell->GetRootFrame();
if (!rootFrame) {
return;
}
nsTArray<nsIFrame*> frames;
nsIScrollableFrame* sf = presShell->GetRootScrollFrameAsScrollable();
nsRect scrollPort = sf ? sf->GetScrollPortRect() : rootFrame->GetRect();
nsLayoutUtils::GetFramesForArea(
presShell->GetRootFrame(),
scrollPort,
frames,
nsLayoutUtils::FrameForPointFlags::ONLY_VISIBLE);
AccessibleHashtable inViewAccs;
for (size_t i = 0; i < frames.Length(); i++) {
nsIContent* content = frames.ElementAt(i)->GetContent();
if (!content) {
continue;
}
Accessible* visibleAcc = docAcc->GetAccessibleOrContainer(content);
if (!visibleAcc) {
continue;
}
for (Accessible* acc = visibleAcc; acc && acc != docAcc->Parent(); acc = acc->Parent()) {
if (inViewAccs.Contains(acc->UniqueID())) {
break;
}
inViewAccs.Put(acc->UniqueID(), acc);
}
}
if (IPCAccessibilityActive()) {
DocAccessibleChild* ipcDoc = docAcc->IPCDoc();
nsTArray<BatchData> cacheData(inViewAccs.Count());
for (auto iter = inViewAccs.Iter(); !iter.Done(); iter.Next()) {
Accessible* accessible = iter.Data();
auto uid = accessible->IsDoc() && accessible->AsDoc()->IPCDoc() ? 0
: reinterpret_cast<uint64_t>(accessible->UniqueID());
cacheData.AppendElement(BatchData(accessible->Document()->IPCDoc(),
uid,
accessible->State(),
accessible->Bounds()));
}
ipcDoc->SendBatch(eBatch_Viewport, cacheData);
} else if (SessionAccessibility* sessionAcc = SessionAccessibility::GetInstanceFor(docAcc)) {
nsTArray<AccessibleWrap*> accessibles(inViewAccs.Count());
for (auto iter = inViewAccs.Iter(); !iter.Done(); iter.Next()) {
accessibles.AppendElement(static_cast<AccessibleWrap*>(iter.Data().get()));
}
sessionAcc->ReplaceViewportCache(accessibles);
}
if (docAcc->mCacheRefreshTimer) {
docAcc->mCacheRefreshTimer = nullptr;
}
}
void
DocAccessibleWrap::CacheViewport()
{
if (VirtualViewID() == kNoID && !mCacheRefreshTimer) {
NS_NewTimerWithFuncCallback(getter_AddRefs(mCacheRefreshTimer),
CacheViewportCallback,
this,
kCacheRefreshInterval,
nsITimer::TYPE_ONE_SHOT,
"a11y::DocAccessibleWrap::CacheViewport");
if (mCacheRefreshTimer) {
NS_ADDREF_THIS(); // Kung fu death grip
}
}
}

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

@ -7,6 +7,7 @@
#define mozilla_a11y_DocAccessibleWrap_h__
#include "DocAccessible.h"
#include "nsITimer.h"
namespace mozilla {
namespace a11y {
@ -17,6 +18,8 @@ public:
DocAccessibleWrap(nsIDocument* aDocument, nsIPresShell* aPresShell);
virtual ~DocAccessibleWrap();
virtual nsresult HandleAccEvent(AccEvent* aEvent) override;
/**
* Manage the mapping from id to Accessible.
*/
@ -27,11 +30,24 @@ public:
void RemoveID(uint32_t aID) { mIDToAccessibleMap.Remove(aID); }
AccessibleWrap* GetAccessibleByID(int32_t aID) const;
enum {
eBatch_Viewport = 0
};
protected:
/*
* This provides a mapping from 32 bit id to accessible objects.
*/
nsDataHashtable<nsUint32HashKey, AccessibleWrap*> mIDToAccessibleMap;
virtual void DoInitialUpdate() override;
private:
void CacheViewport();
static void CacheViewportCallback(nsITimer* aTimer, void* aDocAccParam);
nsCOMPtr<nsITimer> mCacheRefreshTimer;
};
} // namespace a11y

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

@ -6,6 +6,7 @@
#include "Platform.h"
#include "ProxyAccessibleWrap.h"
#include "DocAccessibleWrap.h"
#include "SessionAccessibility.h"
#include "mozilla/a11y/ProxyAccessible.h"
#include "nsIAccessibleEvent.h"
@ -198,3 +199,30 @@ a11y::ProxyScrollingEvent(ProxyAccessible* aTarget,
}
}
}
void
a11y::ProxyBatch(ProxyAccessible* aDocument,
const uint64_t aBatchType,
const nsTArray<ProxyAccessible*>& aAccessibles,
const nsTArray<BatchData>& aData)
{
SessionAccessibility* sessionAcc =
SessionAccessibility::GetInstanceFor(aDocument);
if (!sessionAcc) {
return;
}
nsTArray<AccessibleWrap*> accWraps(aAccessibles.Length());
for (size_t i = 0; i < aAccessibles.Length(); i++) {
accWraps.AppendElement(WrapperFor(aAccessibles.ElementAt(i)));
}
switch (aBatchType) {
case DocAccessibleWrap::eBatch_Viewport:
sessionAcc->ReplaceViewportCache(accWraps, aData);
break;
default:
MOZ_ASSERT_UNREACHABLE("Unknown batch type.");
break;
}
}

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

@ -5,6 +5,7 @@
#include "SessionAccessibility.h"
#include "AndroidUiThread.h"
#include "DocAccessibleParent.h"
#include "nsThreadUtils.h"
#include "AccessibilityEvent.h"
#include "HyperTextAccessible.h"
@ -329,3 +330,21 @@ SessionAccessibility::SendSelectedEvent(AccessibleWrap* aAccessible)
java::sdk::AccessibilityEvent::TYPE_VIEW_SELECTED,
aAccessible->VirtualViewID(), aAccessible->AndroidClass(), nullptr);
}
void
SessionAccessibility::ReplaceViewportCache(const nsTArray<AccessibleWrap*>& aAccessibles,
const nsTArray<BatchData>& aData)
{
auto infos = jni::ObjectArray::New<java::GeckoBundle>(aAccessibles.Length());
for (size_t i = 0; i < aAccessibles.Length(); i++) {
AccessibleWrap* acc = aAccessibles.ElementAt(i);
if (aData.Length() == aAccessibles.Length()) {
const BatchData& data = aData.ElementAt(i);
infos->SetElement(i, acc->ToSmallBundle(data.State(), data.Bounds()));
} else {
infos->SetElement(i, acc->ToSmallBundle());
}
}
mSessionAccessibility->ReplaceViewportCache(infos);
}

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

@ -41,6 +41,7 @@ namespace a11y {
class AccessibleWrap;
class ProxyAccessible;
class RootAccessibleWrap;
class BatchData;
class SessionAccessibility final
: public java::SessionAccessibility::NativeProvider::Natives<SessionAccessibility>
@ -104,6 +105,10 @@ public:
void SendWindowContentChangedEvent(AccessibleWrap* aAccessible);
void SendWindowStateChangedEvent(AccessibleWrap* aAccessible);
// Cache methods
void ReplaceViewportCache(const nsTArray<AccessibleWrap*>& aAccessibles,
const nsTArray<BatchData>& aData = nsTArray<BatchData>());
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(SessionAccessibility)
private:

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

@ -10,6 +10,11 @@
#include <stdint.h>
#include "nsStringFwd.h"
#if defined(ANDROID)
#include "nsTArray.h"
#include "nsRect.h"
#endif
namespace mozilla {
namespace a11y {
@ -117,7 +122,15 @@ void ProxyVirtualCursorChangeEvent(ProxyAccessible* aTarget,
void ProxyScrollingEvent(ProxyAccessible* aTarget, uint32_t aEventType,
uint32_t aScrollX, uint32_t aScrollY,
uint32_t aMaxScrollX, uint32_t aMaxScrollY);
class BatchData;
void ProxyBatch(ProxyAccessible* aDocument,
const uint64_t aBatchType,
const nsTArray<ProxyAccessible*>& aAccessibles,
const nsTArray<BatchData>& aData);
#endif
} // namespace a11y
} // namespace mozilla

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

@ -838,5 +838,27 @@ DocAccessibleParent::RecvFocusEvent(const uint64_t& aID,
#endif // defined(XP_WIN)
#if !defined(XP_WIN)
mozilla::ipc::IPCResult
DocAccessibleParent::RecvBatch(const uint64_t& aBatchType, nsTArray<BatchData>&& aData)
{
// Only do something in Android. We can't ifdef the entire protocol out in
// the ipdl because it doesn't allow preprocessing.
#if defined(ANDROID)
nsTArray<ProxyAccessible*> proxies(aData.Length());
for (size_t i = 0; i < aData.Length(); i++) {
DocAccessibleParent* doc = static_cast<DocAccessibleParent*>(
aData.ElementAt(i).Document().get_PDocAccessibleParent());
MOZ_ASSERT(doc);
ProxyAccessible* proxy = doc->GetAccessible(aData.ElementAt(i).ID());
MOZ_ASSERT(proxy);
proxies.AppendElement(proxy);
}
ProxyBatch(this, aBatchType, proxies, aData);
#endif // defined(XP_WIN)
return IPC_OK();
}
#endif // !defined(XP_WIN)
} // a11y
} // mozilla

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

@ -218,6 +218,10 @@ public:
HWND GetEmulatedWindowHandle() const { return mEmulatedWindowHandle; }
#endif
#if !defined(XP_WIN)
virtual mozilla::ipc::IPCResult RecvBatch(const uint64_t& aBatchType, nsTArray<BatchData>&& aData) override;
#endif
private:
class ProxyEntry : public PLDHashEntryHdr

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

@ -25,6 +25,19 @@ struct AccessibleData
uint32_t Interfaces;
};
union OriginDocument
{
PDocAccessible;
};
struct BatchData
{
OriginDocument Document;
uint64_t ID;
uint64_t State;
nsIntRect Bounds;
};
struct ShowEventData
{
uint64_t ID;
@ -82,6 +95,9 @@ parent:
*/
async BindChildDoc(PDocAccessible aChildDoc, uint64_t aID);
// Android
async Batch(uint64_t aBatchType, BatchData[] aData);
child:
async __delete__();

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

@ -134,8 +134,15 @@ pref("app.update.download.promptMaxAttempts", 2);
pref("app.update.elevation.promptMaxAttempts", 2);
// If set to true, the Update Service will automatically download updates if the
// user can apply updates.
// user can apply updates. This pref is no longer used on Windows, except as the
// default value to migrate to the new location that this data is now stored
// (which is in a file in the update directory). Because of this, this pref
// should no longer be used directly. Instead,
// nsIUpdateService::getAutoUpdateIsEnabled and
// nsIUpdateService::setAutoUpdateIsEnabled should be used.
#ifndef XP_WIN
pref("app.update.auto", true);
#endif
// If set to true, the Update Service will present no UI for any event.
pref("app.update.silent", false);

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

@ -40,6 +40,7 @@ function appUpdater(options = {}) {
this.options = options;
this.updateDeck = document.getElementById("updateDeck");
this.promiseAutoUpdateSetting = null;
// Hide the update deck when the update window is already open and it's not
// already applied, to avoid syncing issues between them. Applied updates
@ -81,6 +82,9 @@ function appUpdater(options = {}) {
return;
}
// We might need this value later, so start loading it from the disk now.
this.promiseAutoUpdateSetting = this.aus.getAutoUpdateIsEnabled();
// That leaves the options
// "Check for updates, but let me choose whether to install them", and
// "Automatically install updates".
@ -136,14 +140,6 @@ appUpdater.prototype =
gAppUpdater.aus.canStageUpdates;
},
// true when updating is automatic.
get updateAuto() {
try {
return Services.prefs.getBoolPref("app.update.auto");
} catch (e) { }
return true; // Firefox default is true
},
/**
* Sets the panel of the updateDeck.
*
@ -260,10 +256,16 @@ appUpdater.prototype =
return;
}
if (gAppUpdater.updateAuto) // automatically download and install
gAppUpdater.startDownload();
else // ask
gAppUpdater.selectPanel("downloadAndInstall");
if (this.promiseAutoUpdateSetting == null) {
this.promiseAutoUpdateSetting = this.aus.getAutoUpdateIsEnabled();
}
this.promiseAutoUpdateSetting.then(updateAuto => {
if (updateAuto) { // automatically download and install
gAppUpdater.startDownload();
} else { // ask
gAppUpdater.selectPanel("downloadAndInstall");
}
});
},
/**

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

@ -430,6 +430,7 @@ var ctrlTab = {
onKeyDown(event) {
if (event.keyCode != event.DOM_VK_TAB ||
!event.ctrlKey ||
!this.isOpen && event.shiftKey ||
event.altKey ||
event.metaKey) {
return;
@ -440,7 +441,7 @@ var ctrlTab = {
if (this.isOpen) {
this.advanceFocus(!event.shiftKey);
} else if (!event.shiftKey) {
} else {
let tabs = gBrowser.visibleTabs;
if (tabs.length > 2) {
this.open();

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

@ -19,7 +19,7 @@
:root:-moz-lwtheme {
--toolbar-bgcolor: rgba(255,255,255,.4);
--toolbar-bgimage: none;
--toolbar-color: inherit;
--toolbar-color: var(--lwt-text-color, inherit);
background-color: var(--lwt-accent-color);
color: var(--lwt-text-color);

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

@ -4150,7 +4150,7 @@ const BrowserSearch = {
*/
recordSearchInTelemetry(engine, source, details = {}) {
try {
BrowserUsageTelemetry.recordSearch(engine, source, details);
BrowserUsageTelemetry.recordSearch(gBrowser, engine, source, details);
} catch (ex) {
Cu.reportError(ex);
}
@ -4174,7 +4174,7 @@ const BrowserSearch = {
recordOneoffSearchInTelemetry(engine, source, type, where) {
try {
const details = {type, isOneOff: true};
BrowserUsageTelemetry.recordSearch(engine, source, details);
BrowserUsageTelemetry.recordSearch(gBrowser, engine, source, details);
} catch (ex) {
Cu.reportError(ex);
}

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

@ -73,6 +73,7 @@
persist="screenX screenY width height sizemode"
#ifdef BROWSER_XHTML
hidden="true"
mozpersist=""
#endif
>

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

@ -46,7 +46,12 @@ add_task(async function shift_left_click_test() {
is(win.gURLBar.textValue, TEST_VALUE, "New URL is loaded in new window");
// Cleanup.
let ourWindowRefocusedPromise = Promise.all([
BrowserTestUtils.waitForEvent(window, "activate"),
BrowserTestUtils.waitForEvent(window, "focus", true),
]);
await BrowserTestUtils.closeWindow(win);
await ourWindowRefocusedPromise;
});
add_task(async function right_click_test() {

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

@ -11,6 +11,14 @@ var updateService = Cc["@mozilla.org/updates/update-service;1"].
// policy is applied needs to occur in a different test since the policy does
// not properly take effect unless it is applied during application startup.
add_task(async function test_updates_pre_policy() {
// Turn off automatic update before we set app.update.disabledForTesting to
// false so that we don't cause an actual update.
let originalUpdateAutoValue = await updateService.getAutoUpdateIsEnabled();
await updateService.setAutoUpdateIsEnabled(false);
registerCleanupFunction(async () => {
await updateService.setAutoUpdateIsEnabled(originalUpdateAutoValue);
});
await SpecialPowers.pushPrefEnv({"set": [["app.update.disabledForTesting", false]]});
is(Services.policies.isAllowed("appUpdate"), true,

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

@ -1,7 +1,6 @@
[DEFAULT]
prefs =
app.update.disabledForTesting=false
app.update.auto=true
browser.policies.alternatePath='<test-root>/browser/components/enterprisepolicies/tests/browser/disable_app_update/config_disable_app_update.json'
support-files =
config_disable_app_update.json

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

@ -76,17 +76,20 @@ this.search = class extends ExtensionAPI {
postData: submission.postData,
triggeringPrincipal: context.principal,
};
let tabbrowser;
if (searchProperties.tabId === null) {
let {gBrowser} = windowTracker.topWindow;
let nativeTab = gBrowser.addTab(submission.uri.spec, options);
if (!searchLoadInBackground) {
gBrowser.selectedTab = nativeTab;
}
tabbrowser = gBrowser;
} else {
let tab = tabTracker.getTab(searchProperties.tabId);
tab.linkedBrowser.loadURI(submission.uri.spec, options);
tabbrowser = tab.linkedBrowser.getTabBrowser();
}
BrowserUsageTelemetry.recordSearch(engine, "webextension");
BrowserUsageTelemetry.recordSearch(tabbrowser, engine, "webextension");
},
},
};

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

@ -101,6 +101,11 @@
"optional": true,
"deprecated": "Unsupported on Firefox."
},
"encoding": {
"type": "string",
"optional": true,
"description": "Encoding of the search term."
},
"is_default": {
"type": "boolean",
"optional": true,

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

@ -271,7 +271,10 @@ function Sections(prevState = INITIAL_STATE.Sections, action) {
const rows = Array.from(action.data.rows);
section.rows.forEach((card, index) => {
if (card.pinned) {
rows.splice(index, 0, card);
// Only add it if it's not already there.
if (rows[index].guid !== card.guid) {
rows.splice(index, 0, card);
}
}
});
return Object.assign({}, section, initialized, Object.assign({}, action.data, {rows}));

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

@ -239,13 +239,14 @@ export class ASRouterAdmin extends React.PureComponent {
renderTargetingParameters() {
// There was no error and the result is truthy
const success = this.state.evaluationStatus.success && !!this.state.evaluationStatus.result;
const result = JSON.stringify(this.state.evaluationStatus.result, null, 2) || "(Empty result)";
return (<table><tbody>
<tr><td><h2>Evaluate JEXL expression</h2></td></tr>
<tr>
<td>
<p><textarea ref="expressionInput" rows="10" cols="60" placeholder="Evaluate JEXL expressions and mock parameters by changing their values below" /></p>
<p>Status: <span ref="evaluationStatus">{success ? "✅" : "❌"}, Result: {JSON.stringify(this.state.evaluationStatus.result, null, 2)}</span></p>
<p>Status: <span ref="evaluationStatus">{success ? "✅" : "❌"}, Result: {result}</span></p>
</td>
<td>
<button className="ASRouterButton secondary" onClick={this.handleExpressionEval}>Evaluate</button>

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

@ -2102,6 +2102,7 @@ class ASRouterAdmin extends react__WEBPACK_IMPORTED_MODULE_1___default.a.PureCom
renderTargetingParameters() {
// There was no error and the result is truthy
const success = this.state.evaluationStatus.success && !!this.state.evaluationStatus.result;
const result = JSON.stringify(this.state.evaluationStatus.result, null, 2) || "(Empty result)";
return react__WEBPACK_IMPORTED_MODULE_1___default.a.createElement(
"table",
@ -2142,7 +2143,7 @@ class ASRouterAdmin extends react__WEBPACK_IMPORTED_MODULE_1___default.a.PureCom
{ ref: "evaluationStatus" },
success ? "✅" : "❌",
", Result: ",
JSON.stringify(this.state.evaluationStatus.result, null, 2)
result
)
)
),
@ -9385,7 +9386,10 @@ function Sections(prevState = INITIAL_STATE.Sections, action) {
const rows = Array.from(action.data.rows);
section.rows.forEach((card, index) => {
if (card.pinned) {
rows.splice(index, 0, card);
// Only add it if it's not already there.
if (rows[index].guid !== card.guid) {
rows.splice(index, 0, card);
}
}
});
return Object.assign({}, section, initialized, Object.assign({}, action.data, { rows }));

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 1.6 KiB

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

@ -773,8 +773,8 @@ CFR impression ping has two forms, in which the message_id could be of different
"addon_version": "20180710100040",
"locale": "en-US",
"source": "CFR",
// message_id could be the ID of the recommendation, such as "amazon_addon"
"message_id": "amazon_addon",
// message_id could be the ID of the recommendation, such as "wikipedia_addon"
"message_id": "wikipedia_addon",
"event": "IMPRESSION"
}
```
@ -836,8 +836,8 @@ This reports the user's interaction with Activity Stream Router.
"impression_id": "n/a",
"locale": "en-US",
"source": "CFR",
// message_id could be the ID of the recommendation, such as "amazon_addon"
"message_id": "amazon_addon",
// message_id could be the ID of the recommendation, such as "wikipedia_addon"
"message_id": "wikipedia_addon",
"event": "[INSTALL | BLOCK | DISMISS | RATIONALE | LEARN_MORE | CLICK_DOORHANGER]"
}
```

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

@ -561,7 +561,7 @@ class _ASRouter {
try {
evaluationStatus = {result: await ASRouterTargeting.isMatch(expression, context), success: true};
} catch (e) {
evaluationStatus = {result: e, success: false};
evaluationStatus = {result: e.message, success: false};
}
channel.sendAsyncMessage(OUTGOING_MESSAGE_NAME, {type: "ADMIN_SET_STATE", data: {...this.state, evaluationStatus}});

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

@ -2,12 +2,6 @@
* 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 AMAZON_ASSISTANT_PARAMS = {
existing_addons: ["abb@amazon.com", "{75c7fe97-5a90-4b54-9052-3534235eaf41}", "{ef34596e-1e43-4e84-b2ff-1e58e287e08d}", "{ea280feb-155a-492e-8016-ac96dd995f2c}", "izer@camelcamelcamel.com", "amptra@keepa.com", "pricealarm@icopron.ch", "{774f76c7-6807-481e-bf64-f9b7d5cda602}"],
open_urls: ["smile.amazon.com", "www.audible.com", "www.amazon.com", "amazon.com", "audible.com"],
sumo_path: "extensionrecommendations",
min_frecency: 10000,
};
const FACEBOOK_CONTAINER_PARAMS = {
existing_addons: ["@contain-facebook", "{bb1b80be-e6b3-40a1-9b6e-9d4073343f0b}", "{a50d61ca-d27b-437a-8b52-5fd801a0a88b}"],
open_urls: ["www.facebook.com", "facebook.com"],
@ -45,110 +39,6 @@ const REDDIT_ENHANCEMENT_PARAMS = {
};
const CFR_MESSAGES = [
{
id: "AMAZON_ASSISTANT_1",
template: "cfr_doorhanger",
content: {
bucket_id: "CFR_M1",
notification_text: {string_id: "cfr-doorhanger-extension-notification"},
heading_text: {string_id: "cfr-doorhanger-extension-heading"},
info_icon: {
label: {string_id: "cfr-doorhanger-extension-sumo-link"},
sumo_path: AMAZON_ASSISTANT_PARAMS.sumo_path,
},
addon: {
id: "337359",
title: "Amazon Assistant",
icon: "resource://activity-stream/data/content/assets/cfr_amazon_assistant.png",
rating: 3.3,
users: 443046,
author: "Amazon",
amo_url: "https://addons.mozilla.org/en-US/firefox/addon/amazon-browser-bar/",
},
text: "Amazon Assistant helps you make better shopping decisions by showing product comparisons at thousands of retail sites.",
buttons: {
primary: {
label: {string_id: "cfr-doorhanger-extension-ok-button"},
action: {
type: "INSTALL_ADDON_FROM_URL",
data: {url: null},
},
},
secondary: [{
label: {string_id: "cfr-doorhanger-extension-cancel-button"},
action: {type: "CANCEL"},
}, {
label: {string_id: "cfr-doorhanger-extension-never-show-recommendation"},
}, {
label: {string_id: "cfr-doorhanger-extension-manage-settings-button"},
action: {
type: "OPEN_PREFERENCES_PAGE",
data: {category: "general-cfr", origin: "CFR"},
},
}],
},
},
frequency: {lifetime: 1},
targeting: `
localeLanguageCode == "en" &&
(providerCohorts.cfr == "one_per_day_amazon") &&
(xpinstallEnabled == true) &&
(${JSON.stringify(AMAZON_ASSISTANT_PARAMS.existing_addons)} intersect addonsInfo.addons|keys)|length == 0 &&
(${JSON.stringify(AMAZON_ASSISTANT_PARAMS.open_urls)} intersect topFrecentSites[.frecency >= ${AMAZON_ASSISTANT_PARAMS.min_frecency}]|mapToProperty('host'))|length > 0`,
trigger: {id: "openURL", params: AMAZON_ASSISTANT_PARAMS.open_urls},
},
{
id: "AMAZON_ASSISTANT_3",
template: "cfr_doorhanger",
content: {
bucket_id: "CFR_M1",
notification_text: {string_id: "cfr-doorhanger-extension-notification"},
heading_text: {string_id: "cfr-doorhanger-extension-heading"},
info_icon: {
label: {string_id: "cfr-doorhanger-extension-sumo-link"},
sumo_path: AMAZON_ASSISTANT_PARAMS.sumo_path,
},
addon: {
id: "337359",
title: "Amazon Assistant",
icon: "resource://activity-stream/data/content/assets/cfr_amazon_assistant.png",
rating: 3.3,
users: 443046,
author: "Amazon",
amo_url: "https://addons.mozilla.org/en-US/firefox/addon/amazon-browser-bar/",
},
text: "Amazon Assistant helps you make better shopping decisions by showing product comparisons at thousands of retail sites.",
buttons: {
primary: {
label: {string_id: "cfr-doorhanger-extension-ok-button"},
action: {
type: "INSTALL_ADDON_FROM_URL",
data: {url: null},
},
},
secondary: [{
label: {string_id: "cfr-doorhanger-extension-cancel-button"},
action: {type: "CANCEL"},
}, {
label: {string_id: "cfr-doorhanger-extension-never-show-recommendation"},
}, {
label: {string_id: "cfr-doorhanger-extension-manage-settings-button"},
action: {
type: "OPEN_PREFERENCES_PAGE",
data: {category: "general-cfr", origin: "CFR"},
},
}],
},
},
frequency: {lifetime: 3},
targeting: `
localeLanguageCode == "en" &&
(providerCohorts.cfr == "three_per_day_amazon") &&
(xpinstallEnabled == true) &&
(${JSON.stringify(AMAZON_ASSISTANT_PARAMS.existing_addons)} intersect addonsInfo.addons|keys)|length == 0 &&
(${JSON.stringify(AMAZON_ASSISTANT_PARAMS.open_urls)} intersect topFrecentSites[.frecency >= ${AMAZON_ASSISTANT_PARAMS.min_frecency}]|mapToProperty('host'))|length > 0`,
trigger: {id: "openURL", params: AMAZON_ASSISTANT_PARAMS.open_urls},
},
{
id: "FACEBOOK_CONTAINER_1",
template: "cfr_doorhanger",

9
browser/components/newtab/package-lock.json сгенерированный
Просмотреть файл

@ -7680,10 +7680,9 @@
}
},
"merge": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/merge/-/merge-1.2.0.tgz",
"integrity": "sha1-dTHjnUlJwoGma4xabgJl6LBYlNo=",
"dev": true
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/merge/-/merge-1.2.1.tgz",
"integrity": "sha512-VjFo4P5Whtj4vsLzsYBu5ayHhoHJ0UqNm7ibvShmbmoz7tGi0vXaoJbGdB+GmDMLUdg8DpQXEIeVDAe8MaABvQ=="
},
"micromatch": {
"version": "2.3.11",
@ -10250,7 +10249,7 @@
"known-css-properties": "0.3.0",
"lodash.capitalize": "4.2.1",
"lodash.kebabcase": "4.1.1",
"merge": "1.2.0",
"merge": "^1.2.0",
"path-is-absolute": "1.0.1",
"util": "0.10.3"
},

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

@ -110,6 +110,10 @@
"buildmc:copy": "rsync --exclude-from .mcignore -a . $npm_package_config_mc_dir/browser/components/newtab/",
"buildmc:stringsExport": "cp $npm_package_config_locales_dir/$npm_package_config_default_locale/strings.properties $npm_package_config_mc_dir/browser/locales/$npm_package_config_default_locale/chrome/browser/activity-stream/newtab.properties",
"buildmc:copyPingCentre": "cpx \"ping-centre/PingCentre.jsm\" $npm_package_config_mc_dir/browser/modules",
"builduplift": "npm-run-all builduplift:*",
"prebuilduplift": "npm run prebuildmc",
"builduplift:bundle": "npm run bundle",
"builduplift:copy": "npm run buildmc:copy",
"buildlibrary": "npm-run-all buildlibrary:*",
"buildlibrary:webpack": "webpack --config webpack.aboutlibrary.config.js",
"buildlibrary:css": "node-sass --source-map true --source-map-contents content-src/aboutlibrary -o aboutlibrary/content",

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

@ -10,8 +10,8 @@ const REGULAR_IDS = [
];
describe("CFRMessageProvider", () => {
it("should have a total of 12 messages", () => {
assert.lengthOf(messages, 12);
it("should have a total of 10 messages", () => {
assert.lengthOf(messages, 10);
});
it("should two variants for each of the five regular addons", () => {
for (const id of REGULAR_IDS) {
@ -28,19 +28,6 @@ describe("CFRMessageProvider", () => {
assert.deepEqual(cohort1.content, cohort3.content, "cohorts should have the same content");
}
});
it("should have the two amazon cohorts", () => {
const cohort1 = messages.find(msg => msg.id === `AMAZON_ASSISTANT_1`);
const cohort3 = messages.find(msg => msg.id === `AMAZON_ASSISTANT_3`);
assert.deepEqual(cohort1.content, cohort3.content, "cohorts should have the same content");
assert.ok(cohort1, `contains one day cohort for amazon`);
assert.deepEqual(cohort1.frequency, {lifetime: 1}, "one day cohort has the right frequency cap");
assert.include(cohort1.targeting, `(providerCohorts.cfr == "one_per_day_amazon"`);
assert.ok(cohort3, `contains three day cohort for amazon`);
assert.deepEqual(cohort3.frequency, {lifetime: 3}, "three day cohort has the right frequency cap");
assert.include(cohort3.targeting, `(providerCohorts.cfr == "three_per_day_amazon")`);
});
it("should always have xpinstallEnabled as targeting if it is an addon", () => {
for (const message of messages) {
// Ensure that the CFR messages that are recommending an addon have this targeting.

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

@ -338,7 +338,12 @@ describe("Reducers", () => {
let updatedSection = newState.find(section => section.id === "foo_bar_2");
assert.deepEqual(updatedSection.rows, [ROW]);
const PINNED_ROW = {id: "pinned", pinned: true};
const PINNED_ROW = {id: "pinned", pinned: true, guid: "pinned"};
newState = Sections(newState, {type: at.SECTION_UPDATE, data: Object.assign({rows: [PINNED_ROW]}, {id: "foo_bar_2"})});
updatedSection = newState.find(section => section.id === "foo_bar_2");
assert.deepEqual(updatedSection.rows, [PINNED_ROW]);
// Updating the section again should not duplicate pinned cards
newState = Sections(newState, {type: at.SECTION_UPDATE, data: Object.assign({rows: [PINNED_ROW]}, {id: "foo_bar_2"})});
updatedSection = newState.find(section => section.id === "foo_bar_2");
assert.deepEqual(updatedSection.rows, [PINNED_ROW]);

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

@ -27,6 +27,12 @@ scripts:
stringsExport: cp $npm_package_config_locales_dir/$npm_package_config_default_locale/strings.properties $npm_package_config_mc_dir/browser/locales/$npm_package_config_default_locale/chrome/browser/activity-stream/newtab.properties
copyPingCentre: cpx "ping-centre/PingCentre.jsm" $npm_package_config_mc_dir/browser/modules
# builduplift: Build and export to mozilla central for uplifts without exporting strings to browser/locales
builduplift:
pre: =>prebuildmc
bundle: => bundle
copy: =>buildmc:copy
# buildlibrary: Export about:library code to mozilla-central - intentionally not included in buildmc for now
buildlibrary:
webpack: webpack --config webpack.aboutlibrary.config.js

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

@ -20,6 +20,7 @@ ChromeUtils.defineModuleGetter(this, "CloudStorage",
"resource://gre/modules/CloudStorage.jsm");
XPCOMUtils.defineLazyServiceGetters(this, {
gAUS: ["@mozilla.org/updates/update-service;1", "nsIApplicationUpdateService"],
gHandlerService: ["@mozilla.org/uriloader/handler-service;1", "nsIHandlerService"],
gMIMEService: ["@mozilla.org/mime;1", "nsIMIMEService"],
});
@ -43,6 +44,8 @@ const PREF_HIDE_PLUGINS_WITHOUT_EXTENSIONS =
// Strings to identify ExtensionSettingsStore overrides
const CONTAINERS_KEY = "privacy.containers";
const AUTO_UPDATE_CHANGED_TOPIC = "auto-update-config-change";
// The nsHandlerInfoAction enumeration values in nsIHandlerInfo identify
// the actions the application can take with content of various types.
// But since nsIHandlerInfo doesn't support plugins, there's no value
@ -175,7 +178,6 @@ if (AppConstants.platform === "win") {
if (AppConstants.MOZ_UPDATER) {
Preferences.addAll([
{ id: "app.update.auto", type: "bool" },
{ id: "app.update.disable_button.showUpdateHistory", type: "bool" },
]);
@ -481,6 +483,14 @@ var gMainPane = {
if (AppConstants.MOZ_MAINTENANCE_SERVICE) {
document.getElementById("useService").hidden = true;
}
} else {
// Start with no option selected since we are still reading the value
document.getElementById("autoDesktop").removeAttribute("selected");
document.getElementById("manualDesktop").removeAttribute("selected");
// Start reading the correct value from the disk
this.updateReadPrefs();
setEventListener("updateRadioGroup", "command",
gMainPane.updateWritePrefs);
}
if (AppConstants.MOZ_MAINTENANCE_SERVICE) {
@ -509,6 +519,7 @@ var gMainPane = {
// the view when they change.
Services.prefs.addObserver(PREF_SHOW_PLUGINS_IN_LIST, this);
Services.prefs.addObserver(PREF_HIDE_PLUGINS_WITHOUT_EXTENSIONS, this);
Services.obs.addObserver(this, AUTO_UPDATE_CHANGED_TOPIC);
setEventListener("filter", "command", gMainPane.filter);
setEventListener("typeColumn", "click", gMainPane.sort);
@ -1272,6 +1283,57 @@ var gMainPane = {
}
},
/**
* Selects the correct item in the update radio group
*/
async updateReadPrefs() {
if (AppConstants.MOZ_UPDATER &&
(!Services.policies || Services.policies.isAllowed("appUpdate"))) {
let radiogroup = document.getElementById("updateRadioGroup");
radiogroup.disabled = true;
try {
let enabled = await gAUS.getAutoUpdateIsEnabled();
radiogroup.value = enabled;
radiogroup.disabled = false;
} catch (error) {
Cu.reportError(error);
}
}
},
/**
* Writes the value of the update radio group to the disk
*/
async updateWritePrefs() {
if (AppConstants.MOZ_UPDATER &&
(!Services.policies || Services.policies.isAllowed("appUpdate"))) {
let radiogroup = document.getElementById("updateRadioGroup");
let updateAutoValue = (radiogroup.value == "true");
radiogroup.disabled = true;
try {
await gAUS.setAutoUpdateIsEnabled(updateAutoValue);
radiogroup.disabled = false;
} catch (error) {
Cu.reportError(error);
await this.updateReadPrefs();
await this.reportUpdatePrefWriteError(error);
}
}
},
async reportUpdatePrefWriteError(error) {
let [title, message] = await document.l10n.formatValues([
{id: "update-pref-write-failure-title"},
{id: "update-pref-write-failure-message", args: {path: error.path}},
]);
// Set up the Ok Button
let buttonFlags = (Services.prompt.BUTTON_POS_0 *
Services.prompt.BUTTON_TITLE_OK);
Services.prompt.confirmEx(window, title, message, buttonFlags,
null, null, null, null, {});
},
/**
* Displays the history of installed updates.
*/
@ -1285,6 +1347,8 @@ var gMainPane = {
Services.prefs.removeObserver(PREF_HIDE_PLUGINS_WITHOUT_EXTENSIONS, this);
Services.prefs.removeObserver(PREF_CONTAINERS_EXTENSION, this);
Services.obs.removeObserver(this, AUTO_UPDATE_CHANGED_TOPIC);
},
@ -1315,6 +1379,11 @@ var gMainPane = {
// the view when any of them changes.
this._rebuildView();
}
} else if (aTopic == AUTO_UPDATE_CHANGED_TOPIC) {
if (aData != "true" && aData != "false") {
throw new Error("Invalid preference value for app.update.auto");
}
document.getElementById("updateRadioGroup").value = aData;
}
},

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

@ -558,11 +558,12 @@
#ifdef MOZ_UPDATER
<description id="updateAllowDescription" data-l10n-id="update-application-allow-description"></description>
<radiogroup id="updateRadioGroup" preference="app.update.auto">
<radiogroup id="updateRadioGroup">
<radio id="autoDesktop"
value="true"
data-l10n-id="update-application-auto"/>
<radio value="false"
<radio id="manualDesktop"
value="false"
data-l10n-id="update-application-check-choose"/>
</radiogroup>
#ifdef MOZ_MAINTENANCE_SERVICE

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

@ -360,6 +360,12 @@ update-enable-search-update =
.label = Automatically update search engines
.accesskey = e
update-pref-write-failure-title = Write Failure
# Variables:
# $path (String) - Path to the configuration file
update-pref-write-failure-message = Unable to save preference. Could not write to file: { $path }
## General Section - Performance
performance-title = Performance

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

@ -117,6 +117,11 @@ function getSearchEngineId(engine) {
return "other";
}
function shouldRecordSearchCount(tabbrowser) {
return !PrivateBrowsingUtils.isWindowPrivate(tabbrowser.ownerGlobal) ||
!Services.prefs.getBoolPref("browser.engagement.search_counts.pbm", false);
}
let URICountListener = {
// A set containing the visited domains, see bug 1271310.
_domainSet: new Set(),
@ -200,7 +205,9 @@ let URICountListener = {
return;
}
Services.search.recordSearchURLTelemetry(uriSpec);
if (shouldRecordSearchCount(browser.getTabBrowser())) {
Services.search.recordSearchURLTelemetry(uriSpec);
}
if (!shouldCountURI) {
return;
@ -400,6 +407,8 @@ let BrowserUsageTelemetry = {
* Telemetry records only search counts per engine and action origin, but
* nothing pertaining to the search contents themselves.
*
* @param {tabbrowser} tabbrowser
* The tabbrowser where the search was loaded.
* @param {nsISearchEngine} engine
* The engine handling the search.
* @param {String} source
@ -416,7 +425,11 @@ let BrowserUsageTelemetry = {
* The object describing the event that triggered the search.
* @throws if source is not in the known sources list.
*/
recordSearch(engine, source, details = {}) {
recordSearch(tabbrowser, engine, source, details = {}) {
if (!shouldRecordSearchCount(tabbrowser)) {
return;
}
const isOneOff = !!details.isOneOff;
const countId = getSearchEngineId(engine) + "." + source;

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

@ -574,3 +574,122 @@ add_task(async function test_suggestion_rightclick() {
BrowserTestUtils.removeTab(tab);
});
});
add_task(async function test_privateWindow() {
// Mock the search service's search provider info so that its
// recordSearchURLTelemetry() function adds the in-content SEARCH_COUNTS
// telemetry for our test engine.
Services.search.QueryInterface(Ci.nsIObserver).observe(
null,
"test:setSearchProviderInfo",
JSON.stringify({
"example": {
"regexp": "^http://example\\.com/",
"queryParam": "q",
},
})
);
let search_hist = getAndClearKeyedHistogram("SEARCH_COUNTS");
// First, do a bunch of searches in a private window.
let win = await BrowserTestUtils.openNewBrowserWindow({ private: true });
info("Search in a private window and the pref does not exist");
let p = BrowserTestUtils.browserLoaded(win.gBrowser.selectedBrowser);
await searchInAwesomebar("query", win);
EventUtils.synthesizeKey("KEY_Enter", undefined, win);
await p;
// SEARCH_COUNTS should be incremented.
checkKeyedHistogram(search_hist, "other-MozSearch.urlbar", 1);
checkKeyedHistogram(search_hist, "example.in-content:organic:none", 1);
info("Search again in a private window after setting the pref to true");
Services.prefs.setBoolPref("browser.engagement.search_counts.pbm", true);
p = BrowserTestUtils.browserLoaded(win.gBrowser.selectedBrowser);
await searchInAwesomebar("another query", win);
EventUtils.synthesizeKey("KEY_Enter", undefined, win);
await p;
// SEARCH_COUNTS should *not* be incremented.
checkKeyedHistogram(search_hist, "other-MozSearch.urlbar", 1);
checkKeyedHistogram(search_hist, "example.in-content:organic:none", 1);
info("Search again in a private window after setting the pref to false");
Services.prefs.setBoolPref("browser.engagement.search_counts.pbm", false);
p = BrowserTestUtils.browserLoaded(win.gBrowser.selectedBrowser);
await searchInAwesomebar("another query", win);
EventUtils.synthesizeKey("KEY_Enter", undefined, win);
await p;
// SEARCH_COUNTS should be incremented.
checkKeyedHistogram(search_hist, "other-MozSearch.urlbar", 2);
checkKeyedHistogram(search_hist, "example.in-content:organic:none", 2);
info("Search again in a private window after clearing the pref");
Services.prefs.clearUserPref("browser.engagement.search_counts.pbm");
p = BrowserTestUtils.browserLoaded(win.gBrowser.selectedBrowser);
await searchInAwesomebar("another query", win);
EventUtils.synthesizeKey("KEY_Enter", undefined, win);
await p;
// SEARCH_COUNTS should be incremented.
checkKeyedHistogram(search_hist, "other-MozSearch.urlbar", 3);
checkKeyedHistogram(search_hist, "example.in-content:organic:none", 3);
await BrowserTestUtils.closeWindow(win);
// Now, do a bunch of searches in a non-private window. Telemetry should
// always be recorded regardless of the pref's value.
win = await BrowserTestUtils.openNewBrowserWindow();
info("Search in a non-private window and the pref does not exist");
p = BrowserTestUtils.browserLoaded(win.gBrowser.selectedBrowser);
await searchInAwesomebar("query", win);
EventUtils.synthesizeKey("KEY_Enter", undefined, win);
await p;
// SEARCH_COUNTS should be incremented.
checkKeyedHistogram(search_hist, "other-MozSearch.urlbar", 4);
checkKeyedHistogram(search_hist, "example.in-content:organic:none", 4);
info("Search again in a non-private window after setting the pref to true");
Services.prefs.setBoolPref("browser.engagement.search_counts.pbm", true);
p = BrowserTestUtils.browserLoaded(win.gBrowser.selectedBrowser);
await searchInAwesomebar("another query", win);
EventUtils.synthesizeKey("KEY_Enter", undefined, win);
await p;
// SEARCH_COUNTS should be incremented.
checkKeyedHistogram(search_hist, "other-MozSearch.urlbar", 5);
checkKeyedHistogram(search_hist, "example.in-content:organic:none", 5);
info("Search again in a non-private window after setting the pref to false");
Services.prefs.setBoolPref("browser.engagement.search_counts.pbm", false);
p = BrowserTestUtils.browserLoaded(win.gBrowser.selectedBrowser);
await searchInAwesomebar("another query", win);
EventUtils.synthesizeKey("KEY_Enter", undefined, win);
await p;
// SEARCH_COUNTS should be incremented.
checkKeyedHistogram(search_hist, "other-MozSearch.urlbar", 6);
checkKeyedHistogram(search_hist, "example.in-content:organic:none", 6);
info("Search again in a non-private window after clearing the pref");
Services.prefs.clearUserPref("browser.engagement.search_counts.pbm");
p = BrowserTestUtils.browserLoaded(win.gBrowser.selectedBrowser);
await searchInAwesomebar("another query", win);
EventUtils.synthesizeKey("KEY_Enter", undefined, win);
await p;
// SEARCH_COUNTS should be incremented.
checkKeyedHistogram(search_hist, "other-MozSearch.urlbar", 7);
checkKeyedHistogram(search_hist, "example.in-content:organic:none", 7);
await BrowserTestUtils.closeWindow(win);
// Reset the search provider info.
Services.search.QueryInterface(Ci.nsIObserver)
.observe(null, "test:setSearchProviderInfo", "");
});

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

@ -14,3 +14,7 @@
outline: 1px -moz-dialogtext dotted;
outline-offset: -1px;
}
.tracking-protection-button > .button-box > .button-icon {
margin-inline-end: 5px;
}

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

@ -201,7 +201,7 @@
#cfr-notification-header-link {
margin: 7px;
color: var(--lwt-text-color);
color: inherit;
cursor: default;
}
@ -258,7 +258,7 @@
-moz-context-properties: fill, fill-opacity;
background-image: var(--cfr-notification-footer-star);
background-size: 17px;
fill: var(--lwt-text-color);
fill: currentColor;
fill-opacity: 0.7;
height: 16px;
}

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

@ -7,7 +7,6 @@
there are overrides for each platform in their compacttheme.css files. */
:root:-moz-lwtheme {
--toolbar-color: var(--lwt-text-color);
--toolbar-non-lwt-bgcolor: var(--toolbar-bgcolor);
--toolbar-non-lwt-textcolor: var(--lwt-text-color);
--toolbar-non-lwt-bgimage: none;

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

@ -468,6 +468,7 @@ description#identity-popup-content-verifier,
display: none;
height: 32px;
background-color: var(--arrowpanel-dimmed);
color: inherit;
}
.tracking-protection-button:hover {

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

@ -4,3 +4,6 @@
%include ../../shared/controlcenter/panel.inc.css
.tracking-protection-button > .button-box > .button-icon {
margin-inline-end: 5px;
}

Двоичные данные
build/pgo/certs/cert9.db

Двоичный файл не отображается.

Двоичные данные
build/pgo/certs/key4.db

Двоичный файл не отображается.

Двоичные данные
build/pgo/certs/mochitest.client

Двоичный файл не отображается.

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

@ -173,6 +173,7 @@ http://unwanted.example.com:80
http://tracking.example.com:80
http://not-tracking.example.com:80
http://tracking.example.org:80
http://another-tracking.example.net:80
http://itisatracker.org:80
http://trackertest.org:80
@ -181,6 +182,7 @@ https://unwanted.example.com:443
https://tracking.example.com:443
https://not-tracking.example.com:443
https://tracking.example.org:443
https://another-tracking.example.net:443
#
# Used while testing flash blocking (Bug 1307604)

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

@ -1,6 +1,6 @@
/******************************************************************************
** This file is an amalgamation of many separate C source files from SQLite
** version 3.25.1. By combining all the individual C code files into this
** version 3.25.3. By combining all the individual C code files into this
** single large file, the entire code can be compiled as a single translation
** unit. This allows many compilers to do optimizations that would not be
** possible if the files were compiled separately. Performance improvements
@ -1156,9 +1156,9 @@ extern "C" {
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
#define SQLITE_VERSION "3.25.1"
#define SQLITE_VERSION_NUMBER 3025001
#define SQLITE_SOURCE_ID "2018-09-18 20:20:44 2ac9003de44da7dafa3fbb1915ac5725a9275c86bf2f3b7aa19321bf1460b386"
#define SQLITE_VERSION "3.25.3"
#define SQLITE_VERSION_NUMBER 3025003
#define SQLITE_SOURCE_ID "2018-11-05 20:37:38 89e099fbe5e13c33e683bef07361231ca525b88f7907be7092058007b75036f2"
/*
** CAPI3REF: Run-Time Library Version Numbers
@ -16269,6 +16269,7 @@ struct sqlite3 {
#define SQLITE_EnableQPSG 0x00800000 /* Query Planner Stability Guarantee*/
#define SQLITE_TriggerEQP 0x01000000 /* Show trigger EXPLAIN QUERY PLAN */
#define SQLITE_ResetDatabase 0x02000000 /* Reset the database */
#define SQLITE_LegacyAlter 0x04000000 /* Legacy ALTER TABLE behaviour */
/* Flags used only if debugging */
#ifdef SQLITE_DEBUG
@ -17911,6 +17912,7 @@ struct AuthContext {
*/
#define OPFLAG_NCHANGE 0x01 /* OP_Insert: Set to update db->nChange */
/* Also used in P2 (not P5) of OP_Delete */
#define OPFLAG_NOCHNG 0x01 /* OP_VColumn nochange for UPDATE */
#define OPFLAG_EPHEM 0x01 /* OP_Column: Ephemeral output is ok */
#define OPFLAG_LASTROWID 0x20 /* Set to update db->lastRowid */
#define OPFLAG_ISUPDATE 0x04 /* This OP_Insert is an sql UPDATE */
@ -32619,7 +32621,11 @@ static struct unix_syscall {
#define osLstat ((int(*)(const char*,struct stat*))aSyscall[27].pCurrent)
#if defined(__linux__) && defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE)
# ifdef __ANDROID__
{ "ioctl", (sqlite3_syscall_ptr)(int(*)(int, int, ...))ioctl, 0 },
# else
{ "ioctl", (sqlite3_syscall_ptr)ioctl, 0 },
# endif
#else
{ "ioctl", (sqlite3_syscall_ptr)0, 0 },
#endif
@ -80098,7 +80104,9 @@ SQLITE_PRIVATE int sqlite3VdbeIdxRowid(sqlite3 *db, BtCursor *pCur, i64 *rowid){
(void)getVarint32((u8*)m.z, szHdr);
testcase( szHdr==3 );
testcase( szHdr==m.n );
if( unlikely(szHdr<3 || (int)szHdr>m.n) ){
testcase( szHdr>0x7fffffff );
assert( m.n>=0 );
if( unlikely(szHdr<3 || szHdr>(unsigned)m.n) ){
goto idx_rowid_corruption;
}
@ -89611,10 +89619,11 @@ case OP_VFilter: { /* jump */
**
** If the VColumn opcode is being used to fetch the value of
** an unchanging column during an UPDATE operation, then the P5
** value is 1. Otherwise, P5 is 0. The P5 value is returned
** by sqlite3_vtab_nochange() routine and can be used
** by virtual table implementations to return special "no-change"
** marks which can be more efficient, depending on the virtual table.
** value is OPFLAG_NOCHNG. This will cause the sqlite3_vtab_nochange()
** function to return true inside the xColumn method of the virtual
** table implementation. The P5 column might also contain other
** bits (OPFLAG_LENGTHARG or OPFLAG_TYPEOFARG) but those bits are
** unused by OP_VColumn.
*/
case OP_VColumn: {
sqlite3_vtab *pVtab;
@ -89636,7 +89645,8 @@ case OP_VColumn: {
assert( pModule->xColumn );
memset(&sContext, 0, sizeof(sContext));
sContext.pOut = pDest;
if( pOp->p5 ){
testcase( (pOp->p5 & OPFLAG_NOCHNG)==0 && pOp->p5!=0 );
if( pOp->p5 & OPFLAG_NOCHNG ){
sqlite3VdbeMemSetNull(pDest);
pDest->flags = MEM_Null|MEM_Zero;
pDest->u.nZero = 0;
@ -89713,7 +89723,10 @@ case OP_VNext: { /* jump */
case OP_VRename: {
sqlite3_vtab *pVtab;
Mem *pName;
int isLegacy;
isLegacy = (db->flags & SQLITE_LegacyAlter);
db->flags |= SQLITE_LegacyAlter;
pVtab = pOp->p4.pVtab->pVtab;
pName = &aMem[pOp->p1];
assert( pVtab->pModule->xRename );
@ -89727,6 +89740,7 @@ case OP_VRename: {
rc = sqlite3VdbeChangeEncoding(pName, SQLITE_UTF8);
if( rc ) goto abort_due_to_error;
rc = pVtab->pModule->xRename(pVtab, pName->z);
if( isLegacy==0 ) db->flags &= ~SQLITE_LegacyAlter;
sqlite3VtabImportErrmsg(p, pVtab);
p->expired = 0;
if( rc ) goto abort_due_to_error;
@ -97047,17 +97061,14 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int dupFlags, u8 **pzBuffer){
}
/* Fill in pNew->pLeft and pNew->pRight. */
zAlloc += dupedExprNodeSize(p, dupFlags);
if( ExprHasProperty(pNew, EP_Reduced|EP_TokenOnly) ){
zAlloc += dupedExprNodeSize(p, dupFlags);
if( !ExprHasProperty(pNew, EP_TokenOnly|EP_Leaf) ){
pNew->pLeft = p->pLeft ?
exprDup(db, p->pLeft, EXPRDUP_REDUCE, &zAlloc) : 0;
pNew->pRight = p->pRight ?
exprDup(db, p->pRight, EXPRDUP_REDUCE, &zAlloc) : 0;
}
if( pzBuffer ){
*pzBuffer = zAlloc;
}
}else{
#ifndef SQLITE_OMIT_WINDOWFUNC
if( ExprHasProperty(p, EP_Reduced|EP_TokenOnly) ){
@ -97077,6 +97088,9 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int dupFlags, u8 **pzBuffer){
pNew->pRight = sqlite3ExprDup(db, p->pRight, 0);
}
}
if( pzBuffer ){
*pzBuffer = zAlloc;
}
}
return pNew;
}
@ -100628,18 +100642,15 @@ SQLITE_PRIVATE int sqlite3ExprImpliesExpr(Parse *pParse, Expr *pE1, Expr *pE2, i
/*
** This is the Expr node callback for sqlite3ExprImpliesNotNullRow().
** If the expression node requires that the table at pWalker->iCur
** have a non-NULL column, then set pWalker->eCode to 1 and abort.
** have one or more non-NULL column, then set pWalker->eCode to 1 and abort.
**
** This routine controls an optimization. False positives (setting
** pWalker->eCode to 1 when it should not be) are deadly, but false-negatives
** (never setting pWalker->eCode) is a harmless missed optimization.
*/
static int impliesNotNullRow(Walker *pWalker, Expr *pExpr){
/* This routine is only called for WHERE clause expressions and so it
** cannot have any TK_AGG_COLUMN entries because those are only found
** in HAVING clauses. We can get a TK_AGG_FUNCTION in a WHERE clause,
** but that is an illegal construct and the query will be rejected at
** a later stage of processing, so the TK_AGG_FUNCTION case does not
** need to be considered here. */
assert( pExpr->op!=TK_AGG_COLUMN );
testcase( pExpr->op==TK_AGG_COLUMN );
testcase( pExpr->op==TK_AGG_FUNCTION );
if( ExprHasProperty(pExpr, EP_FromJoin) ) return WRC_Prune;
switch( pExpr->op ){
case TK_ISNOT:
@ -101298,20 +101309,6 @@ SQLITE_PRIVATE void sqlite3AlterRenameTable(
goto exit_rename_table;
}
/* If this is a virtual table, invoke the xRename() function if
** one is defined. The xRename() callback will modify the names
** of any resources used by the v-table implementation (including other
** SQLite tables) that are identified by the name of the virtual table.
*/
#ifndef SQLITE_OMIT_VIRTUALTABLE
if( pVTab ){
int i = ++pParse->nMem;
sqlite3VdbeLoadString(v, i, zName);
sqlite3VdbeAddOp4(v, OP_VRename, i, 0, 0,(const char*)pVTab, P4_VTAB);
sqlite3MayAbort(pParse);
}
#endif
/* figure out how many UTF-8 characters are in zName */
zTabName = pTab->zName;
nTabName = sqlite3Utf8CharLen(zTabName, -1);
@ -101369,6 +101366,20 @@ SQLITE_PRIVATE void sqlite3AlterRenameTable(
, zDb, zTabName, zName, zTabName, zDb, zName);
}
/* If this is a virtual table, invoke the xRename() function if
** one is defined. The xRename() callback will modify the names
** of any resources used by the v-table implementation (including other
** SQLite tables) that are identified by the name of the virtual table.
*/
#ifndef SQLITE_OMIT_VIRTUALTABLE
if( pVTab ){
int i = ++pParse->nMem;
sqlite3VdbeLoadString(v, i, zName);
sqlite3VdbeAddOp4(v, OP_VRename, i, 0, 0,(const char*)pVTab, P4_VTAB);
sqlite3MayAbort(pParse);
}
#endif
renameReloadSchema(pParse, iDb);
renameTestSchema(pParse, zDb, iDb==1);
@ -102551,17 +102562,20 @@ static void renameTableFunc(
rc = renameParseSql(&sParse, zDb, 1, db, zInput, bTemp);
if( rc==SQLITE_OK ){
int isLegacy = (db->flags & SQLITE_LegacyAlter);
if( sParse.pNewTable ){
Table *pTab = sParse.pNewTable;
if( pTab->pSelect ){
NameContext sNC;
memset(&sNC, 0, sizeof(sNC));
sNC.pParse = &sParse;
if( isLegacy==0 ){
NameContext sNC;
memset(&sNC, 0, sizeof(sNC));
sNC.pParse = &sParse;
sqlite3SelectPrep(&sParse, pTab->pSelect, &sNC);
if( sParse.nErr ) rc = sParse.rc;
sqlite3WalkSelect(&sWalker, pTab->pSelect);
sqlite3SelectPrep(&sParse, pTab->pSelect, &sNC);
if( sParse.nErr ) rc = sParse.rc;
sqlite3WalkSelect(&sWalker, pTab->pSelect);
}
}else{
/* Modify any FK definitions to point to the new table. */
#ifndef SQLITE_OMIT_FOREIGN_KEY
@ -102580,7 +102594,9 @@ static void renameTableFunc(
** "CREATE [VIRTUAL] TABLE" bit. */
if( sqlite3_stricmp(zOld, pTab->zName)==0 ){
sCtx.pTab = pTab;
sqlite3WalkExprList(&sWalker, pTab->pCheck);
if( isLegacy==0 ){
sqlite3WalkExprList(&sWalker, pTab->pCheck);
}
renameTokenFind(&sParse, &sCtx, pTab->zName);
}
}
@ -102588,7 +102604,9 @@ static void renameTableFunc(
else if( sParse.pNewIndex ){
renameTokenFind(&sParse, &sCtx, sParse.pNewIndex->zName);
sqlite3WalkExpr(&sWalker, sParse.pNewIndex->pPartIdxWhere);
if( isLegacy==0 ){
sqlite3WalkExpr(&sWalker, sParse.pNewIndex->pPartIdxWhere);
}
}
#ifndef SQLITE_OMIT_TRIGGER
@ -102601,12 +102619,14 @@ static void renameTableFunc(
renameTokenFind(&sParse, &sCtx, sParse.pNewTrigger->table);
}
rc = renameResolveTrigger(&sParse, bTemp ? 0 : zDb);
if( rc==SQLITE_OK ){
renameWalkTrigger(&sWalker, pTrigger);
for(pStep=pTrigger->step_list; pStep; pStep=pStep->pNext){
if( pStep->zTarget && 0==sqlite3_stricmp(pStep->zTarget, zOld) ){
renameTokenFind(&sParse, &sCtx, pStep->zTarget);
if( isLegacy==0 ){
rc = renameResolveTrigger(&sParse, bTemp ? 0 : zDb);
if( rc==SQLITE_OK ){
renameWalkTrigger(&sWalker, pTrigger);
for(pStep=pTrigger->step_list; pStep; pStep=pStep->pNext){
if( pStep->zTarget && 0==sqlite3_stricmp(pStep->zTarget, zOld) ){
renameTokenFind(&sParse, &sCtx, pStep->zTarget);
}
}
}
}
@ -102664,6 +102684,7 @@ static void renameTableTest(
char const *zDb = (const char*)sqlite3_value_text(argv[0]);
char const *zInput = (const char*)sqlite3_value_text(argv[1]);
int bTemp = sqlite3_value_int(argv[4]);
int isLegacy = (db->flags & SQLITE_LegacyAlter);
#ifndef SQLITE_OMIT_AUTHORIZATION
sqlite3_xauth xAuth = db->xAuth;
@ -102676,7 +102697,7 @@ static void renameTableTest(
Parse sParse;
rc = renameParseSql(&sParse, zDb, 1, db, zInput, bTemp);
if( rc==SQLITE_OK ){
if( sParse.pNewTable && sParse.pNewTable->pSelect ){
if( isLegacy==0 && sParse.pNewTable && sParse.pNewTable->pSelect ){
NameContext sNC;
memset(&sNC, 0, sizeof(sNC));
sNC.pParse = &sParse;
@ -102685,7 +102706,9 @@ static void renameTableTest(
}
else if( sParse.pNewTrigger ){
rc = renameResolveTrigger(&sParse, bTemp ? 0 : zDb);
if( isLegacy==0 ){
rc = renameResolveTrigger(&sParse, bTemp ? 0 : zDb);
}
if( rc==SQLITE_OK ){
int i1 = sqlite3SchemaToIndex(db, sParse.pNewTrigger->pTabSchema);
int i2 = sqlite3FindDbName(db, zDb);
@ -107335,10 +107358,6 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
}
}
/* The remaining transformations only apply to b-tree tables, not to
** virtual tables */
if( IN_DECLARE_VTAB ) return;
/* Convert the P3 operand of the OP_CreateBtree opcode from BTREE_INTKEY
** into BTREE_BLOBKEY.
*/
@ -119469,6 +119488,11 @@ static const PragmaName aPragmaName[] = {
/* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
{/* zName: */ "legacy_alter_table",
/* ePragTyp: */ PragTyp_FLAG,
/* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
/* ColNames: */ 0, 0,
/* iArg: */ SQLITE_LegacyAlter },
{/* zName: */ "legacy_file_format",
/* ePragTyp: */ PragTyp_FLAG,
/* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
@ -119722,7 +119746,7 @@ static const PragmaName aPragmaName[] = {
/* iArg: */ SQLITE_WriteSchema },
#endif
};
/* Number of pragmas: 60 on by default, 77 total. */
/* Number of pragmas: 61 on by default, 78 total. */
/************** End of pragma.h **********************************************/
/************** Continuing where we left off in pragma.c *********************/
@ -125422,6 +125446,13 @@ static void generateWithRecursiveQuery(
Expr *pLimit; /* Saved LIMIT and OFFSET */
int regLimit, regOffset; /* Registers used by LIMIT and OFFSET */
#ifndef SQLITE_OMIT_WINDOWFUNC
if( p->pWin ){
sqlite3ErrorMsg(pParse, "cannot use window functions in recursive queries");
return;
}
#endif
/* Obtain authorization to do a recursive query */
if( sqlite3AuthCheck(pParse, SQLITE_RECURSIVE, 0, 0, 0) ) return;
@ -127171,7 +127202,7 @@ static int flattenSubquery(
#endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */
/*
** A structure to keep track of all of the column values that fixed to
** A structure to keep track of all of the column values that are fixed to
** a known value due to WHERE clause constraints of the form COLUMN=VALUE.
*/
typedef struct WhereConst WhereConst;
@ -127183,13 +127214,28 @@ struct WhereConst {
};
/*
** Add a new entry to the pConst object
** Add a new entry to the pConst object. Except, do not add duplicate
** pColumn entires.
*/
static void constInsert(
WhereConst *pConst,
Expr *pColumn,
Expr *pValue
WhereConst *pConst, /* The WhereConst into which we are inserting */
Expr *pColumn, /* The COLUMN part of the constraint */
Expr *pValue /* The VALUE part of the constraint */
){
int i;
assert( pColumn->op==TK_COLUMN );
/* 2018-10-25 ticket [cf5ed20f]
** Make sure the same pColumn is not inserted more than once */
for(i=0; i<pConst->nConst; i++){
const Expr *pExpr = pConst->apExpr[i*2];
assert( pExpr->op==TK_COLUMN );
if( pExpr->iTable==pColumn->iTable
&& pExpr->iColumn==pColumn->iColumn
){
return; /* Already present. Return without doing anything. */
}
}
pConst->nConst++;
pConst->apExpr = sqlite3DbReallocOrFree(pConst->pParse->db, pConst->apExpr,
@ -131955,7 +132001,7 @@ static void updateVirtualTable(
sqlite3ExprCode(pParse, pChanges->a[aXRef[i]].pExpr, regArg+2+i);
}else{
sqlite3VdbeAddOp3(v, OP_VColumn, iCsr, i, regArg+2+i);
sqlite3VdbeChangeP5(v, 1); /* Enable sqlite3_vtab_nochange() */
sqlite3VdbeChangeP5(v, OPFLAG_NOCHNG);/* Enable sqlite3_vtab_nochange() */
}
}
if( HasRowid(pTab) ){
@ -134910,7 +134956,7 @@ static Expr *removeUnindexableInClauseTerms(
for(i=iEq; i<pLoop->nLTerm; i++){
if( pLoop->aLTerm[i]->pExpr==pX ){
int iField = pLoop->aLTerm[i]->iField - 1;
assert( pOrigRhs->a[iField].pExpr!=0 );
if( pOrigRhs->a[iField].pExpr==0 ) continue; /* Duplicate PK column */
pRhs = sqlite3ExprListAppend(pParse, pRhs, pOrigRhs->a[iField].pExpr);
pOrigRhs->a[iField].pExpr = 0;
assert( pOrigLhs->a[iField].pExpr!=0 );
@ -138103,6 +138149,7 @@ static void exprAnalyze(
if( pExpr->op==TK_NOTNULL
&& pExpr->pLeft->op==TK_COLUMN
&& pExpr->pLeft->iColumn>=0
&& !ExprHasProperty(pExpr, EP_FromJoin)
&& OptimizationEnabled(db, SQLITE_Stat34)
){
Expr *pNewExpr;
@ -154763,6 +154810,7 @@ static int openDatabase(
db->nDb = 2;
db->magic = SQLITE_MAGIC_BUSY;
db->aDb = db->aDbStatic;
db->lookaside.bDisable = 1;
assert( sizeof(db->aLimit)==sizeof(aHardLimit) );
memcpy(db->aLimit, aHardLimit, sizeof(db->aLimit));
@ -159141,7 +159189,7 @@ static int fts3ScanInteriorNode(
const char *zCsr = zNode; /* Cursor to iterate through node */
const char *zEnd = &zCsr[nNode];/* End of interior node buffer */
char *zBuffer = 0; /* Buffer to load terms into */
int nAlloc = 0; /* Size of allocated buffer */
i64 nAlloc = 0; /* Size of allocated buffer */
int isFirstTerm = 1; /* True when processing first term on page */
sqlite3_int64 iChild; /* Block id of child node to descend to */
@ -159179,14 +159227,14 @@ static int fts3ScanInteriorNode(
zCsr += fts3GetVarint32(zCsr, &nSuffix);
assert( nPrefix>=0 && nSuffix>=0 );
if( &zCsr[nSuffix]>zEnd ){
if( nPrefix>zCsr-zNode || nSuffix>zEnd-zCsr ){
rc = FTS_CORRUPT_VTAB;
goto finish_scan;
}
if( nPrefix+nSuffix>nAlloc ){
if( (i64)nPrefix+nSuffix>nAlloc ){
char *zNew;
nAlloc = (nPrefix+nSuffix) * 2;
zNew = (char *)sqlite3_realloc(zBuffer, nAlloc);
nAlloc = ((i64)nPrefix+nSuffix) * 2;
zNew = (char *)sqlite3_realloc64(zBuffer, nAlloc);
if( !zNew ){
rc = SQLITE_NOMEM;
goto finish_scan;
@ -168768,15 +168816,19 @@ static int fts3SegReaderNext(
** safe (no risk of overread) even if the node data is corrupted. */
pNext += fts3GetVarint32(pNext, &nPrefix);
pNext += fts3GetVarint32(pNext, &nSuffix);
if( nPrefix<0 || nSuffix<=0
|| &pNext[nSuffix]>&pReader->aNode[pReader->nNode]
if( nSuffix<=0
|| (&pReader->aNode[pReader->nNode] - pNext)<nSuffix
|| nPrefix>pReader->nTermAlloc
){
return FTS_CORRUPT_VTAB;
}
if( nPrefix+nSuffix>pReader->nTermAlloc ){
int nNew = (nPrefix+nSuffix)*2;
char *zNew = sqlite3_realloc(pReader->zTerm, nNew);
/* Both nPrefix and nSuffix were read by fts3GetVarint32() and so are
** between 0 and 0x7FFFFFFF. But the sum of the two may cause integer
** overflow - hence the (i64) casts. */
if( (i64)nPrefix+nSuffix>(i64)pReader->nTermAlloc ){
i64 nNew = ((i64)nPrefix+nSuffix)*2;
char *zNew = sqlite3_realloc64(pReader->zTerm, nNew);
if( !zNew ){
return SQLITE_NOMEM;
}
@ -168798,7 +168850,7 @@ static int fts3SegReaderNext(
** b-tree node. And that the final byte of the doclist is 0x00. If either
** of these statements is untrue, then the data structure is corrupt.
*/
if( &pReader->aDoclist[pReader->nDoclist]>&pReader->aNode[pReader->nNode]
if( (&pReader->aNode[pReader->nNode] - pReader->aDoclist)<pReader->nDoclist
|| (pReader->nPopulate==0 && pReader->aDoclist[pReader->nDoclist-1])
){
return FTS_CORRUPT_VTAB;
@ -171124,6 +171176,9 @@ static int nodeReaderNext(NodeReader *p){
}
p->iOff += fts3GetVarint32(&p->aNode[p->iOff], &nSuffix);
if( nPrefix>p->iOff || nSuffix>p->nNode-p->iOff ){
return SQLITE_CORRUPT_VTAB;
}
blobGrowBuffer(&p->term, nPrefix+nSuffix, &rc);
if( rc==SQLITE_OK ){
memcpy(&p->term.a[nPrefix], &p->aNode[p->iOff], nSuffix);
@ -171131,6 +171186,9 @@ static int nodeReaderNext(NodeReader *p){
p->iOff += nSuffix;
if( p->iChild==0 ){
p->iOff += fts3GetVarint32(&p->aNode[p->iOff], &p->nDoclist);
if( (p->nNode-p->iOff)<p->nDoclist ){
return SQLITE_CORRUPT_VTAB;
}
p->aDoclist = &p->aNode[p->iOff];
p->iOff += p->nDoclist;
}
@ -171138,7 +171196,6 @@ static int nodeReaderNext(NodeReader *p){
}
assert( p->iOff<=p->nNode );
return rc;
}
@ -214424,7 +214481,7 @@ static void fts5SourceIdFunc(
){
assert( nArg==0 );
UNUSED_PARAM2(nArg, apUnused);
sqlite3_result_text(pCtx, "fts5: 2018-09-18 20:20:44 2ac9003de44da7dafa3fbb1915ac5725a9275c86bf2f3b7aa19321bf1460b386", -1, SQLITE_TRANSIENT);
sqlite3_result_text(pCtx, "fts5: 2018-11-05 20:37:38 89e099fbe5e13c33e683bef07361231ca525b88f7907be7092058007b75036f2", -1, SQLITE_TRANSIENT);
}
static int fts5Init(sqlite3 *db){
@ -219134,9 +219191,9 @@ SQLITE_API int sqlite3_stmt_init(
#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_STMTVTAB) */
/************** End of stmt.c ************************************************/
#if __LINE__!=219137
#if __LINE__!=219194
#undef SQLITE_SOURCE_ID
#define SQLITE_SOURCE_ID "2018-09-18 20:20:44 2ac9003de44da7dafa3fbb1915ac5725a9275c86bf2f3b7aa19321bf1460alt2"
#define SQLITE_SOURCE_ID "2018-11-05 20:37:38 89e099fbe5e13c33e683bef07361231ca525b88f7907be7092058007b750alt2"
#endif
/* Return the source-id for this library */
SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; }

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

@ -123,9 +123,9 @@ extern "C" {
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
#define SQLITE_VERSION "3.25.1"
#define SQLITE_VERSION_NUMBER 3025001
#define SQLITE_SOURCE_ID "2018-09-18 20:20:44 2ac9003de44da7dafa3fbb1915ac5725a9275c86bf2f3b7aa19321bf1460b386"
#define SQLITE_VERSION "3.25.3"
#define SQLITE_VERSION_NUMBER 3025003
#define SQLITE_SOURCE_ID "2018-11-05 20:37:38 89e099fbe5e13c33e683bef07361231ca525b88f7907be7092058007b75036f2"
/*
** CAPI3REF: Run-Time Library Version Numbers

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

@ -214,7 +214,7 @@ var gDevToolsBrowser = exports.gDevToolsBrowser = {
toolbox.hostType == Toolbox.HostType.WINDOW) {
toolbox.raise();
} else {
gDevTools.closeToolbox(target);
toolbox.destroy();
}
gDevTools.emit("select-tool-command", toolId);
} else {

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

@ -26,7 +26,7 @@ add_task(async function() {
is(store.getState().requests.requests.size, 0, "No network requests appear in the network panel");
await gDevTools.closeToolbox(target);
await toolbox.destroy();
tab = target = toolbox = panel = null;
gBrowser.removeCurrentTab();
});

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

@ -32,7 +32,7 @@ add_task(async function() {
let toolbox = await gDevTools.showToolbox(target, testToolDefinition.id);
is(toolbox.currentToolId, "testTool", "test-tool was selected");
await gDevTools.closeToolbox(target);
await toolbox.destroy();
// Make the previously selected tool unavailable.
testToolDefinition.isTargetSupported = () => false;
@ -41,7 +41,7 @@ add_task(async function() {
toolbox = await gDevTools.showToolbox(target);
is(toolbox.currentToolId, "webconsole", "web console was selected");
await gDevTools.closeToolbox(target);
await toolbox.destroy();
gDevTools.unregisterTool(testToolDefinition.id);
tab = toolbox = target = null;
gBrowser.removeCurrentTab();

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

@ -20,41 +20,33 @@ class FlexItemSizingProperties extends PureComponent {
}
/**
* Rounds some dimension in pixels and returns a string to be displayed to the user.
* The string will end with 'px'. If the number is 0, the string "0" is returned.
* Rounds some size in pixels and render it.
* The rendered value will end with 'px' (unless the dimension is 0 in which case the
* unit will be omitted)
*
* @param {Number} value
* The number to be rounded
* @return {String}
* Representation of the rounded number
* @param {Boolean} prependPlusSign
* If set to true, the + sign will be printed before a positive value
* @return {Object}
* The React component representing this rounded size
*/
getRoundedDimension(value) {
renderSize(value, prependPlusSign) {
if (value == 0) {
return "0";
}
return (Math.round(value * 100) / 100) + "px";
}
/**
* Format the flexibility value into a meaningful value for the UI.
* If the item grew, then prepend a + sign, if it shrank, prepend a - sign.
* If it didn't flex, return "0".
*
* @param {Boolean} grew
* Whether the item grew or not
* @param {Number} value
* The amount of pixels the item flexed
* @return {String}
* Representation of the flexibility value
*/
getFlexibilityValueString(grew, mainDeltaSize) {
const value = this.getRoundedDimension(mainDeltaSize);
if (grew) {
return "+" + value;
return dom.span({ className: "value" }, "0");
}
return value;
value = (Math.round(value * 100) / 100);
if (prependPlusSign && value > 0) {
value = "+" + value;
}
return (
dom.span({ className: "value" },
value,
dom.span({ className: "unit" }, "px")
)
);
}
/**
@ -70,14 +62,7 @@ class FlexItemSizingProperties extends PureComponent {
* The React component representing this CSS property
*/
renderCssProperty(name, value, isDefaultValue) {
return (
dom.span({ className: "css-property-link" },
dom.span({ className: "theme-fg-color5" }, name),
": ",
dom.span({ className: "theme-fg-color1" }, value),
";"
)
);
return dom.span({ className: "css-property-link" }, `(${name}: ${value})`);
}
/**
@ -120,12 +105,10 @@ class FlexItemSizingProperties extends PureComponent {
return (
dom.li({ className: className + (property ? "" : " no-property") },
dom.span({ className: "name" },
getStr("flexbox.itemSizing.baseSizeSectionHeader")
getStr("flexbox.itemSizing.baseSizeSectionHeader"),
property
),
dom.span({ className: "value theme-fg-color1" },
this.getRoundedDimension(mainBaseSize)
),
property,
this.renderSize(mainBaseSize),
reason
)
);
@ -216,12 +199,10 @@ class FlexItemSizingProperties extends PureComponent {
return (
dom.li({ className: className + (property ? "" : " no-property") },
dom.span({ className: "name" },
getStr("flexbox.itemSizing.flexibilitySectionHeader")
getStr("flexbox.itemSizing.flexibilitySectionHeader"),
property
),
dom.span({ className: "value theme-fg-color1" },
this.getFlexibilityValueString(grew, mainDeltaSize)
),
property,
this.renderSize(mainDeltaSize, true),
this.renderReasons(reasons)
)
);
@ -239,12 +220,10 @@ class FlexItemSizingProperties extends PureComponent {
return (
dom.li({ className: "section min" },
dom.span({ className: "name" },
getStr("flexbox.itemSizing.minSizeSectionHeader")
getStr("flexbox.itemSizing.minSizeSectionHeader"),
this.renderCssProperty(`min-${dimension}`, minDimensionValue)
),
dom.span({ className: "value theme-fg-color1" },
this.getRoundedDimension(mainMinSize)
),
this.renderCssProperty(`min-${dimension}`, minDimensionValue)
this.renderSize(mainMinSize)
)
);
}
@ -259,12 +238,10 @@ class FlexItemSizingProperties extends PureComponent {
return (
dom.li({ className: "section max" },
dom.span({ className: "name" },
getStr("flexbox.itemSizing.maxSizeSectionHeader")
getStr("flexbox.itemSizing.maxSizeSectionHeader"),
this.renderCssProperty(`max-${dimension}`, maxDimensionValue)
),
dom.span({ className: "value theme-fg-color1" },
this.getRoundedDimension(mainMaxSize)
),
this.renderCssProperty(`max-${dimension}`, maxDimensionValue)
this.renderSize(mainMaxSize)
)
);
}
@ -275,9 +252,7 @@ class FlexItemSizingProperties extends PureComponent {
dom.span({ className: "name" },
getStr("flexbox.itemSizing.finalSizeSectionHeader")
),
dom.span({ className: "value theme-fg-color1" },
this.getRoundedDimension(mainFinalSize)
)
this.renderSize(mainFinalSize)
)
);
}

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

@ -11,6 +11,7 @@ support-files =
!/devtools/client/inspector/test/head.js
!/devtools/client/inspector/test/shared-head.js
!/devtools/client/shared/test/shared-head.js
!/devtools/client/shared/test/shared-redux-head.js
!/devtools/client/shared/test/telemetry-test-helpers.js
!/devtools/client/shared/test/test-actor.js
!/devtools/client/shared/test/test-actor-registry.js

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

@ -25,8 +25,9 @@ add_task(async function() {
info("Check that the base, flexibility and final sizes are displayed");
const allSections = [...flexSizingContainer.querySelectorAll(".section .name")];
const allSectionTitles = allSections.map(el => el.textContent);
const expectedTitles = ["Base Size", "Flexibility", "Final Size"];
ok(expectedTitles.every(title => allSectionTitles.includes(title)),
"The 3 main sizing sections where found");
["Base Size", "Flexibility", "Final Size"].forEach((expectedTitle, i) => {
ok(allSectionTitles[i].includes(expectedTitle),
`Sizing section #${i + 1} (${expectedTitle}) was found`);
});
});

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

@ -20,10 +20,10 @@ async function checkFlexItemDimension(inspector, doc, selector, expectedDimensio
info("Check that the minimum size section shows the correct dimension.");
const [sectionMinRowItem] = [...flexItemSizingContainer.querySelectorAll(
".section.min")];
const minDimension = sectionMinRowItem.querySelector(".theme-fg-color5");
const minDimension = sectionMinRowItem.querySelector(".css-property-link");
is(minDimension.textContent, expectedDimension,
"The flex item sizing has the correct dimension value.");
ok(minDimension.textContent.includes(expectedDimension),
"The flex item sizing has the correct dimension value.");
}
add_task(async function() {

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

@ -35,7 +35,8 @@ add_task(async function() {
is(sections.length, expectedSections.length, "Correct number of sections found");
expectedSections.forEach((expectedSection, i) => {
is(sections[i], expectedSection, `The ${expectedSection} section was found`);
ok(sections[i].includes(expectedSection),
`The ${expectedSection} section was found`);
});
}
});

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

@ -58,7 +58,7 @@ add_task(async function() {
await assertMarkupView(inspector);
info("Close DevTools before testing Inspect Element");
await gDevTools.closeToolbox(inspector.target);
await toolbox.destroy();
info("Waiting for element picker to become active.");
const newTestActor = await getTestActorWithoutToolbox(tab);

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

@ -35,7 +35,7 @@ add_task(async function() {
ok(splitter.classList.contains("horz"), "Splitter is in horizontal mode");
info("Close the inspector");
await gDevTools.closeToolbox(toolbox.target);
await toolbox.destroy();
info("Reopen inspector");
({ inspector, toolbox } = await openInspector("window"));

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

@ -26,8 +26,7 @@ async function runTests([win, sp]) {
const target = await TargetFactory.forTab(gBrowser.selectedTab);
const toolbox = await gDevTools.showToolbox(target, "webconsole");
ok(toolbox, "Toolbox was opened.");
const closed = await gDevTools.closeToolbox(target);
is(closed, true, "Toolbox was closed.");
await toolbox.destroy();
// Now see if using the scratcphad works as expected.
sp.setText(source);

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

@ -28,7 +28,7 @@ add_task(async function testNormalExecution() {
terminateWorkerInTab(tab, WORKER_URL);
await waitForWorkerClose(workerTargetFront);
await gDevTools.closeToolbox(TargetFactory.forWorker(workerTargetFront));
await toolbox.destroy();
await close(client);
await removeTab(tab);
});

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

@ -56,7 +56,7 @@ add_task(async function testWhilePaused() {
terminateWorkerInTab(tab, WORKER_URL);
await waitForWorkerClose(workerTargetFront);
await gDevTools.closeToolbox(TargetFactory.forWorker(workerTargetFront));
await toolbox.destroy();
await close(client);
await removeTab(tab);
});

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

@ -47,7 +47,7 @@ add_task(async function testPausedByConsole() {
terminateWorkerInTab(tab, WORKER_URL);
await waitForWorkerClose(workerTargetFront);
await gDevTools.closeToolbox(TargetFactory.forWorker(workerTargetFront));
await toolbox.destroy();
await close(client);
await removeTab(tab);
});

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

@ -43,7 +43,7 @@ add_task(async function testPausedByConsole() {
terminateWorkerInTab(tab, WORKER_URL);
await waitForWorkerClose(workerTargetFront);
await gDevTools.closeToolbox(TargetFactory.forWorker(workerTargetFront));
await toolbox.destroy();
await close(client);
await removeTab(tab);
});

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

@ -16,7 +16,7 @@ add_task(async function() {
info("testing the eyedropper button");
await testButton(toolbox);
await gDevTools.closeToolbox(target);
await toolbox.destroy();
gBrowser.removeCurrentTab();
});

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

@ -24,7 +24,7 @@ add_task(async function() {
info("testing the paintflashing button");
await testButton(toolbox);
await gDevTools.closeToolbox(target);
await toolbox.destroy();
gBrowser.removeCurrentTab();
});

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

@ -43,7 +43,7 @@ add_task(async function() {
info("testing the responsivedesign button");
await testButton(toolbox);
await gDevTools.closeToolbox(target);
await toolbox.destroy();
gBrowser.removeCurrentTab();
});

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

@ -29,7 +29,7 @@ add_task(async function() {
checkResults();
await gDevTools.closeToolbox(target);
await toolbox.destroy();
gBrowser.removeCurrentTab();
});

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

@ -121,7 +121,7 @@ add_task(async function() {
checkResults();
checkEventTelemetry();
await gDevTools.closeToolbox(target);
await toolbox.destroy();
gBrowser.removeCurrentTab();
});

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

@ -132,13 +132,13 @@ async function openAndCloseToolbox(nbOfTimes, usageTime, toolId) {
for (let i = 0; i < nbOfTimes; i++) {
info("Opening toolbox " + (i + 1));
const target = await TargetFactory.forTab(gBrowser.selectedTab);
await gDevTools.showToolbox(target, toolId);
const toolbox = await gDevTools.showToolbox(target, toolId);
// We use a timeout to check the toolbox's active time
await new Promise(resolve => setTimeout(resolve, usageTime));
info("Closing toolbox " + (i + 1));
await gDevTools.closeToolbox(target);
await toolbox.destroy();
}
}

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

@ -136,6 +136,8 @@ function Editor(config) {
themeSwitching: true,
autocomplete: false,
autocompleteOpts: {},
// Set to true to prevent the search addon to be activated.
disableSearchAddon: false,
};
// Additional shortcuts.
@ -438,7 +440,9 @@ Editor.prototype = {
return L10N.getStr(name);
});
this._initShortcuts(win);
if (!this.config.disableSearchAddon) {
this._initSearchShortcuts(win);
}
editors.set(this, cm);
@ -1398,11 +1402,11 @@ Editor.prototype = {
/**
* Register all key shortcuts.
*/
_initShortcuts: function(win) {
_initSearchShortcuts: function(win) {
const shortcuts = new KeyShortcuts({
window: win,
});
this._onShortcut = this._onShortcut.bind(this);
this._onSearchShortcut = this._onSearchShortcut.bind(this);
const keys = [
"find.key",
"findNext.key",
@ -1417,13 +1421,13 @@ Editor.prototype = {
// Process generic keys:
keys.forEach(name => {
const key = L10N.getStr(name);
shortcuts.on(key, event => this._onShortcut(name, event));
shortcuts.on(key, event => this._onSearchShortcut(name, event));
});
},
/**
* Key shortcut listener.
*/
_onShortcut: function(name, event) {
_onSearchShortcut: function(name, event) {
if (!this._isInputOrTextarea(event.target)) {
return;
}

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

@ -389,30 +389,22 @@
*/
.flex-item-sizing {
margin: 20px;
margin: 0;
padding: 0;
list-style: none;
}
.flex-item-sizing .section {
--padding: 10px;
margin-block-start: var(--padding);
padding: var(--padding) 0 0 0;
padding: var(--padding);
border-block-start: 1px solid var(--theme-splitter-color);
display: grid;
grid-template-columns: 1fr max-content;
grid-column-gap: var(--padding);
}
/* If the outline isn't displayed before the sizing information, then no need for a first
top border or padding */
:not(.flex-outline-container) + .flex-item-sizing > .section:first-child {
border: 0;
padding-block-start: 0;
}
.flex-item-sizing .section:first-child {
margin: 0;
border: 0;
}
.flex-item-sizing .name {
@ -425,9 +417,14 @@
font-weight: 600;
}
.flex-item-sizing .value .unit {
color: var(--theme-comment);
font-weight: normal;
}
.flex-item-sizing .css-property-link {
grid-column: 2;
text-align: end;
font-weight: normal;
margin-inline-start: .5em;
}
.flex-item-sizing .reasons,

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

@ -200,6 +200,7 @@ class JSTerm extends Component {
styleActiveLine: false,
tabIndex: "0",
viewportMargin: Infinity,
disableSearchAddon: true,
extraKeys: {
"Enter": () => {
// No need to handle shift + Enter as it's natively handled by CodeMirror.

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

@ -19,14 +19,14 @@ const TEST_URI =
add_task(async function() {
// Run in legacy JsTerm.
await pushPref("devtools.webconsole.jsterm.codeMirror", false);
await testHistory();
await performTests();
// And then in codeMirror JsTerm.
await pushPref("devtools.webconsole.jsterm.codeMirror", true);
await testHistory();
await performTests();
});
async function testHistory() {
async function performTests() {
const hud = await openNewTabAndConsole(TEST_URI);
info("Web Console opened");
const outputScroller = hud.ui.outputScroller;
@ -70,6 +70,11 @@ async function testHistory() {
info("try ctrl-f to focus filter");
synthesizeKeyShortcut(WCUL10n.getStr("webconsole.find.key"));
ok(!isJstermFocused(hud.jsterm), "jsterm input is not focused");
ok(hasFocus(hud.ui.filterBox), "filter input is focused");
info("try ctrl-f when filter is already focused");
synthesizeKeyShortcut(WCUL10n.getStr("webconsole.find.key"));
ok(!isJstermFocused(hud.jsterm), "jsterm input is not focused");
is(hud.ui.filterBox, outputScroller.ownerDocument.activeElement,
"filter input is focused");
}

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

@ -545,10 +545,14 @@ const ThreadActor = ActorClassWithSpec(threadSpec, {
if (steppingType == "finish") {
const parentFrame = thread._getNextStepFrame(this);
if (parentFrame && parentFrame.script) {
const { onStep } = thread._makeSteppingHooks(
const { onStep, onPop } = thread._makeSteppingHooks(
originalLocation, "next", false, completion
);
parentFrame.onStep = onStep;
// We need the onPop alongside the onStep because it is possible that
// the parent frame won't have any steppable offsets, and we want to
// make sure that we always pause in the parent _somewhere_.
parentFrame.onPop = onPop;
return undefined;
}
}

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

@ -0,0 +1,62 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
/**
* Check that step out stops at the end of the parent if it fails to stop
* anywhere else. Bug 1504358.
*/
var gDebuggee;
var gClient;
var gCallback;
function run_test() {
do_test_pending();
run_test_with_server(DebuggerServer, function() {
run_test_with_server(WorkerDebuggerServer, do_test_finished);
});
}
function run_test_with_server(server, callback) {
gCallback = callback;
initTestDebuggerServer(server);
gDebuggee = addTestGlobal("test-stepping", server);
gClient = new DebuggerClient(server.connectPipe());
gClient.connect(testStepOutWithBreakpoint);
}
async function testStepOutWithBreakpoint() {
const [attachResponse,, threadClient] = await attachTestTabAndResume(gClient,
"test-stepping");
ok(!attachResponse.error, "Should not get an error attaching");
dumpn("Evaluating test code and waiting for first debugger statement");
const dbgStmt = await executeOnNextTickAndWaitForPause(evaluateTestCode, gClient);
equal(dbgStmt.frame.where.line, 2, "Should be at debugger statement on line 2");
dumpn("Step out of inner and into outer");
const step2 = await stepOut(gClient, threadClient);
// The bug was that we'd step right past the end of the function and never pause.
equal(step2.frame.where.line, 2);
equal(step2.why.frameFinished.return, 42);
finishClient(gClient, gCallback);
}
function evaluateTestCode() {
// By placing the inner and outer on the same line, this triggers the server's
// logic to skip steps for these functions, meaning that onPop is the only
// thing that will cause it to pop.
Cu.evalInSandbox(
`
function outer(){ inner(); return 42; } function inner(){ debugger; }
outer();
`,
gDebuggee,
"1.8",
"test_stepping-09-test-code.js",
1
);
}

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

@ -196,6 +196,7 @@ reason = bug 1104838
[test_stepping-06.js]
[test_stepping-07.js]
[test_stepping-08.js]
[test_stepping-09.js]
[test_stepping-with-pause-points.js]
[test_stepping-with-skip-breakpoints.js]
[test_framebindings-01.js]

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

@ -424,6 +424,10 @@ nsDocShell::~nsDocShell()
// Avoid notifying observers while we're in the dtor.
mIsBeingDestroyed = true;
#ifdef MOZ_GECKO_PROFILER
profiler_unregister_pages(mHistoryID);
#endif
Destroy();
if (mSessionHistory) {
@ -2526,8 +2530,6 @@ nsDocShell::SetCustomUserAgent(const nsAString& aCustomUserAgent)
NS_IMETHODIMP
nsDocShell::GetTouchEventsOverride(uint32_t* aTouchEventsOverride)
{
NS_ENSURE_ARG_POINTER(aTouchEventsOverride);
*aTouchEventsOverride = mTouchEventsOverride;
return NS_OK;
}
@ -11360,6 +11362,21 @@ nsDocShell::OnNewURI(nsIURI* aURI, nsIChannel* aChannel,
}
}
#ifdef MOZ_GECKO_PROFILER
// We register the page load only if the load updates the history and it's not
// a refresh. This also registers the iframes in shift-reload case, but it's
// reasonable to register since we are updating the historyId in that case.
if (updateSHistory) {
uint32_t id = 0;
nsAutoCString spec;
if (mLSHE) {
mLSHE->GetID(&id);
}
aURI->GetSpec(spec);
profiler_register_page(mHistoryID, id, spec, IsFrame());
}
#endif
// If this is a POST request, we do not want to include this in global
// history.
if (updateGHistory && aAddToGlobalHistory && !ChannelIsPost(aChannel)) {
@ -11670,6 +11687,12 @@ nsDocShell::AddState(JS::Handle<JS::Value> aData, const nsAString& aTitle,
// we'll just set mOSHE here.
mOSHE = newSHEntry;
#ifdef MOZ_GECKO_PROFILER
uint32_t id = 0;
GetOSHEId(&id);
profiler_register_page(mHistoryID, id, NS_ConvertUTF16toUTF8(aURL), IsFrame());
#endif
} else {
newSHEntry = mOSHE;
newSHEntry->SetURI(newURI);
@ -13759,6 +13782,17 @@ nsDocShell::SetOriginAttributes(JS::Handle<JS::Value> aOriginAttributes,
return SetOriginAttributes(attrs);
}
NS_IMETHODIMP
nsDocShell::GetOSHEId(uint32_t* aSHEntryId)
{
if (mOSHE) {
mOSHE->GetID(aSHEntryId);
return NS_OK;
} else {
return NS_ERROR_FAILURE;
}
}
NS_IMETHODIMP
nsDocShell::GetAsyncPanZoomEnabled(bool* aOut)
{
@ -14039,7 +14073,6 @@ nsIDocShell::SetHTMLEditor(HTMLEditor* aHTMLEditor)
NS_IMETHODIMP
nsDocShell::GetDisplayMode(uint32_t* aDisplayMode)
{
NS_ENSURE_ARG_POINTER(aDisplayMode);
*aDisplayMode = mDisplayMode;
return NS_OK;
}

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

@ -1091,6 +1091,8 @@ interface nsIDocShell : nsIDocShellTreeItem
in string asyncCause);
[noscript,notxpcom,nostdcall] void notifyJSRunToCompletionStop();
[noscript] void GetOSHEId(out uint32_t aSHEntryId);
/**
* This attribute determines whether a document which is not about:blank has
* already be loaded by this docShell.
@ -1136,7 +1138,7 @@ interface nsIDocShell : nsIDocShellTreeItem
* This allows chrome to override the default choice of whether touch events
* are available on a specific docshell. Possible values are listed below.
*/
attribute unsigned long touchEventsOverride;
[infallible] attribute unsigned long touchEventsOverride;
/**
* Override platform/pref default behaviour and force-disable touch events.
*/
@ -1252,7 +1254,7 @@ interface nsIDocShell : nsIDocShellTreeItem
* Display mode for this docshell. Defaults to DISPLAY_MODE_BROWSER.
* Media queries only look at the value in the top-most docshell.
*/
attribute unsigned long displayMode;
[infallible] attribute unsigned long displayMode;
/**
* The message manager for this docshell. This does not throw, but

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

@ -19,7 +19,6 @@
#include "mozilla/AutoRestore.h"
#include "mozilla/ComputedStyleInlines.h"
#include "mozilla/EffectSet.h"
#include "mozilla/LayerAnimationInfo.h"
#include "mozilla/RestyleManager.h"
#include "mozilla/ServoBindings.h" // Servo_GetProperties_Overriding_Animation
#include "mozilla/ServoStyleSet.h"
@ -609,7 +608,9 @@ EffectCompositor::GetOverriddenProperties(EffectSet& aEffectSet,
return result;
}
AutoTArray<nsCSSPropertyID, LayerAnimationInfo::kRecords> propertiesToTrack;
static constexpr size_t compositorAnimatableCount =
nsCSSPropertyIDSet::CompositorAnimatableCount();
AutoTArray<nsCSSPropertyID, compositorAnimatableCount> propertiesToTrack;
{
nsCSSPropertyIDSet propertiesToTrackAsSet;
for (KeyframeEffect* effect : aEffectSet) {
@ -623,7 +624,7 @@ EffectCompositor::GetOverriddenProperties(EffectSet& aEffectSet,
}
// Skip iterating over the rest of the effects if we've already
// found all the compositor-animatable properties.
if (propertiesToTrack.Length() == LayerAnimationInfo::kRecords) {
if (propertiesToTrack.Length() == compositorAnimatableCount) {
break;
}
}
@ -666,31 +667,17 @@ EffectCompositor::UpdateCascadeResults(EffectSet& aEffectSet,
nsCSSPropertyIDSet overriddenProperties =
GetOverriddenProperties(aEffectSet, aElement, aPseudoType);
// Returns a bitset the represents which properties from
// LayerAnimationInfo::sRecords are present in |aPropertySet|.
auto compositorPropertiesInSet =
[](nsCSSPropertyIDSet& aPropertySet) ->
std::bitset<LayerAnimationInfo::kRecords> {
std::bitset<LayerAnimationInfo::kRecords> result;
for (size_t i = 0; i < LayerAnimationInfo::kRecords; i++) {
if (aPropertySet.HasProperty(
LayerAnimationInfo::sRecords[i].mProperty)) {
result.set(i);
}
}
return result;
};
nsCSSPropertyIDSet& propertiesWithImportantRules =
aEffectSet.PropertiesWithImportantRules();
nsCSSPropertyIDSet& propertiesForAnimationsLevel =
aEffectSet.PropertiesForAnimationsLevel();
static constexpr nsCSSPropertyIDSet compositorAnimatables =
nsCSSPropertyIDSet::CompositorAnimatables();
// Record which compositor-animatable properties were originally set so we can
// compare for changes later.
std::bitset<LayerAnimationInfo::kRecords>
prevCompositorPropertiesWithImportantRules =
compositorPropertiesInSet(propertiesWithImportantRules);
nsCSSPropertyIDSet prevCompositorPropertiesWithImportantRules =
propertiesWithImportantRules.Intersect(compositorAnimatables);
nsCSSPropertyIDSet prevPropertiesForAnimationsLevel =
propertiesForAnimationsLevel;
@ -732,8 +719,8 @@ EffectCompositor::UpdateCascadeResults(EffectSet& aEffectSet,
// released from being overridden by !important rules, we need to update
// layers for animations level because it's a trigger to send animations to
// the compositor or pull animations back from the compositor.
if (prevCompositorPropertiesWithImportantRules !=
compositorPropertiesInSet(propertiesWithImportantRules)) {
if (!prevCompositorPropertiesWithImportantRules.Equals(
propertiesWithImportantRules.Intersect(compositorAnimatables))) {
presContext->EffectCompositor()->
RequestRestyle(aElement, aPseudoType,
EffectCompositor::RestyleType::Layer,
@ -750,7 +737,7 @@ EffectCompositor::UpdateCascadeResults(EffectSet& aEffectSet,
changedPropertiesForAnimationLevel);
if (!commonProperties.IsEmpty()) {
EffectCompositor::RestyleType restyleType =
compositorPropertiesInSet(changedPropertiesForAnimationLevel).none()
changedPropertiesForAnimationLevel.Intersects(compositorAnimatables)
? EffectCompositor::RestyleType::Standard
: EffectCompositor::RestyleType::Layer;
presContext->EffectCompositor()->

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

@ -1242,29 +1242,33 @@ KeyframeEffect::CanThrottle() const
return true;
}
// First we need to check layer generation and transform overflow
// prior to the property.mIsRunningOnCompositor check because we should
// occasionally unthrottle these animations even if the animations are
// already running on compositor.
for (const LayerAnimationInfo::Record& record :
LayerAnimationInfo::sRecords) {
// Skip properties that are overridden by !important rules.
// (GetEffectiveAnimationOfProperty, as called by
// HasEffectiveAnimationOfProperty, only returns a property which is
// neither overridden by !important rules nor overridden by other
// animation.)
if (!HasEffectiveAnimationOfProperty(record.mProperty)) {
continue;
EffectSet* effectSet = nullptr;
for (const AnimationProperty& property : mProperties) {
if (!property.mIsRunningOnCompositor) {
return false;
}
EffectSet* effectSet = EffectSet::GetEffectSet(mTarget->mElement,
mTarget->mPseudoType);
MOZ_ASSERT(effectSet, "CanThrottle should be called on an effect "
"associated with a target element");
MOZ_ASSERT(nsCSSPropertyIDSet::CompositorAnimatables()
.HasProperty(property.mProperty),
"The property should be able to run on the compositor");
MOZ_ASSERT(HasEffectiveAnimationOfProperty(property.mProperty),
"There should be an effective animation of the property while "
"it is marked as being run on the compositor");
if (!effectSet) {
effectSet = EffectSet::GetEffectSet(mTarget->mElement,
mTarget->mPseudoType);
MOZ_ASSERT(effectSet, "CanThrottle should be called on an effect "
"associated with a target element");
}
DisplayItemType displayItemType =
LayerAnimationInfo::GetDisplayItemTypeForProperty(property.mProperty);
// Note that AnimationInfo::GetGenarationFromFrame() is supposed to work
// with the primary frame instead of the style frame.
Maybe<uint64_t> generation = layers::AnimationInfo::GetGenerationFromFrame(
GetPrimaryFrame(), record.mLayerType);
GetPrimaryFrame(), displayItemType);
// Unthrottle if the animation needs to be brought up to date
if (!generation || effectSet->GetAnimationGeneration() != *generation) {
return false;
@ -1278,12 +1282,6 @@ KeyframeEffect::CanThrottle() const
}
}
for (const AnimationProperty& property : mProperties) {
if (!property.mIsRunningOnCompositor) {
return false;
}
}
return true;
}

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

@ -30,7 +30,8 @@ class ContentBlockingLog final
// Each element is a tuple of (type, blocked, repeatCount). The type values
// come from the blocking types defined in nsIWebProgressListener.
typedef nsTArray<LogEntry> OriginLog;
typedef nsClassHashtable<nsStringHashKey, OriginLog> OriginLogHashTable;
typedef Pair<bool, OriginLog> OriginData;
typedef nsClassHashtable<nsStringHashKey, OriginData> OriginDataHashTable;
struct StringWriteFunc : public JSONWriteFunc
{
@ -56,9 +57,14 @@ public:
}
auto entry = mLog.LookupForAdd(aOrigin);
if (entry) {
auto& log = entry.Data();
if (!log->IsEmpty()) {
auto& last = log->LastElement();
auto& data = entry.Data();
if (aType == nsIWebProgressListener::STATE_LOADED_TRACKING_CONTENT) {
data->first() = aBlocked;
return;
}
auto& log = data->second();
if (!log.IsEmpty()) {
auto& last = log.LastElement();
if (last.mType == aType &&
last.mBlocked == aBlocked) {
++last.mRepeatCount;
@ -66,17 +72,21 @@ public:
return;
}
}
if (log->Length() ==
if (log.Length() ==
std::max(1u, StaticPrefs::browser_contentblocking_originlog_length())) {
// Cap the size at the maximum length adjustable by the pref
log->RemoveElementAt(0);
log.RemoveElementAt(0);
}
log->AppendElement(LogEntry{aType, 1u, aBlocked});
log.AppendElement(LogEntry{aType, 1u, aBlocked});
} else {
entry.OrInsert([=] {
auto log(MakeUnique<OriginLog>());
log->AppendElement(LogEntry{aType, 1u, aBlocked});
return log.release();
nsAutoPtr<OriginData> data(new OriginData(false, OriginLog()));
if (aType == nsIWebProgressListener::STATE_LOADED_TRACKING_CONTENT) {
data->first() = true;
} else {
data->second().AppendElement(LogEntry{aType, 1u, aBlocked});
}
return data.forget();
});
}
}
@ -96,7 +106,17 @@ public:
}
w.StartArrayProperty(NS_ConvertUTF16toUTF8(iter.Key()).get(), w.SingleLineStyle);
for (auto& item: *iter.UserData()) {
auto& data = *iter.UserData();
if (data.first()) {
w.StartArrayElement(w.SingleLineStyle);
{
w.IntElement(nsIWebProgressListener::STATE_LOADED_TRACKING_CONTENT);
w.BoolElement(true); // blocked
w.IntElement(1); // repeat count
}
w.EndArray();
}
for (auto& item: data.second()) {
w.StartArrayElement(w.SingleLineStyle);
{
w.IntElement(item.mType);
@ -120,10 +140,16 @@ public:
continue;
}
for (auto& item: *iter.UserData()) {
if ((item.mType & aType) != 0) {
if (aType == nsIWebProgressListener::STATE_LOADED_TRACKING_CONTENT) {
if (iter.UserData()->first()) {
return true;
}
} else {
for (auto& item: iter.UserData()->second()) {
if ((item.mType & aType) != 0) {
return true;
}
}
}
}
return false;
@ -136,17 +162,17 @@ public:
// Now add the sizes of each origin log queue.
// The const_cast is needed because the nsTHashtable::Iterator interface is
// not const-safe. :-(
for (auto iter = const_cast<OriginLogHashTable&>(mLog).Iter();
for (auto iter = const_cast<OriginDataHashTable&>(mLog).Iter();
!iter.Done(); iter.Next()) {
if (iter.UserData()) {
aSizes.mDOMOtherSize +=
iter.UserData()->ShallowSizeOfIncludingThis(aSizes.mState.mMallocSizeOf);
iter.UserData()->second().ShallowSizeOfIncludingThis(aSizes.mState.mMallocSizeOf);
}
}
}
private:
OriginLogHashTable mLog;
OriginDataHashTable mLog;
};
} // namespace dom

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

@ -102,14 +102,16 @@ void
nsDOMNavigationTiming::NotifyUnloadEventStart()
{
mUnloadStart = TimeStamp::Now();
PROFILER_TRACING("Navigation", "Unload", TRACING_INTERVAL_START);
PROFILER_TRACING_DOCSHELL(
"Navigation", "Unload", TRACING_INTERVAL_START, mDocShell);
}
void
nsDOMNavigationTiming::NotifyUnloadEventEnd()
{
mUnloadEnd = TimeStamp::Now();
PROFILER_TRACING("Navigation", "Unload", TRACING_INTERVAL_END);
PROFILER_TRACING_DOCSHELL(
"Navigation", "Unload", TRACING_INTERVAL_END, mDocShell);
}
void
@ -120,7 +122,8 @@ nsDOMNavigationTiming::NotifyLoadEventStart()
}
mLoadEventStart = TimeStamp::Now();
PROFILER_TRACING("Navigation", "Load", TRACING_INTERVAL_START);
PROFILER_TRACING_DOCSHELL(
"Navigation", "Load", TRACING_INTERVAL_START, mDocShell);
if (IsTopLevelContentDocumentInContentProcess()) {
TimeStamp now = TimeStamp::Now();
@ -151,7 +154,8 @@ nsDOMNavigationTiming::NotifyLoadEventEnd()
}
mLoadEventEnd = TimeStamp::Now();
PROFILER_TRACING("Navigation", "Load", TRACING_INTERVAL_END);
PROFILER_TRACING_DOCSHELL(
"Navigation", "Load", TRACING_INTERVAL_END, mDocShell);
if (IsTopLevelContentDocumentInContentProcess()) {
Telemetry::AccumulateTimeDelta(Telemetry::TIME_TO_LOAD_EVENT_END_MS,
@ -215,7 +219,8 @@ nsDOMNavigationTiming::NotifyDOMContentLoadedStart(nsIURI* aURI)
mLoadedURI = aURI;
mDOMContentLoadedEventStart = TimeStamp::Now();
PROFILER_TRACING("Navigation", "DOMContentLoaded", TRACING_INTERVAL_START);
PROFILER_TRACING_DOCSHELL(
"Navigation", "DOMContentLoaded", TRACING_INTERVAL_START, mDocShell);
if (IsTopLevelContentDocumentInContentProcess()) {
TimeStamp now = TimeStamp::Now();
@ -248,7 +253,8 @@ nsDOMNavigationTiming::NotifyDOMContentLoadedEnd(nsIURI* aURI)
mLoadedURI = aURI;
mDOMContentLoadedEventEnd = TimeStamp::Now();
PROFILER_TRACING("Navigation", "DOMContentLoaded", TRACING_INTERVAL_END);
PROFILER_TRACING_DOCSHELL(
"Navigation", "DOMContentLoaded", TRACING_INTERVAL_END, mDocShell);
if (IsTopLevelContentDocumentInContentProcess()) {
Telemetry::AccumulateTimeDelta(Telemetry::TIME_TO_DOM_CONTENT_LOADED_END_MS,
@ -356,8 +362,12 @@ nsDOMNavigationTiming::TTITimeout(nsITimer* aTimer)
int(elapsed.ToMilliseconds()),
int(elapsedLongTask.ToMilliseconds()),spec.get());
DECLARE_DOCSHELL_AND_HISTORY_ID(mDocShell);
profiler_add_marker(
"TTI", MakeUnique<UserTimingMarkerPayload>(NS_ConvertASCIItoUTF16(marker), mTTFI));
"TTI", MakeUnique<UserTimingMarkerPayload>(NS_ConvertASCIItoUTF16(marker),
mTTFI,
docShellId,
docShellHistoryId));
}
#endif
return;

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

@ -259,6 +259,7 @@
#include "mozilla/dom/TabGroup.h"
#ifdef MOZ_XUL
#include "mozilla/dom/XULBroadcastManager.h"
#include "mozilla/dom/XULPersist.h"
#include "mozilla/dom/TreeBoxObject.h"
#include "nsIXULWindow.h"
#include "nsXULCommandDispatcher.h"
@ -1737,6 +1738,10 @@ nsDocument::~nsDocument()
mXULBroadcastManager->DropDocumentReference();
}
if (mXULPersist) {
mXULPersist->DropDocumentReference();
}
delete mHeaderData;
ClearAllBoxObjects();
@ -8972,6 +8977,13 @@ nsIDocument::SetReadyStateInternal(ReadyState rs)
}
if (READYSTATE_INTERACTIVE == rs) {
if (nsContentUtils::IsSystemPrincipal(NodePrincipal())) {
Element* root = GetRootElement();
if (root && root->HasAttr(kNameSpaceID_None, nsGkAtoms::mozpersist)) {
mXULPersist = new XULPersist(this);
mXULPersist->Init();
}
}
TriggerInitialDocumentTranslation();
}

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

@ -562,6 +562,7 @@ SetTreeOwnerAndChromeEventHandlerOnDocshellTree(nsIDocShellTreeItem* aItem,
}
}
#if defined(MOZ_DIAGNOSTIC_ASSERT_ENABLED)
static bool
CheckDocShellType(mozilla::dom::Element* aOwnerContent,
nsIDocShellTreeItem* aDocShell,
@ -586,6 +587,7 @@ CheckDocShellType(mozilla::dom::Element* aOwnerContent,
return parent && parent->ItemType() == aDocShell->ItemType();
}
#endif // defined(MOZ_DIAGNOSTIC_ASSERT_ENABLED)
/**
* Hook up a given TreeItem to its tree owner. aItem's type must have already

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

@ -149,6 +149,7 @@ class AnonymousContent;
class Attr;
class BoxObject;
class XULBroadcastManager;
class XULPersist;
class ClientInfo;
class ClientState;
class CDATASection;
@ -4756,6 +4757,7 @@ protected:
nsCOMPtr<nsIDOMXULCommandDispatcher> mCommandDispatcher; // [OWNER] of the focus tracker
RefPtr<mozilla::dom::XULBroadcastManager> mXULBroadcastManager;
RefPtr<mozilla::dom::XULPersist> mXULPersist;
// At the moment, trackers might be blocked by Tracking Protection or FastBlock.
// In order to know the numbers of trackers detected and blocked, we add

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

@ -1612,7 +1612,10 @@ nsObjectLoadingContent::UpdateObjectParameters()
thisElement->GetAttr(kNameSpaceID_None, nsGkAtoms::type, rawTypeAttr);
if (!rawTypeAttr.IsEmpty()) {
typeAttr = rawTypeAttr;
CopyUTF16toUTF8(rawTypeAttr, newMime);
nsAutoString params;
nsAutoString mime;
nsContentUtils::SplitMimeType(rawTypeAttr, mime, params);
CopyUTF16toUTF8(mime, newMime);
}
// If we failed to build a valid URI, use the document's base URI

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

@ -237,6 +237,7 @@ support-files =
PASS.html
FAIL.html
!/dom/events/test/event_leak_utils.js
../../../browser/extensions/pdfjs/test/file_pdfjs_test.pdf
[test_anchor_area_referrer.html]
[test_anchor_area_referrer_changing.html]
@ -617,6 +618,8 @@ skip-if = toolkit == 'android'
[test_bug1453693.html]
skip-if = os == "mac"
[test_bug1472427.html]
[test_bug1499169.html]
skip-if = toolkit == 'android' # Timeouts on android due to page closing issues with embedded pdf
[test_caretPositionFromPoint.html]
[test_change_policy.html]
[test_clearTimeoutIntervalNoArg.html]

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

@ -0,0 +1,32 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=1499139
-->
<head>
<meta charset="utf-8">
<title>Test for Bug 1499169</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/SpecialPowers.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="application/javascript">
SimpleTest.waitForExplicitFinish();
function test() {
const OBJLC = SpecialPowers.Ci.nsIObjectLoadingContent;
let obj = document.getElementById("pdftest");
obj instanceof OBJLC;
obj = SpecialPowers.wrap(obj);
// Make sure we've set our type correctly even though the mime type isn't quite as expected.
ok(obj.displayedType == OBJLC.TYPE_DOCUMENT, "expected document type");
SimpleTest.finish();
}
</script>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1499169">Mozilla Bug 1499169</a>
<object id="pdftest" onload="test()" data="file_pdfjs_test.pdf" type="application/pdf;charset=UTF-8" width="90%" height="600"></object>
</body>
</html>

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

@ -6,6 +6,7 @@
#include "nsPresContext.h"
#include "nsContentUtils.h"
#include "nsDocShell.h"
#include "nsError.h"
#include <new>
#include "nsIContent.h"
@ -1134,12 +1135,17 @@ EventDispatcher::Dispatch(nsISupports* aTarget,
AUTO_PROFILER_LABEL_DYNAMIC_LOSSY_NSSTRING(
"EventDispatcher::Dispatch", OTHER, typeStr);
nsCOMPtr<nsIDocShell> docShell;
docShell = nsContentUtils::GetDocShellForEventTarget(aEvent->mTarget);
DECLARE_DOCSHELL_AND_HISTORY_ID(docShell);
profiler_add_marker(
"DOMEvent",
MakeUnique<DOMEventMarkerPayload>(typeStr,
aEvent->mTimeStamp,
"DOMEvent",
TRACING_INTERVAL_START));
TRACING_INTERVAL_START,
docShellId,
docShellHistoryId));
EventTargetChainItem::HandleEventTargetChain(chain, postVisitor,
aCallback, cd);
@ -1149,7 +1155,9 @@ EventDispatcher::Dispatch(nsISupports* aTarget,
MakeUnique<DOMEventMarkerPayload>(typeStr,
aEvent->mTimeStamp,
"DOMEvent",
TRACING_INTERVAL_END));
TRACING_INTERVAL_END,
docShellId,
docShellHistoryId));
} else
#endif
{

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

@ -2991,7 +2991,7 @@ ContentChild::StartForceKillTimer()
return;
}
int32_t timeoutSecs = Preferences::GetInt("dom.ipc.tabs.shutdownTimeoutSecs", 5);
int32_t timeoutSecs = StaticPrefs::dom_ipc_tabs_shutdownTimeoutSecs();
if (timeoutSecs > 0) {
NS_NewTimerWithFuncCallback(getter_AddRefs(mForceKillTimer),
ContentChild::ForceKillTimerCallback,

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

@ -1933,7 +1933,7 @@ ContentParent::StartForceKillTimer()
return;
}
int32_t timeoutSecs = Preferences::GetInt("dom.ipc.tabs.shutdownTimeoutSecs", 5);
int32_t timeoutSecs = StaticPrefs::dom_ipc_tabs_shutdownTimeoutSecs();
if (timeoutSecs > 0) {
NS_NewTimerWithFuncCallback(getter_AddRefs(mForceKillTimer),
ContentParent::ForceKillTimerCallback,

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

@ -154,13 +154,13 @@ OpusDataDecoder::DecodeHeader(const unsigned char* aData, size_t aLength)
AutoTArray<uint8_t, 8> map;
map.SetLength(channels);
if (vorbisLayout.MappingTable(smpteLayout, &map)) {
if (mOpusParser->mChannelMapping == 1 &&
vorbisLayout.MappingTable(smpteLayout, &map)) {
for (int i = 0; i < channels; i++) {
mMappingTable[i] = mOpusParser->mMappingTable[map[i]];
}
} else {
// Should never get here as vorbis layout is always convertible to SMPTE
// default layout.
// Use Opus set channel mapping and return channels as-is.
PodCopy(mMappingTable.Elements(), mOpusParser->mMappingTable, channels);
}
} else {

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

@ -7,6 +7,7 @@
#include "Performance.h"
#include "GeckoProfiler.h"
#include "nsIDocShell.h"
#include "nsRFPService.h"
#include "PerformanceEntry.h"
#include "PerformanceMainThread.h"
@ -249,9 +250,14 @@ Performance::Mark(const nsAString& aName, ErrorResult& aRv)
#ifdef MOZ_GECKO_PROFILER
if (profiler_is_active()) {
nsCOMPtr<EventTarget> et = do_QueryInterface(GetOwner());
nsCOMPtr<nsIDocShell> docShell =
nsContentUtils::GetDocShellForEventTarget(et);
DECLARE_DOCSHELL_AND_HISTORY_ID(docShell);
profiler_add_marker(
"UserTiming",
MakeUnique<UserTimingMarkerPayload>(aName, TimeStamp::Now()));
MakeUnique<UserTimingMarkerPayload>(
aName, TimeStamp::Now(), docShellId, docShellHistoryId));
}
#endif
}
@ -347,10 +353,18 @@ Performance::Measure(const nsAString& aName,
endMark.emplace(aEndMark.Value());
}
profiler_add_marker(
"UserTiming",
MakeUnique<UserTimingMarkerPayload>(aName, startMark, endMark,
startTimeStamp, endTimeStamp));
nsCOMPtr<EventTarget> et = do_QueryInterface(GetOwner());
nsCOMPtr<nsIDocShell> docShell =
nsContentUtils::GetDocShellForEventTarget(et);
DECLARE_DOCSHELL_AND_HISTORY_ID(docShell);
profiler_add_marker("UserTiming",
MakeUnique<UserTimingMarkerPayload>(aName,
startMark,
endMark,
startTimeStamp,
endTimeStamp,
docShellId,
docShellHistoryId));
}
#endif
}

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

@ -82,6 +82,7 @@
#include "mozilla/dom/ProcessingInstruction.h"
#include "mozilla/dom/ScriptSettings.h"
#include "mozilla/dom/XULDocumentBinding.h"
#include "mozilla/dom/XULPersist.h"
#include "mozilla/EventDispatcher.h"
#include "mozilla/LoadInfo.h"
#include "mozilla/Preferences.h"
@ -127,7 +128,6 @@ namespace dom {
XULDocument::XULDocument(void)
: XMLDocument("application/vnd.mozilla.xul+xml"),
mNextSrcLoadWaiter(nullptr),
mApplyingPersistedAttrs(false),
mIsWritingFastLoad(false),
mDocumentLoaded(false),
mStillWalking(false),
@ -201,12 +201,10 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(XULDocument, XMLDocument)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCurrentPrototype)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPrototypes)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLocalStore)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(XULDocument, XMLDocument)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mLocalStore)
//XXX We should probably unlink all the objects we traverse.
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
@ -423,58 +421,6 @@ XULDocument::OnPrototypeLoadDone(bool aResumeWalk)
return rv;
}
static bool
ShouldPersistAttribute(Element* aElement, nsAtom* aAttribute)
{
if (aElement->IsXULElement(nsGkAtoms::window)) {
// This is not an element of the top document, its owner is
// not an nsXULWindow. Persist it.
if (aElement->OwnerDoc()->GetParentDocument()) {
return true;
}
// The following attributes of xul:window should be handled in
// nsXULWindow::SavePersistentAttributes instead of here.
if (aAttribute == nsGkAtoms::screenX ||
aAttribute == nsGkAtoms::screenY ||
aAttribute == nsGkAtoms::width ||
aAttribute == nsGkAtoms::height ||
aAttribute == nsGkAtoms::sizemode) {
return false;
}
}
return true;
}
void
XULDocument::AttributeChanged(Element* aElement, int32_t aNameSpaceID,
nsAtom* aAttribute, int32_t aModType,
const nsAttrValue* aOldValue)
{
NS_ASSERTION(aElement->OwnerDoc() == this, "unexpected doc");
// Might not need this, but be safe for now.
nsCOMPtr<nsIMutationObserver> kungFuDeathGrip(this);
// See if there is anything we need to persist in the localstore.
//
// XXX Namespace handling broken :-(
nsAutoString persist;
aElement->GetAttr(kNameSpaceID_None, nsGkAtoms::persist, persist);
// Persistence of attributes of xul:window is handled in nsXULWindow.
if (ShouldPersistAttribute(aElement, aAttribute) && !persist.IsEmpty() &&
// XXXldb This should check that it's a token, not just a substring.
persist.Find(nsDependentAtomString(aAttribute)) >= 0) {
nsContentUtils::AddScriptRunner(
NewRunnableMethod<Element*, int32_t, nsAtom*>(
"dom::XULDocument::Persist",
this,
&XULDocument::Persist,
aElement,
kNameSpaceID_None,
aAttribute));
}
}
void
XULDocument::ContentAppended(nsIContent* aFirstNewContent)
{
@ -513,58 +459,6 @@ XULDocument::ContentRemoved(nsIContent* aChild, nsIContent* aPreviousSibling)
// nsIDocument interface
//
void
XULDocument::Persist(Element* aElement, int32_t aNameSpaceID,
nsAtom* aAttribute)
{
// For non-chrome documents, persistance is simply broken
if (!nsContentUtils::IsSystemPrincipal(NodePrincipal()))
return;
if (!mLocalStore) {
mLocalStore = do_GetService("@mozilla.org/xul/xulstore;1");
if (NS_WARN_IF(!mLocalStore)) {
return;
}
}
nsAutoString id;
aElement->GetAttr(kNameSpaceID_None, nsGkAtoms::id, id);
nsAtomString attrstr(aAttribute);
nsAutoString valuestr;
aElement->GetAttr(kNameSpaceID_None, aAttribute, valuestr);
nsAutoCString utf8uri;
nsresult rv = mDocumentURI->GetSpec(utf8uri);
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
NS_ConvertUTF8toUTF16 uri(utf8uri);
bool hasAttr;
rv = mLocalStore->HasValue(uri, id, attrstr, &hasAttr);
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
if (hasAttr && valuestr.IsEmpty()) {
mLocalStore->RemoveValue(uri, id, attrstr);
return;
}
// Persisting attributes to top level windows is handled by nsXULWindow.
if (aElement->IsXULElement(nsGkAtoms::window)) {
if (nsCOMPtr<nsIXULWindow> win = GetXULWindowIfToplevelChrome()) {
return;
}
}
mLocalStore->SetValue(uri, id, attrstr, valuestr);
}
void
XULDocument::AddElementToDocumentPost(Element* aElement)
{
@ -721,145 +615,6 @@ XULDocument::PrepareToLoadPrototype(nsIURI* aURI, const char* aCommand,
}
nsresult
XULDocument::ApplyPersistentAttributes()
{
// For non-chrome documents, persistance is simply broken
if (!nsContentUtils::IsSystemPrincipal(NodePrincipal()))
return NS_ERROR_NOT_AVAILABLE;
// Add all of the 'persisted' attributes into the content
// model.
if (!mLocalStore) {
mLocalStore = do_GetService("@mozilla.org/xul/xulstore;1");
if (NS_WARN_IF(!mLocalStore)) {
return NS_ERROR_NOT_INITIALIZED;
}
}
mApplyingPersistedAttrs = true;
ApplyPersistentAttributesInternal();
mApplyingPersistedAttrs = false;
return NS_OK;
}
nsresult
XULDocument::ApplyPersistentAttributesInternal()
{
nsCOMArray<Element> elements;
nsAutoCString utf8uri;
nsresult rv = mDocumentURI->GetSpec(utf8uri);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
NS_ConvertUTF8toUTF16 uri(utf8uri);
// Get a list of element IDs for which persisted values are available
nsCOMPtr<nsIStringEnumerator> ids;
rv = mLocalStore->GetIDsEnumerator(uri, getter_AddRefs(ids));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
while (1) {
bool hasmore = false;
ids->HasMore(&hasmore);
if (!hasmore) {
break;
}
nsAutoString id;
ids->GetNext(id);
nsIdentifierMapEntry* entry = mIdentifierMap.GetEntry(id);
if (!entry) {
continue;
}
// We want to hold strong refs to the elements while applying
// persistent attributes, just in case.
elements.Clear();
elements.SetCapacity(entry->GetIdElements().Length());
for (Element* element : entry->GetIdElements()) {
elements.AppendObject(element);
}
if (elements.IsEmpty()) {
continue;
}
rv = ApplyPersistentAttributesToElements(id, elements);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
}
return NS_OK;
}
nsresult
XULDocument::ApplyPersistentAttributesToElements(const nsAString &aID,
nsCOMArray<Element>& aElements)
{
nsAutoCString utf8uri;
nsresult rv = mDocumentURI->GetSpec(utf8uri);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
NS_ConvertUTF8toUTF16 uri(utf8uri);
// Get a list of attributes for which persisted values are available
nsCOMPtr<nsIStringEnumerator> attrs;
rv = mLocalStore->GetAttributeEnumerator(uri, aID, getter_AddRefs(attrs));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
while (1) {
bool hasmore = PR_FALSE;
attrs->HasMore(&hasmore);
if (!hasmore) {
break;
}
nsAutoString attrstr;
attrs->GetNext(attrstr);
nsAutoString value;
rv = mLocalStore->GetValue(uri, aID, attrstr, value);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
RefPtr<nsAtom> attr = NS_Atomize(attrstr);
if (NS_WARN_IF(!attr)) {
return NS_ERROR_OUT_OF_MEMORY;
}
uint32_t cnt = aElements.Count();
for (int32_t i = int32_t(cnt) - 1; i >= 0; --i) {
RefPtr<Element> element = aElements.SafeObjectAt(i);
if (!element) {
continue;
}
// Applying persistent attributes to top level windows is handled
// by nsXULWindow.
if (element->IsXULElement(nsGkAtoms::window)) {
if (nsCOMPtr<nsIXULWindow> win = GetXULWindowIfToplevelChrome()) {
continue;
}
}
Unused << element->SetAttr(kNameSpaceID_None, attr, value, true);
}
}
return NS_OK;
}
void
XULDocument::TraceProtos(JSTracer* aTrc)
{
@ -1282,7 +1037,8 @@ XULDocument::ResumeWalk()
// If we get here, there is nothing left for us to walk. The content
// model is built and ready for layout.
ApplyPersistentAttributes();
mXULPersist = new XULPersist(this);
mXULPersist->Init();
mStillWalking = false;
if (mPendingSheets == 0) {

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

@ -19,7 +19,6 @@
#include "nsIStreamListener.h"
#include "nsIStreamLoader.h"
#include "nsICSSLoaderObserver.h"
#include "nsIXULStore.h"
#include "mozilla/Attributes.h"
#include "mozilla/dom/ScriptLoader.h"
@ -83,7 +82,6 @@ public:
NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED
/**
* Notify the XUL document that a subtree has been added
@ -146,11 +144,6 @@ protected:
nsIPrincipal* aDocumentPrincipal,
nsIParser** aResult);
nsresult ApplyPersistentAttributes();
nsresult ApplyPersistentAttributesInternal();
nsresult ApplyPersistentAttributesToElements(const nsAString &aID,
nsCOMArray<Element>& aElements);
void AddElementToDocumentPost(Element* aElement);
static void DirectionChanged(const char* aPrefName, XULDocument* aData);
@ -160,11 +153,6 @@ protected:
static LazyLogModule gXULLog;
void
Persist(mozilla::dom::Element* aElement,
int32_t aNameSpaceID,
nsAtom* aAttribute);
virtual JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override;
// IMPORTANT: The ownership implicit in the following member
@ -177,8 +165,6 @@ protected:
XULDocument* mNextSrcLoadWaiter; // [OWNER] but not COMPtr
nsCOMPtr<nsIXULStore> mLocalStore;
bool mApplyingPersistedAttrs;
bool mIsWritingFastLoad;
bool mDocumentLoaded;
/**

285
dom/xul/XULPersist.cpp Normal file
Просмотреть файл

@ -0,0 +1,285 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
#include "XULPersist.h"
#include "nsIXULStore.h"
namespace mozilla {
namespace dom {
static bool
ShouldPersistAttribute(Element* aElement, nsAtom* aAttribute)
{
if (aElement->IsXULElement(nsGkAtoms::window)) {
// This is not an element of the top document, its owner is
// not an nsXULWindow. Persist it.
if (aElement->OwnerDoc()->GetParentDocument()) {
return true;
}
// The following attributes of xul:window should be handled in
// nsXULWindow::SavePersistentAttributes instead of here.
if (aAttribute == nsGkAtoms::screenX ||
aAttribute == nsGkAtoms::screenY ||
aAttribute == nsGkAtoms::width ||
aAttribute == nsGkAtoms::height ||
aAttribute == nsGkAtoms::sizemode) {
return false;
}
}
return true;
}
NS_IMPL_ISUPPORTS(XULPersist, nsIDocumentObserver)
XULPersist::XULPersist(nsIDocument* aDocument)
: nsStubDocumentObserver(),
mDocument(aDocument)
{
}
XULPersist::~XULPersist()
{
}
void
XULPersist::Init()
{
ApplyPersistentAttributes();
mDocument->AddObserver(this);
}
void
XULPersist::DropDocumentReference()
{
mDocument->RemoveObserver(this);
mDocument = nullptr;
}
void
XULPersist::AttributeChanged(dom::Element* aElement,
int32_t aNameSpaceID,
nsAtom* aAttribute,
int32_t aModType,
const nsAttrValue* aOldValue)
{
NS_ASSERTION(aElement->OwnerDoc() == mDocument, "unexpected doc");
// Might not need this, but be safe for now.
nsCOMPtr<nsIDocumentObserver> kungFuDeathGrip(this);
// See if there is anything we need to persist in the localstore.
//
// XXX Namespace handling broken :-(
nsAutoString persist;
aElement->GetAttr(kNameSpaceID_None, nsGkAtoms::persist, persist);
// Persistence of attributes of xul:window is handled in nsXULWindow.
if (ShouldPersistAttribute(aElement, aAttribute) && !persist.IsEmpty() &&
// XXXldb This should check that it's a token, not just a substring.
persist.Find(nsDependentAtomString(aAttribute)) >= 0) {
nsContentUtils::AddScriptRunner(
NewRunnableMethod<Element*, int32_t, nsAtom*>(
"dom::XULPersist::Persist",
this,
&XULPersist::Persist,
aElement,
kNameSpaceID_None,
aAttribute));
}
}
void
XULPersist::Persist(Element* aElement, int32_t aNameSpaceID, nsAtom* aAttribute)
{
if (!mDocument) {
return;
}
// For non-chrome documents, persistance is simply broken
if (!nsContentUtils::IsSystemPrincipal(mDocument->NodePrincipal())) {
return;
}
if (!mLocalStore) {
mLocalStore = do_GetService("@mozilla.org/xul/xulstore;1");
if (NS_WARN_IF(!mLocalStore)) {
return;
}
}
nsAutoString id;
aElement->GetAttr(kNameSpaceID_None, nsGkAtoms::id, id);
nsAtomString attrstr(aAttribute);
nsAutoString valuestr;
aElement->GetAttr(kNameSpaceID_None, aAttribute, valuestr);
nsAutoCString utf8uri;
nsresult rv = mDocument->GetDocumentURI()->GetSpec(utf8uri);
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
NS_ConvertUTF8toUTF16 uri(utf8uri);
bool hasAttr;
rv = mLocalStore->HasValue(uri, id, attrstr, &hasAttr);
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
if (hasAttr && valuestr.IsEmpty()) {
mLocalStore->RemoveValue(uri, id, attrstr);
return;
}
// Persisting attributes to top level windows is handled by nsXULWindow.
if (aElement->IsXULElement(nsGkAtoms::window)) {
if (nsCOMPtr<nsIXULWindow> win = mDocument->GetXULWindowIfToplevelChrome()) {
return;
}
}
mLocalStore->SetValue(uri, id, attrstr, valuestr);
}
nsresult
XULPersist::ApplyPersistentAttributes()
{
if (!mDocument) {
return NS_ERROR_NOT_AVAILABLE;
}
// For non-chrome documents, persistance is simply broken
if (!nsContentUtils::IsSystemPrincipal(mDocument->NodePrincipal())) {
return NS_ERROR_NOT_AVAILABLE;
}
// Add all of the 'persisted' attributes into the content
// model.
if (!mLocalStore) {
mLocalStore = do_GetService("@mozilla.org/xul/xulstore;1");
if (NS_WARN_IF(!mLocalStore)) {
return NS_ERROR_NOT_INITIALIZED;
}
}
ApplyPersistentAttributesInternal();
return NS_OK;
}
nsresult
XULPersist::ApplyPersistentAttributesInternal()
{
nsCOMArray<Element> elements;
nsAutoCString utf8uri;
nsresult rv = mDocument->GetDocumentURI()->GetSpec(utf8uri);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
NS_ConvertUTF8toUTF16 uri(utf8uri);
// Get a list of element IDs for which persisted values are available
nsCOMPtr<nsIStringEnumerator> ids;
rv = mLocalStore->GetIDsEnumerator(uri, getter_AddRefs(ids));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
while (1) {
bool hasmore = false;
ids->HasMore(&hasmore);
if (!hasmore) {
break;
}
nsAutoString id;
ids->GetNext(id);
// We want to hold strong refs to the elements while applying
// persistent attributes, just in case.
const nsTArray<Element*>* allElements = mDocument->GetAllElementsForId(id);
if (!allElements) {
continue;
}
elements.Clear();
elements.SetCapacity(allElements->Length());
for (Element* element : *allElements) {
elements.AppendObject(element);
}
rv = ApplyPersistentAttributesToElements(id, elements);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
}
return NS_OK;
}
nsresult
XULPersist::ApplyPersistentAttributesToElements(const nsAString &aID,
nsCOMArray<Element>& aElements)
{
nsAutoCString utf8uri;
nsresult rv = mDocument->GetDocumentURI()->GetSpec(utf8uri);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
NS_ConvertUTF8toUTF16 uri(utf8uri);
// Get a list of attributes for which persisted values are available
nsCOMPtr<nsIStringEnumerator> attrs;
rv = mLocalStore->GetAttributeEnumerator(uri, aID, getter_AddRefs(attrs));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
while (1) {
bool hasmore = PR_FALSE;
attrs->HasMore(&hasmore);
if (!hasmore) {
break;
}
nsAutoString attrstr;
attrs->GetNext(attrstr);
nsAutoString value;
rv = mLocalStore->GetValue(uri, aID, attrstr, value);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
RefPtr<nsAtom> attr = NS_Atomize(attrstr);
if (NS_WARN_IF(!attr)) {
return NS_ERROR_OUT_OF_MEMORY;
}
uint32_t cnt = aElements.Length();
for (int32_t i = int32_t(cnt) - 1; i >= 0; --i) {
Element* element = aElements.SafeElementAt(i);
if (!element) {
continue;
}
// Applying persistent attributes to top level windows is handled
// by nsXULWindow.
if (element->IsXULElement(nsGkAtoms::window)) {
if (nsCOMPtr<nsIXULWindow> win = mDocument->GetXULWindowIfToplevelChrome()) {
continue;
}
}
Unused << element->SetAttr(kNameSpaceID_None, attr, value, true);
}
}
return NS_OK;
}
} // namespace dom
} // namespace mozilla

49
dom/xul/XULPersist.h Normal file
Просмотреть файл

@ -0,0 +1,49 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_XULPersist_h
#define mozilla_dom_XULPersist_h
class nsIXULStore;
namespace mozilla {
namespace dom {
class XULPersist final : public nsStubDocumentObserver
{
public:
NS_DECL_ISUPPORTS
explicit XULPersist(nsIDocument* aDocument);
void Init();
void DropDocumentReference();
NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED
protected:
void Persist(mozilla::dom::Element* aElement,
int32_t aNameSpaceID,
nsAtom* aAttribute);
private:
~XULPersist();
nsresult ApplyPersistentAttributes();
nsresult ApplyPersistentAttributesInternal();
nsresult ApplyPersistentAttributesToElements(const nsAString &aID,
nsCOMArray<Element>& aElements);
nsCOMPtr<nsIXULStore> mLocalStore;
// A weak pointer to our document. Nulled out by DropDocumentReference.
nsIDocument* MOZ_NON_OWNING_REF mDocument;
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_XULPersist_h

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше