This commit is contained in:
Kyle Huey 2012-08-15 06:25:20 -07:00
Родитель 46e8f55753 762ff5ea6b
Коммит 0cc1845191
501 изменённых файлов: 4348 добавлений и 2807 удалений

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

@ -20,9 +20,6 @@
return NS_OK; \
} else
#define NS_OK_DEFUNCT_OBJECT \
NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_GENERAL, 0x22)
#define NS_ENSURE_A11Y_SUCCESS(res, ret) \
PR_BEGIN_MACRO \
nsresult __rv = res; /* Don't evaluate |res| more than once */ \

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

@ -17,10 +17,6 @@
class Accessible;
class nsIAccessibleTraversalRule;
// raised when current pivot's position is needed but it is not in the tree.
#define NS_ERROR_NOT_IN_TREE \
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_GENERAL, 0x26)
/**
* Class represents an accessible pivot.
*/

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

@ -19,9 +19,6 @@
using namespace mozilla::a11y;
#define NS_OK_NO_NAME_CLAUSE_HANDLED \
NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_GENERAL, 0x24)
////////////////////////////////////////////////////////////////////////////////
// nsTextEquivUtils. Public.

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

@ -78,18 +78,6 @@ class nsIView;
typedef nsRefPtrHashtable<nsPtrHashKey<const void>, Accessible>
AccessibleHashtable;
// see Accessible::GetAttrValue
#define NS_OK_NO_ARIA_VALUE \
NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_GENERAL, 0x21)
// see Accessible::GetNameInternal
#define NS_OK_EMPTY_NAME \
NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_GENERAL, 0x23)
// see Accessible::GetNameInternal
#define NS_OK_NAME_FROM_TOOLTIP \
NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_GENERAL, 0x25)
#define NS_ACCESSIBLE_IMPL_IID \
{ /* 133c8bf4-4913-4355-bd50-426bd1d6e1ad */ \

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

@ -33,7 +33,7 @@
#include "nsITableLayout.h"
#include "nsITableCellLayout.h"
#include "nsFrameSelection.h"
#include "nsLayoutErrors.h"
#include "nsError.h"
#include "nsArrayUtils.h"
#include "nsComponentManagerUtils.h"

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

@ -459,6 +459,11 @@ window[chromehidden~="toolbar"] toolbar:not(.toolbar-primary):not(.chromeclass-m
display: none;
}
#notification-popup .text-link.custom-link {
-moz-binding: url("chrome://global/content/bindings/text.xml#text-label");
text-decoration: none;
}
#invalid-form-popup > description {
max-width: 280px;
}
@ -471,6 +476,10 @@ window[chromehidden~="toolbar"] toolbar:not(.toolbar-primary):not(.chromeclass-m
-moz-binding: url("chrome://browser/content/urlbarBindings.xml#addon-progress-notification");
}
#identity-request-notification {
-moz-binding: url("chrome://browser/content/urlbarBindings.xml#identity-request-notification");
}
/* override hidden="true" for the status bar compatibility shim
in case it was persisted for the real status bar */
#status-bar {

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

@ -564,6 +564,7 @@
onblur="setTimeout(function() document.getElementById('identity-box').style.MozUserFocus = '', 0);">
<box id="notification-popup-box" hidden="true" align="center">
<image id="default-notification-icon" class="notification-anchor-icon" role="button"/>
<image id="identity-notification-icon" class="notification-anchor-icon" role="button"/>
<image id="geo-notification-icon" class="notification-anchor-icon" role="button"/>
<image id="addons-notification-icon" class="notification-anchor-icon" role="button"/>
<image id="indexedDB-notification-icon" class="notification-anchor-icon" role="button"/>

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

@ -78,7 +78,7 @@ function runNextTest() {
onHidden.call(nextTest, this);
if (!onHiddenArray.length)
goNext();
});
}.bind(this));
}, onHiddenArray.length);
info("[Test #" + gTestIndex + "] added listeners; panel state: " + PopupNotifications.isPanelOpen);
}

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

@ -1175,6 +1175,261 @@
</implementation>
</binding>
<binding id="identity-request-notification" extends="chrome://global/content/bindings/notification.xml#popup-notification">
<content align="start">
<xul:image class="popup-notification-icon"
xbl:inherits="popupid,src=icon"/>
<xul:vbox flex="1">
<xul:vbox anonid="identity-deck">
<xul:vbox flex="1" pack="center"> <!-- 1: add an email -->
<html:input type="email" anonid="email" required="required" size="30"/>
<xul:description anonid="newidentitydesc"/>
<xul:spacer flex="1"/>
<xul:label class="text-link custom-link small-margin" anonid="chooseemail" hidden="true"/>
</xul:vbox>
<xul:vbox flex="1" hidden="true"> <!-- 2: choose an email -->
<xul:description anonid="chooseidentitydesc"/>
<xul:radiogroup anonid="identities">
</xul:radiogroup>
<xul:label class="text-link custom-link" anonid="newemail"/>
</xul:vbox>
</xul:vbox>
<xul:hbox class="popup-notification-button-container"
pack="end" align="center">
<xul:label anonid="tos" class="text-link" hidden="true"/>
<xul:label anonid="privacypolicy" class="text-link" hidden="true"/>
<xul:spacer flex="1"/>
<xul:image anonid="throbber" src="chrome://browser/skin/tabbrowser/loading.png"
style="visibility:hidden" width="16" height="16"/>
<xul:button anonid="button"
type="menu-button"
class="popup-notification-menubutton"
xbl:inherits="oncommand=buttoncommand,label=buttonlabel,accesskey=buttonaccesskey">
<xul:menupopup anonid="menupopup"
xbl:inherits="oncommand=menucommand">
<children/>
<xul:menuitem class="menuitem-iconic popup-notification-closeitem"
label="&closeNotificationItem.label;"
xbl:inherits="oncommand=closeitemcommand"/>
</xul:menupopup>
</xul:button>
</xul:hbox>
</xul:vbox>
<xul:vbox pack="start">
<xul:toolbarbutton anonid="closebutton"
class="messageCloseButton popup-notification-closebutton tabbable"
xbl:inherits="oncommand=closebuttoncommand"
tooltiptext="&closeNotification.tooltip;"/>
</xul:vbox>
</content>
<implementation>
<constructor><![CDATA[
// this.notification.options.identity is used to pass identity-specific info to the binding
let origin = this.identity.origin
// Populate text
this.emailField.placeholder = gNavigatorBundle.
getString("identity.newIdentity.email.placeholder");
this.newIdentityDesc.textContent = gNavigatorBundle.getFormattedString(
"identity.newIdentity.description", [origin]);
this.chooseIdentityDesc.textContent = gNavigatorBundle.getFormattedString(
"identity.chooseIdentity.description", [origin]);
// Show optional terms of service and privacy policy links
this._populateLink(this.identity.termsOfService, "tos", "identity.termsOfService");
this._populateLink(this.identity.privacyPolicy, "privacypolicy", "identity.privacyPolicy");
// Populate the list of identities to choose from. The origin is used to provide
// better suggestions.
let identities = this.SignInToWebsiteUX.getIdentitiesForSite(origin);
this._populateIdentityList(identities);
if (typeof this.step == "undefined") {
// First opening of this notification
// Show the add email pane (0) if there are no existing identities otherwise show the list
this.step = "result" in identities && identities.result.length ? 1 : 0;
} else {
// Already opened so restore previous state
if (this.identity.typedEmail) {
this.emailField.value = this.identity.typedEmail;
}
if (this.identity.selected) {
// If the user already chose an identity then update the UI to reflect that
this.onIdentitySelected();
}
// Update the view for the step
this.step = this.step;
}
// Fire notification with the chosen identity when main button is clicked
this.button.addEventListener("command", this._onButtonCommand.bind(this), true);
// Do the same if enter is pressed in the email field
this.emailField.addEventListener("keypress", function emailFieldKeypress(aEvent) {
if (aEvent.keyCode != aEvent.DOM_VK_RETURN)
return;
this._onButtonCommand(aEvent);
}.bind(this));
this.addEmailLink.value = gNavigatorBundle.getString("identity.newIdentity.label");
this.addEmailLink.accessKey = gNavigatorBundle.getString("identity.newIdentity.accessKey");
this.addEmailLink.addEventListener("click", function addEmailClick(evt) {
this.step = 0;
}.bind(this));
this.chooseEmailLink.value = gNavigatorBundle.getString("identity.chooseIdentity.label");
this.chooseEmailLink.hidden = !("result" in identities && identities.result.length);
this.chooseEmailLink.addEventListener("click", function chooseEmailClick(evt) {
this.step = 1;
}.bind(this));
this.emailField.addEventListener("blur", function onEmailBlur() {
this.identity.typedEmail = this.emailField.value;
}.bind(this));
]]></constructor>
<field name="SignInToWebsiteUX" readonly="true">
let sitw = {};
Components.utils.import("resource:///modules/SignInToWebsite.jsm", sitw);
sitw.SignInToWebsiteUX;
</field>
<field name="newIdentityDesc" readonly="true">
document.getAnonymousElementByAttribute(this, "anonid", "newidentitydesc");
</field>
<field name="chooseIdentityDesc" readonly="true">
document.getAnonymousElementByAttribute(this, "anonid", "chooseidentitydesc");
</field>
<field name="identityList" readonly="true">
document.getAnonymousElementByAttribute(this, "anonid", "identities");
</field>
<field name="emailField" readonly="true">
document.getAnonymousElementByAttribute(this, "anonid", "email");
</field>
<field name="addEmailLink" readonly="true">
document.getAnonymousElementByAttribute(this, "anonid", "newemail");
</field>
<field name="chooseEmailLink" readonly="true">
document.getAnonymousElementByAttribute(this, "anonid", "chooseemail");
</field>
<field name="throbber" readonly="true">
document.getAnonymousElementByAttribute(this, "anonid", "throbber");
</field>
<field name="identity" readonly="true">
this.notification.options.identity;
</field>
<!-- persist the state on the identity object so we can re-create the
notification state upon re-opening -->
<property name="step">
<getter>
return this.identity.step;
</getter>
<setter><![CDATA[
let deck = document.getAnonymousElementByAttribute(this, "anonid", "identity-deck");
for (let i = 0; i < deck.children.length; i++) {
deck.children[i].hidden = (val != i);
}
this.identity.step = val;
switch (val) {
case 0:
this.emailField.focus();
break;
}]]>
</setter>
</property>
<method name="onIdentitySelected">
<body><![CDATA[
this.throbber.style.visibility = "visible";
this.button.disabled = true;
this.emailField.value = this.identity.selected
this.emailField.disabled = true;
this.identityList.disabled = true;
]]></body>
</method>
<method name="_populateLink">
<parameter name="aURL"/>
<parameter name="aLinkId"/>
<parameter name="aStringId"/>
<body><![CDATA[
if (aURL) {
// Show optional link to aURL
let link = document.getAnonymousElementByAttribute(this, "anonid", aLinkId);
link.value = gNavigatorBundle.getString(aStringId);
link.href = aURL;
link.hidden = false;
}
]]></body>
</method>
<method name="_populateIdentityList">
<parameter name="aIdentities"/>
<body><![CDATA[
let foundLastUsed = false;
let lastUsed = this.identity.selected || aIdentities.lastUsed;
for (let id in aIdentities.result) {
let label = aIdentities.result[id];
let opt = this.identityList.appendItem(label);
if (label == lastUsed) {
this.identityList.selectedItem = opt;
foundLastUsed = true;
}
}
if (!foundLastUsed) {
this.identityList.selectedIndex = -1;
}
]]></body>
</method>
<method name="_onButtonCommand">
<parameter name="aEvent"/>
<body><![CDATA[
if (aEvent.target != aEvent.currentTarget)
return;
let chosenId;
switch (this.step) {
case 0:
aEvent.stopPropagation();
if (!this.emailField.validity.valid) {
this.emailField.focus();
return;
}
chosenId = this.emailField.value;
break;
case 1:
aEvent.stopPropagation();
let selectedItem = this.identityList.selectedItem
chosenId = selectedItem ? selectedItem.label : null;
if (!chosenId)
return;
break;
default:
throw new Error("Unknown case");
return;
}
// Actually select the identity
this.SignInToWebsiteUX.selectIdentity(this.identity.rpId, chosenId);
this.identity.selected = chosenId;
this.onIdentitySelected();
]]></body>
</method>
</implementation>
</binding>
<binding id="splitmenu">
<content>
<xul:hbox anonid="menuitem" flex="1"

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

@ -12,6 +12,7 @@ const XULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource:///modules/SignInToWebsite.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "AddonManager",
"resource://gre/modules/AddonManager.jsm");
@ -25,7 +26,7 @@ XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
XPCOMUtils.defineLazyModuleGetter(this, "BookmarkHTMLUtils",
"resource://gre/modules/BookmarkHTMLUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "webappsUI",
XPCOMUtils.defineLazyModuleGetter(this, "webappsUI",
"resource:///modules/webappsUI.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "PageThumbs",
@ -308,6 +309,7 @@ BrowserGlue.prototype = {
if (this._isPlacesShutdownObserver)
os.removeObserver(this, "places-shutdown");
webappsUI.uninit();
SignInToWebsiteUX.uninit();
},
_onAppDefaults: function BG__onAppDefaults() {
@ -337,6 +339,8 @@ BrowserGlue.prototype = {
PageThumbs.init();
SignInToWebsiteUX.init();
PdfJs.init();
Services.obs.notifyObservers(null, "browser-ui-startup-complete", "");

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

@ -909,11 +909,6 @@ SourceScripts.prototype = {
this._addScript({ url: aPacket.url, startLine: aPacket.startLine }, true);
// Select the script if it's the preferred one.
if (aPacket.url === DebuggerView.Scripts.preferredScriptUrl) {
DebuggerView.Scripts.selectScript(aPacket.url);
}
// If there are any stored breakpoints for this script, display them again,
// both in the editor and the pane.
for each (let breakpoint in DebuggerController.Breakpoints.store) {
@ -932,14 +927,6 @@ SourceScripts.prototype = {
}
DebuggerView.Scripts.commitScripts();
DebuggerController.Breakpoints.updatePaneBreakpoints();
// Select the preferred script if one exists, the first entry otherwise.
let preferredScriptUrl = DebuggerView.Scripts.preferredScriptUrl;
if (preferredScriptUrl && DebuggerView.Scripts.contains(preferredScriptUrl)) {
DebuggerView.Scripts.selectScript(preferredScriptUrl);
} else {
DebuggerView.Scripts.selectIndex(0);
}
},
/**

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

@ -245,16 +245,6 @@ ScriptsView.prototype = {
return false;
},
/**
* Selects the script with the specified index from the list.
*
* @param number aIndex
* The script index.
*/
selectIndex: function DVS_selectIndex(aIndex) {
this._scripts.selectedIndex = aIndex;
},
/**
* Selects the script with the specified URL from the list.
*
@ -293,13 +283,6 @@ ScriptsView.prototype = {
this._scripts.selectedItem.value : null;
},
/**
* Gets the most recently selected script url.
* @return string | null
*/
get preferredScriptUrl()
this._preferredScriptUrl ? this._preferredScriptUrl : null,
/**
* Returns the list of labels in the scripts container.
* @return array
@ -368,7 +351,7 @@ ScriptsView.prototype = {
}
}
// The script is alphabetically the last one.
this._createScriptElement(aLabel, aScript, -1);
this._createScriptElement(aLabel, aScript, -1, true);
},
/**
@ -388,7 +371,7 @@ ScriptsView.prototype = {
for (let i = 0, l = newScripts.length; i < l; i++) {
let item = newScripts[i];
this._createScriptElement(item.label, item.script, -1);
this._createScriptElement(item.label, item.script, -1, true);
}
},
@ -403,8 +386,12 @@ ScriptsView.prototype = {
* @param number aIndex
* The index where to insert to new script in the container.
* Pass -1 to append the script at the end.
* @param boolean aSelectIfEmptyFlag
* True to set the newly created script as the currently selected item
* if there are no other existing scripts in the container.
*/
_createScriptElement: function DVS__createScriptElement(aLabel, aScript, aIndex)
_createScriptElement: function DVS__createScriptElement(
aLabel, aScript, aIndex, aSelectIfEmptyFlag)
{
// Make sure we don't duplicate anything.
if (aLabel == "null" || this.containsLabel(aLabel) || this.contains(aScript.url)) {
@ -417,6 +404,10 @@ ScriptsView.prototype = {
scriptItem.setAttribute("tooltiptext", aScript.url);
scriptItem.setUserData("sourceScript", aScript, null);
if (this._scripts.itemCount == 1 && aSelectIfEmptyFlag) {
this._scripts.selectedItem = scriptItem;
}
},
/**
@ -452,7 +443,6 @@ ScriptsView.prototype = {
}
this._preferredScript = selectedItem;
this._preferredScriptUrl = selectedItem.value;
this._scripts.setAttribute("tooltiptext", selectedItem.value);
DebuggerController.SourceScripts.showScript(selectedItem.getUserData("sourceScript"));
},

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

@ -35,7 +35,6 @@ MOCHITEST_BROWSER_TESTS = \
browser_dbg_propertyview-09.js \
browser_dbg_propertyview-10.js \
browser_dbg_propertyview-edit.js \
browser_dbg_reload-same-script.js \
browser_dbg_panesize.js \
browser_dbg_panesize-inner.js \
browser_dbg_stack-01.js \
@ -44,7 +43,6 @@ MOCHITEST_BROWSER_TESTS = \
browser_dbg_stack-04.js \
browser_dbg_stack-05.js \
browser_dbg_location-changes.js \
browser_dbg_location-changes-new.js \
browser_dbg_location-changes-blank.js \
browser_dbg_script-switching.js \
browser_dbg_scripts-sorting.js \

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

@ -1,91 +0,0 @@
/* vim:set ts=2 sw=2 sts=2 et: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Make sure that changing the tab location URL to a page with other scripts works.
*/
var gPane = null;
var gTab = null;
var gDebuggee = null;
var gDebugger = null;
function test()
{
debug_tab_pane(STACK_URL, function(aTab, aDebuggee, aPane) {
gTab = aTab;
gDebuggee = aDebuggee;
gPane = aPane;
gDebugger = gPane.contentWindow;
testSimpleCall();
});
}
function testSimpleCall() {
gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
Services.tm.currentThread.dispatch({
run: function() {
var frames = gDebugger.DebuggerView.StackFrames._frames,
childNodes = frames.childNodes;
is(gDebugger.DebuggerController.activeThread.state, "paused",
"Should only be getting stack frames while paused.");
is(frames.querySelectorAll(".dbg-stackframe").length, 1,
"Should have only one frame.");
is(childNodes.length, frames.querySelectorAll(".dbg-stackframe").length,
"All children should be frames.");
isnot(gDebugger.DebuggerView.Scripts.selected, null,
"There should be a selected script.");
isnot(gDebugger.editor.getText().length, 0,
"The source editor should have some text displayed.");
testLocationChange();
}
}, 0);
});
gDebuggee.simpleCall();
}
function testLocationChange()
{
gDebugger.DebuggerController.activeThread.resume(function() {
gDebugger.DebuggerController.client.addOneTimeListener("tabNavigated", function(aEvent, aPacket) {
ok(true, "tabNavigated event was fired.");
gDebugger.DebuggerController.client.addOneTimeListener("tabAttached", function(aEvent, aPacket) {
ok(true, "Successfully reattached to the tab again.");
// Wait for the initial resume...
gDebugger.gClient.addOneTimeListener("resumed", function() {
isnot(gDebugger.DebuggerView.Scripts.selected, null,
"There should be a selected script.");
isnot(gDebugger.editor.getText().length, 0,
"The source editor should have some text displayed.");
let menulist = gDebugger.DebuggerView.Scripts._scripts;
let noScripts = gDebugger.L10N.getStr("noScriptsText");
isnot(menulist.getAttribute("label"), noScripts,
"The menulist should not display a notice that there are no scripts availalble.");
isnot(menulist.getAttribute("tooltiptext"), "",
"The menulist should have a tooltip text attributed.");
closeDebuggerAndFinish();
});
});
});
content.location = EXAMPLE_URL + "browser_dbg_iframes.html";
});
}
registerCleanupFunction(function() {
removeTab(gTab);
gPane = null;
gTab = null;
gDebuggee = null;
gDebugger = null;
});

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

@ -1,126 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Tests if the same script is shown after a page is reloaded.
*/
const TAB_URL = EXAMPLE_URL + "browser_dbg_script-switching.html";
let gPane = null;
let gTab = null;
let gDebuggee = null;
let gDebugger = null;
let gView = null;
function test()
{
let step = 0;
let scriptShown = false;
let scriptShownUrl = null;
let resumed = false;
let testStarted = false;
debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
gTab = aTab;
gDebuggee = aDebuggee;
gPane = aPane;
gDebugger = gPane.contentWindow;
gView = gDebugger.DebuggerView;
resumed = true;
executeSoon(startTest);
});
function onScriptShown(aEvent)
{
scriptShown = aEvent.detail.url.indexOf("-01.js") != -1;
scriptShownUrl = aEvent.detail.url;
executeSoon(startTest);
}
function onUlteriorScriptShown(aEvent)
{
scriptShownUrl = aEvent.detail.url;
executeSoon(testScriptShown);
}
window.addEventListener("Debugger:ScriptShown", onScriptShown);
function startTest()
{
if (scriptShown && resumed && !testStarted) {
window.removeEventListener("Debugger:ScriptShown", onScriptShown);
window.addEventListener("Debugger:ScriptShown", onUlteriorScriptShown);
testStarted = true;
Services.tm.currentThread.dispatch({ run: performTest }, 0);
}
}
function finishTest()
{
if (scriptShown && resumed && testStarted) {
window.removeEventListener("Debugger:ScriptShown", onUlteriorScriptShown);
closeDebuggerAndFinish();
}
}
function performTest()
{
testCurrentScript("-01.js", step);
step = 1;
reloadPage();
}
function testScriptShown()
{
if (step === 1) {
testCurrentScript("-01.js", step);
step = 2;
reloadPage();
}
else if (step === 2) {
testCurrentScript("-01.js", step);
step = 3;
gView.Scripts.selectScript(gView.Scripts.scriptLocations[1]);
}
else if (step === 3) {
testCurrentScript("-02.js", step);
step = 4;
reloadPage();
}
else if (step === 4) {
testCurrentScript("-02.js", step);
finishTest();
}
}
function testCurrentScript(part, step)
{
info("Currently preferred script: " + gView.Scripts.preferredScriptUrl);
info("Currently selected script: " + gView.Scripts.selected);
isnot(gView.Scripts.preferredScriptUrl.indexOf(part), -1,
"The preferred script url wasn't set correctly. (" + step + ")");
isnot(gView.Scripts.selected.indexOf(part), -1,
"The selected script isn't the correct one. (" + step + ")");
is(gView.Scripts.selected, scriptShownUrl,
"The shown script is not the the correct one. (" + step + ")");
}
function reloadPage()
{
executeSoon(function() {
gDebuggee.location.reload();
});
}
registerCleanupFunction(function() {
removeTab(gTab);
gPane = null;
gTab = null;
gDebuggee = null;
gDebugger = null;
gView = null;
});
}

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

@ -383,3 +383,21 @@ social.remove.accesskey=R
# LOCALIZATION NOTE (social.enabled.message): %1$S is the name of the social provider, %2$S is brandShortName (e.g. Firefox)
social.activated.message=%1$S integration with %2$S has been activated.
# Identity notifications popups
identity.termsOfService = Terms of Service
identity.privacyPolicy = Privacy Policy
identity.chooseIdentity.description = Sign in to %S
identity.chooseIdentity.label = Use an existing email
identity.newIdentity.label = Use a different email
identity.newIdentity.accessKey = e
identity.newIdentity.email.placeholder = Email
# LOCALIZATION NOTE (identity.newIdentity.description, identity.chooseIdentity.description): %S is the website origin (ie. https://www.mozilla.org) shown in popup notifications.
identity.newIdentity.description = Enter your email address to sign in to %S
identity.next.label = Next
identity.next.accessKey = n
# LOCALIZATION NOTE: shown in the popup notification when a user successfully logs into a website
# LOCALIZATION NOTE (identity.loggedIn.description): %S is the website origin (ie. https://www.mozilla.org)
identity.loggedIn.description = Signed in as: %S
identity.loggedIn.signOut.label = Sign Out
identity.loggedIn.signOut.accessKey = O

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

@ -19,12 +19,13 @@ EXTRA_JS_MODULES = \
NetworkPrioritizer.jsm \
NewTabUtils.jsm \
offlineAppCache.jsm \
SignInToWebsite.jsm \
TelemetryTimestamps.jsm \
Social.jsm \
webappsUI.jsm \
$(NULL)
ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
EXTRA_JS_MODULES += \
WindowsPreviewPerTab.jsm \
WindowsJumpLists.jsm \

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

@ -0,0 +1,235 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const EXPORTED_SYMBOLS = ["SignInToWebsiteUX"];
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cu = Components.utils;
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "IdentityService",
"resource://gre/modules/identity/Identity.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Logger",
"resource://gre/modules/identity/LogUtils.jsm");
function log(...aMessageArgs) {
Logger.log.apply(Logger, ["SignInToWebsiteUX"].concat(aMessageArgs));
}
let SignInToWebsiteUX = {
init: function SignInToWebsiteUX_init() {
Services.obs.addObserver(this, "identity-request", false);
Services.obs.addObserver(this, "identity-auth", false);
Services.obs.addObserver(this, "identity-auth-complete", false);
Services.obs.addObserver(this, "identity-login-state-changed", false);
},
uninit: function SignInToWebsiteUX_uninit() {
Services.obs.removeObserver(this, "identity-request");
Services.obs.removeObserver(this, "identity-auth");
Services.obs.removeObserver(this, "identity-auth-complete");
Services.obs.removeObserver(this, "identity-login-state-changed");
},
observe: function SignInToWebsiteUX_observe(aSubject, aTopic, aData) {
log("observe: received", aTopic, "with", aData, "for", aSubject);
let options = null;
if (aSubject) {
options = aSubject.wrappedJSObject;
}
switch(aTopic) {
case "identity-request":
this.requestLogin(options);
break;
case "identity-auth":
this._openAuthenticationUI(aData, options);
break;
case "identity-auth-complete":
this._closeAuthenticationUI(aData);
break;
case "identity-login-state-changed":
let emailAddress = aData;
if (emailAddress) {
this._removeRequestUI(options);
this._showLoggedInUI(emailAddress, options);
} else {
this._removeLoggedInUI(options);
}
break;
default:
Logger.reportError("SignInToWebsiteUX", "Unknown observer notification:", aTopic);
break;
}
},
/**
* The website is requesting login so the user must choose an identity to use.
*/
requestLogin: function SignInToWebsiteUX_requestLogin(aOptions) {
let windowID = aOptions.rpId;
log("requestLogin", aOptions);
let [chromeWin, browserEl] = this._getUIForWindowID(windowID);
// message is not shown in the UI but is required
let message = aOptions.origin;
let mainAction = {
label: chromeWin.gNavigatorBundle.getString("identity.next.label"),
accessKey: chromeWin.gNavigatorBundle.getString("identity.next.accessKey"),
callback: function() {}, // required
};
let options = {
identity: {
origin: aOptions.origin,
},
};
let secondaryActions = [];
// add some extra properties to the notification to store some identity-related state
for (let opt in aOptions) {
options.identity[opt] = aOptions[opt];
}
log("requestLogin: rpId: ", options.identity.rpId);
chromeWin.PopupNotifications.show(browserEl, "identity-request", message,
"identity-notification-icon", mainAction,
[], options);
},
/**
* Get the list of possible identities to login to the given origin.
*/
getIdentitiesForSite: function SignInToWebsiteUX_getIdentitiesForSite(aOrigin) {
return IdentityService.RP.getIdentitiesForSite(aOrigin);
},
/**
* User chose a new or existing identity from the doorhanger after a request() call
*/
selectIdentity: function SignInToWebsiteUX_selectIdentity(aRpId, aIdentity) {
log("selectIdentity: rpId: ", aRpId, " identity: ", aIdentity);
IdentityService.selectIdentity(aRpId, aIdentity);
},
// Private
/**
* Return the chrome window and <browser> for the given outer window ID.
*/
_getUIForWindowID: function(aWindowID) {
let someWindow = Services.wm.getMostRecentWindow("navigator:browser");
if (!someWindow) {
Logger.reportError("SignInToWebsiteUX", "no window");
return [null, null];
}
let windowUtils = someWindow.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils);
let content = windowUtils.getOuterWindowWithId(aWindowID);
if (content) {
let browser = content.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIDocShell).chromeEventHandler;
let chromeWin = browser.ownerDocument.defaultView;
return [chromeWin, browser];
}
Logger.reportError("SignInToWebsiteUX", "no content");
return [null, null];
},
/**
* Open UI with a content frame displaying aAuthURI so that the user can authenticate with their
* IDP. Then tell Identity.jsm the identifier for the window so that it knows that the DOM API
* calls are for this authentication flow.
*/
_openAuthenticationUI: function _openAuthenticationUI(aAuthURI, aContext) {
// Open a tab/window with aAuthURI with an identifier (aID) attached so that the DOM APIs know this is an auth. window.
let chromeWin = Services.wm.getMostRecentWindow('navigator:browser');
let features = "chrome=false,width=640,height=480,centerscreen,location=yes,resizable=yes,scrollbars=yes,status=yes";
log("aAuthURI: ", aAuthURI);
let authWin = Services.ww.openWindow(chromeWin, "about:blank", "", features, null);
let windowID = authWin.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils).outerWindowID;
log("authWin outer id: ", windowID);
let provId = aContext.provId;
// Tell the ID service about the id before loading the url
IdentityService.IDP.setAuthenticationFlow(windowID, provId);
authWin.location = aAuthURI;
},
_closeAuthenticationUI: function _closeAuthenticationUI(aAuthId) {
log("_closeAuthenticationUI:", aAuthId);
let [chromeWin, browserEl] = this._getUIForWindowID(aAuthId);
if (chromeWin)
chromeWin.close();
else
Logger.reportError("SignInToWebsite", "Could not close window with ID", aAuthId);
},
/**
* Show a doorhanger indicating the currently logged-in user.
*/
_showLoggedInUI: function _showLoggedInUI(aIdentity, aContext) {
let windowID = aContext.rpId;
log("_showLoggedInUI for ", windowID);
let [chromeWin, browserEl] = this._getUIForWindowID(windowID);
let message = chromeWin.gNavigatorBundle.getFormattedString("identity.loggedIn.description",
[aIdentity]);
let mainAction = {
label: chromeWin.gNavigatorBundle.getString("identity.loggedIn.signOut.label"),
accessKey: chromeWin.gNavigatorBundle.getString("identity.loggedIn.signOut.accessKey"),
callback: function() {
log("sign out callback fired");
IdentityService.RP.logout(windowID);
},
};
let secondaryActions = [];
let options = {
dismissed: true,
};
let loggedInNot = chromeWin.PopupNotifications.show(browserEl, "identity-logged-in", message,
"identity-notification-icon", mainAction,
secondaryActions, options);
loggedInNot.rpId = windowID;
},
/**
* Remove the doorhanger indicating the currently logged-in user.
*/
_removeLoggedInUI: function _removeLoggedInUI(aContext) {
let windowID = aContext.rpId;
log("_removeLoggedInUI for ", windowID);
if (!windowID)
throw "_removeLoggedInUI: Invalid RP ID";
let [chromeWin, browserEl] = this._getUIForWindowID(windowID);
let loggedInNot = chromeWin.PopupNotifications.getNotification("identity-logged-in", browserEl);
if (loggedInNot)
chromeWin.PopupNotifications.remove(loggedInNot);
},
/**
* Remove the doorhanger indicating the currently logged-in user.
*/
_removeRequestUI: function _removeRequestUI(aContext) {
let windowID = aContext.rpId;
log("_removeRequestUI for ", windowID);
let [chromeWin, browserEl] = this._getUIForWindowID(windowID);
let requestNot = chromeWin.PopupNotifications.getNotification("identity-request", browserEl);
if (requestNot)
chromeWin.PopupNotifications.remove(requestNot);
},
};

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

@ -14,9 +14,10 @@ include $(topsrcdir)/config/rules.mk
_BROWSER_FILES = \
browser_NetworkPrioritizer.js \
browser_TelemetryTimestamps.js \
browser_SignInToWebsite.js \
$(NULL)
ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
_BROWSER_FILES += \
browser_taskbar_preview.js \
$(NULL)

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

@ -0,0 +1,549 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
/**
* TO TEST:
* - test state saved on doorhanger dismissal
* - links to switch steps
* - TOS and PP link clicks
* - identityList is populated correctly
*/
Services.prefs.setBoolPref("toolkit.identity.debug", true);
XPCOMUtils.defineLazyModuleGetter(this, "IdentityService",
"resource://gre/modules/identity/Identity.jsm");
const TEST_ORIGIN = "https://example.com";
const TEST_EMAIL = "user@example.com";
let gTestIndex = 0;
let outerWinId = gBrowser.contentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils).outerWindowID;
function NotificationBase(aNotId) {
this.id = aNotId;
}
NotificationBase.prototype = {
message: TEST_ORIGIN,
mainAction: {
label: "",
callback: function() {
this.mainActionClicked = true;
}.bind(this),
},
secondaryActions: [],
options: {
"identity": {
origin: TEST_ORIGIN,
rpId: outerWinId,
},
},
};
let tests = [
{
name: "test_request_required_typed",
run: function() {
setupRPFlow();
this.notifyOptions = {
rpId: outerWinId,
origin: TEST_ORIGIN,
};
this.notifyObj = new NotificationBase("identity-request");
Services.obs.notifyObservers({wrappedJSObject: this.notifyOptions},
"identity-request", null);
},
onShown: function(popup) {
checkPopup(popup, this.notifyObj);
let notification = popup.childNodes[0];
// Check identity popup state
let state = notification.identity;
ok(!state.typedEmail, "Nothing should be typed yet");
ok(!state.selected, "Identity should not be selected yet");
ok(!state.termsOfService, "No TOS specified");
ok(!state.privacyPolicy, "No PP specified");
is(state.step, 0, "Step should be persisted with default value");
is(state.rpId, outerWinId, "Check rpId");
is(state.origin, TEST_ORIGIN, "Check origin");
is(notification.step, 0, "Should be on the new email step");
is(notification.chooseEmailLink.hidden, true, "Identity list is empty so link to list view should be hidden");
is(notification.addEmailLink.parentElement.hidden, true, "We are already on the email input step so choose email pane should be hidden");
is(notification.emailField.value, "", "Email field should default to empty on a new notification");
let notifDoc = notification.ownerDocument;
ok(notifDoc.getAnonymousElementByAttribute(notification, "anonid", "tos").hidden,
"TOS link should be hidden");
ok(notifDoc.getAnonymousElementByAttribute(notification, "anonid", "privacypolicy").hidden,
"PP link should be hidden");
// Try to continue with a missing email address
triggerMainCommand(popup);
is(notification.throbber.style.visibility, "hidden", "is throbber visible");
ok(!notification.button.disabled, "Button should not be disabled");
is(window.gIdentitySelected, null, "Check no identity selected");
// Fill in an invalid email address and try again
notification.emailField.value = "foo";
triggerMainCommand(popup);
is(notification.throbber.style.visibility, "hidden", "is throbber visible");
ok(!notification.button.disabled, "Button should not be disabled");
is(window.gIdentitySelected, null, "Check no identity selected");
// Fill in an email address and try again
notification.emailField.value = TEST_EMAIL;
triggerMainCommand(popup);
is(window.gIdentitySelected.rpId, outerWinId, "Check identity selected rpId");
is(window.gIdentitySelected.identity, TEST_EMAIL, "Check identity selected email");
is(notification.identity.selected, TEST_EMAIL, "Check persisted email");
is(notification.throbber.style.visibility, "visible", "is throbber visible");
ok(notification.button.disabled, "Button should be disabled");
ok(notification.emailField.disabled, "Email field should be disabled");
ok(notification.identityList.disabled, "Identity list should be disabled");
PopupNotifications.getNotification("identity-request").remove();
},
onHidden: function(popup) { },
},
{
name: "test_request_optional",
run: function() {
this.notifyOptions = {
rpId: outerWinId,
origin: TEST_ORIGIN,
privacyPolicy: TEST_ORIGIN + "/pp.txt",
termsOfService: TEST_ORIGIN + "/tos.tzt",
};
this.notifyObj = new NotificationBase("identity-request");
Services.obs.notifyObservers({ wrappedJSObject: this.notifyOptions },
"identity-request", null);
},
onShown: function(popup) {
checkPopup(popup, this.notifyObj);
let notification = popup.childNodes[0];
// Check identity popup state
let state = notification.identity;
ok(!state.typedEmail, "Nothing should be typed yet");
ok(!state.selected, "Identity should not be selected yet");
is(state.termsOfService, this.notifyOptions.termsOfService, "Check TOS URL");
is(state.privacyPolicy, this.notifyOptions.privacyPolicy, "Check PP URL");
is(state.step, 0, "Step should be persisted with default value");
is(state.rpId, outerWinId, "Check rpId");
is(state.origin, TEST_ORIGIN, "Check origin");
is(notification.step, 0, "Should be on the new email step");
is(notification.chooseEmailLink.hidden, true, "Identity list is empty so link to list view should be hidden");
is(notification.addEmailLink.parentElement.hidden, true, "We are already on the email input step so choose email pane should be hidden");
is(notification.emailField.value, "", "Email field should default to empty on a new notification");
let notifDoc = notification.ownerDocument;
let tosLink = notifDoc.getAnonymousElementByAttribute(notification, "anonid", "tos");
ok(!tosLink.hidden, "TOS link should be visible");
is(tosLink.href, this.notifyOptions.termsOfService, "Check TOS link URL");
let ppLink = notifDoc.getAnonymousElementByAttribute(notification, "anonid", "privacypolicy");
ok(!ppLink.hidden, "PP link should be visible");
is(ppLink.href, this.notifyOptions.privacyPolicy, "Check PP link URL");
// Try to continue with a missing email address
triggerMainCommand(popup);
is(notification.throbber.style.visibility, "hidden", "is throbber visible");
ok(!notification.button.disabled, "Button should not be disabled");
is(window.gIdentitySelected, null, "Check no identity selected");
// Fill in an invalid email address and try again
notification.emailField.value = "foo";
triggerMainCommand(popup);
is(notification.throbber.style.visibility, "hidden", "is throbber visible");
ok(!notification.button.disabled, "Button should not be disabled");
is(window.gIdentitySelected, null, "Check no identity selected");
// Fill in an email address and try again
notification.emailField.value = TEST_EMAIL;
triggerMainCommand(popup);
is(window.gIdentitySelected.rpId, outerWinId, "Check identity selected rpId");
is(window.gIdentitySelected.identity, TEST_EMAIL, "Check identity selected email");
is(notification.identity.selected, TEST_EMAIL, "Check persisted email");
is(notification.throbber.style.visibility, "visible", "is throbber visible");
ok(notification.button.disabled, "Button should be disabled");
ok(notification.emailField.disabled, "Email field should be disabled");
ok(notification.identityList.disabled, "Identity list should be disabled");
PopupNotifications.getNotification("identity-request").remove();
},
onHidden: function(popup) {},
},
{
name: "test_login_state_changed",
run: function () {
this.notifyOptions = {
rpId: outerWinId,
};
this.notifyObj = new NotificationBase("identity-logged-in");
this.notifyObj.message = "Signed in as: user@example.com";
this.notifyObj.mainAction.label = "Sign Out";
this.notifyObj.mainAction.accessKey = "O";
Services.obs.notifyObservers({ wrappedJSObject: this.notifyOptions },
"identity-login-state-changed", TEST_EMAIL);
executeSoon(function() {
PopupNotifications.getNotification("identity-logged-in").anchorElement.click();
});
},
onShown: function(popup) {
checkPopup(popup, this.notifyObj);
// Fire the notification that the user is no longer logged-in to close the UI.
Services.obs.notifyObservers({ wrappedJSObject: this.notifyOptions },
"identity-login-state-changed", null);
},
onHidden: function(popup) {},
},
{
name: "test_login_state_changed_logout",
run: function () {
this.notifyOptions = {
rpId: outerWinId,
};
this.notifyObj = new NotificationBase("identity-logged-in");
this.notifyObj.message = "Signed in as: user@example.com";
this.notifyObj.mainAction.label = "Sign Out";
this.notifyObj.mainAction.accessKey = "O";
Services.obs.notifyObservers({ wrappedJSObject: this.notifyOptions },
"identity-login-state-changed", TEST_EMAIL);
executeSoon(function() {
PopupNotifications.getNotification("identity-logged-in").anchorElement.click();
});
},
onShown: function(popup) {
checkPopup(popup, this.notifyObj);
// This time trigger the Sign Out button and make sure the UI goes away.
triggerMainCommand(popup);
},
onHidden: function(popup) {},
},
];
function test_auth() {
let notifyOptions = {
provId: outerWinId,
origin: TEST_ORIGIN,
};
Services.obs.addObserver(function() {
// prepare to send auth-complete and close the window
let winCloseObs = new WindowObserver(function(closedWin) {
info("closed window");
finish();
}, "domwindowclosed");
Services.ww.registerNotification(winCloseObs);
Services.obs.notifyObservers(null, "identity-auth-complete", IdentityService.IDP.authenticationFlowSet.authId);
}, "test-identity-auth-window", false);
let winObs = new WindowObserver(function(authWin) {
ok(authWin, "Authentication window opened");
ok(authWin.contentWindow.location);
});
Services.ww.registerNotification(winObs);
Services.obs.notifyObservers({ wrappedJSObject: notifyOptions },
"identity-auth", TEST_ORIGIN + "/auth");
}
function test() {
waitForExplicitFinish();
registerCleanupFunction(cleanUp);
let sitw = {};
Components.utils.import("resource:///modules/SignInToWebsite.jsm", sitw);
ok(sitw.SignInToWebsiteUX, "SignInToWebsiteUX object exists");
// Replace implementation of ID Service functions for testing
window.selectIdentity = sitw.SignInToWebsiteUX.selectIdentity;
sitw.SignInToWebsiteUX.selectIdentity = function(aRpId, aIdentity) {
info("Identity selected: " + aIdentity);
window.gIdentitySelected = {rpId: aRpId, identity: aIdentity};
};
window.setAuthenticationFlow = IdentityService.IDP.setAuthenticationFlow;
IdentityService.IDP.setAuthenticationFlow = function(aAuthId, aProvId) {
info("setAuthenticationFlow: " + aAuthId + " : " + aProvId);
this.authenticationFlowSet = { authId: aAuthId, provId: aProvId };
Services.obs.notifyObservers(null, "test-identity-auth-window", aAuthId);
};
runNextTest();
}
// Cleanup between tests
function resetState() {
delete window.gIdentitySelected;
delete IdentityService.IDP.authenticationFlowSet;
IdentityService.reset();
}
// Cleanup after all tests
function cleanUp() {
info("cleanup");
resetState();
for (let topic in gActiveObservers)
Services.obs.removeObserver(gActiveObservers[topic], topic);
for (let eventName in gActiveListeners)
PopupNotifications.panel.removeEventListener(eventName, gActiveListeners[eventName], false);
delete IdentityService.RP._rpFlows[outerWinId];
// Put the JSM functions back to how they were
IdentityService.IDP.setAuthenticationFlow = window.setAuthenticationFlow;
delete window.setAuthenticationFlow;
let sitw = {};
Components.utils.import("resource:///modules/SignInToWebsite.jsm", sitw);
sitw.SignInToWebsiteUX.selectIdentity = window.selectIdentity;
delete window.selectIdentity;
Services.prefs.clearUserPref("toolkit.identity.debug");
}
let gActiveListeners = {};
let gActiveObservers = {};
let gShownState = {};
function runNextTest() {
let nextTest = tests[gTestIndex];
function goNext() {
resetState();
if (++gTestIndex == tests.length)
executeSoon(test_auth);
else
executeSoon(runNextTest);
}
function addObserver(topic) {
function observer() {
Services.obs.removeObserver(observer, "PopupNotifications-" + topic);
delete gActiveObservers["PopupNotifications-" + topic];
info("[Test #" + gTestIndex + "] observer for " + topic + " called");
nextTest[topic]();
goNext();
}
Services.obs.addObserver(observer, "PopupNotifications-" + topic, false);
gActiveObservers["PopupNotifications-" + topic] = observer;
}
if (nextTest.backgroundShow) {
addObserver("backgroundShow");
} else if (nextTest.updateNotShowing) {
addObserver("updateNotShowing");
} else {
doOnPopupEvent("popupshowing", function () {
info("[Test #" + gTestIndex + "] popup showing");
});
doOnPopupEvent("popupshown", function () {
gShownState[gTestIndex] = true;
info("[Test #" + gTestIndex + "] popup shown");
nextTest.onShown(this);
});
// We allow multiple onHidden functions to be defined in an array. They're
// called in the order they appear.
let onHiddenArray = nextTest.onHidden instanceof Array ?
nextTest.onHidden :
[nextTest.onHidden];
doOnPopupEvent("popuphidden", function () {
if (!gShownState[gTestIndex]) {
// TODO: needed?
info("Popup from test " + gTestIndex + " was hidden before its popupshown fired");
}
let onHidden = onHiddenArray.shift();
info("[Test #" + gTestIndex + "] popup hidden (" + onHiddenArray.length + " hides remaining)");
executeSoon(function () {
onHidden.call(nextTest, this);
if (!onHiddenArray.length)
goNext();
}.bind(this));
}, onHiddenArray.length);
info("[Test #" + gTestIndex + "] added listeners; panel state: " + PopupNotifications.isPanelOpen);
}
info("[Test #" + gTestIndex + "] running test");
nextTest.run();
}
function doOnPopupEvent(eventName, callback, numExpected) {
gActiveListeners[eventName] = function (event) {
if (event.target != PopupNotifications.panel)
return;
if (typeof(numExpected) === "number")
numExpected--;
if (!numExpected) {
PopupNotifications.panel.removeEventListener(eventName, gActiveListeners[eventName], false);
delete gActiveListeners[eventName];
}
callback.call(PopupNotifications.panel);
};
PopupNotifications.panel.addEventListener(eventName, gActiveListeners[eventName], false);
}
function checkPopup(popup, notificationObj) {
info("[Test #" + gTestIndex + "] checking popup");
let notifications = popup.childNodes;
is(notifications.length, 1, "only one notification displayed");
let notification = notifications[0];
let icon = document.getAnonymousElementByAttribute(notification, "class", "popup-notification-icon");
is(notification.getAttribute("label"), notificationObj.message, "message matches");
is(notification.id, notificationObj.id + "-notification", "id matches");
if (notificationObj.id != "identity-request" && notificationObj.mainAction) {
is(notification.getAttribute("buttonlabel"), notificationObj.mainAction.label, "main action label matches");
is(notification.getAttribute("buttonaccesskey"), notificationObj.mainAction.accessKey, "main action accesskey matches");
}
let actualSecondaryActions = notification.childNodes;
let secondaryActions = notificationObj.secondaryActions || [];
let actualSecondaryActionsCount = actualSecondaryActions.length;
if (secondaryActions.length) {
let lastChild = actualSecondaryActions.item(actualSecondaryActions.length - 1);
is(lastChild.tagName, "menuseparator", "menuseparator exists");
actualSecondaryActionsCount--;
}
is(actualSecondaryActionsCount, secondaryActions.length, actualSecondaryActions.length + " secondary actions");
secondaryActions.forEach(function (a, i) {
is(actualSecondaryActions[i].getAttribute("label"), a.label, "label for secondary action " + i + " matches");
is(actualSecondaryActions[i].getAttribute("accesskey"), a.accessKey, "accessKey for secondary action " + i + " matches");
});
}
function triggerMainCommand(popup) {
info("[Test #" + gTestIndex + "] triggering main command");
let notifications = popup.childNodes;
ok(notifications.length > 0, "at least one notification displayed");
let notification = notifications[0];
// 20, 10 so that the inner button is hit
EventUtils.synthesizeMouse(notification.button, 20, 10, {});
}
function triggerSecondaryCommand(popup, index) {
info("[Test #" + gTestIndex + "] triggering secondary command");
let notifications = popup.childNodes;
ok(notifications.length > 0, "at least one notification displayed");
let notification = notifications[0];
notification.button.focus();
popup.addEventListener("popupshown", function () {
popup.removeEventListener("popupshown", arguments.callee, false);
// Press down until the desired command is selected
for (let i = 0; i <= index; i++)
EventUtils.synthesizeKey("VK_DOWN", {});
// Activate
EventUtils.synthesizeKey("VK_ENTER", {});
}, false);
// One down event to open the popup
EventUtils.synthesizeKey("VK_DOWN", { altKey: (navigator.platform.indexOf("Mac") == -1) });
}
function dismissNotification(popup) {
info("[Test #" + gTestIndex + "] dismissing notification");
executeSoon(function () {
EventUtils.synthesizeKey("VK_ESCAPE", {});
});
}
function partial(fn) {
let args = Array.prototype.slice.call(arguments, 1);
return function() {
return fn.apply(this, args.concat(Array.prototype.slice.call(arguments)));
};
}
// create a mock "doc" object, which the Identity Service
// uses as a pointer back into the doc object
function mock_doc(aIdentity, aOrigin, aDoFunc) {
let mockedDoc = {};
mockedDoc.id = outerWinId;
mockedDoc.loggedInEmail = aIdentity;
mockedDoc.origin = aOrigin;
mockedDoc['do'] = aDoFunc;
mockedDoc.doReady = partial(aDoFunc, 'ready');
mockedDoc.doLogin = partial(aDoFunc, 'login');
mockedDoc.doLogout = partial(aDoFunc, 'logout');
mockedDoc.doError = partial(aDoFunc, 'error');
mockedDoc.doCancel = partial(aDoFunc, 'cancel');
mockedDoc.doCoffee = partial(aDoFunc, 'coffee');
return mockedDoc;
}
// takes a list of functions and returns a function that
// when called the first time, calls the first func,
// then the next time the second, etc.
function call_sequentially() {
let numCalls = 0;
let funcs = arguments;
return function() {
if (!funcs[numCalls]) {
let argString = Array.prototype.slice.call(arguments).join(",");
ok(false, "Too many calls: " + argString);
return;
}
funcs[numCalls].apply(funcs[numCalls], arguments);
numCalls += 1;
};
}
function setupRPFlow(aIdentity) {
IdentityService.RP.watch(mock_doc(aIdentity, TEST_ORIGIN, call_sequentially(
function(action, params) {
is(action, "ready", "1st callback");
is(params, null);
},
function(action, params) {
is(action, "logout", "2nd callback");
is(params, null);
},
function(action, params) {
is(action, "ready", "3rd callback");
is(params, null);
}
)));
}
function WindowObserver(aCallback, aObserveTopic = "domwindowopened") {
this.observe = function(aSubject, aTopic, aData) {
if (aTopic != aObserveTopic) {
return;
}
info(aObserveTopic);
Services.ww.unregisterNotification(this);
SimpleTest.executeSoon(function() {
let domWin = aSubject.QueryInterface(Ci.nsIDOMWindow);
aCallback(domWin);
});
};
}

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

@ -1240,6 +1240,10 @@ toolbar[iconsize="small"] #feed-button {
list-style-image: url(chrome://global/skin/icons/information-16.png);
}
#identity-notification-icon {
list-style-image: url(chrome://mozapps/skin/profile/profileicon.png);
}
#geo-notification-icon {
list-style-image: url(chrome://browser/skin/Geolocation-16.png);
}

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

@ -2369,12 +2369,19 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker {
list-style-image: url(chrome://global/skin/icons/information-16.png);
}
#identity-notification-icon {
list-style-image: url(chrome://mozapps/skin/profile/profileicon.png);
}
#geo-notification-icon {
list-style-image: url(chrome://browser/skin/Geolocation-16.png);
}
.geolocation-text-link {
#notification-popup .text-link {
color: #fff;
}
.geolocation-text-link {
-moz-margin-start: 0; /* override default label margin to match description margin */
}

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

@ -2375,6 +2375,10 @@ toolbarbutton.bookmark-item[dragover="true"][open="true"] {
list-style-image: url(chrome://global/skin/icons/information-16.png);
}
#identity-notification-icon {
list-style-image: url(chrome://mozapps/skin/profile/profileicon.png);
}
#geo-notification-icon {
list-style-image: url(chrome://browser/skin/Geolocation-16.png);
}

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

@ -2,7 +2,6 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
# You can obtain one at http://mozilla.org/MPL/2.0/.
import time
import hashlib
import socket
import os

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

@ -6,8 +6,8 @@ import subprocess
from devicemanager import DeviceManager, DMError, _pop_last_line
import re
import os
import sys
import tempfile
import time
class DeviceManagerADB(DeviceManager):
@ -65,7 +65,7 @@ class DeviceManagerADB(DeviceManager):
self.useRunAs = False
try:
self.verifyRoot()
except DMError, e:
except DMError:
try:
self.checkCmd(["root"])
# The root command does not fail even if ADB cannot get
@ -394,7 +394,9 @@ class DeviceManagerADB(DeviceManager):
args.append("-9")
args.append(pid)
p = self.runCmdAs(args)
didKillProcess = True
p.communicate()
if p.returncode == 0:
didKillProcess = True
return didKillProcess
@ -499,11 +501,11 @@ class DeviceManagerADB(DeviceManager):
# success: MD5 hash for given filename
# failure: None
def getRemoteHash(self, filename):
data = p = self.runCmd(["shell", "ls", "-l", filename]).stdout.read()
data = self.runCmd(["shell", "ls", "-l", filename]).stdout.read()
return data.split()[3]
def getLocalHash(self, filename):
data = p = subprocess.Popen(["ls", "-l", filename], stdout=subprocess.PIPE).stdout.read()
data = subprocess.Popen(["ls", "-l", filename], stdout=subprocess.PIPE).stdout.read()
return data.split()[4]
# Internal method to setup the device root and cache its value
@ -693,7 +695,7 @@ class DeviceManagerADB(DeviceManager):
return ret
def runCmd(self, args):
# If we are not root but have run-as, and we're trying to execute
# If we are not root but have run-as, and we're trying to execute
# a shell command then using run-as is the best we can do
finalArgs = [self.adbPath]
if self.deviceSerial:
@ -711,7 +713,7 @@ class DeviceManagerADB(DeviceManager):
return self.runCmd(args)
def checkCmd(self, args):
# If we are not root but have run-as, and we're trying to execute
# If we are not root but have run-as, and we're trying to execute
# a shell command then using run-as is the best we can do
finalArgs = [self.adbPath]
if self.deviceSerial:

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

@ -5,17 +5,14 @@
import select
import socket
import SocketServer
import time, datetime
import time
import os
import re
import hashlib
import posixpath
import subprocess
from threading import Thread
import traceback
import sys
import StringIO
from devicemanager import DeviceManager, DMError, FileError, NetworkTools, _pop_last_line
from devicemanager import DeviceManager, FileError, NetworkTools, _pop_last_line
import errno
class AgentError(Exception):
@ -126,7 +123,6 @@ class DeviceManagerSUT(DeviceManager):
one fails. this is necessary in particular for pushFile(), where we don't want
to accidentally send extra data if a failure occurs during data transmission.
'''
done = False
while self.retries < self.retrylimit:
try:
self._doCmds(cmdlist, outputfile, timeout)
@ -187,7 +183,7 @@ class DeviceManagerSUT(DeviceManager):
sent = self._sock.send(cmd['data'])
if sent != len(cmd['data']):
raise AgentError("ERROR: we had %s bytes of data to send, but "
"only sent %s" % (len(cmd['data'], sent)))
"only sent %s" % (len(cmd['data']), sent))
if (self.debug >= 4): print "sent cmd: " + str(cmd['cmd'])
except socket.error, msg:
@ -503,7 +499,7 @@ class DeviceManagerSUT(DeviceManager):
return None
try:
data = self.runCmds([{ 'cmd': 'exec ' + appname }])
self.runCmds([{ 'cmd': 'exec ' + appname }])
except AgentError:
return None
@ -547,7 +543,7 @@ class DeviceManagerSUT(DeviceManager):
if forceKill:
print "WARNING: killProcess(): forceKill parameter unsupported on SUT"
try:
data = self.runCmds([{ 'cmd': 'kill ' + appname }])
self.runCmds([{ 'cmd': 'kill ' + appname }])
except AgentError:
return False
@ -640,7 +636,8 @@ class DeviceManagerSUT(DeviceManager):
# or, if error,
# <filename>,-1\n<error message>
try:
data = self.runCmds([{ 'cmd': 'pull ' + remoteFile }])
# just send the command first, we read the response inline below
self.runCmds([{ 'cmd': 'pull ' + remoteFile }])
except AgentError:
return None
@ -880,7 +877,6 @@ class DeviceManagerSUT(DeviceManager):
cmd = 'rebt'
if (self.debug > 3): print "INFO: sending rebt command"
callbacksvrstatus = None
if (ipAddr is not None):
#create update.info file:

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

@ -268,10 +268,9 @@ class Emulator(object):
local_port = s.getsockname()[1]
s.close()
output = self._run_adb(['-s', 'emulator-%d' % self.port,
'forward',
'tcp:%d' % local_port,
'tcp:%d' % remote_port])
self._run_adb(['-s', 'emulator-%d' % self.port, 'forward',
'tcp:%d' % local_port,
'tcp:%d' % remote_port])
self.local_port = local_port

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

@ -3,19 +3,18 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
import time
import sys
import os
import socket
import automationutils
import tempfile
import shutil
import subprocess
from automation import Automation
from devicemanager import DeviceManager, NetworkTools
from devicemanager import NetworkTools
class RemoteAutomation(Automation):
_devicemanager = None
def __init__(self, deviceManager, appName = '', remoteLog = None):
self._devicemanager = deviceManager
self._appName = appName
@ -28,7 +27,7 @@ class RemoteAutomation(Automation):
def setDeviceManager(self, deviceManager):
self._devicemanager = deviceManager
def setAppName(self, appName):
self._appName = appName
@ -37,7 +36,7 @@ class RemoteAutomation(Automation):
def setProduct(self, product):
self._product = product
def setRemoteLog(self, logfile):
self._remoteLog = logfile
@ -88,11 +87,11 @@ class RemoteAutomation(Automation):
if (self._remoteProfile):
profileDir = self._remoteProfile
# Hack for robocop, if app & testURL == None and extraArgs contains the rest of the stuff, lets
# Hack for robocop, if app & testURL == None and extraArgs contains the rest of the stuff, lets
# assume extraArgs is all we need
if app == "am" and extraArgs[0] == "instrument":
return app, extraArgs
cmd, args = Automation.buildCommandLine(self, app, debuggerInfo, profileDir, testURL, extraArgs)
# Remove -foreground if it exists, if it doesn't this just returns
try:
@ -113,7 +112,7 @@ class RemoteAutomation(Automation):
return self.RProcess(self._devicemanager, cmd, stdout, stderr, env, cwd)
# be careful here as this inner class doesn't have access to outer class members
# be careful here as this inner class doesn't have access to outer class members
class RProcess(object):
# device manager process
dm = None
@ -162,7 +161,7 @@ class RemoteAutomation(Automation):
if (hexpid == None):
hexpid = "0x0"
return int(hexpid, 0)
@property
def stdout(self):
t = self.dm.getFile(self.proc)
@ -171,7 +170,7 @@ class RemoteAutomation(Automation):
retVal = t[self.stdoutlen:]
self.stdoutlen = tlen
return retVal.strip('\n').strip()
def wait(self, timeout = None):
timer = 0
interval = 5
@ -190,6 +189,6 @@ class RemoteAutomation(Automation):
if (timer >= timeout):
return 1
return 0
def kill(self):
self.dm.killProcess(self.procName)

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

@ -5,15 +5,10 @@
package @ANDROID_PACKAGE_NAME@;
import java.lang.Class;
import java.lang.ClassLoader;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.Long;
import java.lang.NoSuchMethodException;
import java.util.concurrent.SynchronousQueue;
import java.util.ArrayList;
@ -40,15 +35,16 @@ public class FennecNativeActions implements Actions {
// Objects for reflexive access of fennec classes.
private ClassLoader mClassLoader;
private Class mGel;
private Class mGe;
private Class mGas;
private Class mDrawListener;
private Method mRegisterGEL;
private Method mUnregisterGEL;
private Method mSendGE;
private Method mGetLayerClient;
private Class mApiClass;
private Class mEventListenerClass;
private Class mDrawListenerClass;
private Method mRegisterEventListener;
private Method mUnregisterEventListener;
private Method mBroadcastEvent;
private Method mSetDrawListener;
private Method mQuerySql;
private Object mRobocopApi;
private static final String LOGTAG = "FennecNativeActions";
public FennecNativeActions(Activity activity, Solo robocop, Instrumentation instrumentation, Assert asserter) {
@ -59,29 +55,19 @@ public class FennecNativeActions implements Actions {
// Set up reflexive access of java classes and methods.
try {
mClassLoader = activity.getClassLoader();
mGel = mClassLoader.loadClass("org.mozilla.gecko.util.GeckoEventListener");
mGe = mClassLoader.loadClass("org.mozilla.gecko.GeckoEvent");
mGas = mClassLoader.loadClass("org.mozilla.gecko.GeckoAppShell");
Class [] parameters = new Class[2];
parameters[0] = String.class;
parameters[1] = mGel;
mRegisterGEL = mGas.getMethod("registerEventListener", parameters);
mUnregisterGEL = mGas.getMethod("unregisterEventListener", parameters);
parameters = new Class[1];
parameters[0] = mGe;
mSendGE = mGas.getMethod("sendEventToGecko", parameters);
mGetLayerClient = activity.getClass().getMethod("getLayerClient");
Class gslc = mClassLoader.loadClass("org.mozilla.gecko.gfx.GeckoLayerClient");
mDrawListener = mClassLoader.loadClass("org.mozilla.gecko.gfx.GeckoLayerClient$DrawListener");
mSetDrawListener = gslc.getDeclaredMethod("setDrawListener", mDrawListener);
} catch (ClassNotFoundException e) {
FennecNativeDriver.log(LogLevel.ERROR, e);
} catch (SecurityException e) {
FennecNativeDriver.log(LogLevel.ERROR, e);
} catch (NoSuchMethodException e) {
FennecNativeDriver.log(LogLevel.ERROR, e);
} catch (IllegalArgumentException e) {
mApiClass = mClassLoader.loadClass("org.mozilla.gecko.RobocopAPI");
mEventListenerClass = mClassLoader.loadClass("org.mozilla.gecko.util.GeckoEventListener");
mDrawListenerClass = mClassLoader.loadClass("org.mozilla.gecko.gfx.GeckoLayerClient$DrawListener");
mRegisterEventListener = mApiClass.getMethod("registerEventListener", String.class, mEventListenerClass);
mUnregisterEventListener = mApiClass.getMethod("unregisterEventListener", String.class, mEventListenerClass);
mBroadcastEvent = mApiClass.getMethod("broadcastEvent", String.class, String.class);
mSetDrawListener = mApiClass.getMethod("setDrawListener", mDrawListenerClass);
mQuerySql = mApiClass.getMethod("querySql", String.class, String.class);
mRobocopApi = mApiClass.getConstructor(Activity.class).newInstance(activity);
} catch (Exception e) {
FennecNativeDriver.log(LogLevel.ERROR, e);
}
}
@ -144,7 +130,7 @@ public class FennecNativeActions implements Actions {
}
}
try {
mUnregisterGEL.invoke(null, mRegistrationParams);
mUnregisterEventListener.invoke(mRobocopApi, mRegistrationParams);
} catch (IllegalAccessException e) {
FennecNativeDriver.log(LogLevel.ERROR, e);
} catch (InvocationTargetException e) {
@ -192,7 +178,7 @@ public class FennecNativeActions implements Actions {
startTime = endTime;
}
try {
mUnregisterGEL.invoke(null, mRegistrationParams);
mUnregisterEventListener.invoke(mRobocopApi, mRegistrationParams);
} catch (IllegalAccessException e) {
FennecNativeDriver.log(LogLevel.ERROR, e);
} catch (InvocationTargetException e) {
@ -220,17 +206,14 @@ public class FennecNativeActions implements Actions {
FennecNativeDriver.log(FennecNativeDriver.LogLevel.DEBUG,
"waiting for "+geckoEvent);
try {
Class [] interfaces = new Class[1];
interfaces[0] = mGel;
Object[] finalParams = new Object[2];
finalParams[0] = geckoEvent;
GeckoEventExpecter expecter = new GeckoEventExpecter(geckoEvent, finalParams);
wakeInvocationHandler wIH = new wakeInvocationHandler(expecter);
Object proxy = Proxy.newProxyInstance(mClassLoader, interfaces, wIH);
Object proxy = Proxy.newProxyInstance(mClassLoader, new Class[] { mEventListenerClass }, wIH);
finalParams[1] = proxy;
mRegisterGEL.invoke(null, finalParams);
mRegisterEventListener.invoke(mRobocopApi, finalParams);
return expecter;
} catch (IllegalAccessException e) {
FennecNativeDriver.log(LogLevel.ERROR, e);
@ -242,11 +225,7 @@ public class FennecNativeActions implements Actions {
public void sendGeckoEvent(String geckoEvent, String data) {
try {
Method cbe = mGe.getMethod("createBroadcastEvent", String.class, String.class);
Object event = cbe.invoke(null, geckoEvent, data);
mSendGE.invoke(null, event);
} catch (NoSuchMethodException e) {
FennecNativeDriver.log(LogLevel.ERROR, e);
mBroadcastEvent.invoke(mRobocopApi, geckoEvent, data);
} catch (IllegalAccessException e) {
FennecNativeDriver.log(LogLevel.ERROR, e);
} catch (InvocationTargetException e) {
@ -284,8 +263,8 @@ public class FennecNativeActions implements Actions {
private static final int MAX_WAIT_MS = 90000;
PaintExpecter() throws IllegalAccessException, InvocationTargetException {
mLayerClient = mGetLayerClient.invoke(mGeckoApp);
mSetDrawListener.invoke(mLayerClient, Proxy.newProxyInstance(mClassLoader, new Class[] { mDrawListener }, new DrawListenerProxy(this)));
Object proxy = Proxy.newProxyInstance(mClassLoader, new Class[] { mDrawListenerClass }, new DrawListenerProxy(this));
mSetDrawListener.invoke(mRobocopApi, proxy);
}
void notifyOfEvent() {
@ -312,7 +291,7 @@ public class FennecNativeActions implements Actions {
}
}
try {
mSetDrawListener.invoke(mLayerClient, (Object)null);
mSetDrawListener.invoke(mRobocopApi, (Object)null);
} catch (Exception e) {
FennecNativeDriver.log(LogLevel.ERROR, e);
}
@ -360,7 +339,7 @@ public class FennecNativeActions implements Actions {
startTime = endTime;
}
try {
mSetDrawListener.invoke(mLayerClient, (Object)null);
mSetDrawListener.invoke(mRobocopApi, (Object)null);
} catch (Exception e) {
FennecNativeDriver.log(LogLevel.ERROR, e);
}
@ -415,30 +394,9 @@ public class FennecNativeActions implements Actions {
public Cursor querySql(String dbPath, String sql) {
try {
ClassLoader classLoader = mGeckoApp.getClassLoader();
Class sqlClass = classLoader.loadClass("org.mozilla.gecko.sqlite.SQLiteBridge");
Class stringClass = String.class;
Class stringArrayClass = String[].class;
Class appshell = classLoader.loadClass("org.mozilla.gecko.GeckoAppShell");
Class contextClass = Context.class;
Constructor bridgeConstructor = sqlClass.getConstructor(stringClass);
Method query = sqlClass.getMethod("rawQuery", stringClass, stringArrayClass);
Method loadSQLiteLibs = appshell.getMethod("loadSQLiteLibs", contextClass, stringClass);
Object bridge = bridgeConstructor.newInstance(dbPath);
String resourcePath = mGeckoApp.getApplication().getPackageResourcePath();
loadSQLiteLibs.invoke(null, mGeckoApp, resourcePath);
return (Cursor)query.invoke(bridge, sql, null);
} catch(ClassNotFoundException ex) {
Log.e(LOGTAG, "Error getting class", ex);
} catch(NoSuchMethodException ex) {
Log.e(LOGTAG, "Error getting method", ex);
return (Cursor)mQuerySql.invoke(mRobocopApi, dbPath, sql);
} catch(InvocationTargetException ex) {
Log.e(LOGTAG, "Error invoking method", ex);
} catch(InstantiationException ex) {
Log.e(LOGTAG, "Error calling constructor", ex);
} catch(IllegalAccessException ex) {
Log.e(LOGTAG, "Error using field", ex);
}

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

@ -20,12 +20,10 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.lang.Class;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.Long;
import android.app.Activity;
import android.opengl.GLSurfaceView;
@ -49,17 +47,16 @@ public class FennecNativeDriver implements Driver {
// Objects for reflexive access of fennec classes.
private ClassLoader mClassLoader;
private Class mGel;
private Class mGe;
private Class mGas;
private Method mRegisterGEL;
private Method mUnregisterGEL;
private Method mSendGE;
private Method _startFrameRecording;
private Method _stopFrameRecording;
private Method _startCheckerboardRecording;
private Method _stopCheckerboardRecording;
private Method _getPixels;
private Class mApiClass;
private Class mEventListenerClass;
private Class mPanningPerfClass;
private Method mRegisterEventListener;
private Method mGetPixels;
private Method mStartFrameRecording;
private Method mStopFrameRecording;
private Method mStartCheckerboardRecording;
private Method mStopCheckerboardRecording;
private Object mRobocopApi;
public enum LogLevel {
DEBUG(1),
@ -89,33 +86,20 @@ public class FennecNativeDriver implements Driver {
// Set up reflexive access of java classes and methods.
try {
mClassLoader = activity.getClassLoader();
mGel = mClassLoader.loadClass("org.mozilla.gecko.util.GeckoEventListener");
mGe = mClassLoader.loadClass("org.mozilla.gecko.GeckoEvent");
mGas = mClassLoader.loadClass("org.mozilla.gecko.GeckoAppShell");
Class [] parameters = new Class[2];
parameters[0] = String.class;
parameters[1] = mGel;
mRegisterGEL = mGas.getMethod("registerEventListener", parameters);
mUnregisterGEL = mGas.getMethod("unregisterEventListener", parameters);
parameters = new Class[1];
parameters[0] = mGe;
mSendGE = mGas.getMethod("sendEventToGecko", parameters);
Class gfx = mClassLoader.loadClass("org.mozilla.gecko.gfx.PanningPerfAPI");
_startFrameRecording = gfx.getDeclaredMethod("startFrameTimeRecording");
_stopFrameRecording = gfx.getDeclaredMethod("stopFrameTimeRecording");
_startCheckerboardRecording = gfx.getDeclaredMethod("startCheckerboardRecording");
_stopCheckerboardRecording = gfx.getDeclaredMethod("stopCheckerboardRecording");
mApiClass = mClassLoader.loadClass("org.mozilla.gecko.RobocopAPI");
mEventListenerClass = mClassLoader.loadClass("org.mozilla.gecko.util.GeckoEventListener");
mPanningPerfClass = mClassLoader.loadClass("org.mozilla.gecko.gfx.PanningPerfAPI");
Class layerView = mClassLoader.loadClass("org.mozilla.gecko.gfx.LayerView");
_getPixels = layerView.getDeclaredMethod("getPixels");
} catch (ClassNotFoundException e) {
log(LogLevel.ERROR, e);
} catch (SecurityException e) {
log(LogLevel.ERROR, e);
} catch (NoSuchMethodException e) {
log(LogLevel.ERROR, e);
} catch (IllegalArgumentException e) {
mRegisterEventListener = mApiClass.getMethod("registerEventListener", String.class, mEventListenerClass);
mGetPixels = mApiClass.getMethod("getViewPixels", View.class);
mStartFrameRecording = mPanningPerfClass.getDeclaredMethod("startFrameTimeRecording");
mStopFrameRecording = mPanningPerfClass.getDeclaredMethod("stopFrameTimeRecording");
mStartCheckerboardRecording = mPanningPerfClass.getDeclaredMethod("startCheckerboardRecording");
mStopCheckerboardRecording = mPanningPerfClass.getDeclaredMethod("stopCheckerboardRecording");
mRobocopApi = mApiClass.getConstructor(Activity.class).newInstance(activity);
} catch (Exception e) {
log(LogLevel.ERROR, e);
}
}
@ -189,8 +173,7 @@ public class FennecNativeDriver implements Driver {
public void startFrameRecording() {
try {
Object [] params = null;
_startFrameRecording.invoke(null, params);
mStartFrameRecording.invoke(null);
} catch (IllegalAccessException e) {
log(LogLevel.ERROR, e);
} catch (InvocationTargetException e) {
@ -199,12 +182,8 @@ public class FennecNativeDriver implements Driver {
}
public int stopFrameRecording() {
Class [] parameters = new Class[1];
parameters[0] = null;
try {
Object [] params = null;
List<Long> frames = (List<Long>)_stopFrameRecording.invoke(null, params);
List<Long> frames = (List<Long>)mStopFrameRecording.invoke(null);
int badness = 0;
for (int i = 1; i < frames.size(); i++) {
long frameTime = frames.get(i) - frames.get(i - 1);
@ -230,8 +209,7 @@ public class FennecNativeDriver implements Driver {
public void startCheckerboardRecording() {
try {
Object [] params = null;
_startCheckerboardRecording.invoke(null, params);
mStartCheckerboardRecording.invoke(null);
} catch (IllegalAccessException e) {
log(LogLevel.ERROR, e);
} catch (InvocationTargetException e) {
@ -240,12 +218,8 @@ public class FennecNativeDriver implements Driver {
}
public float stopCheckerboardRecording() {
Class [] parameters = new Class[1];
parameters[0] = null;
try {
Object [] params = null;
List<Float> checkerboard = (List<Float>)_stopCheckerboardRecording.invoke(null, params);
List<Float> checkerboard = (List<Float>)mStopCheckerboardRecording.invoke(null);
float total = 0;
for (float val : checkerboard) {
total += val;
@ -281,7 +255,7 @@ public class FennecNativeDriver implements Driver {
}
IntBuffer pixelBuffer;
try {
pixelBuffer = (IntBuffer)_getPixels.invoke(view);
pixelBuffer = (IntBuffer)mGetPixels.invoke(mRobocopApi, view);
} catch (Exception e) {
log(LogLevel.ERROR, e);
return null;
@ -368,11 +342,11 @@ public class FennecNativeDriver implements Driver {
//Setup scrollHandler to catch "robocop:scroll" events.
try {
Class [] interfaces = new Class[1];
interfaces[0] = mGel;
interfaces[0] = mEventListenerClass;
Object[] finalParams = new Object[2];
finalParams[0] = "robocop:scroll";
finalParams[1] = Proxy.newProxyInstance(mClassLoader, interfaces, new scrollHandler());
mRegisterGEL.invoke(null, finalParams);
mRegisterEventListener.invoke(mRobocopApi, finalParams);
} catch (IllegalAccessException e) {
log(LogLevel.ERROR, e);
} catch (InvocationTargetException e) {

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

@ -19,7 +19,7 @@
#include "nsNetUtil.h"
#include "nsIClassInfoImpl.h"
#include "nsNetCID.h"
#include "nsDOMError.h"
#include "nsError.h"
#include "nsIScriptSecurityManager.h"
#include "nsScriptSecurityManager.h"

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

@ -20,7 +20,7 @@
#include "nsIObjectInputStream.h"
#include "nsIObjectOutputStream.h"
#include "nsIClassInfoImpl.h"
#include "nsDOMError.h"
#include "nsError.h"
#include "nsIContentSecurityPolicy.h"
#include "nsContentUtils.h"
#include "jswrapper.h"

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

@ -22,7 +22,7 @@
#include "nsCRT.h"
#include "nsCRTGlue.h"
#include "nsIJSContextStack.h"
#include "nsDOMError.h"
#include "nsError.h"
#include "nsDOMCID.h"
#include "jsdbgapi.h"
#include "nsIXPConnect.h"

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

@ -14,7 +14,7 @@
#include "prprf.h"
#include "nsCOMPtr.h"
#include "nsDOMError.h"
#include "nsError.h"
#include "nsEscape.h"
#include "nsLayoutCID.h"
#include "nsNetUtil.h"

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

@ -18,7 +18,6 @@ mozFlushType.h \
nsIContent.h \
nsIAttribute.h \
nsIContentIterator.h \
nsContentErrors.h \
nsContentPolicyUtils.h \
nsContentUtils.h \
nsIDocument.h \

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

@ -1,61 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
// vim: ft=cpp sw=2 ts=2 tw=78 et
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef nsContentErrors_h___
#define nsContentErrors_h___
/** Error codes for nsHTMLStyleSheet */
// XXX this is not really used
#define NS_HTML_STYLE_PROPERTY_NOT_THERE \
NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_CONTENT, 2)
/** Error codes for image loading */
#define NS_ERROR_IMAGE_SRC_CHANGED \
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_CONTENT, 4)
#define NS_ERROR_IMAGE_BLOCKED \
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_CONTENT, 5)
/** Error codes for content policy blocking */
#define NS_ERROR_CONTENT_BLOCKED \
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_CONTENT, 6)
#define NS_ERROR_CONTENT_BLOCKED_SHOW_ALT \
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_CONTENT, 7)
/** Success variations of content policy blocking */
#define NS_CONTENT_BLOCKED \
NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_CONTENT, 8)
#define NS_CONTENT_BLOCKED_SHOW_ALT \
NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_CONTENT, 9)
#define NS_PROPTABLE_PROP_NOT_THERE \
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_CONTENT, 10)
#define NS_PROPTABLE_PROP_OVERWRITTEN \
NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_CONTENT, 11)
/* Error codes for FindBroadcaster in nsXULDocument.cpp */
#define NS_FINDBROADCASTER_NOT_FOUND \
NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_CONTENT, 12)
#define NS_FINDBROADCASTER_FOUND \
NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_CONTENT, 13)
#define NS_FINDBROADCASTER_AWAIT_OVERLAYS \
NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_CONTENT, 14)
/* Error codes for CSP */
#define NS_ERROR_CSP_FRAME_ANCESTOR_VIOLATION \
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_SECURITY, 99)
/* Error codes for XBL */
#define NS_ERROR_XBL_BLOCKED \
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_CONTENT, 15)
#endif // nsContentErrors_h___

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

@ -20,8 +20,8 @@ class Element;
} // namespace mozilla
#define NS_IMUTATION_OBSERVER_IID \
{ 0x85eea794, 0xed8e, 0x4e1b, \
{ 0xa1, 0x28, 0xd0, 0x93, 0x00, 0xae, 0x51, 0xaa } }
{ 0x16fe5e3e, 0xeadc, 0x4312, \
{ 0x9d, 0x44, 0xb6, 0xbe, 0xdd, 0x6b, 0x54, 0x74 } }
/**
* Information details about a characterdata change. Basically, we
@ -192,6 +192,20 @@ public:
nsIAtom* aAttribute,
PRInt32 aModType) = 0;
/**
* Notification that an attribute of an element has been
* set to the value it already had.
*
* @param aDocument The owner-document of aContent.
* @param aElement The element whose attribute changed
* @param aNameSpaceID The namespace id of the changed attribute
* @param aAttribute The name of the changed attribute
*/
virtual void AttributeSetToCurrentValue(nsIDocument* aDocument,
mozilla::dom::Element* aElement,
PRInt32 aNameSpaceID,
nsIAtom* aAttribute) {}
/**
* Notification that one or more content nodes have been appended to the
* child list of another node in the tree.

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

@ -5,7 +5,7 @@
#include "FileIOObject.h"
#include "nsDOMFile.h"
#include "nsDOMError.h"
#include "nsError.h"
#include "nsIDOMEvent.h"
#include "nsIDOMProgressEvent.h"
#include "nsComponentManagerUtils.h"

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

@ -45,7 +45,7 @@
#include "nsContentList.h"
#include "nsDOMTokenList.h"
#include "nsXBLPrototypeBinding.h"
#include "nsDOMError.h"
#include "nsError.h"
#include "nsDOMString.h"
#include "nsIScriptSecurityManager.h"
#include "nsIDOMMutationEvent.h"

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

@ -4,7 +4,7 @@
#include "nsBlobProtocolHandler.h"
#include "nsBlobURI.h"
#include "nsDOMError.h"
#include "nsError.h"
#include "nsClassHashtable.h"
#include "nsNetUtil.h"
#include "nsIPrincipal.h"

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

@ -16,7 +16,7 @@
#include "nsIChannelEventSink.h"
#include "nsIPropertyBag2.h"
#include "nsIWritablePropertyBag2.h"
#include "nsNetError.h"
#include "nsError.h"
#include "nsChannelProperties.h"
#include "nsIAsyncVerifyRedirectCallback.h"
#include "nsAsyncRedirectVerifyHelper.h"

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

@ -85,7 +85,7 @@ static NS_DEFINE_CID(kXTFServiceCID, NS_XTFSERVICE_CID);
#include "nsContentCreatorFunctions.h"
#include "nsMutationEvent.h"
#include "nsIMEStateManager.h"
#include "nsContentErrors.h"
#include "nsError.h"
#include "nsUnicharUtilCIID.h"
#include "nsINativeKeyBindings.h"
#include "nsXULPopupManager.h"

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

@ -6,7 +6,7 @@
#include "nsCrossSiteListenerProxy.h"
#include "nsIChannel.h"
#include "nsIHttpChannel.h"
#include "nsDOMError.h"
#include "nsError.h"
#include "nsContentUtils.h"
#include "nsIScriptSecurityManager.h"
#include "nsNetUtil.h"

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

@ -12,7 +12,7 @@
#include "mozilla/dom/Element.h"
#include "nsContentCreatorFunctions.h"
#include "nsINameSpaceManager.h"
#include "nsDOMError.h"
#include "nsError.h"
#include "nsUnicharUtils.h"
#include "nsDOMString.h"
#include "nsIDocument.h"

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

@ -13,7 +13,7 @@
#include "nsGenericElement.h"
#include "nsIDocument.h"
#include "nsINameSpaceManager.h"
#include "nsDOMError.h"
#include "nsError.h"
#include "nsContentUtils.h"
#include "nsNodeInfoManager.h"
#include "nsAttrName.h"

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

@ -9,7 +9,7 @@
#include "nsContentCID.h"
#include "nsContentUtils.h"
#include "nsDOMClassInfoID.h"
#include "nsDOMError.h"
#include "nsError.h"
#include "nsICharsetDetector.h"
#include "nsICharsetConverterManager.h"
#include "nsIClassInfo.h"

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

@ -9,7 +9,7 @@
#include "nsContentUtils.h"
#include "nsDOMClassInfoID.h"
#include "nsDOMFile.h"
#include "nsDOMError.h"
#include "nsError.h"
#include "nsCharsetAlias.h"
#include "nsICharsetConverterManager.h"
#include "nsIConverterInputStream.h"

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

@ -8,7 +8,7 @@
*/
#include "nsDOMLists.h"
#include "nsDOMError.h"
#include "nsError.h"
#include "nsDOMClassInfoID.h"
#include "nsINode.h"

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

@ -6,7 +6,7 @@
#include "nsDOMMutationObserver.h"
#include "nsDOMClassInfoID.h"
#include "nsDOMError.h"
#include "nsError.h"
#include "nsIClassInfo.h"
#include "nsIXPCScriptable.h"
#include "nsIScriptGlobalObject.h"

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

@ -21,6 +21,7 @@
#include "mozilla/dom/Element.h"
#include "nsClassHashtable.h"
#include "nsNodeUtils.h"
#include "nsIDOMMutationEvent.h"
class nsDOMMutationObserver;
@ -273,6 +274,16 @@ public:
NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
NS_DECL_NSIMUTATIONOBSERVER_NODEWILLBEDESTROYED
virtual void AttributeSetToCurrentValue(nsIDocument* aDocument,
mozilla::dom::Element* aElement,
PRInt32 aNameSpaceID,
nsIAtom* aAttribute)
{
// We can reuse AttributeWillChange implementation.
AttributeWillChange(aDocument, aElement, aNameSpaceID, aAttribute,
nsIDOMMutationEvent::MODIFICATION);
}
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsMutationReceiver, NS_MUTATION_OBSERVER_IID)

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

@ -22,7 +22,7 @@
#include "nsNetCID.h"
#include "nsContentUtils.h"
#include "nsDOMJSUtils.h"
#include "nsDOMError.h"
#include "nsError.h"
#include "nsIDOMWindow.h"
#include "nsPIDOMWindow.h"
#include "mozilla/AutoRestore.h"

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

@ -13,7 +13,7 @@
#include "nsString.h"
#include "nsContentCID.h"
#include "nsContentUtils.h"
#include "nsDOMError.h"
#include "nsError.h"
nsDOMSerializer::nsDOMSerializer()
{

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

@ -10,7 +10,7 @@
#include "nsAttrValue.h"
#include "nsContentUtils.h"
#include "nsDOMError.h"
#include "nsError.h"
#include "nsGenericElement.h"
#include "dombindings.h"

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

@ -62,7 +62,7 @@
#include "nsIServiceManager.h"
#include "nsContentCID.h"
#include "nsDOMError.h"
#include "nsError.h"
#include "nsIPresShell.h"
#include "nsPresContext.h"
#include "nsIJSON.h"
@ -130,7 +130,6 @@
#include "nsIDocumentLoaderFactory.h"
#include "nsIContentViewer.h"
#include "nsIXMLContentSink.h"
#include "nsContentErrors.h"
#include "nsIXULDocument.h"
#include "nsIPrompt.h"
#include "nsIPropertyBag2.h"

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

@ -13,7 +13,7 @@
#include "nsINameSpaceManager.h"
#include "nsINodeInfo.h"
#include "nsNodeInfoManager.h"
#include "nsDOMError.h"
#include "nsError.h"
#include "nsGkAtoms.h"
#include "nsDOMString.h"
#include "nsContentUtils.h"

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

@ -33,7 +33,7 @@
#include "nsDOMEventTargetHelper.h"
#include "mozilla/Attributes.h"
#include "nsDOMClassInfoID.h"
#include "nsDOMError.h"
#include "nsError.h"
using namespace mozilla;

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

@ -46,7 +46,7 @@
#include "nsIFrame.h"
#include "nsIScrollableFrame.h"
#include "nsSubDocumentFrame.h"
#include "nsDOMError.h"
#include "nsError.h"
#include "nsGUIEvent.h"
#include "nsEventDispatcher.h"
#include "nsISHistory.h"

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

@ -10,7 +10,7 @@
#include "ContentChild.h"
#include "ContentParent.h"
#include "nsContentUtils.h"
#include "nsDOMError.h"
#include "nsError.h"
#include "nsIXPConnect.h"
#include "jsapi.h"
#include "nsJSUtils.h"

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

@ -14,7 +14,7 @@
#include "nsIContent.h"
#include "nsTextFragment.h"
#include "nsDOMError.h"
#include "nsError.h"
#include "nsEventListenerManager.h"
#include "nsGenericElement.h"
#include "nsCycleCollectionParticipant.h"

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

@ -45,7 +45,7 @@
#include "nsContentList.h"
#include "nsDOMTokenList.h"
#include "nsXBLPrototypeBinding.h"
#include "nsDOMError.h"
#include "nsError.h"
#include "nsDOMString.h"
#include "nsIScriptSecurityManager.h"
#include "nsIDOMMutationEvent.h"
@ -1883,13 +1883,7 @@ nsGenericElement::MaybeCheckSameAttrVal(PRInt32 aNamespaceID,
}
bool valueMatches = aValue.EqualsAsStrings(*info.mValue);
if (valueMatches && aPrefix == info.mName->GetPrefix()) {
if (OwnerDoc()->MayHaveDOMMutationObservers()) {
// For backward compatibility, don't fire mutation events
// when setting an attribute to its old value.
*aHasListeners = false;
} else {
return true;
}
return true;
}
modification = true;
}
@ -1920,8 +1914,8 @@ nsGenericElement::SetAttr(PRInt32 aNamespaceID, nsIAtom* aName,
nsAttrValueOrString value(aValue);
nsAttrValue oldValue;
if (MaybeCheckSameAttrVal(aNamespaceID, aName, aPrefix, value, aNotify,
oldValue, &modType, &hasListeners)) {
if (OnlyNotifySameValueSet(aNamespaceID, aName, aPrefix, value, aNotify,
oldValue, &modType, &hasListeners)) {
return NS_OK;
}
@ -1967,8 +1961,8 @@ nsGenericElement::SetParsedAttr(PRInt32 aNamespaceID, nsIAtom* aName,
nsAttrValueOrString value(aParsedValue);
nsAttrValue oldValue;
if (MaybeCheckSameAttrVal(aNamespaceID, aName, aPrefix, value, aNotify,
oldValue, &modType, &hasListeners)) {
if (OnlyNotifySameValueSet(aNamespaceID, aName, aPrefix, value, aNotify,
oldValue, &modType, &hasListeners)) {
return NS_OK;
}

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

@ -36,7 +36,7 @@
#include "nsIInlineEventHandlers.h"
#include "mozilla/CORSMode.h"
#include "mozilla/Attributes.h"
#include "nsContentUtils.h"
#include "nsISMILAttr.h"
class nsIDOMAttr;
@ -102,6 +102,22 @@ public:
const nsAttrValueOrString& aValue,
bool aNotify, nsAttrValue& aOldValue,
PRUint8* aModType, bool* aHasListeners);
bool OnlyNotifySameValueSet(PRInt32 aNamespaceID, nsIAtom* aName,
nsIAtom* aPrefix,
const nsAttrValueOrString& aValue,
bool aNotify, nsAttrValue& aOldValue,
PRUint8* aModType, bool* aHasListeners)
{
if (MaybeCheckSameAttrVal(aNamespaceID, aName, aPrefix, aValue, aNotify,
aOldValue, aModType, aHasListeners)) {
nsAutoScriptBlocker scriptBlocker;
nsNodeUtils::AttributeSetToCurrentValue(this, aNamespaceID, aName);
return true;
}
return false;
}
virtual nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName, nsIAtom* aPrefix,
const nsAString& aValue, bool aNotify);
virtual nsresult SetParsedAttr(PRInt32 aNameSpaceID, nsIAtom* aName,

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

@ -30,7 +30,7 @@
#include "nsDOMAttributeMap.h"
#include "nsDOMCID.h"
#include "nsDOMCSSAttrDeclaration.h"
#include "nsDOMError.h"
#include "nsError.h"
#include "nsDOMMutationObserver.h"
#include "nsDOMString.h"
#include "nsDOMTokenList.h"

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

@ -12,7 +12,7 @@
#include "nsImageLoadingContent.h"
#include "nsAutoPtr.h"
#include "nsContentErrors.h"
#include "nsError.h"
#include "nsIContent.h"
#include "nsIDocument.h"
#include "nsIScriptGlobalObject.h"

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

@ -12,7 +12,7 @@
#include "nsIDOMNode.h"
#include "nsIDOMNodeFilter.h"
#include "nsDOMError.h"
#include "nsError.h"
#include "nsIContent.h"
#include "nsIDocument.h"

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

@ -107,6 +107,16 @@ nsNodeUtils::AttributeChanged(Element* aElement,
aModType));
}
void
nsNodeUtils::AttributeSetToCurrentValue(Element* aElement,
PRInt32 aNameSpaceID,
nsIAtom* aAttribute)
{
nsIDocument* doc = aElement->OwnerDoc();
IMPL_MUTATION_NOTIFICATION(AttributeSetToCurrentValue, aElement,
(doc, aElement, aNameSpaceID, aAttribute));
}
void
nsNodeUtils::ContentAppended(nsIContent* aContainer,
nsIContent* aFirstNewContent,

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

@ -64,6 +64,16 @@ public:
PRInt32 aNameSpaceID,
nsIAtom* aAttribute,
PRInt32 aModType);
/**
* Send AttributeSetToCurrentValue notifications to nsIMutationObservers.
* @param aElement Element whose data changed
* @param aNameSpaceID Namespace of the attribute
* @param aAttribute Local-name of the attribute
* @see nsIMutationObserver::AttributeSetToCurrentValue
*/
static void AttributeSetToCurrentValue(mozilla::dom::Element* aElement,
PRInt32 aNameSpaceID,
nsIAtom* aAttribute);
/**
* Send ContentAppended notifications to nsIMutationObservers

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

@ -38,7 +38,7 @@
#include "nsIAsyncVerifyRedirectCallback.h"
#include "nsIAppShell.h"
#include "nsPluginError.h"
#include "nsError.h"
// Util headers
#include "prenv.h"
@ -540,7 +540,7 @@ IsPluginEnabledForType(const nsCString& aMIMEType)
if (!pluginHost) {
NS_NOTREACHED("No pluginhost");
return false;
return NS_ERROR_FAILURE;
}
nsresult rv = pluginHost->IsPluginEnabledForType(aMIMEType.get());
@ -726,7 +726,7 @@ nsObjectLoadingContent::InstantiatePluginInstance()
if (!pluginHost) {
NS_NOTREACHED("No pluginhost");
return false;
return NS_ERROR_FAILURE;
}
// If you add early return(s), be sure to balance this call to

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

@ -22,7 +22,7 @@
#include "nsPropertyTable.h"
#include "pldhash.h"
#include "nsContentErrors.h"
#include "nsError.h"
#include "nsIAtom.h"
struct PropertyListMapEntry : public PLDHashEntryHdr {

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

@ -19,7 +19,7 @@
#include "nsIContent.h"
#include "nsIDocument.h"
#include "nsIDOMText.h"
#include "nsDOMError.h"
#include "nsError.h"
#include "nsIContentIterator.h"
#include "nsIDOMNodeList.h"
#include "nsGkAtoms.h"

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

@ -31,7 +31,7 @@
#include "nsUnicharUtils.h"
#include "nsAutoPtr.h"
#include "nsIXPConnect.h"
#include "nsContentErrors.h"
#include "nsError.h"
#include "nsThreadUtils.h"
#include "nsDocShellCID.h"
#include "nsIContentSecurityPolicy.h"

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

@ -8,7 +8,7 @@
#include "nsIDOMNode.h"
#include "nsIDOMNodeFilter.h"
#include "nsDOMError.h"
#include "nsError.h"
#include "nsINode.h"
#include "nsGkAtoms.h"

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

@ -12,7 +12,7 @@
#include "nsIDOMNode.h"
#include "nsIDOMNodeFilter.h"
#include "nsDOMError.h"
#include "nsError.h"
#include "nsINode.h"
#include "nsDOMClassInfoID.h"
#include "nsContentUtils.h"

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

@ -15,7 +15,7 @@
#include "nsIXPConnect.h"
#include "nsContentUtils.h"
#include "nsEventDispatcher.h"
#include "nsDOMError.h"
#include "nsError.h"
#include "nsIScriptObjectPrincipal.h"
#include "nsDOMClassInfoID.h"
#include "jsapi.h"
@ -42,7 +42,6 @@
#include "nsDOMLists.h"
#include "xpcpublic.h"
#include "nsContentPolicyUtils.h"
#include "nsContentErrors.h"
#include "jsfriendapi.h"
#include "prmem.h"
#include "nsDOMFile.h"

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

@ -51,10 +51,9 @@
#include "nsCycleCollectionParticipant.h"
#include "nsIContentPolicy.h"
#include "nsContentPolicyUtils.h"
#include "nsContentErrors.h"
#include "nsError.h"
#include "nsLayoutStatics.h"
#include "nsCrossSiteListenerProxy.h"
#include "nsDOMError.h"
#include "nsIHTMLDocument.h"
#include "nsIMultiPartChannel.h"
#include "nsIScriptObjectPrincipal.h"

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

@ -43,6 +43,7 @@ MOCHITEST_CHROME_FILES = \
test_bug752226-3.xul \
test_bug752226-4.xul \
test_bug682305.html \
test_bug780199.xul \
$(NULL)
include $(topsrcdir)/config/rules.mk

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

@ -0,0 +1,51 @@
<?xml version="1.0"?>
<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=780199
-->
<window title="Mozilla Bug 780199"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
onload="test()">
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
<!-- test results are displayed in the html:body -->
<body xmlns="http://www.w3.org/1999/xhtml">
<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=780199"
target="_blank">Mozilla Bug 780199</a>
</body>
<!-- test code goes here -->
<script type="application/javascript">
<![CDATA[
/** Test for Bug 780199 **/
SimpleTest.waitForExplicitFinish();
var b;
function callback(r) {
is(r[0].type, "attributes");
is(r[0].oldValue, b.getAttribute("src"));
setTimeout(continueTest, 500);
}
function continueTest() {
// Check that a new page wasn't loaded.
is(b.contentDocument.documentElement.textContent, "testvalue");
SimpleTest.finish();
}
function test() {
b = document.getElementById("b");
var m = MutationObserver(callback);
m.observe(b, { attributes: true, attributeOldValue: true });
b.contentDocument.documentElement.textContent = "testvalue";
b.setAttribute("src", b.getAttribute("src"));
}
]]>
</script>
<browser id="b" src="data:text/plain,initial"/>
</window>

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

@ -2,7 +2,7 @@
* 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/. */
do_load_httpd_js();
Components.utils.import("resource://testing-common/httpd.js");
var server = null;
@ -36,7 +36,7 @@ function headerCheckHandler(metadata, response) {
}
function run_test() {
var server = new nsHttpServer();
var server = new HttpServer();
server.registerPathHandler(redirectPath, redirectHandler);
server.registerPathHandler(headerCheckPath, headerCheckHandler);
server.start(SERVER_PORT);

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

@ -1,5 +1,11 @@
Components.utils.import('resource://gre/modules/CSPUtils.jsm');
do_load_httpd_js();
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cu = Components.utils;
const Cr = Components.results;
Cu.import('resource://gre/modules/CSPUtils.jsm');
Cu.import("resource://testing-common/httpd.js");
var httpserv = null;
@ -16,9 +22,9 @@ var TESTS = [];
// helper to make URIs
function mkuri(foo) {
return Components.classes["@mozilla.org/network/io-service;1"]
.getService(Components.interfaces.nsIIOService)
.newURI(foo, null, null);
return Cc["@mozilla.org/network/io-service;1"]
.getService(Ci.nsIIOService)
.newURI(foo, null, null);
}
// helper to use .equals on stuff
@ -87,7 +93,7 @@ listener.prototype = {
};
function run_test() {
httpserv = new nsHttpServer();
httpserv = new HttpServer();
httpserv.registerPathHandler("/document", csp_doc_response);
httpserv.registerPathHandler("/policy", csp_policy_response);
httpserv.start(POLICY_PORT);

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

@ -2,11 +2,16 @@
* 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/. */
Components.utils.import('resource://gre/modules/CSPUtils.jsm');
Components.utils.import('resource://gre/modules/NetUtil.jsm');
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cu = Components.utils;
const Cr = Components.results;
Cu.import('resource://gre/modules/CSPUtils.jsm');
Cu.import('resource://gre/modules/NetUtil.jsm');
// load the HTTP server
do_load_httpd_js();
Cu.import("resource://testing-common/httpd.js");
const REPORT_SERVER_PORT = 9000;
const REPORT_SERVER_URI = "http://localhost";
@ -87,7 +92,7 @@ function run_test() {
":" + REPORT_SERVER_PORT +
"/foo/self");
httpServer = new nsHttpServer();
httpServer = new HttpServer();
httpServer.start(REPORT_SERVER_PORT);
// test that inline script violations cause a report.

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

@ -2,14 +2,19 @@
* 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 Cc = Components.classes;
const Ci = Components.interfaces;
const Cu = Components.utils;
const Cr = Components.results;
//load('CSPUtils.jsm');
Components.utils.import('resource://gre/modules/CSPUtils.jsm');
Components.utils.import('resource://gre/modules/NetUtil.jsm');
Cu.import('resource://gre/modules/CSPUtils.jsm');
Cu.import('resource://gre/modules/NetUtil.jsm');
// load the HTTP server
do_load_httpd_js();
Cu.import("resource://testing-common/httpd.js");
var httpServer = new nsHttpServer();
var httpServer = new HttpServer();
const POLICY_FROM_URI = "allow 'self'; img-src *";
const POLICY_PORT = 9000;
@ -18,8 +23,8 @@ const POLICY_URI_RELATIVE = "/policy";
//converts string to nsIURI
function URI(uriString) {
var ioService = Components.classes["@mozilla.org/network/io-service;1"]
.getService(Components.interfaces.nsIIOService);
var ioService = Cc["@mozilla.org/network/io-service;1"]
.getService(Ci.nsIIOService);
return ioService.newURI(uriString, null, null);
}

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

@ -3,7 +3,7 @@
* 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 "nsDOMError.h"
#include "nsError.h"
#include "nsIDOMCanvasRenderingContext2D.h"
#include "mozilla/CheckedInt.h"
#include "nsMathUtils.h"

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

@ -11,7 +11,7 @@
#include "nsIClassInfoImpl.h"
#include "nsContentUtils.h"
#include "nsIXPConnect.h"
#include "nsDOMError.h"
#include "nsError.h"
#include "nsIGfxInfo.h"
#include "nsIPropertyBag.h"

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

@ -13,7 +13,7 @@
#include "gfxPlatform.h"
#include "nsContentUtils.h"
#include "nsDOMError.h"
#include "nsError.h"
#include "nsLayoutUtils.h"
#include "CanvasUtils.h"

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

@ -26,7 +26,7 @@
#include "nsIVariant.h"
#include "nsIInterfaceRequestorUtils.h"
#include "nsDOMError.h"
#include "nsError.h"
#include "nsIScriptError.h"
#include "nsCSSParser.h"

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

@ -25,7 +25,7 @@
#include "nsIInterfaceRequestorUtils.h"
#include "nsIFrame.h"
#include "nsDOMError.h"
#include "nsError.h"
#include "nsIScriptError.h"
#include "nsCSSParser.h"

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

@ -17,7 +17,7 @@
#include "nsIScriptSecurityManager.h"
#include "nsDOMLists.h"
#include "nsGUIEvent.h"
#include "nsDOMError.h"
#include "nsError.h"
#include "nsIDragService.h"
#include "nsIScriptableRegion.h"
#include "nsContentUtils.h"

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

@ -10,7 +10,7 @@
#include "IPC/IPCMessageUtils.h"
#include "nsCOMPtr.h"
#include "nsDOMError.h"
#include "nsError.h"
#include "nsDOMEvent.h"
#include "nsEventStateManager.h"
#include "nsIFrame.h"

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

@ -4,7 +4,7 @@
* 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 "nsDOMError.h"
#include "nsError.h"
#include "nsDOMNotifyAudioAvailableEvent.h"
#include "nsDOMClassInfoID.h" // DOMCI_DATA, NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO
#include "nsContentUtils.h" // NS_DROP_JS_OBJECTS

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

@ -9,7 +9,7 @@
#include "nsPresContext.h"
#include "nsEventListenerManager.h"
#include "nsContentUtils.h"
#include "nsDOMError.h"
#include "nsError.h"
#include "mozilla/FunctionTimer.h"
#include "nsMutationEvent.h"
#include NEW_H

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

@ -32,7 +32,7 @@
#include "nsCOMPtr.h"
#include "nsIServiceManager.h"
#include "nsIScriptSecurityManager.h"
#include "nsDOMError.h"
#include "nsError.h"
#include "nsIJSContextStack.h"
#include "nsIDocument.h"
#include "nsIPresShell.h"

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

@ -10,7 +10,7 @@
#include "nsGenericHTMLElement.h"
#include "nsGkAtoms.h"
#include "nsSize.h"
#include "nsDOMError.h"
#include "nsError.h"
#include "nsNodeInfoManager.h"
#include "nsICanvasElementExternal.h"

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

@ -4,7 +4,7 @@
* 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 "nsDOMError.h"
#include "nsError.h"
#include "nsDOMStringMap.h"
#include "nsDOMClassInfoID.h"

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

@ -15,7 +15,7 @@
#include "nsGkAtoms.h"
#include "nsIFormControl.h"
#include "nsIDOMHTMLFormElement.h"
#include "nsDOMError.h"
#include "nsError.h"
#include "nsGenericHTMLElement.h"
#include "nsISaveAsCharset.h"
#include "nsIFile.h"

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

@ -44,7 +44,7 @@
#include "nsIDocShell.h"
#include "nsIDocShellTreeItem.h"
#include "nsINameSpaceManager.h"
#include "nsDOMError.h"
#include "nsError.h"
#include "nsScriptLoader.h"
#include "nsRuleData.h"

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

@ -3,7 +3,7 @@
/* 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 "nsDOMError.h"
#include "nsError.h"
#include "nsIDOMHTMLAudioElement.h"
#include "nsHTMLAudioElement.h"
#include "nsGenericHTMLElement.h"

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

@ -25,7 +25,7 @@
#include "nsLayoutUtils.h"
#include "nsEventDispatcher.h"
#include "nsPresState.h"
#include "nsLayoutErrors.h"
#include "nsError.h"
#include "nsFocusManager.h"
#include "nsHTMLFormElement.h"
#include "nsIConstraintValidation.h"

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

@ -12,7 +12,7 @@
#include "nsPresContext.h"
#include "nsIDocument.h"
#include "nsIFormControlFrame.h"
#include "nsDOMError.h"
#include "nsError.h"
#include "nsContentUtils.h"
#include "nsInterfaceHashtable.h"
#include "nsContentList.h"

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

@ -8,7 +8,7 @@
#include "nsIDOMHTMLFrameElement.h"
#include "nsGenericHTMLFrameElement.h"
#include "nsGkAtoms.h"
#include "nsDOMError.h"
#include "nsError.h"
class nsIDOMDocument;

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

@ -9,7 +9,7 @@
#include "nsIDOMSVGDocument.h"
#include "nsGkAtoms.h"
#include "nsMappedAttributes.h"
#include "nsDOMError.h"
#include "nsError.h"
#include "nsRuleData.h"
#include "nsStyleConsts.h"

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

@ -36,7 +36,7 @@
#include "nsEventStates.h"
#include "nsIServiceManager.h"
#include "nsIScriptSecurityManager.h"
#include "nsDOMError.h"
#include "nsError.h"
#include "nsIEditor.h"
#include "nsGUIEvent.h"
#include "nsIIOService.h"
@ -44,7 +44,6 @@
#include "nsAttrValueOrString.h"
#include "nsPresState.h"
#include "nsLayoutErrors.h"
#include "nsIDOMEvent.h"
#include "nsIDOMNodeList.h"
#include "nsIDOMHTMLCollection.h"

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