зеркало из https://github.com/mozilla/gecko-dev.git
Backed out 3 changesets (bug 1494549) for OSX devtools failures. CLOSED TREE
Backed out changeset e9abf60db23b (bug 1494549) Backed out changeset 3e89e661031c (bug 1494549) Backed out changeset 0d7e2a4ad360 (bug 1494549)
This commit is contained in:
Родитель
04e75c921a
Коммит
ee928c38ca
|
@ -34,8 +34,6 @@ const {
|
||||||
removeUSBRuntimesObserver,
|
removeUSBRuntimesObserver,
|
||||||
} = require("./src/modules/usb-runtimes");
|
} = require("./src/modules/usb-runtimes");
|
||||||
|
|
||||||
loader.lazyRequireGetter(this, "adbAddon", "devtools/shared/adb/adb-addon", true);
|
|
||||||
|
|
||||||
const App = createFactory(require("./src/components/App"));
|
const App = createFactory(require("./src/components/App"));
|
||||||
|
|
||||||
const { PAGES, RUNTIMES } = require("./src/constants");
|
const { PAGES, RUNTIMES } = require("./src/constants");
|
||||||
|
@ -48,7 +46,6 @@ const AboutDebugging = {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.onAdbAddonUpdated = this.onAdbAddonUpdated.bind(this);
|
|
||||||
this.onNetworkLocationsUpdated = this.onNetworkLocationsUpdated.bind(this);
|
this.onNetworkLocationsUpdated = this.onNetworkLocationsUpdated.bind(this);
|
||||||
this.onUSBRuntimesUpdated = this.onUSBRuntimesUpdated.bind(this);
|
this.onUSBRuntimesUpdated = this.onUSBRuntimesUpdated.bind(this);
|
||||||
|
|
||||||
|
@ -68,9 +65,6 @@ const AboutDebugging = {
|
||||||
addNetworkLocationsObserver(this.onNetworkLocationsUpdated);
|
addNetworkLocationsObserver(this.onNetworkLocationsUpdated);
|
||||||
addUSBRuntimesObserver(this.onUSBRuntimesUpdated);
|
addUSBRuntimesObserver(this.onUSBRuntimesUpdated);
|
||||||
await enableUSBRuntimes();
|
await enableUSBRuntimes();
|
||||||
|
|
||||||
adbAddon.on("update", this.onAdbAddonUpdated);
|
|
||||||
this.onAdbAddonUpdated();
|
|
||||||
},
|
},
|
||||||
|
|
||||||
async createMessageContexts() {
|
async createMessageContexts() {
|
||||||
|
@ -98,10 +92,6 @@ const AboutDebugging = {
|
||||||
return contexts;
|
return contexts;
|
||||||
},
|
},
|
||||||
|
|
||||||
onAdbAddonUpdated() {
|
|
||||||
this.actions.updateAdbAddonStatus(adbAddon.status);
|
|
||||||
},
|
|
||||||
|
|
||||||
onNetworkLocationsUpdated() {
|
onNetworkLocationsUpdated() {
|
||||||
this.actions.updateNetworkLocations(getNetworkLocations());
|
this.actions.updateNetworkLocations(getNetworkLocations());
|
||||||
},
|
},
|
||||||
|
@ -123,7 +113,6 @@ const AboutDebugging = {
|
||||||
removeNetworkLocationsObserver(this.onNetworkLocationsUpdated);
|
removeNetworkLocationsObserver(this.onNetworkLocationsUpdated);
|
||||||
removeUSBRuntimesObserver(this.onUSBRuntimesUpdated);
|
removeUSBRuntimesObserver(this.onUSBRuntimesUpdated);
|
||||||
disableUSBRuntimes();
|
disableUSBRuntimes();
|
||||||
adbAddon.off("update", this.onAdbAddonUpdated);
|
|
||||||
setDebugTargetCollapsibilities(state.ui.debugTargetCollapsibilities);
|
setDebugTargetCollapsibilities(state.ui.debugTargetCollapsibilities);
|
||||||
unmountComponentAtNode(this.mount);
|
unmountComponentAtNode(this.mount);
|
||||||
},
|
},
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
const {
|
const {
|
||||||
ADB_ADDON_STATUS_UPDATED,
|
|
||||||
DEBUG_TARGET_COLLAPSIBILITY_UPDATED,
|
DEBUG_TARGET_COLLAPSIBILITY_UPDATED,
|
||||||
NETWORK_LOCATIONS_UPDATED,
|
NETWORK_LOCATIONS_UPDATED,
|
||||||
PAGE_SELECTED,
|
PAGE_SELECTED,
|
||||||
|
@ -61,10 +60,6 @@ function removeNetworkLocation(location) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateAdbAddonStatus(adbAddonStatus) {
|
|
||||||
return { type: ADB_ADDON_STATUS_UPDATED, adbAddonStatus };
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateNetworkLocations(locations) {
|
function updateNetworkLocations(locations) {
|
||||||
return { type: NETWORK_LOCATIONS_UPDATED, locations };
|
return { type: NETWORK_LOCATIONS_UPDATED, locations };
|
||||||
}
|
}
|
||||||
|
@ -73,7 +68,6 @@ module.exports = {
|
||||||
addNetworkLocation,
|
addNetworkLocation,
|
||||||
removeNetworkLocation,
|
removeNetworkLocation,
|
||||||
selectPage,
|
selectPage,
|
||||||
updateAdbAddonStatus,
|
|
||||||
updateDebugTargetCollapsibility,
|
updateDebugTargetCollapsibility,
|
||||||
updateNetworkLocations,
|
updateNetworkLocations,
|
||||||
};
|
};
|
||||||
|
|
|
@ -21,7 +21,6 @@ const Sidebar = createFactory(require("./sidebar/Sidebar"));
|
||||||
class App extends PureComponent {
|
class App extends PureComponent {
|
||||||
static get propTypes() {
|
static get propTypes() {
|
||||||
return {
|
return {
|
||||||
adbAddonStatus: PropTypes.string,
|
|
||||||
// The "dispatch" helper is forwarded to the App component via connect.
|
// The "dispatch" helper is forwarded to the App component via connect.
|
||||||
// From that point, components are responsible for forwarding the dispatch
|
// From that point, components are responsible for forwarding the dispatch
|
||||||
// property to all components who need to dispatch actions.
|
// property to all components who need to dispatch actions.
|
||||||
|
@ -52,7 +51,6 @@ class App extends PureComponent {
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
adbAddonStatus,
|
|
||||||
dispatch,
|
dispatch,
|
||||||
messageContexts,
|
messageContexts,
|
||||||
runtimes,
|
runtimes,
|
||||||
|
@ -63,15 +61,7 @@ class App extends PureComponent {
|
||||||
{ messages: messageContexts },
|
{ messages: messageContexts },
|
||||||
dom.div(
|
dom.div(
|
||||||
{ className: "app" },
|
{ className: "app" },
|
||||||
Sidebar(
|
Sidebar({ className: "app__sidebar", dispatch, runtimes, selectedPage }),
|
||||||
{
|
|
||||||
adbAddonStatus,
|
|
||||||
className: "app__sidebar",
|
|
||||||
dispatch,
|
|
||||||
runtimes,
|
|
||||||
selectedPage
|
|
||||||
}
|
|
||||||
),
|
|
||||||
dom.main(
|
dom.main(
|
||||||
{ className: "app__content" },
|
{ className: "app__content" },
|
||||||
this.getSelectedPageComponent()
|
this.getSelectedPageComponent()
|
||||||
|
@ -83,7 +73,6 @@ class App extends PureComponent {
|
||||||
|
|
||||||
const mapStateToProps = state => {
|
const mapStateToProps = state => {
|
||||||
return {
|
return {
|
||||||
adbAddonStatus: state.ui.adbAddonStatus,
|
|
||||||
runtimes: state.runtimes,
|
runtimes: state.runtimes,
|
||||||
networkLocations: state.ui.networkLocations,
|
networkLocations: state.ui.networkLocations,
|
||||||
selectedPage: state.ui.selectedPage,
|
selectedPage: state.ui.selectedPage,
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
.sidebar__devices__message {
|
.sidebar__devices__no-devices-message {
|
||||||
color: var(--grey-40);
|
color: var(--grey-40);
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
padding: 12px 0;
|
padding: 12px 0;
|
||||||
|
|
|
@ -12,7 +12,6 @@ const FluentReact = require("devtools/client/shared/vendor/fluent-react");
|
||||||
const Localized = createFactory(FluentReact.Localized);
|
const Localized = createFactory(FluentReact.Localized);
|
||||||
|
|
||||||
const { PAGES, RUNTIMES } = require("../../constants");
|
const { PAGES, RUNTIMES } = require("../../constants");
|
||||||
loader.lazyRequireGetter(this, "ADB_ADDON_STATES", "devtools/shared/adb/adb-addon", true);
|
|
||||||
|
|
||||||
const DeviceSidebarItemAction = createFactory(require("./DeviceSidebarItemAction"));
|
const DeviceSidebarItemAction = createFactory(require("./DeviceSidebarItemAction"));
|
||||||
const SidebarItem = createFactory(require("./SidebarItem"));
|
const SidebarItem = createFactory(require("./SidebarItem"));
|
||||||
|
@ -24,7 +23,6 @@ const USB_ICON = "chrome://devtools/skin/images/aboutdebugging-connect-icon.svg"
|
||||||
class Sidebar extends PureComponent {
|
class Sidebar extends PureComponent {
|
||||||
static get propTypes() {
|
static get propTypes() {
|
||||||
return {
|
return {
|
||||||
adbAddonStatus: PropTypes.string,
|
|
||||||
className: PropTypes.string,
|
className: PropTypes.string,
|
||||||
dispatch: PropTypes.func.isRequired,
|
dispatch: PropTypes.func.isRequired,
|
||||||
runtimes: PropTypes.object.isRequired,
|
runtimes: PropTypes.object.isRequired,
|
||||||
|
@ -32,31 +30,15 @@ class Sidebar extends PureComponent {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
renderAdbAddonStatus() {
|
|
||||||
const isAddonInstalled = this.props.adbAddonStatus === ADB_ADDON_STATES.INSTALLED;
|
|
||||||
const localizationId = isAddonInstalled ? "about-debugging-sidebar-usb-enabled" :
|
|
||||||
"about-debugging-sidebar-usb-disabled";
|
|
||||||
return Localized(
|
|
||||||
{
|
|
||||||
id: localizationId
|
|
||||||
}, dom.aside(
|
|
||||||
{
|
|
||||||
className: "sidebar__devices__message js-sidebar-usb-status"
|
|
||||||
},
|
|
||||||
localizationId
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
renderDevices() {
|
renderDevices() {
|
||||||
const { runtimes } = this.props;
|
const { runtimes } = this.props;
|
||||||
if (!runtimes.networkRuntimes.length && !runtimes.usbRuntimes.length) {
|
if (!runtimes.networkRuntimes.length && !runtimes.usbRuntimes.length) {
|
||||||
return Localized(
|
return Localized(
|
||||||
{
|
{
|
||||||
id: "about-debugging-sidebar-no-devices"
|
id: "about-debugging-sidebar-no-devices"
|
||||||
}, dom.aside(
|
}, dom.span(
|
||||||
{
|
{
|
||||||
className: "sidebar__devices__message js-sidebar-no-devices"
|
className: "sidebar__devices__no-devices-message js-sidebar-no-devices"
|
||||||
},
|
},
|
||||||
"No devices discovered"
|
"No devices discovered"
|
||||||
)
|
)
|
||||||
|
@ -129,7 +111,6 @@ class Sidebar extends PureComponent {
|
||||||
})
|
})
|
||||||
),
|
),
|
||||||
dom.hr(),
|
dom.hr(),
|
||||||
this.renderAdbAddonStatus(),
|
|
||||||
this.renderDevices()
|
this.renderDevices()
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
const actionTypes = {
|
const actionTypes = {
|
||||||
ADB_ADDON_STATUS_UPDATED: "ADB_ADDON_STATUS_UPDATED",
|
|
||||||
CONNECT_RUNTIME_FAILURE: "CONNECT_RUNTIME_FAILURE",
|
CONNECT_RUNTIME_FAILURE: "CONNECT_RUNTIME_FAILURE",
|
||||||
CONNECT_RUNTIME_START: "CONNECT_RUNTIME_START",
|
CONNECT_RUNTIME_START: "CONNECT_RUNTIME_START",
|
||||||
CONNECT_RUNTIME_SUCCESS: "CONNECT_RUNTIME_SUCCESS",
|
CONNECT_RUNTIME_SUCCESS: "CONNECT_RUNTIME_SUCCESS",
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
const {
|
const {
|
||||||
ADB_ADDON_STATUS_UPDATED,
|
|
||||||
DEBUG_TARGET_COLLAPSIBILITY_UPDATED,
|
DEBUG_TARGET_COLLAPSIBILITY_UPDATED,
|
||||||
NETWORK_LOCATIONS_UPDATED,
|
NETWORK_LOCATIONS_UPDATED,
|
||||||
PAGE_SELECTED,
|
PAGE_SELECTED,
|
||||||
|
@ -13,7 +12,6 @@ const {
|
||||||
|
|
||||||
function UiState(locations = [], debugTargetCollapsibilities = {}) {
|
function UiState(locations = [], debugTargetCollapsibilities = {}) {
|
||||||
return {
|
return {
|
||||||
adbAddonStatus: null,
|
|
||||||
debugTargetCollapsibilities,
|
debugTargetCollapsibilities,
|
||||||
networkLocations: locations,
|
networkLocations: locations,
|
||||||
selectedPage: null,
|
selectedPage: null,
|
||||||
|
@ -22,11 +20,6 @@ function UiState(locations = [], debugTargetCollapsibilities = {}) {
|
||||||
|
|
||||||
function uiReducer(state = UiState(), action) {
|
function uiReducer(state = UiState(), action) {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case ADB_ADDON_STATUS_UPDATED: {
|
|
||||||
const { adbAddonStatus } = action;
|
|
||||||
return Object.assign({}, state, { adbAddonStatus });
|
|
||||||
}
|
|
||||||
|
|
||||||
case DEBUG_TARGET_COLLAPSIBILITY_UPDATED: {
|
case DEBUG_TARGET_COLLAPSIBILITY_UPDATED: {
|
||||||
const { isCollapsed, key } = action;
|
const { isCollapsed, key } = action;
|
||||||
const debugTargetCollapsibilities = new Map(state.debugTargetCollapsibilities);
|
const debugTargetCollapsibilities = new Map(state.debugTargetCollapsibilities);
|
||||||
|
|
|
@ -5,7 +5,6 @@ support-files =
|
||||||
debug-target-pane_collapsibilities_head.js
|
debug-target-pane_collapsibilities_head.js
|
||||||
head-addons-script.js
|
head-addons-script.js
|
||||||
head.js
|
head.js
|
||||||
resources/test-adb-extension/*
|
|
||||||
resources/test-temporary-extension/*
|
resources/test-temporary-extension/*
|
||||||
!/devtools/client/shared/test/shared-head.js
|
!/devtools/client/shared/test/shared-head.js
|
||||||
!/devtools/client/shared/test/telemetry-test-helpers.js
|
!/devtools/client/shared/test/telemetry-test-helpers.js
|
||||||
|
@ -16,5 +15,4 @@ support-files =
|
||||||
[browser_aboutdebugging_debug-target-pane_empty.js]
|
[browser_aboutdebugging_debug-target-pane_empty.js]
|
||||||
[browser_aboutdebugging_navigate.js]
|
[browser_aboutdebugging_navigate.js]
|
||||||
[browser_aboutdebugging_sidebar_network_runtimes.js]
|
[browser_aboutdebugging_sidebar_network_runtimes.js]
|
||||||
[browser_aboutdebugging_sidebar_usb_status.js]
|
|
||||||
[browser_aboutdebugging_thisfirefox.js]
|
[browser_aboutdebugging_thisfirefox.js]
|
||||||
|
|
|
@ -1,49 +0,0 @@
|
||||||
/* Any copyright is dedicated to the Public Domain.
|
|
||||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
|
||||||
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
const { adbAddon } = require("devtools/shared/adb/adb-addon");
|
|
||||||
const { ADB } = require("devtools/shared/adb/adb");
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This test asserts that the sidebar shows a message describing the status of the USB
|
|
||||||
* devices scanning.
|
|
||||||
*/
|
|
||||||
add_task(async function() {
|
|
||||||
// Make sure the ADB addon is removed when the test ends.
|
|
||||||
registerCleanupFunction(async function() {
|
|
||||||
try {
|
|
||||||
await adbAddon.uninstall();
|
|
||||||
} catch (e) {
|
|
||||||
// Will throw if the addon is already uninstalled, ignore exceptions here.
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
await pushPref("devtools.remote.adb.extensionURL",
|
|
||||||
CHROME_URL_ROOT + "resources/test-adb-extension/adb-extension-#OS#.xpi");
|
|
||||||
|
|
||||||
const { document, tab } = await openAboutDebugging();
|
|
||||||
|
|
||||||
const usbStatusElement = document.querySelector(".js-sidebar-usb-status");
|
|
||||||
ok(usbStatusElement, "Sidebar shows the USB status element");
|
|
||||||
ok(usbStatusElement.textContent.includes("USB devices disabled"),
|
|
||||||
"USB status element has the expected content");
|
|
||||||
|
|
||||||
info("Install the adb extension and wait for the message to udpate");
|
|
||||||
adbAddon.install();
|
|
||||||
await waitUntil(() => usbStatusElement.textContent.includes("USB devices enabled"));
|
|
||||||
|
|
||||||
// Right now we are resuming as soon as "USB devices enabled" is displayed, but ADB
|
|
||||||
// might still be starting up. If we move to uninstall directly, the ADB startup will
|
|
||||||
// fail and we will have an unhandled promise rejection.
|
|
||||||
// See Bug 1498469.
|
|
||||||
info("Wait until ADB has started.");
|
|
||||||
await waitUntil(() => ADB.ready);
|
|
||||||
|
|
||||||
info("Uninstall the adb extension and wait for the message to udpate");
|
|
||||||
adbAddon.uninstall();
|
|
||||||
await waitUntil(() => usbStatusElement.textContent.includes("USB devices disabled"));
|
|
||||||
|
|
||||||
await removeTab(tab);
|
|
||||||
});
|
|
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
|
@ -13,12 +13,8 @@ about-debugging-sidebar-this-firefox =
|
||||||
about-debugging-sidebar-connect =
|
about-debugging-sidebar-connect =
|
||||||
.name = Connect
|
.name = Connect
|
||||||
|
|
||||||
# Text displayed in the about:debugging sidebar when USB devices discovery is enabled.
|
# Text displayed in the about:debugging sidebar when no device was found.
|
||||||
about-debugging-sidebar-usb-enabled = USB devices enabled
|
about-debugging-sidebar-no-devices = No devices discovered
|
||||||
|
|
||||||
# Text displayed in the about:debugging sidebar when USB devices discovery is disabled
|
|
||||||
# (for instance because the mandatory ADB extension is not installed).
|
|
||||||
about-debugging-sidebar-usb-disabled = USB devices disabled
|
|
||||||
|
|
||||||
# Text displayed in buttons found in sidebar items representing remote runtimes.
|
# Text displayed in buttons found in sidebar items representing remote runtimes.
|
||||||
# Clicking on the button will attempt to connect to the runtime.
|
# Clicking on the button will attempt to connect to the runtime.
|
||||||
|
|
|
@ -8,8 +8,8 @@ const {AddonManager} = require("resource://gre/modules/AddonManager.jsm");
|
||||||
const Services = require("Services");
|
const Services = require("Services");
|
||||||
const EventEmitter = require("devtools/shared/event-emitter");
|
const EventEmitter = require("devtools/shared/event-emitter");
|
||||||
|
|
||||||
const PREF_ADB_EXTENSION_URL = "devtools.remote.adb.extensionURL";
|
const ADB_LINK = Services.prefs.getCharPref("devtools.remote.adb.extensionURL");
|
||||||
const PREF_ADB_EXTENSION_ID = "devtools.remote.adb.extensionID";
|
const ADB_ADDON_ID = Services.prefs.getCharPref("devtools.remote.adb.extensionID");
|
||||||
|
|
||||||
// Extension ID for adb helper extension that might be installed on Firefox 63 or older.
|
// Extension ID for adb helper extension that might be installed on Firefox 63 or older.
|
||||||
const OLD_ADB_ADDON_ID = "adbhelper@mozilla.org";
|
const OLD_ADB_ADDON_ID = "adbhelper@mozilla.org";
|
||||||
|
@ -65,13 +65,8 @@ class ADBAddon extends EventEmitter {
|
||||||
return this._status;
|
return this._status;
|
||||||
}
|
}
|
||||||
|
|
||||||
async _getAddon() {
|
|
||||||
const addonId = Services.prefs.getCharPref(PREF_ADB_EXTENSION_ID);
|
|
||||||
return AddonManager.getAddonByID(addonId);
|
|
||||||
}
|
|
||||||
|
|
||||||
async updateInstallStatus() {
|
async updateInstallStatus() {
|
||||||
const addon = await this._getAddon();
|
const addon = await AddonManager.getAddonByID(ADB_ADDON_ID);
|
||||||
if (addon && !addon.userDisabled) {
|
if (addon && !addon.userDisabled) {
|
||||||
this.status = ADB_ADDON_STATES.INSTALLED;
|
this.status = ADB_ADDON_STATES.INSTALLED;
|
||||||
} else {
|
} else {
|
||||||
|
@ -97,8 +92,7 @@ class ADBAddon extends EventEmitter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const xpiLink = Services.prefs.getCharPref(PREF_ADB_EXTENSION_URL);
|
return ADB_LINK.replace(/#OS#/g, OS);
|
||||||
return xpiLink.replace(/#OS#/g, OS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -109,7 +103,7 @@ class ADBAddon extends EventEmitter {
|
||||||
* String passed to the AddonManager for telemetry.
|
* String passed to the AddonManager for telemetry.
|
||||||
*/
|
*/
|
||||||
async install(source) {
|
async install(source) {
|
||||||
const addon = await this._getAddon();
|
const addon = await AddonManager.getAddonByID(ADB_ADDON_ID);
|
||||||
if (addon && !addon.userDisabled) {
|
if (addon && !addon.userDisabled) {
|
||||||
this.status = ADB_ADDON_STATES.INSTALLED;
|
this.status = ADB_ADDON_STATES.INSTALLED;
|
||||||
return;
|
return;
|
||||||
|
@ -130,7 +124,7 @@ class ADBAddon extends EventEmitter {
|
||||||
}
|
}
|
||||||
|
|
||||||
async uninstall() {
|
async uninstall() {
|
||||||
const addon = await this._getAddon();
|
const addon = await AddonManager.getAddonByID(ADB_ADDON_ID);
|
||||||
addon.uninstall();
|
addon.uninstall();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче