mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge m-c to inbound. a=merge
This commit is contained in:
commit
80ba0ac842
6
CLOBBER
6
CLOBBER
@ -22,4 +22,8 @@
|
||||
# changes to stick? As of bug 928195, this shouldn't be necessary! Please
|
||||
# don't change CLOBBER for WebIDL changes any more.
|
||||
|
||||
Bug 1153796: Merge Bluetooth backend interfaces
|
||||
Bug 1154235: Merge BluetoothUtils.{cpp,h} variants into single file
|
||||
|
||||
This patch set renames and removes source files. This requires updating
|
||||
the build system's dependency information from scratch. The issue has
|
||||
been reported in bug 1154232.
|
||||
|
@ -15,7 +15,7 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="ef937d1aca7c4cf89ecb5cc43ae8c21c2000a9db">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="29fde3db031b910f1c9d1a35a3aab022872de205"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="3cd0a9facce26c2acc7be3755a17131a6358e33f"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f2f2f0cbee2f2517070dd194051d509c07cdacff"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
@ -19,7 +19,7 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="29fde3db031b910f1c9d1a35a3aab022872de205"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="3cd0a9facce26c2acc7be3755a17131a6358e33f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f2f2f0cbee2f2517070dd194051d509c07cdacff"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="93f9ba577f68d772093987c2f1c0a4ae293e1802"/>
|
||||
|
@ -17,7 +17,7 @@
|
||||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="29fde3db031b910f1c9d1a35a3aab022872de205"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="3cd0a9facce26c2acc7be3755a17131a6358e33f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f2f2f0cbee2f2517070dd194051d509c07cdacff"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="8a1ba73572c713e298ae53821d000fc3a5087b5f"/>
|
||||
|
@ -15,7 +15,7 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="ef937d1aca7c4cf89ecb5cc43ae8c21c2000a9db">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="29fde3db031b910f1c9d1a35a3aab022872de205"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="3cd0a9facce26c2acc7be3755a17131a6358e33f"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f2f2f0cbee2f2517070dd194051d509c07cdacff"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
@ -15,7 +15,7 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="6b0721ca0e92788df30daf8f7a5fb2863544f9c8">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="29fde3db031b910f1c9d1a35a3aab022872de205"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="3cd0a9facce26c2acc7be3755a17131a6358e33f"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f2f2f0cbee2f2517070dd194051d509c07cdacff"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
@ -19,7 +19,7 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="29fde3db031b910f1c9d1a35a3aab022872de205"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="3cd0a9facce26c2acc7be3755a17131a6358e33f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f2f2f0cbee2f2517070dd194051d509c07cdacff"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="93f9ba577f68d772093987c2f1c0a4ae293e1802"/>
|
||||
|
@ -15,7 +15,7 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="ef937d1aca7c4cf89ecb5cc43ae8c21c2000a9db">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="29fde3db031b910f1c9d1a35a3aab022872de205"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="3cd0a9facce26c2acc7be3755a17131a6358e33f"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f2f2f0cbee2f2517070dd194051d509c07cdacff"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
@ -17,7 +17,7 @@
|
||||
</project>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="29fde3db031b910f1c9d1a35a3aab022872de205"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="3cd0a9facce26c2acc7be3755a17131a6358e33f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f2f2f0cbee2f2517070dd194051d509c07cdacff"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="8a1ba73572c713e298ae53821d000fc3a5087b5f"/>
|
||||
|
@ -1,9 +1,9 @@
|
||||
{
|
||||
"git": {
|
||||
"git_revision": "29fde3db031b910f1c9d1a35a3aab022872de205",
|
||||
"git_revision": "3cd0a9facce26c2acc7be3755a17131a6358e33f",
|
||||
"remote": "https://git.mozilla.org/releases/gaia.git",
|
||||
"branch": ""
|
||||
},
|
||||
"revision": "2511908f59de62fbba1461a6dd0b23c16ba0be63",
|
||||
"revision": "c5c31cccfb22048626664d063643ae1fb1e2facc",
|
||||
"repo_path": "integration/gaia-central"
|
||||
}
|
||||
|
@ -17,7 +17,7 @@
|
||||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="29fde3db031b910f1c9d1a35a3aab022872de205"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="3cd0a9facce26c2acc7be3755a17131a6358e33f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f2f2f0cbee2f2517070dd194051d509c07cdacff"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="8a1ba73572c713e298ae53821d000fc3a5087b5f"/>
|
||||
|
@ -15,7 +15,7 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="6b0721ca0e92788df30daf8f7a5fb2863544f9c8">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="29fde3db031b910f1c9d1a35a3aab022872de205"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="3cd0a9facce26c2acc7be3755a17131a6358e33f"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f2f2f0cbee2f2517070dd194051d509c07cdacff"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
@ -251,6 +251,8 @@ pref("browser.uitour.loglevel", "Error");
|
||||
pref("browser.uitour.requireSecure", true);
|
||||
pref("browser.uitour.themeOrigin", "https://addons.mozilla.org/%LOCALE%/firefox/themes/");
|
||||
pref("browser.uitour.url", "https://www.mozilla.org/%LOCALE%/firefox/%VERSION%/tour/");
|
||||
// This is used as a regexp match against the page's URL.
|
||||
pref("browser.uitour.readerViewTrigger", "^https:\/\/www\.mozilla\.org\/[^\/]+\/firefox\/reading\/start");
|
||||
|
||||
pref("browser.customizemode.tip0.shown", false);
|
||||
pref("browser.customizemode.tip0.learnMoreUrl", "https://support.mozilla.org/1/firefox/%VERSION%/%OS%/%LOCALE%/customize");
|
||||
|
@ -4203,6 +4203,7 @@ var XULBrowserWindow = {
|
||||
|
||||
BookmarkingUI.onLocationChange();
|
||||
SocialUI.updateState(location);
|
||||
UITour.onLocationChange(location);
|
||||
}
|
||||
|
||||
// Utility functions for disabling find
|
||||
|
@ -560,7 +560,7 @@ loop.conversationViews = (function(mozL10n) {
|
||||
React.createElement("button", {className: emailClasses,
|
||||
onClick: this.emailLink,
|
||||
disabled: this.state.emailLinkButtonDisabled},
|
||||
mozL10n.get("share_button2")
|
||||
mozL10n.get("share_button3")
|
||||
)
|
||||
)
|
||||
)
|
||||
|
@ -560,7 +560,7 @@ loop.conversationViews = (function(mozL10n) {
|
||||
<button className={emailClasses}
|
||||
onClick={this.emailLink}
|
||||
disabled={this.state.emailLinkButtonDisabled}>
|
||||
{mozL10n.get("share_button2")}
|
||||
{mozL10n.get("share_button3")}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1103,6 +1103,12 @@ body[dir=rtl] .share-service-dropdown .share-panel-header {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
right: 0px;
|
||||
|
||||
/* Override the 100% specified in the .standalone-room-info selector
|
||||
block so that this div doesn't take over the _whole_ screen and
|
||||
transparently occlude UI widgetry (like the Join button), making
|
||||
it unusable. */
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.standalone-context-url {
|
||||
|
@ -200,6 +200,7 @@ loop.shared.actions = (function() {
|
||||
* dispatched when a stream connects for the first time.
|
||||
*/
|
||||
VideoDimensionsChanged: Action.define("videoDimensionsChanged", {
|
||||
isLocal: Boolean,
|
||||
videoType: String,
|
||||
dimensions: Object
|
||||
}),
|
||||
|
@ -85,15 +85,17 @@ let CtypesHelpers = {
|
||||
},
|
||||
|
||||
/**
|
||||
* Converts a FILETIME struct (2 DWORDS), to a SYSTEMTIME struct.
|
||||
* Converts a FILETIME struct (2 DWORDS), to a SYSTEMTIME struct,
|
||||
* and then deduces the number of seconds since the epoch (which
|
||||
* is the data we want for the cookie expiry date).
|
||||
*
|
||||
* @param aTimeHi
|
||||
* Least significant DWORD.
|
||||
* @param aTimeLo
|
||||
* Most significant DWORD.
|
||||
* @return a Date object representing the converted datetime.
|
||||
* @return the number of seconds since the epoch
|
||||
*/
|
||||
fileTimeToDate: function CH_fileTimeToDate(aTimeHi, aTimeLo) {
|
||||
fileTimeToSecondsSinceEpoch(aTimeHi, aTimeLo) {
|
||||
let fileTime = this._structs.FILETIME();
|
||||
fileTime.dwLowDateTime = aTimeLo;
|
||||
fileTime.dwHighDateTime = aTimeHi;
|
||||
@ -103,13 +105,15 @@ let CtypesHelpers = {
|
||||
if (result == 0)
|
||||
throw new Error(ctypes.winLastError);
|
||||
|
||||
return new Date(systemTime.wYear,
|
||||
systemTime.wMonth - 1,
|
||||
systemTime.wDay,
|
||||
systemTime.wHour,
|
||||
systemTime.wMinute,
|
||||
systemTime.wSecond,
|
||||
systemTime.wMilliseconds);
|
||||
// System time is in UTC, so we use Date.UTC to get milliseconds from epoch,
|
||||
// then divide by 1000 to get seconds, and round down:
|
||||
return Math.floor(Date.UTC(systemTime.wYear,
|
||||
systemTime.wMonth - 1,
|
||||
systemTime.wDay,
|
||||
systemTime.wHour,
|
||||
systemTime.wMinute,
|
||||
systemTime.wSecond,
|
||||
systemTime.wMilliseconds) / 1000);
|
||||
}
|
||||
};
|
||||
|
||||
@ -458,8 +462,8 @@ Cookies.prototype = {
|
||||
host = "." + host;
|
||||
}
|
||||
|
||||
let expireTime = CtypesHelpers.fileTimeToDate(Number(expireTimeHi),
|
||||
Number(expireTimeLo));
|
||||
let expireTime = CtypesHelpers.fileTimeToSecondsSinceEpoch(Number(expireTimeHi),
|
||||
Number(expireTimeLo));
|
||||
Services.cookies.add(host,
|
||||
path,
|
||||
name,
|
||||
|
@ -1,11 +1,6 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
const { classes: Cc, interfaces: Ci, results: Cr, utils: Cu } = Components;
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cu = Components.utils;
|
||||
const Cr = Components.results;
|
||||
Cu.importGlobalProperties([ "URL" ]);
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
@ -16,49 +11,27 @@ XPCOMUtils.defineLazyModuleGetter(this, "FileUtils",
|
||||
"resource://gre/modules/FileUtils.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "MigrationUtils",
|
||||
"resource:///modules/MigrationUtils.jsm");
|
||||
|
||||
// Initialize profile.
|
||||
let gProfD = do_get_profile();
|
||||
|
||||
// Create a fake XULAppInfo to satisfy the eventual needs of the migrators.
|
||||
let XULAppInfo = {
|
||||
// nsIXUlAppInfo
|
||||
get vendor() "Mozilla",
|
||||
get name() "XPCShell",
|
||||
get ID() "xpcshell@tests.mozilla.org",
|
||||
get version() "1",
|
||||
get appBuildID() "2007010101",
|
||||
get platformVersion() "1.0",
|
||||
get platformBuildID() "2007010101",
|
||||
Cu.import("resource://testing-common/AppInfo.jsm");
|
||||
updateAppInfo();
|
||||
|
||||
// nsIXUlRuntime (partial)
|
||||
get inSafeMode() false,
|
||||
logConsoleErrors: true,
|
||||
get OS() "XPCShell",
|
||||
get XPCOMABI() "noarch-spidermonkey",
|
||||
invalidateCachesOnRestart: function () {},
|
||||
/**
|
||||
* Migrates the requested resource and waits for the migration to be complete.
|
||||
*/
|
||||
function promiseMigration(migrator, resourceType) {
|
||||
// Ensure resource migration is available.
|
||||
let availableSources = migrator.getMigrateData(null, false);
|
||||
Assert.ok((availableSources & resourceType) > 0);
|
||||
|
||||
// nsIWinAppHelper
|
||||
get userCanElevate() false,
|
||||
return new Promise (resolve => {
|
||||
Services.obs.addObserver(function onMigrationEnded() {
|
||||
Services.obs.removeObserver(onMigrationEnded, "Migration:Ended");
|
||||
resolve();
|
||||
}, "Migration:Ended", false);
|
||||
|
||||
QueryInterface: function (aIID) {
|
||||
let interfaces = [Ci.nsIXULAppInfo, Ci.nsIXULRuntime];
|
||||
if ("nsIWinAppHelper" in Ci)
|
||||
interfaces.push(Ci.nsIWinAppHelper);
|
||||
if (!interfaces.some(function (v) aIID.equals(v)))
|
||||
throw Cr.NS_ERROR_NO_INTERFACE;
|
||||
return this;
|
||||
}
|
||||
};
|
||||
|
||||
const CONTRACT_ID = "@mozilla.org/xre/app-info;1";
|
||||
const CID = Components.ID("7685dac8-3637-4660-a544-928c5ec0e714}");
|
||||
|
||||
let registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar);
|
||||
registrar.registerFactory(CID, "XULAppInfo", CONTRACT_ID, {
|
||||
createInstance: function (aOuter, aIID) {
|
||||
if (aOuter != null)
|
||||
throw Cr.NS_ERROR_NO_AGGREGATION;
|
||||
return XULAppInfo.QueryInterface(aIID);
|
||||
},
|
||||
QueryInterface: XPCOMUtils.generateQI(Ci.nsIFactory)
|
||||
});
|
||||
migrator.migrate(resourceType, null, null);
|
||||
});
|
||||
}
|
||||
|
@ -1,18 +1,7 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
function run_test() {
|
||||
do_test_pending();
|
||||
|
||||
add_task(function* () {
|
||||
let migrator = MigrationUtils.getMigrator("ie");
|
||||
|
||||
// Sanity check for the source.
|
||||
do_check_true(migrator.sourceExists);
|
||||
|
||||
// Ensure bookmarks migration is available.
|
||||
let availableSources = migrator.getMigrateData(null, false);
|
||||
do_check_true((availableSources & MigrationUtils.resourceTypes.BOOKMARKS) > 0);
|
||||
Assert.ok(migrator.sourceExists);
|
||||
|
||||
// Wait for the imported bookmarks. Check that "From Internet Explorer"
|
||||
// folders are created in the menu and on the toolbar.
|
||||
@ -23,34 +12,25 @@ function run_test() {
|
||||
PlacesUtils.toolbarFolderId ];
|
||||
|
||||
PlacesUtils.bookmarks.addObserver({
|
||||
onItemAdded: function onItemAdded(aItemId, aParentId, aIndex, aItemType,
|
||||
aURI, aTitle) {
|
||||
onItemAdded(aItemId, aParentId, aIndex, aItemType, aURI, aTitle) {
|
||||
if (aTitle == label) {
|
||||
let index = expectedParents.indexOf(aParentId);
|
||||
do_check_neq(index, -1);
|
||||
Assert.notEqual(index, -1);
|
||||
expectedParents.splice(index, 1);
|
||||
if (expectedParents.length == 0)
|
||||
PlacesUtils.bookmarks.removeObserver(this);
|
||||
}
|
||||
},
|
||||
onBeginUpdateBatch: function () {},
|
||||
onEndUpdateBatch: function () {},
|
||||
onItemRemoved: function () {},
|
||||
onItemChanged: function () {},
|
||||
onItemVisited: function () {},
|
||||
onItemMoved: function () {},
|
||||
onBeginUpdateBatch() {},
|
||||
onEndUpdateBatch() {},
|
||||
onItemRemoved() {},
|
||||
onItemChanged() {},
|
||||
onItemVisited() {},
|
||||
onItemMoved() {},
|
||||
}, false);
|
||||
|
||||
// Wait for migration.
|
||||
Services.obs.addObserver(function onMigrationEnded() {
|
||||
Services.obs.removeObserver(onMigrationEnded, "Migration:Ended");
|
||||
yield promiseMigration(migrator, MigrationUtils.resourceTypes.BOOKMARKS);
|
||||
|
||||
// Check the bookmarks have been imported to all the expected parents.
|
||||
do_check_eq(expectedParents.length, 0);
|
||||
|
||||
do_test_finished();
|
||||
}, "Migration:Ended", false);
|
||||
|
||||
migrator.migrate(MigrationUtils.resourceTypes.BOOKMARKS, null,
|
||||
null);
|
||||
}
|
||||
// Check the bookmarks have been imported to all the expected parents.
|
||||
Assert.equal(expectedParents.length, 0);
|
||||
});
|
||||
|
67
browser/components/migration/tests/unit/test_IE_cookies.js
Normal file
67
browser/components/migration/tests/unit/test_IE_cookies.js
Normal file
@ -0,0 +1,67 @@
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "ctypes",
|
||||
"resource://gre/modules/ctypes.jsm");
|
||||
|
||||
add_task(function* () {
|
||||
let migrator = MigrationUtils.getMigrator("ie");
|
||||
// Sanity check for the source.
|
||||
Assert.ok(migrator.sourceExists);
|
||||
|
||||
const BOOL = ctypes.bool;
|
||||
const LPCTSTR = ctypes.char16_t.ptr;
|
||||
|
||||
let wininet = ctypes.open("Wininet");
|
||||
do_register_cleanup(() => {
|
||||
try {
|
||||
wininet.close();
|
||||
} catch (ex) {}
|
||||
});
|
||||
|
||||
/*
|
||||
BOOL InternetSetCookie(
|
||||
_In_ LPCTSTR lpszUrl,
|
||||
_In_ LPCTSTR lpszCookieName,
|
||||
_In_ LPCTSTR lpszCookieData
|
||||
);
|
||||
*/
|
||||
let setIECookie = wininet.declare("InternetSetCookieW",
|
||||
ctypes.default_abi,
|
||||
BOOL,
|
||||
LPCTSTR,
|
||||
LPCTSTR,
|
||||
LPCTSTR);
|
||||
|
||||
let expiry = new Date();
|
||||
expiry.setDate(expiry.getDate() + 7);
|
||||
const COOKIE = {
|
||||
host: "mycookietest.com",
|
||||
name: "testcookie",
|
||||
value: "testvalue",
|
||||
expiry
|
||||
};
|
||||
|
||||
// Sanity check.
|
||||
Assert.equal(Services.cookies.countCookiesFromHost(COOKIE.host), 0,
|
||||
"There are no cookies initially");
|
||||
|
||||
// Create the persistent cookie in IE.
|
||||
let value = COOKIE.name + " = " + COOKIE.value +"; expires = " +
|
||||
COOKIE.expiry.toUTCString();
|
||||
let rv = setIECookie(new URL("http://" + COOKIE.host).href, null, value);
|
||||
Assert.ok(rv, "Added a persistent IE cookie");
|
||||
|
||||
// Migrate cookies.
|
||||
yield promiseMigration(migrator, MigrationUtils.resourceTypes.COOKIES);
|
||||
|
||||
Assert.equal(Services.cookies.countCookiesFromHost(COOKIE.host), 1,
|
||||
"Migrated the expected number of cookies");
|
||||
|
||||
// Now check the cookie details.
|
||||
let enumerator = Services.cookies.getCookiesFromHost(COOKIE.host);
|
||||
Assert.ok(enumerator.hasMoreElements());
|
||||
let foundCookie = enumerator.getNext().QueryInterface(Ci.nsICookie2);
|
||||
|
||||
Assert.equal(foundCookie.name, COOKIE.name);
|
||||
Assert.equal(foundCookie.value, COOKIE.value);
|
||||
Assert.equal(foundCookie.host, "." + COOKIE.host);
|
||||
Assert.equal(foundCookie.expiry, Math.floor(COOKIE.expiry / 1000));
|
||||
});
|
@ -4,7 +4,8 @@ tail =
|
||||
firefox-appdir = browser
|
||||
skip-if = toolkit == 'android' || toolkit == 'gonk'
|
||||
|
||||
[test_fx_fhr.js]
|
||||
[test_IE_bookmarks.js]
|
||||
skip-if = os != "win"
|
||||
|
||||
[test_fx_fhr.js]
|
||||
[test_IE_cookies.js]
|
||||
skip-if = os != "win"
|
||||
|
@ -137,7 +137,6 @@ this.PlacesUIUtils = {
|
||||
get _copyableAnnotations() [
|
||||
this.DESCRIPTION_ANNO,
|
||||
this.LOAD_IN_SIDEBAR_ANNO,
|
||||
PlacesUtils.POST_DATA_ANNO,
|
||||
PlacesUtils.READ_ONLY_ANNO,
|
||||
],
|
||||
|
||||
@ -172,7 +171,6 @@ this.PlacesUIUtils = {
|
||||
);
|
||||
}
|
||||
|
||||
let keyword = aData.keyword || null;
|
||||
let annos = [];
|
||||
if (aData.annos) {
|
||||
annos = aData.annos.filter(function (aAnno) {
|
||||
@ -180,9 +178,10 @@ this.PlacesUIUtils = {
|
||||
}, this);
|
||||
}
|
||||
|
||||
// There's no need to copy the keyword since it's bound to the bookmark url.
|
||||
return new PlacesCreateBookmarkTransaction(PlacesUtils._uri(aData.uri),
|
||||
aContainer, aIndex, aData.title,
|
||||
keyword, annos, transactions);
|
||||
null, annos, transactions);
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -167,7 +167,8 @@
|
||||
accesskey="&editBookmarkOverlay.description.accesskey;"
|
||||
control="editBMPanel_descriptionField"/>
|
||||
<textbox id="editBMPanel_descriptionField"
|
||||
multiline="true"/>
|
||||
multiline="true"
|
||||
rows="4"/>
|
||||
</row>
|
||||
</rows>
|
||||
</grid>
|
||||
|
@ -3,7 +3,10 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Components.utils.import("resource://gre/modules/PlacesUtils.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
|
||||
"resource://gre/modules/PlacesUtils.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Task",
|
||||
"resource://gre/modules/Task.jsm");
|
||||
|
||||
const ENGINE_FLAVOR = "text/x-moz-search-engine";
|
||||
|
||||
@ -191,19 +194,13 @@ var gSearchPane = {
|
||||
document.getElementById("engineList").focus();
|
||||
},
|
||||
|
||||
editKeyword: function(aEngine, aNewKeyword) {
|
||||
editKeyword: Task.async(function* (aEngine, aNewKeyword) {
|
||||
if (aNewKeyword) {
|
||||
let bduplicate = false;
|
||||
let eduplicate = false;
|
||||
let dupName = "";
|
||||
|
||||
try {
|
||||
let bmserv =
|
||||
Components.classes["@mozilla.org/browser/nav-bookmarks-service;1"]
|
||||
.getService(Components.interfaces.nsINavBookmarksService);
|
||||
if (bmserv.getURIForKeyword(aNewKeyword))
|
||||
bduplicate = true;
|
||||
} catch(ex) {}
|
||||
// Check for duplicates in Places keywords.
|
||||
let bduplicate = !!(yield PlacesUtils.keywords.fetch(aNewKeyword));
|
||||
|
||||
// Check for duplicates in changes we haven't committed yet
|
||||
let engines = gEngineView._engineStore.engines;
|
||||
@ -231,7 +228,7 @@ var gSearchPane = {
|
||||
gEngineView._engineStore.changeEngine(aEngine, "alias", aNewKeyword);
|
||||
gEngineView.invalidate();
|
||||
return true;
|
||||
},
|
||||
}),
|
||||
|
||||
saveOneClickEnginesList: function () {
|
||||
let hiddenList = [];
|
||||
@ -519,11 +516,11 @@ EngineView.prototype = {
|
||||
},
|
||||
setCellText: function(index, column, value) {
|
||||
if (column.id == "engineKeyword") {
|
||||
if (!gSearchPane.editKeyword(this._engineStore.engines[index], value)) {
|
||||
setTimeout(() => {
|
||||
gSearchPane.editKeyword(this._engineStore.engines[index], value)
|
||||
.then(valid => {
|
||||
if (!valid)
|
||||
document.getElementById("engineList").startEditing(index, column);
|
||||
}, 0);
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
performAction: function(action) { },
|
||||
|
@ -3,7 +3,10 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Components.utils.import("resource://gre/modules/PlacesUtils.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
|
||||
"resource://gre/modules/PlacesUtils.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Task",
|
||||
"resource://gre/modules/Task.jsm");
|
||||
|
||||
const ENGINE_FLAVOR = "text/x-moz-search-engine";
|
||||
|
||||
@ -123,19 +126,13 @@ var gSearchPane = {
|
||||
document.getElementById("engineList").focus();
|
||||
},
|
||||
|
||||
editKeyword: function(aEngine, aNewKeyword) {
|
||||
editKeyword: Task.async(function* (aEngine, aNewKeyword) {
|
||||
if (aNewKeyword) {
|
||||
let bduplicate = false;
|
||||
let eduplicate = false;
|
||||
let dupName = "";
|
||||
|
||||
try {
|
||||
let bmserv =
|
||||
Components.classes["@mozilla.org/browser/nav-bookmarks-service;1"]
|
||||
.getService(Components.interfaces.nsINavBookmarksService);
|
||||
if (bmserv.getURIForKeyword(aNewKeyword))
|
||||
bduplicate = true;
|
||||
} catch(ex) {}
|
||||
// Check for duplicates in Places keywords.
|
||||
let bduplicate = !!(yield PlacesUtils.keywords.fetch(aNewKeyword));
|
||||
|
||||
// Check for duplicates in changes we haven't committed yet
|
||||
let engines = gEngineView._engineStore.engines;
|
||||
@ -163,7 +160,7 @@ var gSearchPane = {
|
||||
gEngineView._engineStore.changeEngine(aEngine, "alias", aNewKeyword);
|
||||
gEngineView.invalidate();
|
||||
return true;
|
||||
},
|
||||
}),
|
||||
|
||||
saveOneClickEnginesList: function () {
|
||||
let hiddenList = [];
|
||||
@ -534,11 +531,11 @@ EngineView.prototype = {
|
||||
},
|
||||
setCellText: function(index, column, value) {
|
||||
if (column.id == "engineKeyword") {
|
||||
if (!gSearchPane.editKeyword(this._engineStore.engines[index], value)) {
|
||||
setTimeout(() => {
|
||||
gSearchPane.editKeyword(this._engineStore.engines[index], value)
|
||||
.then(valid => {
|
||||
if (!valid)
|
||||
document.getElementById("engineList").startEditing(index, column);
|
||||
}, 0);
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
performAction: function(action) { },
|
||||
|
@ -57,7 +57,9 @@ let RLSidebar = {
|
||||
this.emptyListInfo = document.getElementById("emptyListInfo");
|
||||
this.itemTemplate = document.getElementById("item-template");
|
||||
|
||||
this.list.addEventListener("click", event => this.onListClick(event));
|
||||
// click events for middle-clicks are not sent to DOM nodes, only to the document.
|
||||
document.addEventListener("click", event => this.onClick(event));
|
||||
|
||||
this.list.addEventListener("mousemove", event => this.onListMouseMove(event));
|
||||
this.list.addEventListener("keydown", event => this.onListKeyDown(event), true);
|
||||
|
||||
@ -384,10 +386,10 @@ let RLSidebar = {
|
||||
},
|
||||
|
||||
/**
|
||||
* Handle a click event on the list box.
|
||||
* Handle a click event on the sidebar.
|
||||
* @param {Event} event - Triggering event.
|
||||
*/
|
||||
onListClick(event) {
|
||||
onClick(event) {
|
||||
let itemNode = this.findParentItemNode(event.target);
|
||||
if (!itemNode)
|
||||
return;
|
||||
|
@ -2,7 +2,12 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
|
||||
"resource://gre/modules/PlacesUtils.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Task",
|
||||
"resource://gre/modules/Task.jsm");
|
||||
|
||||
const Ci = Components.interfaces;
|
||||
const Cc = Components.classes;
|
||||
@ -105,7 +110,7 @@ var gEngineManagerDialog = {
|
||||
document.getElementById("engineList").focus();
|
||||
},
|
||||
|
||||
editKeyword: function engineManager_editKeyword() {
|
||||
editKeyword: Task.async(function* () {
|
||||
var selectedEngine = gEngineView.selectedEngine;
|
||||
if (!selectedEngine)
|
||||
return;
|
||||
@ -121,12 +126,8 @@ var gEngineManagerDialog = {
|
||||
var dupName = "";
|
||||
|
||||
if (alias.value != "") {
|
||||
try {
|
||||
let bmserv = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
|
||||
getService(Ci.nsINavBookmarksService);
|
||||
if (bmserv.getURIForKeyword(alias.value))
|
||||
bduplicate = true;
|
||||
} catch(ex) {}
|
||||
// Check for duplicates in Places keywords.
|
||||
bduplicate = !!(yield PlacesUtils.keywords.fetch(alias.value));
|
||||
|
||||
// Check for duplicates in changes we haven't committed yet
|
||||
let engines = gEngineView._engineStore.engines;
|
||||
@ -154,7 +155,7 @@ var gEngineManagerDialog = {
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
}),
|
||||
|
||||
onSelect: function engineManager_onSelect() {
|
||||
// Buttons only work if an engine is selected and it's not the last engine,
|
||||
|
@ -36,7 +36,7 @@
|
||||
oncommand="gEngineManagerDialog.bump(-1);"
|
||||
disabled="true"/>
|
||||
<command id="cmd_editkeyword"
|
||||
oncommand="gEngineManagerDialog.editKeyword();"
|
||||
oncommand="gEngineManagerDialog.editKeyword().catch(Components.utils.reportError);"
|
||||
disabled="true"/>
|
||||
</commandset>
|
||||
|
||||
|
@ -285,9 +285,13 @@ if (typeof Mozilla == 'undefined') {
|
||||
_sendEvent('forceShowReaderIcon');
|
||||
};
|
||||
|
||||
Mozilla.UITour.toggleReaderMode = function(feature) {
|
||||
_sendEvent('toggleReaderMode');
|
||||
};
|
||||
|
||||
})();
|
||||
|
||||
// Make this library Require-able.
|
||||
if (typeof module !== 'undefined' && module.exports) {
|
||||
module.exports = Mozilla.UITour;
|
||||
module.exports = Mozilla.UITour;
|
||||
}
|
||||
|
@ -27,12 +27,15 @@ XPCOMUtils.defineLazyModuleGetter(this, "BrowserUITelemetry",
|
||||
"resource:///modules/BrowserUITelemetry.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Metrics",
|
||||
"resource://gre/modules/Metrics.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "ReaderMode",
|
||||
"resource://gre/modules/ReaderMode.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "ReaderParent",
|
||||
"resource:///modules/ReaderParent.jsm");
|
||||
|
||||
// See LOG_LEVELS in Console.jsm. Common examples: "All", "Info", "Warn", & "Error".
|
||||
const PREF_LOG_LEVEL = "browser.uitour.loglevel";
|
||||
const PREF_SEENPAGEIDS = "browser.uitour.seenPageIDs";
|
||||
const PREF_READERVIEW_TRIGGER = "browser.uitour.readerViewTrigger";
|
||||
|
||||
const BACKGROUND_PAGE_ACTIONS_ALLOWED = new Set([
|
||||
"endUrlbarCapture",
|
||||
@ -190,6 +193,7 @@ this.UITour = {
|
||||
}],
|
||||
["privateWindow", {query: "#privatebrowsing-button"}],
|
||||
["quit", {query: "#PanelUI-quit"}],
|
||||
["readerMode-urlBar", {query: "#reader-mode-button"}],
|
||||
["search", {
|
||||
infoPanelOffsetX: 18,
|
||||
infoPanelPosition: "after_start",
|
||||
@ -344,6 +348,22 @@ this.UITour = {
|
||||
JSON.stringify([...this.seenPageIDs]));
|
||||
},
|
||||
|
||||
get _readerViewTriggerRegEx() {
|
||||
delete this._readerViewTriggerRegEx;
|
||||
let readerViewUITourTrigger = Services.prefs.getCharPref(PREF_READERVIEW_TRIGGER);
|
||||
return this._readerViewTriggerRegEx = new RegExp(readerViewUITourTrigger, "i");
|
||||
},
|
||||
|
||||
onLocationChange: function(aLocation) {
|
||||
// The ReadingList/ReaderView tour page is expected to run in Reader View,
|
||||
// which disables JavaScript on the page. To get around that, we
|
||||
// automatically start a pre-defined tour on page load.
|
||||
let originalUrl = ReaderMode.getOriginalUrl(aLocation);
|
||||
if (this._readerViewTriggerRegEx.test(originalUrl)) {
|
||||
this.startSubTour("readinglist");
|
||||
}
|
||||
},
|
||||
|
||||
onPageEvent: function(aMessage, aEvent) {
|
||||
let browser = aMessage.target;
|
||||
let window = browser.ownerDocument.defaultView;
|
||||
@ -685,6 +705,13 @@ this.UITour = {
|
||||
ReaderParent.forceShowReaderIcon(browser);
|
||||
break;
|
||||
}
|
||||
|
||||
case "toggleReaderMode": {
|
||||
let targetPromise = this.getTarget(window, "readerMode-urlBar");
|
||||
targetPromise.then(target => {
|
||||
ReaderParent.toggleReaderMode({target: target.node});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (!this.tourBrowsersByWindow.has(window)) {
|
||||
@ -1720,6 +1747,20 @@ this.UITour = {
|
||||
});
|
||||
},
|
||||
|
||||
startSubTour: function (aFeature) {
|
||||
if (aFeature != "string") {
|
||||
log.error("startSubTour: No feature option specified");
|
||||
return;
|
||||
}
|
||||
|
||||
if (aFeature == "readinglist") {
|
||||
ReaderParent.showReaderModeInfoPanel(browser);
|
||||
} else {
|
||||
log.error("startSubTour: Unknown feature option specified");
|
||||
return;
|
||||
}
|
||||
},
|
||||
|
||||
addNavBarWidget: function (aTarget, aMessageManager, aCallbackID) {
|
||||
if (aTarget.node) {
|
||||
log.error("addNavBarWidget: can't add a widget already present:", aTarget);
|
||||
|
@ -9,30 +9,32 @@ support-files =
|
||||
[browser_UITour.js]
|
||||
skip-if = os == "linux" || e10s # Intermittent failures, bug 951965
|
||||
[browser_UITour2.js]
|
||||
skip-if = e10s # Bug 941428 - UITour.jsm not e10s friendly
|
||||
skip-if = e10s # Bug 1073247 - UITour.jsm not e10s friendly
|
||||
# [browser_UITour3.js] Bug 1113038
|
||||
# skip-if = os == "linux" || e10s # Linux: Bug 986760, Bug 989101; e10s: Bug 941428 - UITour.jsm not e10s friendly
|
||||
# skip-if = os == "linux" || e10s # Linux: Bug 986760, Bug 989101; e10s: Bug 1073247 - UITour.jsm not e10s friendly
|
||||
[browser_UITour_availableTargets.js]
|
||||
skip-if = e10s # Bug 941428 - UITour.jsm not e10s friendly
|
||||
skip-if = e10s # Bug 1073247 - UITour.jsm not e10s friendly
|
||||
[browser_UITour_detach_tab.js]
|
||||
skip-if = e10s # Bug 941428 - UITour.jsm not e10s friendly
|
||||
skip-if = e10s # Bug 1073247 - UITour.jsm not e10s friendly
|
||||
[browser_UITour_annotation_size_attributes.js]
|
||||
skip-if = e10s # Bug 941428 - UITour.jsm not e10s friendly.
|
||||
skip-if = e10s # Bug 1073247 - UITour.jsm not e10s friendly.
|
||||
[browser_UITour_forceReaderMode.js]
|
||||
skip-if = e10s # Bug 941428 - UITour.jsm not e10s friendly.
|
||||
skip-if = e10s # Bug 1073247 - UITour.jsm not e10s friendly.
|
||||
[browser_UITour_toggleReaderMode.js]
|
||||
skip-if = e10s # Bug 1073247 - UITour.jsm not e10s friendly
|
||||
[browser_UITour_heartbeat.js]
|
||||
skip-if = e10s # Bug 941428 - UITour.jsm not e10s friendly.
|
||||
skip-if = e10s # Bug 1073247 - UITour.jsm not e10s friendly.
|
||||
[browser_UITour_loop.js]
|
||||
skip-if = os == "linux" || e10s # Bug 941428 - UITour.jsm not e10s friendly.
|
||||
skip-if = os == "linux" || e10s # Bug 1073247 - UITour.jsm not e10s friendly.
|
||||
[browser_UITour_modalDialog.js]
|
||||
skip-if = os != "mac" || e10s # modal dialog disabling only working on OS X.Bug 941428 - UITour.jsm not e10s friendly
|
||||
skip-if = os != "mac" || e10s # modal dialog disabling only working on OS X.Bug 1073247 - UITour.jsm not e10s friendly
|
||||
[browser_UITour_observe.js]
|
||||
skip-if = e10s # Bug 941428 - UITour.jsm not e10s friendly.
|
||||
skip-if = e10s # Bug 1073247 - UITour.jsm not e10s friendly.
|
||||
[browser_UITour_panel_close_annotation.js]
|
||||
skip-if = true # Disabled due to frequent failures, bugs 1026310 and 1032137
|
||||
[browser_UITour_registerPageID.js]
|
||||
skip-if = e10s # Bug 941428 - UITour.jsm not e10s friendly
|
||||
skip-if = e10s # Bug 1073247 - UITour.jsm not e10s friendly
|
||||
[browser_UITour_sync.js]
|
||||
skip-if = e10s # Bug 941428 - UITour.jsm not e10s friendly
|
||||
skip-if = e10s # Bug 1073247 - UITour.jsm not e10s friendly
|
||||
[browser_UITour_resetProfile.js]
|
||||
skip-if = e10s # Bug 941428 - UITour.jsm not e10s friendly
|
||||
skip-if = e10s # Bug 1073247 - UITour.jsm not e10s friendly
|
||||
|
@ -39,6 +39,7 @@ let tests = [
|
||||
"devtools",
|
||||
"privateWindow",
|
||||
"quit",
|
||||
"readerMode-urlBar",
|
||||
"search",
|
||||
"searchIcon",
|
||||
"urlbar",
|
||||
@ -69,6 +70,7 @@ let tests = [
|
||||
"home",
|
||||
"privateWindow",
|
||||
"quit",
|
||||
"readerMode-urlBar",
|
||||
"search",
|
||||
"searchIcon",
|
||||
"urlbar",
|
||||
@ -104,6 +106,7 @@ let tests = [
|
||||
"devtools",
|
||||
"privateWindow",
|
||||
"quit",
|
||||
"readerMode-urlBar",
|
||||
"urlbar",
|
||||
...(hasWebIDE ? ["webide"] : [])
|
||||
]);
|
||||
|
@ -0,0 +1,20 @@
|
||||
"use strict";
|
||||
|
||||
let gTestTab;
|
||||
let gContentAPI;
|
||||
let gContentWindow;
|
||||
|
||||
Components.utils.import("resource:///modules/UITour.jsm");
|
||||
|
||||
function test() {
|
||||
UITourTest();
|
||||
}
|
||||
|
||||
let tests = [
|
||||
taskify(function*() {
|
||||
ok(!gBrowser.selectedBrowser.currentURI.spec.startsWith("about:reader"), "Should not be in reader mode at start of test.");
|
||||
gContentAPI.toggleReaderMode();
|
||||
yield waitForConditionPromise(() => gBrowser.selectedBrowser.currentURI.spec.startsWith("about:reader"));
|
||||
ok(gBrowser.selectedBrowser.currentURI.spec.startsWith("about:reader"), "Should be in reader mode now.");
|
||||
})
|
||||
];
|
@ -55,7 +55,7 @@ let shutdown = Task.async(function*() {
|
||||
yield AnimationsController.destroy();
|
||||
// Don't assume that AnimationsPanel is defined here, it's in another file.
|
||||
if (typeof AnimationsPanel !== "undefined") {
|
||||
yield AnimationsPanel.destroy()
|
||||
yield AnimationsPanel.destroy();
|
||||
}
|
||||
gToolbox = gInspector = null;
|
||||
});
|
||||
@ -97,8 +97,11 @@ let AnimationsController = {
|
||||
}
|
||||
this.initialized = promise.defer();
|
||||
|
||||
this.onPanelVisibilityChange = this.onPanelVisibilityChange.bind(this);
|
||||
this.onNewNodeFront = this.onNewNodeFront.bind(this);
|
||||
this.onAnimationMutations = this.onAnimationMutations.bind(this);
|
||||
|
||||
let target = gToolbox.target;
|
||||
this.animationsFront = new AnimationsFront(target.client, target.form);
|
||||
|
||||
// Expose actor capabilities.
|
||||
this.hasToggleAll = yield target.actorHasMethod("animations", "toggleAll");
|
||||
@ -109,12 +112,13 @@ let AnimationsController = {
|
||||
this.hasSetPlaybackRate = yield target.actorHasMethod("animationplayer",
|
||||
"setPlaybackRate");
|
||||
|
||||
this.onPanelVisibilityChange = this.onPanelVisibilityChange.bind(this);
|
||||
this.onNewNodeFront = this.onNewNodeFront.bind(this);
|
||||
this.onAnimationMutations = this.onAnimationMutations.bind(this);
|
||||
if (this.destroyed) {
|
||||
console.warn("Could not fully initialize the AnimationsController");
|
||||
return;
|
||||
}
|
||||
|
||||
this.animationsFront = new AnimationsFront(target.client, target.form);
|
||||
this.startListeners();
|
||||
|
||||
yield this.onNewNodeFront();
|
||||
|
||||
this.initialized.resolve();
|
||||
|
@ -14,6 +14,10 @@ let AnimationsPanel = {
|
||||
PANEL_INITIALIZED: "panel-initialized",
|
||||
|
||||
initialize: Task.async(function*() {
|
||||
if (AnimationsController.destroyed) {
|
||||
console.warn("Could not initialize the animation-panel, controller was destroyed");
|
||||
return;
|
||||
}
|
||||
if (this.initialized) {
|
||||
return this.initialized.promise;
|
||||
}
|
||||
|
@ -409,6 +409,10 @@ InspectorPanel.prototype = {
|
||||
* reload
|
||||
*/
|
||||
set selectionCssSelector(cssSelector = null) {
|
||||
if (this._panelDestroyer) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._selectionCssSelector = {
|
||||
selector: cssSelector,
|
||||
url: this._target.url
|
||||
|
@ -15,6 +15,7 @@ support-files =
|
||||
[browser_layoutview_editablemodel_stylerules.js]
|
||||
[browser_layoutview_guides.js]
|
||||
[browser_layoutview_rotate-labels-on-sides.js]
|
||||
[browser_layoutview_tooltips.js]
|
||||
[browser_layoutview_update-after-navigation.js]
|
||||
[browser_layoutview_update-after-reload.js]
|
||||
# [browser_layoutview_update-in-iframes.js]
|
||||
|
126
browser/devtools/layoutview/test/browser_layoutview_tooltips.js
Normal file
126
browser/devtools/layoutview/test/browser_layoutview_tooltips.js
Normal file
@ -0,0 +1,126 @@
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Test that the regions in the layout-view have tooltips, and that individual
|
||||
// values too. Also test that values that are set from a css rule have tooltips
|
||||
// referencing the rule.
|
||||
|
||||
const TEST_URI = "<style>" +
|
||||
"#div1 { color: red; margin: 3em; }\n" +
|
||||
"#div2 { border-bottom: 1px solid black; background: red; }\n" +
|
||||
"html, body, #div3 { box-sizing: border-box; padding: 0 2em; }" +
|
||||
"</style>" +
|
||||
"<div id='div1'></div><div id='div2'></div><div id='div3'></div>";
|
||||
|
||||
// Test data for the tooltips over individual values.
|
||||
// Each entry should contain:
|
||||
// - selector: The selector for the node to be selected before starting to test
|
||||
// - values: An array containing objects for each of the values that are defined
|
||||
// by css rules. Each entry should contain:
|
||||
// - name: the name of the property that is set by the css rule
|
||||
// - ruleSelector: the selector of the rule
|
||||
// - styleSheetLocation: the fileName:lineNumber
|
||||
const VALUES_TEST_DATA = [{
|
||||
selector: "#div1",
|
||||
values: [{
|
||||
name: "margin-top",
|
||||
ruleSelector: "#div1",
|
||||
styleSheetLocation: "null:1"
|
||||
}, {
|
||||
name: "margin-right",
|
||||
ruleSelector: "#div1",
|
||||
styleSheetLocation: "null:1"
|
||||
}, {
|
||||
name: "margin-bottom",
|
||||
ruleSelector: "#div1",
|
||||
styleSheetLocation: "null:1"
|
||||
}, {
|
||||
name: "margin-left",
|
||||
ruleSelector: "#div1",
|
||||
styleSheetLocation: "null:1"
|
||||
}]
|
||||
},{
|
||||
selector: "#div2",
|
||||
values: [{
|
||||
name: "border-bottom-width",
|
||||
ruleSelector: "#div2",
|
||||
styleSheetLocation: "null:2"
|
||||
}]
|
||||
},{
|
||||
selector: "#div3",
|
||||
values: [{
|
||||
name: "padding-top",
|
||||
ruleSelector: "html, body, #div3",
|
||||
styleSheetLocation: "null:3"
|
||||
}, {
|
||||
name: "padding-right",
|
||||
ruleSelector: "html, body, #div3",
|
||||
styleSheetLocation: "null:3"
|
||||
}, {
|
||||
name: "padding-bottom",
|
||||
ruleSelector: "html, body, #div3",
|
||||
styleSheetLocation: "null:3"
|
||||
}, {
|
||||
name: "padding-left",
|
||||
ruleSelector: "html, body, #div3",
|
||||
styleSheetLocation: "null:3"
|
||||
}]
|
||||
}];
|
||||
|
||||
add_task(function*() {
|
||||
yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
|
||||
let {toolbox, inspector, view} = yield openLayoutView();
|
||||
|
||||
info("Checking the regions tooltips");
|
||||
|
||||
ok(view.doc.querySelector("#margins").hasAttribute("title"),
|
||||
"The margin region has a tooltip");
|
||||
is(view.doc.querySelector("#margins").getAttribute("title"), "margin",
|
||||
"The margin region has the correct tooltip content");
|
||||
|
||||
ok(view.doc.querySelector("#borders").hasAttribute("title"),
|
||||
"The border region has a tooltip");
|
||||
is(view.doc.querySelector("#borders").getAttribute("title"), "border",
|
||||
"The border region has the correct tooltip content");
|
||||
|
||||
ok(view.doc.querySelector("#padding").hasAttribute("title"),
|
||||
"The padding region has a tooltip");
|
||||
is(view.doc.querySelector("#padding").getAttribute("title"), "padding",
|
||||
"The padding region has the correct tooltip content");
|
||||
|
||||
ok(view.doc.querySelector("#content").hasAttribute("title"),
|
||||
"The content region has a tooltip");
|
||||
is(view.doc.querySelector("#content").getAttribute("title"), "content",
|
||||
"The content region has the correct tooltip content");
|
||||
|
||||
for (let {selector, values} of VALUES_TEST_DATA) {
|
||||
info("Selecting " + selector + " and checking the values tooltips");
|
||||
yield selectNode(selector, inspector);
|
||||
|
||||
info("Iterate over all values");
|
||||
for (let key in view.map) {
|
||||
if (key === "position") {
|
||||
continue;
|
||||
}
|
||||
|
||||
let name = view.map[key].property;
|
||||
let expectedTooltipData = values.find(o => o.name === name);
|
||||
let el = view.doc.querySelector(view.map[key].selector);
|
||||
|
||||
ok(el.hasAttribute("title"), "The " + name + " value has a tooltip");
|
||||
|
||||
if (expectedTooltipData) {
|
||||
info("The " + name + " value comes from a css rule");
|
||||
let expectedTooltip = name + "\n" + expectedTooltipData.ruleSelector +
|
||||
"\n" + expectedTooltipData.styleSheetLocation;
|
||||
is(el.getAttribute("title"), expectedTooltip, "The tooltip is correct");
|
||||
} else {
|
||||
info("The " + name + " isn't set by a css rule");
|
||||
is(el.getAttribute("title"), name, "The tooltip is correct");
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
@ -441,6 +441,7 @@ LayoutView.prototype = {
|
||||
for (let i in this.map) {
|
||||
let selector = this.map[i].selector;
|
||||
let span = this.doc.querySelector(selector);
|
||||
this.updateSourceRuleTooltip(span, this.map[i].property, styleEntries);
|
||||
if (span.textContent.length > 0 &&
|
||||
span.textContent == this.map[i].value) {
|
||||
continue;
|
||||
@ -469,6 +470,40 @@ LayoutView.prototype = {
|
||||
return this._lastRequest = lastRequest;
|
||||
},
|
||||
|
||||
/**
|
||||
* Update the text in the tooltip shown when hovering over a value to provide
|
||||
* information about the source CSS rule that sets this value.
|
||||
* @param {DOMNode} el The element that will receive the tooltip.
|
||||
* @param {String} property The name of the CSS property for the tooltip.
|
||||
* @param {Array} rules An array of applied rules retrieved by
|
||||
* styleActor.getApplied.
|
||||
*/
|
||||
updateSourceRuleTooltip: function(el, property, rules) {
|
||||
// Dummy element used to parse the cssText of applied rules.
|
||||
let dummyEl = this.doc.createElement("div");
|
||||
|
||||
// Rules are in order of priority so iterate until we find the first that
|
||||
// defines a value for the property.
|
||||
let sourceRule, value;
|
||||
for (let {rule} of rules) {
|
||||
dummyEl.style.cssText = rule.cssText;
|
||||
value = dummyEl.style.getPropertyValue(property);
|
||||
if (value !== "") {
|
||||
sourceRule = rule;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
let title = property;
|
||||
if (sourceRule && sourceRule.selectors) {
|
||||
title += "\n" + sourceRule.selectors.join(", ");
|
||||
}
|
||||
if (sourceRule && sourceRule.parentStyleSheet) {
|
||||
title += "\n" + sourceRule.parentStyleSheet.href + ":" + sourceRule.line;
|
||||
}
|
||||
el.setAttribute("title", title);
|
||||
},
|
||||
|
||||
/**
|
||||
* Show the box-model highlighter on the currently selected element
|
||||
* @param {Object} options Options passed to the highlighter actor
|
||||
|
@ -30,11 +30,11 @@
|
||||
|
||||
<div id="main">
|
||||
|
||||
<span class="legend" data-box="margin">&margin.tooltip;</span>
|
||||
<span class="legend" data-box="margin" title="&margin.tooltip;">&margin.tooltip;</span>
|
||||
<div id="margins" data-box="margin" title="&margin.tooltip;">
|
||||
<span class="legend" data-box="border">&border.tooltip;</span>
|
||||
<span class="legend" data-box="border" title="&border.tooltip;">&border.tooltip;</span>
|
||||
<div id="borders" data-box="border" title="&border.tooltip;">
|
||||
<span class="legend" data-box="padding">&padding.tooltip;</span>
|
||||
<span class="legend" data-box="padding" title="&padding.tooltip;">&padding.tooltip;</span>
|
||||
<div id="padding" data-box="padding" title="&padding.tooltip;">
|
||||
<div id="content" data-box="content" title="&content.tooltip;">
|
||||
</div>
|
||||
|
@ -16,6 +16,7 @@ Cu.import("resource://gre/modules/Task.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils","resource://gre/modules/PlacesUtils.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "ReaderMode", "resource://gre/modules/ReaderMode.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "ReadingList", "resource:///modules/readinglist/ReadingList.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "UITour", "resource:///modules/UITour.jsm");
|
||||
|
||||
const gStringBundle = Services.strings.createBundle("chrome://global/locale/aboutReader.properties");
|
||||
|
||||
@ -188,6 +189,23 @@ let ReaderParent = {
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Shows an info panel from the UITour for Reader Mode.
|
||||
*
|
||||
* @param browser The <browser> that the tour should be started for.
|
||||
*/
|
||||
showReaderModeInfoPanel(browser) {
|
||||
let win = browser.ownerDocument.defaultView;
|
||||
let targetPromise = UITour.getTarget(win, "readerMode-urlBar");
|
||||
targetPromise.then(target => {
|
||||
let browserBundle = Services.strings.createBundle("chrome://browser/locale/browser.properties");
|
||||
UITour.showInfo(win, browser.messageManager, target,
|
||||
browserBundle.GetStringFromName("readerView.promo.firstDetectedArticle.title"),
|
||||
browserBundle.GetStringFromName("readerView.promo.firstDetectedArticle.body"),
|
||||
"chrome://browser/skin/reader-tour.png");
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets an article for a given URL. This method will download and parse a document.
|
||||
*
|
||||
|
@ -93,6 +93,7 @@ browser.jar:
|
||||
skin/classic/browser/session-restore.svg (../shared/incontent-icons/session-restore.svg)
|
||||
skin/classic/browser/tab-crashed.svg (../shared/incontent-icons/tab-crashed.svg)
|
||||
skin/classic/browser/welcome-back.svg (../shared/incontent-icons/welcome-back.svg)
|
||||
skin/classic/browser/reader-tour.png (../shared/reader/reader-tour.png)
|
||||
skin/classic/browser/readerMode.svg (../shared/reader/readerMode.svg)
|
||||
skin/classic/browser/readinglist/icons.svg (../shared/readinglist/icons.svg)
|
||||
skin/classic/browser/readinglist/readinglist-icon.svg (../shared/readinglist/readinglist-icon.svg)
|
||||
|
@ -145,6 +145,7 @@ browser.jar:
|
||||
skin/classic/browser/session-restore.svg (../shared/incontent-icons/session-restore.svg)
|
||||
skin/classic/browser/tab-crashed.svg (../shared/incontent-icons/tab-crashed.svg)
|
||||
skin/classic/browser/welcome-back.svg (../shared/incontent-icons/welcome-back.svg)
|
||||
skin/classic/browser/reader-tour.png (../shared/reader/reader-tour.png)
|
||||
skin/classic/browser/readerMode.svg (../shared/reader/readerMode.svg)
|
||||
skin/classic/browser/readinglist/icons.svg (../shared/readinglist/icons.svg)
|
||||
skin/classic/browser/readinglist/readinglist-icon.svg (../shared/readinglist/readinglist-icon.svg)
|
||||
|
@ -355,6 +355,17 @@ description > html|a {
|
||||
* End Dialog
|
||||
*/
|
||||
|
||||
/**
|
||||
* Font dialog menulist fixes
|
||||
*/
|
||||
|
||||
#defaultFontType,
|
||||
#serif,
|
||||
#sans-serif,
|
||||
#monospace {
|
||||
min-width: 30ch;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sync migration
|
||||
*/
|
||||
|
BIN
browser/themes/shared/reader/reader-tour.png
Normal file
BIN
browser/themes/shared/reader/reader-tour.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
@ -26,6 +26,10 @@ notification[value="translation"][state="translating"] .messageImage {
|
||||
}
|
||||
}
|
||||
|
||||
notification[value="translation"] hbox[anonid="details"] {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
notification[value="translation"] button,
|
||||
notification[value="translation"] menulist {
|
||||
-moz-appearance: none;
|
||||
|
@ -128,6 +128,7 @@ browser.jar:
|
||||
skin/classic/browser/session-restore.svg (../shared/incontent-icons/session-restore.svg)
|
||||
skin/classic/browser/tab-crashed.svg (../shared/incontent-icons/tab-crashed.svg)
|
||||
skin/classic/browser/welcome-back.svg (../shared/incontent-icons/welcome-back.svg)
|
||||
skin/classic/browser/reader-tour.png (../shared/reader/reader-tour.png)
|
||||
skin/classic/browser/readerMode.svg (../shared/reader/readerMode.svg)
|
||||
skin/classic/browser/readinglist/icons.svg (../shared/readinglist/icons.svg)
|
||||
skin/classic/browser/readinglist/readinglist-icon.svg (../shared/readinglist/readinglist-icon.svg)
|
||||
|
@ -31,10 +31,11 @@ UuidToString(const BluetoothUuid& aUuid, nsAString& aString)
|
||||
memcpy(&uuid4, &aUuid.mUuid[10], sizeof(uint32_t));
|
||||
memcpy(&uuid5, &aUuid.mUuid[14], sizeof(uint16_t));
|
||||
|
||||
sprintf(uuidStr, "%.8x-%.4x-%.4x-%.4x-%.8x%.4x",
|
||||
ntohl(uuid0), ntohs(uuid1),
|
||||
ntohs(uuid2), ntohs(uuid3),
|
||||
ntohl(uuid4), ntohs(uuid5));
|
||||
snprintf(uuidStr, sizeof(uuidStr),
|
||||
"%.8x-%.4x-%.4x-%.4x-%.8x%.4x",
|
||||
ntohl(uuid0), ntohs(uuid1),
|
||||
ntohs(uuid2), ntohs(uuid3),
|
||||
ntohl(uuid4), ntohs(uuid5));
|
||||
|
||||
aString.Truncate();
|
||||
aString.AssignLiteral(uuidStr);
|
||||
@ -98,7 +99,7 @@ GeneratePathFromGattId(const BluetoothGattId& aId,
|
||||
/**
|
||||
* |SetJsObject| is an internal function used by |BroadcastSystemMessage| only
|
||||
*/
|
||||
bool
|
||||
static bool
|
||||
SetJsObject(JSContext* aContext,
|
||||
const BluetoothValue& aValue,
|
||||
JS::Handle<JSObject*> aObj)
|
||||
@ -219,6 +220,7 @@ BroadcastSystemMessage(const nsAString& aType,
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef MOZ_B2G_BT_API_V2
|
||||
void
|
||||
DispatchReplySuccess(BluetoothReplyRunnable* aRunnable)
|
||||
{
|
||||
@ -281,6 +283,48 @@ DispatchStatusChangedEvent(const nsAString& aType,
|
||||
NS_ENSURE_TRUE_VOID(bs);
|
||||
bs->DistributeSignal(aType, NS_LITERAL_STRING(KEY_ADAPTER), data);
|
||||
}
|
||||
#else
|
||||
// TODO: remove with bluetooth1
|
||||
void
|
||||
DispatchBluetoothReply(BluetoothReplyRunnable* aRunnable,
|
||||
const BluetoothValue& aValue,
|
||||
const nsAString& aErrorStr)
|
||||
{
|
||||
// Reply will be deleted by the runnable after running on main thread
|
||||
BluetoothReply* reply;
|
||||
if (!aErrorStr.IsEmpty()) {
|
||||
nsString err(aErrorStr);
|
||||
reply = new BluetoothReply(BluetoothReplyError(err));
|
||||
} else {
|
||||
MOZ_ASSERT(aValue.type() != BluetoothValue::T__None);
|
||||
reply = new BluetoothReply(BluetoothReplySuccess(aValue));
|
||||
}
|
||||
|
||||
aRunnable->SetReply(reply);
|
||||
if (NS_FAILED(NS_DispatchToMainThread(aRunnable))) {
|
||||
BT_WARNING("Failed to dispatch to main thread!");
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: remove with bluetooth1
|
||||
void
|
||||
DispatchStatusChangedEvent(const nsAString& aType,
|
||||
const nsAString& aAddress,
|
||||
bool aStatus)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
InfallibleTArray<BluetoothNamedValue> data;
|
||||
BT_APPEND_NAMED_VALUE(data, "address", nsString(aAddress));
|
||||
BT_APPEND_NAMED_VALUE(data, "status", aStatus);
|
||||
|
||||
BluetoothSignal signal(nsString(aType), NS_LITERAL_STRING(KEY_ADAPTER), data);
|
||||
|
||||
BluetoothService* bs = BluetoothService::Get();
|
||||
NS_ENSURE_TRUE_VOID(bs);
|
||||
bs->DistributeSignal(signal);
|
||||
}
|
||||
#endif
|
||||
|
||||
bool
|
||||
IsMainProcess()
|
@ -93,6 +93,7 @@ BroadcastSystemMessage(const nsAString& aType,
|
||||
// Dispatch bluetooth reply to main thread
|
||||
//
|
||||
|
||||
#ifdef MOZ_B2G_BT_API_V2
|
||||
/**
|
||||
* Dispatch successful bluetooth reply with NO value to reply request.
|
||||
*
|
||||
@ -142,6 +143,19 @@ DispatchReplyError(BluetoothReplyRunnable* aRunnable,
|
||||
void
|
||||
DispatchReplyError(BluetoothReplyRunnable* aRunnable,
|
||||
const enum BluetoothStatus aStatus);
|
||||
#else
|
||||
// TODO: remove with bluetooth1
|
||||
void
|
||||
DispatchBluetoothReply(BluetoothReplyRunnable* aRunnable,
|
||||
const BluetoothValue& aValue,
|
||||
const nsAString& aErrorStr);
|
||||
|
||||
// TODO: remove with bluetooth1
|
||||
void
|
||||
DispatchStatusChangedEvent(const nsAString& aType,
|
||||
const nsAString& aDeviceAddress,
|
||||
bool aStatus);
|
||||
#endif
|
||||
|
||||
void
|
||||
DispatchStatusChangedEvent(const nsAString& aType,
|
@ -729,15 +729,6 @@ BluetoothService::Notify(const BluetoothSignal& aData)
|
||||
{
|
||||
nsString type = NS_LITERAL_STRING("bluetooth-pairing-request");
|
||||
|
||||
AutoSafeJSContext cx;
|
||||
JS::Rooted<JSObject*> obj(cx, JS_NewPlainObject(cx));
|
||||
NS_ENSURE_TRUE_VOID(obj);
|
||||
|
||||
if (!SetJsObject(cx, aData.value(), obj)) {
|
||||
BT_WARNING("Failed to set properties of system message!");
|
||||
return;
|
||||
}
|
||||
|
||||
BT_LOGD("[S] %s: %s", __FUNCTION__, NS_ConvertUTF16toUTF8(aData.name()).get());
|
||||
|
||||
if (aData.name().EqualsLiteral("RequestConfirmation")) {
|
||||
@ -765,13 +756,7 @@ BluetoothService::Notify(const BluetoothSignal& aData)
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsISystemMessagesInternal> systemMessenger =
|
||||
do_GetService("@mozilla.org/system-message-internal;1");
|
||||
NS_ENSURE_TRUE_VOID(systemMessenger);
|
||||
|
||||
JS::Rooted<JS::Value> value(cx, JS::ObjectValue(*obj));
|
||||
systemMessenger->BroadcastMessage(type, value,
|
||||
JS::UndefinedHandleValue);
|
||||
BroadcastSystemMessage(type, aData.value());
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1,178 +0,0 @@
|
||||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "BluetoothUtils.h"
|
||||
#include "BluetoothReplyRunnable.h"
|
||||
#include "BluetoothService.h"
|
||||
#include "jsapi.h"
|
||||
#include "mozilla/dom/bluetooth/BluetoothTypes.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsISystemMessagesInternal.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
|
||||
BEGIN_BLUETOOTH_NAMESPACE
|
||||
|
||||
bool
|
||||
SetJsObject(JSContext* aContext,
|
||||
const BluetoothValue& aValue,
|
||||
JS::Handle<JSObject*> aObj)
|
||||
{
|
||||
MOZ_ASSERT(aContext && aObj);
|
||||
|
||||
if (aValue.type() != BluetoothValue::TArrayOfBluetoothNamedValue) {
|
||||
BT_WARNING("SetJsObject: Invalid parameter type");
|
||||
return false;
|
||||
}
|
||||
|
||||
const nsTArray<BluetoothNamedValue>& arr =
|
||||
aValue.get_ArrayOfBluetoothNamedValue();
|
||||
|
||||
for (uint32_t i = 0; i < arr.Length(); i++) {
|
||||
JS::Rooted<JS::Value> val(aContext);
|
||||
const BluetoothValue& v = arr[i].value();
|
||||
|
||||
switch(v.type()) {
|
||||
case BluetoothValue::TnsString: {
|
||||
JSString* jsData = JS_NewUCStringCopyN(aContext,
|
||||
v.get_nsString().BeginReading(),
|
||||
v.get_nsString().Length());
|
||||
NS_ENSURE_TRUE(jsData, false);
|
||||
val = STRING_TO_JSVAL(jsData);
|
||||
break;
|
||||
}
|
||||
case BluetoothValue::Tuint32_t:
|
||||
val = INT_TO_JSVAL(v.get_uint32_t());
|
||||
break;
|
||||
case BluetoothValue::Tbool:
|
||||
val = BOOLEAN_TO_JSVAL(v.get_bool());
|
||||
break;
|
||||
default:
|
||||
BT_WARNING("SetJsObject: Parameter is not handled");
|
||||
break;
|
||||
}
|
||||
|
||||
if (!JS_SetProperty(aContext, aObj,
|
||||
NS_ConvertUTF16toUTF8(arr[i].name()).get(),
|
||||
val)) {
|
||||
BT_WARNING("Failed to set property");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
BroadcastSystemMessage(const nsAString& aType,
|
||||
const BluetoothValue& aData)
|
||||
{
|
||||
mozilla::AutoSafeJSContext cx;
|
||||
NS_ASSERTION(!::JS_IsExceptionPending(cx),
|
||||
"Shouldn't get here when an exception is pending!");
|
||||
|
||||
nsCOMPtr<nsISystemMessagesInternal> systemMessenger =
|
||||
do_GetService("@mozilla.org/system-message-internal;1");
|
||||
NS_ENSURE_TRUE(systemMessenger, false);
|
||||
|
||||
JS::Rooted<JS::Value> value(cx);
|
||||
if (aData.type() == BluetoothValue::TnsString) {
|
||||
JSString* jsData = JS_NewUCStringCopyN(cx,
|
||||
aData.get_nsString().BeginReading(),
|
||||
aData.get_nsString().Length());
|
||||
value = STRING_TO_JSVAL(jsData);
|
||||
} else if (aData.type() == BluetoothValue::TArrayOfBluetoothNamedValue) {
|
||||
JS::Rooted<JSObject*> obj(cx, JS_NewPlainObject(cx));
|
||||
if (!obj) {
|
||||
BT_WARNING("Failed to new JSObject for system message!");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!SetJsObject(cx, aData, obj)) {
|
||||
BT_WARNING("Failed to set properties of system message!");
|
||||
return false;
|
||||
}
|
||||
value = JS::ObjectValue(*obj);
|
||||
} else {
|
||||
BT_WARNING("Not support the unknown BluetoothValue type");
|
||||
return false;
|
||||
}
|
||||
|
||||
systemMessenger->BroadcastMessage(aType, value,
|
||||
JS::UndefinedHandleValue);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
BroadcastSystemMessage(const nsAString& aType,
|
||||
const InfallibleTArray<BluetoothNamedValue>& aData)
|
||||
{
|
||||
mozilla::AutoSafeJSContext cx;
|
||||
NS_ASSERTION(!::JS_IsExceptionPending(cx),
|
||||
"Shouldn't get here when an exception is pending!");
|
||||
|
||||
JS::Rooted<JSObject*> obj(cx, JS_NewPlainObject(cx));
|
||||
if (!obj) {
|
||||
BT_WARNING("Failed to new JSObject for system message!");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!SetJsObject(cx, aData, obj)) {
|
||||
BT_WARNING("Failed to set properties of system message!");
|
||||
return false;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsISystemMessagesInternal> systemMessenger =
|
||||
do_GetService("@mozilla.org/system-message-internal;1");
|
||||
NS_ENSURE_TRUE(systemMessenger, false);
|
||||
|
||||
JS::Rooted<JS::Value> value(cx, JS::ObjectValue(*obj));
|
||||
systemMessenger->BroadcastMessage(aType, value,
|
||||
JS::UndefinedHandleValue);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
DispatchBluetoothReply(BluetoothReplyRunnable* aRunnable,
|
||||
const BluetoothValue& aValue,
|
||||
const nsAString& aErrorStr)
|
||||
{
|
||||
// Reply will be deleted by the runnable after running on main thread
|
||||
BluetoothReply* reply;
|
||||
if (!aErrorStr.IsEmpty()) {
|
||||
nsString err(aErrorStr);
|
||||
reply = new BluetoothReply(BluetoothReplyError(err));
|
||||
} else {
|
||||
MOZ_ASSERT(aValue.type() != BluetoothValue::T__None);
|
||||
reply = new BluetoothReply(BluetoothReplySuccess(aValue));
|
||||
}
|
||||
|
||||
aRunnable->SetReply(reply);
|
||||
if (NS_FAILED(NS_DispatchToMainThread(aRunnable))) {
|
||||
BT_WARNING("Failed to dispatch to main thread!");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
DispatchStatusChangedEvent(const nsAString& aType,
|
||||
const nsAString& aAddress,
|
||||
bool aStatus)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
InfallibleTArray<BluetoothNamedValue> data;
|
||||
BT_APPEND_NAMED_VALUE(data, "address", nsString(aAddress));
|
||||
BT_APPEND_NAMED_VALUE(data, "status", aStatus);
|
||||
|
||||
BluetoothSignal signal(nsString(aType), NS_LITERAL_STRING(KEY_ADAPTER), data);
|
||||
|
||||
BluetoothService* bs = BluetoothService::Get();
|
||||
NS_ENSURE_TRUE_VOID(bs);
|
||||
bs->DistributeSignal(signal);
|
||||
}
|
||||
|
||||
END_BLUETOOTH_NAMESPACE
|
@ -1,44 +0,0 @@
|
||||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_dom_bluetooth_bluetoothutils_h
|
||||
#define mozilla_dom_bluetooth_bluetoothutils_h
|
||||
|
||||
#include "BluetoothCommon.h"
|
||||
#include "js/TypeDecls.h"
|
||||
|
||||
BEGIN_BLUETOOTH_NAMESPACE
|
||||
|
||||
class BluetoothNamedValue;
|
||||
class BluetoothValue;
|
||||
class BluetoothReplyRunnable;
|
||||
|
||||
bool
|
||||
SetJsObject(JSContext* aContext,
|
||||
const BluetoothValue& aValue,
|
||||
JS::Handle<JSObject*> aObj);
|
||||
|
||||
bool
|
||||
BroadcastSystemMessage(const nsAString& aType,
|
||||
const BluetoothValue& aData);
|
||||
|
||||
bool
|
||||
BroadcastSystemMessage(const nsAString& aType,
|
||||
const InfallibleTArray<BluetoothNamedValue>& aData);
|
||||
|
||||
void
|
||||
DispatchBluetoothReply(BluetoothReplyRunnable* aRunnable,
|
||||
const BluetoothValue& aValue,
|
||||
const nsAString& aErrorStr);
|
||||
|
||||
void
|
||||
DispatchStatusChangedEvent(const nsAString& aType,
|
||||
const nsAString& aDeviceAddress,
|
||||
bool aStatus);
|
||||
|
||||
END_BLUETOOTH_NAMESPACE
|
||||
|
||||
#endif
|
@ -12,7 +12,8 @@ if CONFIG['MOZ_B2G_BT']:
|
||||
|
||||
SOURCES += [
|
||||
'BluetoothInterface.cpp',
|
||||
'BluetoothInterfaceHelpers.cpp'
|
||||
'BluetoothInterfaceHelpers.cpp',
|
||||
'BluetoothUtils.cpp'
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_B2G_BT_API_V2']:
|
||||
@ -32,7 +33,6 @@ if CONFIG['MOZ_B2G_BT']:
|
||||
'bluetooth2/BluetoothProfileController.cpp',
|
||||
'bluetooth2/BluetoothReplyRunnable.cpp',
|
||||
'bluetooth2/BluetoothService.cpp',
|
||||
'bluetooth2/BluetoothUtils.cpp',
|
||||
'bluetooth2/BluetoothUuid.cpp',
|
||||
'bluetooth2/ipc/BluetoothChild.cpp',
|
||||
'bluetooth2/ipc/BluetoothParent.cpp',
|
||||
@ -58,7 +58,6 @@ if CONFIG['MOZ_B2G_BT']:
|
||||
'bluetooth1/BluetoothPropertyContainer.cpp',
|
||||
'bluetooth1/BluetoothReplyRunnable.cpp',
|
||||
'bluetooth1/BluetoothService.cpp',
|
||||
'bluetooth1/BluetoothUtils.cpp',
|
||||
'bluetooth1/BluetoothUuid.cpp',
|
||||
'bluetooth1/ipc/BluetoothChild.cpp',
|
||||
'bluetooth1/ipc/BluetoothParent.cpp',
|
||||
|
@ -16,7 +16,7 @@ skip-if = buildapp == 'mulet'
|
||||
[test_bug703150.xul]
|
||||
skip-if = buildapp == 'mulet'
|
||||
[test_bug987230.xul]
|
||||
skip-if = os == 'linux' # No native mousedown event
|
||||
skip-if = os == 'linux' || (os == 'win' && (os_version == '6.2' || os_version == '6.3')) # No native mousedown event on Linux, bug 1135545 for win8 intermittent failures
|
||||
[test_popupReflowPos.xul]
|
||||
[test_popupSizeTo.xul]
|
||||
[test_popupZoom.xul]
|
||||
|
@ -9,11 +9,11 @@ import org.mozilla.gecko.AppConstants.Versions;
|
||||
import org.mozilla.gecko.GeckoApp;
|
||||
import org.mozilla.gecko.GeckoApplication;
|
||||
import org.mozilla.gecko.R;
|
||||
import org.mozilla.gecko.Tab;
|
||||
import org.mozilla.gecko.Tabs;
|
||||
import org.mozilla.gecko.Telemetry;
|
||||
import org.mozilla.gecko.TelemetryContract;
|
||||
import org.mozilla.gecko.animation.PropertyAnimator;
|
||||
import org.mozilla.gecko.Tab;
|
||||
import org.mozilla.gecko.Tabs;
|
||||
import org.mozilla.gecko.animation.ViewHelper;
|
||||
import org.mozilla.gecko.lwt.LightweightTheme;
|
||||
import org.mozilla.gecko.lwt.LightweightThemeDrawable;
|
||||
@ -31,6 +31,7 @@ import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewStub;
|
||||
import android.view.ViewTreeObserver;
|
||||
import android.widget.Button;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageButton;
|
||||
@ -377,9 +378,19 @@ public class TabsPanel extends LinearLayout
|
||||
|
||||
public void show(Panel panelToShow) {
|
||||
prepareToShow(panelToShow);
|
||||
int height = getVerticalPanelHeight();
|
||||
dispatchLayoutChange(getWidth(), height);
|
||||
mHeaderVisible = true;
|
||||
|
||||
final ViewTreeObserver vto = mTabsContainer.getViewTreeObserver();
|
||||
if (vto.isAlive()) {
|
||||
vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
|
||||
@Override
|
||||
public void onGlobalLayout() {
|
||||
vto.removeGlobalOnLayoutListener(this);
|
||||
int height = getVerticalPanelHeight();
|
||||
dispatchLayoutChange(getWidth(), height);
|
||||
mHeaderVisible = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void prepareToDrag() {
|
||||
@ -460,8 +471,22 @@ public class TabsPanel extends LinearLayout
|
||||
inflateLayout(mContext);
|
||||
initialize();
|
||||
|
||||
if (mVisible)
|
||||
show(mCurrentPanel);
|
||||
if (mVisible) {
|
||||
final ViewTreeObserver vto = getViewTreeObserver();
|
||||
if (vto.isAlive()) {
|
||||
vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
|
||||
@Override
|
||||
public void onGlobalLayout() {
|
||||
vto.removeGlobalOnLayoutListener(this);
|
||||
|
||||
// If we've just inflated the tabs panel, only show it once the current
|
||||
// layout pass is done to avoid displayed temporary UI states during
|
||||
// relayout.
|
||||
show(mCurrentPanel);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void autoHidePanel() {
|
||||
|
@ -26,8 +26,20 @@ let APP_INFO = {
|
||||
logConsoleErrors: true,
|
||||
OS: "XPCShell",
|
||||
XPCOMABI: "noarch-spidermonkey",
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIXULAppInfo, Ci.nsIXULRuntime]),
|
||||
invalidateCachesOnRestart: function() {},
|
||||
|
||||
invalidateCachesOnRestart() {},
|
||||
|
||||
// nsIWinAppHelper
|
||||
get userCanElevate() false,
|
||||
|
||||
QueryInterface(iid) {
|
||||
let interfaces = [ Ci.nsIXULAppInfo, Ci.nsIXULRuntime ];
|
||||
if ("nsIWinAppHelper" in Ci)
|
||||
interfaces.push(Ci.nsIWinAppHelper);
|
||||
if (!interfaces.some(v => iid.equals(v)))
|
||||
throw Cr.NS_ERROR_NO_INTERFACE;
|
||||
return this;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
@ -68,7 +68,6 @@ Cu.import("resource://gre/modules/NetUtil.jsm");
|
||||
Cu.import("resource://gre/modules/osfile.jsm");
|
||||
Cu.import("resource://gre/modules/FileUtils.jsm");
|
||||
Cu.import("resource://gre/modules/PlacesUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Promise.jsm");
|
||||
Cu.import("resource://gre/modules/Task.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "PlacesBackups",
|
||||
@ -126,13 +125,6 @@ function notifyObservers(aTopic, aInitialImport) {
|
||||
: "html");
|
||||
}
|
||||
|
||||
function promiseSoon() {
|
||||
let deferred = Promise.defer();
|
||||
Services.tm.mainThread.dispatch(deferred.resolve,
|
||||
Ci.nsIThread.DISPATCH_NORMAL);
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
this.BookmarkHTMLUtils = Object.freeze({
|
||||
/**
|
||||
* Loads the current bookmarks hierarchy from a "bookmarks.html" file.
|
||||
@ -602,17 +594,10 @@ BookmarkImporter.prototype = {
|
||||
|
||||
// Save the keyword.
|
||||
if (keyword) {
|
||||
try {
|
||||
PlacesUtils.bookmarks.setKeywordForBookmark(frame.previousId, keyword);
|
||||
if (postData) {
|
||||
PlacesUtils.annotations.setItemAnnotation(frame.previousId,
|
||||
PlacesUtils.POST_DATA_ANNO,
|
||||
postData,
|
||||
0,
|
||||
PlacesUtils.annotations.EXPIRE_NEVER);
|
||||
}
|
||||
} catch(e) {
|
||||
}
|
||||
let kwPromise = PlacesUtils.keywords.insert({ keyword,
|
||||
url: frame.previousLink.spec,
|
||||
postData });
|
||||
this._importPromises.push(kwPromise);
|
||||
}
|
||||
|
||||
// Set load-in-sidebar annotation for the bookmark.
|
||||
@ -629,7 +614,8 @@ BookmarkImporter.prototype = {
|
||||
|
||||
// Import last charset.
|
||||
if (lastCharset) {
|
||||
PlacesUtils.setCharsetForURI(frame.previousLink, lastCharset);
|
||||
let chPromise = PlacesUtils.setCharsetForURI(frame.previousLink, lastCharset);
|
||||
this._importPromises.push(chPromise);
|
||||
}
|
||||
},
|
||||
|
||||
@ -934,33 +920,35 @@ BookmarkImporter.prototype = {
|
||||
PlacesUtils.bookmarks.runInBatchMode(this, aDoc);
|
||||
},
|
||||
|
||||
importFromURL: function importFromURL(aSpec) {
|
||||
let deferred = Promise.defer();
|
||||
let xhr = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"]
|
||||
.createInstance(Ci.nsIXMLHttpRequest);
|
||||
xhr.onload = () => {
|
||||
try {
|
||||
this._walkTreeForImport(xhr.responseXML);
|
||||
deferred.resolve();
|
||||
} catch(e) {
|
||||
deferred.reject(e);
|
||||
throw e;
|
||||
}
|
||||
};
|
||||
xhr.onabort = xhr.onerror = xhr.ontimeout = () => {
|
||||
deferred.reject(new Error("xmlhttprequest failed"));
|
||||
};
|
||||
try {
|
||||
xhr.open("GET", aSpec);
|
||||
importFromURL: Task.async(function* (href) {
|
||||
this._importPromises = [];
|
||||
yield new Promise((resolve, reject) => {
|
||||
let xhr = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"]
|
||||
.createInstance(Ci.nsIXMLHttpRequest);
|
||||
xhr.onload = () => {
|
||||
try {
|
||||
this._walkTreeForImport(xhr.responseXML);
|
||||
resolve();
|
||||
} catch(e) {
|
||||
reject(e);
|
||||
}
|
||||
};
|
||||
xhr.onabort = xhr.onerror = xhr.ontimeout = () => {
|
||||
reject(new Error("xmlhttprequest failed"));
|
||||
};
|
||||
xhr.open("GET", href);
|
||||
xhr.responseType = "document";
|
||||
xhr.overrideMimeType("text/html");
|
||||
xhr.send();
|
||||
} catch (e) {
|
||||
deferred.reject(e);
|
||||
});
|
||||
// TODO (bug 1095427) once converted to the new bookmarks API, methods will
|
||||
// yield, so this hack should not be needed anymore.
|
||||
try {
|
||||
yield Promise.all(this._importPromises);
|
||||
} finally {
|
||||
delete this._importPromises;
|
||||
}
|
||||
return deferred.promise;
|
||||
},
|
||||
|
||||
}),
|
||||
};
|
||||
|
||||
function BookmarkExporter(aBookmarksTree) {
|
||||
@ -1104,10 +1092,6 @@ BookmarkExporter.prototype = {
|
||||
},
|
||||
|
||||
_writeItem: function (aItem, aIndent) {
|
||||
// This is a workaround for "too much recursion" error, due to the fact
|
||||
// Task.jsm still uses old on-same-tick promises. It may be removed as
|
||||
// soon as bug 887923 is fixed.
|
||||
yield promiseSoon();
|
||||
let uri = null;
|
||||
try {
|
||||
uri = NetUtil.newURI(aItem.uri);
|
||||
@ -1121,14 +1105,11 @@ BookmarkExporter.prototype = {
|
||||
this._writeDateAttributes(aItem);
|
||||
yield this._writeFaviconAttribute(aItem);
|
||||
|
||||
let keyword = PlacesUtils.bookmarks.getKeywordForBookmark(aItem.id);
|
||||
if (aItem.keyword)
|
||||
this._writeAttribute("SHORTCUTURL", escapeHtmlEntities(keyword));
|
||||
|
||||
let postDataAnno = aItem.annos &&
|
||||
aItem.annos.find(anno => anno.name == PlacesUtils.POST_DATA_ANNO);
|
||||
if (postDataAnno)
|
||||
this._writeAttribute("POST_DATA", escapeHtmlEntities(postDataAnno.value));
|
||||
if (aItem.keyword) {
|
||||
this._writeAttribute("SHORTCUTURL", escapeHtmlEntities(aItem.keyword));
|
||||
if (aItem.postData)
|
||||
this._writeAttribute("POST_DATA", escapeHtmlEntities(aItem.postData));
|
||||
}
|
||||
|
||||
if (aItem.annos && aItem.annos.some(anno => anno.name == LOAD_IN_SIDEBAR_ANNO))
|
||||
this._writeAttribute("WEB_PANEL", "true");
|
||||
|
@ -14,7 +14,7 @@ Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/NetUtil.jsm");
|
||||
Cu.import("resource://gre/modules/osfile.jsm");
|
||||
Cu.import("resource://gre/modules/PlacesUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Promise.jsm");
|
||||
Cu.import("resource://gre/modules/PromiseUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Task.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "PlacesBackups",
|
||||
@ -188,47 +188,35 @@ BookmarkImporter.prototype = {
|
||||
* @resolves When the new bookmarks have been created.
|
||||
* @rejects JavaScript exception.
|
||||
*/
|
||||
importFromURL: function BI_importFromURL(aSpec) {
|
||||
let deferred = Promise.defer();
|
||||
|
||||
let streamObserver = {
|
||||
onStreamComplete: function (aLoader, aContext, aStatus, aLength,
|
||||
aResult) {
|
||||
let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"].
|
||||
createInstance(Ci.nsIScriptableUnicodeConverter);
|
||||
converter.charset = "UTF-8";
|
||||
|
||||
try {
|
||||
let jsonString = converter.convertFromByteArray(aResult,
|
||||
aResult.length);
|
||||
deferred.resolve(this.importFromJSON(jsonString));
|
||||
} catch (ex) {
|
||||
Cu.reportError("Failed to import from URL: " + ex);
|
||||
deferred.reject(ex);
|
||||
throw ex;
|
||||
importFromURL(spec) {
|
||||
return new Promise((resolve, reject) => {
|
||||
let streamObserver = {
|
||||
onStreamComplete: (aLoader, aContext, aStatus, aLength, aResult) => {
|
||||
let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"].
|
||||
createInstance(Ci.nsIScriptableUnicodeConverter);
|
||||
converter.charset = "UTF-8";
|
||||
try {
|
||||
let jsonString = converter.convertFromByteArray(aResult,
|
||||
aResult.length);
|
||||
resolve(this.importFromJSON(jsonString));
|
||||
} catch (ex) {
|
||||
Cu.reportError("Failed to import from URL: " + ex);
|
||||
reject(ex);
|
||||
}
|
||||
}
|
||||
}.bind(this)
|
||||
};
|
||||
|
||||
try {
|
||||
var uri = NetUtil.newURI(aSpec);
|
||||
let principal = Services.scriptSecurityManager.getNoAppCodebasePrincipal(uri);
|
||||
let channel = Services.io.newChannelFromURI2(uri,
|
||||
null, // aLoadingNode
|
||||
principal,
|
||||
null, // aTriggeringPrincipal
|
||||
Ci.nsILoadInfo.SEC_NORMAL,
|
||||
Ci.nsIContentPolicy.TYPE_DATAREQUEST);
|
||||
let streamLoader = Cc["@mozilla.org/network/stream-loader;1"].
|
||||
createInstance(Ci.nsIStreamLoader);
|
||||
};
|
||||
|
||||
let uri = NetUtil.newURI(spec);
|
||||
let channel = NetUtil.newChannel({
|
||||
uri,
|
||||
loadingPrincipal: Services.scriptSecurityManager.getNoAppCodebasePrincipal(uri),
|
||||
contentPolicyType: Ci.nsIContentPolicy.TYPE_DATAREQUEST
|
||||
});
|
||||
let streamLoader = Cc["@mozilla.org/network/stream-loader;1"]
|
||||
.createInstance(Ci.nsIStreamLoader);
|
||||
streamLoader.init(streamObserver);
|
||||
channel.asyncOpen(streamLoader, channel);
|
||||
} catch (ex) {
|
||||
deferred.reject(ex);
|
||||
}
|
||||
|
||||
return deferred.promise;
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
@ -256,8 +244,9 @@ BookmarkImporter.prototype = {
|
||||
* @param aString
|
||||
* JSON string of serialized bookmark data.
|
||||
*/
|
||||
importFromJSON: function BI_importFromJSON(aString) {
|
||||
let deferred = Promise.defer();
|
||||
importFromJSON: Task.async(function* (aString) {
|
||||
this._importPromises = [];
|
||||
let deferred = PromiseUtils.defer();
|
||||
let nodes =
|
||||
PlacesUtils.unwrapNodes(aString, PlacesUtils.TYPE_X_MOZ_PLACE_CONTAINER);
|
||||
|
||||
@ -360,8 +349,15 @@ BookmarkImporter.prototype = {
|
||||
|
||||
PlacesUtils.bookmarks.runInBatchMode(batch, null);
|
||||
}
|
||||
return deferred.promise;
|
||||
},
|
||||
yield deferred.promise;
|
||||
// TODO (bug 1095426) once converted to the new bookmarks API, methods will
|
||||
// yield, so this hack should not be needed anymore.
|
||||
try {
|
||||
yield Promise.all(this._importPromises);
|
||||
} finally {
|
||||
delete this._importPromises;
|
||||
}
|
||||
}),
|
||||
|
||||
/**
|
||||
* Takes a JSON-serialized node and inserts it into the db.
|
||||
@ -452,8 +448,18 @@ BookmarkImporter.prototype = {
|
||||
case PlacesUtils.TYPE_X_MOZ_PLACE:
|
||||
id = PlacesUtils.bookmarks.insertBookmark(
|
||||
aContainer, NetUtil.newURI(aData.uri), aIndex, aData.title);
|
||||
if (aData.keyword)
|
||||
PlacesUtils.bookmarks.setKeywordForBookmark(id, aData.keyword);
|
||||
if (aData.keyword) {
|
||||
// POST data could be set in 2 ways:
|
||||
// 1. new backups have a postData property
|
||||
// 2. old backups have an item annotation
|
||||
let postDataAnno = aData.annos &&
|
||||
aData.annos.find(anno => anno.name == PlacesUtils.POST_DATA_ANNO);
|
||||
let postData = aData.postData || (postDataAnno && postDataAnno.value);
|
||||
let kwPromise = PlacesUtils.keywords.insert({ keyword: aData.keyword,
|
||||
url: aData.uri,
|
||||
postData });
|
||||
this._importPromises.push(kwPromise);
|
||||
}
|
||||
if (aData.tags) {
|
||||
// TODO (bug 967196) the tagging service should trim by itself.
|
||||
let tags = aData.tags.split(",").map(tag => tag.trim());
|
||||
|
@ -1679,6 +1679,7 @@ this.PlacesUtils = {
|
||||
* - tags (string): csv string of the bookmark's tags.
|
||||
* - charset (string): the last known charset of the bookmark.
|
||||
* - keyword (string): the bookmark's keyword (unset if none).
|
||||
* - postData (string): the bookmark's keyword postData (unset if none).
|
||||
* - iconuri (string): the bookmark's favicon url.
|
||||
* The last four properties are not set at all if they're irrelevant (e.g.
|
||||
* |charset| is not set if no charset was previously set for the bookmark
|
||||
@ -1693,7 +1694,7 @@ this.PlacesUtils = {
|
||||
* resolved to null.
|
||||
*/
|
||||
promiseBookmarksTree: Task.async(function* (aItemGuid = "", aOptions = {}) {
|
||||
let createItemInfoObject = (aRow, aIncludeParentGuid) => {
|
||||
let createItemInfoObject = function* (aRow, aIncludeParentGuid) {
|
||||
let item = {};
|
||||
let copyProps = (...props) => {
|
||||
for (let prop of props) {
|
||||
@ -1732,9 +1733,11 @@ this.PlacesUtils = {
|
||||
// If this throws due to an invalid url, the item will be skipped.
|
||||
item.uri = NetUtil.newURI(aRow.getResultByName("url")).spec;
|
||||
// Keywords are cached, so this should be decently fast.
|
||||
let keyword = PlacesUtils.bookmarks.getKeywordForBookmark(itemId);
|
||||
if (keyword)
|
||||
item.keyword = keyword;
|
||||
let entry = yield PlacesUtils.keywords.fetch({ url: item.uri });
|
||||
if (entry) {
|
||||
item.keyword = entry.keyword;
|
||||
item.postData = entry.postData;
|
||||
}
|
||||
break;
|
||||
case Ci.nsINavBookmarksService.TYPE_FOLDER:
|
||||
item.type = PlacesUtils.TYPE_X_MOZ_PLACE_CONTAINER;
|
||||
@ -1756,7 +1759,7 @@ this.PlacesUtils = {
|
||||
break;
|
||||
}
|
||||
return item;
|
||||
};
|
||||
}.bind(this);
|
||||
|
||||
const QUERY_STR =
|
||||
`WITH RECURSIVE
|
||||
@ -1809,40 +1812,34 @@ this.PlacesUtils = {
|
||||
return exclude;
|
||||
};
|
||||
|
||||
let rootItem = null, rootItemCreationEx = null;
|
||||
let rootItem = null;
|
||||
let parentsMap = new Map();
|
||||
try {
|
||||
let conn = yield this.promiseDBConnection();
|
||||
yield conn.executeCached(QUERY_STR,
|
||||
{ tags_folder: PlacesUtils.tagsFolderId,
|
||||
charset_anno: PlacesUtils.CHARSET_ANNO,
|
||||
item_guid: aItemGuid }, (aRow) => {
|
||||
let item;
|
||||
if (!rootItem) {
|
||||
let conn = yield this.promiseDBConnection();
|
||||
let rows = yield conn.executeCached(QUERY_STR,
|
||||
{ tags_folder: PlacesUtils.tagsFolderId,
|
||||
charset_anno: PlacesUtils.CHARSET_ANNO,
|
||||
item_guid: aItemGuid });
|
||||
for (let row of rows) {
|
||||
let item;
|
||||
if (!rootItem) {
|
||||
try {
|
||||
// This is the first row.
|
||||
try {
|
||||
rootItem = item = createItemInfoObject(aRow, true);
|
||||
}
|
||||
catch(ex) {
|
||||
// If we couldn't figure out the root item, that is just as bad
|
||||
// as a failed query. Bail out.
|
||||
rootItemCreationEx = ex;
|
||||
throw StopIteration;
|
||||
}
|
||||
|
||||
Object.defineProperty(rootItem, "itemsCount",
|
||||
{ value: 1
|
||||
, writable: true
|
||||
, enumerable: false
|
||||
, configurable: false });
|
||||
rootItem = item = yield createItemInfoObject(row, true);
|
||||
Object.defineProperty(rootItem, "itemsCount", { value: 1
|
||||
, writable: true
|
||||
, enumerable: false
|
||||
, configurable: false });
|
||||
} catch(ex) {
|
||||
throw new Error("Failed to fetch the data for the root item " + ex);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
try {
|
||||
// Our query guarantees that we always visit parents ahead of their
|
||||
// children.
|
||||
item = createItemInfoObject(aRow, false);
|
||||
let parentGuid = aRow.getResultByName("parentGuid");
|
||||
item = yield createItemInfoObject(row, false);
|
||||
let parentGuid = row.getResultByName("parentGuid");
|
||||
if (hasExcludeItemsCallback && shouldExcludeItem(item, parentGuid))
|
||||
return;
|
||||
continue;
|
||||
|
||||
let parentItem = parentsMap.get(parentGuid);
|
||||
if ("children" in parentItem)
|
||||
@ -1851,17 +1848,15 @@ this.PlacesUtils = {
|
||||
parentItem.children = [item];
|
||||
|
||||
rootItem.itemsCount++;
|
||||
} catch(ex) {
|
||||
// This is a bogus child, report and skip it.
|
||||
Cu.reportError("Failed to fetch the data for an item " + ex);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (item.type == this.TYPE_X_MOZ_PLACE_CONTAINER)
|
||||
parentsMap.set(item.guid, item);
|
||||
});
|
||||
} catch(e) {
|
||||
throw new Error("Unable to query the database " + e);
|
||||
}
|
||||
if (rootItemCreationEx) {
|
||||
throw new Error("Failed to fetch the data for the root item" +
|
||||
rootItemCreationEx);
|
||||
if (item.type == this.TYPE_X_MOZ_PLACE_CONTAINER)
|
||||
parentsMap.set(item.guid, item);
|
||||
}
|
||||
|
||||
return rootItem;
|
||||
|
@ -1,270 +1,173 @@
|
||||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
const LOAD_IN_SIDEBAR_ANNO = "bookmarkProperties/loadInSidebar";
|
||||
const DESCRIPTION_ANNO = "bookmarkProperties/description";
|
||||
const POST_DATA_ANNO = "bookmarkProperties/POSTData";
|
||||
|
||||
do_check_eq(typeof PlacesUtils, "object");
|
||||
|
||||
// main
|
||||
function run_test() {
|
||||
do_test_pending();
|
||||
|
||||
/*
|
||||
HTML+FEATURES SUMMARY:
|
||||
- import legacy bookmarks
|
||||
- export as json, import, test (tests integrity of html > json)
|
||||
- export as html, import, test (tests integrity of json > html)
|
||||
|
||||
BACKUP/RESTORE SUMMARY:
|
||||
- create a bookmark in each root
|
||||
- tag multiple URIs with multiple tags
|
||||
- export as json, import, test
|
||||
*/
|
||||
|
||||
// import the importer
|
||||
Cu.import("resource://gre/modules/BookmarkHTMLUtils.jsm");
|
||||
|
||||
// file pointer to legacy bookmarks file
|
||||
var bookmarksFileOld = OS.Path.join(do_get_cwd().path, "bookmarks.preplaces.html");
|
||||
// file pointer to a new places-exported json file
|
||||
var jsonFile = OS.Path.join(OS.Constants.Path.profileDir, "bookmarks.exported.json");
|
||||
Task.spawn(function () {
|
||||
// create bookmarks.exported.json
|
||||
if ((yield OS.File.exists(jsonFile)))
|
||||
yield OS.File.remove(jsonFile);
|
||||
|
||||
// Test importing a pre-Places canonical bookmarks file.
|
||||
// 1. import bookmarks.preplaces.html
|
||||
// Note: we do not empty the db before this import to catch bugs like 380999
|
||||
try {
|
||||
BookmarkHTMLUtils.importFromFile(bookmarksFileOld, true)
|
||||
.then(after_import, do_report_unexpected_exception);
|
||||
} catch(ex) { do_throw("couldn't import legacy bookmarks file: " + ex); }
|
||||
});
|
||||
|
||||
function after_import() {
|
||||
populate();
|
||||
|
||||
// 2. run the test-suite
|
||||
Task.spawn(function() {
|
||||
yield validate();
|
||||
yield PlacesTestUtils.promiseAsyncUpdates();
|
||||
|
||||
// Test exporting a Places canonical json file.
|
||||
// 1. export to bookmarks.exported.json
|
||||
try {
|
||||
yield BookmarkJSONUtils.exportToFile(jsonFile);
|
||||
} catch(ex) { do_throw("couldn't export to file: " + ex); }
|
||||
LOG("exported json");
|
||||
|
||||
// 2. empty bookmarks db
|
||||
// 3. import bookmarks.exported.json
|
||||
try {
|
||||
yield BookmarkJSONUtils.importFromFile(jsonFile, true);
|
||||
} catch(ex) { do_throw("couldn't import the exported file: " + ex); }
|
||||
LOG("imported json");
|
||||
|
||||
// 4. run the test-suite
|
||||
yield validate();
|
||||
LOG("validated import");
|
||||
|
||||
yield PlacesTestUtils.promiseAsyncUpdates();
|
||||
do_test_finished();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
var tagData = [
|
||||
let tagData = [
|
||||
{ uri: uri("http://slint.us"), tags: ["indie", "kentucky", "music"] },
|
||||
{ uri: uri("http://en.wikipedia.org/wiki/Diplodocus"), tags: ["dinosaur", "dj", "rad word"] }
|
||||
];
|
||||
|
||||
var bookmarkData = [
|
||||
let bookmarkData = [
|
||||
{ uri: uri("http://slint.us"), title: "indie, kentucky, music" },
|
||||
{ uri: uri("http://en.wikipedia.org/wiki/Diplodocus"), title: "dinosaur, dj, rad word" }
|
||||
];
|
||||
|
||||
/*
|
||||
populate data in each folder
|
||||
(menu is populated via the html import)
|
||||
*/
|
||||
function populate() {
|
||||
// add tags
|
||||
for each(let {uri: u, tags: t} in tagData)
|
||||
PlacesUtils.tagging.tagURI(u, t);
|
||||
|
||||
// add unfiled bookmarks
|
||||
for each(let {uri: u, title: t} in bookmarkData) {
|
||||
PlacesUtils.bookmarks.insertBookmark(PlacesUtils.bookmarks.unfiledBookmarksFolder,
|
||||
u, PlacesUtils.bookmarks.DEFAULT_INDEX, t);
|
||||
}
|
||||
|
||||
// add to the toolbar
|
||||
for each(let {uri: u, title: t} in bookmarkData) {
|
||||
PlacesUtils.bookmarks.insertBookmark(PlacesUtils.bookmarks.toolbarFolder,
|
||||
u, PlacesUtils.bookmarks.DEFAULT_INDEX, t);
|
||||
}
|
||||
function run_test() {
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
function validate() {
|
||||
yield testCanonicalBookmarks();
|
||||
yield testToolbarFolder();
|
||||
/*
|
||||
HTML+FEATURES SUMMARY:
|
||||
- import legacy bookmarks
|
||||
- export as json, import, test (tests integrity of html > json)
|
||||
- export as html, import, test (tests integrity of json > html)
|
||||
|
||||
BACKUP/RESTORE SUMMARY:
|
||||
- create a bookmark in each root
|
||||
- tag multiple URIs with multiple tags
|
||||
- export as json, import, test
|
||||
*/
|
||||
add_task(function* () {
|
||||
// Remove eventual bookmarks.exported.json.
|
||||
let jsonFile = OS.Path.join(OS.Constants.Path.profileDir, "bookmarks.exported.json");
|
||||
if ((yield OS.File.exists(jsonFile)))
|
||||
yield OS.File.remove(jsonFile);
|
||||
|
||||
// Test importing a pre-Places canonical bookmarks file.
|
||||
// Note: we do not empty the db before this import to catch bugs like 380999
|
||||
let htmlFile = OS.Path.join(do_get_cwd().path, "bookmarks.preplaces.html");
|
||||
yield BookmarkHTMLUtils.importFromFile(htmlFile, true);
|
||||
|
||||
// Populate the database.
|
||||
for (let { uri, tags } of tagData) {
|
||||
PlacesUtils.tagging.tagURI(uri, tags);
|
||||
}
|
||||
for (let { uri, title } of bookmarkData) {
|
||||
yield PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
url: uri,
|
||||
title });
|
||||
}
|
||||
for (let { uri, title } of bookmarkData) {
|
||||
yield PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.toolbarGuid,
|
||||
url: uri,
|
||||
title });
|
||||
}
|
||||
|
||||
yield validate();
|
||||
|
||||
// Test exporting a Places canonical json file.
|
||||
// 1. export to bookmarks.exported.json
|
||||
yield BookmarkJSONUtils.exportToFile(jsonFile);
|
||||
do_print("exported json");
|
||||
|
||||
// 2. empty bookmarks db
|
||||
// 3. import bookmarks.exported.json
|
||||
yield BookmarkJSONUtils.importFromFile(jsonFile, true);
|
||||
do_print("imported json");
|
||||
|
||||
// 4. run the test-suite
|
||||
yield validate();
|
||||
do_print("validated import");
|
||||
});
|
||||
|
||||
function* validate() {
|
||||
yield testMenuBookmarks();
|
||||
yield testToolbarBookmarks();
|
||||
testUnfiledBookmarks();
|
||||
testTags();
|
||||
yield PlacesTestUtils.promiseAsyncUpdates();
|
||||
}
|
||||
|
||||
// Tests a bookmarks datastore that has a set of bookmarks, etc
|
||||
// that flex each supported field and feature.
|
||||
function testCanonicalBookmarks() {
|
||||
// query to see if the deleted folder and items have been imported
|
||||
var query = PlacesUtils.history.getNewQuery();
|
||||
query.setFolders([PlacesUtils.bookmarksMenuFolderId], 1);
|
||||
var result = PlacesUtils.history.executeQuery(query, PlacesUtils.history.getNewQueryOptions());
|
||||
var rootNode = result.root;
|
||||
rootNode.containerOpen = true;
|
||||
function* testMenuBookmarks() {
|
||||
let root = PlacesUtils.getFolderContents(PlacesUtils.bookmarksMenuFolderId).root;
|
||||
Assert.equal(root.childCount, 3);
|
||||
|
||||
// Count expected bookmarks in the menu root.
|
||||
do_check_eq(rootNode.childCount, 3);
|
||||
let separatorNode = root.getChild(1);
|
||||
Assert.equal(separatorNode.type, separatorNode.RESULT_TYPE_SEPARATOR);
|
||||
|
||||
// check separator
|
||||
var testSeparator = rootNode.getChild(1);
|
||||
do_check_eq(testSeparator.type, testSeparator.RESULT_TYPE_SEPARATOR);
|
||||
let folderNode = root.getChild(2);
|
||||
Assert.equal(folderNode.type, folderNode.RESULT_TYPE_FOLDER);
|
||||
Assert.equal(folderNode.title, "test");
|
||||
let folder = yield PlacesUtils.bookmarks.fetch(folderNode.bookmarkGuid);
|
||||
Assert.equal(folder.dateAdded.getTime(), 1177541020000);
|
||||
|
||||
// get test folder
|
||||
var testFolder = rootNode.getChild(2);
|
||||
do_check_eq(testFolder.type, testFolder.RESULT_TYPE_FOLDER);
|
||||
do_check_eq(testFolder.title, "test");
|
||||
Assert.equal(PlacesUtils.asQuery(folderNode).hasChildren, true);
|
||||
|
||||
/*
|
||||
// add date
|
||||
do_check_eq(PlacesUtils.bookmarks.getItemDateAdded(testFolder.itemId)/1000000, 1177541020);
|
||||
// last modified
|
||||
do_check_eq(PlacesUtils.bookmarks.getItemLastModified(testFolder.itemId)/1000000, 1177541050);
|
||||
*/
|
||||
|
||||
testFolder = testFolder.QueryInterface(Ci.nsINavHistoryQueryResultNode);
|
||||
do_check_eq(testFolder.hasChildren, true);
|
||||
// folder description
|
||||
do_check_true(PlacesUtils.annotations.itemHasAnnotation(testFolder.itemId,
|
||||
DESCRIPTION_ANNO));
|
||||
do_check_eq("folder test comment",
|
||||
PlacesUtils.annotations.getItemAnnotation(testFolder.itemId, DESCRIPTION_ANNO));
|
||||
// open test folder, and test the children
|
||||
testFolder.containerOpen = true;
|
||||
var cc = testFolder.childCount;
|
||||
// XXX Bug 380468
|
||||
// do_check_eq(cc, 2);
|
||||
do_check_eq(cc, 1);
|
||||
|
||||
// test bookmark 1
|
||||
var testBookmark1 = testFolder.getChild(0);
|
||||
// url
|
||||
do_check_eq("http://test/post", testBookmark1.uri);
|
||||
// title
|
||||
do_check_eq("test post keyword", testBookmark1.title);
|
||||
// keyword
|
||||
do_check_eq("test", PlacesUtils.bookmarks.getKeywordForBookmark(testBookmark1.itemId));
|
||||
// sidebar
|
||||
do_check_true(PlacesUtils.annotations.itemHasAnnotation(testBookmark1.itemId,
|
||||
LOAD_IN_SIDEBAR_ANNO));
|
||||
/*
|
||||
// add date
|
||||
do_check_eq(testBookmark1.dateAdded/1000000, 1177375336);
|
||||
|
||||
// last modified
|
||||
do_check_eq(testBookmark1.lastModified/1000000, 1177375423);
|
||||
*/
|
||||
|
||||
// post data
|
||||
do_check_true(PlacesUtils.annotations.itemHasAnnotation(testBookmark1.itemId, POST_DATA_ANNO));
|
||||
do_check_eq("hidden1%3Dbar&text1%3D%25s",
|
||||
PlacesUtils.annotations.getItemAnnotation(testBookmark1.itemId, POST_DATA_ANNO));
|
||||
|
||||
// last charset
|
||||
var testURI = PlacesUtils._uri(testBookmark1.uri);
|
||||
do_check_eq("ISO-8859-1", (yield PlacesUtils.getCharsetForURI(testURI)));
|
||||
|
||||
// description
|
||||
do_check_true(PlacesUtils.annotations.itemHasAnnotation(testBookmark1.itemId,
|
||||
DESCRIPTION_ANNO));
|
||||
do_check_eq("item description",
|
||||
PlacesUtils.annotations.getItemAnnotation(testBookmark1.itemId,
|
||||
Assert.equal("folder test comment",
|
||||
PlacesUtils.annotations.getItemAnnotation(folderNode.itemId,
|
||||
DESCRIPTION_ANNO));
|
||||
|
||||
// clean up
|
||||
testFolder.containerOpen = false;
|
||||
rootNode.containerOpen = false;
|
||||
// open test folder, and test the children
|
||||
folderNode.containerOpen = true;
|
||||
Assert.equal(folderNode.childCount, 1);
|
||||
|
||||
let bookmarkNode = folderNode.getChild(0);
|
||||
Assert.equal("http://test/post", bookmarkNode.uri);
|
||||
Assert.equal("test post keyword", bookmarkNode.title);
|
||||
Assert.ok(PlacesUtils.annotations.itemHasAnnotation(bookmarkNode.itemId,
|
||||
LOAD_IN_SIDEBAR_ANNO));
|
||||
Assert.equal(bookmarkNode.dateAdded, 1177375336000000);
|
||||
|
||||
let entry = yield PlacesUtils.keywords.fetch({ url: bookmarkNode.uri });
|
||||
Assert.equal("test", entry.keyword);
|
||||
Assert.equal("hidden1%3Dbar&text1%3D%25s", entry.postData);
|
||||
|
||||
Assert.equal("ISO-8859-1",
|
||||
(yield PlacesUtils.getCharsetForURI(NetUtil.newURI(bookmarkNode.uri))));
|
||||
Assert.equal("item description",
|
||||
PlacesUtils.annotations.getItemAnnotation(bookmarkNode.itemId,
|
||||
DESCRIPTION_ANNO));
|
||||
|
||||
folderNode.containerOpen = false;
|
||||
root.containerOpen = false;
|
||||
}
|
||||
|
||||
function testToolbarFolder() {
|
||||
var query = PlacesUtils.history.getNewQuery();
|
||||
query.setFolders([PlacesUtils.toolbarFolderId], 1);
|
||||
var result = PlacesUtils.history.executeQuery(query, PlacesUtils.history.getNewQueryOptions());
|
||||
|
||||
var toolbar = result.root;
|
||||
toolbar.containerOpen = true;
|
||||
function* testToolbarBookmarks() {
|
||||
let root = PlacesUtils.getFolderContents(PlacesUtils.toolbarFolderId).root;
|
||||
|
||||
// child count (add 2 for pre-existing items)
|
||||
do_check_eq(toolbar.childCount, bookmarkData.length + 2);
|
||||
Assert.equal(root.childCount, bookmarkData.length + 2);
|
||||
|
||||
// livemark
|
||||
var livemark = toolbar.getChild(1);
|
||||
// title
|
||||
do_check_eq("Latest Headlines", livemark.title);
|
||||
let livemarkNode = root.getChild(1);
|
||||
Assert.equal("Latest Headlines", livemarkNode.title);
|
||||
|
||||
let foundLivemark = yield PlacesUtils.livemarks.getLivemark({ id: livemark.itemId });
|
||||
do_check_eq("http://en-us.fxfeeds.mozilla.com/en-US/firefox/livebookmarks/",
|
||||
foundLivemark.siteURI.spec);
|
||||
do_check_eq("http://en-us.fxfeeds.mozilla.com/en-US/firefox/headlines.xml",
|
||||
foundLivemark.feedURI.spec);
|
||||
let livemark = yield PlacesUtils.livemarks.getLivemark({ id: livemarkNode.itemId });
|
||||
Assert.equal("http://en-us.fxfeeds.mozilla.com/en-US/firefox/livebookmarks/",
|
||||
livemark.siteURI.spec);
|
||||
Assert.equal("http://en-us.fxfeeds.mozilla.com/en-US/firefox/headlines.xml",
|
||||
livemark.feedURI.spec);
|
||||
|
||||
// test added bookmark data
|
||||
var child = toolbar.getChild(2);
|
||||
do_check_eq(child.uri, bookmarkData[0].uri.spec);
|
||||
do_check_eq(child.title, bookmarkData[0].title);
|
||||
child = toolbar.getChild(3);
|
||||
do_check_eq(child.uri, bookmarkData[1].uri.spec);
|
||||
do_check_eq(child.title, bookmarkData[1].title);
|
||||
let bookmarkNode = root.getChild(2);
|
||||
Assert.equal(bookmarkNode.uri, bookmarkData[0].uri.spec);
|
||||
Assert.equal(bookmarkNode.title, bookmarkData[0].title);
|
||||
bookmarkNode = root.getChild(3);
|
||||
Assert.equal(bookmarkNode.uri, bookmarkData[1].uri.spec);
|
||||
Assert.equal(bookmarkNode.title, bookmarkData[1].title);
|
||||
|
||||
toolbar.containerOpen = false;
|
||||
root.containerOpen = false;
|
||||
}
|
||||
|
||||
function testUnfiledBookmarks() {
|
||||
var query = PlacesUtils.history.getNewQuery();
|
||||
query.setFolders([PlacesUtils.unfiledBookmarksFolderId], 1);
|
||||
var result = PlacesUtils.history.executeQuery(query, PlacesUtils.history.getNewQueryOptions());
|
||||
var rootNode = result.root;
|
||||
rootNode.containerOpen = true;
|
||||
let root = PlacesUtils.getFolderContents(PlacesUtils.unfiledBookmarksFolderId).root;
|
||||
// child count (add 1 for pre-existing item)
|
||||
do_check_eq(rootNode.childCount, bookmarkData.length + 1);
|
||||
for (var i = 1; i < rootNode.childCount; i++) {
|
||||
var child = rootNode.getChild(i);
|
||||
dump(bookmarkData[i - 1].uri.spec + " == " + child.uri + "?\n");
|
||||
do_check_true(bookmarkData[i - 1].uri.equals(uri(child.uri)));
|
||||
do_check_eq(child.title, bookmarkData[i - 1].title);
|
||||
/* WTF
|
||||
Assert.equal(root.childCount, bookmarkData.length + 1);
|
||||
for (let i = 1; i < root.childCount; ++i) {
|
||||
let child = root.getChild(i);
|
||||
Assert.equal(child.uri, bookmarkData[i - 1].uri.spec);
|
||||
Assert.equal(child.title, bookmarkData[i - 1].title);
|
||||
if (child.tags)
|
||||
do_check_eq(child.tags, bookmarkData[i].title);
|
||||
*/
|
||||
Assert.equal(child.tags, bookmarkData[i - 1].title);
|
||||
}
|
||||
rootNode.containerOpen = false;
|
||||
root.containerOpen = false;
|
||||
}
|
||||
|
||||
function testTags() {
|
||||
for each(let {uri: u, tags: t} in tagData) {
|
||||
var i = 0;
|
||||
dump("test tags for " + u.spec + ": " + t + "\n");
|
||||
var tt = PlacesUtils.tagging.getTagsForURI(u);
|
||||
dump("true tags for " + u.spec + ": " + tt + "\n");
|
||||
do_check_true(t.every(function(el) {
|
||||
i++;
|
||||
return tt.indexOf(el) > -1;
|
||||
}));
|
||||
do_check_eq(i, t.length);
|
||||
for (let { uri, tags } of tagData) {
|
||||
do_print("Test tags for " + uri.spec + ": " + tags + "\n");
|
||||
let foundTags = PlacesUtils.tagging.getTagsForURI(uri);
|
||||
Assert.equal(foundTags.length, tags.length);
|
||||
Assert.ok(tags.every(tag => foundTags.indexOf(tag) != -1));
|
||||
}
|
||||
}
|
||||
|
@ -322,18 +322,21 @@ function* checkItem(aExpected, aNode)
|
||||
base64EncodeString(String.fromCharCode.apply(String, data));
|
||||
do_check_true(base64Icon == aExpected.icon);
|
||||
break;
|
||||
case "keyword":
|
||||
case "keyword": {
|
||||
let entry = yield PlacesUtils.keywords.fetch({ url: aNode.uri });
|
||||
Assert.equal(entry.keyword, aExpected.keyword);
|
||||
break;
|
||||
}
|
||||
case "sidebar":
|
||||
do_check_eq(PlacesUtils.annotations
|
||||
.itemHasAnnotation(id, LOAD_IN_SIDEBAR_ANNO),
|
||||
aExpected.sidebar);
|
||||
break;
|
||||
case "postData":
|
||||
do_check_eq(PlacesUtils.annotations
|
||||
.getItemAnnotation(id, PlacesUtils.POST_DATA_ANNO),
|
||||
aExpected.postData);
|
||||
case "postData": {
|
||||
let entry = yield PlacesUtils.keywords.fetch({ url: aNode.uri });
|
||||
Assert.equal(entry.postData, aExpected.postData);
|
||||
break;
|
||||
}
|
||||
case "charset":
|
||||
let testURI = NetUtil.newURI(aNode.uri);
|
||||
do_check_eq((yield PlacesUtils.getCharsetForURI(testURI)), aExpected.charset);
|
||||
|
@ -1,32 +1,10 @@
|
||||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/*
|
||||
* This test ensures that importing/exporting to HTML does not stop
|
||||
* if a malformed uri is found.
|
||||
*/
|
||||
|
||||
// Get Services
|
||||
var hs = Cc["@mozilla.org/browser/nav-history-service;1"].
|
||||
getService(Ci.nsINavHistoryService);
|
||||
var dbConn = hs.QueryInterface(Ci.nsPIPlacesDatabase).DBConnection;
|
||||
var bs = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
|
||||
getService(Ci.nsINavBookmarksService);
|
||||
var as = Cc["@mozilla.org/browser/annotation-service;1"].
|
||||
getService(Ci.nsIAnnotationService);
|
||||
var icos = Cc["@mozilla.org/browser/favicon-service;1"].
|
||||
getService(Ci.nsIFaviconService);
|
||||
var ps = Cc["@mozilla.org/preferences-service;1"].
|
||||
getService(Ci.nsIPrefBranch);
|
||||
|
||||
Cu.import("resource://gre/modules/BookmarkHTMLUtils.jsm");
|
||||
|
||||
const DESCRIPTION_ANNO = "bookmarkProperties/description";
|
||||
const LOAD_IN_SIDEBAR_ANNO = "bookmarkProperties/loadInSidebar";
|
||||
const POST_DATA_ANNO = "bookmarkProperties/POSTData";
|
||||
|
||||
const TEST_FAVICON_PAGE_URL = "http://en-US.www.mozilla.com/en-US/firefox/central/";
|
||||
const TEST_FAVICON_DATA_SIZE = 580;
|
||||
@ -35,27 +13,27 @@ function run_test() {
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
add_task(function test_corrupt_file() {
|
||||
add_task(function* test_corrupt_file() {
|
||||
// avoid creating the places smart folder during tests
|
||||
ps.setIntPref("browser.places.smartBookmarksVersion", -1);
|
||||
Services.prefs.setIntPref("browser.places.smartBookmarksVersion", -1);
|
||||
|
||||
// Import bookmarks from the corrupt file.
|
||||
yield BookmarkHTMLUtils.importFromFile(OS.Path.join(do_get_cwd().path, "bookmarks.corrupt.html"),
|
||||
true);
|
||||
let corruptHtml = OS.Path.join(do_get_cwd().path, "bookmarks.corrupt.html");
|
||||
yield BookmarkHTMLUtils.importFromFile(corruptHtml, true);
|
||||
|
||||
// Check that bookmarks that are not corrupt have been imported.
|
||||
yield PlacesTestUtils.promiseAsyncUpdates();
|
||||
yield database_check();
|
||||
});
|
||||
|
||||
add_task(function test_corrupt_database() {
|
||||
add_task(function* test_corrupt_database() {
|
||||
// Create corruption in the database, then export.
|
||||
var corruptItemId = bs.insertBookmark(bs.toolbarFolder,
|
||||
uri("http://test.mozilla.org"),
|
||||
bs.DEFAULT_INDEX, "We love belugas");
|
||||
var stmt = dbConn.createStatement("UPDATE moz_bookmarks SET fk = NULL WHERE id = :itemId");
|
||||
stmt.params.itemId = corruptItemId;
|
||||
stmt.execute();
|
||||
stmt.finalize();
|
||||
let corruptBookmark = yield PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.toolbarGuid,
|
||||
url: "http://test.mozilla.org",
|
||||
title: "We love belugas" });
|
||||
let db = yield PlacesUtils.promiseWrappedConnection();
|
||||
yield db.execute("UPDATE moz_bookmarks SET fk = NULL WHERE guid = :guid",
|
||||
{ guid: corruptBookmark.guid });
|
||||
|
||||
let bookmarksFile = OS.Path.join(OS.Constants.Path.profileDir, "bookmarks.exported.html");
|
||||
if ((yield OS.File.exists(bookmarksFile)))
|
||||
@ -65,6 +43,7 @@ add_task(function test_corrupt_database() {
|
||||
// Import again and check for correctness.
|
||||
remove_all_bookmarks();
|
||||
yield BookmarkHTMLUtils.importFromFile(bookmarksFile, true);
|
||||
yield PlacesTestUtils.promiseAsyncUpdates();
|
||||
yield database_check();
|
||||
});
|
||||
|
||||
@ -75,115 +54,81 @@ add_task(function test_corrupt_database() {
|
||||
* @resolves When the checks are finished.
|
||||
* @rejects Never.
|
||||
*/
|
||||
function database_check() {
|
||||
return Task.spawn(function() {
|
||||
// BOOKMARKS MENU
|
||||
var query = hs.getNewQuery();
|
||||
query.setFolders([bs.bookmarksMenuFolder], 1);
|
||||
var options = hs.getNewQueryOptions();
|
||||
options.queryType = Ci.nsINavHistoryQueryOptions.QUERY_TYPE_BOOKMARKS;
|
||||
var result = hs.executeQuery(query, options);
|
||||
var rootNode = result.root;
|
||||
rootNode.containerOpen = true;
|
||||
do_check_eq(rootNode.childCount, 2);
|
||||
let database_check = Task.async(function* () {
|
||||
// BOOKMARKS MENU
|
||||
let root = PlacesUtils.getFolderContents(PlacesUtils.bookmarksMenuFolderId).root;
|
||||
Assert.equal(root.childCount, 2);
|
||||
|
||||
// get test folder
|
||||
var testFolder = rootNode.getChild(1);
|
||||
do_check_eq(testFolder.type, testFolder.RESULT_TYPE_FOLDER);
|
||||
do_check_eq(testFolder.title, "test");
|
||||
// add date
|
||||
do_check_eq(bs.getItemDateAdded(testFolder.itemId)/1000000, 1177541020);
|
||||
// last modified
|
||||
do_check_eq(bs.getItemLastModified(testFolder.itemId)/1000000, 1177541050);
|
||||
testFolder = testFolder.QueryInterface(Ci.nsINavHistoryQueryResultNode);
|
||||
do_check_eq(testFolder.hasChildren, true);
|
||||
// folder description
|
||||
do_check_true(as.itemHasAnnotation(testFolder.itemId,
|
||||
DESCRIPTION_ANNO));
|
||||
do_check_eq("folder test comment",
|
||||
as.getItemAnnotation(testFolder.itemId, DESCRIPTION_ANNO));
|
||||
// open test folder, and test the children
|
||||
testFolder.containerOpen = true;
|
||||
var cc = testFolder.childCount;
|
||||
do_check_eq(cc, 1);
|
||||
let folderNode = root.getChild(1);
|
||||
Assert.equal(folderNode.type, folderNode.RESULT_TYPE_FOLDER);
|
||||
Assert.equal(folderNode.title, "test");
|
||||
Assert.equal(PlacesUtils.bookmarks.getItemDateAdded(folderNode.itemId), 1177541020000000);
|
||||
Assert.equal(PlacesUtils.bookmarks.getItemLastModified(folderNode.itemId), 1177541050000000);
|
||||
Assert.equal("folder test comment",
|
||||
PlacesUtils.annotations.getItemAnnotation(folderNode.itemId,
|
||||
DESCRIPTION_ANNO));
|
||||
// open test folder, and test the children
|
||||
PlacesUtils.asQuery(folderNode);
|
||||
Assert.equal(folderNode.hasChildren, true);
|
||||
folderNode.containerOpen = true;
|
||||
Assert.equal(folderNode.childCount, 1);
|
||||
|
||||
// test bookmark 1
|
||||
var testBookmark1 = testFolder.getChild(0);
|
||||
// url
|
||||
do_check_eq("http://test/post", testBookmark1.uri);
|
||||
// title
|
||||
do_check_eq("test post keyword", testBookmark1.title);
|
||||
// keyword
|
||||
do_check_eq("test", bs.getKeywordForBookmark(testBookmark1.itemId));
|
||||
// sidebar
|
||||
do_check_true(as.itemHasAnnotation(testBookmark1.itemId,
|
||||
LOAD_IN_SIDEBAR_ANNO));
|
||||
// add date
|
||||
do_check_eq(testBookmark1.dateAdded/1000000, 1177375336);
|
||||
// last modified
|
||||
do_check_eq(testBookmark1.lastModified/1000000, 1177375423);
|
||||
// post data
|
||||
do_check_true(as.itemHasAnnotation(testBookmark1.itemId,
|
||||
POST_DATA_ANNO));
|
||||
do_check_eq("hidden1%3Dbar&text1%3D%25s",
|
||||
as.getItemAnnotation(testBookmark1.itemId, POST_DATA_ANNO));
|
||||
// last charset
|
||||
var testURI = uri(testBookmark1.uri);
|
||||
do_check_eq((yield PlacesUtils.getCharsetForURI(testURI)), "ISO-8859-1");
|
||||
let bookmarkNode = folderNode.getChild(0);
|
||||
Assert.equal("http://test/post", bookmarkNode.uri);
|
||||
Assert.equal("test post keyword", bookmarkNode.title);
|
||||
|
||||
// description
|
||||
do_check_true(as.itemHasAnnotation(testBookmark1.itemId,
|
||||
DESCRIPTION_ANNO));
|
||||
do_check_eq("item description",
|
||||
as.getItemAnnotation(testBookmark1.itemId,
|
||||
DESCRIPTION_ANNO));
|
||||
let entry = yield PlacesUtils.keywords.fetch({ url: bookmarkNode.uri });
|
||||
Assert.equal("test", entry.keyword);
|
||||
Assert.equal("hidden1%3Dbar&text1%3D%25s", entry.postData);
|
||||
|
||||
// clean up
|
||||
testFolder.containerOpen = false;
|
||||
rootNode.containerOpen = false;
|
||||
Assert.ok(PlacesUtils.annotations.itemHasAnnotation(bookmarkNode.itemId,
|
||||
LOAD_IN_SIDEBAR_ANNO));
|
||||
Assert.equal(bookmarkNode.dateAdded, 1177375336000000);
|
||||
Assert.equal(bookmarkNode.lastModified, 1177375423000000);
|
||||
|
||||
// BOOKMARKS TOOLBAR
|
||||
query.setFolders([bs.toolbarFolder], 1);
|
||||
result = hs.executeQuery(query, hs.getNewQueryOptions());
|
||||
var toolbar = result.root;
|
||||
toolbar.containerOpen = true;
|
||||
do_check_eq(toolbar.childCount, 3);
|
||||
Assert.equal((yield PlacesUtils.getCharsetForURI(NetUtil.newURI(bookmarkNode.uri))),
|
||||
"ISO-8859-1");
|
||||
|
||||
// livemark
|
||||
var livemark = toolbar.getChild(1);
|
||||
// title
|
||||
do_check_eq("Latest Headlines", livemark.title);
|
||||
Assert.equal("item description",
|
||||
PlacesUtils.annotations.getItemAnnotation(bookmarkNode.itemId,
|
||||
DESCRIPTION_ANNO));
|
||||
|
||||
let foundLivemark = yield PlacesUtils.livemarks.getLivemark({ id: livemark.itemId });
|
||||
do_check_eq("http://en-us.fxfeeds.mozilla.com/en-US/firefox/livebookmarks/",
|
||||
foundLivemark.siteURI.spec);
|
||||
do_check_eq("http://en-us.fxfeeds.mozilla.com/en-US/firefox/headlines.xml",
|
||||
foundLivemark.feedURI.spec);
|
||||
// clean up
|
||||
folderNode.containerOpen = false;
|
||||
root.containerOpen = false;
|
||||
|
||||
// cleanup
|
||||
toolbar.containerOpen = false;
|
||||
// BOOKMARKS TOOLBAR
|
||||
root = PlacesUtils.getFolderContents(PlacesUtils.toolbarFolderId).root;
|
||||
Assert.equal(root.childCount, 3);
|
||||
|
||||
// UNFILED BOOKMARKS
|
||||
query.setFolders([bs.unfiledBookmarksFolder], 1);
|
||||
result = hs.executeQuery(query, hs.getNewQueryOptions());
|
||||
var unfiledBookmarks = result.root;
|
||||
unfiledBookmarks.containerOpen = true;
|
||||
do_check_eq(unfiledBookmarks.childCount, 1);
|
||||
unfiledBookmarks.containerOpen = false;
|
||||
let livemarkNode = root.getChild(1);
|
||||
Assert.equal("Latest Headlines", livemarkNode.title);
|
||||
|
||||
// favicons
|
||||
let deferGetFaviconData = Promise.defer();
|
||||
icos.getFaviconDataForPage(uri(TEST_FAVICON_PAGE_URL),
|
||||
function DC_onComplete(aURI, aDataLen, aData, aMimeType) {
|
||||
let livemark = yield PlacesUtils.livemarks.getLivemark({ id: livemarkNode.itemId });
|
||||
Assert.equal("http://en-us.fxfeeds.mozilla.com/en-US/firefox/livebookmarks/",
|
||||
livemark.siteURI.spec);
|
||||
Assert.equal("http://en-us.fxfeeds.mozilla.com/en-US/firefox/headlines.xml",
|
||||
livemark.feedURI.spec);
|
||||
|
||||
// cleanup
|
||||
root.containerOpen = false;
|
||||
|
||||
// UNFILED BOOKMARKS
|
||||
root = PlacesUtils.getFolderContents(PlacesUtils.unfiledBookmarksFolderId).root;
|
||||
Assert.equal(root.childCount, 1);
|
||||
root.containerOpen = false;
|
||||
|
||||
// favicons
|
||||
yield new Promise(resolve => {
|
||||
PlacesUtils.favicons.getFaviconDataForPage(uri(TEST_FAVICON_PAGE_URL),
|
||||
(aURI, aDataLen, aData, aMimeType) => {
|
||||
// aURI should never be null when aDataLen > 0.
|
||||
do_check_neq(aURI, null);
|
||||
Assert.notEqual(aURI, null);
|
||||
// Favicon data is stored in the bookmarks file as a "data:" URI. For
|
||||
// simplicity, instead of converting the data we receive to a "data:" URI
|
||||
// and comparing it, we just check the data size.
|
||||
do_check_eq(TEST_FAVICON_DATA_SIZE, aDataLen);
|
||||
deferGetFaviconData.resolve();
|
||||
}
|
||||
);
|
||||
yield deferGetFaviconData.promise;
|
||||
Assert.equal(TEST_FAVICON_DATA_SIZE, aDataLen);
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
@ -182,16 +182,20 @@ function checkItem(aExpected, aNode) {
|
||||
base64EncodeString(String.fromCharCode.apply(String, data));
|
||||
do_check_true(base64Icon == aExpected.icon);
|
||||
break;
|
||||
case "keyword":
|
||||
case "keyword": {
|
||||
let entry = yield PlacesUtils.keywords.fetch({ url: aNode.uri });
|
||||
Assert.equal(entry.keyword, aExpected.keyword);
|
||||
break;
|
||||
}
|
||||
case "sidebar":
|
||||
do_check_eq(PlacesUtils.annotations.itemHasAnnotation(
|
||||
id, LOAD_IN_SIDEBAR_ANNO), aExpected.sidebar);
|
||||
break;
|
||||
case "postData":
|
||||
do_check_eq(PlacesUtils.annotations.getItemAnnotation(
|
||||
id, PlacesUtils.POST_DATA_ANNO), aExpected.postData);
|
||||
case "postData": {
|
||||
let entry = yield PlacesUtils.keywords.fetch({ url: aNode.uri });
|
||||
Assert.equal(entry.postData, aExpected.postData);
|
||||
break;
|
||||
}
|
||||
case "charset":
|
||||
let testURI = NetUtil.newURI(aNode.uri);
|
||||
do_check_eq((yield PlacesUtils.getCharsetForURI(testURI)), aExpected.charset);
|
||||
|
@ -729,7 +729,6 @@ add_test(function test_edit_postData() {
|
||||
}
|
||||
|
||||
Task.spawn(function* () {
|
||||
const POST_DATA_ANNO = "bookmarkProperties/POSTData";
|
||||
let postData = "post-test_edit_postData";
|
||||
let testURI = NetUtil.newURI("http://test_edit_postData.com");
|
||||
|
||||
|
@ -3106,7 +3106,7 @@ var WalkerFront = exports.WalkerFront = protocol.FrontClass(WalkerActor, {
|
||||
*/
|
||||
onMutations: protocol.preEvent("new-mutations", function() {
|
||||
// Fetch and process the mutations.
|
||||
this.getMutations({cleanup: this.autoCleanup}).then(null, console.error);
|
||||
this.getMutations({cleanup: this.autoCleanup}).catch(() => {});
|
||||
}),
|
||||
|
||||
isLocal: function() {
|
||||
|
Loading…
Reference in New Issue
Block a user