зеркало из https://github.com/mozilla/gecko-dev.git
Merge m-c to inbound a=merge CLOSED TREE
This commit is contained in:
Коммит
afda1781f5
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 1148639 - libvpx update moved a bunch of files around.
|
||||
Bug 1155718: Merge Bluetooth v1/v2 files for all simple cases
|
||||
|
||||
This patch set renames 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="cb41d8421da5dc4f16ea566ea2917a9b7f828154"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="a8e4f95dce9db727dda5d408b038f97fb4296557"/>
|
||||
<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,10 +19,10 @@
|
|||
<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="cb41d8421da5dc4f16ea566ea2917a9b7f828154"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="a8e4f95dce9db727dda5d408b038f97fb4296557"/>
|
||||
<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"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="9a9797062c6001d6346504161c51187a2968466b"/>
|
||||
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="46e1877c0d88b085f7ebc5f432d5bb8f1e2d1f3b"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="34ea6163f9f0e0122fb0bb03607eccdca31ced7a"/>
|
||||
|
|
|
@ -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="cb41d8421da5dc4f16ea566ea2917a9b7f828154"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="a8e4f95dce9db727dda5d408b038f97fb4296557"/>
|
||||
<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="c7d4045742862a7cf3f0074902ebc7d1b339b0ee"/>
|
||||
|
|
|
@ -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="cb41d8421da5dc4f16ea566ea2917a9b7f828154"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="a8e4f95dce9db727dda5d408b038f97fb4296557"/>
|
||||
<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"/>
|
||||
|
@ -131,7 +131,7 @@
|
|||
<project name="device_generic_goldfish" path="device/generic/goldfish" remote="b2g" revision="f5f7fa2fc26b96d2cbd0af4569c0036fe034bb43"/>
|
||||
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="fbd2becab3825c49e756db5149552f85049c66e2"/>
|
||||
<project name="platform/external/wpa_supplicant_8" path="external/wpa_supplicant_8" revision="694cecf256122d0cb3b6a1a4efb4b5c7401db223"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="c0bf1eec60644abbc5e72c251c15092b4c71b6a9"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="0c2ffe181ca64a6cad9c5f93ddea623f080c6434"/>
|
||||
<project name="platform/development" path="development" revision="5968ff4e13e0d696ad8d972281fc27ae5a12829b"/>
|
||||
<project name="android-sdk" path="sdk" remote="b2g" revision="0951179277915335251c5e11d242e4e1a8c2236f"/>
|
||||
<project name="darwinstreamingserver" path="system/darwinstreamingserver" remote="b2g" revision="cf85968c7f85e0ec36e72c87ceb4837a943b8af6"/>
|
||||
|
|
|
@ -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="cb41d8421da5dc4f16ea566ea2917a9b7f828154"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="a8e4f95dce9db727dda5d408b038f97fb4296557"/>
|
||||
<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,10 +19,10 @@
|
|||
<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="cb41d8421da5dc4f16ea566ea2917a9b7f828154"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="a8e4f95dce9db727dda5d408b038f97fb4296557"/>
|
||||
<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"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="9a9797062c6001d6346504161c51187a2968466b"/>
|
||||
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="46e1877c0d88b085f7ebc5f432d5bb8f1e2d1f3b"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="34ea6163f9f0e0122fb0bb03607eccdca31ced7a"/>
|
||||
|
|
|
@ -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="cb41d8421da5dc4f16ea566ea2917a9b7f828154"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="a8e4f95dce9db727dda5d408b038f97fb4296557"/>
|
||||
<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="cb41d8421da5dc4f16ea566ea2917a9b7f828154"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="a8e4f95dce9db727dda5d408b038f97fb4296557"/>
|
||||
<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="c7d4045742862a7cf3f0074902ebc7d1b339b0ee"/>
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
{
|
||||
"git": {
|
||||
"git_revision": "cb41d8421da5dc4f16ea566ea2917a9b7f828154",
|
||||
"git_revision": "a8e4f95dce9db727dda5d408b038f97fb4296557",
|
||||
"remote": "https://git.mozilla.org/releases/gaia.git",
|
||||
"branch": ""
|
||||
},
|
||||
"revision": "06ea3f1fb3f2706336c6b32d31663db0ec690cd9",
|
||||
"revision": "b3bc7b2c50201c1110e3f7157d6ed542e52d9355",
|
||||
"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="cb41d8421da5dc4f16ea566ea2917a9b7f828154"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="a8e4f95dce9db727dda5d408b038f97fb4296557"/>
|
||||
<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="c7d4045742862a7cf3f0074902ebc7d1b339b0ee"/>
|
||||
|
|
|
@ -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="cb41d8421da5dc4f16ea566ea2917a9b7f828154"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="a8e4f95dce9db727dda5d408b038f97fb4296557"/>
|
||||
<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"/>
|
||||
|
|
|
@ -253,7 +253,9 @@ loop.conversationViews = (function(mozL10n) {
|
|||
onClick: this._handleDecline},
|
||||
mozL10n.get("incoming_call_cancel_button")
|
||||
),
|
||||
React.createElement("div", {className: "btn-chevron", onClick: this.toggleDropdownMenu})
|
||||
React.createElement("div", {className: "btn-chevron",
|
||||
onClick: this.toggleDropdownMenu,
|
||||
ref: "menu-button"})
|
||||
),
|
||||
|
||||
React.createElement("ul", {className: dropdownMenuClassesDecline},
|
||||
|
|
|
@ -253,7 +253,9 @@ loop.conversationViews = (function(mozL10n) {
|
|||
onClick={this._handleDecline}>
|
||||
{mozL10n.get("incoming_call_cancel_button")}
|
||||
</button>
|
||||
<div className="btn-chevron" onClick={this.toggleDropdownMenu} />
|
||||
<div className="btn-chevron"
|
||||
onClick={this.toggleDropdownMenu}
|
||||
ref="menu-button" />
|
||||
</div>
|
||||
|
||||
<ul className={dropdownMenuClassesDecline}>
|
||||
|
|
|
@ -163,7 +163,7 @@ loop.panel = (function(_, mozL10n) {
|
|||
|
||||
return (
|
||||
React.createElement("div", {className: "dropdown"},
|
||||
React.createElement("p", {className: "dnd-status", onClick: this.showDropdownMenu},
|
||||
React.createElement("p", {className: "dnd-status", onClick: this.toggleDropdownMenu, ref: "menu-button"},
|
||||
React.createElement("span", null, availabilityText),
|
||||
React.createElement("i", {className: availabilityStatus})
|
||||
),
|
||||
|
@ -344,8 +344,10 @@ loop.panel = (function(_, mozL10n) {
|
|||
|
||||
return (
|
||||
React.createElement("div", {className: "settings-menu dropdown"},
|
||||
React.createElement("a", {className: "button-settings", onClick: this.showDropdownMenu,
|
||||
title: mozL10n.get("settings_menu_button_tooltip")}),
|
||||
React.createElement("a", {className: "button-settings",
|
||||
onClick: this.toggleDropdownMenu,
|
||||
title: mozL10n.get("settings_menu_button_tooltip"),
|
||||
ref: "menu-button"}),
|
||||
React.createElement("ul", {className: cx({"dropdown-menu": true, hide: !this.state.showMenu})},
|
||||
React.createElement(SettingsDropdownEntry, {label: mozL10n.get("settings_menu_item_settings"),
|
||||
onClick: this.handleClickSettingsEntry,
|
||||
|
|
|
@ -163,7 +163,7 @@ loop.panel = (function(_, mozL10n) {
|
|||
|
||||
return (
|
||||
<div className="dropdown">
|
||||
<p className="dnd-status" onClick={this.showDropdownMenu}>
|
||||
<p className="dnd-status" onClick={this.toggleDropdownMenu} ref="menu-button">
|
||||
<span>{availabilityText}</span>
|
||||
<i className={availabilityStatus}></i>
|
||||
</p>
|
||||
|
@ -344,8 +344,10 @@ loop.panel = (function(_, mozL10n) {
|
|||
|
||||
return (
|
||||
<div className="settings-menu dropdown">
|
||||
<a className="button-settings" onClick={this.showDropdownMenu}
|
||||
title={mozL10n.get("settings_menu_button_tooltip")} />
|
||||
<a className="button-settings"
|
||||
onClick={this.toggleDropdownMenu}
|
||||
title={mozL10n.get("settings_menu_button_tooltip")}
|
||||
ref="menu-button" />
|
||||
<ul className={cx({"dropdown-menu": true, hide: !this.state.showMenu})}>
|
||||
<SettingsDropdownEntry label={mozL10n.get("settings_menu_item_settings")}
|
||||
onClick={this.handleClickSettingsEntry}
|
||||
|
|
|
@ -94,8 +94,16 @@ loop.shared.mixins = (function() {
|
|||
return {showMenu: false};
|
||||
},
|
||||
|
||||
_onBodyClick: function() {
|
||||
this.setState({showMenu: false});
|
||||
_onBodyClick: function(event) {
|
||||
var menuButton = this.refs["menu-button"] && this.refs["menu-button"].getDOMNode();
|
||||
if (this.refs.anchor) {
|
||||
menuButton = this.refs.anchor.getDOMNode();
|
||||
}
|
||||
// If a menu button/ anchor is defined and clicked on, it will be in charge
|
||||
// of hiding or showing the popup.
|
||||
if (event.target !== menuButton) {
|
||||
this.setState({ showMenu: false });
|
||||
}
|
||||
},
|
||||
|
||||
_correctMenuPosition: function() {
|
||||
|
|
|
@ -163,6 +163,7 @@ loop.shared.views = (function(_, l10n) {
|
|||
React.createElement("div", null,
|
||||
React.createElement("button", {className: screenShareClasses,
|
||||
onClick: this.handleClick,
|
||||
ref: "menu-button",
|
||||
title: this._getTitle()},
|
||||
isActive ? null : React.createElement("span", {className: "chevron"})
|
||||
),
|
||||
|
|
|
@ -163,6 +163,7 @@ loop.shared.views = (function(_, l10n) {
|
|||
<div>
|
||||
<button className={screenShareClasses}
|
||||
onClick={this.handleClick}
|
||||
ref="menu-button"
|
||||
title={this._getTitle()}>
|
||||
{isActive ? null : <span className="chevron"/>}
|
||||
</button>
|
||||
|
|
|
@ -20,6 +20,7 @@ Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
|||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/NetUtil.jsm");
|
||||
Cu.import("resource://gre/modules/FileUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Task.jsm");
|
||||
Cu.import("resource:///modules/MigrationUtils.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
|
||||
|
@ -42,29 +43,24 @@ function chromeTimeToDate(aTime)
|
|||
/**
|
||||
* Insert bookmark items into specific folder.
|
||||
*
|
||||
* @param aFolderId
|
||||
* id of folder where items will be inserted
|
||||
* @param aItems
|
||||
* @param parentGuid
|
||||
* GUID of the folder where items will be inserted
|
||||
* @param items
|
||||
* bookmark items to be inserted
|
||||
*/
|
||||
function insertBookmarkItems(aFolderId, aItems)
|
||||
{
|
||||
for (let i = 0; i < aItems.length; i++) {
|
||||
let item = aItems[i];
|
||||
|
||||
function* insertBookmarkItems(parentGuid, items) {
|
||||
for (let item of items) {
|
||||
try {
|
||||
if (item.type == "url") {
|
||||
PlacesUtils.bookmarks.insertBookmark(aFolderId,
|
||||
NetUtil.newURI(item.url),
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX,
|
||||
item.name);
|
||||
yield PlacesUtils.bookmarks.insert({
|
||||
parentGuid, url: item.url, title: item.name
|
||||
});
|
||||
} else if (item.type == "folder") {
|
||||
let newFolderId =
|
||||
PlacesUtils.bookmarks.createFolder(aFolderId,
|
||||
item.name,
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX);
|
||||
let newFolderGuid = (yield PlacesUtils.bookmarks.insert({
|
||||
parentGuid, type: PlacesUtils.bookmarks.TYPE_FOLDER, title: item.name
|
||||
})).guid;
|
||||
|
||||
insertBookmarkItems(newFolderId, item.children);
|
||||
yield insertBookmarkItems(newFolderGuid, item.children);
|
||||
}
|
||||
} catch (e) {
|
||||
Cu.reportError(e);
|
||||
|
@ -189,48 +185,51 @@ function GetBookmarksResource(aProfileFolder) {
|
|||
type: MigrationUtils.resourceTypes.BOOKMARKS,
|
||||
|
||||
migrate: function(aCallback) {
|
||||
NetUtil.asyncFetch2(bookmarksFile, MigrationUtils.wrapMigrateFunction(
|
||||
function(aInputStream, aResultCode) {
|
||||
if (!Components.isSuccessCode(aResultCode))
|
||||
throw new Error("Could not read Bookmarks file");
|
||||
|
||||
// Parse Chrome bookmark file that is JSON format
|
||||
let bookmarkJSON = NetUtil.readInputStreamToString(
|
||||
aInputStream, aInputStream.available(), { charset : "UTF-8" });
|
||||
let roots = JSON.parse(bookmarkJSON).roots;
|
||||
PlacesUtils.bookmarks.runInBatchMode({
|
||||
runBatched: function() {
|
||||
// Importing bookmark bar items
|
||||
if (roots.bookmark_bar.children &&
|
||||
roots.bookmark_bar.children.length > 0) {
|
||||
// Toolbar
|
||||
let parentId = PlacesUtils.toolbarFolderId;
|
||||
if (!MigrationUtils.isStartupMigration) {
|
||||
parentId = MigrationUtils.createImportedBookmarksFolder(
|
||||
"Chrome", parentId);
|
||||
}
|
||||
insertBookmarkItems(parentId, roots.bookmark_bar.children);
|
||||
}
|
||||
return Task.spawn(function* () {
|
||||
let jsonStream = yield new Promise(resolve =>
|
||||
NetUtil.asyncFetch({ uri: NetUtil.newURI(bookmarksFile),
|
||||
loadUsingSystemPrincipal: true
|
||||
},
|
||||
(inputStream, resultCode) => {
|
||||
if (Components.isSuccessCode(resultCode)) {
|
||||
resolve(inputStream);
|
||||
} else {
|
||||
reject(new Error("Could not read Bookmarks file"));
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
// Importing bookmark menu items
|
||||
if (roots.other.children &&
|
||||
roots.other.children.length > 0) {
|
||||
// Bookmark menu
|
||||
let parentId = PlacesUtils.bookmarksMenuFolderId;
|
||||
if (!MigrationUtils.isStartupMigration) {
|
||||
parentId = MigrationUtils.createImportedBookmarksFolder(
|
||||
"Chrome", parentId);
|
||||
}
|
||||
insertBookmarkItems(parentId, roots.other.children);
|
||||
}
|
||||
}
|
||||
}, null);
|
||||
}, aCallback),
|
||||
null, // aLoadingNode
|
||||
Services.scriptSecurityManager.getSystemPrincipal(),
|
||||
null, // aTriggeringPrincipal
|
||||
Ci.nsILoadInfo.SEC_NORMAL,
|
||||
Ci.nsIContentPolicy.TYPE_OTHER);
|
||||
// Parse Chrome bookmark file that is JSON format
|
||||
let bookmarkJSON = NetUtil.readInputStreamToString(
|
||||
jsonStream, jsonStream.available(), { charset : "UTF-8" });
|
||||
let roots = JSON.parse(bookmarkJSON).roots;
|
||||
|
||||
// Importing bookmark bar items
|
||||
if (roots.bookmark_bar.children &&
|
||||
roots.bookmark_bar.children.length > 0) {
|
||||
// Toolbar
|
||||
let parentGuid = PlacesUtils.bookmarks.toolbarGuid;
|
||||
if (!MigrationUtils.isStartupMigration) {
|
||||
parentGuid =
|
||||
yield MigrationUtils.createImportedBookmarksFolder("Chrome", parentGuid);
|
||||
}
|
||||
yield insertBookmarkItems(parentGuid, roots.bookmark_bar.children);
|
||||
}
|
||||
|
||||
// Importing bookmark menu items
|
||||
if (roots.other.children &&
|
||||
roots.other.children.length > 0) {
|
||||
// Bookmark menu
|
||||
let parentGuid = PlacesUtils.bookmarks.menuGuid;
|
||||
if (!MigrationUtils.isStartupMigration) {
|
||||
parentGuid =
|
||||
yield MigrationUtils.createImportedBookmarksFolder("Chrome", parentGuid);
|
||||
}
|
||||
yield insertBookmarkItems(parentGuid, roots.other.children);
|
||||
}
|
||||
}.bind(this)).then(() => aCallback(true),
|
||||
e => { Cu.reportError(e); aCallback(false) });
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ const kMainKey = "Software\\Microsoft\\Internet Explorer\\Main";
|
|||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/NetUtil.jsm");
|
||||
Cu.import("resource://gre/modules/Task.jsm");
|
||||
Cu.import("resource:///modules/MigrationUtils.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
|
||||
|
@ -169,23 +169,19 @@ Bookmarks.prototype = {
|
|||
},
|
||||
|
||||
migrate: function B_migrate(aCallback) {
|
||||
PlacesUtils.bookmarks.runInBatchMode({
|
||||
runBatched: (function migrateBatched() {
|
||||
// Import to the bookmarks menu.
|
||||
let destFolderId = PlacesUtils.bookmarksMenuFolderId;
|
||||
if (!MigrationUtils.isStartupMigration) {
|
||||
destFolderId =
|
||||
MigrationUtils.createImportedBookmarksFolder("IE", destFolderId);
|
||||
}
|
||||
|
||||
this._migrateFolder(this._favoritesFolder, destFolderId);
|
||||
|
||||
aCallback(true);
|
||||
}).bind(this)
|
||||
}, null);
|
||||
return Task.spawn(function* () {
|
||||
// Import to the bookmarks menu.
|
||||
let folderGuid = PlacesUtils.bookmarks.menuGuid;
|
||||
if (!MigrationUtils.isStartupMigration) {
|
||||
folderGuid =
|
||||
yield MigrationUtils.createImportedBookmarksFolder("IE", folderGuid);
|
||||
}
|
||||
yield this._migrateFolder(this._favoritesFolder, folderGuid);
|
||||
}.bind(this)).then(() => aCallback(true),
|
||||
e => { Cu.reportError(e); aCallback(false) });
|
||||
},
|
||||
|
||||
_migrateFolder: function B__migrateFolder(aSourceFolder, aDestFolderId) {
|
||||
_migrateFolder: Task.async(function* (aSourceFolder, aDestFolderGuid) {
|
||||
// TODO (bug 741993): the favorites order is stored in the Registry, at
|
||||
// HCU\Software\Microsoft\Windows\CurrentVersion\Explorer\MenuOrder\Favorites
|
||||
// Until we support it, bookmarks are imported in alphabetical order.
|
||||
|
@ -198,26 +194,28 @@ Bookmarks.prototype = {
|
|||
// Don't use isSymlink(), since it would throw for invalid
|
||||
// lnk files pointing to URLs or to unresolvable paths.
|
||||
if (entry.path == entry.target && entry.isDirectory()) {
|
||||
let destFolderId;
|
||||
let folderGuid;
|
||||
if (entry.leafName == this._toolbarFolderName &&
|
||||
entry.parent.equals(this._favoritesFolder)) {
|
||||
// Import to the bookmarks toolbar.
|
||||
destFolderId = PlacesUtils.toolbarFolderId;
|
||||
folderGuid = PlacesUtils.bookmarks.toolbarGuid;
|
||||
if (!MigrationUtils.isStartupMigration) {
|
||||
destFolderId =
|
||||
MigrationUtils.createImportedBookmarksFolder("IE", destFolderId);
|
||||
folderGuid =
|
||||
yield MigrationUtils.createImportedBookmarksFolder("IE", folderGuid);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Import to a new folder.
|
||||
destFolderId =
|
||||
PlacesUtils.bookmarks.createFolder(aDestFolderId, entry.leafName,
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX);
|
||||
folderGuid = (yield PlacesUtils.bookmarks.insert({
|
||||
type: PlacesUtils.bookmarks.TYPE_FOLDER,
|
||||
parentGuid: aDestFolderGuid,
|
||||
title: entry.leafName
|
||||
})).guid;
|
||||
}
|
||||
|
||||
if (entry.isReadable()) {
|
||||
// Recursively import the folder.
|
||||
this._migrateFolder(entry, destFolderId);
|
||||
yield this._migrateFolder(entry, folderGuid);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -230,17 +228,16 @@ Bookmarks.prototype = {
|
|||
let uri = fileHandler.readURLFile(entry);
|
||||
let title = matches[1];
|
||||
|
||||
PlacesUtils.bookmarks.insertBookmark(aDestFolderId,
|
||||
uri,
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX,
|
||||
title);
|
||||
yield PlacesUtils.bookmarks.insert({
|
||||
parentGuid: aDestFolderGuid, url: uri, title
|
||||
});
|
||||
}
|
||||
}
|
||||
} catch (ex) {
|
||||
Components.utils.reportError("Unable to import IE favorite (" + entry.leafName + "): " + ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
function History() {
|
||||
|
|
|
@ -15,11 +15,10 @@ const TOPIC_DID_IMPORT_BOOKMARKS = "initial-migration-did-import-default-bookmar
|
|||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/Task.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
|
||||
"resource://gre/modules/PlacesUtils.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
|
||||
"resource://gre/modules/NetUtil.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "BookmarkHTMLUtils",
|
||||
"resource://gre/modules/BookmarkHTMLUtils.jsm");
|
||||
|
||||
|
@ -422,23 +421,22 @@ this.MigrationUtils = Object.freeze({
|
|||
* Helper for creating a folder for imported bookmarks from a particular
|
||||
* migration source. The folder is created at the end of the given folder.
|
||||
*
|
||||
* @param aSourceNameStr
|
||||
* @param sourceNameStr
|
||||
* the source name (first letter capitalized). This is used
|
||||
* for reading the localized source name from the migration
|
||||
* bundle (e.g. if aSourceNameStr is Mosaic, this will try to read
|
||||
* sourceNameMosaic from the migration bundle).
|
||||
* @param aParentId
|
||||
* the item-id of the folder in which the new folder should be
|
||||
* created.
|
||||
* @return the item-id of the new folder.
|
||||
* @param parentGuid
|
||||
* the GUID of the folder in which the new folder should be created.
|
||||
* @return the GUID of the new folder.
|
||||
*/
|
||||
createImportedBookmarksFolder:
|
||||
function MU_createImportedBookmarksFolder(aSourceNameStr, aParentId) {
|
||||
let source = this.getLocalizedString("sourceName" + aSourceNameStr);
|
||||
let label = this.getLocalizedString("importedBookmarksFolder", [source]);
|
||||
return PlacesUtils.bookmarks.createFolder(
|
||||
aParentId, label, PlacesUtils.bookmarks.DEFAULT_INDEX);
|
||||
},
|
||||
createImportedBookmarksFolder: Task.async(function* (sourceNameStr, parentGuid) {
|
||||
let source = this.getLocalizedString("sourceName" + sourceNameStr);
|
||||
let title = this.getLocalizedString("importedBookmarksFolder", [source]);
|
||||
return (yield PlacesUtils.bookmarks.insert({
|
||||
type: PlacesUtils.bookmarks.TYPE_FOLDER, parentGuid, title
|
||||
})).guid;
|
||||
}),
|
||||
|
||||
get _migrators() {
|
||||
return gMigrators ? gMigrators : gMigrators = new Map();
|
||||
|
|
|
@ -32,23 +32,21 @@ Bookmarks.prototype = {
|
|||
type: MigrationUtils.resourceTypes.BOOKMARKS,
|
||||
|
||||
migrate: function B_migrate(aCallback) {
|
||||
PropertyListUtils.read(this._file,
|
||||
MigrationUtils.wrapMigrateFunction(function migrateBookmarks(aDict) {
|
||||
if (!aDict)
|
||||
throw new Error("Could not read Bookmarks.plist");
|
||||
return Task.spawn(function* () {
|
||||
let dict = yield new Promise(resolve =>
|
||||
PropertyListUtils.read(this._file, resolve)
|
||||
);
|
||||
if (!dict)
|
||||
throw new Error("Could not read Bookmarks.plist");
|
||||
let children = dict.get("Children");
|
||||
if (!children)
|
||||
throw new Error("Invalid Bookmarks.plist format");
|
||||
|
||||
let children = aDict.get("Children");;
|
||||
if (!children)
|
||||
throw new Error("Invalid Bookmarks.plist format");
|
||||
|
||||
PlacesUtils.bookmarks.runInBatchMode({
|
||||
runBatched: function() {
|
||||
let collection = aDict.get("Title") == "com.apple.ReadingList" ?
|
||||
this.READING_LIST_COLLECTION : this.ROOT_COLLECTION;
|
||||
this._migrateCollection(children, collection);
|
||||
}.bind(this)
|
||||
}, null);
|
||||
}.bind(this), aCallback));
|
||||
let collection = dict.get("Title") == "com.apple.ReadingList" ?
|
||||
this.READING_LIST_COLLECTION : this.ROOT_COLLECTION;
|
||||
yield this._migrateCollection(children, collection);
|
||||
}.bind(this)).then(() => aCallback(true),
|
||||
e => { Cu.reportError(e); aCallback(false) });
|
||||
},
|
||||
|
||||
// Bookmarks collections in Safari. Constants for migrateCollection.
|
||||
|
@ -65,7 +63,7 @@ Bookmarks.prototype = {
|
|||
* @param aCollection
|
||||
* one of the values above.
|
||||
*/
|
||||
_migrateCollection: function B__migrateCollection(aEntries, aCollection) {
|
||||
_migrateCollection: Task.async(function* (aEntries, aCollection) {
|
||||
// A collection of bookmarks in Safari resembles places roots. In the
|
||||
// property list files (Bookmarks.plist, ReadingList.plist) they are
|
||||
// stored as regular bookmarks folders, and thus can only be distinguished
|
||||
|
@ -79,11 +77,11 @@ Bookmarks.prototype = {
|
|||
let title = entry.get("Title");
|
||||
let children = entry.get("Children");
|
||||
if (title == "BookmarksBar")
|
||||
this._migrateCollection(children, this.TOOLBAR_COLLECTION);
|
||||
yield this._migrateCollection(children, this.TOOLBAR_COLLECTION);
|
||||
else if (title == "BookmarksMenu")
|
||||
this._migrateCollection(children, this.MENU_COLLECTION);
|
||||
yield this._migrateCollection(children, this.MENU_COLLECTION);
|
||||
else if (title == "com.apple.ReadingList")
|
||||
this._migrateCollection(children, this.READING_LIST_COLLECTION);
|
||||
yield this._migrateCollection(children, this.READING_LIST_COLLECTION);
|
||||
else if (entry.get("ShouldOmitFromUI") !== true)
|
||||
entriesFiltered.push(entry);
|
||||
}
|
||||
|
@ -99,7 +97,7 @@ Bookmarks.prototype = {
|
|||
if (entriesFiltered.length == 0)
|
||||
return;
|
||||
|
||||
let folder = -1;
|
||||
let folderGuid = -1;
|
||||
switch (aCollection) {
|
||||
case this.ROOT_COLLECTION: {
|
||||
// In Safari, it is possible (though quite cumbersome) to move
|
||||
|
@ -108,22 +106,22 @@ Bookmarks.prototype = {
|
|||
// both the places root and the unfiled-bookmarks root.
|
||||
// Because the former is only an implementation detail in our UI,
|
||||
// the unfiled root seems to be the best choice.
|
||||
folder = PlacesUtils.unfiledBookmarksFolderId;
|
||||
folderGuid = PlacesUtils.bookmarks.unfiledGuid;
|
||||
break;
|
||||
}
|
||||
case this.MENU_COLLECTION: {
|
||||
folder = PlacesUtils.bookmarksMenuFolderId;
|
||||
folderGuid = PlacesUtils.bookmarks.menuGuid;
|
||||
if (!MigrationUtils.isStartupMigration) {
|
||||
folder = MigrationUtils.createImportedBookmarksFolder("Safari",
|
||||
folder);
|
||||
folderGuid =
|
||||
yield MigrationUtils.createImportedBookmarksFolder("Safari", folderGuid);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case this.TOOLBAR_COLLECTION: {
|
||||
folder = PlacesUtils.toolbarFolderId;
|
||||
folderGuid = PlacesUtils.bookmarks.toolbarGuid;
|
||||
if (!MigrationUtils.isStartupMigration) {
|
||||
folder = MigrationUtils.createImportedBookmarksFolder("Safari",
|
||||
folder);
|
||||
folderGuid =
|
||||
yield MigrationUtils.createImportedBookmarksFolder("Safari", folderGuid);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -131,51 +129,52 @@ Bookmarks.prototype = {
|
|||
// Reading list items are imported as regular bookmarks.
|
||||
// They are imported under their own folder, created either under the
|
||||
// bookmarks menu (in the case of startup migration).
|
||||
folder = PlacesUtils.bookmarks.createFolder(
|
||||
PlacesUtils.bookmarksMenuFolderId,
|
||||
MigrationUtils.getLocalizedString("importedSafariReadingList"),
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX);
|
||||
folderGuid = (yield PlacesUtils.bookmarks.insert({
|
||||
parentGuid: PlacesUtils.bookmarks.menuGuid,
|
||||
type: PlacesUtils.bookmarks.TYPE_FOLDER,
|
||||
title: MigrationUtils.getLocalizedString("importedSafariReadingList"),
|
||||
})).guid;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw new Error("Unexpected value for aCollection!");
|
||||
}
|
||||
if (folderGuid == -1)
|
||||
throw new Error("Invalid folder GUID");
|
||||
|
||||
this._migrateEntries(entriesFiltered, folder);
|
||||
},
|
||||
yield this._migrateEntries(entriesFiltered, folderGuid);
|
||||
}),
|
||||
|
||||
// migrate the given array of safari bookmarks to the given places
|
||||
// folder.
|
||||
_migrateEntries: function B__migrateEntries(aEntries, aFolderId) {
|
||||
for (let entry of aEntries) {
|
||||
_migrateEntries: Task.async(function* (entries, parentGuid) {
|
||||
for (let entry of entries) {
|
||||
let type = entry.get("WebBookmarkType");
|
||||
if (type == "WebBookmarkTypeList" && entry.has("Children")) {
|
||||
let title = entry.get("Title");
|
||||
let folderId = PlacesUtils.bookmarks.createFolder(
|
||||
aFolderId, title, PlacesUtils.bookmarks.DEFAULT_INDEX);
|
||||
let newFolderGuid = (yield PlacesUtils.bookmarks.insert({
|
||||
parentGuid, type: PlacesUtils.bookmarks.TYPE_FOLDER, title
|
||||
})).guid;
|
||||
|
||||
// Empty folders may not have a children array.
|
||||
if (entry.has("Children"))
|
||||
this._migrateEntries(entry.get("Children"), folderId, false);
|
||||
yield this._migrateEntries(entry.get("Children"), newFolderGuid, false);
|
||||
}
|
||||
else if (type == "WebBookmarkTypeLeaf" && entry.has("URLString")) {
|
||||
let title, uri;
|
||||
let title;
|
||||
if (entry.has("URIDictionary"))
|
||||
title = entry.get("URIDictionary").get("title");
|
||||
|
||||
try {
|
||||
uri = NetUtil.newURI(entry.get("URLString"));
|
||||
}
|
||||
catch(ex) {
|
||||
Cu.reportError("Invalid uri set for Safari bookmark: " + entry.get("URLString"));
|
||||
}
|
||||
if (uri) {
|
||||
PlacesUtils.bookmarks.insertBookmark(aFolderId, uri,
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX, title);
|
||||
yield PlacesUtils.bookmarks.insert({
|
||||
parentGuid, url: entry.get("URLString"), title
|
||||
});
|
||||
} catch(ex) {
|
||||
Cu.reportError("Invalid Safari bookmark: " + ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
function History(aHistoryFile) {
|
||||
|
|
Двоичный файл не отображается.
|
@ -35,3 +35,26 @@ function promiseMigration(migrator, resourceType) {
|
|||
migrator.migrate(resourceType, null, null);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces a directory service entry with a given nsIFile.
|
||||
*/
|
||||
function registerFakePath(key, file) {
|
||||
// Register our own provider for the Library directory.
|
||||
let provider = {
|
||||
getFile(prop, persistent) {
|
||||
persistent.value = true;
|
||||
if (prop == key) {
|
||||
return file;
|
||||
}
|
||||
throw Cr.NS_ERROR_FAILURE;
|
||||
},
|
||||
QueryInterface: XPCOMUtils.generateQI([ Ci.nsIDirectoryServiceProvider ])
|
||||
};
|
||||
Services.dirsvc.QueryInterface(Ci.nsIDirectoryService)
|
||||
.registerProvider(provider);
|
||||
do_register_cleanup(() => {
|
||||
Services.dirsvc.QueryInterface(Ci.nsIDirectoryService)
|
||||
.unregisterProvider(provider);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
add_task(function* () {
|
||||
registerFakePath("ULibDir", do_get_file("Library/"));
|
||||
|
||||
let migrator = MigrationUtils.getMigrator("safari");
|
||||
// Sanity check for the source.
|
||||
Assert.ok(migrator.sourceExists);
|
||||
|
||||
// Wait for the imported bookmarks. Check that "From Safari"
|
||||
// folders are created on the toolbar.
|
||||
let source = MigrationUtils.getLocalizedString("sourceNameSafari");
|
||||
let label = MigrationUtils.getLocalizedString("importedBookmarksFolder", [source]);
|
||||
|
||||
let expectedParents = [ PlacesUtils.toolbarFolderId ];
|
||||
|
||||
PlacesUtils.bookmarks.addObserver({
|
||||
onItemAdded(aItemId, aParentId, aIndex, aItemType, aURI, aTitle) {
|
||||
if (aTitle == label) {
|
||||
let index = expectedParents.indexOf(aParentId);
|
||||
Assert.notEqual(index, -1);
|
||||
expectedParents.splice(index, 1);
|
||||
if (expectedParents.length == 0)
|
||||
PlacesUtils.bookmarks.removeObserver(this);
|
||||
}
|
||||
},
|
||||
onBeginUpdateBatch() {},
|
||||
onEndUpdateBatch() {},
|
||||
onItemRemoved() {},
|
||||
onItemChanged() {},
|
||||
onItemVisited() {},
|
||||
onItemMoved() {},
|
||||
}, false);
|
||||
|
||||
yield promiseMigration(migrator, MigrationUtils.resourceTypes.BOOKMARKS);
|
||||
|
||||
// Check the bookmarks have been imported to all the expected parents.
|
||||
Assert.equal(expectedParents.length, 0);
|
||||
});
|
|
@ -3,9 +3,13 @@ head = head_migration.js
|
|||
tail =
|
||||
firefox-appdir = browser
|
||||
skip-if = toolkit == 'android' || toolkit == 'gonk'
|
||||
support-files =
|
||||
Library/Safari/Bookmarks.plist
|
||||
|
||||
[test_fx_fhr.js]
|
||||
[test_IE_bookmarks.js]
|
||||
skip-if = os != "win"
|
||||
[test_IE_cookies.js]
|
||||
skip-if = os != "win"
|
||||
[test_Safari_bookmarks.js]
|
||||
skip-if = os != "mac"
|
||||
|
|
|
@ -220,7 +220,13 @@ let SessionFileInternal = {
|
|||
break;
|
||||
} catch (ex if ex instanceof OS.File.Error && ex.becauseNoSuchFile) {
|
||||
exists = false;
|
||||
} catch (ex if ex instanceof OS.File.Error) {
|
||||
// The file might be inaccessible due to wrong permissions
|
||||
// or similar failures. We'll just count it as "corrupted".
|
||||
console.error("Could not read session file ", ex, ex.stack);
|
||||
corrupted = true;
|
||||
} catch (ex if ex instanceof SyntaxError) {
|
||||
console.error("Corrupt session file (invalid JSON found) ", ex, ex.stack);
|
||||
// File is corrupted, try next file
|
||||
corrupted = true;
|
||||
} finally {
|
||||
|
|
|
@ -30,7 +30,6 @@ add_task(function* init() {
|
|||
});
|
||||
|
||||
add_task(function* test_creation() {
|
||||
|
||||
let OLD_BACKUP = Path.join(Constants.Path.profileDir, "sessionstore.bak");
|
||||
let OLD_UPGRADE_BACKUP = Path.join(Constants.Path.profileDir, "sessionstore.bak-0000000");
|
||||
|
||||
|
@ -115,6 +114,27 @@ add_task(function* test_recovery() {
|
|||
yield File.writeAtomic(Paths.recoveryBackup, SOURCE);
|
||||
yield File.writeAtomic(Paths.recovery, "<Invalid JSON>");
|
||||
is((yield SessionFile.read()).source, SOURCE, "Recovered the correct source from the recovery file");
|
||||
yield SessionFile.wipe();
|
||||
});
|
||||
|
||||
add_task(function* test_recovery_inaccessible() {
|
||||
// Can't do chmod() on non-UNIX platforms, we need that for this test.
|
||||
if (AppConstants.platform != "macosx" && AppConstants.platform != "linux") {
|
||||
return;
|
||||
}
|
||||
|
||||
info("Making recovery file inaccessible, attempting to recover from recovery backup");
|
||||
let SOURCE_RECOVERY = yield promiseSource("Paths.recovery");
|
||||
let SOURCE = yield promiseSource("Paths.recoveryBackup");
|
||||
yield File.makeDir(Paths.backups);
|
||||
yield File.writeAtomic(Paths.recoveryBackup, SOURCE);
|
||||
|
||||
// Write a valid recovery file but make it inaccessible.
|
||||
yield File.writeAtomic(Paths.recovery, SOURCE_RECOVERY);
|
||||
yield File.setPermissions(Paths.recovery, { unixMode: 0 });
|
||||
|
||||
is((yield SessionFile.read()).source, SOURCE, "Recovered the correct source from the recovery file");
|
||||
yield File.setPermissions(Paths.recovery, { unixMode: 0644 });
|
||||
});
|
||||
|
||||
add_task(function* test_clean() {
|
||||
|
|
|
@ -8,14 +8,14 @@ const TEST_URI = "data:text/html;charset=utf-8,<p>Web Console test for notificat
|
|||
let test = asyncTest(function* () {
|
||||
yield loadTab(TEST_URI);
|
||||
|
||||
let gotEvents = waitForEvents();
|
||||
|
||||
let hud = yield openConsole();
|
||||
let consoleOpened = promise.defer();
|
||||
let gotEvents = waitForEvents(consoleOpened.promise);
|
||||
let hud = yield openConsole().then(() => consoleOpened.resolve());
|
||||
|
||||
yield gotEvents;
|
||||
});
|
||||
|
||||
function waitForEvents() {
|
||||
function waitForEvents(onConsoleOpened) {
|
||||
let deferred = promise.defer();
|
||||
|
||||
function webConsoleCreated(aID)
|
||||
|
@ -37,7 +37,7 @@ function waitForEvents() {
|
|||
Services.obs.removeObserver(observer, "web-console-message-created");
|
||||
ok(aID, "we have a console ID");
|
||||
is(typeof aNodeID, "string", "message node id is a string");
|
||||
executeSoon(closeConsole);
|
||||
onConsoleOpened.then(closeConsole);
|
||||
}
|
||||
|
||||
let observer = {
|
||||
|
|
|
@ -1,29 +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_bluetoothhfpmanagerbase_h__
|
||||
#define mozilla_dom_bluetooth_bluetoothhfpmanagerbase_h__
|
||||
|
||||
#include "BluetoothProfileManagerBase.h"
|
||||
|
||||
BEGIN_BLUETOOTH_NAMESPACE
|
||||
|
||||
class BluetoothHfpManagerBase : public BluetoothProfileManagerBase
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Returns true if Sco is connected.
|
||||
*/
|
||||
virtual bool IsScoConnected() = 0;
|
||||
};
|
||||
|
||||
#define BT_DECL_HFP_MGR_BASE \
|
||||
BT_DECL_PROFILE_MGR_BASE \
|
||||
virtual bool IsScoConnected() override;
|
||||
|
||||
END_BLUETOOTH_NAMESPACE
|
||||
|
||||
#endif //#ifndef mozilla_dom_bluetooth_bluetoothhfpmanagerbase_h__
|
|
@ -1,270 +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 "base/basictypes.h"
|
||||
|
||||
#include "BluetoothHidManager.h"
|
||||
|
||||
#include "BluetoothCommon.h"
|
||||
#include "BluetoothService.h"
|
||||
#include "BluetoothUtils.h"
|
||||
|
||||
#include "mozilla/dom/bluetooth/BluetoothTypes.h"
|
||||
#include "mozilla/Services.h"
|
||||
#include "mozilla/StaticPtr.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "MainThreadUtils.h"
|
||||
|
||||
using namespace mozilla;
|
||||
USING_BLUETOOTH_NAMESPACE
|
||||
|
||||
namespace {
|
||||
StaticRefPtr<BluetoothHidManager> sBluetoothHidManager;
|
||||
bool sInShutdown = false;
|
||||
} // anonymous namespace
|
||||
|
||||
NS_IMETHODIMP
|
||||
BluetoothHidManager::Observe(nsISupports* aSubject,
|
||||
const char* aTopic,
|
||||
const char16_t* aData)
|
||||
{
|
||||
MOZ_ASSERT(sBluetoothHidManager);
|
||||
|
||||
if (!strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID)) {
|
||||
HandleShutdown();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(false, "BluetoothHidManager got unexpected topic!");
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
BluetoothHidManager::BluetoothHidManager()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothHidManager::Reset()
|
||||
{
|
||||
mConnected = false;
|
||||
mController = nullptr;
|
||||
}
|
||||
|
||||
bool
|
||||
BluetoothHidManager::Init()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
|
||||
NS_ENSURE_TRUE(obs, false);
|
||||
if (NS_FAILED(obs->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false))) {
|
||||
BT_WARNING("Failed to add shutdown observer!");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
BluetoothHidManager::~BluetoothHidManager()
|
||||
{
|
||||
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
|
||||
NS_ENSURE_TRUE_VOID(obs);
|
||||
if (NS_FAILED(obs->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID))) {
|
||||
BT_WARNING("Failed to remove shutdown observer!");
|
||||
}
|
||||
}
|
||||
|
||||
//static
|
||||
BluetoothHidManager*
|
||||
BluetoothHidManager::Get()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
// If we already exist, exit early
|
||||
if (sBluetoothHidManager) {
|
||||
return sBluetoothHidManager;
|
||||
}
|
||||
|
||||
// If we're in shutdown, don't create a new instance
|
||||
NS_ENSURE_FALSE(sInShutdown, nullptr);
|
||||
|
||||
// Create a new instance, register, and return
|
||||
BluetoothHidManager* manager = new BluetoothHidManager();
|
||||
NS_ENSURE_TRUE(manager->Init(), nullptr);
|
||||
|
||||
sBluetoothHidManager = manager;
|
||||
return sBluetoothHidManager;
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothHidManager::HandleShutdown()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
sInShutdown = true;
|
||||
Disconnect(nullptr);
|
||||
sBluetoothHidManager = nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothHidManager::Connect(const nsAString& aDeviceAddress,
|
||||
BluetoothProfileController* aController)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(!aDeviceAddress.IsEmpty());
|
||||
MOZ_ASSERT(aController && !mController);
|
||||
|
||||
BluetoothService* bs = BluetoothService::Get();
|
||||
if (!bs || sInShutdown) {
|
||||
aController->NotifyCompletion(NS_LITERAL_STRING(ERR_NO_AVAILABLE_RESOURCE));
|
||||
return;
|
||||
}
|
||||
|
||||
if (mConnected) {
|
||||
aController->NotifyCompletion(NS_LITERAL_STRING(ERR_ALREADY_CONNECTED));
|
||||
return;
|
||||
}
|
||||
|
||||
mDeviceAddress = aDeviceAddress;
|
||||
mController = aController;
|
||||
|
||||
if (NS_FAILED(bs->SendInputMessage(aDeviceAddress,
|
||||
NS_LITERAL_STRING("Connect")))) {
|
||||
aController->NotifyCompletion(NS_LITERAL_STRING(ERR_NO_AVAILABLE_RESOURCE));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothHidManager::Disconnect(BluetoothProfileController* aController)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
BluetoothService* bs = BluetoothService::Get();
|
||||
if (!bs) {
|
||||
if (aController) {
|
||||
aController->NotifyCompletion(NS_LITERAL_STRING(ERR_NO_AVAILABLE_RESOURCE));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mConnected) {
|
||||
if (aController) {
|
||||
aController->NotifyCompletion(NS_LITERAL_STRING(ERR_ALREADY_DISCONNECTED));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(!mDeviceAddress.IsEmpty());
|
||||
MOZ_ASSERT(!mController);
|
||||
|
||||
mController = aController;
|
||||
|
||||
if (NS_FAILED(bs->SendInputMessage(mDeviceAddress,
|
||||
NS_LITERAL_STRING("Disconnect")))) {
|
||||
aController->NotifyCompletion(NS_LITERAL_STRING(ERR_NO_AVAILABLE_RESOURCE));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothHidManager::OnConnect(const nsAString& aErrorStr)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
/**
|
||||
* On the one hand, notify the controller that we've done for outbound
|
||||
* connections. On the other hand, we do nothing for inbound connections.
|
||||
*/
|
||||
NS_ENSURE_TRUE_VOID(mController);
|
||||
|
||||
nsRefPtr<BluetoothProfileController> controller = mController.forget();
|
||||
controller->NotifyCompletion(aErrorStr);
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothHidManager::OnDisconnect(const nsAString& aErrorStr)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
/**
|
||||
* On the one hand, notify the controller that we've done for outbound
|
||||
* connections. On the other hand, we do nothing for inbound connections.
|
||||
*/
|
||||
NS_ENSURE_TRUE_VOID(mController);
|
||||
|
||||
nsRefPtr<BluetoothProfileController> controller = mController.forget();
|
||||
controller->NotifyCompletion(aErrorStr);
|
||||
}
|
||||
|
||||
bool
|
||||
BluetoothHidManager::IsConnected()
|
||||
{
|
||||
return mConnected;
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothHidManager::HandleInputPropertyChanged(const BluetoothSignal& aSignal)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(aSignal.value().type() == BluetoothValue::TArrayOfBluetoothNamedValue);
|
||||
|
||||
const InfallibleTArray<BluetoothNamedValue>& arr =
|
||||
aSignal.value().get_ArrayOfBluetoothNamedValue();
|
||||
MOZ_ASSERT(arr.Length() == 1);
|
||||
|
||||
const nsString& name = arr[0].name();
|
||||
const BluetoothValue& value = arr[0].value();
|
||||
|
||||
if (name.EqualsLiteral("Connected")) {
|
||||
MOZ_ASSERT(value.type() == BluetoothValue::Tbool);
|
||||
MOZ_ASSERT(mConnected != value.get_bool());
|
||||
|
||||
mConnected = value.get_bool();
|
||||
NotifyStatusChanged();
|
||||
if (mConnected) {
|
||||
OnConnect(EmptyString());
|
||||
} else {
|
||||
OnDisconnect(EmptyString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothHidManager::NotifyStatusChanged()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
NS_NAMED_LITERAL_STRING(type, BLUETOOTH_HID_STATUS_CHANGED_ID);
|
||||
InfallibleTArray<BluetoothNamedValue> parameters;
|
||||
|
||||
BT_APPEND_NAMED_VALUE(parameters, "connected", mConnected);
|
||||
BT_APPEND_NAMED_VALUE(parameters, "address", mDeviceAddress);
|
||||
|
||||
BT_ENSURE_TRUE_VOID_BROADCAST_SYSMSG(type, parameters);
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothHidManager::OnGetServiceChannel(const nsAString& aDeviceAddress,
|
||||
const nsAString& aServiceUuid,
|
||||
int aChannel)
|
||||
{
|
||||
// Do nothing here as bluez acquires service channel and connects for us
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothHidManager::OnUpdateSdpRecords(const nsAString& aDeviceAddress)
|
||||
{
|
||||
// Do nothing here as bluez acquires service channel and connects for us
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothHidManager::GetAddress(nsAString& aDeviceAddress)
|
||||
{
|
||||
aDeviceAddress = mDeviceAddress;
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(BluetoothHidManager, nsIObserver)
|
|
@ -1,47 +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_bluetoothhidmanager_h__
|
||||
#define mozilla_dom_bluetooth_bluetoothhidmanager_h__
|
||||
|
||||
#include "BluetoothCommon.h"
|
||||
#include "BluetoothProfileController.h"
|
||||
#include "BluetoothProfileManagerBase.h"
|
||||
|
||||
BEGIN_BLUETOOTH_NAMESPACE
|
||||
|
||||
class BluetoothHidManager : public BluetoothProfileManagerBase
|
||||
{
|
||||
public:
|
||||
BT_DECL_PROFILE_MGR_BASE
|
||||
virtual void GetName(nsACString& aName)
|
||||
{
|
||||
aName.AssignLiteral("HID");
|
||||
}
|
||||
|
||||
static BluetoothHidManager* Get();
|
||||
virtual ~BluetoothHidManager();
|
||||
|
||||
// HID-specific functions
|
||||
void HandleInputPropertyChanged(const BluetoothSignal& aSignal);
|
||||
|
||||
private:
|
||||
BluetoothHidManager();
|
||||
bool Init();
|
||||
void Cleanup();
|
||||
void HandleShutdown();
|
||||
|
||||
void NotifyStatusChanged();
|
||||
|
||||
// data member
|
||||
bool mConnected;
|
||||
nsString mDeviceAddress;
|
||||
nsRefPtr<BluetoothProfileController> mController;
|
||||
};
|
||||
|
||||
END_BLUETOOTH_NAMESPACE
|
||||
|
||||
#endif //#ifndef mozilla_dom_bluetooth_bluetoothhidmanager_h__
|
|
@ -1,110 +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_bluetoothprofilemanagerbase_h__
|
||||
#define mozilla_dom_bluetooth_bluetoothprofilemanagerbase_h__
|
||||
|
||||
/**
|
||||
* Error Messages used in Bluetooth profiles
|
||||
*
|
||||
* These error messages would be sent to Gaia as an argument of onError event.
|
||||
*/
|
||||
#define ERR_ALREADY_CONNECTED "AlreadyConnectedError"
|
||||
#define ERR_ALREADY_DISCONNECTED "AlreadyDisconnectedError"
|
||||
#define ERR_CONNECTION_FAILED "ConnectionFailedError"
|
||||
#define ERR_DISCONNECTION_FAILED "DisconnectionFailedError"
|
||||
#define ERR_NO_AVAILABLE_RESOURCE "NoAvailableResourceError"
|
||||
#define ERR_REACHED_CONNECTION_LIMIT "ReachedConnectionLimitError"
|
||||
#define ERR_SERVICE_CHANNEL_NOT_FOUND "DeviceChannelRetrievalError"
|
||||
#define ERR_UNKNOWN_PROFILE "UnknownProfileError"
|
||||
#define ERR_OPERATION_TIMEOUT "OperationTimeout"
|
||||
|
||||
#include "BluetoothCommon.h"
|
||||
#include "nsIObserver.h"
|
||||
|
||||
BEGIN_BLUETOOTH_NAMESPACE
|
||||
class BluetoothProfileController;
|
||||
|
||||
class BluetoothProfileResultHandler
|
||||
{
|
||||
public:
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(BluetoothProfileResultHandler);
|
||||
|
||||
virtual ~BluetoothProfileResultHandler() { }
|
||||
|
||||
virtual void OnError(nsresult aResult) { }
|
||||
virtual void Init() { }
|
||||
virtual void Deinit() { }
|
||||
};
|
||||
|
||||
class BluetoothProfileManagerBase : public nsIObserver
|
||||
{
|
||||
public:
|
||||
virtual void OnGetServiceChannel(const nsAString& aDeviceAddress,
|
||||
const nsAString& aServiceUuid,
|
||||
int aChannel) = 0;
|
||||
virtual void OnUpdateSdpRecords(const nsAString& aDeviceAddress) = 0;
|
||||
|
||||
/**
|
||||
* Returns the address of the connected device.
|
||||
*/
|
||||
virtual void GetAddress(nsAString& aDeviceAddress) = 0;
|
||||
|
||||
/**
|
||||
* Returns true if the profile is connected.
|
||||
*/
|
||||
virtual bool IsConnected() = 0;
|
||||
|
||||
/**
|
||||
* Connect to a specific remote device. When it has been done, the
|
||||
* callback "OnConnect" will be invoked.
|
||||
*/
|
||||
virtual void Connect(const nsAString& aDeviceAddress,
|
||||
BluetoothProfileController* aController) = 0;
|
||||
|
||||
/**
|
||||
* Close the socket and then invoke the callback "OnDisconnect".
|
||||
*/
|
||||
virtual void Disconnect(BluetoothProfileController* aController) = 0;
|
||||
|
||||
/**
|
||||
* If it establishes/releases a connection successfully, the error string
|
||||
* will be empty. Otherwise, the error string shows the failure reason.
|
||||
*/
|
||||
virtual void OnConnect(const nsAString& aErrorStr) = 0;
|
||||
virtual void OnDisconnect(const nsAString& aErrorStr) = 0;
|
||||
|
||||
/**
|
||||
* Clean up profile resources and set mController as null.
|
||||
*/
|
||||
virtual void Reset() = 0;
|
||||
|
||||
/**
|
||||
* Returns string of profile name.
|
||||
*/
|
||||
virtual void GetName(nsACString& aName) = 0;
|
||||
};
|
||||
|
||||
#define BT_DECL_PROFILE_MGR_BASE \
|
||||
public: \
|
||||
NS_DECL_ISUPPORTS \
|
||||
NS_DECL_NSIOBSERVER \
|
||||
virtual void OnGetServiceChannel(const nsAString& aDeviceAddress, \
|
||||
const nsAString& aServiceUuid, \
|
||||
int aChannel) override; \
|
||||
virtual void OnUpdateSdpRecords(const nsAString& aDeviceAddress) override; \
|
||||
virtual void GetAddress(nsAString& aDeviceAddress) override; \
|
||||
virtual bool IsConnected() override; \
|
||||
virtual void Connect(const nsAString& aDeviceAddress, \
|
||||
BluetoothProfileController* aController) override; \
|
||||
virtual void Disconnect(BluetoothProfileController* aController) override; \
|
||||
virtual void OnConnect(const nsAString& aErrorStr) override; \
|
||||
virtual void OnDisconnect(const nsAString& AErrorStr) override; \
|
||||
virtual void Reset() override;
|
||||
|
||||
END_BLUETOOTH_NAMESPACE
|
||||
|
||||
#endif //#ifndef mozilla_dom_bluetooth_bluetoothprofilemanagerbase_h__
|
|
@ -1,134 +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_bluetoothrillistener_h__
|
||||
#define mozilla_dom_bluetooth_bluetoothrillistener_h__
|
||||
|
||||
#include "BluetoothCommon.h"
|
||||
|
||||
#include "nsAutoPtr.h"
|
||||
|
||||
#include "nsIIccService.h"
|
||||
#include "nsIMobileConnectionService.h"
|
||||
#include "nsITelephonyCallInfo.h"
|
||||
#include "nsITelephonyService.h"
|
||||
|
||||
BEGIN_BLUETOOTH_NAMESPACE
|
||||
|
||||
class BluetoothRilListener;
|
||||
|
||||
class IccListener : public nsIIccListener
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIICCLISTENER
|
||||
|
||||
IccListener() { }
|
||||
virtual ~IccListener() { }
|
||||
|
||||
bool Listen(bool aStart);
|
||||
void SetOwner(BluetoothRilListener *aOwner);
|
||||
|
||||
private:
|
||||
BluetoothRilListener* mOwner;
|
||||
};
|
||||
|
||||
class MobileConnectionListener : public nsIMobileConnectionListener
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIMOBILECONNECTIONLISTENER
|
||||
|
||||
MobileConnectionListener(uint32_t aClientId)
|
||||
: mClientId(aClientId) { }
|
||||
virtual ~MobileConnectionListener() { }
|
||||
|
||||
bool Listen(bool aStart);
|
||||
|
||||
private:
|
||||
uint32_t mClientId;
|
||||
};
|
||||
|
||||
class TelephonyListener : public nsITelephonyListener
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSITELEPHONYLISTENER
|
||||
|
||||
TelephonyListener() { }
|
||||
virtual ~TelephonyListener() { }
|
||||
|
||||
bool Listen(bool aStart);
|
||||
|
||||
private:
|
||||
nsresult HandleCallInfo(nsITelephonyCallInfo* aInfo, bool aSend);
|
||||
};
|
||||
|
||||
class BluetoothRilListener
|
||||
{
|
||||
public:
|
||||
BluetoothRilListener();
|
||||
~BluetoothRilListener();
|
||||
|
||||
/**
|
||||
* Start/Stop listening.
|
||||
*
|
||||
* @param aStart [in] whether to start/stop listening
|
||||
*/
|
||||
bool Listen(bool aStart);
|
||||
|
||||
/**
|
||||
* Be informed that certain client's service has changed.
|
||||
*
|
||||
* @param aClientId [in] the client id with service change
|
||||
* @param aRegistered [in] whether changed service is registered
|
||||
*/
|
||||
void ServiceChanged(uint32_t aClientId, bool aRegistered);
|
||||
|
||||
/**
|
||||
* Enumerate current calls.
|
||||
*/
|
||||
void EnumerateCalls();
|
||||
|
||||
/**
|
||||
* The id of client that mobile connection and icc info listeners
|
||||
* are listening to.
|
||||
*
|
||||
* mClientId equals to number of total clients (array length of
|
||||
* mobile connection listeners) if there is no available client to listen.
|
||||
*/
|
||||
uint32_t mClientId;
|
||||
|
||||
private:
|
||||
/**
|
||||
* Start/Stop listening of mobile connection and icc info.
|
||||
*
|
||||
* @param aStart [in] whether to start/stop listening
|
||||
*/
|
||||
bool ListenMobileConnAndIccInfo(bool aStart);
|
||||
|
||||
/**
|
||||
* Select available client to listen and assign mClientId.
|
||||
*
|
||||
* mClientId is assigned to number of total clients (array length of
|
||||
* mobile connection listeners) if there is no available client to listen.
|
||||
*/
|
||||
void SelectClient();
|
||||
|
||||
/**
|
||||
* Array of mobile connection listeners.
|
||||
*
|
||||
* The length equals to number of total clients.
|
||||
*/
|
||||
nsTArray<nsRefPtr<MobileConnectionListener> > mMobileConnListeners;
|
||||
|
||||
nsRefPtr<IccListener> mIccListener;
|
||||
nsRefPtr<TelephonyListener> mTelephonyListener;
|
||||
};
|
||||
|
||||
END_BLUETOOTH_NAMESPACE
|
||||
|
||||
#endif
|
|
@ -1,48 +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_BluetoothSocketObserver_h
|
||||
#define mozilla_dom_bluetooth_BluetoothSocketObserver_h
|
||||
|
||||
#include "BluetoothCommon.h"
|
||||
#include "mozilla/ipc/UnixSocket.h"
|
||||
|
||||
BEGIN_BLUETOOTH_NAMESPACE
|
||||
|
||||
class BluetoothSocket;
|
||||
|
||||
class BluetoothSocketObserver
|
||||
{
|
||||
public:
|
||||
virtual void ReceiveSocketData(
|
||||
BluetoothSocket* aSocket,
|
||||
nsAutoPtr<mozilla::ipc::UnixSocketRawData>& aMessage) = 0;
|
||||
|
||||
/**
|
||||
* A callback function which would be called when a socket connection
|
||||
* is established successfully. To be more specific, this would be called
|
||||
* when socket state changes from CONNECTING/LISTENING to CONNECTED.
|
||||
*/
|
||||
virtual void OnSocketConnectSuccess(BluetoothSocket* aSocket) = 0;
|
||||
|
||||
/**
|
||||
* A callback function which would be called when BluetoothSocket::Connect()
|
||||
* fails.
|
||||
*/
|
||||
virtual void OnSocketConnectError(BluetoothSocket* aSocket) = 0;
|
||||
|
||||
/**
|
||||
* A callback function which would be called when a socket connection
|
||||
* is dropped. To be more specific, this would be called when socket state
|
||||
* changes from CONNECTED/LISTENING to DISCONNECTED.
|
||||
*/
|
||||
virtual void OnSocketDisconnect(BluetoothSocket* aSocket) = 0;
|
||||
|
||||
};
|
||||
|
||||
END_BLUETOOTH_NAMESPACE
|
||||
|
||||
#endif
|
|
@ -1,138 +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 "ObexBase.h"
|
||||
|
||||
BEGIN_BLUETOOTH_NAMESPACE
|
||||
|
||||
int
|
||||
AppendHeaderName(uint8_t* aRetBuf, int aBufferSize, const char* aName,
|
||||
int aLength)
|
||||
{
|
||||
int headerLength = aLength + 3;
|
||||
|
||||
aRetBuf[0] = ObexHeaderId::Name;
|
||||
aRetBuf[1] = (headerLength & 0xFF00) >> 8;
|
||||
aRetBuf[2] = headerLength & 0x00FF;
|
||||
|
||||
memcpy(&aRetBuf[3], aName, (aLength < aBufferSize - 3)? aLength
|
||||
: aBufferSize - 3);
|
||||
|
||||
return headerLength;
|
||||
}
|
||||
|
||||
int
|
||||
AppendHeaderBody(uint8_t* aRetBuf, int aBufferSize, const uint8_t* aData,
|
||||
int aLength)
|
||||
{
|
||||
int headerLength = aLength + 3;
|
||||
|
||||
aRetBuf[0] = ObexHeaderId::Body;
|
||||
aRetBuf[1] = (headerLength & 0xFF00) >> 8;
|
||||
aRetBuf[2] = headerLength & 0x00FF;
|
||||
|
||||
memcpy(&aRetBuf[3], aData, (aLength < aBufferSize - 3)? aLength
|
||||
: aBufferSize - 3);
|
||||
|
||||
return headerLength;
|
||||
}
|
||||
|
||||
int
|
||||
AppendHeaderEndOfBody(uint8_t* aRetBuf)
|
||||
{
|
||||
aRetBuf[0] = ObexHeaderId::EndOfBody;
|
||||
aRetBuf[1] = 0x00;
|
||||
aRetBuf[2] = 0x03;
|
||||
|
||||
return 3;
|
||||
}
|
||||
|
||||
int
|
||||
AppendHeaderLength(uint8_t* aRetBuf, int aObjectLength)
|
||||
{
|
||||
aRetBuf[0] = ObexHeaderId::Length;
|
||||
aRetBuf[1] = (aObjectLength & 0xFF000000) >> 24;
|
||||
aRetBuf[2] = (aObjectLength & 0x00FF0000) >> 16;
|
||||
aRetBuf[3] = (aObjectLength & 0x0000FF00) >> 8;
|
||||
aRetBuf[4] = aObjectLength & 0x000000FF;
|
||||
|
||||
return 5;
|
||||
}
|
||||
|
||||
int
|
||||
AppendHeaderConnectionId(uint8_t* aRetBuf, int aConnectionId)
|
||||
{
|
||||
aRetBuf[0] = ObexHeaderId::ConnectionId;
|
||||
aRetBuf[1] = (aConnectionId & 0xFF000000) >> 24;
|
||||
aRetBuf[2] = (aConnectionId & 0x00FF0000) >> 16;
|
||||
aRetBuf[3] = (aConnectionId & 0x0000FF00) >> 8;
|
||||
aRetBuf[4] = aConnectionId & 0x000000FF;
|
||||
|
||||
return 5;
|
||||
}
|
||||
|
||||
void
|
||||
SetObexPacketInfo(uint8_t* aRetBuf, uint8_t aOpcode, int aPacketLength)
|
||||
{
|
||||
aRetBuf[0] = aOpcode;
|
||||
aRetBuf[1] = (aPacketLength & 0xFF00) >> 8;
|
||||
aRetBuf[2] = aPacketLength & 0x00FF;
|
||||
}
|
||||
|
||||
bool
|
||||
ParseHeaders(const uint8_t* aHeaderStart,
|
||||
int aTotalLength,
|
||||
ObexHeaderSet* aRetHandlerSet)
|
||||
{
|
||||
const uint8_t* ptr = aHeaderStart;
|
||||
|
||||
while (ptr - aHeaderStart < aTotalLength) {
|
||||
ObexHeaderId headerId = (ObexHeaderId)*ptr++;
|
||||
|
||||
uint16_t contentLength = 0;
|
||||
uint8_t highByte, lowByte;
|
||||
|
||||
// Defined in 2.1 OBEX Headers, IrOBEX 1.2
|
||||
switch (headerId >> 6)
|
||||
{
|
||||
case 0x00:
|
||||
// Null-terminated Unicode text, length prefixed with 2-byte
|
||||
// unsigned integer.
|
||||
case 0x01:
|
||||
// byte sequence, length prefixed with 2 byte unsigned integer.
|
||||
highByte = *ptr++;
|
||||
lowByte = *ptr++;
|
||||
contentLength = (((uint16_t)highByte << 8) | lowByte) - 3;
|
||||
break;
|
||||
|
||||
case 0x02:
|
||||
// 1 byte quantity
|
||||
contentLength = 1;
|
||||
break;
|
||||
|
||||
case 0x03:
|
||||
// 4 byte quantity
|
||||
contentLength = 4;
|
||||
break;
|
||||
}
|
||||
|
||||
// Length check to prevent from memory pollusion.
|
||||
if (ptr + contentLength > aHeaderStart + aTotalLength) {
|
||||
// Severe error occurred. We can't even believe the received data, so
|
||||
// clear all headers.
|
||||
MOZ_ASSERT(false);
|
||||
aRetHandlerSet->ClearHeaders();
|
||||
return false;
|
||||
}
|
||||
|
||||
aRetHandlerSet->AddHeader(new ObexHeader(headerId, contentLength, ptr));
|
||||
ptr += contentLength;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
END_BLUETOOTH_NAMESPACE
|
|
@ -1,272 +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_obexbase_h__
|
||||
#define mozilla_dom_bluetooth_obexbase_h__
|
||||
|
||||
#include "BluetoothCommon.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsTArray.h"
|
||||
|
||||
BEGIN_BLUETOOTH_NAMESPACE
|
||||
|
||||
const char FINAL_BIT = 0x80;
|
||||
|
||||
/*
|
||||
* Defined in section 2.1 "OBEX Headers", IrOBEX ver 1.2
|
||||
*/
|
||||
enum ObexHeaderId {
|
||||
Count = 0xC0,
|
||||
Name = 0x01,
|
||||
Type = 0x42,
|
||||
Length = 0xC3,
|
||||
TimeISO8601 = 0x44,
|
||||
Time4Byte = 0xC4,
|
||||
Description = 0x05,
|
||||
Target = 0x46,
|
||||
HTTP = 0x47,
|
||||
Body = 0x48,
|
||||
EndOfBody = 0x49,
|
||||
Who = 0x4A,
|
||||
ConnectionId = 0xCB,
|
||||
AppParameters = 0x4C,
|
||||
AuthChallenge = 0x4D,
|
||||
AuthResponse = 0x4E,
|
||||
ObjectClass = 0x4F
|
||||
};
|
||||
|
||||
/*
|
||||
* Defined in section 3.3 "OBEX Operations and Opcode definitions",
|
||||
* IrOBEX ver 1.2
|
||||
*/
|
||||
enum ObexRequestCode {
|
||||
Connect = 0x80,
|
||||
Disconnect = 0x81,
|
||||
Put = 0x02,
|
||||
PutFinal = 0x82,
|
||||
Get = 0x03,
|
||||
GetFinal = 0x83,
|
||||
SetPath = 0x85,
|
||||
Abort = 0xFF
|
||||
};
|
||||
|
||||
/*
|
||||
* Defined in section 3.2.1 "Response Code values", IrOBEX ver 1.2
|
||||
*/
|
||||
enum ObexResponseCode {
|
||||
Continue = 0x90,
|
||||
|
||||
Success = 0xA0,
|
||||
Created = 0xA1,
|
||||
Accepted = 0xA2,
|
||||
NonAuthoritativeInfo = 0xA3,
|
||||
NoContent = 0xA4,
|
||||
ResetContent = 0xA5,
|
||||
PartialContent = 0xA6,
|
||||
|
||||
MultipleChoices = 0xB0,
|
||||
MovedPermanently = 0xB1,
|
||||
MovedTemporarily = 0xB2,
|
||||
SeeOther = 0xB3,
|
||||
NotModified = 0xB4,
|
||||
UseProxy = 0xB5,
|
||||
|
||||
BadRequest = 0xC0,
|
||||
Unauthorized = 0xC1,
|
||||
PaymentRequired = 0xC2,
|
||||
Forbidden = 0xC3,
|
||||
NotFound = 0xC4,
|
||||
MethodNotAllowed = 0xC5,
|
||||
NotAcceptable = 0xC6,
|
||||
ProxyAuthenticationRequired = 0xC7,
|
||||
RequestTimeOut = 0xC8,
|
||||
Conflict = 0xC9,
|
||||
Gone = 0xCA,
|
||||
LengthRequired = 0xCB,
|
||||
PreconditionFailed = 0xCC,
|
||||
RequestedEntityTooLarge = 0xCD,
|
||||
RequestUrlTooLarge = 0xCE,
|
||||
UnsupprotedMediaType = 0xCF,
|
||||
|
||||
InternalServerError = 0xD0,
|
||||
NotImplemented = 0xD1,
|
||||
BadGateway = 0xD2,
|
||||
ServiceUnavailable = 0xD3,
|
||||
GatewayTimeout = 0xD4,
|
||||
HttpVersionNotSupported = 0xD5,
|
||||
|
||||
DatabaseFull = 0xE0,
|
||||
DatabaseLocked = 0xE1,
|
||||
};
|
||||
|
||||
class ObexHeader
|
||||
{
|
||||
public:
|
||||
ObexHeader(ObexHeaderId aId, int aDataLength, const uint8_t* aData)
|
||||
: mId(aId)
|
||||
, mDataLength(aDataLength)
|
||||
, mData(nullptr)
|
||||
{
|
||||
mData = new uint8_t[mDataLength];
|
||||
memcpy(mData, aData, aDataLength);
|
||||
}
|
||||
|
||||
~ObexHeader()
|
||||
{
|
||||
}
|
||||
|
||||
ObexHeaderId mId;
|
||||
int mDataLength;
|
||||
nsAutoArrayPtr<uint8_t> mData;
|
||||
};
|
||||
|
||||
class ObexHeaderSet
|
||||
{
|
||||
public:
|
||||
ObexHeaderSet(uint8_t aOpcode) : mOpcode(aOpcode)
|
||||
{
|
||||
}
|
||||
|
||||
~ObexHeaderSet()
|
||||
{
|
||||
}
|
||||
|
||||
void AddHeader(ObexHeader* aHeader)
|
||||
{
|
||||
mHeaders.AppendElement(aHeader);
|
||||
}
|
||||
|
||||
void GetName(nsString& aRetName) const
|
||||
{
|
||||
aRetName.Truncate();
|
||||
|
||||
int length = mHeaders.Length();
|
||||
|
||||
for (int i = 0; i < length; ++i) {
|
||||
if (mHeaders[i]->mId == ObexHeaderId::Name) {
|
||||
/*
|
||||
* According to section 2.2.2 [Name] of IrOBEX spec, we know that
|
||||
* the Name header is "a null terminated Unicode text string describing
|
||||
* the name of the object.", and that's the reason why we need to minus
|
||||
* 1 to get the real length of the file name.
|
||||
*/
|
||||
int nameLength = mHeaders[i]->mDataLength / 2 - 1;
|
||||
uint8_t* ptr = mHeaders[i]->mData.get();
|
||||
|
||||
for (int j = 0; j < nameLength; ++j) {
|
||||
char16_t c = ((((uint32_t)ptr[j * 2]) << 8) | ptr[j * 2 + 1]);
|
||||
aRetName += c;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GetContentType(nsString& aRetContentType) const
|
||||
{
|
||||
aRetContentType.Truncate();
|
||||
|
||||
int length = mHeaders.Length();
|
||||
|
||||
for (int i = 0; i < length; ++i) {
|
||||
if (mHeaders[i]->mId == ObexHeaderId::Type) {
|
||||
uint8_t* ptr = mHeaders[i]->mData.get();
|
||||
aRetContentType.AssignASCII((const char*)ptr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// @return file length, 0 means file length is unknown.
|
||||
void GetLength(uint32_t* aRetLength) const
|
||||
{
|
||||
int length = mHeaders.Length();
|
||||
*aRetLength = 0;
|
||||
|
||||
for (int i = 0; i < length; ++i) {
|
||||
if (mHeaders[i]->mId == ObexHeaderId::Length) {
|
||||
uint8_t* ptr = mHeaders[i]->mData.get();
|
||||
*aRetLength = ((uint32_t)ptr[0] << 24) |
|
||||
((uint32_t)ptr[1] << 16) |
|
||||
((uint32_t)ptr[2] << 8) |
|
||||
((uint32_t)ptr[3]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GetBodyLength(int* aRetBodyLength) const
|
||||
{
|
||||
int length = mHeaders.Length();
|
||||
*aRetBodyLength = 0;
|
||||
|
||||
for (int i = 0; i < length; ++i) {
|
||||
if (mHeaders[i]->mId == ObexHeaderId::Body ||
|
||||
mHeaders[i]->mId == ObexHeaderId::EndOfBody) {
|
||||
*aRetBodyLength = mHeaders[i]->mDataLength;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GetBody(uint8_t** aRetBody) const
|
||||
{
|
||||
int length = mHeaders.Length();
|
||||
*aRetBody = nullptr;
|
||||
|
||||
for (int i = 0; i < length; ++i) {
|
||||
if (mHeaders[i]->mId == ObexHeaderId::Body ||
|
||||
mHeaders[i]->mId == ObexHeaderId::EndOfBody) {
|
||||
uint8_t* ptr = mHeaders[i]->mData.get();
|
||||
*aRetBody = new uint8_t[mHeaders[i]->mDataLength];
|
||||
memcpy(*aRetBody, ptr, mHeaders[i]->mDataLength);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Has(ObexHeaderId aId) const
|
||||
{
|
||||
int length = mHeaders.Length();
|
||||
for (int i = 0; i < length; ++i) {
|
||||
if (mHeaders[i]->mId == aId) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void ClearHeaders()
|
||||
{
|
||||
mHeaders.Clear();
|
||||
}
|
||||
|
||||
private:
|
||||
uint8_t mOpcode;
|
||||
nsTArray<nsAutoPtr<ObexHeader> > mHeaders;
|
||||
};
|
||||
|
||||
int AppendHeaderName(uint8_t* aRetBuf, int aBufferSize, const char* aName,
|
||||
int aLength);
|
||||
int AppendHeaderBody(uint8_t* aRetBuf, int aBufferSize, const uint8_t* aData,
|
||||
int aLength);
|
||||
int AppendHeaderEndOfBody(uint8_t* aRetBuf);
|
||||
int AppendHeaderLength(uint8_t* aRetBuf, int aObjectLength);
|
||||
int AppendHeaderConnectionId(uint8_t* aRetBuf, int aConnectionId);
|
||||
void SetObexPacketInfo(uint8_t* aRetBuf, uint8_t aOpcode, int aPacketLength);
|
||||
|
||||
/**
|
||||
* @return true when the message was parsed without any error, false otherwise.
|
||||
*/
|
||||
bool ParseHeaders(const uint8_t* aHeaderStart,
|
||||
int aTotalLength,
|
||||
ObexHeaderSet* aRetHanderSet);
|
||||
|
||||
END_BLUETOOTH_NAMESPACE
|
||||
|
||||
#endif
|
|
@ -11,12 +11,19 @@ if CONFIG['MOZ_B2G_BT']:
|
|||
#
|
||||
|
||||
SOURCES += [
|
||||
'BluetoothHidManager.cpp',
|
||||
'BluetoothInterface.cpp',
|
||||
'BluetoothInterfaceHelpers.cpp',
|
||||
'BluetoothUtils.cpp',
|
||||
'BluetoothUuid.cpp'
|
||||
'BluetoothUuid.cpp',
|
||||
'ObexBase.cpp'
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_B2G_RIL']:
|
||||
SOURCES += [
|
||||
'BluetoothRilListener.cpp'
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_B2G_BT_API_V2']:
|
||||
SOURCES += [
|
||||
'bluetooth2/BluetoothAdapter.cpp',
|
||||
|
@ -27,7 +34,6 @@ if CONFIG['MOZ_B2G_BT']:
|
|||
'bluetooth2/BluetoothGattCharacteristic.cpp',
|
||||
'bluetooth2/BluetoothGattDescriptor.cpp',
|
||||
'bluetooth2/BluetoothGattService.cpp',
|
||||
'bluetooth2/BluetoothHidManager.cpp',
|
||||
'bluetooth2/BluetoothManager.cpp',
|
||||
'bluetooth2/BluetoothPairingHandle.cpp',
|
||||
'bluetooth2/BluetoothPairingListener.cpp',
|
||||
|
@ -37,12 +43,7 @@ if CONFIG['MOZ_B2G_BT']:
|
|||
'bluetooth2/ipc/BluetoothChild.cpp',
|
||||
'bluetooth2/ipc/BluetoothParent.cpp',
|
||||
'bluetooth2/ipc/BluetoothServiceChildProcess.cpp',
|
||||
'bluetooth2/ObexBase.cpp'
|
||||
]
|
||||
if CONFIG['MOZ_B2G_RIL']:
|
||||
SOURCES += [
|
||||
'bluetooth2/BluetoothRilListener.cpp',
|
||||
]
|
||||
LOCAL_INCLUDES += [
|
||||
'bluetooth2',
|
||||
'bluetooth2/ipc',
|
||||
|
@ -52,7 +53,6 @@ if CONFIG['MOZ_B2G_BT']:
|
|||
SOURCES += [
|
||||
'bluetooth1/BluetoothAdapter.cpp',
|
||||
'bluetooth1/BluetoothDevice.cpp',
|
||||
'bluetooth1/BluetoothHidManager.cpp',
|
||||
'bluetooth1/BluetoothManager.cpp',
|
||||
'bluetooth1/BluetoothProfileController.cpp',
|
||||
'bluetooth1/BluetoothPropertyContainer.cpp',
|
||||
|
@ -61,12 +61,7 @@ if CONFIG['MOZ_B2G_BT']:
|
|||
'bluetooth1/ipc/BluetoothChild.cpp',
|
||||
'bluetooth1/ipc/BluetoothParent.cpp',
|
||||
'bluetooth1/ipc/BluetoothServiceChildProcess.cpp',
|
||||
'bluetooth1/ObexBase.cpp'
|
||||
]
|
||||
if CONFIG['MOZ_B2G_RIL']:
|
||||
SOURCES += [
|
||||
'bluetooth1/BluetoothRilListener.cpp',
|
||||
]
|
||||
LOCAL_INCLUDES += [
|
||||
'bluetooth1',
|
||||
'bluetooth1/ipc',
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "nsDOMTokenList.h"
|
||||
#include "nsFocusManager.h"
|
||||
#include "nsFrame.h"
|
||||
#include "nsGenericHTMLElement.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIDocShell.h"
|
||||
#include "nsIDOMDocument.h"
|
||||
|
@ -622,10 +623,16 @@ SelectionCarets::SelectWord()
|
|||
}
|
||||
} else {
|
||||
nsIContent* focusedContent = GetFocusedContent();
|
||||
if (focusedContent && focusedContent->GetTextEditorRootContent()) {
|
||||
nsIDOMWindow* win = mPresShell->GetDocument()->GetWindow();
|
||||
if (win) {
|
||||
fm->ClearFocus(win);
|
||||
if (focusedContent) {
|
||||
// Clear focus if content was editable element, or contentEditable.
|
||||
nsGenericHTMLElement* focusedGeneric =
|
||||
nsGenericHTMLElement::FromContent(focusedContent);
|
||||
if (focusedContent->GetTextEditorRootContent() ||
|
||||
(focusedGeneric && focusedGeneric->IsContentEditable())) {
|
||||
nsIDOMWindow* win = mPresShell->GetDocument()->GetWindow();
|
||||
if (win) {
|
||||
fm->ClearFocus(win);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -142,20 +142,23 @@ LogManager.prototype = {
|
|||
this._prefs = null;
|
||||
},
|
||||
|
||||
get _logFileDirectory() {
|
||||
// At this point we don't allow a custom directory for the logs so
|
||||
// about:sync-log can be used. We could fix this later if necessary.
|
||||
return FileUtils.getDir("ProfD", ["weave", "logs"]);
|
||||
get _logFileSubDirectoryEntries() {
|
||||
// At this point we don't allow a custom directory for the logs, nor allow
|
||||
// it to be outside the profile directory.
|
||||
// This returns an array of the the relative directory entries below the
|
||||
// profile dir, and is the directory about:sync-log uses.
|
||||
return ["weave", "logs"];
|
||||
},
|
||||
|
||||
/**
|
||||
* Copy an input stream to the named file, doing everything off the main
|
||||
* thread.
|
||||
* outputFile is an nsIFile, but is used only for the name.
|
||||
* Returns a promise that is resolved with the file modification date on
|
||||
* completion or rejected if there is an error.
|
||||
* outputFileName is a string with the tail of the filename - the file will
|
||||
* be created in the log directory.
|
||||
* Returns a promise that is resolved<undefined> on completion or rejected if
|
||||
* there is an error.
|
||||
*/
|
||||
_copyStreamToFile: Task.async(function* (inputStream, outputFile) {
|
||||
_copyStreamToFile: Task.async(function* (inputStream, outputFileName) {
|
||||
// The log data could be large, so we don't want to pass it all in a single
|
||||
// message, so use BUFFER_SIZE chunks.
|
||||
const BUFFER_SIZE = 8192;
|
||||
|
@ -163,7 +166,11 @@ LogManager.prototype = {
|
|||
// get a binary stream
|
||||
let binaryStream = Cc["@mozilla.org/binaryinputstream;1"].createInstance(Ci.nsIBinaryInputStream);
|
||||
binaryStream.setInputStream(inputStream);
|
||||
yield OS.File.makeDir(outputFile.parent.path, { ignoreExisting: true });
|
||||
// We assume the profile directory exists, but not that the dirs under it do.
|
||||
let profd = FileUtils.getDir("ProfD", []);
|
||||
let outputFile = FileUtils.getDir("ProfD", this._logFileSubDirectoryEntries);
|
||||
yield OS.File.makeDir(outputFile.path, { ignoreExisting: true, from: profd.path });
|
||||
outputFile.append(outputFileName);
|
||||
let output = yield OS.File.open(outputFile.path, { write: true} );
|
||||
try {
|
||||
while (true) {
|
||||
|
@ -221,12 +228,10 @@ LogManager.prototype = {
|
|||
// We have reasonPrefix at the start of the filename so all "error"
|
||||
// logs are grouped in about:sync-log.
|
||||
let filename = reasonPrefix + "-" + this.logFilePrefix + "-" + Date.now() + ".txt";
|
||||
let file = this._logFileDirectory;
|
||||
file.append(filename);
|
||||
this._log.trace("Beginning stream copy to " + file.leafName + ": " +
|
||||
this._log.trace("Beginning stream copy to " + filename + ": " +
|
||||
Date.now());
|
||||
try {
|
||||
yield this._copyStreamToFile(inStream, file);
|
||||
yield this._copyStreamToFile(inStream, filename);
|
||||
this._log.trace("onCopyComplete", Date.now());
|
||||
} catch (ex) {
|
||||
this._log.error("Failed to copy log stream to file", ex);
|
||||
|
@ -256,7 +261,8 @@ LogManager.prototype = {
|
|||
*/
|
||||
cleanupLogs: Task.async(function* () {
|
||||
this._cleaningUpFileLogs = true;
|
||||
let iterator = new OS.File.DirectoryIterator(this._logFileDirectory.path);
|
||||
let logDir = FileUtils.getDir("ProfD", this._logFileSubDirectoryEntries);
|
||||
let iterator = new OS.File.DirectoryIterator(logDir.path);
|
||||
let maxAge = this._prefs.get("log.appender.file.maxErrorAge", DEFAULT_MAX_ERROR_AGE);
|
||||
let threshold = Date.now() - 1000 * maxAge;
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
Cu.import("resource://services-common/logmanager.js");
|
||||
Cu.import("resource://gre/modules/Log.jsm");
|
||||
Cu.import("resource://gre/modules/FileUtils.jsm");
|
||||
|
||||
function run_test() {
|
||||
run_next_test();
|
||||
|
@ -101,3 +102,34 @@ add_task(function* test_SharedLogs() {
|
|||
lm1.finalize();
|
||||
lm2.finalize();
|
||||
});
|
||||
|
||||
// A little helper to test what log files exist. We expect exactly zero (if
|
||||
// prefix is null) or exactly one with the specified prefix.
|
||||
function checkLogFile(prefix) {
|
||||
let logsdir = FileUtils.getDir("ProfD", ["weave", "logs"], true);
|
||||
let entries = logsdir.directoryEntries;
|
||||
if (!prefix) {
|
||||
// expecting no files.
|
||||
ok(!entries.hasMoreElements());
|
||||
} else {
|
||||
// expecting 1 file.
|
||||
ok(entries.hasMoreElements());
|
||||
let logfile = entries.getNext().QueryInterface(Ci.nsILocalFile);
|
||||
equal(logfile.leafName.slice(-4), ".txt");
|
||||
ok(logfile.leafName.startsWith(prefix + "-test-"), logfile.leafName);
|
||||
// and remove it ready for the next check.
|
||||
logfile.remove(false);
|
||||
}
|
||||
}
|
||||
|
||||
// Test that we correctly write error logs by default
|
||||
add_task(function* test_logFileErrorDefault() {
|
||||
let lm = new LogManager("log-manager.test.", ["TestLog2"], "test");
|
||||
|
||||
let log = Log.repository.getLogger("TestLog2");
|
||||
log.error("an error message");
|
||||
yield lm.resetFileLog(lm.REASON_ERROR);
|
||||
// One error log file exists.
|
||||
checkLogFile("error");
|
||||
lm.finalize();
|
||||
});
|
||||
|
|
|
@ -652,16 +652,18 @@ function EnvironmentCache() {
|
|||
|
||||
this._updateSettings();
|
||||
|
||||
#ifndef MOZ_WIDGET_ANDROID
|
||||
this._currentEnvironment.profile = {};
|
||||
#endif
|
||||
|
||||
// Build the remaining asynchronous parts of the environment. Don't register change listeners
|
||||
// until the initial environment has been built.
|
||||
|
||||
this._addonBuilder = new EnvironmentAddonBuilder(this);
|
||||
|
||||
this._initTask = Promise.all([this._addonBuilder.init(), this._updateProfile()])
|
||||
let p = [ this._addonBuilder.init() ];
|
||||
#ifndef MOZ_WIDGET_ANDROID
|
||||
this._currentEnvironment.profile = {};
|
||||
p.push(this._updateProfile());
|
||||
#endif
|
||||
|
||||
this._initTask = Promise.all(p)
|
||||
.then(
|
||||
() => {
|
||||
this._initTask = null;
|
||||
|
@ -671,7 +673,7 @@ function EnvironmentCache() {
|
|||
},
|
||||
(err) => {
|
||||
// log errors but eat them for consumers
|
||||
this._log.error("error while initializing", err);
|
||||
this._log.error("EnvironmentCache - error while initializing", err);
|
||||
this._initTask = null;
|
||||
this._startWatchingPrefs();
|
||||
this._addonBuilder.watchForChanges();
|
||||
|
@ -1019,7 +1021,9 @@ EnvironmentCache.prototype = {
|
|||
let gfxData = {
|
||||
D2DEnabled: getGfxField("D2DEnabled", null),
|
||||
DWriteEnabled: getGfxField("DWriteEnabled", null),
|
||||
DWriteVersion: getGfxField("DWriteVersion", null),
|
||||
// The following line is disabled due to main thread jank and will be enabled
|
||||
// again as part of bug 1154500.
|
||||
//DWriteVersion: getGfxField("DWriteVersion", null),
|
||||
adapters: [],
|
||||
};
|
||||
|
||||
|
|
|
@ -604,13 +604,16 @@ let Impl = {
|
|||
", aOptions " + JSON.stringify(aOptions));
|
||||
|
||||
let pingData = this.assemblePing(aType, aPayload, aOptions);
|
||||
let archivePromise = this._archivePing(pingData)
|
||||
.catch(e => this._log.error("addPendingPing - Failed to archive ping " + pingData.id, e));
|
||||
|
||||
let savePromise = TelemetryFile.savePing(pingData, aOptions.overwrite);
|
||||
let archivePromise = this._archivePing(pingData).catch(e => {
|
||||
this._log.error("addPendingPing - Failed to archive ping " + pingData.id, e);
|
||||
});
|
||||
|
||||
// Wait for both the archiving and ping persistence to complete.
|
||||
let promises = [
|
||||
savePromise,
|
||||
archivePromise,
|
||||
TelemetryFile.savePing(pingData, aOptions.overwrite),
|
||||
];
|
||||
return Promise.all(promises).then(() => pingData.id);
|
||||
},
|
||||
|
@ -1076,7 +1079,8 @@ let Impl = {
|
|||
|
||||
const creationDate = new Date(aPingData.creationDate);
|
||||
const filePath = getArchivedPingPath(aPingData.id, creationDate, aPingData.type);
|
||||
yield OS.File.makeDir(OS.Path.dirname(filePath), { ignoreExisting: true });
|
||||
yield OS.File.makeDir(OS.Path.dirname(filePath), { ignoreExisting: true,
|
||||
from: OS.Constants.Path.profileDir });
|
||||
yield TelemetryFile.savePingToFile(aPingData, filePath, true);
|
||||
}),
|
||||
|
||||
|
|
|
@ -249,7 +249,8 @@ function toLocalTimeISOString(date) {
|
|||
}
|
||||
|
||||
let sign = (n) => n >= 0 ? "+" : "-";
|
||||
let tzOffset = date.getTimezoneOffset();
|
||||
// getTimezoneOffset counter-intuitively returns -60 for UTC+1.
|
||||
let tzOffset = - date.getTimezoneOffset();
|
||||
|
||||
// YYYY-MM-DDThh:mm:ss.sTZD (eg 1997-07-16T19:20:30.45+01:00)
|
||||
return padNumber(date.getFullYear(), 4)
|
||||
|
@ -259,8 +260,8 @@ function toLocalTimeISOString(date) {
|
|||
+ ":" + padNumber(date.getMinutes(), 2)
|
||||
+ ":" + padNumber(date.getSeconds(), 2)
|
||||
+ "." + date.getMilliseconds()
|
||||
+ sign(tzOffset) + Math.abs(Math.floor(tzOffset / 60))
|
||||
+ ":" + Math.abs(tzOffset % 60);
|
||||
+ sign(tzOffset) + padNumber(Math.floor(Math.abs(tzOffset / 60)), 2)
|
||||
+ ":" + padNumber(Math.abs(tzOffset % 60), 2);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1703,9 +1704,8 @@ let Impl = {
|
|||
addClientId: true,
|
||||
addEnvironment: true,
|
||||
overwrite: true,
|
||||
filePath: file.path,
|
||||
};
|
||||
return TelemetryPing.addPendingPing(getPingType(payload), payload, options);
|
||||
return TelemetryPing.savePing(getPingType(payload), payload, file.path, options);
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -2071,7 +2071,7 @@ let Impl = {
|
|||
if (abortedExists) {
|
||||
this._log.trace("_checkAbortedSessionPing - aborted session found: " + FILE_PATH);
|
||||
yield this._abortedSessionSerializer.enqueueTask(
|
||||
() => TelemetryPing.addPendingPing(FILE_PATH, true));
|
||||
() => TelemetryPing.addPendingPingFromFile(FILE_PATH, true));
|
||||
}
|
||||
}),
|
||||
|
||||
|
|
|
@ -112,7 +112,7 @@ Structure::
|
|||
gfx: {
|
||||
D2DEnabled: <bool>, // null on failure
|
||||
DWriteEnabled: <bool>, // null on failure
|
||||
DWriteVersion: <string>, // null on failure
|
||||
//DWriteVersion: <string>, // temporarily removed, pending bug 1154500
|
||||
adapters: [
|
||||
{
|
||||
description: <string>, // e.g. "Intel(R) HD Graphics 4600", null on failure
|
||||
|
|
|
@ -392,11 +392,14 @@ function checkSystemSection(data) {
|
|||
let gfxData = data.system.gfx;
|
||||
Assert.ok("D2DEnabled" in gfxData);
|
||||
Assert.ok("DWriteEnabled" in gfxData);
|
||||
Assert.ok("DWriteVersion" in gfxData);
|
||||
// DWriteVersion is disabled due to main thread jank and will be enabled
|
||||
// again as part of bug 1154500.
|
||||
//Assert.ok("DWriteVersion" in gfxData);
|
||||
if (gIsWindows) {
|
||||
Assert.equal(typeof gfxData.D2DEnabled, "boolean");
|
||||
Assert.equal(typeof gfxData.DWriteEnabled, "boolean");
|
||||
Assert.ok(checkString(gfxData.DWriteVersion));
|
||||
// As above, will be enabled again as part of bug 1154500.
|
||||
//Assert.ok(checkString(gfxData.DWriteVersion));
|
||||
}
|
||||
|
||||
Assert.ok("adapters" in gfxData);
|
||||
|
|
|
@ -212,15 +212,23 @@ function checkPayloadInfo(data) {
|
|||
const ALLOWED_REASONS = [
|
||||
"environment-change", "shutdown", "daily", "saved-session", "test-ping"
|
||||
];
|
||||
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
||||
let numberCheck = arg => { return (typeof arg == "number"); };
|
||||
let positiveNumberCheck = arg => { return numberCheck(arg) && (arg >= 0); };
|
||||
let stringCheck = arg => { return (typeof arg == "string") && (arg != ""); };
|
||||
let isoDateCheck = arg => { return stringCheck(arg) && !Number.isNaN(Date.parse(arg)); }
|
||||
let revisionCheck = arg => {
|
||||
return (Services.appinfo.isOfficial) ? stringCheck(arg) : (typeof arg == "string");
|
||||
};
|
||||
let uuidCheck = arg => uuidRegex.test(arg);
|
||||
let uuidCheck = arg => {
|
||||
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
||||
return uuidRegex.test(arg);
|
||||
};
|
||||
let isoDateCheck = arg => {
|
||||
// We expect use of this version of the ISO format:
|
||||
// 2015-04-12T18:51:19.1+00:00
|
||||
const isoDateRegEx = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d+[+-]\d{2}:\d{2}$/;
|
||||
return stringCheck(arg) && !Number.isNaN(Date.parse(arg)) &&
|
||||
isoDateRegEx.test(arg);
|
||||
};
|
||||
|
||||
const EXPECTED_INFO_FIELDS_TYPES = {
|
||||
reason: stringCheck,
|
||||
|
@ -1582,6 +1590,7 @@ add_task(function* test_schedulerUserIdle() {
|
|||
// We should not miss midnight when going to idle.
|
||||
now.setHours(23);
|
||||
now.setMinutes(50);
|
||||
fakeNow(now);
|
||||
fakeIdleNotification("idle");
|
||||
Assert.equal(schedulerTimeout, 10 * 60 * 1000);
|
||||
|
||||
|
|
|
@ -65,11 +65,20 @@ let WebProgressListener = {
|
|||
|
||||
_setupJSON: function setupJSON(aWebProgress, aRequest) {
|
||||
if (aWebProgress) {
|
||||
let domWindowID;
|
||||
try {
|
||||
domWindowID = aWebProgress && aWebProgress.DOMWindowID;
|
||||
} catch (e) {
|
||||
// If nsDocShell::Destroy has already been called, then we'll
|
||||
// get NS_NOINTERFACE when trying to get the DOM window ID.
|
||||
domWindowID = null;
|
||||
}
|
||||
|
||||
aWebProgress = {
|
||||
isTopLevel: aWebProgress.isTopLevel,
|
||||
isLoadingDocument: aWebProgress.isLoadingDocument,
|
||||
loadType: aWebProgress.loadType,
|
||||
DOMWindowID: aWebProgress.DOMWindowID,
|
||||
DOMWindowID: domWindowID
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -99,67 +99,11 @@ this.ForgetAboutSite = {
|
|||
}
|
||||
|
||||
// Downloads
|
||||
let useJSTransfer = false;
|
||||
try {
|
||||
// This method throws an exception if the old Download Manager is disabled.
|
||||
Services.downloads.activeDownloadCount;
|
||||
} catch (ex) {
|
||||
useJSTransfer = true;
|
||||
}
|
||||
|
||||
if (useJSTransfer) {
|
||||
Task.spawn(function*() {
|
||||
let list = yield Downloads.getList(Downloads.ALL);
|
||||
list.removeFinished(download => hasRootDomain(
|
||||
NetUtil.newURI(download.source.url).host, aDomain));
|
||||
}).then(null, Cu.reportError);
|
||||
}
|
||||
else {
|
||||
let dm = Cc["@mozilla.org/download-manager;1"].
|
||||
getService(Ci.nsIDownloadManager);
|
||||
// Active downloads
|
||||
for (let enumerator of [dm.activeDownloads, dm.activePrivateDownloads]) {
|
||||
while (enumerator.hasMoreElements()) {
|
||||
let dl = enumerator.getNext().QueryInterface(Ci.nsIDownload);
|
||||
if (hasRootDomain(dl.source.host, aDomain)) {
|
||||
dl.cancel();
|
||||
dl.remove();
|
||||
}
|
||||
}
|
||||
|
||||
const deleteAllLike = function(db) {
|
||||
// NOTE: This is lossy, but we feel that it is OK to be lossy here and not
|
||||
// invoke the cost of creating a URI for each download entry and
|
||||
// ensure that the hostname matches.
|
||||
let stmt = db.createStatement(
|
||||
"DELETE FROM moz_downloads " +
|
||||
"WHERE source LIKE ?1 ESCAPE '/' " +
|
||||
"AND state NOT IN (?2, ?3, ?4)"
|
||||
);
|
||||
let pattern = stmt.escapeStringForLIKE(aDomain, "/");
|
||||
stmt.bindByIndex(0, "%" + pattern + "%");
|
||||
stmt.bindByIndex(1, Ci.nsIDownloadManager.DOWNLOAD_DOWNLOADING);
|
||||
stmt.bindByIndex(2, Ci.nsIDownloadManager.DOWNLOAD_PAUSED);
|
||||
stmt.bindByIndex(3, Ci.nsIDownloadManager.DOWNLOAD_QUEUED);
|
||||
try {
|
||||
stmt.execute();
|
||||
}
|
||||
finally {
|
||||
stmt.finalize();
|
||||
}
|
||||
}
|
||||
|
||||
// Completed downloads
|
||||
deleteAllLike(dm.DBConnection);
|
||||
deleteAllLike(dm.privateDBConnection);
|
||||
|
||||
// We want to rebuild the list if the UI is showing, so dispatch the
|
||||
// observer topic
|
||||
let os = Cc["@mozilla.org/observer-service;1"].
|
||||
getService(Ci.nsIObserverService);
|
||||
os.notifyObservers(null, "download-manager-remove-download", null);
|
||||
}
|
||||
}
|
||||
Task.spawn(function*() {
|
||||
let list = yield Downloads.getList(Downloads.ALL);
|
||||
list.removeFinished(download => hasRootDomain(
|
||||
NetUtil.newURI(download.source.url).host, aDomain));
|
||||
}).then(null, Cu.reportError);
|
||||
|
||||
// Passwords
|
||||
let lm = Cc["@mozilla.org/login-manager;1"].
|
||||
|
|
|
@ -15,7 +15,6 @@ var profileDir = do_get_profile();
|
|||
function cleanUp()
|
||||
{
|
||||
let files = [
|
||||
"downloads.sqlite",
|
||||
"places.sqlite",
|
||||
"cookies.sqlite",
|
||||
"signons.sqlite",
|
||||
|
@ -30,14 +29,3 @@ function cleanUp()
|
|||
}
|
||||
}
|
||||
cleanUp();
|
||||
|
||||
function oldDownloadManagerDisabled()
|
||||
{
|
||||
try {
|
||||
// This method throws an exception if the old Download Manager is disabled.
|
||||
Services.downloads.activeDownloadCount;
|
||||
} catch (ex) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -107,74 +107,6 @@ function check_cookie_exists(aDomain, aExists)
|
|||
checker(cm.cookieExists(cookie));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a download to download history.
|
||||
*
|
||||
* @param aURIString
|
||||
* The string of the URI to add.
|
||||
* @param aIsActive
|
||||
* If it should be set to an active state in the database. This does not
|
||||
* make it show up in the list of active downloads however!
|
||||
*/
|
||||
function add_download(aURIString, aIsActive)
|
||||
{
|
||||
function makeGUID() {
|
||||
let guid = "";
|
||||
for (var i = 0; i < 12; i++)
|
||||
guid += Math.floor(Math.random() * 10);
|
||||
return guid;
|
||||
}
|
||||
|
||||
check_downloaded(aURIString, false);
|
||||
let db = Cc["@mozilla.org/download-manager;1"].
|
||||
getService(Ci.nsIDownloadManager).
|
||||
DBConnection;
|
||||
let stmt = db.createStatement(
|
||||
"INSERT INTO moz_downloads (source, state, guid) " +
|
||||
"VALUES (:source, :state, :guid)"
|
||||
);
|
||||
stmt.params.source = aURIString;
|
||||
stmt.params.state = aIsActive ? Ci.nsIDownloadManager.DOWNLOAD_DOWNLOADING :
|
||||
Ci.nsIDownloadManager.DOWNLOAD_FINISHED;
|
||||
stmt.params.guid = makeGUID();
|
||||
try {
|
||||
stmt.execute();
|
||||
}
|
||||
finally {
|
||||
stmt.finalize();
|
||||
}
|
||||
check_downloaded(aURIString, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to ensure a URI string is in download history or not.
|
||||
*
|
||||
* @param aURIString
|
||||
* The string of the URI to check.
|
||||
* @param aIsDownloaded
|
||||
* True if the URI should be downloaded, false otherwise.
|
||||
*/
|
||||
function check_downloaded(aURIString, aIsDownloaded)
|
||||
{
|
||||
let db = Cc["@mozilla.org/download-manager;1"].
|
||||
getService(Ci.nsIDownloadManager).
|
||||
DBConnection;
|
||||
let stmt = db.createStatement(
|
||||
"SELECT * " +
|
||||
"FROM moz_downloads " +
|
||||
"WHERE source = :source"
|
||||
);
|
||||
stmt.params.source = aURIString;
|
||||
|
||||
let checker = aIsDownloaded ? do_check_true : do_check_false;
|
||||
try {
|
||||
checker(stmt.executeStep());
|
||||
}
|
||||
finally {
|
||||
stmt.finalize();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a disabled host to the login manager.
|
||||
*
|
||||
|
@ -380,51 +312,6 @@ function test_cookie_not_cleared_with_uri_contains_domain()
|
|||
check_cookie_exists(TEST_DOMAIN, true);
|
||||
}
|
||||
|
||||
// Download Manager
|
||||
function test_download_history_cleared_with_direct_match()
|
||||
{
|
||||
if (oldDownloadManagerDisabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const TEST_URI = "http://mozilla.org/foo";
|
||||
add_download(TEST_URI, false);
|
||||
ForgetAboutSite.removeDataFromDomain("mozilla.org");
|
||||
check_downloaded(TEST_URI, false);
|
||||
}
|
||||
|
||||
function test_download_history_cleared_with_subdomain()
|
||||
{
|
||||
if (oldDownloadManagerDisabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const TEST_URI = "http://www.mozilla.org/foo";
|
||||
add_download(TEST_URI, false);
|
||||
ForgetAboutSite.removeDataFromDomain("mozilla.org");
|
||||
check_downloaded(TEST_URI, false);
|
||||
}
|
||||
|
||||
function test_download_history_not_cleared_with_active_direct_match()
|
||||
{
|
||||
if (oldDownloadManagerDisabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Tests that downloads marked as active in the db are not deleted from the db
|
||||
const TEST_URI = "http://mozilla.org/foo";
|
||||
add_download(TEST_URI, true);
|
||||
ForgetAboutSite.removeDataFromDomain("mozilla.org");
|
||||
check_downloaded(TEST_URI, true);
|
||||
|
||||
// Reset state
|
||||
let db = Cc["@mozilla.org/download-manager;1"].
|
||||
getService(Ci.nsIDownloadManager).
|
||||
DBConnection;
|
||||
db.executeSimpleSQL("DELETE FROM moz_downloads");
|
||||
check_downloaded(TEST_URI, false);
|
||||
}
|
||||
|
||||
// Login Manager
|
||||
function test_login_manager_disabled_hosts_cleared_with_direct_match()
|
||||
{
|
||||
|
@ -650,12 +537,6 @@ let tests = [
|
|||
test_cookie_cleared_with_subdomain,
|
||||
test_cookie_not_cleared_with_uri_contains_domain,
|
||||
|
||||
// Download Manager
|
||||
// Note: active downloads tested in test_removeDataFromDomain_activeDownloads.js
|
||||
test_download_history_cleared_with_direct_match,
|
||||
test_download_history_cleared_with_subdomain,
|
||||
test_download_history_not_cleared_with_active_direct_match,
|
||||
|
||||
// Login Manager
|
||||
test_login_manager_disabled_hosts_cleared_with_direct_match,
|
||||
test_login_manager_disabled_hosts_cleared_with_subdomain,
|
||||
|
|
|
@ -807,6 +807,8 @@ function LazyMapProxyHandler () {
|
|||
}
|
||||
return target.delete(key);
|
||||
};
|
||||
case "has":
|
||||
return key => target.has(key);
|
||||
default:
|
||||
return target[name];
|
||||
}
|
||||
|
|
|
@ -35,7 +35,13 @@ function checkMainPropertyList(aPropertyListRoot) {
|
|||
const PRIMITIVE = PropertyListUtils.TYPE_PRIMITIVE;
|
||||
|
||||
checkValue(aPropertyListRoot, PropertyListUtils.TYPE_DICTIONARY);
|
||||
|
||||
// Check .has()
|
||||
Assert.ok(aPropertyListRoot.has("Boolean"));
|
||||
Assert.ok(!aPropertyListRoot.has("Nonexistent"));
|
||||
|
||||
checkValue(aPropertyListRoot.get("Boolean"), PRIMITIVE, false);
|
||||
|
||||
let array = aPropertyListRoot.get("Array");
|
||||
checkValue(array, PropertyListUtils.TYPE_ARRAY);
|
||||
do_check_eq(array.length, 8);
|
||||
|
|
|
@ -387,7 +387,7 @@ CopyUpdaterIntoUpdateDir(nsIFile *greDir, nsIFile *appDir, nsIFile *updateDir,
|
|||
return false;
|
||||
CopyFileIntoUpdateDir(appDir, kUpdaterINI, updateDir);
|
||||
#endif
|
||||
#if defined(XP_UNIX) && !defined(XP_MACOSX)
|
||||
#if defined(XP_UNIX) && !defined(XP_MACOSX) && !defined(ANDROID)
|
||||
nsCOMPtr<nsIFile> iconDir;
|
||||
appDir->Clone(getter_AddRefs(iconDir));
|
||||
iconDir->AppendNative(NS_LITERAL_CSTRING("icons"));
|
||||
|
|
Загрузка…
Ссылка в новой задаче