Merge m-c to b2g-inbound a=merge CLOSED TREE

This commit is contained in:
Wes Kocher 2015-02-05 17:27:46 -08:00
commit beffbe39d1
603 changed files with 6650 additions and 6045 deletions

View File

@ -186,6 +186,14 @@ this.EventManager.prototype = {
}
break;
}
case Events.NAME_CHANGE:
{
let acc = aEvent.accessible;
if (acc === this.contentControl.vc.position) {
this.present(Presentation.nameChanged(acc));
}
break;
}
case Events.SCROLLING_START:
{
this.contentControl.autoMove(aEvent.accessible);

View File

@ -74,6 +74,12 @@ Presenter.prototype = {
*/
selectionChanged: function selectionChanged(aObject) {}, // jshint ignore:line
/**
* Name has changed.
* @param {nsIAccessible} aAccessible the object whose value has changed.
*/
nameChanged: function nameChanged(aAccessible) {}, // jshint ignore: line
/**
* Value has changed.
* @param {nsIAccessible} aAccessible the object whose value has changed.
@ -514,6 +520,17 @@ B2GPresenter.prototype.pivotChanged =
};
};
B2GPresenter.prototype.nameChanged =
function B2GPresenter_nameChanged(aAccessible) {
return {
type: this.type,
details: {
eventType: 'name-change',
data: aAccessible.name
}
};
};
B2GPresenter.prototype.valueChanged =
function B2GPresenter_valueChanged(aAccessible) {
@ -689,6 +706,10 @@ this.Presentation = { // jshint ignore:line
aIsFromUserInput) for each (p in this.presenters)]; // jshint ignore:line
},
nameChanged: function nameChanged(aAccessible) {
return [ p.nameChanged(aAccessible) for (p of this.presenters) ]; // jshint ignore:line
},
valueChanged: function valueChanged(aAccessible) {
return [ p.valueChanged(aAccessible) for (p of this.presenters) ]; // jshint ignore:line
},

View File

@ -40,6 +40,10 @@
document.getElementById('iframe').setAttribute('aria-hidden', true);
}
function renameFruit() {
document.getElementById('fruit').setAttribute('aria-label', 'banana');
}
</script>
<style>
#windows {
@ -84,5 +88,6 @@
<div id="appframe"></div>
</div>
<button id="home">Home</button>
<button id="fruit" aria-label="apple"></button>
</body>
</html>

View File

@ -617,6 +617,15 @@ function ExpectedCheckAction(aChecked, aOptions) {
ExpectedCheckAction.prototype = Object.create(ExpectedPresent.prototype);
function ExpectedNameChange(aName, aOptions) {
ExpectedPresent.call(this, {
eventType: 'name-change',
data: aName
}, null, aOptions);
}
ExpectedNameChange.prototype = Object.create(ExpectedPresent.prototype);
function ExpectedValueChange(aValue, aOptions) {
ExpectedPresent.call(this, {
eventType: 'value-change',

View File

@ -56,8 +56,12 @@
[ContentMessages.moveOrAdjustUp(), new ExpectedValueChange('6')],
[ContentMessages.simpleMoveNext,
new ExpectedCursorChange(['Home', {'string': 'pushbutton'}])],
[ContentMessages.simpleMoveNext,
new ExpectedCursorChange(['apple', {'string': 'pushbutton'}])],
// Simple traversal backward
[ContentMessages.simpleMovePrevious,
new ExpectedCursorChange(['Home', {'string': 'pushbutton'}])],
[ContentMessages.simpleMovePrevious,
new ExpectedCursorChange(['much range', '6', {'string': 'slider'}, 'such app'])],
[ContentMessages.moveOrAdjustDown(), new ExpectedValueChange('5')],
@ -88,7 +92,7 @@
// Move from an inner frame to the last element in the parent doc
[ContentMessages.simpleMoveLast,
new ExpectedCursorChange(
['Home', {'string': 'pushbutton'}], { b2g_todo: true })],
['apple', {'string': 'pushbutton'}], { b2g_todo: true })],
[ContentMessages.clearCursor, 'AccessFu:CursorCleared'],
@ -136,6 +140,17 @@
// Reset cursors
[ContentMessages.clearCursor, 'AccessFu:CursorCleared'],
// Current virtual cursor's position's name changes
[ContentMessages.simpleMoveNext,
new ExpectedCursorChange(['Phone status bar', 'Traversal Rule test document'])],
[ContentMessages.focusSelector('button#fruit', false),
new ExpectedCursorChange(['apple', {'string': 'pushbutton'}])],
[doc.defaultView.renameFruit, new ExpectedNameChange('banana')],
// Blur button and reset cursor
[ContentMessages.focusSelector('button#fruit', true), null],
[ContentMessages.clearCursor, 'AccessFu:CursorCleared'],
// Move cursor with focus in outside document
[ContentMessages.simpleMoveNext,
new ExpectedCursorChange(['Phone status bar', 'Traversal Rule test document'])],
@ -207,14 +222,14 @@
// Open dialog in outer doc, while cursor is also in outer doc
[ContentMessages.simpleMoveLast,
new ExpectedCursorChange(['Home', {'string': 'pushbutton'}])],
new ExpectedCursorChange(['banana', {'string': 'pushbutton'}])],
[doc.defaultView.showAlert,
new ExpectedCursorChange(['This is an alert!',
{'string': 'headingLevel', 'args': [1]},
{'string': 'dialog'}])],
[doc.defaultView.hideAlert,
new ExpectedCursorChange(['Home', {'string': 'pushbutton'}])],
new ExpectedCursorChange(['banana', {'string': 'pushbutton'}])],
[ContentMessages.clearCursor, 'AccessFu:CursorCleared'],
@ -253,6 +268,8 @@
doc.querySelector('button#home').focus();
}, new ExpectedCursorChange(['Home', {'string': 'pushbutton'},
'Traversal Rule test document'])],
[ContentMessages.simpleMoveNext,
new ExpectedCursorChange(['banana', {'string': 'pushbutton'}])]
[ContentMessages.simpleMoveNext, new ExpectedNoMove()]
]);

View File

@ -1171,20 +1171,3 @@ Services.obs.addObserver(function resetProfile(subject, topic, data) {
.getService(Ci.nsIAppStartup);
appStartup.quit(Ci.nsIAppStartup.eForceQuit);
}, 'b2g-reset-profile', false);
/**
* CID of our implementation of nsITransfer.
*/
const kTransferCid = Components.ID("{1b4c85df-cbdd-4bb6-b04e-613caece083c}");
/**
* Contract ID of the service implementing nsITransfer.
*/
const kTransferContractId = "@mozilla.org/transfer;1";
// Override Toolkit's nsITransfer implementation with the one from the
// JavaScript API for downloads. This will eventually be removed when
// nsIDownloadManager will not be available anymore (bug 851471).
Components.manager.QueryInterface(Ci.nsIComponentRegistrar)
.registerFactory(kTransferCid, "",
kTransferContractId, null);

View File

@ -1756,6 +1756,12 @@ pref("identity.fxaccounts.remote.signin.uri", "https://accounts.firefox.com/sign
// "identity.fxaccounts.remote.signup.uri" pref.
pref("identity.fxaccounts.settings.uri", "https://accounts.firefox.com/settings");
// The remote URL of the FxA Profile Server
pref("identity.fxaccounts.remote.profile.uri", "https://profile.accounts.firefox.com/v1");
// The remote URL of the FxA OAuth Server
pref("identity.fxaccounts.remote.oauth.uri", "https://oauth.accounts.firefox.com/v1");
// Migrate any existing Firefox Account data from the default profile to the
// Developer Edition profile.
#ifdef MOZ_DEV_EDITION

View File

@ -823,10 +823,12 @@ function _loadURIWithFlags(browser, uri, flags, referrer, charset, postdata) {
browser.userTypedClear++;
}
let shouldBeRemote = gMultiProcessBrowser &&
E10SUtils.shouldBrowserBeRemote(uri);
let process = browser.isRemoteBrowser ? Ci.nsIXULRuntime.PROCESS_TYPE_CONTENT
: Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT;
let mustChangeProcess = gMultiProcessBrowser &&
!E10SUtils.canLoadURIInProcess(uri, process);
try {
if (browser.isRemoteBrowser == shouldBeRemote) {
if (!mustChangeProcess) {
browser.webNavigation.loadURI(uri, flags, referrer, postdata, null);
} else {
LoadInOtherProcess(browser, {
@ -840,7 +842,7 @@ function _loadURIWithFlags(browser, uri, flags, referrer, charset, postdata) {
// We might lose history that way but at least the browser loaded a page.
// This might be necessary if SessionStore wasn't initialized yet i.e.
// when the homepage is a non-remote page.
gBrowser.updateBrowserRemoteness(browser, shouldBeRemote);
gBrowser.updateBrowserRemotenessByURL(browser, uri);
browser.webNavigation.loadURI(uri, flags, referrer, postdata, null);
} finally {
if (browser.userTypedClear) {

View File

@ -1514,9 +1514,18 @@
<parameter name="aURL"/>
<body>
<![CDATA[
let shouldBeRemote = gMultiProcessBrowser &&
E10SUtils.shouldBrowserBeRemote(aURL);
return this.updateBrowserRemoteness(aBrowser, shouldBeRemote);
if (!gMultiProcessBrowser)
return this.updateBrowserRemoteness(aBrowser, false);
let process = aBrowser.isRemoteBrowser ? Ci.nsIXULRuntime.PROCESS_TYPE_CONTENT
: Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT;
// If this URL can't load in the browser's current process then flip
// it to the other process
if (!E10SUtils.canLoadURIInProcess(aURL, process))
return this.updateBrowserRemoteness(aBrowser, !aBrowser.isRemoteBrowser);
return false;
]]>
</body>
</method>
@ -1690,7 +1699,10 @@
t.setAttribute("onerror", "this.removeAttribute('image');");
t.className = "tabbrowser-tab";
let remote = gMultiProcessBrowser && E10SUtils.shouldBrowserBeRemote(aURI);
// The new browser should be remote if this is an e10s window and
// the uri to load can be loaded remotely.
let remote = gMultiProcessBrowser &&
E10SUtils.canLoadURIInProcess(aURI, Ci.nsIXULRuntime.PROCESS_TYPE_CONTENT);
if (remote)
t.setAttribute("remote", "true");

View File

@ -61,12 +61,14 @@ function doTest(evt) {
function reportResult(info, pass, error) {
let data = {type: "testResult", info: info, pass: pass, error: error};
window.parent.postMessage(data, "*");
let event = new CustomEvent("FirefoxAccountsTestResponse", {detail: {data: data}, bubbles: true});
document.dispatchEvent(event);
}
function reportFinished(cmd) {
let data = {type: "testsComplete", count: tests.length};
window.parent.postMessage(data, "*");
let event = new CustomEvent("FirefoxAccountsTestResponse", {detail: {data: data}, bubbles: true});
document.dispatchEvent(event);
}
function sendToBrowser(type, data) {

View File

@ -79,6 +79,7 @@ support-files =
test_bug628179.html
test_bug839103.html
test_bug959531.html
test_process_flags_chrome.html
test_wyciwyg_copying.html
title_test.svg
video.ogg
@ -480,6 +481,8 @@ skip-if = e10s
skip-if = e10s # Bug 1100687 - test directly manipulates content (content.document.getElementById)
[browser_bug1045809.js]
[browser_e10s_switchbrowser.js]
[browser_e10s_about_process.js]
[browser_e10s_chrome_process.js]
[browser_blockHPKP.js]
skip-if = e10s # bug 1100687 - test directly manipulates content (content.document.getElementById)
[browser_mcb_redirect.js]

View File

@ -45,26 +45,24 @@ let gTests = [
{
setPref("identity.fxaccounts.remote.signup.uri",
"https://example.com/browser/browser/base/content/test/general/accounts_testRemoteCommands.html");
yield promiseNewTabLoadEvent("about:accounts");
let tab = yield promiseNewTabLoadEvent("about:accounts");
let mm = tab.linkedBrowser.messageManager;
let deferred = Promise.defer();
let results = 0;
try {
let win = gBrowser.contentWindow;
win.addEventListener("message", function testLoad(e) {
if (e.data.type == "testResult") {
ok(e.data.pass, e.data.info);
mm.addMessageListener("test:response", function responseHandler(msg) {
let data = msg.data.data;
if (data.type == "testResult") {
ok(data.pass, data.info);
results++;
}
else if (e.data.type == "testsComplete") {
is(results, e.data.count, "Checking number of results received matches the number of tests that should have run");
win.removeEventListener("message", testLoad, false, true);
} else if (data.type == "testsComplete") {
is(results, data.count, "Checking number of results received matches the number of tests that should have run");
mm.removeMessageListener("test:response", responseHandler);
deferred.resolve();
}
}, false, true);
});
} catch(e) {
ok(false, "Failed to get all commands");
deferred.reject();
@ -217,10 +215,10 @@ let gTests = [
yield OS.File.writeAtomic(fxAccountsStorage, JSON.stringify(signedInUser));
info("Wrote file " + fxAccountsStorage);
// this is a little subtle - we load about:blank so we get a tab, then
// we send a message which does both (a) load the URL we want and (b) mocks
// the default profile path used by about:accounts.
let tab = yield promiseNewTabLoadEvent("about:blank?");
// this is a little subtle - we load about:robots so we get a non-remote
// tab, then we send a message which does both (a) load the URL we want and
// (b) mocks the default profile path used by about:accounts.
let tab = yield promiseNewTabLoadEvent("about:robots");
let readyPromise = promiseOneMessage(tab, "test:load-with-mocked-profile-path-response");
let mm = tab.linkedBrowser.messageManager;
@ -261,7 +259,7 @@ let gTests = [
mockDir.createUnique(Ci.nsIFile.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY);
// but leave it empty, so we don't think a user is logged in.
let tab = yield promiseNewTabLoadEvent("about:blank?");
let tab = yield promiseNewTabLoadEvent("about:robots");
let readyPromise = promiseOneMessage(tab, "test:load-with-mocked-profile-path-response");
let mm = tab.linkedBrowser.messageManager;

View File

@ -29,7 +29,7 @@ let gTests = [
Services.prefs.setCharPref("datareporting.healthreport.about.reportUrl",
"https://example.com/browser/browser/base/content/test/general/healthreport_testRemoteCommands.html");
},
run: function ()
run: function (iframe)
{
let deferred = Promise.defer();
@ -40,19 +40,18 @@ let gTests = [
let results = 0;
try {
let win = gBrowser.contentWindow;
win.addEventListener("message", function testLoad(e) {
if (e.data.type == "testResult") {
ok(e.data.pass, e.data.info);
iframe.contentWindow.addEventListener("FirefoxHealthReportTestResponse", function evtHandler(event) {
let data = event.detail.data;
if (data.type == "testResult") {
ok(data.pass, data.info);
results++;
}
else if (e.data.type == "testsComplete") {
is(results, e.data.count, "Checking number of results received matches the number of tests that should have run");
win.removeEventListener("message", testLoad, false, true);
else if (data.type == "testsComplete") {
is(results, data.count, "Checking number of results received matches the number of tests that should have run");
iframe.contentWindow.removeEventListener("FirefoxHealthReportTestResponse", evtHandler, true);
deferred.resolve();
}
}, false, true);
}, true);
} catch(e) {
ok(false, "Failed to get all commands");
@ -77,9 +76,9 @@ function test()
info(test.desc);
test.setup();
yield promiseNewTabLoadEvent("about:healthreport");
let iframe = yield promiseNewTabLoadEvent("about:healthreport");
yield test.run();
yield test.run(iframe);
gBrowser.removeCurrentTab();
}
@ -96,8 +95,12 @@ function promiseNewTabLoadEvent(aUrl, aEventType="load")
tab.linkedBrowser.removeEventListener(aEventType, load, true);
let iframe = tab.linkedBrowser.contentDocument.getElementById("remote-report");
iframe.addEventListener("load", function frameLoad(e) {
if (iframe.contentWindow.location.href == "about:blank" ||
e.target != iframe) {
return;
}
iframe.removeEventListener("load", frameLoad, false);
deferred.resolve();
deferred.resolve(iframe);
}, false);
}, true);
return deferred.promise;

View File

@ -13,8 +13,13 @@ add_task(function test_ignoreFragment() {
switchTab("about:home#1", true);
switchTab("about:mozilla", true);
let hashChangePromise = new Promise(resolve => {
tabRefAboutHome.linkedBrowser.contentWindow.addEventListener("hashchange", resolve, false);
});
switchTab("about:home#2", true, { ignoreFragment: true });
is(tabRefAboutHome, gBrowser.selectedTab, "The same about:home tab should be switched to");
yield hashChangePromise;
is(gBrowser.currentURI.ref, "2", "The ref should be updated to the new ref");
switchTab("about:mozilla", true);
switchTab("about:home#1", false);

View File

@ -0,0 +1,114 @@
const CHROME_PROCESS = Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT;
const CONTENT_PROCESS = Ci.nsIXULRuntime.PROCESS_TYPE_CONTENT;
const CHROME = {
id: "cb34538a-d9da-40f3-b61a-069f0b2cb9fb",
path: "test-chrome",
flags: 0,
}
const CANREMOTE = {
id: "2480d3e1-9ce4-4b84-8ae3-910b9a95cbb3",
path: "test-allowremote",
flags: Ci.nsIAboutModule.URI_CAN_LOAD_IN_CHILD,
}
const MUSTREMOTE = {
id: "f849cee5-e13e-44d2-981d-0fb3884aaead",
path: "test-mustremote",
flags: Ci.nsIAboutModule.URI_MUST_LOAD_IN_CHILD,
}
const TEST_MODULES = [
CHROME,
CANREMOTE,
MUSTREMOTE
]
function AboutModule() {
}
AboutModule.prototype = {
newChannel: function(aURI, aLoadInfo) {
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
},
getURIFlags: function(aURI) {
for (let module of TEST_MODULES) {
if (aURI.path.startsWith(module.path)) {
return module.flags;
}
}
ok(false, "Called getURIFlags for an unknown page " + aURI.spec);
return 0;
},
getIndexedDBOriginPostfix: function(aURI) {
return null;
},
QueryInterface: XPCOMUtils.generateQI([Ci.nsIAboutModule])
};
let AboutModuleFactory = {
createInstance: function(aOuter, aIID) {
if (aOuter)
throw Components.results.NS_ERROR_NO_AGGREGATION;
return new AboutModule().QueryInterface(aIID);
},
lockFactory: function(aLock) {
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
},
QueryInterface: XPCOMUtils.generateQI([Ci.nsIFactory])
};
add_task(function* init() {
let registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar);
for (let module of TEST_MODULES) {
registrar.registerFactory(Components.ID(module.id), "",
"@mozilla.org/network/protocol/about;1?what=" + module.path,
AboutModuleFactory);
}
});
registerCleanupFunction(() => {
let registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar);
for (let module of TEST_MODULES) {
registrar.unregisterFactory(Components.ID(module.id), AboutModuleFactory);
}
});
function test_url(url, chromeResult, contentResult) {
is(E10SUtils.canLoadURIInProcess(url, CHROME_PROCESS),
chromeResult, "Check URL in chrome process.");
is(E10SUtils.canLoadURIInProcess(url, CONTENT_PROCESS),
contentResult, "Check URL in content process.");
is(E10SUtils.canLoadURIInProcess(url + "#foo", CHROME_PROCESS),
chromeResult, "Check URL with ref in chrome process.");
is(E10SUtils.canLoadURIInProcess(url + "#foo", CONTENT_PROCESS),
contentResult, "Check URL with ref in content process.");
is(E10SUtils.canLoadURIInProcess(url + "?foo", CHROME_PROCESS),
chromeResult, "Check URL with query in chrome process.");
is(E10SUtils.canLoadURIInProcess(url + "?foo", CONTENT_PROCESS),
contentResult, "Check URL with query in content process.");
is(E10SUtils.canLoadURIInProcess(url + "?foo#bar", CHROME_PROCESS),
chromeResult, "Check URL with query and ref in chrome process.");
is(E10SUtils.canLoadURIInProcess(url + "?foo#bar", CONTENT_PROCESS),
contentResult, "Check URL with query and ref in content process.");
}
add_task(function* test_chrome() {
test_url("about:" + CHROME.path, true, false);
});
add_task(function* test_any() {
test_url("about:" + CANREMOTE.path, true, true);
});
add_task(function* test_remote() {
test_url("about:" + MUSTREMOTE.path, false, true);
});

View File

@ -0,0 +1,150 @@
// Returns a function suitable for add_task which loads startURL, runs
// transitionTask and waits for endURL to load, checking that the URLs were
// loaded in the correct process.
function makeTest(name, startURL, startProcessIsRemote, endURL, endProcessIsRemote, transitionTask) {
return function*() {
info("Running test " + name + ", " + transitionTask.name);
let browser = gBrowser.selectedBrowser;
// In non-e10s nothing should be remote
if (!gMultiProcessBrowser) {
startProcessIsRemote = false;
endProcessIsRemote = false;
}
// Load the initial URL and make sure we are in the right initial process
info("Loading initial URL");
browser.loadURI(startURL);
yield waitForDocLoadComplete();
is(browser.currentURI.spec, startURL, "Shouldn't have been redirected");
is(browser.isRemoteBrowser, startProcessIsRemote, "Should be displayed in the right process");
let docLoadedPromise = waitForDocLoadComplete();
let asyncTask = Task.async(transitionTask);
let expectSyncChange = yield asyncTask(browser, endURL);
if (expectSyncChange) {
is(browser.isRemoteBrowser, endProcessIsRemote, "Should have switched to the right process synchronously");
}
yield docLoadedPromise;
is(browser.currentURI.spec, endURL, "Should have made it to the final URL");
is(browser.isRemoteBrowser, endProcessIsRemote, "Should be displayed in the right process");
}
}
const CHROME_PROCESS = Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT;
const CONTENT_PROCESS = Ci.nsIXULRuntime.PROCESS_TYPE_CONTENT;
const PATH = (getRootDirectory(gTestPath) + "test_process_flags_chrome.html").replace("chrome://mochitests", "");
const CHROME = "chrome://mochitests" + PATH;
const CANREMOTE = "chrome://mochitests-any" + PATH;
const MUSTREMOTE = "chrome://mochitests-content" + PATH;
add_task(function* init() {
gBrowser.selectedTab = gBrowser.addTab("about:blank");
});
registerCleanupFunction(() => {
gBrowser.removeCurrentTab();
});
function test_url(url, chromeResult, contentResult) {
is(E10SUtils.canLoadURIInProcess(url, CHROME_PROCESS),
chromeResult, "Check URL in chrome process.");
is(E10SUtils.canLoadURIInProcess(url, CONTENT_PROCESS),
contentResult, "Check URL in content process.");
is(E10SUtils.canLoadURIInProcess(url + "#foo", CHROME_PROCESS),
chromeResult, "Check URL with ref in chrome process.");
is(E10SUtils.canLoadURIInProcess(url + "#foo", CONTENT_PROCESS),
contentResult, "Check URL with ref in content process.");
is(E10SUtils.canLoadURIInProcess(url + "?foo", CHROME_PROCESS),
chromeResult, "Check URL with query in chrome process.");
is(E10SUtils.canLoadURIInProcess(url + "?foo", CONTENT_PROCESS),
contentResult, "Check URL with query in content process.");
is(E10SUtils.canLoadURIInProcess(url + "?foo#bar", CHROME_PROCESS),
chromeResult, "Check URL with query and ref in chrome process.");
is(E10SUtils.canLoadURIInProcess(url + "?foo#bar", CONTENT_PROCESS),
contentResult, "Check URL with query and ref in content process.");
}
add_task(function* test_chrome() {
test_url(CHROME, true, false);
});
add_task(function* test_any() {
test_url(CANREMOTE, true, true);
});
add_task(function* test_remote() {
test_url(MUSTREMOTE, false, true);
});
// The set of page transitions
let TESTS = [
[
"chrome -> chrome",
CHROME, false,
CHROME, false,
],
[
"chrome -> canremote",
CHROME, false,
CANREMOTE, false,
],
[
"chrome -> mustremote",
CHROME, false,
MUSTREMOTE, true,
],
[
"remote -> chrome",
MUSTREMOTE, true,
CHROME, false,
],
[
"remote -> canremote",
MUSTREMOTE, true,
CANREMOTE, true,
],
[
"remote -> mustremote",
MUSTREMOTE, true,
MUSTREMOTE, true,
],
];
// The different ways to transition from one page to another
let TRANSITIONS = [
// Loads the new page by calling browser.loadURI directly
function* loadURI(browser, uri) {
info("Calling browser.loadURI");
browser.loadURI(uri);
return true;
},
// Loads the new page by finding a link with the right href in the document and
// clicking it
function* clickLink(browser, uri) {
info("Clicking link");
function frame_script(uri) {
let link = content.document.querySelector("a[href='" + uri + "']");
link.click();
}
browser.messageManager.loadFrameScript("data:,(" + frame_script.toString() + ")(" + JSON.stringify(uri) + ");", false);
return false;
},
];
// Creates a set of test tasks, one for each combination of TESTS and TRANSITIONS.
for (let test of TESTS) {
for (let transition of TRANSITIONS) {
add_task(makeTest(...test, transition));
}
}

View File

@ -29,6 +29,11 @@ addEventListener("DOMContentLoaded", function domContentLoaded(event) {
}
iframe.removeEventListener("load", iframeLoaded, true);
sendAsyncMessage("test:iframe:load", {url: iframe.getAttribute("src")});
// And an event listener for the test responses, which we send to the test
// via a message.
iframe.contentWindow.addEventListener("FirefoxAccountsTestResponse", function (event) {
sendAsyncMessage("test:response", {data: event.detail.data});
}, true);
}, true);
}, true);

View File

@ -119,12 +119,14 @@ function doTest(evt) {
function reportResult(info, pass, error) {
var data = {type: "testResult", info: info, pass: pass, error: error};
window.parent.postMessage(data, "*");
var event = new CustomEvent("FirefoxHealthReportTestResponse", {detail: {data: data}, bubbles: true});
document.dispatchEvent(event);
}
function reportFinished(cmd) {
var data = {type: "testsComplete", count: tests.length};
window.parent.postMessage(data, "*");
var event = new CustomEvent("FirefoxHealthReportTestResponse", {detail: {data: data}, bubbles: true});
document.dispatchEvent(event);
}
function sendToBrowser(type) {

View File

@ -0,0 +1,10 @@
<!DOCTYPE html>
<html>
<body>
<p>chrome: test page</p>
<p><a href="chrome://mochitests/content/browser/browser/base/content/test/general/test_process_flags_chrome.html">chrome</a></p>
<p><a href="chrome://mochitests-any/content/browser/browser/base/content/test/general/test_process_flags_chrome.html">canremote</a></p>
<p><a href="chrome://mochitests-content/content/browser/browser/base/content/test/general/test_process_flags_chrome.html">mustremote</a></p>
</body>
</html>

View File

@ -246,22 +246,22 @@ let tests = [
onShown: function (popup) {
let self = this;
let progressListener = {
onLocationChange: function onLocationChange(aBrowser) {
if (aBrowser != gBrowser.selectedBrowser) {
return;
}
let notification = PopupNotifications.getNotification(self.notifyObj.id,
self.notifyObj.browser);
ok(notification != null, "Notification remained when subframe navigated");
self.notifyObj.options.eventCallback = undefined;
onLocationChange: function onLocationChange() {
gBrowser.removeProgressListener(progressListener);
notification.remove();
gBrowser.removeTabsProgressListener(progressListener);
executeSoon(() => {
let notification = PopupNotifications.getNotification(self.notifyObj.id,
self.notifyObj.browser);
ok(notification != null, "Notification remained when subframe navigated");
self.notifyObj.options.eventCallback = undefined;
notification.remove();
});
},
};
info("Adding progress listener and performing navigation");
gBrowser.addTabsProgressListener(progressListener);
gBrowser.addProgressListener(progressListener);
content.document.getElementById("iframe")
.setAttribute("src", "http://example.org/");
},

View File

@ -42,6 +42,7 @@ static RedirEntry kRedirMap[] = {
#endif
{ "certerror", "chrome://browser/content/certerror/aboutCertError.xhtml",
nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
nsIAboutModule::URI_CAN_LOAD_IN_CHILD |
nsIAboutModule::ALLOW_SCRIPT |
nsIAboutModule::HIDE_FROM_ABOUTABOUT },
{ "socialerror", "chrome://browser/content/aboutSocialError.xhtml",
@ -83,6 +84,7 @@ static RedirEntry kRedirMap[] = {
#endif
{ "home", "chrome://browser/content/abouthome/aboutHome.xhtml",
nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
nsIAboutModule::URI_MUST_LOAD_IN_CHILD |
nsIAboutModule::ALLOW_SCRIPT |
nsIAboutModule::ENABLE_INDEXED_DB },
{ "newtab", "chrome://browser/content/newtab/newTab.xul",

View File

@ -1,3 +0,0 @@
component {49507fe5-2cee-4824-b6a3-e999150ce9b8} DownloadsStartup.js
contract @mozilla.org/browser/downloadsstartup;1 {49507fe5-2cee-4824-b6a3-e999150ce9b8}
category profile-after-change DownloadsStartup @mozilla.org/browser/downloadsstartup;1

View File

@ -1,62 +0,0 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80 filetype=javascript: */
/* 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/. */
/**
* This component enables the JavaScript API for downloads at startup. This
* will eventually be removed when nsIDownloadManager will not be available
* anymore (bug 851471).
*/
"use strict";
////////////////////////////////////////////////////////////////////////////////
//// Globals
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cu = Components.utils;
const Cr = Components.results;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
/**
* CID and Contract ID of the JavaScript implementation of nsITransfer.
*/
const kTransferCid = Components.ID("{1b4c85df-cbdd-4bb6-b04e-613caece083c}");
const kTransferContractId = "@mozilla.org/transfer;1";
////////////////////////////////////////////////////////////////////////////////
//// DownloadsStartup
function DownloadsStartup() { }
DownloadsStartup.prototype = {
classID: Components.ID("{49507fe5-2cee-4824-b6a3-e999150ce9b8}"),
_xpcom_factory: XPCOMUtils.generateSingletonFactory(DownloadsStartup),
//////////////////////////////////////////////////////////////////////////////
//// nsISupports
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver]),
//////////////////////////////////////////////////////////////////////////////
//// nsIObserver
observe: function DS_observe(aSubject, aTopic, aData)
{
// Override Toolkit's nsITransfer implementation with the one from the
// JavaScript API for downloads.
Components.manager.QueryInterface(Ci.nsIComponentRegistrar)
.registerFactory(kTransferCid, "",
kTransferContractId, null);
},
};
////////////////////////////////////////////////////////////////////////////////
//// Module
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([DownloadsStartup]);

View File

@ -9,11 +9,6 @@ BROWSER_CHROME_MANIFESTS += ['test/browser/browser.ini']
JAR_MANIFESTS += ['jar.mn']
EXTRA_COMPONENTS += [
'BrowserDownloads.manifest',
'DownloadsStartup.js',
]
EXTRA_JS_MODULES += [
'DownloadsCommon.jsm',
'DownloadsLogger.jsm',

View File

@ -164,8 +164,7 @@ loop.conversation = (function(mozL10n) {
});
// Obtain the windowId and pass it through
var helper = new loop.shared.utils.Helper();
var locationHash = helper.locationData().hash;
var locationHash = loop.shared.utils.locationData().hash;
var windowId;
var hash = locationHash.match(/#(.*)/);

View File

@ -164,8 +164,7 @@ loop.conversation = (function(mozL10n) {
});
// Obtain the windowId and pass it through
var helper = new loop.shared.utils.Helper();
var locationHash = helper.locationData().hash;
var locationHash = loop.shared.utils.locationData().hash;
var windowId;
var hash = locationHash.match(/#(.*)/);

View File

@ -393,7 +393,8 @@ p {
.info-panel h4 {
color: #aaa;
text-align: center;
font-weight: 300;
font-weight: 500;
font-size: 1.2em;
margin: 0;
}

View File

@ -305,24 +305,6 @@
flex: 1;
}
/* Expired call url page */
.expired-url-info {
width: 400px;
margin: 0 auto;
}
.promote-firefox {
text-align: center;
font-size: 18px;
line-height: 24px;
margin: 2em 0;
}
.promote-firefox h3 {
font-weight: 300;
}
/*
* Dropdown menu hidden behind a chevron
*

View File

@ -84,42 +84,51 @@ loop.shared.utils = (function(mozL10n) {
return !!localStorage.getItem(prefName);
}
/**
* Helper for general things
*/
function Helper() {
this._iOSRegex = /^(iPad|iPhone|iPod)/;
function isFirefox(platform) {
return platform.indexOf("Firefox") !== -1;
}
Helper.prototype = {
isFirefox: function(platform) {
return platform.indexOf("Firefox") !== -1;
},
function isFirefoxOS(platform) {
// So far WebActivities are exposed only in FxOS, but they may be
// exposed in Firefox Desktop soon, so we check for its existence
// and also check if the UA belongs to a mobile platform.
// XXX WebActivities are also exposed in WebRT on Firefox for Android,
// so we need a better check. Bug 1065403.
return !!window.MozActivity && /mobi/i.test(platform);
}
isFirefoxOS: function(platform) {
// So far WebActivities are exposed only in FxOS, but they may be
// exposed in Firefox Desktop soon, so we check for its existence
// and also check if the UA belongs to a mobile platform.
// XXX WebActivities are also exposed in WebRT on Firefox for Android,
// so we need a better check. Bug 1065403.
return !!window.MozActivity && /mobi/i.test(platform);
},
isIOS: function(platform) {
return this._iOSRegex.test(platform);
},
/**
* Helper to allow getting some of the location data in a way that's compatible
* with stubbing for unit tests.
*/
locationData: function() {
return {
hash: window.location.hash,
pathname: window.location.pathname
};
/**
* Helper to get the platform if it is unsupported.
*
* @param {String} platform The platform this is running on.
* @return null for supported platforms, a string for unsupported platforms.
*/
function getUnsupportedPlatform(platform) {
if (/^(iPad|iPhone|iPod)/.test(platform)) {
return "ios";
}
};
if (/Windows Phone/i.test(platform)) {
return "windows_phone";
}
if (/BlackBerry/i.test(platform)) {
return "blackberry";
}
return null;
}
/**
* Helper to allow getting some of the location data in a way that's compatible
* with stubbing for unit tests.
*/
function locationData() {
return {
hash: window.location.hash,
pathname: window.location.pathname
};
}
/**
* Generates and opens a mailto: url with call URL information prefilled.
@ -153,9 +162,12 @@ loop.shared.utils = (function(mozL10n) {
WEBSOCKET_REASONS: WEBSOCKET_REASONS,
STREAM_PROPERTIES: STREAM_PROPERTIES,
SCREEN_SHARE_STATES: SCREEN_SHARE_STATES,
Helper: Helper,
composeCallUrlEmail: composeCallUrlEmail,
formatDate: formatDate,
getBoolPreference: getBoolPreference
getBoolPreference: getBoolPreference,
isFirefox: isFirefox,
isFirefoxOS: isFirefoxOS,
getUnsupportedPlatform: getUnsupportedPlatform,
locationData: locationData
};
})(document.mozL10n || navigator.mozL10n);

View File

@ -88,3 +88,4 @@ config:
@echo "loop.config.roomsSupportUrl = 'https://support.mozilla.org/kb/group-conversations-firefox-hello-webrtc';" >> content/config.js
@echo "loop.config.guestSupportUrl = 'https://support.mozilla.org/kb/respond-firefox-hello-invitation-guest-mode';" >> content/config.js
@echo "loop.config.generalSupportUrl = 'https://support.mozilla.org/kb/respond-firefox-hello-invitation-guest-mode';" >> content/config.js
@echo "loop.config.unsupportedPlatformUrl = 'https://support.mozilla.org/en-US/kb/which-browsers-will-work-firefox-hello-video-chat';" >> content/config.js

View File

@ -234,6 +234,31 @@ p.standalone-btn-label {
flex: 1;
}
/**
* Unsupported/expired views
*/
.highlight-issue-box {
width: 400px;
margin: 0 auto;
}
.promote-firefox {
text-align: center;
font-size: 18px;
line-height: 24px;
margin: 2em 0;
}
.promote-firefox h3 {
font-weight: 300;
}
.btn-unsupported-device {
width: 80%;
line-height: 24px;
}
/**
* Feedback form overlay (standalone only)
*/

View File

@ -33,9 +33,6 @@ loop.store.StandaloneAppStore = (function() {
if (!options.sdk) {
throw new Error("Missing option sdk");
}
if (!options.helper) {
throw new Error("Missing option helper");
}
if (!options.conversation) {
throw new Error("Missing option conversation");
}
@ -43,7 +40,6 @@ loop.store.StandaloneAppStore = (function() {
this._dispatcher = options.dispatcher;
this._storeState = {};
this._sdk = options.sdk;
this._helper = options.helper;
this._conversation = options.conversation;
this._dispatcher.register(this, [
@ -113,7 +109,10 @@ loop.store.StandaloneAppStore = (function() {
var token;
// Check if we're on a supported device/platform.
if (this._helper.isIOS(navigator.platform)) {
var unsupportedPlatform =
sharedUtils.getUnsupportedPlatform(navigator.platform);
if (unsupportedPlatform) {
windowType = "unsupportedDevice";
} else if (!this._sdk.checkSystemRequirements()) {
windowType = "unsupportedBrowser";
@ -130,7 +129,9 @@ loop.store.StandaloneAppStore = (function() {
}
this.setStoreState({
windowType: windowType
windowType: windowType,
isFirefox: sharedUtils.isFirefox(navigator.userAgent),
unsupportedPlatform: unsupportedPlatform
});
// If we've not got a window ID, don't dispatch the action, as we don't need

View File

@ -19,7 +19,7 @@ loop.standaloneRoomViews = (function(mozL10n) {
var StandaloneRoomInfoArea = React.createClass({displayName: "StandaloneRoomInfoArea",
propTypes: {
helper: React.PropTypes.instanceOf(loop.shared.utils.Helper).isRequired,
isFirefox: React.PropTypes.bool.isRequired,
activeRoomStore: React.PropTypes.oneOfType([
React.PropTypes.instanceOf(loop.store.ActiveRoomStore),
React.PropTypes.instanceOf(loop.store.FxOSActiveRoomStore)
@ -34,7 +34,7 @@ loop.standaloneRoomViews = (function(mozL10n) {
},
_renderCallToActionLink: function() {
if (this.props.helper.isFirefox(navigator.userAgent)) {
if (this.props.isFirefox) {
return (
React.createElement("a", {href: loop.config.learnMoreUrl, className: "btn btn-info"},
mozL10n.get("rooms_room_full_call_to_action_label", {
@ -201,7 +201,7 @@ loop.standaloneRoomViews = (function(mozL10n) {
React.PropTypes.instanceOf(loop.store.FxOSActiveRoomStore)
]).isRequired,
dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
helper: React.PropTypes.instanceOf(loop.shared.utils.Helper).isRequired
isFirefox: React.PropTypes.bool.isRequired
},
getInitialState: function() {
@ -360,7 +360,7 @@ loop.standaloneRoomViews = (function(mozL10n) {
React.createElement(StandaloneRoomInfoArea, {roomState: this.state.roomState,
failureReason: this.state.failureReason,
joinRoom: this.joinRoom,
helper: this.props.helper,
isFirefox: this.props.isFirefox,
activeRoomStore: this.props.activeRoomStore,
roomUsed: this.state.used}),
React.createElement("div", {className: "video-layout-wrapper"},

View File

@ -19,7 +19,7 @@ loop.standaloneRoomViews = (function(mozL10n) {
var StandaloneRoomInfoArea = React.createClass({
propTypes: {
helper: React.PropTypes.instanceOf(loop.shared.utils.Helper).isRequired,
isFirefox: React.PropTypes.bool.isRequired,
activeRoomStore: React.PropTypes.oneOfType([
React.PropTypes.instanceOf(loop.store.ActiveRoomStore),
React.PropTypes.instanceOf(loop.store.FxOSActiveRoomStore)
@ -34,7 +34,7 @@ loop.standaloneRoomViews = (function(mozL10n) {
},
_renderCallToActionLink: function() {
if (this.props.helper.isFirefox(navigator.userAgent)) {
if (this.props.isFirefox) {
return (
<a href={loop.config.learnMoreUrl} className="btn btn-info">
{mozL10n.get("rooms_room_full_call_to_action_label", {
@ -201,7 +201,7 @@ loop.standaloneRoomViews = (function(mozL10n) {
React.PropTypes.instanceOf(loop.store.FxOSActiveRoomStore)
]).isRequired,
dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
helper: React.PropTypes.instanceOf(loop.shared.utils.Helper).isRequired
isFirefox: React.PropTypes.bool.isRequired
},
getInitialState: function() {
@ -360,7 +360,7 @@ loop.standaloneRoomViews = (function(mozL10n) {
<StandaloneRoomInfoArea roomState={this.state.roomState}
failureReason={this.state.failureReason}
joinRoom={this.joinRoom}
helper={this.props.helper}
isFirefox={this.props.isFirefox}
activeRoomStore={this.props.activeRoomStore}
roomUsed={this.state.used} />
<div className="video-layout-wrapper">

View File

@ -39,15 +39,19 @@ loop.webapp = (function($, _, OT, mozL10n) {
* Unsupported Browsers view.
*/
var UnsupportedBrowserView = React.createClass({displayName: "UnsupportedBrowserView",
propTypes: {
isFirefox: React.PropTypes.bool.isRequired
},
render: function() {
return (
React.createElement("div", {className: "expired-url-info"},
React.createElement("div", {className: "highlight-issue-box"},
React.createElement("div", {className: "info-panel"},
React.createElement("div", {className: "firefox-logo"}),
React.createElement("h1", null, mozL10n.get("incompatible_browser_heading")),
React.createElement("h4", null, mozL10n.get("incompatible_browser_message"))
),
React.createElement(PromoteFirefoxView, {helper: this.props.helper})
React.createElement(PromoteFirefoxView, {isFirefox: this.props.isFirefox})
)
);
}
@ -57,12 +61,28 @@ loop.webapp = (function($, _, OT, mozL10n) {
* Unsupported Device view.
*/
var UnsupportedDeviceView = React.createClass({displayName: "UnsupportedDeviceView",
propTypes: {
platform: React.PropTypes.string.isRequired
},
render: function() {
var unsupportedDeviceParams = {
clientShortname: mozL10n.get("clientShortname2"),
platform: mozL10n.get("unsupported_platform_" + this.props.platform)
};
var unsupportedLearnMoreText = mozL10n.get("unsupported_platform_learn_more_link",
{clientShortname: mozL10n.get("clientShortname2")});
return (
React.createElement("div", null,
React.createElement("h2", null, mozL10n.get("incompatible_device")),
React.createElement("p", null, mozL10n.get("sorry_device_unsupported", {clientShortname: mozL10n.get("clientShortname2")})),
React.createElement("p", null, mozL10n.get("use_firefox_windows_mac_linux", {brandShortname: mozL10n.get("brandShortname")}))
React.createElement("div", {className: "highlight-issue-box"},
React.createElement("div", {className: "info-panel"},
React.createElement("div", {className: "firefox-logo"}),
React.createElement("h1", null, mozL10n.get("unsupported_platform_heading")),
React.createElement("h4", null, mozL10n.get("unsupported_platform_message", unsupportedDeviceParams))
),
React.createElement("p", null,
React.createElement("a", {className: "btn btn-large btn-accept btn-unsupported-device",
href: loop.config.unsupportedPlatformUrl}, unsupportedLearnMoreText))
)
);
}
@ -73,11 +93,11 @@ loop.webapp = (function($, _, OT, mozL10n) {
*/
var PromoteFirefoxView = React.createClass({displayName: "PromoteFirefoxView",
propTypes: {
helper: React.PropTypes.object.isRequired
isFirefox: React.PropTypes.bool.isRequired
},
render: function() {
if (this.props.helper.isFirefox(navigator.userAgent)) {
if (this.props.isFirefox) {
return React.createElement("div", null);
}
return (
@ -101,18 +121,18 @@ loop.webapp = (function($, _, OT, mozL10n) {
*/
var CallUrlExpiredView = React.createClass({displayName: "CallUrlExpiredView",
propTypes: {
helper: React.PropTypes.object.isRequired
isFirefox: React.PropTypes.bool.isRequired
},
render: function() {
return (
React.createElement("div", {className: "expired-url-info"},
React.createElement("div", {className: "highlight-issue-box"},
React.createElement("div", {className: "info-panel"},
React.createElement("div", {className: "firefox-logo"}),
React.createElement("h1", null, mozL10n.get("call_url_unavailable_notification_heading")),
React.createElement("h4", null, mozL10n.get("call_url_unavailable_notification_message2"))
),
React.createElement(PromoteFirefoxView, {helper: this.props.helper})
React.createElement(PromoteFirefoxView, {isFirefox: this.props.isFirefox})
)
);
}
@ -630,7 +650,6 @@ loop.webapp = (function($, _, OT, mozL10n) {
React.PropTypes.instanceOf(FxOSConversationModel)
]).isRequired,
dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
helper: React.PropTypes.instanceOf(sharedUtils.Helper).isRequired,
notifications: React.PropTypes.instanceOf(sharedModels.NotificationCollection)
.isRequired,
sdk: React.PropTypes.object.isRequired
@ -723,7 +742,7 @@ loop.webapp = (function($, _, OT, mozL10n) {
}
case "expired": {
return (
React.createElement(CallUrlExpiredView, {helper: this.props.helper})
React.createElement(CallUrlExpiredView, null)
);
}
default: {
@ -927,7 +946,6 @@ loop.webapp = (function($, _, OT, mozL10n) {
React.PropTypes.instanceOf(sharedModels.ConversationModel),
React.PropTypes.instanceOf(FxOSConversationModel)
]).isRequired,
helper: React.PropTypes.instanceOf(sharedUtils.Helper).isRequired,
notifications: React.PropTypes.instanceOf(sharedModels.NotificationCollection)
.isRequired,
sdk: React.PropTypes.object.isRequired,
@ -963,10 +981,10 @@ loop.webapp = (function($, _, OT, mozL10n) {
render: function() {
switch (this.state.windowType) {
case "unsupportedDevice": {
return React.createElement(UnsupportedDeviceView, null);
return React.createElement(UnsupportedDeviceView, {platform: this.state.unsupportedPlatform});
}
case "unsupportedBrowser": {
return React.createElement(UnsupportedBrowserView, {helper: this.props.helper});
return React.createElement(UnsupportedBrowserView, {isFirefox: this.state.isFirefox});
}
case "outgoing": {
return (
@ -974,7 +992,6 @@ loop.webapp = (function($, _, OT, mozL10n) {
client: this.props.client,
dispatcher: this.props.dispatcher,
conversation: this.props.conversation,
helper: this.props.helper,
notifications: this.props.notifications,
sdk: this.props.sdk}
)
@ -985,7 +1002,7 @@ loop.webapp = (function($, _, OT, mozL10n) {
React.createElement(loop.standaloneRoomViews.StandaloneRoomView, {
activeRoomStore: this.props.activeRoomStore,
dispatcher: this.props.dispatcher,
helper: this.props.helper}
isFirefox: this.state.isFirefox}
)
);
}
@ -1005,7 +1022,6 @@ loop.webapp = (function($, _, OT, mozL10n) {
* App initialization.
*/
function init() {
var helper = new sharedUtils.Helper();
var standaloneMozLoop = new loop.StandaloneMozLoop({
baseServerUrl: loop.config.serverUrl
});
@ -1031,7 +1047,7 @@ loop.webapp = (function($, _, OT, mozL10n) {
});
var conversation;
var activeRoomStore;
if (helper.isFirefoxOS(navigator.userAgent)) {
if (sharedUtils.isFirefoxOS(navigator.userAgent)) {
if (loop.config.fxosApp) {
conversation = new FxOSConversationModel();
if (loop.config.fxosApp.rooms) {
@ -1063,7 +1079,6 @@ loop.webapp = (function($, _, OT, mozL10n) {
var standaloneAppStore = new loop.store.StandaloneAppStore({
conversation: conversation,
dispatcher: dispatcher,
helper: helper,
sdk: OT
});
var feedbackStore = new loop.store.FeedbackStore(dispatcher, {
@ -1079,7 +1094,6 @@ loop.webapp = (function($, _, OT, mozL10n) {
React.render(React.createElement(WebappRootView, {
client: client,
conversation: conversation,
helper: helper,
notifications: notifications,
sdk: OT,
standaloneAppStore: standaloneAppStore,
@ -1092,10 +1106,12 @@ loop.webapp = (function($, _, OT, mozL10n) {
document.documentElement.dir = mozL10n.language.direction;
document.title = mozL10n.get("clientShortname2");
var locationData = sharedUtils.locationData();
dispatcher.dispatch(new sharedActions.ExtractTokenInfo({
// We pass the hash or the pathname - the hash was used for the original
// urls, the pathname for later ones.
windowPath: helper.locationData().hash || helper.locationData().pathname
windowPath: locationData.hash || locationData.pathname
}));
}

View File

@ -39,15 +39,19 @@ loop.webapp = (function($, _, OT, mozL10n) {
* Unsupported Browsers view.
*/
var UnsupportedBrowserView = React.createClass({
propTypes: {
isFirefox: React.PropTypes.bool.isRequired
},
render: function() {
return (
<div className="expired-url-info">
<div className="highlight-issue-box">
<div className="info-panel">
<div className="firefox-logo" />
<h1>{mozL10n.get("incompatible_browser_heading")}</h1>
<h4>{mozL10n.get("incompatible_browser_message")}</h4>
</div>
<PromoteFirefoxView helper={this.props.helper} />
<PromoteFirefoxView isFirefox={this.props.isFirefox}/>
</div>
);
}
@ -57,12 +61,28 @@ loop.webapp = (function($, _, OT, mozL10n) {
* Unsupported Device view.
*/
var UnsupportedDeviceView = React.createClass({
propTypes: {
platform: React.PropTypes.string.isRequired
},
render: function() {
var unsupportedDeviceParams = {
clientShortname: mozL10n.get("clientShortname2"),
platform: mozL10n.get("unsupported_platform_" + this.props.platform)
};
var unsupportedLearnMoreText = mozL10n.get("unsupported_platform_learn_more_link",
{clientShortname: mozL10n.get("clientShortname2")});
return (
<div>
<h2>{mozL10n.get("incompatible_device")}</h2>
<p>{mozL10n.get("sorry_device_unsupported", {clientShortname: mozL10n.get("clientShortname2")})}</p>
<p>{mozL10n.get("use_firefox_windows_mac_linux", {brandShortname: mozL10n.get("brandShortname")})}</p>
<div className="highlight-issue-box">
<div className="info-panel">
<div className="firefox-logo" />
<h1>{mozL10n.get("unsupported_platform_heading")}</h1>
<h4>{mozL10n.get("unsupported_platform_message", unsupportedDeviceParams)}</h4>
</div>
<p>
<a className="btn btn-large btn-accept btn-unsupported-device"
href={loop.config.unsupportedPlatformUrl}>{unsupportedLearnMoreText}</a></p>
</div>
);
}
@ -73,11 +93,11 @@ loop.webapp = (function($, _, OT, mozL10n) {
*/
var PromoteFirefoxView = React.createClass({
propTypes: {
helper: React.PropTypes.object.isRequired
isFirefox: React.PropTypes.bool.isRequired
},
render: function() {
if (this.props.helper.isFirefox(navigator.userAgent)) {
if (this.props.isFirefox) {
return <div />;
}
return (
@ -101,18 +121,18 @@ loop.webapp = (function($, _, OT, mozL10n) {
*/
var CallUrlExpiredView = React.createClass({
propTypes: {
helper: React.PropTypes.object.isRequired
isFirefox: React.PropTypes.bool.isRequired
},
render: function() {
return (
<div className="expired-url-info">
<div className="highlight-issue-box">
<div className="info-panel">
<div className="firefox-logo" />
<h1>{mozL10n.get("call_url_unavailable_notification_heading")}</h1>
<h4>{mozL10n.get("call_url_unavailable_notification_message2")}</h4>
</div>
<PromoteFirefoxView helper={this.props.helper} />
<PromoteFirefoxView isFirefox={this.props.isFirefox}/>
</div>
);
}
@ -630,7 +650,6 @@ loop.webapp = (function($, _, OT, mozL10n) {
React.PropTypes.instanceOf(FxOSConversationModel)
]).isRequired,
dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
helper: React.PropTypes.instanceOf(sharedUtils.Helper).isRequired,
notifications: React.PropTypes.instanceOf(sharedModels.NotificationCollection)
.isRequired,
sdk: React.PropTypes.object.isRequired
@ -723,7 +742,7 @@ loop.webapp = (function($, _, OT, mozL10n) {
}
case "expired": {
return (
<CallUrlExpiredView helper={this.props.helper} />
<CallUrlExpiredView />
);
}
default: {
@ -927,7 +946,6 @@ loop.webapp = (function($, _, OT, mozL10n) {
React.PropTypes.instanceOf(sharedModels.ConversationModel),
React.PropTypes.instanceOf(FxOSConversationModel)
]).isRequired,
helper: React.PropTypes.instanceOf(sharedUtils.Helper).isRequired,
notifications: React.PropTypes.instanceOf(sharedModels.NotificationCollection)
.isRequired,
sdk: React.PropTypes.object.isRequired,
@ -963,10 +981,10 @@ loop.webapp = (function($, _, OT, mozL10n) {
render: function() {
switch (this.state.windowType) {
case "unsupportedDevice": {
return <UnsupportedDeviceView />;
return <UnsupportedDeviceView platform={this.state.unsupportedPlatform}/>;
}
case "unsupportedBrowser": {
return <UnsupportedBrowserView helper={this.props.helper}/>;
return <UnsupportedBrowserView isFirefox={this.state.isFirefox}/>;
}
case "outgoing": {
return (
@ -974,7 +992,6 @@ loop.webapp = (function($, _, OT, mozL10n) {
client={this.props.client}
dispatcher={this.props.dispatcher}
conversation={this.props.conversation}
helper={this.props.helper}
notifications={this.props.notifications}
sdk={this.props.sdk}
/>
@ -985,7 +1002,7 @@ loop.webapp = (function($, _, OT, mozL10n) {
<loop.standaloneRoomViews.StandaloneRoomView
activeRoomStore={this.props.activeRoomStore}
dispatcher={this.props.dispatcher}
helper={this.props.helper}
isFirefox={this.state.isFirefox}
/>
);
}
@ -1005,7 +1022,6 @@ loop.webapp = (function($, _, OT, mozL10n) {
* App initialization.
*/
function init() {
var helper = new sharedUtils.Helper();
var standaloneMozLoop = new loop.StandaloneMozLoop({
baseServerUrl: loop.config.serverUrl
});
@ -1031,7 +1047,7 @@ loop.webapp = (function($, _, OT, mozL10n) {
});
var conversation;
var activeRoomStore;
if (helper.isFirefoxOS(navigator.userAgent)) {
if (sharedUtils.isFirefoxOS(navigator.userAgent)) {
if (loop.config.fxosApp) {
conversation = new FxOSConversationModel();
if (loop.config.fxosApp.rooms) {
@ -1063,7 +1079,6 @@ loop.webapp = (function($, _, OT, mozL10n) {
var standaloneAppStore = new loop.store.StandaloneAppStore({
conversation: conversation,
dispatcher: dispatcher,
helper: helper,
sdk: OT
});
var feedbackStore = new loop.store.FeedbackStore(dispatcher, {
@ -1079,7 +1094,6 @@ loop.webapp = (function($, _, OT, mozL10n) {
React.render(<WebappRootView
client={client}
conversation={conversation}
helper={helper}
notifications={notifications}
sdk={OT}
standaloneAppStore={standaloneAppStore}
@ -1092,10 +1106,12 @@ loop.webapp = (function($, _, OT, mozL10n) {
document.documentElement.dir = mozL10n.language.direction;
document.title = mozL10n.get("clientShortname2");
var locationData = sharedUtils.locationData();
dispatcher.dispatch(new sharedActions.ExtractTokenInfo({
// We pass the hash or the pathname - the hash was used for the original
// urls, the pathname for later ones.
windowPath: helper.locationData().hash || helper.locationData().pathname
windowPath: locationData.hash || locationData.pathname
}));
}

View File

@ -27,9 +27,12 @@ incompatible_browser_heading=Oops!
incompatible_browser_message=Firefox Hello only works in browsers that support WebRTC
powered_by_webrtc=The audio and video components of {{clientShortname}} are powered by WebRTC.
use_latest_firefox=Please try this link in a WebRTC-enabled browser, such as {{firefoxBrandNameLink}}.
incompatible_device=Incompatible device
sorry_device_unsupported=Sorry, {{clientShortname}} does not currently support your device.
use_firefox_windows_mac_linux=Please open this page using the latest {{brandShortname}} on Windows, Android, Mac or Linux.
unsupported_platform_heading=Sorry!
unsupported_platform_message={{platform}} does not currently support {{clientShortname}}
unsupported_platform_ios=iOS
unsupported_platform_windows_phone=Windows Phone
unsupported_platform_blackberry=Blackberry
unsupported_platform_learn_more_link=Learn more about why your platform doesn't support {{clientShortname}}
connection_error_see_console_notification=Call failed; see console for details.
call_url_unavailable_notification_heading=Oops!
call_url_unavailable_notification_message2=Sorry, this URL is not available. It may be expired or entered incorrectly.

View File

@ -34,7 +34,8 @@ function getConfigFile(req, res) {
"loop.config.fxosApp.manifestUrl = 'http://fake-market.herokuapp.com/apps/packagedApp/manifest.webapp';",
"loop.config.roomsSupportUrl = 'https://support.mozilla.org/kb/group-conversations-firefox-hello-webrtc';",
"loop.config.guestSupportUrl = 'https://support.mozilla.org/kb/respond-firefox-hello-invitation-guest-mode';",
"loop.config.generalSupportUrl = 'https://support.mozilla.org/kb/respond-firefox-hello-invitation-guest-mode';"
"loop.config.generalSupportUrl = 'https://support.mozilla.org/kb/respond-firefox-hello-invitation-guest-mode';",
"loop.config.unsupportedPlatformUrl = 'https://support.mozilla.org/en-US/kb/which-browsers-will-work-firefox-hello-video-chat'"
].join("\n"));
}

View File

@ -83,7 +83,7 @@ describe("loop.conversation", function() {
sandbox.stub(loop.Dispatcher.prototype, "dispatch");
sandbox.stub(loop.shared.utils.Helper.prototype,
sandbox.stub(loop.shared.utils,
"locationData").returns({
hash: "#42",
pathname: "/"

View File

@ -22,69 +22,71 @@ describe("loop.shared.utils", function() {
sandbox.restore();
});
describe("Helper", function() {
var helper;
beforeEach(function() {
helper = new sharedUtils.Helper();
describe("#getUnsupportedPlatform", function() {
it("should detect iOS", function() {
expect(sharedUtils.getUnsupportedPlatform("iPad")).eql('ios');
expect(sharedUtils.getUnsupportedPlatform("iPod")).eql('ios');
expect(sharedUtils.getUnsupportedPlatform("iPhone")).eql('ios');
expect(sharedUtils.getUnsupportedPlatform("iPhone Simulator")).eql('ios');
});
describe("#isIOS", function() {
it("should detect iOS", function() {
expect(helper.isIOS("iPad")).eql(true);
expect(helper.isIOS("iPod")).eql(true);
expect(helper.isIOS("iPhone")).eql(true);
expect(helper.isIOS("iPhone Simulator")).eql(true);
it("should detect Windows Phone", function() {
expect(sharedUtils.getUnsupportedPlatform("Windows Phone"))
.eql('windows_phone');
});
it("should detect BlackBerry", function() {
expect(sharedUtils.getUnsupportedPlatform("BlackBerry"))
.eql('blackberry');
});
it("shouldn't detect other platforms", function() {
expect(sharedUtils.getUnsupportedPlatform("MacIntel")).eql(null);
});
});
describe("#isFirefox", function() {
it("should detect Firefox", function() {
expect(sharedUtils.isFirefox("Firefox")).eql(true);
expect(sharedUtils.isFirefox("Gecko/Firefox")).eql(true);
expect(sharedUtils.isFirefox("Firefox/Gecko")).eql(true);
expect(sharedUtils.isFirefox("Gecko/Firefox/Chuck Norris")).eql(true);
});
it("shouldn't detect Firefox with other platforms", function() {
expect(sharedUtils.isFirefox("Opera")).eql(false);
});
});
describe("#isFirefoxOS", function() {
describe("without mozActivities", function() {
it("shouldn't detect FirefoxOS on mobile platform", function() {
expect(sharedUtils.isFirefoxOS("mobi")).eql(false);
});
it("shouldn't detect iOS with other platforms", function() {
expect(helper.isIOS("MacIntel")).eql(false);
it("shouldn't detect FirefoxOS on non mobile platform", function() {
expect(sharedUtils.isFirefoxOS("whatever")).eql(false);
});
});
describe("#isFirefox", function() {
it("should detect Firefox", function() {
expect(helper.isFirefox("Firefox")).eql(true);
expect(helper.isFirefox("Gecko/Firefox")).eql(true);
expect(helper.isFirefox("Firefox/Gecko")).eql(true);
expect(helper.isFirefox("Gecko/Firefox/Chuck Norris")).eql(true);
describe("with mozActivities", function() {
var realMozActivity;
before(function() {
realMozActivity = window.MozActivity;
window.MozActivity = {};
});
it("shouldn't detect Firefox with other platforms", function() {
expect(helper.isFirefox("Opera")).eql(false);
});
});
describe("#isFirefoxOS", function() {
describe("without mozActivities", function() {
it("shouldn't detect FirefoxOS on mobile platform", function() {
expect(helper.isFirefoxOS("mobi")).eql(false);
});
it("shouldn't detect FirefoxOS on non mobile platform", function() {
expect(helper.isFirefoxOS("whatever")).eql(false);
});
after(function() {
window.MozActivity = realMozActivity;
});
describe("with mozActivities", function() {
var realMozActivity;
it("should detect FirefoxOS on mobile platform", function() {
expect(sharedUtils.isFirefoxOS("mobi")).eql(true);
});
before(function() {
realMozActivity = window.MozActivity;
window.MozActivity = {};
});
after(function() {
window.MozActivity = realMozActivity;
});
it("should detect FirefoxOS on mobile platform", function() {
expect(helper.isFirefoxOS("mobi")).eql(true);
});
it("shouldn't detect FirefoxOS on non mobile platform", function() {
expect(helper.isFirefoxOS("whatever")).eql(false);
});
it("shouldn't detect FirefoxOS on non mobile platform", function() {
expect(sharedUtils.isFirefoxOS("whatever")).eql(false);
});
});
});

View File

@ -38,16 +38,6 @@ describe("loop.store.StandaloneAppStore", function () {
}).to.Throw(/sdk/);
});
it("should throw an error if helper is missing", function() {
expect(function() {
new loop.store.StandaloneAppStore({
dispatcher: dispatcher,
sdk: {},
conversation: {}
});
}).to.Throw(/helper/);
});
it("should throw an error if conversation is missing", function() {
expect(function() {
new loop.store.StandaloneAppStore({
@ -67,8 +57,8 @@ describe("loop.store.StandaloneAppStore", function () {
windowPath: ""
};
helper = new sharedUtils.Helper();
sandbox.stub(helper, "isIOS").returns(false);
sandbox.stub(loop.shared.utils, "getUnsupportedPlatform").returns();
sandbox.stub(loop.shared.utils, "isFirefox").returns(true);
fakeSdk = {
checkSystemRequirements: sinon.stub().returns(true)
@ -88,16 +78,39 @@ describe("loop.store.StandaloneAppStore", function () {
});
});
it("should set windowType to `unsupportedDevice` for IOS", function() {
// The stub should return true for this test.
helper.isIOS.returns(true);
it("should set isFirefox to true for Firefox", function() {
store.extractTokenInfo(
new sharedActions.ExtractTokenInfo(fakeGetWindowData));
expect(store.getStoreState().isFirefox).eql(true);
});
it("should set isFirefox to false for non-Firefox", function() {
loop.shared.utils.isFirefox.returns(false);
store.extractTokenInfo(
new sharedActions.ExtractTokenInfo(fakeGetWindowData));
expect(store.getStoreState()).eql({
windowType: "unsupportedDevice"
});
expect(store.getStoreState().isFirefox).eql(false);
});
it("should store the platform for unsupported platforms", function() {
loop.shared.utils.getUnsupportedPlatform.returns("fake");
store.extractTokenInfo(
new sharedActions.ExtractTokenInfo(fakeGetWindowData));
expect(store.getStoreState().unsupportedPlatform).eql("fake");
});
it("should set windowType to `unsupportedDevice` for ios", function() {
// The stub should return a platform for this test.
loop.shared.utils.getUnsupportedPlatform.returns("ios");
store.extractTokenInfo(
new sharedActions.ExtractTokenInfo(fakeGetWindowData));
expect(store.getStoreState().windowType).eql("unsupportedDevice");
});
it("should set windowType to `unsupportedBrowser` for browsers the sdk does not support",
@ -108,9 +121,7 @@ describe("loop.store.StandaloneAppStore", function () {
store.extractTokenInfo(
new sharedActions.ExtractTokenInfo(fakeGetWindowData));
expect(store.getStoreState()).eql({
windowType: "unsupportedBrowser"
});
expect(store.getStoreState().windowType).eql("unsupportedBrowser");
});
it("should set windowType to `outgoing` for old style call hashes", function() {
@ -119,9 +130,7 @@ describe("loop.store.StandaloneAppStore", function () {
store.extractTokenInfo(
new sharedActions.ExtractTokenInfo(fakeGetWindowData));
expect(store.getStoreState()).eql({
windowType: "outgoing"
});
expect(store.getStoreState().windowType).eql("outgoing");
});
it("should set windowType to `outgoing` for new style call paths", function() {
@ -130,9 +139,7 @@ describe("loop.store.StandaloneAppStore", function () {
store.extractTokenInfo(
new sharedActions.ExtractTokenInfo(fakeGetWindowData));
expect(store.getStoreState()).eql({
windowType: "outgoing"
});
expect(store.getStoreState().windowType).eql("outgoing");
});
it("should set windowType to `room` for room paths", function() {
@ -141,9 +148,7 @@ describe("loop.store.StandaloneAppStore", function () {
store.extractTokenInfo(
new sharedActions.ExtractTokenInfo(fakeGetWindowData));
expect(store.getStoreState()).eql({
windowType: "room"
});
expect(store.getStoreState().windowType).eql("room");
});
it("should set windowType to `home` for unknown paths", function() {
@ -152,9 +157,7 @@ describe("loop.store.StandaloneAppStore", function () {
store.extractTokenInfo(
new sharedActions.ExtractTokenInfo(fakeGetWindowData));
expect(store.getStoreState()).eql({
windowType: "home"
});
expect(store.getStoreState().windowType).eql("home");
});
it("should set the loopToken on the conversation for old style call hashes",

View File

@ -45,7 +45,7 @@ describe("loop.standaloneRoomViews", function() {
loop.standaloneRoomViews.StandaloneRoomView, {
dispatcher: dispatcher,
activeRoomStore: activeRoomStore,
helper: new loop.shared.utils.Helper()
isFirefox: true
}));
}

View File

@ -72,7 +72,7 @@ describe("loop.webapp", function() {
});
it("should dispatch a ExtractTokenInfo action with the hash", function() {
sandbox.stub(loop.shared.utils.Helper.prototype, "locationData").returns({
sandbox.stub(loop.shared.utils, "locationData").returns({
hash: "#call/faketoken",
pathname: "invalid"
});
@ -88,7 +88,7 @@ describe("loop.webapp", function() {
it("should dispatch a ExtractTokenInfo action with the path if there is no hash",
function() {
sandbox.stub(loop.shared.utils.Helper.prototype, "locationData").returns({
sandbox.stub(loop.shared.utils, "locationData").returns({
hash: "",
pathname: "/c/faketoken"
});
@ -123,7 +123,6 @@ describe("loop.webapp", function() {
});
conversation.set("loopToken", "fakeToken");
ocView = mountTestComponent({
helper: new sharedUtils.Helper(),
client: client,
conversation: conversation,
notifications: notifications,
@ -644,7 +643,7 @@ describe("loop.webapp", function() {
});
describe("WebappRootView", function() {
var helper, sdk, conversationModel, client, props, standaloneAppStore;
var sdk, conversationModel, client, props, standaloneAppStore;
var activeRoomStore;
function mountTestComponent() {
@ -652,7 +651,6 @@ describe("loop.webapp", function() {
React.createElement(
loop.webapp.WebappRootView, {
client: client,
helper: helper,
dispatcher: dispatcher,
notifications: notifications,
sdk: sdk,
@ -663,7 +661,6 @@ describe("loop.webapp", function() {
}
beforeEach(function() {
helper = new sharedUtils.Helper();
sdk = {
checkSystemRequirements: function() { return true; }
};
@ -680,7 +677,6 @@ describe("loop.webapp", function() {
standaloneAppStore = new loop.store.StandaloneAppStore({
dispatcher: dispatcher,
sdk: sdk,
helper: helper,
conversation: conversationModel
});
// Stub this to stop the StartConversationView kicking in the request and
@ -1104,7 +1100,7 @@ describe("loop.webapp", function() {
it("should not render when using Firefox", function() {
var comp = TestUtils.renderIntoDocument(
React.createElement(loop.webapp.PromoteFirefoxView, {
helper: {isFirefox: function() { return true; }}
isFirefox: true
}));
expect(comp.getDOMNode().querySelectorAll("h3").length).eql(0);
@ -1114,7 +1110,7 @@ describe("loop.webapp", function() {
var comp = TestUtils.renderIntoDocument(
React.createElement(
loop.webapp.PromoteFirefoxView, {
helper: {isFirefox: function() { return false; }}
isFirefox: false
}));
expect(comp.getDOMNode().querySelectorAll("h3").length).eql(1);

View File

@ -497,10 +497,10 @@
React.createElement(Section, {name: "CallUrlExpiredView"},
React.createElement(Example, {summary: "Firefox User"},
React.createElement(CallUrlExpiredView, {helper: {isFirefox: returnTrue}})
React.createElement(CallUrlExpiredView, {isFirefox: true})
),
React.createElement(Example, {summary: "Non-Firefox User"},
React.createElement(CallUrlExpiredView, {helper: {isFirefox: returnFalse}})
React.createElement(CallUrlExpiredView, {isFirefox: false})
)
),
@ -547,7 +547,7 @@
React.createElement(Section, {name: "UnsupportedBrowserView"},
React.createElement(Example, {summary: "Standalone Unsupported Browser"},
React.createElement("div", {className: "standalone"},
React.createElement(UnsupportedBrowserView, {helper: {isFirefox: returnFalse}})
React.createElement(UnsupportedBrowserView, {isFirefox: false})
)
)
),
@ -555,7 +555,7 @@
React.createElement(Section, {name: "UnsupportedDeviceView"},
React.createElement(Example, {summary: "Standalone Unsupported Device"},
React.createElement("div", {className: "standalone"},
React.createElement(UnsupportedDeviceView, null)
React.createElement(UnsupportedDeviceView, {platform: "ios"})
)
)
),
@ -591,7 +591,7 @@
dispatcher: dispatcher,
activeRoomStore: activeRoomStore,
roomState: ROOM_STATES.READY,
helper: {isFirefox: returnTrue}})
isFirefox: true})
)
),
@ -601,7 +601,7 @@
dispatcher: dispatcher,
activeRoomStore: activeRoomStore,
roomState: ROOM_STATES.JOINED,
helper: {isFirefox: returnTrue}})
isFirefox: true})
)
),
@ -611,7 +611,7 @@
dispatcher: dispatcher,
activeRoomStore: activeRoomStore,
roomState: ROOM_STATES.HAS_PARTICIPANTS,
helper: {isFirefox: returnTrue}})
isFirefox: true})
)
),
@ -621,7 +621,7 @@
dispatcher: dispatcher,
activeRoomStore: activeRoomStore,
roomState: ROOM_STATES.FULL,
helper: {isFirefox: returnTrue}})
isFirefox: true})
)
),
@ -631,7 +631,7 @@
dispatcher: dispatcher,
activeRoomStore: activeRoomStore,
roomState: ROOM_STATES.FULL,
helper: {isFirefox: returnFalse}})
isFirefox: false})
)
),
@ -642,7 +642,7 @@
activeRoomStore: activeRoomStore,
feedbackStore: feedbackStore,
roomState: ROOM_STATES.ENDED,
helper: {isFirefox: returnFalse}})
isFirefox: false})
)
),
@ -652,7 +652,7 @@
dispatcher: dispatcher,
activeRoomStore: activeRoomStore,
roomState: ROOM_STATES.FAILED,
helper: {isFirefox: returnFalse}})
isFirefox: false})
)
)
),

View File

@ -497,10 +497,10 @@
<Section name="CallUrlExpiredView">
<Example summary="Firefox User">
<CallUrlExpiredView helper={{isFirefox: returnTrue}} />
<CallUrlExpiredView isFirefox={true} />
</Example>
<Example summary="Non-Firefox User">
<CallUrlExpiredView helper={{isFirefox: returnFalse}} />
<CallUrlExpiredView isFirefox={false} />
</Example>
</Section>
@ -547,7 +547,7 @@
<Section name="UnsupportedBrowserView">
<Example summary="Standalone Unsupported Browser">
<div className="standalone">
<UnsupportedBrowserView helper={{isFirefox: returnFalse}}/>
<UnsupportedBrowserView isFirefox={false}/>
</div>
</Example>
</Section>
@ -555,7 +555,7 @@
<Section name="UnsupportedDeviceView">
<Example summary="Standalone Unsupported Device">
<div className="standalone">
<UnsupportedDeviceView />
<UnsupportedDeviceView platform="ios"/>
</div>
</Example>
</Section>
@ -591,7 +591,7 @@
dispatcher={dispatcher}
activeRoomStore={activeRoomStore}
roomState={ROOM_STATES.READY}
helper={{isFirefox: returnTrue}} />
isFirefox={true} />
</div>
</Example>
@ -601,7 +601,7 @@
dispatcher={dispatcher}
activeRoomStore={activeRoomStore}
roomState={ROOM_STATES.JOINED}
helper={{isFirefox: returnTrue}} />
isFirefox={true} />
</div>
</Example>
@ -611,7 +611,7 @@
dispatcher={dispatcher}
activeRoomStore={activeRoomStore}
roomState={ROOM_STATES.HAS_PARTICIPANTS}
helper={{isFirefox: returnTrue}} />
isFirefox={true} />
</div>
</Example>
@ -621,7 +621,7 @@
dispatcher={dispatcher}
activeRoomStore={activeRoomStore}
roomState={ROOM_STATES.FULL}
helper={{isFirefox: returnTrue}} />
isFirefox={true} />
</div>
</Example>
@ -631,7 +631,7 @@
dispatcher={dispatcher}
activeRoomStore={activeRoomStore}
roomState={ROOM_STATES.FULL}
helper={{isFirefox: returnFalse}} />
isFirefox={false} />
</div>
</Example>
@ -642,7 +642,7 @@
activeRoomStore={activeRoomStore}
feedbackStore={feedbackStore}
roomState={ROOM_STATES.ENDED}
helper={{isFirefox: returnFalse}} />
isFirefox={false} />
</div>
</Example>
@ -652,7 +652,7 @@
dispatcher={dispatcher}
activeRoomStore={activeRoomStore}
roomState={ROOM_STATES.FAILED}
helper={{isFirefox: returnFalse}} />
isFirefox={false} />
</div>
</Example>
</Section>

View File

@ -24,6 +24,7 @@ skip-if = e10s # Bug ?????? - clipboard operations don't seem to work in this te
[browser_library_panel_leak.js]
[browser_library_search.js]
[browser_history_sidebar_search.js]
skip-if = e10s && (os == 'linux' || os == 'mac') # Bug 1116457
[browser_bookmarksProperties.js]
skip-if = e10s

View File

@ -2,58 +2,63 @@
* http://creativecommons.org/publicdomain/zero/1.0/
*/
add_task(function* test() {
waitForExplicitFinish();
"use strict";
add_task(function* test() {
let sidebarBox = document.getElementById("sidebar-box");
is(sidebarBox.hidden, true, "The sidebar should be hidden");
// Uncollapse the personal toolbar if needed.
let toolbar = document.getElementById("PersonalToolbar");
let wasCollapsed = toolbar.collapsed;
if (wasCollapsed)
if (wasCollapsed) {
yield promiseSetToolbarVisibility(toolbar, true);
}
let sidebar = document.getElementById("sidebar");
sidebar.addEventListener("load", function() {
sidebar.removeEventListener("load", arguments.callee, true);
let tree = sidebar.contentDocument.getElementById("bookmarks-view");
let sidebar = yield promiseLoadedSidebar("viewBookmarksSidebar");
registerCleanupFunction(toggleSidebar);
// The Places view is build on load, so we enqueue our test.
executeSoon(function() {
// Focus the tree and check if its controller is returned.
tree.focus();
// Focus the tree and check if its controller is returned.
let tree = sidebar.contentDocument.getElementById("bookmarks-view");
tree.focus();
let controller = doGetPlacesControllerForCommand("placesCmd_copy");
let treeController = tree.controllers
.getControllerForCommand("placesCmd_copy");
ok(controller == treeController, "tree controller was returned");
let controller = doGetPlacesControllerForCommand("placesCmd_copy");
let treeController = tree.controllers
.getControllerForCommand("placesCmd_copy");
ok(controller == treeController, "tree controller was returned");
// Open the context menu for a toolbar item, and check if the toolbar's
// controller is returned.
let toolbarItems = document.getElementById("PlacesToolbarItems");
EventUtils.synthesizeMouse(toolbarItems.childNodes[0],
4, 4, { type: "contextmenu", button: 2 },
window);
controller = doGetPlacesControllerForCommand("placesCmd_copy");
let toolbarController = document.getElementById("PlacesToolbar")
.controllers
.getControllerForCommand("placesCmd_copy");
ok(controller == toolbarController, "the toolbar controller was returned");
// Open the context menu for a toolbar item, and check if the toolbar's
// controller is returned.
let toolbarItems = document.getElementById("PlacesToolbarItems");
EventUtils.synthesizeMouse(toolbarItems.childNodes[0],
4, 4, { type: "contextmenu", button: 2 },
window);
controller = doGetPlacesControllerForCommand("placesCmd_copy");
let toolbarController = document.getElementById("PlacesToolbar")
.controllers
.getControllerForCommand("placesCmd_copy");
ok(controller == toolbarController, "the toolbar controller was returned");
document.getElementById("placesContext").hidePopup();
document.getElementById("placesContext").hidePopup();
// Now that the context menu is closed, try to get the tree controller again.
tree.focus();
controller = doGetPlacesControllerForCommand("placesCmd_copy");
ok(controller == treeController, "tree controller was returned");
// Now that the context menu is closed, try to get the tree controller again.
tree.focus();
controller = doGetPlacesControllerForCommand("placesCmd_copy");
ok(controller == treeController, "tree controller was returned");
toggleSidebar();
if (wasCollapsed)
yield promiseSetToolbarVisibility(toolbar, false);
finish();
});
}, true);
toggleSidebar("viewBookmarksSidebar", true);
if (wasCollapsed) {
yield promiseSetToolbarVisibility(toolbar, false);
}
});
function promiseLoadedSidebar(cmd) {
return new Promise(resolve => {
let sidebar = document.getElementById("sidebar");
sidebar.addEventListener("load", function onLoad() {
sidebar.removeEventListener("load", onLoad, true);
resolve(sidebar);
}, true);
toggleSidebar(cmd, true);
});
}

View File

@ -34,47 +34,50 @@
<![CDATA[
function runTest() {
// Sanity checks.
ok(PlacesUtils, "PlacesUtils is running in chrome context");
ok(PlacesUIUtils, "PlacesUIUtils is running in chrome context");
ok(PlacesUIUtils.ORGANIZER_LEFTPANE_VERSION > 0,
"Left pane version in chrome context, " +
"current version is: " + PlacesUIUtils.ORGANIZER_LEFTPANE_VERSION );
SimpleTest.waitForExplicitFinish();
var fakeLeftPanes = [];
var as = PlacesUtils.annotations;
var bs = PlacesUtils.bookmarks;
Task.spawn(function* () {
// Sanity checks.
ok(PlacesUtils, "PlacesUtils is running in chrome context");
ok(PlacesUIUtils, "PlacesUIUtils is running in chrome context");
ok(PlacesUIUtils.ORGANIZER_LEFTPANE_VERSION > 0,
"Left pane version in chrome context, " +
"current version is: " + PlacesUIUtils.ORGANIZER_LEFTPANE_VERSION );
// We need 2 left pane folders to simulate a corrupt profile.
do {
let leftPaneItems = as.getItemsWithAnnotation(PlacesUIUtils.ORGANIZER_FOLDER_ANNO);
// Create a fake left pane folder.
let fakeLeftPaneRoot = bs.createFolder(PlacesUtils.placesRootId, "",
bs.DEFAULT_INDEX);
as.setItemAnnotation(fakeLeftPaneRoot, PlacesUIUtils.ORGANIZER_FOLDER_ANNO,
PlacesUIUtils.ORGANIZER_LEFTPANE_VERSION, 0,
as.EXPIRE_NEVER);
fakeLeftPanes.push(fakeLeftPaneRoot);
} while (fakeLeftPanes.length < 2);
let fakeLeftPanes = [];
// We need 2 left pane folders to simulate a corrupt profile.
do {
let leftPaneItems = PlacesUtils.annotations.getItemsWithAnnotation(PlacesUIUtils.ORGANIZER_FOLDER_ANNO);
// Initialize the left pane queries.
PlacesUIUtils.leftPaneFolderId;
// Create a fake left pane folder.
let folder = yield PlacesUtils.bookmarks.insert({
parentGuid: PlacesUtils.bookmarks.rootGuid,
index: PlacesUtils.bookmarks.DEFAULT_INDEX,
type: PlacesUtils.bookmarks.TYPE_FOLDER
});
// Check left pane.
ok(PlacesUIUtils.leftPaneFolderId > 0,
"Left pane folder correctly created");
var leftPaneItems = as.getItemsWithAnnotation(PlacesUIUtils.ORGANIZER_FOLDER_ANNO);
is(leftPaneItems.length, 1,
"We correctly have only 1 left pane folder");
let fakeLeftPaneRoot = yield PlacesUtils.promiseItemId(folder.guid);
PlacesUtils.annotations.setItemAnnotation(fakeLeftPaneRoot, PlacesUIUtils.ORGANIZER_FOLDER_ANNO,
PlacesUIUtils.ORGANIZER_LEFTPANE_VERSION, 0,
PlacesUtils.annotations.EXPIRE_NEVER);
fakeLeftPanes.push(folder.guid);
} while (fakeLeftPanes.length < 2);
// Check that all old left pane items have been removed.
fakeLeftPanes.forEach(function(aItemId) {
try {
bs.getItemTitle(aItemId);
throw("This folder should have been removed");
} catch (ex) {}
});
// Initialize the left pane queries.
PlacesUIUtils.leftPaneFolderId;
// Check left pane.
ok(PlacesUIUtils.leftPaneFolderId > 0,
"Left pane folder correctly created");
let leftPaneItems = PlacesUtils.annotations.getItemsWithAnnotation(PlacesUIUtils.ORGANIZER_FOLDER_ANNO);
is(leftPaneItems.length, 1,
"We correctly have only 1 left pane folder");
// Check that all old left pane items have been removed.
for (let guid of fakeLeftPanes) {
ok(!(yield PlacesUtils.bookmarks.fetch({guid})), "This folder should have been removed");
}
}).then(() => SimpleTest.finish());
}
]]>
</script>

View File

@ -42,43 +42,48 @@
*/
function runTest() {
var bs = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
getService(Ci.nsINavBookmarksService);
var ios = Cc["@mozilla.org/network/io-service;1"].
getService(Ci.nsIIOService);
function uri(spec) {
return ios.newURI(spec, null, null);
}
// Add a bookmark.
var itemId = bs.insertBookmark(PlacesUtils.toolbarFolderId,
uri("http://www.example.com/"),
bs.DEFAULT_INDEX,
"mozilla");
// Init panel.
ok(gEditItemOverlay, "gEditItemOverlay is in context");
gEditItemOverlay.initPanel(itemId);
ok(gEditItemOverlay._initialized, "gEditItemOverlay is initialized");
// We must be sure tree is initialized, so we wait for place to be set.
SimpleTest.waitForExplicitFinish();
var tree = gEditItemOverlay._element("folderTree");
tree.addEventListener("DOMAttrModified", function(event) {
if (event.attrName != "place")
return;
tree.removeEventListener("DOMAttrModified", arguments.callee, false);
SimpleTest.executeSoon(function() {
tree.view.selection.clearSelection();
ok(document.getElementById("editBMPanel_newFolderButton").disabled,
"New folder button is disabled if there's no selection");
// Cleanup.
bs.removeItem(itemId);
SimpleTest.finish();
});
}, false);
// Open the folder tree.
document.getElementById("editBMPanel_foldersExpander").doCommand();
Task.spawn(function* () {
// Add a bookmark.
let bm = yield PlacesUtils.bookmarks.insert({
parentGuid: PlacesUtils.bookmarks.toolbarGuid,
url: "http://www.example.com/",
index: PlacesUtils.bookmarks.DEFAULT_INDEX,
type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
title: "mozilla"
});
// Init panel.
ok(gEditItemOverlay, "gEditItemOverlay is in context");
let itemId = yield PlacesUtils.promiseItemId(bm.guid);
gEditItemOverlay.initPanel(itemId);
ok(gEditItemOverlay._initialized, "gEditItemOverlay is initialized");
let tree = gEditItemOverlay._element("folderTree");
yield openFolderTree(tree);
tree.view.selection.clearSelection();
ok(document.getElementById("editBMPanel_newFolderButton").disabled,
"New folder button is disabled if there's no selection");
// Cleanup.
yield PlacesUtils.bookmarks.remove(bm.guid);
}).then(() => SimpleTest.finish());
}
function openFolderTree(tree) {
return new Promise(resolve => {
tree.addEventListener("DOMAttrModified", function onAttrModified(event) {
if (event.attrName == "place") {
tree.removeEventListener("DOMAttrModified", onAttrModified);
resolve();
}
});
// Open the folder tree.
document.getElementById("editBMPanel_foldersExpander").doCommand();
});
}
]]>
</script>

View File

@ -37,47 +37,45 @@
<![CDATA[
function runTest() {
var bs = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
getService(Ci.nsINavBookmarksService);
var ts = Cc["@mozilla.org/browser/tagging-service;1"].
getService(Ci.nsITaggingService);
var ios = Cc["@mozilla.org/network/io-service;1"].
getService(Ci.nsIIOService);
function uri(spec) {
return ios.newURI(spec, null, null);
}
SimpleTest.waitForExplicitFinish();
var testURI = uri("http://www.example.com/");
var testTag = "foo";
var testTagUpper = "Foo";
Task.spawn(function* () {
let testTag = "foo";
let testTagUpper = "Foo";
let testURI = Services.io.newURI("http://www.example.com/", null, null);
// Add a bookmark
var itemId = bs.insertBookmark(bs.toolbarFolder,
testURI,
bs.DEFAULT_INDEX,
"mozilla");
// Add a bookmark.
let bm = yield PlacesUtils.bookmarks.insert({
parentGuid: PlacesUtils.bookmarks.toolbarGuid,
index: PlacesUtils.bookmarks.DEFAULT_INDEX,
type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
title: "mozilla",
url: testURI
});
// Init panel
ok(gEditItemOverlay, "gEditItemOverlay is in context");
gEditItemOverlay.initPanel(itemId);
// Init panel
ok(gEditItemOverlay, "gEditItemOverlay is in context");
let itemId = yield PlacesUtils.promiseItemId(bm.guid);
gEditItemOverlay.initPanel(itemId);
// add a tag
document.getElementById("editBMPanel_tagsField").value = testTag;
gEditItemOverlay.onTagsFieldBlur();
// add a tag
document.getElementById("editBMPanel_tagsField").value = testTag;
gEditItemOverlay.onTagsFieldBlur();
// test that the tag has been added in the backend
is(ts.getTagsForURI(testURI)[0], testTag, "tags match");
// test that the tag has been added in the backend
is(PlacesUtils.tagging.getTagsForURI(testURI)[0], testTag, "tags match");
// change the tag
document.getElementById("editBMPanel_tagsField").value = testTagUpper;
gEditItemOverlay.onTagsFieldBlur();
// change the tag
document.getElementById("editBMPanel_tagsField").value = testTagUpper;
gEditItemOverlay.onTagsFieldBlur();
// test that the tag has been added in the backend
is(ts.getTagsForURI(testURI)[0], testTagUpper, "tags match");
// test that the tag has been added in the backend
is(PlacesUtils.tagging.getTagsForURI(testURI)[0], testTagUpper, "tags match");
// Cleanup.
ts.untagURI(testURI, [testTag]);
bs.removeItem(itemId);
// Cleanup.
PlacesUtils.tagging.untagURI(testURI, [testTag]);
yield PlacesUtils.bookmarks.remove(bm.guid);
}).then(() => SimpleTest.finish());
}
]]>
</script>

View File

@ -41,26 +41,25 @@
* Ensures that history views are updated after deleting entries.
*/
SimpleTest.waitForExplicitFinish();
function runTest() {
// The mochitest page is added to history.
PlacesTestUtils.clearHistory().then(continue_test);
}
SimpleTest.waitForExplicitFinish();
function continue_test() {
// Add some visits.
let vtime = Date.now() * 1000;
const ttype = PlacesUtils.history.TRANSITION_TYPED;
let places =
[{ uri: Services.io.newURI("http://example.tld/", null, null),
visitDate: ++vtime, transition: ttype },
{ uri: Services.io.newURI("http://example2.tld/", null, null),
visitDate: ++vtime, transition: ttype },
{ uri: Services.io.newURI("http://example3.tld/", null, null),
visitDate: ++vtime, transition: ttype }];
Task.spawn(function* () {
yield PlacesTestUtils.clearHistory();
// Add some visits.
let vtime = Date.now() * 1000;
const ttype = PlacesUtils.history.TRANSITION_TYPED;
let places =
[{ uri: Services.io.newURI("http://example.tld/", null, null),
visitDate: ++vtime, transition: ttype },
{ uri: Services.io.newURI("http://example2.tld/", null, null),
visitDate: ++vtime, transition: ttype },
{ uri: Services.io.newURI("http://example3.tld/", null, null),
visitDate: ++vtime, transition: ttype }];
yield new Promise(resolve => addVisits(places, resolve));
addVisits(places, function() {
// Make a history query.
let query = PlacesUtils.history.getNewQuery();
let opts = PlacesUtils.history.getNewQueryOptions();
@ -87,29 +86,28 @@
// First check live-update of the view when adding visits.
places.forEach(place => place.visitDate = ++vtime);
addVisits(places, function() {
for (let i = 0; i < rc; i++) {
selection.select(i);
let node = tree.selectedNode;
is(node.uri, places[rc - i - 1].uri.spec,
"Found expected node at position " + i + ".");
}
yield new Promise(resolve => addVisits(places, resolve));
// Now remove the pages and verify live-update again.
for (let i = 0; i < rc; i++) {
selection.select(0);
let node = tree.selectedNode;
tree.controller.remove("Removing page");
ok(treeView.treeIndexForNode(node) == Ci.nsINavHistoryResultTreeViewer.INDEX_INVISIBLE,
node.uri + " removed.");
ok(treeView.rowCount == rc - i - 1, "Rows count decreased");
}
for (let i = 0; i < rc; i++) {
selection.select(i);
let node = tree.selectedNode;
is(node.uri, places[rc - i - 1].uri.spec,
"Found expected node at position " + i + ".");
}
// Cleanup.
PlacesTestUtils.clearHistory().then(SimpleTest.finish);
});
});
// Now remove the pages and verify live-update again.
for (let i = 0; i < rc; i++) {
selection.select(0);
let node = tree.selectedNode;
tree.controller.remove("Removing page");
ok(treeView.treeIndexForNode(node) == Ci.nsINavHistoryResultTreeViewer.INDEX_INVISIBLE,
node.uri + " removed.");
ok(treeView.rowCount == rc - i - 1, "Rows count decreased");
}
// Cleanup.
yield PlacesTestUtils.clearHistory();
}).then(() => SimpleTest.finish());
}
]]></script>
</window>

View File

@ -44,37 +44,36 @@
* throw.
*/
SimpleTest.waitForExplicitFinish();
function runTest() {
// The mochitest page is added to history.
PlacesTestUtils.clearHistory().then(continue_test);
SimpleTest.waitForExplicitFinish();
Task.spawn(function* () {
yield PlacesTestUtils.clearHistory();
let visits = {
uri: Services.io.newURI("http://example.tld/", null, null),
transition: PlacesUtils.history.TRANSITION_TYPED
};
yield new Promise(resolve => addVisits(visits, resolve));
// Make a history query.
let query = PlacesUtils.history.getNewQuery();
let opts = PlacesUtils.history.getNewQueryOptions();
let queryURI = PlacesUtils.history.queriesToQueryString([query], 1, opts);
// Setup the places tree contents.
let tree = document.getElementById("tree");
tree.place = queryURI;
let rootNode = tree.result.root;
let obs = tree.view.QueryInterface(Ci.nsINavHistoryResultObserver);
obs.nodeHistoryDetailsChanged(rootNode, rootNode.time, rootNode.accessCount);
obs.nodeTitleChanged(rootNode, rootNode.title);
ok(true, "No exceptions thrown");
// Cleanup.
yield PlacesTestUtils.clearHistory();
}).then(SimpleTest.finish);
}
function continue_test() {
addVisits(
{uri: Services.io.newURI("http://example.tld/", null, null),
transition: PlacesUtils.history.TRANSITION_TYPED},
function() {
// Make a history query.
let query = PlacesUtils.history.getNewQuery();
let opts = PlacesUtils.history.getNewQueryOptions();
let queryURI = PlacesUtils.history.queriesToQueryString([query], 1, opts);
// Setup the places tree contents.
let tree = document.getElementById("tree");
tree.place = queryURI;
let rootNode = tree.result.root;
let obs = tree.view.QueryInterface(Ci.nsINavHistoryResultObserver);
obs.nodeHistoryDetailsChanged(rootNode, rootNode.time, rootNode.accessCount);
obs.nodeTitleChanged(rootNode, rootNode.title);
ok(true, "No exceptions thrown");
// Cleanup.
PlacesTestUtils.clearHistory().then(SimpleTest.finish);
});
}
]]></script>
</window>

View File

@ -43,115 +43,126 @@
function runTest() {
SimpleTest.waitForExplicitFinish();
Components.utils.import("resource://gre/modules/NetUtil.jsm");
Task.spawn(function* () {
let bs = PlacesUtils.bookmarks;
let tags = ["a", "b", "c", "d", "e", "f", "g",
"h", "i", "l", "m", "n", "o", "p"];
let tags = ["a", "b", "c", "d", "e", "f", "g",
"h", "i", "l", "m", "n", "o", "p"];
// Add a bookmark and tag it.
let uri1 = NetUtil.newURI("http://www1.mozilla.org/");
let id1 = PlacesUtils.bookmarks.insertBookmark(
PlacesUtils.toolbarFolderId, uri1,
PlacesUtils.bookmarks.DEFAULT_INDEX, "mozilla"
);
PlacesUtils.tagging.tagURI(uri1, tags);
// Add a second bookmark so that tags won't disappear when unchecked.
let uri2 = NetUtil.newURI("http://www2.mozilla.org/");
let id2 = PlacesUtils.bookmarks.insertBookmark(
PlacesUtils.toolbarFolderId, uri2,
PlacesUtils.bookmarks.DEFAULT_INDEX, "mozilla"
);
PlacesUtils.tagging.tagURI(uri2, tags);
// Init panel.
ok(gEditItemOverlay, "gEditItemOverlay is in context");
gEditItemOverlay.initPanel(id1);
ok(gEditItemOverlay._initialized, "gEditItemOverlay is initialized");
// Wait for the tags selector to be open.
let tagsSelectorRow = document.getElementById("editBMPanel_tagsSelectorRow");
tagsSelectorRow.addEventListener("DOMAttrModified", function (event) {
tagsSelectorRow.removeEventListener("DOMAttrModified", arguments.callee, false);
SimpleTest.executeSoon(function () {
let tagsSelector = document.getElementById("editBMPanel_tagsSelector");
// Go by two so there is some untouched tag in the middle.
for (let i = 8; i < tags.length; i += 2) {
tagsSelector.selectedIndex = i;
let listItem = tagsSelector.selectedItem;
SimpleTest.isnot(listItem, null, "Valid listItem found");
tagsSelector.ensureElementIsVisible(listItem);
let visibleIndex = tagsSelector.getIndexOfFirstVisibleRow();
SimpleTest.ok(listItem.checked, "Item is checked " + i);
let selectedTag = listItem.label;
// Uncheck the tag.
listItem.checked = false;
SimpleTest.is(visibleIndex,
tagsSelector.getIndexOfFirstVisibleRow(),
"Scroll position did not change");
// The listbox is rebuilt, so we have to get the new element.
let newItem = tagsSelector.selectedItem;
SimpleTest.isnot(newItem, null, "Valid new listItem found");
SimpleTest.ok(!newItem.checked, "New listItem is unchecked " + i);
SimpleTest.is(newItem.label, selectedTag,
"Correct tag is still selected");
// Check the tag.
newItem.checked = true;
SimpleTest.is(visibleIndex,
tagsSelector.getIndexOfFirstVisibleRow(),
"Scroll position did not change");
}
// Remove the second bookmark, then nuke some of the tags.
PlacesUtils.bookmarks.removeItem(id2);
// Doing this backwords tests more interesting paths.
for (let i = tags.length - 1; i >= 0 ; i -= 2) {
tagsSelector.selectedIndex = i;
let listItem = tagsSelector.selectedItem;
SimpleTest.isnot(listItem, null, "Valid listItem found");
tagsSelector.ensureElementIsVisible(listItem);
let firstVisibleTag = tags[tagsSelector.getIndexOfFirstVisibleRow()];
SimpleTest.ok(listItem.checked, "Item is checked " + i);
let selectedTag = listItem.label;
// Uncheck the tag.
listItem.checked = false;
// Ensure the first visible tag is still visible in the list.
let firstVisibleIndex = tagsSelector.getIndexOfFirstVisibleRow();
let lastVisibleIndex = firstVisibleIndex + tagsSelector.getNumberOfVisibleRows() -1;
let expectedTagIndex = tags.indexOf(firstVisibleTag);
SimpleTest.ok(expectedTagIndex >= firstVisibleIndex &&
expectedTagIndex <= lastVisibleIndex,
"Scroll position is correct");
// The listbox is rebuilt, so we have to get the new element.
let newItem = tagsSelector.selectedItem;
SimpleTest.isnot(newItem, null, "Valid new listItem found");
SimpleTest.ok(newItem.checked, "New listItem is checked " + i);
SimpleTest.is(tagsSelector.selectedItem.label,
tags[Math.min(i + 1, tags.length - 2)],
"The next tag is now selected");
}
// Cleanup.
PlacesUtils.bookmarks.removeItem(id1);
SimpleTest.finish();
// Add a bookmark and tag it.
let uri1 = Services.io.newURI("http://www1.mozilla.org/", null, null);
let bm1 = yield bs.insert({
parentGuid: bs.toolbarGuid,
index: bs.DEFAULT_INDEX,
type: bs.TYPE_BOOKMARK,
title: "mozilla",
url: uri1.spec
});
}, false);
PlacesUtils.tagging.tagURI(uri1, tags);
// Add a second bookmark so that tags won't disappear when unchecked.
let uri2 = Services.io.newURI("http://www2.mozilla.org/", null, null);
let bm2 = yield bs.insert({
parentGuid: bs.toolbarGuid,
index: bs.DEFAULT_INDEX,
type: bs.TYPE_BOOKMARK,
title: "mozilla",
url: uri2.spec
});
PlacesUtils.tagging.tagURI(uri2, tags);
// Init panel.
ok(gEditItemOverlay, "gEditItemOverlay is in context");
let id1 = yield PlacesUtils.promiseItemId(bm1.guid);
gEditItemOverlay.initPanel(id1);
ok(gEditItemOverlay._initialized, "gEditItemOverlay is initialized");
yield openTagSelector();
let tagsSelector = document.getElementById("editBMPanel_tagsSelector");
// Go by two so there is some untouched tag in the middle.
for (let i = 8; i < tags.length; i += 2) {
tagsSelector.selectedIndex = i;
let listItem = tagsSelector.selectedItem;
isnot(listItem, null, "Valid listItem found");
tagsSelector.ensureElementIsVisible(listItem);
let visibleIndex = tagsSelector.getIndexOfFirstVisibleRow();
ok(listItem.checked, "Item is checked " + i);
let selectedTag = listItem.label;
// Uncheck the tag.
listItem.checked = false;
is(visibleIndex, tagsSelector.getIndexOfFirstVisibleRow(),
"Scroll position did not change");
// The listbox is rebuilt, so we have to get the new element.
let newItem = tagsSelector.selectedItem;
isnot(newItem, null, "Valid new listItem found");
ok(!newItem.checked, "New listItem is unchecked " + i);
is(newItem.label, selectedTag, "Correct tag is still selected");
// Check the tag.
newItem.checked = true;
is(visibleIndex, tagsSelector.getIndexOfFirstVisibleRow(),
"Scroll position did not change");
}
// Remove the second bookmark, then nuke some of the tags.
yield bs.remove(bm2.guid);
// Doing this backwords tests more interesting paths.
for (let i = tags.length - 1; i >= 0 ; i -= 2) {
tagsSelector.selectedIndex = i;
let listItem = tagsSelector.selectedItem;
isnot(listItem, null, "Valid listItem found");
tagsSelector.ensureElementIsVisible(listItem);
let firstVisibleTag = tags[tagsSelector.getIndexOfFirstVisibleRow()];
ok(listItem.checked, "Item is checked " + i);
let selectedTag = listItem.label;
// Uncheck the tag.
listItem.checked = false;
// Ensure the first visible tag is still visible in the list.
let firstVisibleIndex = tagsSelector.getIndexOfFirstVisibleRow();
let lastVisibleIndex = firstVisibleIndex + tagsSelector.getNumberOfVisibleRows() -1;
let expectedTagIndex = tags.indexOf(firstVisibleTag);
ok(expectedTagIndex >= firstVisibleIndex &&
expectedTagIndex <= lastVisibleIndex,
"Scroll position is correct");
// The listbox is rebuilt, so we have to get the new element.
let newItem = tagsSelector.selectedItem;
isnot(newItem, null, "Valid new listItem found");
ok(newItem.checked, "New listItem is checked " + i);
is(tagsSelector.selectedItem.label,
tags[Math.min(i + 1, tags.length - 2)],
"The next tag is now selected");
}
// Cleanup.
yield bs.remove(bm1.guid);
}).then(SimpleTest.finish).catch(alert);
}
function openTagSelector() {
// Wait for the tags selector to be open.
let promise = new Promise(resolve => {
let row = document.getElementById("editBMPanel_tagsSelectorRow");
row.addEventListener("DOMAttrModified", function onAttrModified() {
row.removeEventListener("DOMAttrModified", onAttrModified);
resolve();
});
});
// Open the tags selector.
document.getElementById("editBMPanel_tagsSelectorExpander").doCommand();
return promise;
}
]]>
</script>

View File

@ -34,163 +34,170 @@
<script type="application/javascript">
<![CDATA[
function runTest()
{
Components.utils.import("resource://gre/modules/NetUtil.jsm");
function checkTagsSelector(aAvailableTags, aCheckedTags) {
is(PlacesUtils.tagging.allTags.length, aAvailableTags.length,
"tagging service is in sync.");
let tagsSelector = document.getElementById("editBMPanel_tagsSelector");
let children = tagsSelector.childNodes;
is(children.length, aAvailableTags.length,
"Found expected number of tags in the tags selector");
const TEST_URI = NetUtil.newURI("http://www.test.me/");
const TEST_URI2 = NetUtil.newURI("http://www.test.again.me/");
const TEST_TAG = "test-tag";
Array.forEach(children, function (aChild) {
let tag = aChild.getAttribute("label");
ok(true, "Found tag '" + tag + "' in the selector");
ok(aAvailableTags.indexOf(tag) != -1, "Found expected tag");
let checked = aChild.getAttribute("checked") == "true";
is(checked, aCheckedTags.indexOf(tag) != -1,
"Tag is correctly marked");
});
}
ok(gEditItemOverlay, "Sanity check: gEditItemOverlay is in context");
function runTest() {
SimpleTest.waitForExplicitFinish();
// Open the tags selector.
document.getElementById("editBMPanel_tagsSelectorRow").collapsed = false;
Task.spawn(function* () {
const TEST_URI = Services.io.newURI("http://www.test.me/", null, null);
const TEST_URI2 = Services.io.newURI("http://www.test.again.me/", null, null);
const TEST_TAG = "test-tag";
function checkTagsSelector(aAvailableTags, aCheckedTags)
{
is(PlacesUtils.tagging.allTags.length, aAvailableTags.length,
"tagging service is in sync.");
let tagsSelector = document.getElementById("editBMPanel_tagsSelector");
let children = tagsSelector.childNodes;
is(children.length, aAvailableTags.length,
"Found expected number of tags in the tags selector");
Array.forEach(children, function (aChild) {
let tag = aChild.getAttribute("label");
ok(true, "Found tag '" + tag + "' in the selector");
ok(aAvailableTags.indexOf(tag) != -1, "Found expected tag");
let checked = aChild.getAttribute("checked") == "true";
is(checked, aCheckedTags.indexOf(tag) != -1,
"Tag is correctly marked");
ok(gEditItemOverlay, "Sanity check: gEditItemOverlay is in context");
// Open the tags selector.
document.getElementById("editBMPanel_tagsSelectorRow").collapsed = false;
// Add a bookmark.
let bm = yield PlacesUtils.bookmarks.insert({
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
index: PlacesUtils.bookmarks.DEFAULT_INDEX,
type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
url: TEST_URI.spec,
title: "test.me"
});
}
// Add a bookmark.
let itemId = PlacesUtils.bookmarks.insertBookmark(
PlacesUtils.unfiledBookmarksFolderId, TEST_URI,
PlacesUtils.bookmarks.DEFAULT_INDEX, "test.me"
);
// Init panel.
itemId = yield PlacesUtils.promiseItemId(bm.guid);
gEditItemOverlay.initPanel(itemId);
// Init panel.
gEditItemOverlay.initPanel(itemId);
// Add a tag.
PlacesUtils.tagging.tagURI(TEST_URI, [TEST_TAG]);
// Add a tag.
PlacesUtils.tagging.tagURI(TEST_URI, [TEST_TAG]);
is(PlacesUtils.tagging.getTagsForURI(TEST_URI)[0], TEST_TAG,
"Correctly added tag to a single bookmark");
is(document.getElementById("editBMPanel_tagsField").value, TEST_TAG,
"Editing a single bookmark shows the added tag");
checkTagsSelector([TEST_TAG], [TEST_TAG]);
is(PlacesUtils.tagging.getTagsForURI(TEST_URI)[0], TEST_TAG,
"Correctly added tag to a single bookmark");
is(document.getElementById("editBMPanel_tagsField").value, TEST_TAG,
"Editing a single bookmark shows the added tag");
checkTagsSelector([TEST_TAG], [TEST_TAG]);
// Remove tag.
PlacesUtils.tagging.untagURI(TEST_URI, [TEST_TAG]);
is(PlacesUtils.tagging.getTagsForURI(TEST_URI)[0], undefined,
"The tag has been removed");
is(document.getElementById("editBMPanel_tagsField").value, "",
"Editing a single bookmark should not show any tag");
checkTagsSelector([], []);
// Remove tag.
PlacesUtils.tagging.untagURI(TEST_URI, [TEST_TAG]);
is(PlacesUtils.tagging.getTagsForURI(TEST_URI)[0], undefined,
"The tag has been removed");
is(document.getElementById("editBMPanel_tagsField").value, "",
"Editing a single bookmark should not show any tag");
checkTagsSelector([], []);
// Add a second bookmark.
let bm2 = yield PlacesUtils.bookmarks.insert({
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
index: PlacesUtils.bookmarks.DEFAULT_INDEX,
type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
title: "test.again.me",
url: TEST_URI2.spec
});
// Add a second bookmark.
let itemId2 = PlacesUtils.bookmarks.insertBookmark(
PlacesUtils.unfiledBookmarksFolderId, TEST_URI2,
PlacesUtils.bookmarks.DEFAULT_INDEX, "test.again.me"
);
// Init panel with multiple bookmarks.
itemId2 = yield PlacesUtils.promiseItemId(bm2.guid);
gEditItemOverlay.initPanel([itemId, itemId2]);
// Init panel with multiple bookmarks.
gEditItemOverlay.initPanel([itemId, itemId2]);
// Add a tag to the first bookmark.
PlacesUtils.tagging.tagURI(TEST_URI, [TEST_TAG]);
is(PlacesUtils.tagging.getTagsForURI(TEST_URI)[0], TEST_TAG,
"Correctly added a tag to the first bookmark.");
is(document.getElementById("editBMPanel_tagsField").value, "",
"Editing multiple bookmarks without matching tags should not show any tag.");
checkTagsSelector([TEST_TAG], []);
// Add a tag to the first bookmark.
PlacesUtils.tagging.tagURI(TEST_URI, [TEST_TAG]);
is(PlacesUtils.tagging.getTagsForURI(TEST_URI)[0], TEST_TAG,
"Correctly added a tag to the first bookmark.");
is(document.getElementById("editBMPanel_tagsField").value, "",
"Editing multiple bookmarks without matching tags should not show any tag.");
checkTagsSelector([TEST_TAG], []);
// Add a tag to the second bookmark.
PlacesUtils.tagging.tagURI(TEST_URI2, [TEST_TAG]);
is(PlacesUtils.tagging.getTagsForURI(TEST_URI2)[0], TEST_TAG,
"Correctly added a tag to the second bookmark.");
is(document.getElementById("editBMPanel_tagsField").value, TEST_TAG,
"Editing multiple bookmarks should show matching tags.");
checkTagsSelector([TEST_TAG], [TEST_TAG]);
// Add a tag to the second bookmark.
PlacesUtils.tagging.tagURI(TEST_URI2, [TEST_TAG]);
is(PlacesUtils.tagging.getTagsForURI(TEST_URI2)[0], TEST_TAG,
"Correctly added a tag to the second bookmark.");
is(document.getElementById("editBMPanel_tagsField").value, TEST_TAG,
"Editing multiple bookmarks should show matching tags.");
checkTagsSelector([TEST_TAG], [TEST_TAG]);
// Remove tag from the first bookmark.
PlacesUtils.tagging.untagURI(TEST_URI, [TEST_TAG]);
is(PlacesUtils.tagging.getTagsForURI(TEST_URI)[0], undefined,
"Correctly removed tag from the first bookmark.");
is(document.getElementById("editBMPanel_tagsField").value, "",
"Editing multiple bookmarks without matching tags should not show any tag.");
checkTagsSelector([TEST_TAG], []);
// Remove tag from the first bookmark.
PlacesUtils.tagging.untagURI(TEST_URI, [TEST_TAG]);
is(PlacesUtils.tagging.getTagsForURI(TEST_URI)[0], undefined,
"Correctly removed tag from the first bookmark.");
is(document.getElementById("editBMPanel_tagsField").value, "",
"Editing multiple bookmarks without matching tags should not show any tag.");
checkTagsSelector([TEST_TAG], []);
// Remove tag from the second bookmark.
PlacesUtils.tagging.untagURI(TEST_URI2, [TEST_TAG]);
is(PlacesUtils.tagging.getTagsForURI(TEST_URI2)[0], undefined,
"Correctly removed tag from the second bookmark.");
is(document.getElementById("editBMPanel_tagsField").value, "",
"Editing multiple bookmarks without matching tags should not show any tag.");
checkTagsSelector([], []);
// Remove tag from the second bookmark.
PlacesUtils.tagging.untagURI(TEST_URI2, [TEST_TAG]);
is(PlacesUtils.tagging.getTagsForURI(TEST_URI2)[0], undefined,
"Correctly removed tag from the second bookmark.");
is(document.getElementById("editBMPanel_tagsField").value, "",
"Editing multiple bookmarks without matching tags should not show any tag.");
checkTagsSelector([], []);
// Init panel with a nsIURI entry.
gEditItemOverlay.initPanel(TEST_URI);
// Init panel with a nsIURI entry.
gEditItemOverlay.initPanel(TEST_URI);
// Add a tag.
PlacesUtils.tagging.tagURI(TEST_URI, [TEST_TAG]);
is(PlacesUtils.tagging.getTagsForURI(TEST_URI)[0], TEST_TAG,
"Correctly added tag to the first entry.");
is(document.getElementById("editBMPanel_tagsField").value, TEST_TAG,
"Editing a single nsIURI entry shows the added tag");
checkTagsSelector([TEST_TAG], [TEST_TAG]);
// Add a tag.
PlacesUtils.tagging.tagURI(TEST_URI, [TEST_TAG]);
is(PlacesUtils.tagging.getTagsForURI(TEST_URI)[0], TEST_TAG,
"Correctly added tag to the first entry.");
is(document.getElementById("editBMPanel_tagsField").value, TEST_TAG,
"Editing a single nsIURI entry shows the added tag");
checkTagsSelector([TEST_TAG], [TEST_TAG]);
// Remove tag.
PlacesUtils.tagging.untagURI(TEST_URI, [TEST_TAG]);
is(PlacesUtils.tagging.getTagsForURI(TEST_URI)[0], undefined,
"Correctly removed tag from the nsIURI entry.");
is(document.getElementById("editBMPanel_tagsField").value, "",
"Editing a single nsIURI entry should not show any tag");
checkTagsSelector([], []);
// Remove tag.
PlacesUtils.tagging.untagURI(TEST_URI, [TEST_TAG]);
is(PlacesUtils.tagging.getTagsForURI(TEST_URI)[0], undefined,
"Correctly removed tag from the nsIURI entry.");
is(document.getElementById("editBMPanel_tagsField").value, "",
"Editing a single nsIURI entry should not show any tag");
checkTagsSelector([], []);
// Init panel with multiple nsIURI entries.
gEditItemOverlay.initPanel([TEST_URI, TEST_URI2]);
// Init panel with multiple nsIURI entries.
gEditItemOverlay.initPanel([TEST_URI, TEST_URI2]);
// Add a tag to the first entry.
PlacesUtils.tagging.tagURI(TEST_URI, [TEST_TAG]);
is(PlacesUtils.tagging.getTagsForURI(TEST_URI)[0], TEST_TAG,
"Tag correctly added.");
is(document.getElementById("editBMPanel_tagsField").value, "",
"Editing multiple nsIURIs without matching tags should not show any tag.");
checkTagsSelector([TEST_TAG], []);
// Add a tag to the first entry.
PlacesUtils.tagging.tagURI(TEST_URI, [TEST_TAG]);
is(PlacesUtils.tagging.getTagsForURI(TEST_URI)[0], TEST_TAG,
"Tag correctly added.");
is(document.getElementById("editBMPanel_tagsField").value, "",
"Editing multiple nsIURIs without matching tags should not show any tag.");
checkTagsSelector([TEST_TAG], []);
// Add a tag to the second entry.
PlacesUtils.tagging.tagURI(TEST_URI2, [TEST_TAG]);
is(PlacesUtils.tagging.getTagsForURI(TEST_URI2)[0], TEST_TAG,
"Tag correctly added.");
is(document.getElementById("editBMPanel_tagsField").value, TEST_TAG,
"Editing multiple nsIURIs should show matching tags");
checkTagsSelector([TEST_TAG], [TEST_TAG]);
// Add a tag to the second entry.
PlacesUtils.tagging.tagURI(TEST_URI2, [TEST_TAG]);
is(PlacesUtils.tagging.getTagsForURI(TEST_URI2)[0], TEST_TAG,
"Tag correctly added.");
is(document.getElementById("editBMPanel_tagsField").value, TEST_TAG,
"Editing multiple nsIURIs should show matching tags");
checkTagsSelector([TEST_TAG], [TEST_TAG]);
// Remove tag from the first entry.
PlacesUtils.tagging.untagURI(TEST_URI, [TEST_TAG]);
is(PlacesUtils.tagging.getTagsForURI(TEST_URI)[0], undefined,
"Correctly removed tag from the first entry.");
is(document.getElementById("editBMPanel_tagsField").value, "",
"Editing multiple nsIURIs without matching tags should not show any tag.");
checkTagsSelector([TEST_TAG], []);
// Remove tag from the first entry.
PlacesUtils.tagging.untagURI(TEST_URI, [TEST_TAG]);
is(PlacesUtils.tagging.getTagsForURI(TEST_URI)[0], undefined,
"Correctly removed tag from the first entry.");
is(document.getElementById("editBMPanel_tagsField").value, "",
"Editing multiple nsIURIs without matching tags should not show any tag.");
checkTagsSelector([TEST_TAG], []);
// Remove tag from the second entry.
PlacesUtils.tagging.untagURI(TEST_URI2, [TEST_TAG]);
is(PlacesUtils.tagging.getTagsForURI(TEST_URI2)[0], undefined,
"Correctly removed tag from the second entry.");
is(document.getElementById("editBMPanel_tagsField").value, "",
"Editing multiple nsIURIs without matching tags should not show any tag.");
checkTagsSelector([], []);
// Cleanup.
PlacesUtils.bookmarks.removeFolderChildren(
PlacesUtils.unfiledBookmarksFolderId
);
// Remove tag from the second entry.
PlacesUtils.tagging.untagURI(TEST_URI2, [TEST_TAG]);
is(PlacesUtils.tagging.getTagsForURI(TEST_URI2)[0], undefined,
"Correctly removed tag from the second entry.");
is(document.getElementById("editBMPanel_tagsField").value, "",
"Editing multiple nsIURIs without matching tags should not show any tag.");
checkTagsSelector([], []);
// Cleanup.
yield PlacesUtils.bookmarks.remove(bm.guid);
yield PlacesUtils.bookmarks.remove(bm2.guid);
}).then(SimpleTest.finish);
}
]]>
</script>

View File

@ -38,29 +38,49 @@
*/
function runTest() {
PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId,
NetUtil.newURI("place:folder=UNFILED_BOOKMARKS"),
PlacesUtils.bookmarks.DEFAULT_INDEX,
"shortcut");
PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId,
NetUtil.newURI("place:folder=UNFILED_BOOKMARKS&maxResults=10"),
PlacesUtils.bookmarks.DEFAULT_INDEX,
"query");
let folderId = PlacesUtils.bookmarks.createFolder(PlacesUtils.unfiledBookmarksFolderId,
"folder",
PlacesUtils.bookmarks.DEFAULT_INDEX);
let itemId = PlacesUtils.bookmarks.insertBookmark(folderId,
NetUtil.newURI("http://www.mozilla.org/"),
PlacesUtils.bookmarks.DEFAULT_INDEX,
"bookmark");
// Setup the places tree contents.
var tree = document.getElementById("tree");
tree.place = "place:folder=UNFILED_BOOKMARKS";
SimpleTest.waitForExplicitFinish();
// Select the last bookmark.
tree.selectItems([itemId]);
is (tree.selectedNode.itemId, itemId, "The right node was selected");
Task.spawn(function* () {
yield PlacesUtils.bookmarks.insert({
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
index: PlacesUtils.bookmarks.DEFAULT_INDEX,
type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
url: "place:folder=UNFILED_BOOKMARKS",
title: "shortcut"
});
yield PlacesUtils.bookmarks.insert({
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
index: PlacesUtils.bookmarks.DEFAULT_INDEX,
type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
url: "place:folder=UNFILED_BOOKMARKS&maxResults=10",
title: "query"
});
let folder = yield PlacesUtils.bookmarks.insert({
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
index: PlacesUtils.bookmarks.DEFAULT_INDEX,
type: PlacesUtils.bookmarks.TYPE_FOLDER,
title: "folder"
});
let bm = yield PlacesUtils.bookmarks.insert({
parentGuid: folder.guid,
index: PlacesUtils.bookmarks.DEFAULT_INDEX,
type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
url: "http://www.mozilla.org/",
title: "bookmark"
});
// Setup the places tree contents.
let tree = document.getElementById("tree");
tree.place = "place:folder=UNFILED_BOOKMARKS";
// Select the last bookmark.
let itemId = yield PlacesUtils.promiseItemId(bm.guid);
tree.selectItems([itemId]);
is (tree.selectedNode.itemId, itemId, "The right node was selected");
}).then(SimpleTest.finish);
}
]]></script>
</window>

View File

@ -50,62 +50,69 @@
* Ensures that date in places treeviews is correctly formatted.
*/
SimpleTest.waitForExplicitFinish();
function runTest() {
// The mochitest page is added to history.
PlacesTestUtils.clearHistory().then(continue_test);
}
SimpleTest.waitForExplicitFinish();
function continue_test() {
var hs = Cc["@mozilla.org/browser/nav-history-service;1"].
getService(Ci.nsINavHistoryService);
var bh = hs.QueryInterface(Ci.nsIBrowserHistory);
var bs = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
getService(Ci.nsINavBookmarksService);
var ds = Cc["@mozilla.org/intl/scriptabledateformat;1"].
let ds = Cc["@mozilla.org/intl/scriptabledateformat;1"].
getService(Ci.nsIScriptableDateFormat);
var iosvc = Cc["@mozilla.org/network/io-service;1"].
getService(Ci.nsIIOService);
function uri(spec) {
return iosvc.newURI(spec, null, null);
return Services.io.newURI(spec, null, null);
}
var midnight = new Date();
midnight.setHours(0);
midnight.setMinutes(0);
midnight.setSeconds(0);
midnight.setMilliseconds(0);
Task.spawn(function* () {
yield PlacesTestUtils.clearHistory();
let midnight = new Date();
midnight.setHours(0);
midnight.setMinutes(0);
midnight.setSeconds(0);
midnight.setMilliseconds(0);
// Add a visit 1ms before midnight, a visit at midnight, and
// a visit 1ms after midnight.
yield new Promise(resolve => addVisits(
[{uri: uri("http://before.midnight.com/"),
visitDate: (midnight.getTime() - 1) * 1000,
transition: PlacesUtils.history.TRANSITION_TYPED},
{uri: uri("http://at.midnight.com/"),
visitDate: (midnight.getTime()) * 1000,
transition: PlacesUtils.history.TRANSITION_TYPED},
{uri: uri("http://after.midnight.com/"),
visitDate: (midnight.getTime() + 1) * 1000,
transition: PlacesUtils.history.TRANSITION_TYPED}],
resolve));
function addVisitsCallback() {
// add a bookmark to the midnight visit
var itemId = bs.insertBookmark(bs.toolbarFolder,
uri("http://at.midnight.com/"),
bs.DEFAULT_INDEX,
"A bookmark at midnight");
let bm = yield PlacesUtils.bookmarks.insert({
parentGuid: PlacesUtils.bookmarks.toolbarGuid,
index: PlacesUtils.bookmarks.DEFAULT_INDEX,
url: "http://at.midnight.com/",
title: "A bookmark at midnight",
type: PlacesUtils.bookmarks.TYPE_BOOKMARK
});
// Make a history query.
var query = hs.getNewQuery();
var opts = hs.getNewQueryOptions();
var queryURI = hs.queriesToQueryString([query], 1, opts);
let query = PlacesUtils.history.getNewQuery();
let opts = PlacesUtils.history.getNewQueryOptions();
let queryURI = PlacesUtils.history.queriesToQueryString([query], 1, opts);
// Setup the places tree contents.
var tree = document.getElementById("tree");
let tree = document.getElementById("tree");
tree.place = queryURI;
// loop through the rows and check formatting
var treeView = tree.view;
var rc = treeView.rowCount;
let treeView = tree.view;
let rc = treeView.rowCount;
ok(rc >= 3, "Rows found");
var columns = tree.columns;
let columns = tree.columns;
ok(columns.count > 0, "Columns found");
for (var r = 0; r < rc; r++) {
var node = treeView.nodeForTreeIndex(r);
for (let r = 0; r < rc; r++) {
let node = treeView.nodeForTreeIndex(r);
ok(node, "Places node found");
for (var ci = 0; ci < columns.count; ci++) {
var c = columns.getColumnAt(ci);
var text = treeView.getCellText(r, c);
for (let ci = 0; ci < columns.count; ci++) {
let c = columns.getColumnAt(ci);
let text = treeView.getCellText(r, c);
switch (c.element.getAttribute("anonid")) {
case "title":
// The title can differ, we did not set any title so we would
@ -118,9 +125,9 @@
is(text, node.uri, "Uri is correct");
break;
case "date":
var timeObj = new Date(node.time / 1000);
let timeObj = new Date(node.time / 1000);
// Default is short date format.
var dateFormat = Ci.nsIScriptableDateFormat.dateFormatShort;
let dateFormat = Ci.nsIScriptableDateFormat.dateFormatShort;
// For today's visits we don't show date portion.
if (node.uri == "http://at.midnight.com/" ||
node.uri == "http://after.midnight.com/")
@ -132,7 +139,7 @@
// a redirecting uri could be put in the tree while we test.
break;
}
var timeStr = ds.FormatDateTime("", dateFormat,
let timeStr = ds.FormatDateTime("", dateFormat,
Ci.nsIScriptableDateFormat.timeFormatNoSeconds,
timeObj.getFullYear(), timeObj.getMonth() + 1,
timeObj.getDate(), timeObj.getHours(),
@ -146,26 +153,12 @@
}
}
}
// Cleanup.
bs.removeItem(itemId);
PlacesTestUtils.clearHistory().then(SimpleTest.finish);
}
// Add a visit 1ms before midnight, a visit at midnight, and
// a visit 1ms after midnight.
addVisits(
[{uri: uri("http://before.midnight.com/"),
visitDate: (midnight.getTime() - 1) * 1000,
transition: hs.TRANSITION_TYPED},
{uri: uri("http://at.midnight.com/"),
visitDate: (midnight.getTime()) * 1000,
transition: hs.TRANSITION_TYPED},
{uri: uri("http://after.midnight.com/"),
visitDate: (midnight.getTime() + 1) * 1000,
transition: hs.TRANSITION_TYPED}],
addVisitsCallback);
yield PlacesUtils.bookmarks.remove(bm.guid);
yield PlacesTestUtils.clearHistory();
}).then(SimpleTest.finish);
}
]]>
</script>
</window>

View File

@ -44,8 +44,11 @@ var gContentPane = {
let drmInfoURL =
Services.urlFormatter.formatURLPref("app.support.baseURL") + "drm-content";
document.getElementById("playDRMContentLink").setAttribute("href", drmInfoURL);
document.getElementById("playDRMContentRow").hidden =
!Services.prefs.getBoolPref("browser.eme.ui.enabled");
if (!Services.prefs.getBoolPref("browser.eme.ui.enabled")) {
// Don't want to rely on .hidden for the toplevel groupbox because
// of the pane hiding/showing code potentially interfering:
document.getElementById("drmGroup").setAttribute("style", "display: none !important");
}
},
// UTILITY FUNCTIONS

View File

@ -39,22 +39,35 @@
<label class="header-name">&paneContent.title;</label>
</hbox>
<groupbox id="drmGroup" data-category="paneContent" hidden="true">
<caption><label>&drmContent.label;</label></caption>
<grid id="contentGrid2">
<columns>
<column flex="1"/>
<column/>
</columns>
<rows id="contentRows-2">
<row id="playDRMContentRow">
<vbox align="start">
<checkbox id="playDRMContent" preference="media.eme.enabled"
label="&playDRMContent.label;" accesskey="&playDRMContent.accesskey;"/>
</vbox>
<hbox pack="end" align="center">
<label id="playDRMContentLink" class="text-link" value="&playDRMContent.learnMore.label;"/>
</hbox>
</row>
</rows>
</grid>
</groupbox>
<groupbox id="miscGroup" data-category="paneContent" hidden="true">
<caption><label>&popups.label;</label></caption>
<grid id="contentGrid">
<columns>
<column flex="1"/>
<column/>
</columns>
<rows id="contentRows-1">
<row id="playDRMContentRow">
<vbox align="start">
<checkbox id="playDRMContent" preference="media.eme.enabled"
label="&playDRMContent.label;" accesskey="&playDRMContent.accesskey;"/>
</vbox>
<hbox pack="end">
<label id="playDRMContentLink" class="text-link" value="&playDRMContent.learnMore.label;"/>
</hbox>
</row>
<row id="popupPolicyRow">
<vbox align="start">
<checkbox id="popupPolicy" preference="dom.disable_open_during_load"

View File

@ -110,6 +110,9 @@ let gSubDialog = {
this.injectXMLStylesheet(styleSheetURL);
}
// Provide the ability for the dialog to know that it is being loaded "in-content".
this._frame.contentDocument.documentElement.setAttribute("subdialog", "true");
// Make window.close calls work like dialog closing.
let oldClose = this._frame.contentWindow.close;
this._frame.contentWindow.close = function() {

View File

@ -27,6 +27,7 @@ function checkElements(expectedPane) {
}
function runTest(win) {
Services.prefs.setBoolPref("browser.eme.ui.enabled", true);
is(gBrowser.currentURI.spec, "about:preferences", "about:preferences loaded");
let tab = win.document;
@ -44,5 +45,6 @@ function runTest(win) {
gBrowser.removeCurrentTab();
win.close();
Services.prefs.clearUserPref("browser.eme.ui.enabled");
finish();
}

View File

@ -4,6 +4,15 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
let gSanitizeDialog = Object.freeze({
init: function() {
let customWidthElements = document.getElementsByAttribute("dialogWidth", "*");
let isInSubdialog = document.documentElement.hasAttribute("subdialog");
for (let element of customWidthElements) {
element.style.width = element.getAttribute(isInSubdialog ? "subdialogWidth" : "dialogWidth");
}
onClearHistoryChanged();
},
onClearHistoryChanged: function () {
let downloadsPref = document.getElementById("privacy.clearOnShutdown.downloads");
let historyPref = document.getElementById("privacy.clearOnShutdown.history");

View File

@ -19,9 +19,10 @@
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
dlgbuttons="accept,cancel,help"
ondialoghelp="openPrefsHelp()"
style="width: &dialog.width2;;"
dialogWidth="&dialog.width2;"
subdialogWidth="&inContentDialog.width;"
title="&sanitizePrefs2.title;"
onload="gSanitizeDialog.onClearHistoryChanged();">
onload="gSanitizeDialog.init();">
<script type="application/javascript" src="chrome://browser/content/utilityOverlay.js"/>
<script type="application/javascript" src="chrome://browser/content/preferences/sanitize.js"/>
@ -48,7 +49,8 @@
<caption label="&historySection.label;"/>
<grid flex="1">
<columns>
<column style="width: &column.width2;"/>
<column dialogWidth="&column.width2;"
subdialogWidth="&inContentColumn.width;"/>
<column flex="1"/>
</columns>
<rows>
@ -80,7 +82,8 @@
<caption label="&dataSection.label;"/>
<grid flex="1">
<columns>
<column style="width: &column.width2;"/>
<column dialogWidth="&column.width2;"
subdialogWidth="&inContentColumn.width;"/>
<column flex="1"/>
</columns>
<rows>

View File

@ -13,7 +13,7 @@ function test() {
let engine = Services.search.getEngineByName("Bing");
ok(engine, "Bing");
let base = "http://www.bing.com/search?q=foo&pc=MOZI";
let base = "https://www.bing.com/search?q=foo&pc=MOZI";
let url;
// Test search URLs (including purposes).
@ -32,14 +32,14 @@ function test() {
// Check search suggestion URL.
url = engine.getSubmission("foo", "application/x-suggestions+json").uri.spec;
is(url, "http://api.bing.com/osjson.aspx?query=foo&form=OSDJAS&language=" + getLocale(), "Check search suggestion URL for 'foo'");
is(url, "https://www.bing.com/osjson.aspx?query=foo&form=OSDJAS&language=" + getLocale(), "Check search suggestion URL for 'foo'");
// Check all other engine properties.
const EXPECTED_ENGINE = {
name: "Bing",
alias: null,
description: "Bing. Search by Microsoft.",
searchForm: "http://www.bing.com/search?q=&pc=MOZI",
searchForm: "https://www.bing.com/search?q=&pc=MOZI",
type: Ci.nsISearchEngine.TYPE_MOZSEARCH,
hidden: false,
wrappedJSObject: {
@ -49,7 +49,7 @@ function test() {
{
type: "application/x-suggestions+json",
method: "GET",
template: "http://api.bing.com/osjson.aspx",
template: "https://www.bing.com/osjson.aspx",
params: [
{
name: "query",
@ -71,7 +71,7 @@ function test() {
{
type: "text/html",
method: "GET",
template: "http://www.bing.com/search",
template: "https://www.bing.com/search",
params: [
{
name: "q",

View File

@ -18,7 +18,7 @@ function test() {
Services.search.currentEngine = engine;
engine.alias = "b";
let base = "http://www.bing.com/search?q=foo&pc=MOZI";
let base = "https://www.bing.com/search?q=foo&pc=MOZI";
let url;
// Test search URLs (including purposes).

View File

@ -13,7 +13,7 @@ function test() {
let engine = Services.search.getEngineByName("Yahoo");
ok(engine, "Yahoo");
let base = "https://search.yahoo.com/yhs/search?p=foo&ei=UTF-8&hspart=mozilla&hsimp=yhs-001";
let base = "https://search.yahoo.com/yhs/search?p=foo&ei=UTF-8&hspart=mozilla";
let url;
// Test search URLs (including purposes).
@ -29,7 +29,7 @@ function test() {
name: "Yahoo",
alias: null,
description: "Yahoo Search",
searchForm: "https://search.yahoo.com/yhs/search?p=&ei=UTF-8&hspart=mozilla&hsimp=yhs-001",
searchForm: "https://search.yahoo.com/yhs/search?p=&ei=UTF-8&hspart=mozilla",
type: Ci.nsISearchEngine.TYPE_MOZSEARCH,
hidden: false,
wrappedJSObject: {
@ -81,7 +81,27 @@ function test() {
{
name: "hsimp",
value: "yhs-001",
purpose: undefined,
purpose: "searchbar",
},
{
name: "hsimp",
value: "yhs-002",
purpose: "keyword",
},
{
name: "hsimp",
value: "yhs-003",
purpose: "homepage",
},
{
name: "hsimp",
value: "yhs-004",
purpose: "newtab",
},
{
name: "hsimp",
value: "yhs-005",
purpose: "contextmenu",
},
],
mozparams: {},

View File

@ -18,7 +18,7 @@ function test() {
Services.search.currentEngine = engine;
engine.alias = "y";
let base = "https://search.yahoo.com/yhs/search?p=foo&ei=UTF-8&hspart=mozilla&hsimp=yhs-001";
let base = "https://search.yahoo.com/yhs/search?p=foo&ei=UTF-8&hspart=mozilla";
let url;
// Test search URLs (including purposes).
@ -31,7 +31,7 @@ function test() {
var gTests = [
{
name: "context menu search",
searchURL: base,
searchURL: base + "&hsimp=yhs-005",
run: function () {
// Simulate a contextmenu search
// FIXME: This is a bit "low-level"...
@ -40,7 +40,7 @@ function test() {
},
{
name: "keyword search",
searchURL: base,
searchURL: base + "&hsimp=yhs-002",
run: function () {
gURLBar.value = "? foo";
gURLBar.focus();
@ -48,8 +48,8 @@ function test() {
}
},
{
name: "keyword search",
searchURL: base,
name: "keyword search with alias",
searchURL: base + "&hsimp=yhs-002",
run: function () {
gURLBar.value = "y foo";
gURLBar.focus();
@ -58,7 +58,7 @@ function test() {
},
{
name: "search bar search",
searchURL: base,
searchURL: base + "&hsimp=yhs-001",
run: function () {
let sb = BrowserSearch.searchBar;
sb.focus();
@ -71,7 +71,7 @@ function test() {
},
{
name: "new tab search",
searchURL: base,
searchURL: base + "&hsimp=yhs-004",
run: function () {
function doSearch(doc) {
// Re-add the listener, and perform a search

View File

@ -3,8 +3,8 @@
"use strict";
const URL = ROOT + "browser_frametree_sample.html";
const URL_FRAMESET = ROOT + "browser_frametree_sample_frameset.html";
const URL = HTTPROOT + "browser_frametree_sample.html";
const URL_FRAMESET = HTTPROOT + "browser_frametree_sample_frameset.html";
/**
* This ensures that loading a page normally, aborting a page load, reloading

View File

@ -6,6 +6,7 @@ const TAB_STATE_NEEDS_RESTORE = 1;
const TAB_STATE_RESTORING = 2;
const ROOT = getRootDirectory(gTestPath);
const HTTPROOT = ROOT.replace("chrome://mochitests/content/", "http://example.com/");
const FRAME_SCRIPTS = [
ROOT + "content.js",
ROOT + "content-forms.js"

View File

@ -540,7 +540,7 @@ skip-if = e10s && debug
[browser_dbg_variables-view-popup-13.js]
skip-if = e10s && debug
[browser_dbg_variables-view-popup-14.js]
skip-if = (e10s && debug) || (e10s && os == 'linux') # Linux e10s - bug 1029545
skip-if = true # Bug 1029545
[browser_dbg_variables-view-popup-15.js]
skip-if = e10s && debug
[browser_dbg_variables-view-popup-16.js]

View File

@ -30,7 +30,7 @@ let PerformanceView = {
* Sets up the view with event binding and main subviews.
*/
initialize: function () {
this._recordButton = $("#record-button");
this._recordButton = $("#main-record-button");
this._importButton = $("#import-button");
this._clearButton = $("#clear-button");

View File

@ -64,7 +64,7 @@
class="devtools-toolbar">
<hbox id="recordings-controls"
class="devtools-toolbarbutton-group">
<toolbarbutton id="record-button"
<toolbarbutton id="main-record-button"
class="devtools-toolbarbutton record-button"
tooltiptext="&profilerUI.recordButton.tooltip;"/>
<toolbarbutton id="import-button"

View File

@ -21,10 +21,10 @@ let test = Task.async(function*() {
RecordingsView.selectedIndex = 0;
yield select;
ok($("#record-button").hasAttribute("checked"),
ok($("#main-record-button").hasAttribute("checked"),
"Button is still checked after selecting another item.");
ok(!$("#record-button").hasAttribute("locked"),
ok(!$("#main-record-button").hasAttribute("locked"),
"Button is not locked after selecting another item.");
yield stopRecording(panel);

View File

@ -244,7 +244,7 @@ function* startRecording(panel) {
let clicked = panel.panelWin.PerformanceView.once(win.EVENTS.UI_START_RECORDING);
let willStart = panel.panelWin.PerformanceController.once(win.EVENTS.RECORDING_WILL_START);
let hasStarted = panel.panelWin.PerformanceController.once(win.EVENTS.RECORDING_STARTED);
let button = win.$("#record-button");
let button = win.$("#main-record-button");
ok(!button.hasAttribute("checked"),
"The record button should not be checked yet.");
@ -275,7 +275,7 @@ function* stopRecording(panel) {
let clicked = panel.panelWin.PerformanceView.once(win.EVENTS.UI_STOP_RECORDING);
let willStop = panel.panelWin.PerformanceController.once(win.EVENTS.RECORDING_WILL_STOP);
let hasStopped = panel.panelWin.PerformanceController.once(win.EVENTS.RECORDING_STOPPED);
let button = win.$("#record-button");
let button = win.$("#main-record-button");
ok(button.hasAttribute("checked"),
"The record button should already be checked.");

View File

@ -2,7 +2,7 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
const TESTCASE_URI = TEST_BASE + "longload.html";
const TESTCASE_URI = TEST_BASE_HTTP + "longload.html";
function test()

View File

@ -383,8 +383,6 @@
@RESPATH@/browser/components/nsBrowserGlue.js
@RESPATH@/browser/components/nsSetDefaultBrowser.manifest
@RESPATH@/browser/components/nsSetDefaultBrowser.js
@RESPATH@/browser/components/BrowserDownloads.manifest
@RESPATH@/browser/components/DownloadsStartup.js
@RESPATH@/browser/components/devtools-clhandler.manifest
@RESPATH@/browser/components/devtools-clhandler.js
@RESPATH@/browser/components/webideCli.js

View File

@ -43,6 +43,8 @@
<!ENTITY translation.options.attribution.beforeLogo "Translations by">
<!ENTITY translation.options.attribution.afterLogo "">
<!ENTITY drmContent.label "DRM content">
<!ENTITY playDRMContent.label "Play DRM content">
<!ENTITY playDRMContent.accesskey "P">
<!ENTITY playDRMContent.learnMore.label "Learn more">

View File

@ -60,3 +60,11 @@ that require it. -->
at half of the dialog width. -->
<!ENTITY dialog.width2 "34em">
<!ENTITY column.width2 "17em">
<!-- LOCALIZATION NOTE (inContentDialog.width): width of the Clear Recent History and
Clear History on Shutdown subdialogs in the in-content preferences. Should be
large enough to contain the item* strings above on a single line. The column
width adjusts the width of the first column in the dialog. You can set the
column width to a value that makes the dialog look visually balanced, or at half
of the dialog width if unsure. -->
<!ENTITY inContentDialog.width "34em">
<!ENTITY inContentColumn.width "24em">

File diff suppressed because one or more lines are too long

View File

@ -20,6 +20,10 @@
<Param name="p" value="{searchTerms}"/>
<Param name="ei" value="UTF-8"/>
<Param name="hspart" value="mozilla"/>
<Param name="hsimp" value="yhs-001"/>
<MozParam name="hsimp" condition="purpose" purpose="searchbar" value="yhs-001"/>
<MozParam name="hsimp" condition="purpose" purpose="keyword" value="yhs-002"/>
<MozParam name="hsimp" condition="purpose" purpose="homepage" value="yhs-003"/>
<MozParam name="hsimp" condition="purpose" purpose="newtab" value="yhs-004"/>
<MozParam name="hsimp" condition="purpose" purpose="contextmenu" value="yhs-005"/>
</Url>
</SearchPlugin>

View File

@ -10,38 +10,67 @@ const {interfaces: Ci, utils: Cu, classes: Cc} = Components;
Cu.import("resource://gre/modules/Services.jsm");
function getAboutModule(aURL) {
// Needs to match NS_GetAboutModuleName
let moduleName = aURL.path.replace(/[#?].*/, "").toLowerCase();
let contract = "@mozilla.org/network/protocol/about;1?what=" + moduleName;
try {
return Cc[contract].getService(Ci.nsIAboutModule);
}
catch (e) {
// Either the about module isn't defined or it is broken. In either case
// ignore it.
return null;
}
}
this.E10SUtils = {
shouldBrowserBeRemote: function(aURL) {
canLoadURIInProcess: function(aURL, aProcess) {
// loadURI in browser.xml treats null as about:blank
if (!aURL)
aURL = "about:blank";
if (aURL.startsWith("about:") &&
aURL.toLowerCase() != "about:home" &&
aURL.toLowerCase() != "about:blank" &&
!aURL.toLowerCase().startsWith("about:neterror") &&
!aURL.toLowerCase().startsWith("about:certerror")) {
return false;
let processIsRemote = aProcess == Ci.nsIXULRuntime.PROCESS_TYPE_CONTENT;
let canLoadRemote = true;
let mustLoadRemote = true;
if (aURL.startsWith("about:")) {
let url = Services.io.newURI(aURL, null, null);
let module = getAboutModule(url);
// If the module doesn't exist then an error page will be loading, that
// should be ok to load in either process
if (module) {
let flags = module.getURIFlags(url);
canLoadRemote = !!(flags & Ci.nsIAboutModule.URI_CAN_LOAD_IN_CHILD);
mustLoadRemote = !!(flags & Ci.nsIAboutModule.URI_MUST_LOAD_IN_CHILD);
}
}
if (aURL.startsWith("chrome:")) {
let url = Services.io.newURI(aURL, null, null);
let chromeReg = Cc["@mozilla.org/chrome/chrome-registry;1"].
getService(Ci.nsIXULChromeRegistry);
canLoadRemote = chromeReg.canLoadURLRemotely(url);
mustLoadRemote = chromeReg.mustLoadURLRemotely(url);
}
if (mustLoadRemote)
return processIsRemote;
if (!canLoadRemote && processIsRemote)
return false;
return true;
},
shouldLoadURI: function(aDocShell, aURI, aReferrer) {
// about:blank is the initial document and can load anywhere
if (aURI.spec == "about:blank")
return true;
// Inner frames should always load in the current process
if (aDocShell.QueryInterface(Ci.nsIDocShellTreeItem).sameTypeParent)
return true;
// If the URI can be loaded in the current process then continue
let isRemote = Services.appinfo.processType == Services.appinfo.PROCESS_TYPE_CONTENT;
if (this.shouldBrowserBeRemote(aURI.spec) == isRemote)
return true;
return false;
return this.canLoadURIInProcess(aURI.spec, Services.appinfo.processType);
},
redirectLoad: function(aDocShell, aURI, aReferrer) {

View File

@ -51,20 +51,26 @@
/* Overview Panel */
.notice-container button,
#record-button {
.record-button {
list-style-image: url(profiler-stopwatch.svg);
}
.notice-container button[checked],
#record-button[checked] {
.record-button[checked] {
list-style-image: url(profiler-stopwatch-checked.svg);
}
#record-button[locked] {
.record-button[locked] {
pointer-events: none;
}
.record-button .button-icon {
margin: 0;
}
.record-button .button-text {
display: none;
}
/* Details Panel */
#select-waterfall-view {

View File

@ -182,6 +182,13 @@ treecol {
-moz-margin-start: 0;
}
/* Content pane */
#playDRMContentLink {
/* Line up with the buttons in the other grid bits: */
margin-left: 4px !important;
margin-right: 4px !important;
}
/* Applications Pane Styles */
#applicationsContent {

View File

@ -592,6 +592,70 @@ nsChromeRegistry::AllowContentToAccess(nsIURI *aURI, bool *aResult)
return NS_OK;
}
NS_IMETHODIMP
nsChromeRegistry::CanLoadURLRemotely(nsIURI *aURI, bool *aResult)
{
nsresult rv;
*aResult = false;
#ifdef DEBUG
bool isChrome;
aURI->SchemeIs("chrome", &isChrome);
NS_ASSERTION(isChrome, "Non-chrome URI passed to CanLoadURLRemotely!");
#endif
nsCOMPtr<nsIURL> url = do_QueryInterface(aURI);
if (!url) {
NS_ERROR("Chrome URL doesn't implement nsIURL.");
return NS_ERROR_UNEXPECTED;
}
nsAutoCString package;
rv = url->GetHostPort(package);
NS_ENSURE_SUCCESS(rv, rv);
uint32_t flags;
rv = GetFlagsFromPackage(package, &flags);
if (NS_SUCCEEDED(rv)) {
*aResult = !!(flags & REMOTE_ALLOWED);
}
return NS_OK;
}
NS_IMETHODIMP
nsChromeRegistry::MustLoadURLRemotely(nsIURI *aURI, bool *aResult)
{
nsresult rv;
*aResult = false;
#ifdef DEBUG
bool isChrome;
aURI->SchemeIs("chrome", &isChrome);
NS_ASSERTION(isChrome, "Non-chrome URI passed to MustLoadURLRemotely!");
#endif
nsCOMPtr<nsIURL> url = do_QueryInterface(aURI);
if (!url) {
NS_ERROR("Chrome URL doesn't implement nsIURL.");
return NS_ERROR_UNEXPECTED;
}
nsAutoCString package;
rv = url->GetHostPort(package);
NS_ENSURE_SUCCESS(rv, rv);
uint32_t flags;
rv = GetFlagsFromPackage(package, &flags);
if (NS_SUCCEEDED(rv)) {
*aResult = !!(flags & REMOTE_REQUIRED);
}
return NS_OK;
}
NS_IMETHODIMP_(bool)
nsChromeRegistry::WrappersEnabled(nsIURI *aURI)
{

View File

@ -53,6 +53,10 @@ public:
bool* _retval) MOZ_OVERRIDE;
NS_IMETHOD AllowContentToAccess(nsIURI* url,
bool* _retval) MOZ_OVERRIDE;
NS_IMETHOD CanLoadURLRemotely(nsIURI* url,
bool* _retval) MOZ_OVERRIDE;
NS_IMETHOD MustLoadURLRemotely(nsIURI* url,
bool* _retval) MOZ_OVERRIDE;
// nsIChromeRegistry methods:
NS_IMETHOD_(bool) WrappersEnabled(nsIURI *aURI) MOZ_OVERRIDE;
@ -120,26 +124,19 @@ public:
};
virtual void ManifestContent(ManifestProcessingContext& cx, int lineno,
char *const * argv, bool platform,
bool contentaccessible) = 0;
char *const * argv, int flags) = 0;
virtual void ManifestLocale(ManifestProcessingContext& cx, int lineno,
char *const * argv, bool platform,
bool contentaccessible) = 0;
char *const * argv, int flags) = 0;
virtual void ManifestSkin(ManifestProcessingContext& cx, int lineno,
char *const * argv, bool platform,
bool contentaccessible) = 0;
char *const * argv, int flags) = 0;
virtual void ManifestOverlay(ManifestProcessingContext& cx, int lineno,
char *const * argv, bool platform,
bool contentaccessible) = 0;
char *const * argv, int flags) = 0;
virtual void ManifestStyle(ManifestProcessingContext& cx, int lineno,
char *const * argv, bool platform,
bool contentaccessible) = 0;
char *const * argv, int flags) = 0;
virtual void ManifestOverride(ManifestProcessingContext& cx, int lineno,
char *const * argv, bool platform,
bool contentaccessible) = 0;
char *const * argv, int flags) = 0;
virtual void ManifestResource(ManifestProcessingContext& cx, int lineno,
char *const * argv, bool platform,
bool contentaccessible) = 0;
char *const * argv, int flags) = 0;
// Available flags
enum {
@ -153,7 +150,13 @@ public:
XPCNATIVEWRAPPERS = 1 << 1,
// Content script may access files in this package
CONTENT_ACCESSIBLE = 1 << 2
CONTENT_ACCESSIBLE = 1 << 2,
// Package may be loaded remotely
REMOTE_ALLOWED = 1 << 3,
// Package must be loaded remotely
REMOTE_REQUIRED = 1 << 4,
};
bool mInitialized;

View File

@ -772,8 +772,7 @@ SendManifestEntry(const ChromeRegistryItem &aItem)
void
nsChromeRegistryChrome::ManifestContent(ManifestProcessingContext& cx, int lineno,
char *const * argv, bool platform,
bool contentaccessible)
char *const * argv, int flags)
{
char* package = argv[0];
char* uri = argv[1];
@ -797,11 +796,7 @@ nsChromeRegistryChrome::ManifestContent(ManifestProcessingContext& cx, int linen
nsDependentCString packageName(package);
PackageEntry* entry = mPackagesHash.LookupOrAdd(packageName);
entry->baseURI = resolved;
if (platform)
entry->flags |= PLATFORM_PACKAGE;
if (contentaccessible)
entry->flags |= CONTENT_ACCESSIBLE;
entry->flags = flags;
if (mDynamicRegistration) {
ChromePackage chromePackage;
@ -813,8 +808,7 @@ nsChromeRegistryChrome::ManifestContent(ManifestProcessingContext& cx, int linen
void
nsChromeRegistryChrome::ManifestLocale(ManifestProcessingContext& cx, int lineno,
char *const * argv, bool platform,
bool contentaccessible)
char *const * argv, int flags)
{
char* package = argv[0];
char* provider = argv[1];
@ -850,8 +844,7 @@ nsChromeRegistryChrome::ManifestLocale(ManifestProcessingContext& cx, int lineno
void
nsChromeRegistryChrome::ManifestSkin(ManifestProcessingContext& cx, int lineno,
char *const * argv, bool platform,
bool contentaccessible)
char *const * argv, int flags)
{
char* package = argv[0];
char* provider = argv[1];
@ -887,8 +880,7 @@ nsChromeRegistryChrome::ManifestSkin(ManifestProcessingContext& cx, int lineno,
void
nsChromeRegistryChrome::ManifestOverlay(ManifestProcessingContext& cx, int lineno,
char *const * argv, bool platform,
bool contentaccessible)
char *const * argv, int flags)
{
char* base = argv[0];
char* overlay = argv[1];
@ -915,8 +907,7 @@ nsChromeRegistryChrome::ManifestOverlay(ManifestProcessingContext& cx, int linen
void
nsChromeRegistryChrome::ManifestStyle(ManifestProcessingContext& cx, int lineno,
char *const * argv, bool platform,
bool contentaccessible)
char *const * argv, int flags)
{
char* base = argv[0];
char* overlay = argv[1];
@ -943,8 +934,7 @@ nsChromeRegistryChrome::ManifestStyle(ManifestProcessingContext& cx, int lineno,
void
nsChromeRegistryChrome::ManifestOverride(ManifestProcessingContext& cx, int lineno,
char *const * argv, bool platform,
bool contentaccessible)
char *const * argv, int flags)
{
char* chrome = argv[0];
char* resolved = argv[1];
@ -978,8 +968,7 @@ nsChromeRegistryChrome::ManifestOverride(ManifestProcessingContext& cx, int line
void
nsChromeRegistryChrome::ManifestResource(ManifestProcessingContext& cx, int lineno,
char *const * argv, bool platform,
bool contentaccessible)
char *const * argv, int flags)
{
char* package = argv[0];
char* uri = argv[1];

View File

@ -166,26 +166,19 @@ class nsChromeRegistryChrome : public nsChromeRegistry
nsClassHashtable<nsCStringHashKey, PackageEntry> mPackagesHash;
virtual void ManifestContent(ManifestProcessingContext& cx, int lineno,
char *const * argv, bool platform,
bool contentaccessible) MOZ_OVERRIDE;
char *const * argv, int flags) MOZ_OVERRIDE;
virtual void ManifestLocale(ManifestProcessingContext& cx, int lineno,
char *const * argv, bool platform,
bool contentaccessible) MOZ_OVERRIDE;
char *const * argv, int flags) MOZ_OVERRIDE;
virtual void ManifestSkin(ManifestProcessingContext& cx, int lineno,
char *const * argv, bool platform,
bool contentaccessible) MOZ_OVERRIDE;
char *const * argv, int flags) MOZ_OVERRIDE;
virtual void ManifestOverlay(ManifestProcessingContext& cx, int lineno,
char *const * argv, bool platform,
bool contentaccessible) MOZ_OVERRIDE;
char *const * argv, int flags) MOZ_OVERRIDE;
virtual void ManifestStyle(ManifestProcessingContext& cx, int lineno,
char *const * argv, bool platform,
bool contentaccessible) MOZ_OVERRIDE;
char *const * argv, int flags) MOZ_OVERRIDE;
virtual void ManifestOverride(ManifestProcessingContext& cx, int lineno,
char *const * argv, bool platform,
bool contentaccessible) MOZ_OVERRIDE;
char *const * argv, int flags) MOZ_OVERRIDE;
virtual void ManifestResource(ManifestProcessingContext& cx, int lineno,
char *const * argv, bool platform,
bool contentaccessible) MOZ_OVERRIDE;
char *const * argv, int flags) MOZ_OVERRIDE;
};
#endif // nsChromeRegistryChrome_h

View File

@ -22,8 +22,8 @@ nsChromeRegistryContent::RegisterRemoteChrome(
const nsACString& aLocale,
bool aReset)
{
NS_ABORT_IF_FALSE(aReset || mLocale.IsEmpty(),
"RegisterChrome twice?");
MOZ_ASSERT(aReset || mLocale.IsEmpty(),
"RegisterChrome twice?");
if (aReset) {
mPackagesHash.Clear();
@ -257,7 +257,7 @@ nsresult nsChromeRegistryContent::UpdateSelectedLocale()
void
nsChromeRegistryContent::ManifestContent(ManifestProcessingContext& cx,
int lineno, char *const * argv,
bool platform, bool contentaccessible)
int flags)
{
CONTENT_NOTREACHED();
}
@ -265,8 +265,7 @@ nsChromeRegistryContent::ManifestContent(ManifestProcessingContext& cx,
void
nsChromeRegistryContent::ManifestLocale(ManifestProcessingContext& cx,
int lineno,
char *const * argv, bool platform,
bool contentaccessible)
char *const * argv, int flags)
{
CONTENT_NOTREACHED();
}
@ -274,16 +273,14 @@ nsChromeRegistryContent::ManifestLocale(ManifestProcessingContext& cx,
void
nsChromeRegistryContent::ManifestSkin(ManifestProcessingContext& cx,
int lineno,
char *const * argv, bool platform,
bool contentaccessible)
char *const * argv, int flags)
{
CONTENT_NOTREACHED();
}
void
nsChromeRegistryContent::ManifestOverlay(ManifestProcessingContext& cx, int lineno,
char *const * argv, bool platform,
bool contentaccessible)
char *const * argv, int flags)
{
CONTENT_NOTREACHED();
}
@ -291,8 +288,7 @@ nsChromeRegistryContent::ManifestOverlay(ManifestProcessingContext& cx, int line
void
nsChromeRegistryContent::ManifestStyle(ManifestProcessingContext& cx,
int lineno,
char *const * argv, bool platform,
bool contentaccessible)
char *const * argv, int flags)
{
CONTENT_NOTREACHED();
}
@ -300,8 +296,7 @@ nsChromeRegistryContent::ManifestStyle(ManifestProcessingContext& cx,
void
nsChromeRegistryContent::ManifestOverride(ManifestProcessingContext& cx,
int lineno,
char *const * argv, bool platform,
bool contentaccessible)
char *const * argv, int flags)
{
CONTENT_NOTREACHED();
}
@ -309,8 +304,7 @@ nsChromeRegistryContent::ManifestOverride(ManifestProcessingContext& cx,
void
nsChromeRegistryContent::ManifestResource(ManifestProcessingContext& cx,
int lineno,
char *const * argv, bool platform,
bool contentaccessible)
char *const * argv, int flags)
{
CONTENT_NOTREACHED();
}

View File

@ -65,26 +65,19 @@ class nsChromeRegistryContent : public nsChromeRegistry
nsCString mLocale;
virtual void ManifestContent(ManifestProcessingContext& cx, int lineno,
char *const * argv, bool platform,
bool contentaccessible) MOZ_OVERRIDE;
char *const * argv, int flags) MOZ_OVERRIDE;
virtual void ManifestLocale(ManifestProcessingContext& cx, int lineno,
char *const * argv, bool platform,
bool contentaccessible) MOZ_OVERRIDE;
char *const * argv, int flags) MOZ_OVERRIDE;
virtual void ManifestSkin(ManifestProcessingContext& cx, int lineno,
char *const * argv, bool platform,
bool contentaccessible) MOZ_OVERRIDE;
char *const * argv, int flags) MOZ_OVERRIDE;
virtual void ManifestOverlay(ManifestProcessingContext& cx, int lineno,
char *const * argv, bool platform,
bool contentaccessible) MOZ_OVERRIDE;
char *const * argv, int flags) MOZ_OVERRIDE;
virtual void ManifestStyle(ManifestProcessingContext& cx, int lineno,
char *const * argv, bool platform,
bool contentaccessible) MOZ_OVERRIDE;
char *const * argv, int flags) MOZ_OVERRIDE;
virtual void ManifestOverride(ManifestProcessingContext& cx, int lineno,
char *const * argv, bool platform,
bool contentaccessible) MOZ_OVERRIDE;
char *const * argv, int flags) MOZ_OVERRIDE;
virtual void ManifestResource(ManifestProcessingContext& cx, int lineno,
char *const * argv, bool platform,
bool contentaccessible) MOZ_OVERRIDE;
char *const * argv, int flags) MOZ_OVERRIDE;
};
#endif // nsChromeRegistryContent_h

View File

@ -45,7 +45,7 @@ interface nsIChromeRegistry : nsISupports
[notxpcom] boolean wrappersEnabled(in nsIURI aURI);
};
[scriptable, uuid(c2461347-2b8f-48c7-9d59-3a61fb868828)]
[scriptable, uuid(93251ddf-5e85-4172-ac2a-31780562974f)]
interface nsIXULChromeRegistry : nsIChromeRegistry
{
/* Should be called when locales change to reload all chrome (including XUL). */
@ -73,6 +73,20 @@ interface nsIXULChromeRegistry : nsIChromeRegistry
* Do not pass non-chrome URIs to this method.
*/
boolean allowContentToAccess(in nsIURI url);
/**
* Returns true if the passed chrome URL is allowed to be loaded in a remote
* process. This reflects the remoteenabled flag on packages.
* Do not pass non-chrome URIs to this method.
*/
boolean canLoadURLRemotely(in nsIURI url);
/**
* Returns true if the passed chrome URL must be loaded in a remote process.
* This reflects the remoterequired flag on packages.
* Do not pass non-chrome URIs to this method.
*/
boolean mustLoadURLRemotely(in nsIURI url);
};
%{ C++

View File

@ -49,6 +49,7 @@ static RedirEntry kRedirMap[] = {
nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT },
{ "neterror", "chrome://global/content/netError.xhtml",
nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
nsIAboutModule::URI_CAN_LOAD_IN_CHILD |
nsIAboutModule::ALLOW_SCRIPT |
nsIAboutModule::HIDE_FROM_ABOUTABOUT },
{ "memory", "chrome://global/content/aboutMemory.xhtml",

View File

@ -27,7 +27,7 @@ ComputedTimingFunction::Init(const nsTimingFunction &aFunction)
static inline double
StepEnd(uint32_t aSteps, double aPortion)
{
NS_ABORT_IF_FALSE(0.0 <= aPortion && aPortion <= 1.0, "out of range");
MOZ_ASSERT(0.0 <= aPortion && aPortion <= 1.0, "out of range");
uint32_t step = uint32_t(aPortion * aSteps); // floor
return double(step) / double(aSteps);
}
@ -47,7 +47,7 @@ ComputedTimingFunction::GetValue(double aPortion) const
// really meant it.
return 1.0 - StepEnd(mSteps, 1.0 - aPortion);
default:
NS_ABORT_IF_FALSE(false, "bad type");
MOZ_ASSERT(false, "bad type");
// fall through
case nsTimingFunction::StepEnd:
return StepEnd(mSteps, aPortion);

View File

@ -42,7 +42,7 @@ private: //data
NS_IMETHODIMP
ArchiveRequestEvent::Run()
{
NS_ABORT_IF_FALSE(mRequest, "the request is not longer valid");
MOZ_ASSERT(mRequest, "the request is not longer valid");
mRequest->Run();
return NS_OK;
}

View File

@ -48,9 +48,9 @@ Attr::Attr(nsDOMAttributeMap *aAttrMap,
const nsAString &aValue, bool aNsAware)
: nsIAttribute(aAttrMap, aNodeInfo, aNsAware), mValue(aValue)
{
NS_ABORT_IF_FALSE(mNodeInfo, "We must get a nodeinfo here!");
NS_ABORT_IF_FALSE(mNodeInfo->NodeType() == nsIDOMNode::ATTRIBUTE_NODE,
"Wrong nodeType");
MOZ_ASSERT(mNodeInfo, "We must get a nodeinfo here!");
MOZ_ASSERT(mNodeInfo->NodeType() == nsIDOMNode::ATTRIBUTE_NODE,
"Wrong nodeType");
// We don't add a reference to our content. It will tell us
// to drop our reference when it goes away.

View File

@ -19,8 +19,8 @@ class Comment MOZ_FINAL : public nsGenericDOMDataNode,
private:
void Init()
{
NS_ABORT_IF_FALSE(mNodeInfo->NodeType() == nsIDOMNode::COMMENT_NODE,
"Bad NodeType in aNodeInfo");
MOZ_ASSERT(mNodeInfo->NodeType() == nsIDOMNode::COMMENT_NODE,
"Bad NodeType in aNodeInfo");
}
virtual ~Comment();

View File

@ -56,7 +56,7 @@ Crypto::GetRandomValues(JSContext* aCx, const ArrayBufferView& aArray,
JS::MutableHandle<JSObject*> aRetval,
ErrorResult& aRv)
{
NS_ABORT_IF_FALSE(NS_IsMainThread(), "Called on the wrong thread");
MOZ_ASSERT(NS_IsMainThread(), "Called on the wrong thread");
JS::Rooted<JSObject*> view(aCx, aArray.Obj());

View File

@ -27,11 +27,10 @@ class DocumentFragment : public FragmentOrElement,
private:
void Init()
{
NS_ABORT_IF_FALSE(mNodeInfo->NodeType() ==
nsIDOMNode::DOCUMENT_FRAGMENT_NODE &&
mNodeInfo->Equals(nsGkAtoms::documentFragmentNodeName,
kNameSpaceID_None),
"Bad NodeType in aNodeInfo");
MOZ_ASSERT(mNodeInfo->NodeType() == nsIDOMNode::DOCUMENT_FRAGMENT_NODE &&
mNodeInfo->Equals(nsGkAtoms::documentFragmentNodeName,
kNameSpaceID_None),
"Bad NodeType in aNodeInfo");
}
public:

View File

@ -74,8 +74,8 @@ DocumentType::DocumentType(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo,
mSystemId(aSystemId),
mInternalSubset(aInternalSubset)
{
NS_ABORT_IF_FALSE(mNodeInfo->NodeType() == nsIDOMNode::DOCUMENT_TYPE_NODE,
"Bad NodeType in aNodeInfo");
MOZ_ASSERT(mNodeInfo->NodeType() == nsIDOMNode::DOCUMENT_TYPE_NODE,
"Bad NodeType in aNodeInfo");
}
DocumentType::~DocumentType()

View File

@ -204,9 +204,9 @@ Element::NotifyStateChange(EventStates aStates)
void
Element::UpdateLinkState(EventStates aState)
{
NS_ABORT_IF_FALSE(!aState.HasAtLeastOneOfStates(~(NS_EVENT_STATE_VISITED |
NS_EVENT_STATE_UNVISITED)),
"Unexpected link state bits");
MOZ_ASSERT(!aState.HasAtLeastOneOfStates(~(NS_EVENT_STATE_VISITED |
NS_EVENT_STATE_UNVISITED)),
"Unexpected link state bits");
mState =
(mState & ~(NS_EVENT_STATE_VISITED | NS_EVENT_STATE_UNVISITED)) |
aState;

View File

@ -152,8 +152,8 @@ public:
FragmentOrElement(aNodeInfo),
mState(NS_EVENT_STATE_MOZ_READONLY)
{
NS_ABORT_IF_FALSE(mNodeInfo->NodeType() == nsIDOMNode::ELEMENT_NODE,
"Bad NodeType in aNodeInfo");
MOZ_ASSERT(mNodeInfo->NodeType() == nsIDOMNode::ELEMENT_NODE,
"Bad NodeType in aNodeInfo");
SetIsElement();
}
#endif // MOZILLA_INTERNAL_API

View File

@ -580,9 +580,9 @@ EventSource::AsyncOnChannelRedirect(nsIChannel *aOldChannel,
nsresult
EventSource::OnRedirectVerifyCallback(nsresult aResult)
{
NS_ABORT_IF_FALSE(mRedirectCallback, "mRedirectCallback not set in callback");
NS_ABORT_IF_FALSE(mNewRedirectChannel,
"mNewRedirectChannel not set in callback");
MOZ_ASSERT(mRedirectCallback, "mRedirectCallback not set in callback");
MOZ_ASSERT(mNewRedirectChannel,
"mNewRedirectChannel not set in callback");
NS_ENSURE_SUCCESS(aResult, aResult);

Some files were not shown because too many files have changed in this diff Show More