This commit is contained in:
Carsten "Tomcat" Book 2014-04-25 13:55:53 +02:00
Родитель b0a3171977 21d43e38cc
Коммит a93cb7d802
300 изменённых файлов: 6538 добавлений и 4083 удалений

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

@ -12,7 +12,7 @@
#include "States.h"
#include "mozilla/EventStateManager.h"
#include "mozilla/Selection.h"
#include "mozilla/dom/Selection.h"
using namespace mozilla;
using namespace mozilla::a11y;
@ -127,7 +127,7 @@ AccShowEvent::
////////////////////////////////////////////////////////////////////////////////
AccTextSelChangeEvent::AccTextSelChangeEvent(HyperTextAccessible* aTarget,
Selection* aSelection,
dom::Selection* aSelection,
int32_t aReason) :
AccEvent(nsIAccessibleEvent::EVENT_TEXT_SELECTION_CHANGED, aTarget,
eAutoDetect, eCoalesceTextSelChange),

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

@ -12,7 +12,9 @@
namespace mozilla {
namespace dom {
class Selection;
}
namespace a11y {
@ -367,7 +369,8 @@ private:
class AccTextSelChangeEvent : public AccEvent
{
public:
AccTextSelChangeEvent(HyperTextAccessible* aTarget, Selection* aSelection,
AccTextSelChangeEvent(HyperTextAccessible* aTarget,
dom::Selection* aSelection,
int32_t aReason);
virtual ~AccTextSelChangeEvent();
@ -386,7 +389,7 @@ public:
bool IsCaretMoveOnly() const;
private:
nsRefPtr<Selection> mSel;
nsRefPtr<dom::Selection> mSel;
int32_t mReason;
friend class EventQueue;

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

@ -14,11 +14,12 @@
#include "nsIAccessibleTypes.h"
#include "nsIDOMDocument.h"
#include "nsIPresShell.h"
#include "mozilla/Selection.h"
#include "mozilla/dom/Selection.h"
#include "mozilla/dom/Element.h"
using namespace mozilla;
using namespace mozilla::a11y;
using mozilla::dom::Selection;
struct mozilla::a11y::SelData MOZ_FINAL
{

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

@ -42,7 +42,7 @@ HyperTextAccessible::IsValidRange(int32_t aStartOffset, int32_t aEndOffset)
inline bool
HyperTextAccessible::AddToSelection(int32_t aStartOffset, int32_t aEndOffset)
{
Selection* domSel = DOMSelection();
dom::Selection* domSel = DOMSelection();
return domSel &&
SetSelectionBoundsAt(domSel->GetRangeCount(), aStartOffset, aEndOffset);
}
@ -149,7 +149,7 @@ HyperTextAccessible::FrameSelection() const
return frame ? frame->GetFrameSelection() : nullptr;
}
inline Selection*
inline dom::Selection*
HyperTextAccessible::DOMSelection() const
{
nsRefPtr<nsFrameSelection> frameSelection = FrameSelection();

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

@ -33,7 +33,7 @@
#include "nsTextFragment.h"
#include "mozilla/dom/Element.h"
#include "mozilla/EventStates.h"
#include "mozilla/Selection.h"
#include "mozilla/dom/Selection.h"
#include "mozilla/MathAlgorithms.h"
#include "gfxSkipChars.h"
#include <algorithm>
@ -1117,7 +1117,7 @@ HyperTextAccessible::SetSelectionRange(int32_t aStartPos, int32_t aEndPos)
if (isFocusable)
TakeFocus();
Selection* domSel = DOMSelection();
dom::Selection* domSel = DOMSelection();
NS_ENSURE_STATE(domSel);
// Set up the selection.
@ -1164,7 +1164,7 @@ HyperTextAccessible::CaretOffset() const
// Turn the focus node and offset of the selection into caret hypretext
// offset.
Selection* domSel = DOMSelection();
dom::Selection* domSel = DOMSelection();
NS_ENSURE_TRUE(domSel, -1);
nsINode* focusNode = domSel->GetFocusNode();
@ -1194,7 +1194,7 @@ HyperTextAccessible::CaretLineNumber()
if (!frameSelection)
return -1;
Selection* domSel =
dom::Selection* domSel =
frameSelection->GetSelection(nsISelectionController::SELECTION_NORMAL);
if (!domSel)
return - 1;
@ -1310,7 +1310,7 @@ HyperTextAccessible::GetSelectionDOMRanges(int16_t aType,
frameSelection->GetDisplaySelection() <= nsISelectionController::SELECTION_HIDDEN)
return;
Selection* domSel = frameSelection->GetSelection(aType);
dom::Selection* domSel = frameSelection->GetSelection(aType);
if (!domSel)
return;
@ -1397,7 +1397,7 @@ HyperTextAccessible::SetSelectionBoundsAt(int32_t aSelectionNum,
int32_t startOffset = ConvertMagicOffset(aStartOffset);
int32_t endOffset = ConvertMagicOffset(aEndOffset);
Selection* domSel = DOMSelection();
dom::Selection* domSel = DOMSelection();
if (!domSel)
return false;
@ -1426,7 +1426,7 @@ HyperTextAccessible::SetSelectionBoundsAt(int32_t aSelectionNum,
bool
HyperTextAccessible::RemoveFromSelection(int32_t aSelectionNum)
{
Selection* domSel = DOMSelection();
dom::Selection* domSel = DOMSelection();
if (!domSel)
return false;
@ -1521,7 +1521,7 @@ HyperTextAccessible::SelectionRanges(nsTArray<a11y::TextRange>* aRanges) const
{
NS_ASSERTION(aRanges->Length() != 0, "TextRange array supposed to be empty");
Selection* sel = DOMSelection();
dom::Selection* sel = DOMSelection();
if (!sel)
return;
@ -1848,7 +1848,7 @@ HyperTextAccessible::GetSpellTextAttribute(nsINode* aNode,
if (!fs)
return NS_OK;
Selection* domSel = fs->GetSelection(nsISelectionController::SELECTION_SPELLCHECK);
dom::Selection* domSel = fs->GetSelection(nsISelectionController::SELECTION_SPELLCHECK);
if (!domSel)
return NS_OK;

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

@ -489,7 +489,7 @@ protected:
* Return frame/DOM selection object for the accessible.
*/
already_AddRefed<nsFrameSelection> FrameSelection() const;
Selection* DOMSelection() const;
dom::Selection* DOMSelection() const;
/**
* Return selection ranges within the accessible subtree.

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

@ -1,6 +1,6 @@
[
{"size": 169226356,
"digest": "f9456848fd661b8be05d6a30607fad4787bcecfe676b53f9a4074653fdda6a377c961038c866c5d83355e3afd89f1a3bd947a142aeaf7dd7d81b6c376185badd",
{"size": 156447892,
"digest": "02b2e6bcaff4ccadfd85a75cc1dfb526be7937673ed18b2c6fb7fe2256a725bc778d513e3820d86adaec1636e1771bd0c5663e17bf2d3f1d6b445ff1e0a136f2",
"filename": "backup-flame.tar.xz",
"algorithm": "sha512"
}

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

@ -139,7 +139,6 @@
@BINPATH@/components/composer.xpt
@BINPATH@/components/content_base.xpt
@BINPATH@/components/content_events.xpt
@BINPATH@/components/content_canvas.xpt
@BINPATH@/components/content_htmldoc.xpt
@BINPATH@/components/content_html.xpt
@BINPATH@/components/content_xslt.xpt

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

@ -1228,7 +1228,7 @@ pref("devtools.toolbox.footer.height", 250);
pref("devtools.toolbox.sidebar.width", 500);
pref("devtools.toolbox.host", "bottom");
pref("devtools.toolbox.selectedTool", "webconsole");
pref("devtools.toolbox.toolbarSpec", '["splitconsole", "paintflashing toggle","tilt toggle","scratchpad","resize toggle"]');
pref("devtools.toolbox.toolbarSpec", '["splitconsole", "paintflashing toggle","tilt toggle","scratchpad","resize toggle","eyedropper"]');
pref("devtools.toolbox.sideEnabled", true);
pref("devtools.toolbox.zoomValue", "1");
@ -1239,6 +1239,7 @@ pref("devtools.command-button-paintflashing.enabled", false);
pref("devtools.command-button-tilt.enabled", false);
pref("devtools.command-button-scratchpad.enabled", false);
pref("devtools.command-button-responsive.enabled", true);
pref("devtools.command-button-eyedropper.enabled", false);
// Inspector preferences
// Enable the Inspector

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

@ -191,6 +191,60 @@ let AboutHomeListener = {
};
AboutHomeListener.init(this);
let ContentSearchMediator = {
whitelist: new Set([
"about:newtab",
]),
init: function (chromeGlobal) {
chromeGlobal.addEventListener("ContentSearchClient", this, true, true);
addMessageListener("ContentSearch", this);
},
handleEvent: function (event) {
if (this._contentWhitelisted) {
this._sendMsg(event.detail.type, event.detail.data);
}
},
receiveMessage: function (msg) {
if (msg.data.type == "AddToWhitelist") {
for (let uri of msg.data.data) {
this.whitelist.add(uri);
}
this._sendMsg("AddToWhitelistAck");
return;
}
if (this._contentWhitelisted) {
this._fireEvent(msg.data.type, msg.data.data);
}
},
get _contentWhitelisted() {
return this.whitelist.has(content.document.documentURI.toLowerCase());
},
_sendMsg: function (type, data=null) {
sendAsyncMessage("ContentSearch", {
type: type,
data: data,
});
},
_fireEvent: function (type, data=null) {
content.dispatchEvent(new content.CustomEvent("ContentSearchService", {
detail: {
type: type,
data: data,
},
}));
},
};
ContentSearchMediator.init(this);
var global = this;
// Lazily load the finder code

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

@ -197,12 +197,18 @@ let gGrid = {
}
let availSpace = document.documentElement.clientHeight - this._cellMargin -
document.querySelector("#newtab-margin-undo-container").offsetHeight;
document.querySelector("#newtab-margin-undo-container").offsetHeight -
document.querySelector("#newtab-search-form").offsetHeight;
let visibleRows = Math.floor(availSpace / this._cellHeight);
this._node.style.height = this._computeHeight() + "px";
this._node.style.maxHeight = this._computeHeight(visibleRows) + "px";
this._node.style.maxWidth = gGridPrefs.gridColumns * this._cellWidth +
GRID_WIDTH_EXTRA + "px";
// Resize the search bar.
let width = parseFloat(window.getComputedStyle(this._node).width);
let visibleCols = Math.floor(width / this._cellWidth);
gSearch.setWidth(visibleCols * this._cellWidth - this._cellMargin);
},
_shouldRenderGrid : function Grid_shouldRenderGrid() {

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

@ -2,6 +2,11 @@
* 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/. */
input {
font: message-box !important;
font-size: 16px !important;
}
input[type=button] {
cursor: pointer;
}
@ -12,6 +17,7 @@ input[type=button] {
position: relative;
-moz-box-flex: 1;
-moz-user-focus: normal;
-moz-box-orient: vertical;
}
#newtab-scrollbox:not([page-disabled]) {
@ -54,6 +60,7 @@ input[type=button] {
#newtab-margin-undo-container {
display: -moz-box;
-moz-box-pack: center;
margin-bottom: 26px; /* 32 - 6 search form top "padding" */
}
#newtab-horizontal-margin {
@ -64,10 +71,17 @@ input[type=button] {
#newtab-margin-top,
#newtab-margin-bottom {
display: -moz-box;
-moz-box-flex: 1;
position: relative;
}
#newtab-margin-top {
-moz-box-flex: 1;
}
#newtab-margin-bottom {
-moz-box-flex: 2;
}
.newtab-side-margin {
min-width: 16px;
-moz-box-flex: 1;
@ -213,7 +227,7 @@ input[type=button] {
opacity: 0.01;
}
/* PANEL */
/* SPONSORED PANEL */
#sponsored-panel {
width: 330px;
}
@ -225,3 +239,156 @@ input[type=button] {
#sponsored-panel .text-link {
margin: 12px 0 0;
}
/* SEARCH */
#newtab-search-container {
display: -moz-box;
position: relative;
-moz-box-align: center;
-moz-box-pack: center;
}
#newtab-search-container[page-disabled] {
opacity: 0;
pointer-events: none;
}
#newtab-search-form {
display: -moz-box;
-moz-box-orient: horizontal;
-moz-box-align: center;
height: 44px; /* 32 + 6 logo top "padding" + 6 logo bottom "padding" */
margin-bottom: 10px; /* 32 - 16 tiles top margin - 6 logo bottom "padding" */
}
#newtab-search-logo {
display: -moz-box;
width: 77px; /* 65 image width + 6 left "padding" + 6 right "padding" */
height: 38px; /* 26 image height + 6 top "padding" + 6 bottom "padding" */
border: 1px solid transparent;
-moz-margin-end: 8px;
background-repeat: no-repeat;
background-position: center;
background-size: 65px 26px;
}
#newtab-search-logo[hidden] {
display: none;
}
#newtab-search-logo[active],
#newtab-search-logo:hover {
background-color: #e9e9e9;
border: 1px solid rgb(226, 227, 229);
border-radius: 2.5px;
}
#newtab-search-text {
height: 32px;
-moz-box-flex: 1;
padding: 0 8px;
background: hsla(0,0%,100%,.9) padding-box;
border: 1px solid;
border-color: hsla(210,54%,20%,.15) hsla(210,54%,20%,.17) hsla(210,54%,20%,.2);
box-shadow: 0 1px 0 hsla(210,65%,9%,.02) inset,
0 0 2px hsla(210,65%,9%,.1) inset,
0 1px 0 hsla(0,0%,100%,.2);
border-radius: 2.5px 0 0 2.5px;
}
#newtab-search-text:-moz-dir(rtl) {
border-radius: 0 2.5px 2.5px 0;
}
#newtab-search-text:focus,
#newtab-search-text[autofocus] {
border-color: hsla(206,100%,60%,.6) hsla(206,76%,52%,.6) hsla(204,100%,40%,.6);
}
#newtab-search-submit {
height: 32px;
-moz-margin-start: -1px;
background: linear-gradient(hsla(0,0%,100%,.8), hsla(0,0%,100%,.1)) padding-box;
padding: 0 9px;
border: 1px solid;
border-color: hsla(210,54%,20%,.15) hsla(210,54%,20%,.17) hsla(210,54%,20%,.2);
-moz-border-start: 1px solid transparent;
border-radius: 0 2.5px 2.5px 0;
box-shadow: 0 0 2px hsla(0,0%,100%,.5) inset,
0 1px 0 hsla(0,0%,100%,.2);
cursor: pointer;
transition-property: background-color, border-color, box-shadow;
transition-duration: 150ms;
}
#newtab-search-submit:-moz-dir(rtl) {
border-radius: 2.5px 0 0 2.5px;
}
#newtab-search-text:focus + #newtab-search-submit,
#newtab-search-text + #newtab-search-submit:hover,
#newtab-search-text[autofocus] + #newtab-search-submit {
border-color: #59b5fc #45a3e7 #3294d5;
color: white;
}
#newtab-search-text:focus + #newtab-search-submit,
#newtab-search-text[autofocus] + #newtab-search-submit {
background-image: linear-gradient(#4cb1ff, #1793e5);
box-shadow: 0 1px 0 hsla(0,0%,100%,.2) inset,
0 0 0 1px hsla(0,0%,100%,.1) inset,
0 1px 0 hsla(210,54%,20%,.03);
}
#newtab-search-text + #newtab-search-submit:hover {
background-image: linear-gradient(#66bdff, #0d9eff);
box-shadow: 0 1px 0 hsla(0,0%,100%,.2) inset,
0 0 0 1px hsla(0,0%,100%,.1) inset,
0 1px 0 hsla(210,54%,20%,.03),
0 0 4px hsla(206,100%,20%,.2);
}
#newtab-search-text + #newtab-search-submit:hover:active {
box-shadow: 0 1px 1px hsla(211,79%,6%,.1) inset,
0 0 1px hsla(211,79%,6%,.2) inset;
transition-duration: 0ms;
}
#newtab-search-panel .panel-arrowcontent {
-moz-padding-start: 0;
-moz-padding-end: 0;
padding-top: 0;
padding-bottom: 0;
background: rgb(248, 250, 251);
}
.newtab-search-panel-engine {
-moz-box-align: center;
padding-top: 4px;
padding-bottom: 4px;
-moz-padding-start: 24px;
-moz-padding-end: 24px;
}
.newtab-search-panel-engine:not(:last-child) {
border-bottom: 1px solid #ccc;
}
.newtab-search-panel-engine > image {
-moz-margin-end: 8px;
width: 16px;
height: 16px;
list-style-image: url("chrome://mozapps/skin/places/defaultFavicon.png");
}
.newtab-search-panel-engine > label {
-moz-padding-start: 0;
-moz-margin-start: 0;
color: rgb(130, 132, 133);
}
.newtab-search-panel-engine[selected] {
background: url("chrome://global/skin/menu/shared-menu-check.png") center left 4px no-repeat transparent;
}

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

@ -41,6 +41,7 @@ function inPrivateBrowsingMode() {
}
const HTML_NAMESPACE = "http://www.w3.org/1999/xhtml";
const XUL_NAMESPACE = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
#include transformations.js
#include page.js
@ -54,6 +55,7 @@ const HTML_NAMESPACE = "http://www.w3.org/1999/xhtml";
#include dropPreview.js
#include updater.js
#include undo.js
#include search.js
// Everything is loaded. Initialize the New Tab Page.
gPage.init();

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

@ -11,6 +11,8 @@
<!DOCTYPE window [
<!ENTITY % newTabDTD SYSTEM "chrome://browser/locale/newTab.dtd">
%newTabDTD;
<!ENTITY % searchBarDTD SYSTEM "chrome://browser/locale/searchbar.dtd">
%searchBarDTD;
]>
<xul:window id="newtab-window" xmlns="http://www.w3.org/1999/xhtml"
@ -24,6 +26,13 @@
value="&newtab.panel.link.text;" />
</xul:panel>
<xul:panel id="newtab-search-panel" orient="vertical" type="arrow"
noautohide="true">
<xul:hbox id="newtab-search-manage" class="newtab-search-panel-engine">
<xul:label>&cmd_engineManager.label;</xul:label>
</xul:hbox>
</xul:panel>
<div id="newtab-scrollbox">
<div id="newtab-vertical-margin">
@ -46,6 +55,16 @@
</div>
</div>
<div id="newtab-search-container">
<form id="newtab-search-form" name="searchForm">
<div id="newtab-search-logo"/>
<input type="text" name="q" value="" id="newtab-search-text"
maxlength="256" dir="auto"/>
<input id="newtab-search-submit" type="submit"
value="&searchEndCap.label;"/>
</form>
</div>
<div id="newtab-horizontal-margin">
<div class="newtab-side-margin"/>

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

@ -111,6 +111,8 @@ let gPage = {
this._initialized = true;
gSearch.init();
this._mutationObserver = new MutationObserver(() => {
if (this.allowBackgroundCaptures) {
Services.telemetry.getHistogramById("NEWTAB_PAGE_SHOWN").add(true);
@ -138,6 +140,10 @@ let gPage = {
let shownCount = Math.min(10, count);
Services.telemetry.getHistogramById(shownId).add(shownCount);
}
// content.js isn't loaded for the page while it's in the preloader,
// which is why this is necessary.
gSearch.setUpInitialState();
}
});
this._mutationObserver.observe(document.documentElement, {
@ -164,7 +170,7 @@ let gPage = {
*/
_updateAttributes: function Page_updateAttributes(aValue) {
// Set the nodes' states.
let nodeSelector = "#newtab-scrollbox, #newtab-toggle, #newtab-grid";
let nodeSelector = "#newtab-scrollbox, #newtab-toggle, #newtab-grid, #newtab-search-container";
for (let node of document.querySelectorAll(nodeSelector)) {
if (aValue)
node.removeAttribute("page-disabled");

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

@ -0,0 +1,170 @@
#ifdef 0
/* 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/. */
#endif
let gSearch = {
currentEngineName: null,
init: function () {
for (let idSuffix of this._nodeIDSuffixes) {
this._nodes[idSuffix] =
document.getElementById("newtab-search-" + idSuffix);
}
window.addEventListener("ContentSearchService", this);
this.setUpInitialState();
},
setUpInitialState: function () {
this._send("GetState");
},
showPanel: function () {
let panel = this._nodes.panel;
let logo = this._nodes.logo;
panel.openPopup(logo);
logo.setAttribute("active", "true");
panel.addEventListener("popuphidden", function onHidden() {
panel.removeEventListener("popuphidden", onHidden);
logo.removeAttribute("active");
});
},
search: function (event) {
event.preventDefault();
let searchStr = this._nodes.text.value;
if (this.currentEngineName && searchStr.length) {
this._send("Search", {
engineName: this.currentEngineName,
searchString: searchStr,
whence: "newtab",
});
}
},
manageEngines: function () {
this._nodes.panel.hidePopup();
this._send("ManageEngines");
},
setWidth: function (width) {
this._nodes.form.style.width = width + "px";
this._nodes.form.style.maxWidth = width + "px";
},
handleEvent: function (event) {
this["on" + event.detail.type](event.detail.data);
},
onState: function (data) {
this._makePanel(data.engines);
this._setCurrentEngine(data.currentEngine);
this._initWhenInitalStateReceived();
},
onCurrentEngine: function (engineName) {
this._setCurrentEngine(engineName);
},
_nodeIDSuffixes: [
"form",
"logo",
"manage",
"panel",
"text",
],
_nodes: {},
_initWhenInitalStateReceived: function () {
this._nodes.form.addEventListener("submit", e => this.search(e));
this._nodes.logo.addEventListener("click", e => this.showPanel());
this._nodes.manage.addEventListener("click", e => this.manageEngines());
this._initWhenInitalStateReceived = function () {};
},
_send: function (type, data=null) {
window.dispatchEvent(new CustomEvent("ContentSearchClient", {
detail: {
type: type,
data: data,
},
}));
},
_makePanel: function (engines) {
let panel = this._nodes.panel;
// Empty the panel except for the Manage Engines row.
let i = 0;
while (i < panel.childNodes.length) {
let node = panel.childNodes[i];
if (node != this._nodes.manage) {
panel.removeChild(node);
}
else {
i++;
}
}
// Add all the engines.
for (let engine of engines) {
panel.insertBefore(this._makePanelEngine(panel, engine),
this._nodes.manage);
}
},
_makePanelEngine: function (panel, engine) {
let box = document.createElementNS(XUL_NAMESPACE, "hbox");
box.className = "newtab-search-panel-engine";
box.setAttribute("engine", engine.name);
box.addEventListener("click", () => {
this._send("SetCurrentEngine", engine.name);
panel.hidePopup();
this._nodes.text.focus();
});
let image = document.createElementNS(XUL_NAMESPACE, "image");
if (engine.iconURI) {
image.setAttribute("src", engine.iconURI);
}
box.appendChild(image);
let label = document.createElementNS(XUL_NAMESPACE, "label");
label.setAttribute("value", engine.name);
box.appendChild(label);
return box;
},
_setCurrentEngine: function (engine) {
this.currentEngineName = engine.name;
// Set the logo.
let logoURI = window.devicePixelRatio == 2 ? engine.logo2xURI :
engine.logoURI;
if (logoURI) {
this._nodes.logo.hidden = false;
this._nodes.logo.style.backgroundImage = "url(" + logoURI + ")";
this._nodes.text.placeholder = "";
}
else {
this._nodes.logo.hidden = true;
this._nodes.text.placeholder = engine.name;
}
// Set the selected state of all the engines in the panel.
for (let box of this._nodes.panel.childNodes) {
if (box.getAttribute("engine") == engine.name) {
box.setAttribute("selected", "true");
}
else {
box.removeAttribute("selected");
}
}
},
};

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

@ -399,7 +399,6 @@ skip-if = e10s # Bug ????? - test calls gBrowser.contentWindow.stop
[browser_urlbar_search_healthreport.js]
skip-if = e10s # Bug ?????? - FHR tests failing (either with "no data for today" or "2 records for today")
[browser_utilityOverlay.js]
skip-if = e10s # Bug 921947 - openNewTabWith failed with window.content.document being null
[browser_visibleFindSelection.js]
skip-if = e10s # Bug ?????? - test directly manipulates content
[browser_visibleLabel.js]

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

@ -1,6 +1,9 @@
[DEFAULT]
support-files = head.js
skip-if = e10s # Bug ?????? - about:newtab tests don't work in e10s
support-files =
head.js
searchEngineLogo.xml
searchEngineNoLogo.xml
[browser_newtab_background_captures.js]
[browser_newtab_block.js]
@ -25,6 +28,7 @@ skip-if = os == "mac" # Intermittent failures, bug 898317
[browser_newtab_focus.js]
[browser_newtab_perwindow_private_browsing.js]
[browser_newtab_reset.js]
[browser_newtab_search.js]
[browser_newtab_sponsored_icon_click.js]
[browser_newtab_tabsync.js]
[browser_newtab_undo.js]

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

@ -9,9 +9,9 @@ function runTests() {
Services.prefs.setIntPref("accessibility.tabfocus", 7);
// Focus count in new tab page.
// 28 = 9 * 3 + 1 = 9 sites and 1 toggle button, each site has a link, a pin
// and a remove button.
let FOCUS_COUNT = 28;
// 30 = 9 * 3 + 3 = 9 sites, each with link, pin and remove buttons; search
// bar; search button; and toggle button.
let FOCUS_COUNT = 30;
// Create a new tab page.
yield setLinks("0,1,2,3,4,5,6,7,8");

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

@ -0,0 +1,295 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// See browser/components/search/test/browser_*_behavior.js for tests of actual
// searches.
const ENGINE_LOGO = "searchEngineLogo.xml";
const ENGINE_NO_LOGO = "searchEngineNoLogo.xml";
const SERVICE_EVENT_NAME = "ContentSearchService";
const LOGO_LOW_DPI_SIZE = [65, 26];
const LOGO_HIGH_DPI_SIZE = [130, 52];
// The test has an expected search event queue and a search event listener.
// Search events that are expected to happen are added to the queue, and the
// listener consumes the queue and ensures that each event it receives is at
// the head of the queue.
//
// Each item in the queue is an object { type, deferred }. type is the
// expected search event type. deferred is a Promise.defer() value that is
// resolved when the event is consumed.
var gExpectedSearchEventQueue = [];
var gNewEngines = [];
function runTests() {
let oldCurrentEngine = Services.search.currentEngine;
yield addNewTabPageTab();
yield whenSearchInitDone();
// The tab is removed at the end of the test, so there's no need to remove
// this listener at the end of the test.
info("Adding search event listener");
getContentWindow().addEventListener(SERVICE_EVENT_NAME, searchEventListener);
let panel = searchPanel();
is(panel.state, "closed", "Search panel should be closed initially");
// The panel's animation often is not finished when the test clicks on panel
// children, which makes the test click the wrong children, so disable it.
panel.setAttribute("animate", "false");
// Add the two test engines.
let logoEngine = null;
yield promiseNewSearchEngine(true).then(engine => {
logoEngine = engine;
TestRunner.next();
});
ok(!!logoEngine.getIconURLBySize(...LOGO_LOW_DPI_SIZE),
"Sanity check: engine should have 1x logo");
ok(!!logoEngine.getIconURLBySize(...LOGO_HIGH_DPI_SIZE),
"Sanity check: engine should have 2x logo");
let noLogoEngine = null;
yield promiseNewSearchEngine(false).then(engine => {
noLogoEngine = engine;
TestRunner.next();
});
ok(!noLogoEngine.getIconURLBySize(...LOGO_LOW_DPI_SIZE),
"Sanity check: engine should not have 1x logo");
ok(!noLogoEngine.getIconURLBySize(...LOGO_HIGH_DPI_SIZE),
"Sanity check: engine should not have 2x logo");
// Use the search service to change the current engine to the logo engine.
Services.search.currentEngine = logoEngine;
yield promiseSearchEvents(["CurrentEngine"]).then(TestRunner.next);
checkCurrentEngine(ENGINE_LOGO);
// Click the logo to open the search panel.
yield Promise.all([
promisePanelShown(panel),
promiseClick(logoImg()),
]).then(TestRunner.next);
// In the search panel, click the no-logo engine. It should become the
// current engine.
let noLogoBox = null;
for (let box of panel.childNodes) {
if (box.getAttribute("engine") == noLogoEngine.name) {
noLogoBox = box;
break;
}
}
ok(noLogoBox, "Search panel should contain the no-logo engine");
yield Promise.all([
promiseSearchEvents(["CurrentEngine"]),
promiseClick(noLogoBox),
]).then(TestRunner.next);
checkCurrentEngine(ENGINE_NO_LOGO);
// Switch back to the logo engine.
Services.search.currentEngine = logoEngine;
yield promiseSearchEvents(["CurrentEngine"]).then(TestRunner.next);
checkCurrentEngine(ENGINE_LOGO);
// Open the panel again.
yield Promise.all([
promisePanelShown(panel),
promiseClick(logoImg()),
]).then(TestRunner.next);
// In the search panel, click the Manage Engines box.
let manageBox = $("manage");
ok(!!manageBox, "The Manage Engines box should be present in the document");
yield Promise.all([
promiseManagerOpen(),
promiseClick(manageBox),
]).then(TestRunner.next);
// Done. Revert the current engine and remove the new engines.
Services.search.currentEngine = oldCurrentEngine;
yield promiseSearchEvents(["CurrentEngine"]).then(TestRunner.next);
let events = [];
for (let engine of gNewEngines) {
Services.search.removeEngine(engine);
events.push("State");
}
yield promiseSearchEvents(events).then(TestRunner.next);
}
function searchEventListener(event) {
info("Got search event " + event.detail.type);
let passed = false;
let nonempty = gExpectedSearchEventQueue.length > 0;
ok(nonempty, "Expected search event queue should be nonempty");
if (nonempty) {
let { type, deferred } = gExpectedSearchEventQueue.shift();
is(event.detail.type, type, "Got expected search event " + type);
if (event.detail.type == type) {
passed = true;
// Let gSearch respond to the event before continuing.
executeSoon(() => deferred.resolve());
}
}
if (!passed) {
info("Didn't get expected event, stopping the test");
getContentWindow().removeEventListener(SERVICE_EVENT_NAME,
searchEventListener);
// Set next() to a no-op so the test really does stop.
TestRunner.next = function () {};
TestRunner.finish();
}
}
function $(idSuffix) {
return getContentDocument().getElementById("newtab-search-" + idSuffix);
}
function promiseSearchEvents(events) {
info("Expecting search events: " + events);
events = events.map(e => ({ type: e, deferred: Promise.defer() }));
gExpectedSearchEventQueue.push(...events);
return Promise.all(events.map(e => e.deferred.promise));
}
function promiseNewSearchEngine(withLogo) {
let basename = withLogo ? ENGINE_LOGO : ENGINE_NO_LOGO;
info("Waiting for engine to be added: " + basename);
// Wait for the search events triggered by adding the new engine.
// engine-added engine-loaded
let expectedSearchEvents = ["State", "State"];
if (withLogo) {
// an engine-changed for each of the two logos
expectedSearchEvents.push("State", "State");
}
let eventPromise = promiseSearchEvents(expectedSearchEvents);
// Wait for addEngine().
let addDeferred = Promise.defer();
let url = getRootDirectory(gTestPath) + basename;
Services.search.addEngine(url, Ci.nsISearchEngine.TYPE_MOZSEARCH, "", false, {
onSuccess: function (engine) {
info("Search engine added: " + basename);
gNewEngines.push(engine);
addDeferred.resolve(engine);
},
onError: function (errCode) {
ok(false, "addEngine failed with error code " + errCode);
addDeferred.reject();
},
});
// Make a new promise that wraps the previous promises. The only point of
// this is to pass the new engine to the yielder via deferred.resolve(),
// which is a little nicer than passing an array whose first element is the
// new engine.
let deferred = Promise.defer();
Promise.all([addDeferred.promise, eventPromise]).then(values => {
let newEngine = values[0];
deferred.resolve(newEngine);
}, () => deferred.reject());
return deferred.promise;
}
function checkCurrentEngine(basename) {
let engine = Services.search.currentEngine;
ok(engine.name.contains(basename),
"Sanity check: current engine: engine.name=" + engine.name +
" basename=" + basename);
// gSearch.currentEngineName
is(gSearch().currentEngineName, engine.name,
"currentEngineName: " + engine.name);
// search bar logo
let logoSize = [px * window.devicePixelRatio for (px of LOGO_LOW_DPI_SIZE)];
let logoURI = engine.getIconURLBySize(...logoSize);
let logo = logoImg();
is(logo.hidden, !logoURI,
"Logo should be visible iff engine has a logo: " + engine.name);
if (logoURI) {
is(logo.style.backgroundImage, 'url("' + logoURI + '")', "Logo URI");
}
// "selected" attributes of engines in the panel
let panel = searchPanel();
for (let engineBox of panel.childNodes) {
let engineName = engineBox.getAttribute("engine");
if (engineName == engine.name) {
is(engineBox.getAttribute("selected"), "true",
"Engine box's selected attribute should be true for " +
"selected engine: " + engineName);
}
else {
ok(!engineBox.hasAttribute("selected"),
"Engine box's selected attribute should be absent for " +
"non-selected engine: " + engineName);
}
}
}
function promisePanelShown(panel) {
let deferred = Promise.defer();
info("Waiting for popupshown");
panel.addEventListener("popupshown", function onEvent() {
panel.removeEventListener("popupshown", onEvent);
is(panel.state, "open", "Panel state");
executeSoon(() => deferred.resolve());
});
return deferred.promise;
}
function promiseClick(node) {
let deferred = Promise.defer();
let win = getContentWindow();
SimpleTest.waitForFocus(() => {
EventUtils.synthesizeMouseAtCenter(node, {}, win);
deferred.resolve();
}, win);
return deferred.promise;
}
function promiseManagerOpen() {
info("Waiting for the search manager window to open...");
let deferred = Promise.defer();
let winWatcher = Cc["@mozilla.org/embedcomp/window-watcher;1"].
getService(Ci.nsIWindowWatcher);
winWatcher.registerNotification(function onWin(subj, topic, data) {
if (topic == "domwindowopened" && subj instanceof Ci.nsIDOMWindow) {
subj.addEventListener("load", function onLoad() {
subj.removeEventListener("load", onLoad);
if (subj.document.documentURI ==
"chrome://browser/content/search/engineManager.xul") {
winWatcher.unregisterNotification(onWin);
ok(true, "Observed search manager window opened");
is(subj.opener, gWindow,
"Search engine manager opener should be the chrome browser " +
"window containing the newtab page");
executeSoon(() => {
subj.close();
deferred.resolve();
});
}
});
}
});
return deferred.promise;
}
function searchPanel() {
return $("panel");
}
function logoImg() {
return $("logo");
}
function gSearch() {
return getContentWindow().gSearch;
}

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

@ -5,6 +5,10 @@ function runTests() {
yield setLinks("0");
yield addNewTabPageTab();
// When gSearch modifies the DOM as it sets itself up, it can prevent the
// popup from opening, depending on the timing. Wait until that's done.
yield whenSearchInitDone();
let site = getCell(0).node.querySelector(".newtab-site");
site.setAttribute("type", "sponsored");

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

@ -25,10 +25,41 @@ let isLinux = ("@mozilla.org/gnome-gconf-service;1" in Cc);
let isWindows = ("@mozilla.org/windows-registry-key;1" in Cc);
let gWindow = window;
// The tests assume all three rows of sites are shown, but the window may be too
// short to actually show three rows. Resize it if necessary.
let requiredInnerHeight =
40 + 32 + // undo container + bottom margin
44 + 32 + // search bar + bottom margin
(3 * (150 + 32)) + // 3 rows * (tile height + title and bottom margin)
100; // breathing room
let oldInnerHeight = null;
if (gBrowser.contentWindow.innerHeight < requiredInnerHeight) {
oldInnerHeight = gBrowser.contentWindow.innerHeight;
info("Changing browser inner height from " + oldInnerHeight + " to " +
requiredInnerHeight);
gBrowser.contentWindow.innerHeight = requiredInnerHeight;
let screenHeight = {};
Cc["@mozilla.org/gfx/screenmanager;1"].
getService(Ci.nsIScreenManager).
primaryScreen.
GetAvailRectDisplayPix({}, {}, {}, screenHeight);
screenHeight = screenHeight.value;
if (screenHeight < gBrowser.contentWindow.outerHeight) {
info("Warning: Browser outer height is now " +
gBrowser.contentWindow.outerHeight + ", which is larger than the " +
"available screen height, " + screenHeight +
". That may cause problems.");
}
}
registerCleanupFunction(function () {
while (gWindow.gBrowser.tabs.length > 1)
gWindow.gBrowser.removeTab(gWindow.gBrowser.tabs[1]);
if (oldInnerHeight)
gBrowser.contentWindow.innerHeight = oldInnerHeight;
Services.prefs.clearUserPref(PREF_NEWTAB_ENABLED);
Services.prefs.clearUserPref(PREF_NEWTAB_DIRECTORYSOURCE);
@ -549,3 +580,35 @@ function whenPagesUpdated(aCallback, aOnlyIfHidden=false) {
NewTabUtils.allPages.unregister(page);
});
}
/**
* Waits a small amount of time for search events to stop occurring in the
* newtab page.
*
* newtab pages receive some search events around load time that are difficult
* to predict. There are two categories of such events: (1) "State" events
* triggered by engine notifications like engine-changed, due to the search
* service initializing itself on app startup. This can happen when a test is
* the first test to run. (2) "State" events triggered by the newtab page
* itself when gSearch first sets itself up. newtab preloading makes these a
* pain to predict.
*/
function whenSearchInitDone() {
info("Waiting for initial search events...");
let numTicks = 0;
function reset(event) {
info("Got initial search event " + event.detail.type +
", waiting for more...");
numTicks = 0;
}
let eventName = "ContentSearchService";
getContentWindow().addEventListener(eventName, reset);
let interval = window.setInterval(() => {
if (++numTicks >= 100) {
info("Done waiting for initial search events");
window.clearInterval(interval);
getContentWindow().removeEventListener(eventName, reset);
TestRunner.next();
}
}, 0);
}

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

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

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
<ShortName>browser_newtab_search searchEngineNoLogo.xml</ShortName>
<Url type="text/html" method="GET" template="http://browser-newtab-search.com/nologo" rel="searchform"/>
</SearchPlugin>

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

@ -599,17 +599,14 @@ function makeURLAbsolute(aBase, aUrl)
return makeURI(aUrl, null, makeURI(aBase)).spec;
}
/**
* openNewTabWith: opens a new tab with the given URL.
*
* @param aURL
* The URL to open (as a string).
* @param aDocument
* The document from which the URL came, or null. This is used to set the
* referrer header and to do a security check of whether the document is
* allowed to reference the URL. If null, there will be no referrer
* header and no security check.
* Note this parameter is now ignored. There is no security check & no
* referrer header derived from aDocument (null case).
* @param aPostData
* Form POST data, or null.
* @param aEvent
@ -620,46 +617,40 @@ function makeURLAbsolute(aBase, aUrl)
* (e.g., Google's I Feel Lucky) for interpretation. This parameter may
* be undefined in which case it is treated as false.
* @param [optional] aReferrer
* If aDocument is null, then this will be used as the referrer.
* There will be no security check.
* This will be used as the referrer. There will be no security check.
*/
function openNewTabWith(aURL, aDocument, aPostData, aEvent,
aAllowThirdPartyFixup, aReferrer) {
if (aDocument)
urlSecurityCheck(aURL, aDocument.nodePrincipal);
// As in openNewWindowWith(), we want to pass the charset of the
// current document over to a new tab.
var originCharset = aDocument && aDocument.characterSet;
if (!originCharset &&
document.documentElement.getAttribute("windowtype") == "navigator:browser")
originCharset = window.content.document.characterSet;
let originCharset = null;
if (document.documentElement.getAttribute("windowtype") == "navigator:browser")
originCharset = gBrowser.selectedBrowser.characterSet;
openLinkIn(aURL, aEvent && aEvent.shiftKey ? "tabshifted" : "tab",
{ charset: originCharset,
postData: aPostData,
allowThirdPartyFixup: aAllowThirdPartyFixup,
referrerURI: aDocument ? aDocument.documentURIObject : aReferrer });
referrerURI: aReferrer });
}
/**
* @param aDocument
* Note this parameter is ignored. See openNewTabWith()
*/
function openNewWindowWith(aURL, aDocument, aPostData, aAllowThirdPartyFixup, aReferrer) {
if (aDocument)
urlSecurityCheck(aURL, aDocument.nodePrincipal);
// if and only if the current window is a browser window and it has a
// document with a character set, then extract the current charset menu
// setting from the current document and use it to initialize the new browser
// window...
var originCharset = aDocument && aDocument.characterSet;
if (!originCharset &&
document.documentElement.getAttribute("windowtype") == "navigator:browser")
originCharset = window.content.document.characterSet;
// Extract the current charset menu setting from the current document and
// use it to initialize the new browser window...
let originCharset = null;
if (document.documentElement.getAttribute("windowtype") == "navigator:browser")
originCharset = gBrowser.selectedBrowser.characterSet;
openLinkIn(aURL, "window",
{ charset: originCharset,
postData: aPostData,
allowThirdPartyFixup: aAllowThirdPartyFixup,
referrerURI: aDocument ? aDocument.documentURIObject : aReferrer });
referrerURI: aReferrer });
}
// aCalledFromModal is optional

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

@ -98,6 +98,9 @@ XPCOMUtils.defineLazyModuleGetter(this, "SignInToWebsiteUX",
"resource:///modules/SignInToWebsite.jsm");
#endif
XPCOMUtils.defineLazyModuleGetter(this, "ContentSearch",
"resource:///modules/ContentSearch.jsm");
const PREF_PLUGINS_NOTIFYUSER = "plugins.update.notifyUser";
const PREF_PLUGINS_UPDATEURL = "plugins.update.url";
@ -497,6 +500,7 @@ BrowserGlue.prototype = {
AboutHome.init();
SessionStore.init();
BrowserUITelemetry.init();
ContentSearch.init();
if (Services.appinfo.browserTabsRemote) {
ContentClick.init();

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

@ -65,6 +65,50 @@ function test() {
EventUtils.synthesizeKey("VK_RETURN", {});
}
},
{
name: "new tab search",
searchURL: base,
run: function () {
function doSearch(doc) {
// Re-add the listener, and perform a search
gBrowser.addProgressListener(listener);
doc.getElementById("newtab-search-text").value = "foo";
doc.getElementById("newtab-search-submit").click();
}
// load about:newtab, but remove the listener first so it doesn't
// get in the way
gBrowser.removeProgressListener(listener);
gBrowser.loadURI("about:newtab");
info("Waiting for about:newtab load");
tab.linkedBrowser.addEventListener("load", function load(event) {
if (event.originalTarget != tab.linkedBrowser.contentDocument ||
event.target.location.href == "about:blank") {
info("skipping spurious load event");
return;
}
tab.linkedBrowser.removeEventListener("load", load, true);
// Observe page setup
let win = gBrowser.contentWindow;
if (win.gSearch.currentEngineName ==
Services.search.currentEngine.name) {
doSearch(win.document);
}
else {
info("Waiting for newtab search init");
win.addEventListener("ContentSearchService", function done(event) {
info("Got newtab search event " + event.detail.type);
if (event.detail.type == "State") {
win.removeEventListener("ContentSearchService", done);
// Let gSearch respond to the event before continuing.
executeSoon(() => doSearch(win.document));
}
});
}
}, true);
}
},
{
name: "home page search",
searchURL: base + "&form=MOZSPG",

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

@ -95,6 +95,50 @@ function test() {
EventUtils.synthesizeKey("VK_RETURN", {});
}
},
{
name: "new tab search",
searchURL: base,
run: function () {
function doSearch(doc) {
// Re-add the listener, and perform a search
gBrowser.addProgressListener(listener);
doc.getElementById("newtab-search-text").value = "foo";
doc.getElementById("newtab-search-submit").click();
}
// load about:newtab, but remove the listener first so it doesn't
// get in the way
gBrowser.removeProgressListener(listener);
gBrowser.loadURI("about:newtab");
info("Waiting for about:newtab load");
tab.linkedBrowser.addEventListener("load", function load(event) {
if (event.originalTarget != tab.linkedBrowser.contentDocument ||
event.target.location.href == "about:blank") {
info("skipping spurious load event");
return;
}
tab.linkedBrowser.removeEventListener("load", load, true);
// Observe page setup
let win = gBrowser.contentWindow;
if (win.gSearch.currentEngineName ==
Services.search.currentEngine.name) {
doSearch(win.document);
}
else {
info("Waiting for newtab search init");
win.addEventListener("ContentSearchService", function done(event) {
info("Got newtab search event " + event.detail.type);
if (event.detail.type == "State") {
win.removeEventListener("ContentSearchService", done);
// Let gSearch respond to the event before continuing.
executeSoon(() => doSearch(win.document));
}
});
}
}, true);
}
},
{
name: "home page search",
searchURL: base + "&channel=np&source=hp",

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

@ -286,6 +286,10 @@ let SessionHistoryListener = {
return true;
},
OnHistoryReplaceEntry: function (index) {
this.collect();
},
QueryInterface: XPCOMUtils.generateQI([
Ci.nsISHistoryListener,
Ci.nsISupportsWeakReference

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

@ -369,6 +369,7 @@ HistoryListener.prototype = {
OnHistoryGoForward: function(forwardURI) { return true; },
OnHistoryGotoIndex: function(index, gotoURI) { return true; },
OnHistoryPurge: function(numEntries) { return true; },
OnHistoryReplaceEntry: function(index) {},
OnHistoryReload: function(reloadURI, reloadFlags) {
this.callback();

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

@ -2581,6 +2581,12 @@ let SessionStoreInternal = {
// Save the index in case we updated it above.
tabData.index = activeIndex + 1;
// In electrolysis, we may need to change the browser's remote
// attribute so that it runs in a content process.
let activePageData = tabData.entries[activeIndex] || null;
let uri = activePageData ? activePageData.url || null : null;
tabbrowser.updateBrowserRemoteness(browser, uri);
// Start a new epoch and include the epoch in the restoreHistory
// message. If a message is received that relates to a previous epoch, we
// discard it.
@ -2604,12 +2610,6 @@ let SessionStoreInternal = {
pageStyle: tabData.pageStyle || null
});
// In electrolysis, we may need to change the browser's remote
// attribute so that it runs in a content process.
let activePageData = tabData.entries[activeIndex] || null;
let uri = activePageData ? activePageData.url || null : null;
tabbrowser.updateBrowserRemoteness(browser, uri);
browser.messageManager.sendAsyncMessage("SessionStore:restoreHistory",
{tabData: tabData, epoch: epoch});

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

@ -220,15 +220,15 @@ add_task(function test_pushstate_replacestate() {
is(entries[1].url, "http://example.com/test-entry/", "url is correct");
// Disabled until replaceState invalidation is supported. See Bug 967028.
// browser.messageManager.
// sendAsyncMessage("ss-test:historyReplaceState", {url: 'test-entry2/'});
// yield promiseContentMessage(browser, "ss-test:historyReplaceState");
browser.messageManager.
sendAsyncMessage("ss-test:historyReplaceState", {url: 'test-entry2/'});
yield promiseContentMessage(browser, "ss-test:historyReplaceState");
// // Check that we have modified the history entry.
// SyncHandlers.get(browser).flush();
// let {entries} = JSON.parse(ss.getTabState(tab));
// is(entries.length, 2, "there is still two shistory entries");
// is(entries[1].url, "http://example.com/test-entry/test-entry2/", "url is correct");
// Check that we have modified the history entry.
SyncHandlers.get(browser).flush();
let {entries} = JSON.parse(ss.getTabState(tab));
is(entries.length, 2, "there is still two shistory entries");
is(entries[1].url, "http://example.com/test-entry/test-entry2/", "url is correct");
// Cleanup.
gBrowser.removeTab(tab);

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

@ -9,8 +9,6 @@
const TAB_URL = EXAMPLE_URL + "doc_breakpoints-break-on-last-line-of-script-on-reload.html";
const CODE_URL = EXAMPLE_URL + "code_breakpoints-break-on-last-line-of-script-on-reload.js";
const { promiseInvoke } = require("devtools/async-utils");
function test() {
let gPanel, gDebugger, gThreadClient, gEvents;
@ -59,15 +57,15 @@ function test() {
// And we should hit the breakpoints as we resume.
yield promise.all([
doResume(),
doResume(gPanel),
waitForCaretAndScopes(gPanel, 3)
]);
yield promise.all([
doResume(),
doResume(gPanel),
waitForCaretAndScopes(gPanel, 4)
]);
yield promise.all([
doResume(),
doResume(gPanel),
waitForCaretAndScopes(gPanel, 5)
]);
@ -90,23 +88,6 @@ function test() {
});
});
function rdpInvoke(obj, method) {
return promiseInvoke(obj, method)
.then(({error, message }) => {
if (error) {
throw new Error(error + ": " + message);
}
});
}
function doResume() {
return rdpInvoke(gThreadClient, gThreadClient.resume);
}
function doInterrupt() {
return rdpInvoke(gThreadClient, gThreadClient.interrupt);
}
function setBreakpoint(location) {
let deferred = promise.defer();
gThreadClient.setBreakpoint(location, ({ error, message }, bpClient) => {

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

@ -2,16 +2,15 @@
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Test that pretty printing when the debugger is paused
* does not switch away from the selected source.
* Test that pretty printing when the debugger is paused does not switch away
* from the selected source.
*/
const TAB_URL = EXAMPLE_URL + "doc_pretty-print-on-paused.html";
let gTab, gDebuggee, gPanel, gDebugger;
let gSources;
let gTab, gDebuggee, gPanel, gDebugger, gThreadClient, gSources;
let gSecondSourceLabel = "code_ugly-2.js";
const SECOND_SOURCE_VALUE = EXAMPLE_URL + "code_ugly-2.js";
function test(){
initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => {
@ -19,63 +18,50 @@ function test(){
gDebuggee = aDebuggee;
gPanel = aPanel;
gDebugger = gPanel.panelWin;
gThreadClient = gDebugger.gThreadClient;
gSources = gDebugger.DebuggerView.Sources;
gPanel.addBreakpoint({ url: gSources.values[0], line: 6 });
Task.spawn(function* () {
try {
yield ensureSourceIs(gPanel, "code_script-switching-02.js", true);
waitForSourceAndCaretAndScopes(gPanel, "-02.js", 6)
.then(testPaused)
.then(() => {
// Switch to the second source.
let finished = waitForDebuggerEvents(gPanel, gDebugger.EVENTS.SOURCE_SHOWN);
gSources.selectedIndex = 1;
return finished;
})
.then(testSecondSourceIsSelected)
.then(() => {
const finished = waitForDebuggerEvents(gPanel, gDebugger.EVENTS.SOURCE_SHOWN);
clickPrettyPrintButton();
testProgressBarShown();
return finished;
})
.then(testSecondSourceIsStillSelected)
.then(() => closeDebuggerAndFinish(gPanel))
.then(null, aError => {
ok(false, "Got an error: " + DevToolsUtils.safeErrorString(aError));
})
yield doInterrupt(gPanel);
yield rdpInvoke(gThreadClient, gThreadClient.setBreakpoint, {
url: gSources.selectedValue,
line: 6
});
yield doResume(gPanel);
gDebuggee.secondCall();
const bpHit = waitForCaretAndScopes(gPanel, 6);
// Get the debuggee call off this tick so that we aren't accidentally
// blocking the yielding of bpHit which causes a deadlock.
executeSoon(() => gDebuggee.secondCall());
yield bpHit;
info("Switch to the second source.");
const sourceShown = waitForSourceShown(gPanel, SECOND_SOURCE_VALUE);
gSources.selectedValue = SECOND_SOURCE_VALUE;
yield sourceShown;
info("Pretty print the source.");
const prettyPrinted = waitForSourceShown(gPanel, SECOND_SOURCE_VALUE);
gDebugger.document.getElementById("pretty-print").click();
yield prettyPrinted;
yield resumeDebuggerThenCloseAndFinish(gPanel);
} catch (e) {
DevToolsUtils.reportException("browser_dbg_pretty-print-on-paused.js", e);
ok(false, "Got an error: " + DevToolsUtils.safeErrorString(e));
}
});
});
}
function testPaused() {
is(gDebugger.gThreadClient.paused, true,
"The thread should be paused");
}
function testSecondSourceIsSelected() {
ok(gSources.containsValue(EXAMPLE_URL + gSecondSourceLabel),
"The second source should be selected.");
}
function clickPrettyPrintButton() {
gDebugger.document.getElementById("pretty-print").click();
}
function testProgressBarShown() {
const deck = gDebugger.document.getElementById("editor-deck");
is(deck.selectedIndex, 2, "The progress bar should be shown");
}
function testSecondSourceIsStillSelected() {
ok(gSources.containsValue(EXAMPLE_URL + gSecondSourceLabel),
"The second source should still be selected.");
}
registerCleanupFunction(function() {
gTab = null;
gDebuggee = null;
gPanel = null;
gDebugger = null;
gThreadClient = null;
gSources = null;
});

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

@ -22,6 +22,7 @@ let { BrowserToolboxProcess } = Cu.import("resource:///modules/devtools/ToolboxP
let { DebuggerServer } = Cu.import("resource://gre/modules/devtools/dbg-server.jsm", {});
let { DebuggerClient } = Cu.import("resource://gre/modules/devtools/dbg-client.jsm", {});
let { AddonManager } = Cu.import("resource://gre/modules/AddonManager.jsm", {});
const { promiseInvoke } = require("devtools/async-utils");
let TargetFactory = devtools.TargetFactory;
let Toolbox = devtools.Toolbox;
@ -856,3 +857,23 @@ function attachAddonActorForUrl(aClient, aUrl) {
return deferred.promise;
}
function rdpInvoke(aClient, aMethod, ...args) {
return promiseInvoke(aClient, aMethod, ...args)
.then(({error, message }) => {
if (error) {
throw new Error(error + ": " + message);
}
});
}
function doResume(aPanel) {
const threadClient = aPanel.panelWin.gThreadClient;
return rdpInvoke(threadClient, threadClient.resume);
}
function doInterrupt(aPanel) {
const threadClient = aPanel.panelWin.gThreadClient;
return rdpInvoke(threadClient, threadClient.interrupt);
}

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

@ -0,0 +1,50 @@
/* 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/. */
const gcli = require("gcli/index");
const EventEmitter = require("devtools/toolkit/event-emitter");
const eventEmitter = new EventEmitter();
let { Eyedropper, EyedropperManager } = require("devtools/eyedropper/eyedropper");
/**
* 'eyedropper' command
*/
exports.items = [{
name: "eyedropper",
description: gcli.lookup("eyedropperDesc"),
manual: gcli.lookup("eyedropperManual"),
buttonId: "command-button-eyedropper",
buttonClass: "command-button command-button-invertable",
tooltipText: gcli.lookup("eyedropperTooltip"),
state: {
isChecked: function(target) {
let chromeWindow = target.tab.ownerDocument.defaultView;
let dropper = EyedropperManager.getInstance(chromeWindow);
if (dropper) {
return true;
}
return false;
},
onChange: function(target, changeHandler) {
eventEmitter.on("changed", changeHandler);
},
offChange: function(target, changeHandler) {
eventEmitter.off("changed", changeHandler);
},
},
exec: function(args, context) {
let chromeWindow = context.environment.chromeWindow;
let target = context.environment.target;
let dropper = EyedropperManager.createInstance(chromeWindow);
dropper.open();
eventEmitter.emit("changed", target.tab);
dropper.once("destroy", () => {
eventEmitter.emit("changed", target.tab);
});
}
}];

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

@ -48,6 +48,40 @@ const CLOSE_DELAY = 750;
const HEX_BOX_WIDTH = CANVAS_WIDTH + CANVAS_OFFSET * 2;
const HSL_BOX_WIDTH = 158;
/**
* Manage instances of eyedroppers for windows. Registering here isn't
* necessary for creating an eyedropper, but can be used for testing.
*/
let EyedropperManager = {
_instances: new WeakMap(),
getInstance: function(chromeWindow) {
return this._instances.get(chromeWindow);
},
createInstance: function(chromeWindow) {
let dropper = this.getInstance(chromeWindow);
if (dropper) {
return dropper;
}
dropper = new Eyedropper(chromeWindow);
this._instances.set(chromeWindow, dropper);
dropper.on("destroy", () => {
this.deleteInstance(chromeWindow);
});
return dropper;
},
deleteInstance: function(chromeWindow) {
this._instances.delete(chromeWindow);
}
}
exports.EyedropperManager = EyedropperManager;
/**
* Eyedropper widget. Once opened, shows zoomed area above current pixel and
* displays the color value of the center pixel. Clicking on the window will

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

@ -7,6 +7,7 @@
JS_MODULES_PATH = 'modules/devtools/eyedropper'
EXTRA_JS_MODULES += [
'commands.js',
'eyedropper.js'
]

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

@ -7,3 +7,4 @@ support-files =
[browser_eyedropper_basic.js]
skip-if = os == "win" && debug # bug 963492
[browser_eyedropper_cmd.js]

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

@ -62,14 +62,3 @@ function inspectPage(dropper, click=true) {
function pressESC() {
EventUtils.synthesizeKey("VK_ESCAPE", { });
}
function dropperLoaded(dropper) {
if (dropper.loaded) {
return promise.resolve();
}
let deferred = promise.defer();
dropper.once("load", deferred.resolve);
return deferred.promise;
}

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

@ -0,0 +1,56 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
// Tests that the eyedropper command works
const TESTCASE_URI = TEST_BASE + "color-block.html";
const DIV_COLOR = "#0000FF";
function test() {
return Task.spawn(spawnTest).then(finish, helpers.handleError);
}
function spawnTest() {
let options = yield helpers.openTab(TESTCASE_URI);
yield helpers.openToolbar(options);
yield helpers.audit(options, [
{
setup: "eyedropper",
check: {
input: "eyedropper"
},
exec: { output: "" }
},
]);
yield inspectAndWaitForCopy();
yield helpers.closeToolbar(options);
yield helpers.closeTab(options);
}
function inspectAndWaitForCopy() {
let deferred = promise.defer();
waitForClipboard(DIV_COLOR, () => {
inspectPage(); // setup: inspect the page
}, deferred.resolve, deferred.reject);
return deferred.promise;
}
function inspectPage() {
let target = content.document.getElementById("test");
let win = content.window;
EventUtils.synthesizeMouse(target, 20, 20, { type: "mousemove" }, win);
let dropper = EyedropperManager.getInstance(window);
return dropperLoaded(dropper).then(() => {
EventUtils.synthesizeMouse(target, 30, 30, { type: "mousemove" }, win);
EventUtils.synthesizeMouse(target, 30, 30, {}, win);
});
}

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

@ -4,10 +4,11 @@
const TEST_BASE = "chrome://mochitests/content/browser/browser/devtools/eyedropper/test/";
const TEST_HOST = 'mochi.test:8888';
const promise = Cu.import("resource://gre/modules/devtools/deprecated-sync-thenables.js").Promise;
const require = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools.require;
const { Eyedropper } = require("devtools/eyedropper/eyedropper");
let { devtools } = Components.utils.import("resource://gre/modules/devtools/Loader.jsm", {});
const { Eyedropper, EyedropperManager } = devtools.require("devtools/eyedropper/eyedropper");
let testDir = gTestPath.substr(0, gTestPath.lastIndexOf("/"));
Services.scriptloader.loadSubScript(testDir + "../../../commandline/test/helpers.js", this);
waitForExplicitFinish();
@ -35,3 +36,10 @@ function addTab(uri) {
return deferred.promise;
}
function dropperLoaded(dropper) {
if (dropper.loaded) {
return promise.resolve();
}
return dropper.once("load");
}

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

@ -573,7 +573,8 @@ Toolbox.prototype = {
"command-button-responsive",
"command-button-paintflashing",
"command-button-tilt",
"command-button-scratchpad"
"command-button-scratchpad",
"command-button-eyedropper"
].map(id => {
let button = this.doc.getElementById(id);
// Some buttons may not exist inside of Browser Toolbox

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

@ -128,6 +128,7 @@ Tools.inspector = {
commands: [
"devtools/resize-commands",
"devtools/inspector/inspector-commands",
"devtools/eyedropper/commands.js"
],
preventClosingOnKey: true,

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

@ -693,7 +693,7 @@ Tooltip.prototype = {
let iframe = this.doc.createElementNS(XHTML_NS, "iframe");
iframe.setAttribute("transparent", true);
iframe.setAttribute("width", "210");
iframe.setAttribute("height", "220");
iframe.setAttribute("height", "216");
iframe.setAttribute("flex", "1");
iframe.setAttribute("class", "devtools-tooltip-iframe");

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

@ -19,6 +19,6 @@
</head>
<body role="application">
<div id="spectrum"></div>
<button id="eyedropper-button"></button>
<div id="eyedropper-button"></div>
</body>
</html>

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

@ -3,17 +3,40 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#eyedropper-button {
background: url("chrome://browser/skin/devtools/eyedropper-black.png") no-repeat center;
width: 20px;
height: 20px;
-moz-margin-start: 6px;
border: 1px solid #ccc;
background-image: url("chrome://browser/skin/devtools/command-eyedropper.png");
width: 16px;
height: 16px;
background-size: 64px 16px;
background-position: 0 center;
background-repeat: no-repeat;
-moz-margin-start: 5px;
border-radius: 2px;
cursor: pointer;
}
.theme-light #eyedropper-button {
filter: url(chrome://browser/skin/devtools/filters.svg#invert);
border: 1px solid #AAA;
}
.theme-dark #eyedropper-button {
filter: url(chrome://browser/skin/devtools/filters.svg#colorpicker-invert);
border: 1px solid #444;
}
#eyedropper-button:hover {
background-position: -16px center;
}
#eyedropper-button:hover:active {
background-position: -32px center;
}
#eyedropper-button[checked=true] {
background-position: -48px center;
}
@media (min-resolution: 2dppx) {
#eyedropper-button {
background-image: url("chrome://browser/skin/devtools/command-eyedropper@2x.png");
}
}
/* Mix-in classes */

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

@ -170,7 +170,6 @@
@BINPATH@/components/composer.xpt
@BINPATH@/components/content_base.xpt
@BINPATH@/components/content_events.xpt
@BINPATH@/components/content_canvas.xpt
@BINPATH@/components/content_htmldoc.xpt
@BINPATH@/components/content_html.xpt
#ifdef MOZ_WEBRTC

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

@ -430,6 +430,30 @@ FunctionEnd
WriteRegStr SHCTX "$0\.xhtml" "" "FirefoxHTML"
${EndIf}
; Only add .oga if it's not present
${CheckIfRegistryKeyExists} "$0" ".oga" $7
${If} $7 == "false"
WriteRegStr SHCTX "$0\.oga" "" "FirefoxHTML"
${EndIf}
; Only add .ogg if it's not present
${CheckIfRegistryKeyExists} "$0" ".ogg" $7
${If} $7 == "false"
WriteRegStr SHCTX "$0\.ogg" "" "FirefoxHTML"
${EndIf}
; Only add .ogv if it's not present
${CheckIfRegistryKeyExists} "$0" ".ogv" $7
${If} $7 == "false"
WriteRegStr SHCTX "$0\.ogv" "" "FirefoxHTML"
${EndIf}
; Only add .pdf if it's not present
${CheckIfRegistryKeyExists} "$0" ".pdf" $7
${If} $7 == "false"
WriteRegStr SHCTX "$0\.pdf" "" "FirefoxHTML"
${EndIf}
; Only add webm if it's not present
${CheckIfRegistryKeyExists} "$0" ".webm" $7
${If} $7 == "false"

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

@ -324,6 +324,10 @@ Section "Uninstall"
${un.RegCleanFileHandler} ".shtml" "FirefoxHTML"
${un.RegCleanFileHandler} ".xht" "FirefoxHTML"
${un.RegCleanFileHandler} ".xhtml" "FirefoxHTML"
${un.RegCleanFileHandler} ".oga" "FirefoxHTML"
${un.RegCleanFileHandler} ".ogg" "FirefoxHTML"
${un.RegCleanFileHandler} ".ogv" "FirefoxHTML"
${un.RegCleanFileHandler} ".pdf" "FirefoxHTML"
${un.RegCleanFileHandler} ".webm" "FirefoxHTML"
${EndIf}

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

@ -165,6 +165,20 @@ inspectNodeDesc=CSS selector
# on what it does.
inspectNodeManual=A CSS selector for use with document.querySelector which identifies a single element
# LOCALIZATION NOTE (eyedropperDesc) A very short description of the 'eyedropper'
# command. See eyedropperManual for a fuller description of what it does. This
# string is designed to be shown in a menu alongside the command name, which
# is why it should be as short as possible.
eyedropperDesc=Grab a color from the page
# LOCALIZATION NOTE (eyedropperManual) A fuller description of the 'eyedropper'
# command, displayed when the user asks for help on what it does.
eyedropperManual=Open a panel that magnifies an area of page to inspect pixels and copy color values
# LOCALIZATION NOTE (eyedropperTooltip) A string displayed as the
# tooltip of button in devtools toolbox which toggles the Eyedropper tool.
eyedropperTooltip=Grab a color from the page
# LOCALIZATION NOTE (tiltDesc) A very short description of the 'tilt'
# command. See tiltManual for a fuller description of what it does. This
# string is designed to be shown in a menu alongside the command name, which

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

@ -0,0 +1,149 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
this.EXPORTED_SYMBOLS = [
"ContentSearch",
];
const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
Cu.import("resource://gre/modules/Services.jsm");
const INBOUND_MESSAGE = "ContentSearch";
const OUTBOUND_MESSAGE = INBOUND_MESSAGE;
/**
* ContentSearch receives messages named INBOUND_MESSAGE and sends messages
* named OUTBOUND_MESSAGE. The data of each message is expected to look like
* { type, data }. type is the message's type (or subtype if you consider the
* type of the message itself to be INBOUND_MESSAGE), and data is data that is
* specific to the type.
*
* Inbound messages have the following types:
*
* GetState
* Retrieves the current search engine state.
* data: null
* ManageEngines
* Opens the search engine management window.
* data: null
* Search
* Performs a search.
* data: an object { engineName, searchString, whence }
* SetCurrentEngine
* Sets the current engine.
* data: the name of the engine
*
* Outbound messages have the following types:
*
* CurrentEngine
* Sent when the current engine changes.
* data: see _currentEngineObj
* State
* Sent in reply to GetState and when the state changes.
* data: see _currentStateObj
*/
this.ContentSearch = {
init: function () {
Cc["@mozilla.org/globalmessagemanager;1"].
getService(Ci.nsIMessageListenerManager).
addMessageListener(INBOUND_MESSAGE, this);
Services.obs.addObserver(this, "browser-search-engine-modified", false);
},
receiveMessage: function (msg) {
let methodName = "on" + msg.data.type;
if (methodName in this) {
this[methodName](msg, msg.data.data);
}
},
onGetState: function (msg, data) {
this._reply(msg, "State", this._currentStateObj());
},
onSearch: function (msg, data) {
let expectedDataProps = [
"engineName",
"searchString",
"whence",
];
for (let prop of expectedDataProps) {
if (!(prop in data)) {
Cu.reportError("Message data missing required property: " + prop);
return;
}
}
let browserWin = msg.target.ownerDocument.defaultView;
let engine = Services.search.getEngineByName(data.engineName);
browserWin.BrowserSearch.recordSearchInHealthReport(engine, data.whence);
let submission = engine.getSubmission(data.searchString, "", data.whence);
browserWin.loadURI(submission.uri.spec, null, submission.postData);
},
onSetCurrentEngine: function (msg, data) {
Services.search.currentEngine = Services.search.getEngineByName(data);
},
onManageEngines: function (msg, data) {
let browserWin = msg.target.ownerDocument.defaultView;
browserWin.BrowserSearch.searchBar.openManager(null);
},
observe: function (subj, topic, data) {
switch (topic) {
case "browser-search-engine-modified":
if (data == "engine-current") {
this._broadcast("CurrentEngine", this._currentEngineObj());
}
else if (data != "engine-default") {
// engine-default is always sent with engine-current and isn't otherwise
// relevant to content searches.
this._broadcast("State", this._currentStateObj());
}
break;
}
},
_reply: function (msg, type, data) {
msg.target.messageManager.sendAsyncMessage(...this._msgArgs(type, data));
},
_broadcast: function (type, data) {
Cc["@mozilla.org/globalmessagemanager;1"].
getService(Ci.nsIMessageListenerManager).
broadcastAsyncMessage(...this._msgArgs(type, data));
},
_msgArgs: function (type, data) {
return [OUTBOUND_MESSAGE, {
type: type,
data: data,
}];
},
_currentStateObj: function () {
return {
engines: Services.search.getVisibleEngines().map(engine => {
return {
name: engine.name,
iconURI: engine.getIconURLBySize(16, 16),
};
}),
currentEngine: this._currentEngineObj(),
};
},
_currentEngineObj: function () {
return {
name: Services.search.currentEngine.name,
logoURI: Services.search.currentEngine.getIconURLBySize(65, 26),
logo2xURI: Services.search.currentEngine.getIconURLBySize(130, 52),
};
},
};

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

@ -11,6 +11,7 @@ EXTRA_JS_MODULES += [
'BrowserUITelemetry.jsm',
'ContentClick.jsm',
'ContentLinkHandler.jsm',
'ContentSearch.jsm',
'CustomizationTabPreloader.jsm',
'Feeds.jsm',
'NetworkPrioritizer.jsm',

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

@ -1,10 +1,12 @@
[DEFAULT]
support-files =
head.js
uitour.*
contentSearch.js
image.png
uitour.*
[browser_BrowserUITelemetry_buckets.js]
[browser_ContentSearch.js]
[browser_NetworkPrioritizer.js]
skip-if = e10s # Bug 666804 - Support NetworkPrioritizer in e10s
[browser_SignInToWebsite.js]

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

@ -0,0 +1,240 @@
/* 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/. */
const TEST_MSG = "ContentSearchTest";
const CONTENT_SEARCH_MSG = "ContentSearch";
const TEST_CONTENT_SCRIPT_BASENAME = "contentSearch.js";
function generatorTest() {
// nextStep() drives the iterator returned by this function. This function's
// iterator in turn drives the iterator of each test below.
let currentTestIter = yield startNextTest();
let arg = undefined;
while (currentTestIter) {
try {
currentTestIter.send(arg);
arg = yield null;
}
catch (err if err instanceof StopIteration) {
currentTestIter = yield startNextTest();
arg = undefined;
}
}
}
function startNextTest() {
if (!gTests.length) {
setTimeout(() => nextStep(null), 0);
return;
}
let nextTestGen = gTests.shift();
let nextTestIter = nextTestGen();
addTab(() => {
info("Starting test " + nextTestGen.name);
nextStep(nextTestIter);
});
}
function addTest(testGen) {
gTests.push(testGen);
}
var gTests = [];
var gMsgMan;
addTest(function GetState() {
gMsgMan.sendAsyncMessage(TEST_MSG, {
type: "GetState",
});
let msg = yield waitForTestMsg("State");
checkMsg(msg, {
type: "State",
data: currentStateObj(),
});
});
addTest(function SetCurrentEngine() {
let newCurrentEngine = null;
let oldCurrentEngine = Services.search.currentEngine;
let engines = Services.search.getVisibleEngines();
for (let engine of engines) {
if (engine != oldCurrentEngine) {
newCurrentEngine = engine;
break;
}
}
if (!newCurrentEngine) {
info("Couldn't find a non-selected search engine, " +
"skipping this part of the test");
return;
}
gMsgMan.sendAsyncMessage(TEST_MSG, {
type: "SetCurrentEngine",
data: newCurrentEngine.name,
});
Services.obs.addObserver(function obs(subj, topic, data) {
info("Test observed " + data);
if (data == "engine-current") {
ok(true, "Test observed engine-current");
Services.obs.removeObserver(obs, "browser-search-engine-modified", false);
nextStep();
}
}, "browser-search-engine-modified", false);
info("Waiting for test to observe engine-current...");
waitForTestMsg("CurrentEngine");
let maybeMsg1 = yield null;
let maybeMsg2 = yield null;
let msg = maybeMsg1 || maybeMsg2;
ok(!!msg,
"Sanity check: One of the yields is for waitForTestMsg and should have " +
"therefore produced a message object");
checkMsg(msg, {
type: "CurrentEngine",
data: currentEngineObj(newCurrentEngine),
});
Services.search.currentEngine = oldCurrentEngine;
let msg = yield waitForTestMsg("CurrentEngine");
checkMsg(msg, {
type: "CurrentEngine",
data: currentEngineObj(oldCurrentEngine),
});
});
addTest(function ManageEngines() {
gMsgMan.sendAsyncMessage(TEST_MSG, {
type: "ManageEngines",
});
let winWatcher = Cc["@mozilla.org/embedcomp/window-watcher;1"].
getService(Ci.nsIWindowWatcher);
winWatcher.registerNotification(function onOpen(subj, topic, data) {
if (topic == "domwindowopened" && subj instanceof Ci.nsIDOMWindow) {
subj.addEventListener("load", function onLoad() {
subj.removeEventListener("load", onLoad);
if (subj.document.documentURI ==
"chrome://browser/content/search/engineManager.xul") {
winWatcher.unregisterNotification(onOpen);
ok(true, "Observed search manager window open");
is(subj.opener, window,
"Search engine manager opener should be this chrome window");
subj.close();
nextStep();
}
});
}
});
info("Waiting for search engine manager window to open...");
yield null;
});
addTest(function modifyEngine() {
let engine = Services.search.currentEngine;
let oldAlias = engine.alias;
engine.alias = "ContentSearchTest";
let msg = yield waitForTestMsg("State");
checkMsg(msg, {
type: "State",
data: currentStateObj(),
});
engine.alias = oldAlias;
msg = yield waitForTestMsg("State");
checkMsg(msg, {
type: "State",
data: currentStateObj(),
});
});
addTest(function search() {
let engine = Services.search.currentEngine;
let data = {
engineName: engine.name,
searchString: "ContentSearchTest",
whence: "ContentSearchTest",
};
gMsgMan.sendAsyncMessage(TEST_MSG, {
type: "Search",
data: data,
});
let submissionURL =
engine.getSubmission(data.searchString, "", data.whence).uri.spec;
let listener = {
onStateChange: function (webProg, req, flags, status) {
let url = req.originalURI.spec;
info("onStateChange " + url);
let docStart = Ci.nsIWebProgressListener.STATE_IS_DOCUMENT |
Ci.nsIWebProgressListener.STATE_START;
if ((flags & docStart) && webProg.isTopLevel && url == submissionURL) {
gBrowser.removeProgressListener(listener);
ok(true, "Search URL loaded");
req.cancel(Components.results.NS_ERROR_FAILURE);
nextStep();
}
}
};
gBrowser.addProgressListener(listener);
info("Waiting for search URL to load: " + submissionURL);
yield null;
});
function checkMsg(actualMsg, expectedMsgData) {
SimpleTest.isDeeply(actualMsg.data, expectedMsgData, "Checking message");
}
function waitForMsg(name, type, callback) {
info("Waiting for " + name + " message " + type + "...");
gMsgMan.addMessageListener(name, function onMsg(msg) {
info("Received " + name + " message " + msg.data.type + "\n");
if (msg.data.type == type) {
gMsgMan.removeMessageListener(name, onMsg);
(callback || nextStep)(msg);
}
});
}
function waitForTestMsg(type, callback) {
waitForMsg(TEST_MSG, type, callback);
}
function addTab(onLoad) {
let tab = gBrowser.addTab();
gBrowser.selectedTab = tab;
tab.linkedBrowser.addEventListener("load", function load() {
tab.removeEventListener("load", load, true);
let url = getRootDirectory(gTestPath) + TEST_CONTENT_SCRIPT_BASENAME;
gMsgMan = tab.linkedBrowser.messageManager;
gMsgMan.sendAsyncMessage(CONTENT_SEARCH_MSG, {
type: "AddToWhitelist",
data: ["about:blank"],
});
waitForMsg(CONTENT_SEARCH_MSG, "AddToWhitelistAck", () => {
gMsgMan.loadFrameScript(url, false);
onLoad();
});
}, true);
registerCleanupFunction(() => gBrowser.removeTab(tab));
}
function currentStateObj() {
return {
engines: Services.search.getVisibleEngines().map(engine => {
return {
name: engine.name,
iconURI: engine.getIconURLBySize(16, 16),
};
}),
currentEngine: currentEngineObj(),
};
}
function currentEngineObj(expectedCurrentEngine) {
if (expectedCurrentEngine) {
is(Services.search.currentEngine.name, expectedCurrentEngine.name,
"Sanity check: expected current engine");
}
return {
name: Services.search.currentEngine.name,
logoURI: Services.search.currentEngine.getIconURLBySize(65, 26),
logo2xURI: Services.search.currentEngine.getIconURLBySize(130, 52),
};
}

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

@ -0,0 +1,21 @@
/* 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/. */
const TEST_MSG = "ContentSearchTest";
const SERVICE_EVENT_TYPE = "ContentSearchService";
const CLIENT_EVENT_TYPE = "ContentSearchClient";
// Forward events from the in-content service to the test.
content.addEventListener(SERVICE_EVENT_TYPE, event => {
sendAsyncMessage(TEST_MSG, event.detail);
});
// Forward messages from the test to the in-content service.
addMessageListener(TEST_MSG, msg => {
content.dispatchEvent(
new content.CustomEvent(CLIENT_EVENT_TYPE, {
detail: msg.data,
})
);
});

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

@ -199,6 +199,8 @@ browser.jar:
skin/classic/browser/devtools/command-pick@2x.png (../shared/devtools/images/command-pick@2x.png)
skin/classic/browser/devtools/command-console.png (../shared/devtools/images/command-console.png)
skin/classic/browser/devtools/command-console@2x.png (../shared/devtools/images/command-console@2x.png)
skin/classic/browser/devtools/command-eyedropper.png (../shared/devtools/images/command-eyedropper.png)
skin/classic/browser/devtools/command-eyedropper@2x.png (../shared/devtools/images/command-eyedropper@2x.png)
skin/classic/browser/devtools/alerticon-warning.png (devtools/alerticon-warning.png)
* skin/classic/browser/devtools/ruleview.css (../shared/devtools/ruleview.css)
* skin/classic/browser/devtools/webconsole.css (devtools/webconsole.css)
@ -297,7 +299,6 @@ browser.jar:
skin/classic/browser/devtools/app-manager/rocket.svg (../shared/devtools/app-manager/images/rocket.svg)
skin/classic/browser/devtools/app-manager/noise.png (../shared/devtools/app-manager/images/noise.png)
skin/classic/browser/devtools/app-manager/default-app-icon.png (../shared/devtools/app-manager/images/default-app-icon.png)
skin/classic/browser/devtools/eyedropper-black.png (../shared/devtools/images/eyedropper-black.png)
#ifdef MOZ_SERVICES_SYNC
skin/classic/browser/sync-16.png
skin/classic/browser/sync-32.png

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

@ -320,6 +320,8 @@ browser.jar:
skin/classic/browser/devtools/command-pick@2x.png (../shared/devtools/images/command-pick@2x.png)
skin/classic/browser/devtools/command-console.png (../shared/devtools/images/command-console.png)
skin/classic/browser/devtools/command-console@2x.png (../shared/devtools/images/command-console@2x.png)
skin/classic/browser/devtools/command-eyedropper.png (../shared/devtools/images/command-eyedropper.png)
skin/classic/browser/devtools/command-eyedropper@2x.png (../shared/devtools/images/command-eyedropper@2x.png)
skin/classic/browser/devtools/alerticon-warning.png (devtools/alerticon-warning.png)
* skin/classic/browser/devtools/ruleview.css (../shared/devtools/ruleview.css)
skin/classic/browser/devtools/commandline.css (devtools/commandline.css)
@ -418,7 +420,6 @@ browser.jar:
skin/classic/browser/devtools/app-manager/rocket.svg (../shared/devtools/app-manager/images/rocket.svg)
skin/classic/browser/devtools/app-manager/noise.png (../shared/devtools/app-manager/images/noise.png)
skin/classic/browser/devtools/app-manager/default-app-icon.png (../shared/devtools/app-manager/images/default-app-icon.png)
skin/classic/browser/devtools/eyedropper-black.png (../shared/devtools/images/eyedropper-black.png)
#ifdef MOZ_SERVICES_SYNC
skin/classic/browser/sync-16.png

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

@ -6,11 +6,4 @@
<feFuncB type="table" tableValues=".1 0"/>
</feComponentTransfer>
</filter>
<filter id="colorpicker-invert" x="0%" y="0%" width="100%" height="100%" >
<feComponentTransfer>
<feFuncR type="table" tableValues=".6 0"/>
<feFuncG type="table" tableValues=".6 0"/>
<feFuncB type="table" tableValues=".6 0"/>
</feComponentTransfer>
</filter>
</svg>

До

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

После

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

Двоичные данные
browser/themes/shared/devtools/images/command-eyedropper.png Normal file

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

После

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

Двоичные данные
browser/themes/shared/devtools/images/command-eyedropper@2x.png Normal file

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

После

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

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

До

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

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

@ -580,6 +580,9 @@
background-image: url("chrome://browser/skin/devtools/command-console.png");
}
#command-button-eyedropper > image {
background-image: url("chrome://browser/skin/devtools/command-eyedropper.png");
}
@media (min-resolution: 2dppx) {
#command-button-paintflashing > image {
@ -605,6 +608,10 @@
#command-button-splitconsole > image {
background-image: url("chrome://browser/skin/devtools/command-console@2x.png");
}
#command-button-eyedropper > image {
background-image: url("chrome://browser/skin/devtools/command-eyedropper@2x.png");
}
}
/* Tabs */

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

@ -239,6 +239,8 @@ browser.jar:
skin/classic/browser/devtools/command-pick@2x.png (../shared/devtools/images/command-pick@2x.png)
skin/classic/browser/devtools/command-console.png (../shared/devtools/images/command-console.png)
skin/classic/browser/devtools/command-console@2x.png (../shared/devtools/images/command-console@2x.png)
skin/classic/browser/devtools/command-eyedropper.png (../shared/devtools/images/command-eyedropper.png)
skin/classic/browser/devtools/command-eyedropper@2x.png (../shared/devtools/images/command-eyedropper@2x.png)
skin/classic/browser/devtools/markup-view.css (../shared/devtools/markup-view.css)
skin/classic/browser/devtools/editor-error.png (devtools/editor-error.png)
skin/classic/browser/devtools/editor-breakpoint.png (devtools/editor-breakpoint.png)
@ -333,7 +335,6 @@ browser.jar:
skin/classic/browser/devtools/app-manager/rocket.svg (../shared/devtools/app-manager/images/rocket.svg)
skin/classic/browser/devtools/app-manager/noise.png (../shared/devtools/app-manager/images/noise.png)
skin/classic/browser/devtools/app-manager/default-app-icon.png (../shared/devtools/app-manager/images/default-app-icon.png)
skin/classic/browser/devtools/eyedropper-black.png (../shared/devtools/images/eyedropper-black.png)
#ifdef MOZ_SERVICES_SYNC
skin/classic/browser/sync-16.png
@ -599,6 +600,8 @@ browser.jar:
skin/classic/aero/browser/devtools/command-pick@2x.png (../shared/devtools/images/command-pick@2x.png)
skin/classic/aero/browser/devtools/command-console.png (../shared/devtools/images/command-console.png)
skin/classic/aero/browser/devtools/command-console@2x.png (../shared/devtools/images/command-console@2x.png)
skin/classic/aero/browser/devtools/command-eyedropper.png (../shared/devtools/images/command-eyedropper.png)
skin/classic/aero/browser/devtools/command-eyedropper@2x.png (../shared/devtools/images/command-eyedropper@2x.png)
skin/classic/aero/browser/devtools/alerticon-warning.png (devtools/alerticon-warning.png)
* skin/classic/aero/browser/devtools/ruleview.css (../shared/devtools/ruleview.css)
skin/classic/aero/browser/devtools/commandline.css (devtools/commandline.css)
@ -695,8 +698,6 @@ browser.jar:
skin/classic/aero/browser/devtools/app-manager/rocket.svg (../shared/devtools/app-manager/images/rocket.svg)
skin/classic/aero/browser/devtools/app-manager/noise.png (../shared/devtools/app-manager/images/noise.png)
skin/classic/aero/browser/devtools/app-manager/default-app-icon.png (../shared/devtools/app-manager/images/default-app-icon.png)
skin/classic/aero/browser/devtools/eyedropper-black.png (../shared/devtools/images/eyedropper-black.png)
#ifdef MOZ_SERVICES_SYNC
skin/classic/aero/browser/sync-16.png
skin/classic/aero/browser/sync-32.png

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

@ -109,12 +109,12 @@ template<class T> class nsReadingIterator;
namespace mozilla {
class ErrorResult;
class EventListenerManager;
class Selection;
namespace dom {
class DocumentFragment;
class Element;
class EventTarget;
class Selection;
} // namespace dom
namespace layers {
@ -2086,7 +2086,7 @@ public:
* @param aOutStartOffset Output start offset
* @param aOutEndOffset Output end offset
*/
static void GetSelectionInTextControl(mozilla::Selection* aSelection,
static void GetSelectionInTextControl(mozilla::dom::Selection* aSelection,
Element* aRoot,
int32_t& aOutStartOffset,
int32_t& aOutEndOffset);

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

@ -331,7 +331,7 @@ interface nsIXMLHttpRequest : nsISupports
readonly attribute boolean mozSystem;
};
[scriptable, uuid(840d0d00-e83e-4a29-b3c7-67e96e90a499)]
[uuid(840d0d00-e83e-4a29-b3c7-67e96e90a499)]
interface nsIXHRSendable : nsISupports {
void getSendInfo(out nsIInputStream body,
out uint64_t contentLength,

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

@ -50,7 +50,7 @@
#include "mozilla/Likely.h"
#include "mozilla/MouseEvents.h"
#include "mozilla/Preferences.h"
#include "mozilla/Selection.h"
#include "mozilla/dom/Selection.h"
#include "mozilla/TextEvents.h"
#include "nsAString.h"
#include "nsAttrName.h"

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

@ -49,7 +49,7 @@
#include "mozilla/dom/Element.h"
#include "mozilla/EventDispatcher.h"
#include "mozilla/Preferences.h"
#include "mozilla/Selection.h"
#include "mozilla/dom/Selection.h"
using namespace mozilla;
using namespace mozilla::dom;

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

@ -38,7 +38,7 @@
#include "nsIScriptContext.h"
#include "nsIScriptGlobalObject.h"
#include "nsIScriptSecurityManager.h"
#include "mozilla/Selection.h"
#include "mozilla/dom/Selection.h"
#include "nsISelectionPrivate.h"
#include "nsITransferable.h" // for kUnicodeMime
#include "nsContentUtils.h"

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

@ -4,12 +4,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/.
XPIDL_SOURCES += [
'nsICanvasGLPrivate.idl',
]
XPIDL_MODULE = 'content_canvas'
EXPORTS += [
'nsICanvasRenderingContextInternal.h',
]

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

@ -1,20 +0,0 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
#include "nsISupports.idl"
/* These are private interface that's used to identify
* specific concrete classes so we know what we can cast.
*/
[scriptable, uuid(eba2aa03-ae19-46e2-bad7-6b966037e22c)]
interface nsICanvasGLBuffer : nsISupports
{
};
[scriptable, uuid(27310aab-1988-43e8-882e-6293c8c9df60)]
interface nsICanvasGLTexture : nsISupports
{
};

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

@ -12,8 +12,7 @@
* which implements the phonetic interface.
*/
[scriptable, uuid(BC6EA726-AB56-46b6-A21A-AA7B76D6818F)]
[uuid(BC6EA726-AB56-46b6-A21A-AA7B76D6818F)]
interface nsIPhonetic : nsISupports
{
/**

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

@ -35,7 +35,7 @@
#include "nsServiceManagerUtils.h"
#include "nsIEditor.h"
#include "nsTextEditRules.h"
#include "mozilla/Selection.h"
#include "mozilla/dom/Selection.h"
#include "mozilla/EventListenerManager.h"
#include "nsContentUtils.h"
#include "mozilla/Preferences.h"

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

@ -234,7 +234,7 @@ public:
{
// Deprecated
}
mozilla::Selection* GetSelection(mozilla::ErrorResult& aRv);
mozilla::dom::Selection* GetSelection(mozilla::ErrorResult& aRv);
// The XPCOM CaptureEvents works fine for us.
// The XPCOM ReleaseEvents works fine for us.
// We're picking up GetLocation from Document

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

@ -2485,8 +2485,6 @@ XULDocument::PrepareToWalk()
// Block onload until we've finished building the complete
// document content model.
BlockOnload();
nsContentSink::NotifyDocElementCreated(this);
}
// There'd better not be anything on the context stack at this

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

@ -5,7 +5,6 @@ support-files =
overlay2_bug335375.xul
window_bug583948.xul
window_bug757137.xul
window_documentnotification.xul
[test_bug199692.xul]
[test_bug311681.xul]
@ -21,4 +20,3 @@ support-files =
[test_bug583948.xul]
[test_bug640158_overlay_persist.xul]
[test_bug757137.xul]
[test_documentnotification.xul]

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

@ -1,40 +0,0 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
type="text/css"?>
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
<body xmlns="http://www.w3.org/1999/xhtml">
<div id="content" style="display: none"/>
</body>
<script>
SimpleTest.waitForExplicitFinish();
var seenNotification = false;
function notify(subject, topic, data) {
seenNotification = true;
is(topic, "document-element-inserted", "Should be the right notification");
is(subject, otherWindow.document, "Should have been notified about the right window");
ok(subject.documentElement, "documentElement should be defined");
}
var obs = Components.classes["@mozilla.org/observer-service;1"].
getService(Components.interfaces.nsIObserverService)
obs.addObserver(notify, "document-element-inserted", false);
var otherWindow = window.open("window_documentnotification.xul", "_new", "chrome");
otherWindow.addEventListener("load", function() {
ok(seenNotification, "Should have seen the document-element-inserted")
obs.removeObserver(notify, "document-element-inserted");
window.close();
SimpleTest.waitForFocus(function() {
SimpleTest.finish();
});
});
</script>
</window>

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

@ -1,6 +0,0 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<label value="window_documentnotification.xul"/>
</window>

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

@ -10871,21 +10871,31 @@ nsDocShell::AddState(JS::Handle<JS::Value> aData, const nsAString& aTitle,
// Step 5: If aReplace is false, indicating that we're doing a pushState
// rather than a replaceState, notify bfcache that we've added a page to
// the history so it can evict content viewers if appropriate.
// the history so it can evict content viewers if appropriate. Otherwise
// call ReplaceEntry so that we notify nsIHistoryListeners that an entry
// was replaced.
nsCOMPtr<nsISHistory> rootSH;
GetRootSessionHistory(getter_AddRefs(rootSH));
NS_ENSURE_TRUE(rootSH, NS_ERROR_UNEXPECTED);
nsCOMPtr<nsISHistoryInternal> internalSH =
do_QueryInterface(rootSH);
NS_ENSURE_TRUE(internalSH, NS_ERROR_UNEXPECTED);
if (!aReplace) {
nsCOMPtr<nsISHistory> rootSH;
GetRootSessionHistory(getter_AddRefs(rootSH));
NS_ENSURE_TRUE(rootSH, NS_ERROR_UNEXPECTED);
nsCOMPtr<nsISHistoryInternal> internalSH =
do_QueryInterface(rootSH);
NS_ENSURE_TRUE(internalSH, NS_ERROR_UNEXPECTED);
int32_t curIndex = -1;
rv = rootSH->GetIndex(&curIndex);
if (NS_SUCCEEDED(rv) && curIndex > -1) {
internalSH->EvictOutOfRangeContentViewers(curIndex);
}
} else {
nsCOMPtr<nsISHEntry> rootSHEntry = GetRootSHEntry(newSHEntry);
int32_t index = -1;
rv = rootSH->GetIndexOfEntry(rootSHEntry, &index);
if (NS_SUCCEEDED(rv) && index > -1) {
internalSH->ReplaceEntry(index, rootSHEntry);
}
}
// Step 6: If the document's URI changed, update document's URI and update

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

@ -22,12 +22,12 @@ interface nsISimpleEnumerator;
%{C++
#define NS_SHISTORY_CID \
{0x7294fe9c, 0x14d8, 0x11d5, {0x98, 0x82, 0x00, 0xC0, 0x4f, 0xa0, 0x2f, 0x40}}
{0x7b807041, 0xe60a, 0x4384, {0x93, 0x5f, 0xaf, 0x30, 0x61, 0xd8, 0xb8, 0x15}}
#define NS_SHISTORY_CONTRACTID "@mozilla.org/browser/shistory;1"
%}
[scriptable, uuid(b4440e2e-0fc2-11e3-971f-59e799890b3c)]
[scriptable, uuid(7b807041-e60a-4384-935f-af3061d8b815)]
interface nsISHistory: nsISupports
{
/**
@ -147,4 +147,16 @@ interface nsISHistory: nsISupports
readonly attribute nsISimpleEnumerator SHistoryEnumerator;
void reloadCurrentEntry();
/**
* Called to obtain the index to a given history entry.
*
* @param aEntry The entry to obtain the index of.
*
* @return <code>NS_OK</code> index for the history entry
* is obtained successfully.
* <code>NS_ERROR_FAILURE</code> Error in obtaining
* index for the given history entry.
*/
long getIndexOfEntry(in nsISHEntry aEntry);
};

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

@ -21,7 +21,7 @@ interface nsIURI;
* A session history listener can be registered on a particular nsISHistory
* instance via the nsISHistory::addSHistoryListener() method.
*/
[scriptable, uuid(3b07f591-e8e1-11d4-9882-00c04fa02f40)]
[scriptable, uuid(125c0833-746a-400e-9b89-d2d18545c08a)]
interface nsISHistoryListener : nsISupports
{
/**
@ -87,4 +87,14 @@ interface nsISHistoryListener : nsISupports
* @return Whether the operation can proceed.
*/
boolean OnHistoryPurge(in long aNumEntries);
/**
* Called when an entry is replaced in the session history. Entries are
* replaced when navigating away from non-persistent history entries (such as
* about pages) and when history.replaceState is called.
*
* @param aIndex The index in session history of the entry being
* replaced
*/
void OnHistoryReplaceEntry(in long aIndex);
};

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

@ -415,8 +415,11 @@ nsSHistory::AddEntry(nsISHEntry * aSHEntry, bool aPersist)
if(currentTxn)
currentTxn->GetPersist(&currentPersist);
int32_t currentIndex = mIndex;
if(!currentPersist)
{
NOTIFY_LISTENERS(OnHistoryReplaceEntry, (currentIndex));
NS_ENSURE_SUCCESS(currentTxn->SetSHEntry(aSHEntry),NS_ERROR_FAILURE);
currentTxn->SetPersist(aPersist);
return NS_OK;
@ -426,7 +429,6 @@ nsSHistory::AddEntry(nsISHEntry * aSHEntry, bool aPersist)
NS_ENSURE_TRUE(txn, NS_ERROR_FAILURE);
nsCOMPtr<nsIURI> uri;
int32_t currentIndex = mIndex;
aSHEntry->GetURI(getter_AddRefs(uri));
NOTIFY_LISTENERS(OnHistoryNewEntry, (uri));
@ -555,6 +557,50 @@ nsSHistory::GetTransactionAtIndex(int32_t aIndex, nsISHTransaction ** aResult)
return NS_OK;
}
/* Get the index of a given entry */
NS_IMETHODIMP
nsSHistory::GetIndexOfEntry(nsISHEntry* aSHEntry, int32_t* aResult) {
NS_ENSURE_ARG(aSHEntry);
NS_ENSURE_ARG_POINTER(aResult);
*aResult = -1;
if (mLength <= 0) {
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsISHTransaction> currentTxn;
int32_t cnt = 0;
nsresult rv = GetRootTransaction(getter_AddRefs(currentTxn));
if (NS_FAILED(rv) || !currentTxn) {
return NS_ERROR_FAILURE;
}
while (true) {
nsCOMPtr<nsISHEntry> entry;
rv = currentTxn->GetSHEntry(getter_AddRefs(entry));
if (NS_FAILED(rv) || !entry) {
return NS_ERROR_FAILURE;
}
if (aSHEntry == entry) {
*aResult = cnt;
break;
}
rv = currentTxn->GetNext(getter_AddRefs(currentTxn));
if (NS_FAILED(rv) || !currentTxn) {
return NS_ERROR_FAILURE;
}
cnt++;
}
return NS_OK;
}
#ifdef DEBUG
nsresult
nsSHistory::PrintHistory()
@ -734,6 +780,8 @@ nsSHistory::ReplaceEntry(int32_t aIndex, nsISHEntry * aReplaceEntry)
if(currentTxn)
{
NOTIFY_LISTENERS(OnHistoryReplaceEntry, (aIndex));
// Set the replacement entry in the transaction
rv = currentTxn->SetSHEntry(aReplaceEntry);
rv = currentTxn->SetPersist(true);

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

@ -39,6 +39,8 @@ SHistoryListener.prototype = {
return this.retval;
},
OnHistoryReplaceEntry: function (aIndex) {},
QueryInterface: XPCOMUtils.generateQI([Ci.nsISHistoryListener,
Ci.nsISupportsWeakReference])
};

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

@ -39,6 +39,7 @@ function test() {
OnHistoryGoForward: function () true,
OnHistoryGotoIndex: function () true,
OnHistoryPurge: function () true,
OnHistoryReplaceEntry: function () true,
QueryInterface: XPCOMUtils.generateQI([Ci.nsISHistoryListener,
Ci.nsISupportsWeakReference])

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

@ -6,7 +6,7 @@
interface nsIDOMWindow;
[scriptable, uuid(194b55d9-39c0-45c6-b8ef-b8049f978ea5)]
[uuid(194b55d9-39c0-45c6-b8ef-b8049f978ea5)]
interface nsIAudioChannelAgentCallback : nsISupports
{
/**
@ -40,7 +40,7 @@ interface nsIAudioChannelAgentCallback : nsISupports
* 1. Changes to the playable status of this channel.
*/
[scriptable, uuid(2b0222a5-8f7b-49d2-9ab8-cd01b744b23e)]
[uuid(2b0222a5-8f7b-49d2-9ab8-cd01b744b23e)]
interface nsIAudioChannelAgent : nsISupports
{
const long AUDIO_AGENT_CHANNEL_NORMAL = 0;

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

@ -75,7 +75,6 @@
// DOM core includes
#include "nsError.h"
#include "nsIDOMUserDataHandler.h"
#include "nsIDOMXPathNamespace.h"
#include "nsIDOMXULButtonElement.h"
#include "nsIDOMXULCheckboxElement.h"
#include "nsIDOMXULPopupElement.h"
@ -223,7 +222,6 @@ DOMCI_DATA_NO_CLASS(DOMPrototype)
DOMCI_DATA_NO_CLASS(DOMConstructor)
DOMCI_DATA_NO_CLASS(UserDataHandler)
DOMCI_DATA_NO_CLASS(XPathNamespace)
DOMCI_DATA_NO_CLASS(XULControlElement)
DOMCI_DATA_NO_CLASS(XULLabeledControlElement)
DOMCI_DATA_NO_CLASS(XULButtonElement)
@ -448,8 +446,6 @@ static nsDOMClassInfoData sClassInfoData[] = {
NS_DEFINE_CHROME_XBL_CLASSINFO_DATA(UserDataHandler, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(XPathNamespace, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
NS_DEFINE_CHROME_XBL_CLASSINFO_DATA(XULControlElement, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
NS_DEFINE_CHROME_XBL_CLASSINFO_DATA(XULLabeledControlElement, nsDOMGenericSH,
@ -1121,10 +1117,6 @@ nsDOMClassInfo::Init()
DOM_CLASSINFO_MAP_ENTRY(nsIDOMUserDataHandler)
DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(XPathNamespace, nsIDOMXPathNamespace)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMXPathNamespace)
DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(XULControlElement, nsIDOMXULControlElement)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMXULControlElement)
DOM_CLASSINFO_MAP_END
@ -3166,7 +3158,6 @@ const InterfaceShimEntry kInterfaceShimMap[] =
{ "nsIDOMRange", "Range" },
{ "nsIDOMSVGLength", "SVGLength" },
{ "nsIDOMNodeFilter", "NodeFilter" },
{ "nsIDOMXPathNamespace", "XPathNamespace" },
{ "nsIDOMXPathResult", "XPathResult" } };
static nsresult

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

@ -93,7 +93,6 @@ DOMCI_CLASS(CSSPageRule)
DOMCI_CLASS(CSSFontFeatureValuesRule)
DOMCI_CLASS(UserDataHandler)
DOMCI_CLASS(XPathNamespace)
DOMCI_CLASS(XULControlElement)
DOMCI_CLASS(XULLabeledControlElement)
DOMCI_CLASS(XULButtonElement)

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

@ -27,7 +27,7 @@
#include "nsIBaseWindow.h"
#include "nsViewManager.h"
#include "nsFrameSelection.h"
#include "mozilla/Selection.h"
#include "mozilla/dom/Selection.h"
#include "nsXULPopupManager.h"
#include "nsIScriptObjectPrincipal.h"
#include "nsIPrincipal.h"

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

@ -172,7 +172,7 @@
#include "nsIDragService.h"
#include "mozilla/dom/Element.h"
#include "mozilla/Selection.h"
#include "mozilla/dom/Selection.h"
#include "nsFrameLoader.h"
#include "nsISupportsPrimitives.h"
#include "nsXPCOMCID.h"
@ -1607,6 +1607,8 @@ nsGlobalWindow::FreeInnerObjects()
mAudioContexts.Clear();
#ifdef MOZ_GAMEPAD
DisableGamepadUpdates();
mHasGamepad = false;
mGamepads.Clear();
#endif
}

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

@ -104,7 +104,6 @@ class nsWindowSizes;
namespace mozilla {
class DOMEventTargetHelper;
class Selection;
namespace dom {
class BarProp;
class Console;
@ -114,6 +113,7 @@ class Gamepad;
class MediaQueryList;
class Navigator;
class OwningExternalOrWindowProxy;
class Selection;
class SpeechSynthesis;
class WakeLock;
namespace indexedDB {
@ -882,7 +882,7 @@ public:
mozilla::ErrorResult& aError);
nsIDOMStorage* GetSessionStorage(mozilla::ErrorResult& aError);
nsIDOMStorage* GetLocalStorage(mozilla::ErrorResult& aError);
mozilla::Selection* GetSelection(mozilla::ErrorResult& aError);
mozilla::dom::Selection* GetSelection(mozilla::ErrorResult& aError);
mozilla::dom::indexedDB::IDBFactory* GetIndexedDB(mozilla::ErrorResult& aError);
already_AddRefed<nsICSSDeclaration>
GetComputedStyle(mozilla::dom::Element& aElt, const nsAString& aPseudoElt,

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

@ -974,7 +974,6 @@ DOMInterfaces = {
},
'Selection': {
'nativeType': 'mozilla::Selection',
'resultNotAddRefed': [ 'anchorNode', 'focusNode', 'getRangeAt' ],
},

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

@ -276,28 +276,6 @@ KeyboardEvent::InitKeyEvent(const nsAString& aType,
return NS_OK;
}
void
KeyboardEvent::InitKeyboardEvent(const nsAString& aType,
bool aCanBubble,
bool aCancelable,
nsIDOMWindow* aView,
uint32_t aDetail,
const nsAString& aKey,
uint32_t aLocation,
const nsAString& aModifiersList,
bool aRepeat,
ErrorResult& aRv)
{
aRv = UIEvent::InitUIEvent(aType, aCanBubble, aCancelable, aView, aDetail);
WidgetKeyboardEvent* keyEvent = mEvent->AsKeyboardEvent();
keyEvent->modifiers = UIEvent::ComputeModifierState(aModifiersList);
keyEvent->location = aLocation;
keyEvent->mIsRepeat = aRepeat;
keyEvent->mKeyNameIndex = KEY_NAME_INDEX_USE_STRING;
keyEvent->mKeyValue = aKey;
}
} // namespace dom
} // namespace mozilla

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

@ -69,13 +69,6 @@ public:
aKeyCode, aCharCode);
}
void InitKeyboardEvent(const nsAString& aType,
bool aCanBubble, bool aCancelable,
nsIDOMWindow* aView, uint32_t aDetail,
const nsAString& aKey, uint32_t aLocation,
const nsAString& aModifiersList, bool aRepeat,
ErrorResult& aRv);
private:
// True, if the instance is created with Constructor().
bool mInitializedByCtor;

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

@ -20,126 +20,55 @@ SimpleTest.waitForFocus(runTests, window);
function testInitializingUntrustedEvent()
{
const kTests = [
// initKeyEvent
{ createEventArg: "KeyboardEvent", useInitKeyboardEvent: false,
{ createEventArg: "KeyboardEvent",
type: "keydown", bubbles: true, cancelable: true, view: null,
ctrlKey: false, altKey: false, shiftKey: false, metaKey: false,
keyCode: 0x00, charCode: 0x00,
detail: 0, key: "", location: 0, modifiersList: "", repeat: false,
}, // 0
keyCode: 0x00, charCode: 0x00 },
{ createEventArg: "keyboardevent", useInitKeyboardEvent: false,
{ createEventArg: "keyboardevent",
type: "keyup", bubbles: false, cancelable: true, view: window,
ctrlKey: true, altKey: false, shiftKey: false, metaKey: false,
keyCode: 0x10, charCode: 0x00,
detail: 0, key: "", location: 0, modifiersList: "", repeat: false,
}, // 1
keyCode: 0x10, charCode: 0x00 },
{ createEventArg: "Keyboardevent", useInitKeyboardEvent: false,
{ createEventArg: "Keyboardevent",
type: "keypess", bubbles: true, cancelable: false, view: null,
ctrlKey: false, altKey: true, shiftKey: false, metaKey: false,
keyCode: 0x11, charCode: 0x30,
detail: 0, key: "", location: 0, modifiersList: "", repeat: false,
}, // 2
keyCode: 0x11, charCode: 0x30 },
{ createEventArg: "keyboardEvent", useInitKeyboardEvent: false,
{ createEventArg: "keyboardEvent",
type: "boo", bubbles: false, cancelable: false, view: window,
ctrlKey: false, altKey: false, shiftKey: true, metaKey: false,
keyCode: 0x30, charCode: 0x40,
detail: 0, key: "", location: 0, modifiersList: "", repeat: false,
}, // 3
keyCode: 0x30, charCode: 0x40 },
{ createEventArg: "KeyEvents", useInitKeyboardEvent: false,
{ createEventArg: "KeyEvents",
type: "foo", bubbles: true, cancelable: true, view: null,
ctrlKey: false, altKey: false, shiftKey: false, metaKey: true,
keyCode: 0x00, charCode: 0x50,
detail: 0, key: "", location: 0, modifiersList: "", repeat: false,
}, // 4
keyCode: 0x00, charCode: 0x50 },
{ createEventArg: "keyevents", useInitKeyboardEvent: false,
{ createEventArg: "keyevents",
type: "bar", bubbles: false, cancelable: true, view: window,
ctrlKey: true, altKey: true, shiftKey: false, metaKey: false,
keyCode: 0x00, charCode: 0x60,
detail: 0, key: "", location: 0, modifiersList: "", repeat: false,
}, // 5
keyCode: 0x00, charCode: 0x60 },
{ createEventArg: "Keyevents", useInitKeyboardEvent: false,
{ createEventArg: "Keyevents",
type: "keydown", bubbles: true, cancelable: false, view: null,
ctrlKey: false, altKey: true, shiftKey: false, metaKey: true,
keyCode: 0x30, charCode: 0x00,
detail: 0, key: "", location: 0, modifiersList: "", repeat: false,
}, // 6
keyCode: 0x30, charCode: 0x00 },
{ createEventArg: "keyEvents", useInitKeyboardEvent: false,
{ createEventArg: "keyEvents",
type: "keyup", bubbles: false, cancelable: false, view: window,
ctrlKey: true, altKey: false, shiftKey: true, metaKey: false,
keyCode: 0x10, charCode: 0x80,
detail: 0, key: "", location: 0, modifiersList: "", repeat: false,
}, // 7
keyCode: 0x10, charCode: 0x80 },
{ createEventArg: "KeyboardEvent", useInitKeyboardEvent: false,
{ createEventArg: "KeyboardEvent",
type: "keypress", bubbles: false, cancelable: false, view: window,
ctrlKey: true, altKey: false, shiftKey: true, metaKey: true,
keyCode: 0x10, charCode: 0x80,
detail: 0, key: "", location: 0, modifiersList: "", repeat: false,
}, // 8
keyCode: 0x10, charCode: 0x80 },
{ createEventArg: "KeyboardEvent", useInitKeyboardEvent: false,
{ createEventArg: "KeyboardEvent",
type: "foo", bubbles: false, cancelable: false, view: window,
ctrlKey: true, altKey: true, shiftKey: true, metaKey: true,
keyCode: 0x10, charCode: 0x80,
detail: 0, key: "", location: 0, modifiersList: "", repeat: false,
}, // 9
// initKeyboardEvent
{ createEventArg: "KeyboardEvent", useInitKeyboardEvent: true,
type: "keydown", bubbles: true, cancelable: true, view: null,
ctrlKey: false, altKey: false, shiftKey: false, metaKey: false,
keyCode: 0x00, charCode: 0x00,
detail: 0, key: "", location: 0, modifiersList: "", repeat: false,
}, // 10
{ createEventArg: "keyboardevent", useInitKeyboardEvent: true,
type: "keyup", bubbles: false, cancelable: true, view: window,
ctrlKey: true, altKey: false, shiftKey: false, metaKey: false,
keyCode: 0x00, charCode: 0x00,
detail: 2, key: "Unidentified", location: 1, modifiersList: "Control", repeat: false,
}, // 11
{ createEventArg: "Keyboardevent", useInitKeyboardEvent: true,
type: "keypess", bubbles: true, cancelable: false, view: null,
ctrlKey: false, altKey: true, shiftKey: false, metaKey: false,
keyCode: 0x00, charCode: 0x00,
detail: 0, key: "FooBar", location: 2, modifiersList: "Alt", repeat: true,
}, // 12
{ createEventArg: "keyboardevent", useInitKeyboardEvent: true,
type: "foo", bubbles: true, cancelable: true, view: null,
ctrlKey: false, altKey: false, shiftKey: false, metaKey: true,
keyCode: 0x00, charCode: 0x00,
detail: 0, key: "a", location: 0, modifiersList: "Meta", repeat: false,
}, // 13
{ createEventArg: "Keyevents", useInitKeyboardEvent: true,
type: "", bubbles: false, cancelable: false, view: null,
ctrlKey: true, altKey: true, shiftKey: true, metaKey: true,
keyCode: 0x00, charCode: 0x00,
detail: 0, key: "3", location: 0, modifiersList: "Control Alt Meta Shift", repeat: true,
}, // 14
{ createEventArg: "keyevents", useInitKeyboardEvent: true,
type: "", bubbles: false, cancelable: false, view: null,
ctrlKey: false, altKey: false, shiftKey: true, metaKey: false,
keyCode: 0x00, charCode: 0x00,
detail: 0, key: "3", location: 6, modifiersList: "Shift", repeat: true,
}, // 15
{ createEventArg: "keyevents", useInitKeyboardEvent: true,
type: "", bubbles: false, cancelable: false, view: null,
ctrlKey: false, altKey: true, shiftKey: false, metaKey: false,
keyCode: 0x00, charCode: 0x00,
detail: 0, key: "", location: 4, modifiersList: "Shift, Alt", repeat: false,
}, // 16
keyCode: 0x10, charCode: 0x80 },
];
const kOtherModifierName = [
@ -156,23 +85,17 @@ function testInitializingUntrustedEvent()
var description = "testInitializingUntrustedEvent, Index: " + i + ", ";
const kTest = kTests[i];
var e = document.createEvent(kTest.createEventArg);
if (kTest.useInitKeyboardEvent) {
// IE has extra argument for |.locale|. Calling with it shouldn't cause error for compatibility with IE.
e.initKeyboardEvent(kTest.type, kTest.bubbles, kTest.cancelable, kTest.view, kTest.detail,
kTest.key, kTest.location, kTest.modifiersList, kTest.repeat, "locale");
} else {
e.initKeyEvent(kTest.type, kTest.bubbles, kTest.cancelable, kTest.view,
kTest.ctrlKey, kTest.altKey, kTest.shiftKey, kTest.metaKey,
kTest.keyCode, kTest.charCode);
}
e.initKeyEvent(kTest.type, kTest.bubbles, kTest.cancelable, kTest.view,
kTest.ctrlKey, kTest.altKey, kTest.shiftKey, kTest.metaKey,
kTest.keyCode, kTest.charCode);
is(e.toString(), "[object KeyboardEvent]",
description + 'class string should be "KeyboardEvent"');
for (var attr in kTest) {
if (attr == "createEventArg" || attr == "useInitKeyboardEvent" || attr == "modifiersList") {
if (attr == "createEventArg") {
continue;
}
if (!kTest.useInitKeyboardEvent && attr == "keyCode") {
if (attr == "keyCode") {
// If this is keydown, keyup of keypress event, keycod must be correct.
if (kTest.type == "keydown" || kTest.type == "keyup" || kTest.type == "keypress") {
is(e[attr], kTest[attr], description + attr + " returns wrong value");
@ -180,7 +103,7 @@ function testInitializingUntrustedEvent()
} else {
is(e[attr], 0, description + attr + " returns non-zero for invalid event");
}
} else if (!kTest.useInitKeyboardEvent && attr == "charCode") {
} else if (attr == "charCode") {
// If this is keydown or keyup event, charCode always 0.
if (kTest.type == "keydown" || kTest.type == "keyup") {
is(e[attr], 0, description + attr + " returns non-zero for keydown or keyup event");
@ -199,6 +122,9 @@ function testInitializingUntrustedEvent()
}
is(e.isTrusted, false, description + "isTrusted returns wrong value");
// Currently, there is no way to initialize char and key attribute values.
ok(e.key === "", description + "key must return empty string - got " + e.key);
// getModifierState() tests
is(e.getModifierState("Shift"), kTest.shiftKey,
description + "getModifierState(\"Shift\") returns wrong value");

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

@ -37,8 +37,8 @@
[ "Callback message", msg, "Error: hello" ],
[ "Event error-object", errorEvent.error, thrown],
[ "Callback error-object", error, thrown ],
[ "Event column", errorEvent.colno, 0 ], // Sadly not correct right now
[ "Callback column", column, 0 ]
[ "Event column", errorEvent.colno, 6 ], // Sadly not correct right now
[ "Callback column", column, 6 ]
]);
</script>
<script>

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

@ -10,7 +10,7 @@
* collection of DOM window objects.
*/
[scriptable, uuid(a6cf906f-15b3-11d2-932e-00805f8add32)]
[uuid(a6cf906f-15b3-11d2-932e-00805f8add32)]
interface nsIDOMWindowCollection : nsISupports
{
/**

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

@ -8,7 +8,6 @@ XPIDL_SOURCES += [
'nsIDOMNSXPathExpression.idl',
'nsIDOMXPathEvaluator.idl',
'nsIDOMXPathExpression.idl',
'nsIDOMXPathNamespace.idl',
'nsIDOMXPathNSResolver.idl',
'nsIDOMXPathResult.idl',
]

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

@ -1,19 +0,0 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
/**
* Corresponds to http://www.w3.org/TR/2002/WD-DOM-Level-3-XPath-20020208
*/
#include "nsIDOMNode.idl"
[scriptable, uuid(558c2ab9-513e-43c2-afea-4930024b15b3)]
interface nsIDOMXPathNamespace : nsIDOMNode
{
// XPathNodeType
const unsigned short XPATH_NAMESPACE_NODE = 13;
readonly attribute nsIDOMElement ownerElement;
};

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

@ -747,6 +747,7 @@ TabChild::Observe(nsISupports *aSubject,
if (SameCOMIdentity(subject, doc)) {
nsCOMPtr<nsIDOMWindowUtils> utils(GetDOMWindowUtils());
utils->SetIsFirstPaint(true);
mContentDocumentIsDisplayed = true;
@ -810,9 +811,6 @@ TabChild::OnLocationChange(nsIWebProgress* aWebProgress,
return NS_OK;
}
nsCOMPtr<nsIDOMWindowUtils> utils(do_GetInterface(window));
utils->SetIsFirstPaint(true);
nsCOMPtr<nsIDOMDocument> progressDoc;
window->GetDocument(getter_AddRefs(progressDoc));
if (!progressDoc) {

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

@ -584,7 +584,6 @@ exports.browser = {
XPathEvaluator : false,
XPathException : false,
XPathExpression : false,
XPathNamespace : false,
XPathNSResolver : false,
XPathResult : false
};

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