diff --git a/packages/office-addin-dev-settings/README.md b/packages/office-addin-dev-settings/README.md index 922eb50f7..c4a8bc840 100644 --- a/packages/office-addin-dev-settings/README.md +++ b/packages/office-addin-dev-settings/README.md @@ -13,6 +13,7 @@ Provides the ability to configure developer settings for Office Add-ins. * [source-bundle-url](#source-bundle-url) * [unregister](#unregister) * [webview](#webview) +* [configure-disk-manifests](#configure-disk-manifests) # @@ -256,4 +257,27 @@ Disable overriding the source bundle of an add-in. Enable overriding the source bundle of an add-in. -# \ No newline at end of file +# + +### disk-manifests +Configures loading manifests from disk. + +> This switch currently supports the following clients: classic Windows Outlook. + +Syntax: + +`office-addin-dev-settings configure-disk-manifests [options]` + +Without options, displays whether loading manifests from disk is enabled. + +Options: + +`--disable` + +Disable loading manifests from disk. + +`--enable` + +Enable loading manifests from disk. + +# diff --git a/packages/office-addin-dev-settings/src/cli.ts b/packages/office-addin-dev-settings/src/cli.ts index 3d96b6a9d..006154ba5 100644 --- a/packages/office-addin-dev-settings/src/cli.ts +++ b/packages/office-addin-dev-settings/src/cli.ts @@ -108,6 +108,13 @@ commander .description("Configures overriding of the source bundle.") .action(commands.sourceBundleOverrideFile); +commander + .command("disk-manifests") + .option("--enable [path]", `Enable loading manifests from disk.`) + .option("--disable", "Disable loading manifests from disk.") + .description("Configures loading manifests from disk.") + .action(commands.diskManifests); + // if the command is not known, display an error commander.on("command:*", function () { logErrorMessage(`The command syntax is not valid.\n`); diff --git a/packages/office-addin-dev-settings/src/commands.ts b/packages/office-addin-dev-settings/src/commands.ts index 72c765835..2ed61eb6f 100644 --- a/packages/office-addin-dev-settings/src/commands.ts +++ b/packages/office-addin-dev-settings/src/commands.ts @@ -545,4 +545,40 @@ export async function isSourceBundleOverriden(addInId: string) { usageDataObject.reportException("isSourceBundleOverriden", err); logErrorMessage(err); } -} \ No newline at end of file +} + +export async function diskManifests(options: OptionValues) { + try { + if (options.enable) { + const path: string | undefined = + typeof options.enable === "string" ? options.enable : undefined; + await enableDiskManifests(path); + } else if (options.disable) { + await disableDiskManifests(); + } else { + await areDiskManifestsEnabled(); + } + usageDataObject.reportSuccess("diskManifests"); + } catch (err: any) { + usageDataObject.reportException("diskManifests", err); + logErrorMessage(err); + } +} + +export async function enableDiskManifests(path?: string) { + const diskManifestsPath = await devSettings.enableDiskManifests(path); + console.log(`Disk manifests have been enabled. Path: ${diskManifestsPath}`); + usageDataObject.reportSuccess("enableDiskManifests"); +} + +export async function disableDiskManifests() { + await devSettings.disableDiskManifests(); + console.log("Disk manifests have been disabled."); + usageDataObject.reportSuccess("disableDiskManifests"); +} + +export async function areDiskManifestsEnabled() { + const res = await devSettings.areDiskManifestsEnabled(); + console.log(res); + usageDataObject.reportSuccess("areDiskManifestsEnabled"); +} diff --git a/packages/office-addin-dev-settings/src/dev-settings-windows.ts b/packages/office-addin-dev-settings/src/dev-settings-windows.ts index f3c208999..f96d90875 100644 --- a/packages/office-addin-dev-settings/src/dev-settings-windows.ts +++ b/packages/office-addin-dev-settings/src/dev-settings-windows.ts @@ -25,6 +25,7 @@ import fspath from "path"; /* global process */ const DeveloperSettingsRegistryKey: string = `HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Office\\16.0\\Wef\\Developer`; +const ProvidersRegistryKey: string = `HKEY_CURRENT_USER\\Software\\Microsoft\\Office\\16.0\\WEF\\Providers`; const OpenDevTools: string = "OpenDevTools"; export const OutlookSideloadManifestPath: string = "OutlookSideloadManifestPath"; @@ -40,8 +41,12 @@ const UseLiveReload: string = "UseLiveReload"; const UseProxyDebugger: string = "UseWebDebugger"; const WebViewSelection: string = "WebViewSelection"; const JsBundle: string = "JsBundle"; +const Outlook: string = "Outlook"; +const EnableDebugging: string = "EnableDebugging"; +const OutlookDiskProvider: string = "OutlookDiskProvider"; export async function clearDevSettings(addinId: string): Promise { + await disableDiskManifests(); return deleteDeveloperSettingsRegistryKey(addinId); } @@ -97,6 +102,10 @@ export function getDeveloperSettingsRegistryKey(addinId: string): registry.Regis return new registry.RegistryKey(`${DeveloperSettingsRegistryKey}\\${addinId}`); } +export function getProvidersRegistryKey(): registry.RegistryKey { + return new registry.RegistryKey(`${ProvidersRegistryKey}`); +} + export async function getEnabledDebuggingMethods(addinId: string): Promise { const key: registry.RegistryKey = getDeveloperSettingsRegistryKey(addinId); const methods: DebuggingMethod[] = []; @@ -376,4 +385,43 @@ export async function getSourceBundleOverrideFilePath(addInId: string): Promise< const developerSettingsRegKey = getDeveloperSettingsRegistryKey(addInId); const sourceBundleOverridePath = await registry.getStringValue(developerSettingsRegKey, JsBundle); return sourceBundleOverridePath; -} \ No newline at end of file +} + +export async function enableDiskManifests(path: string) { + const providersRegKey = getProvidersRegistryKey(); + await registry.addStringValue(providersRegKey, OutlookDiskProvider, path); + + const outlookDeveloperRegKey = getDeveloperSettingsRegistryKey(Outlook); + await registry.addNumberValue(outlookDeveloperRegKey, EnableDebugging, 1); +} + +export async function disableDiskManifests() { + const providersRegKey = getProvidersRegistryKey(); + await registry.deleteValue(providersRegKey, OutlookDiskProvider); + + const outlookDeveloperRegKey = getDeveloperSettingsRegistryKey(Outlook); + await registry.deleteKey(outlookDeveloperRegKey); +} + +export async function areDiskManifestsEnabled(): Promise { + const diskManifestsPath = await getDiskManifestsPath(); + const enableDebugging = await getOutlookEnableDebugging(); + + if (diskManifestsPath && enableDebugging && enableDebugging > 0) { + return "Disk manifests are enabled. Path = " + diskManifestsPath; + } + + return "Disk manifests are disabled"; +} + +export async function getDiskManifestsPath(): Promise { + const providersRegKey = getProvidersRegistryKey(); + const diskManifestsPath = await registry.getStringValue(providersRegKey, OutlookDiskProvider); + return diskManifestsPath; +} + +export async function getOutlookEnableDebugging(): Promise { + const outlookDeveloperRegKey = getDeveloperSettingsRegistryKey(Outlook); + const enableDebugging = await registry.getNumberValue(outlookDeveloperRegKey, EnableDebugging); + return enableDebugging; +} diff --git a/packages/office-addin-dev-settings/src/dev-settings.ts b/packages/office-addin-dev-settings/src/dev-settings.ts index c67db5611..0ab81780c 100644 --- a/packages/office-addin-dev-settings/src/dev-settings.ts +++ b/packages/office-addin-dev-settings/src/dev-settings.ts @@ -336,4 +336,57 @@ export async function isSourceBundleOverriden(addInId: string) : Promise export async function getSourceBundleOverrideFilePath(addInId: string): Promise { return devSettingsWindows.getSourceBundleOverrideFilePath(addInId); -} \ No newline at end of file +} + +export async function enableDiskManifests(path?: string) : Promise { + switch (process.platform) { + case "win32": { + const isValidPath = isValidDiskManifestsPath(path); + if (path && isValidPath) { + await devSettingsWindows.enableDiskManifests(path); + return path; + } + throw new ExpectedError("The disk manifests path is not specified or is invalid. Ensure that it is an existing directory path."); + } + default: + throw new ExpectedError(`Platform not supported: ${process.platform}.`); + } +} + +function isValidDiskManifestsPath(path?: string) { + let isValid: boolean = false; + try { + if (path) { + const pathExists: boolean = fs.existsSync(path); + if (pathExists) { + const stat = fs.statSync(path); + isValid = stat.isDirectory(); + } + } + } catch (err: any) { + console.log(err); + } + return isValid; +} + +export async function disableDiskManifests() : Promise { + switch (process.platform) { + case "win32": + return devSettingsWindows.disableDiskManifests(); + default: + throw new ExpectedError(`Platform not supported: ${process.platform}.`); + } +} + +export async function areDiskManifestsEnabled() : Promise { + switch (process.platform) { + case "win32": + return devSettingsWindows.areDiskManifestsEnabled(); + default: + throw new ExpectedError(`Platform not supported: ${process.platform}.`); + } +} + +export async function getDiskManifestsPath(): Promise { + return devSettingsWindows.getDiskManifestsPath(); +} diff --git a/packages/office-addin-dev-settings/test/unit-tests/test.ts b/packages/office-addin-dev-settings/test/unit-tests/test.ts index 07a3510bb..e1e1ec5ee 100644 --- a/packages/office-addin-dev-settings/test/unit-tests/test.ts +++ b/packages/office-addin-dev-settings/test/unit-tests/test.ts @@ -641,7 +641,6 @@ describe("Sideload to web", function () { describe("Source bundle override file", function() { if (isWindows) { - let sourceBundleOverridePathBeforeTests: string | undefined; const baseDirPath = process.cwd(); const jsBundleFileName = "bundle.js"; const testBundleOverrideFilePath = fspath.normalize(`${baseDirPath}/${jsBundleFileName}`); @@ -706,4 +705,88 @@ describe("Source bundle override file", function() { }); }); } -}); \ No newline at end of file +}); + +describe("Disk Manifests", function() { + if (isWindows) { + let diskManifestsPathBeforeTests: string | undefined; + const diskManifestsDisableStr = "Disk manifests are disabled"; + const testExecDirName = "testExec"; + const baseDirPath = process.cwd(); + const testExecDirPath = fspath.normalize(`${baseDirPath}/${testExecDirName}`); + const enableDiskManifestsError = "The disk manifests path is not specified or is invalid. Ensure that it is an existing directory path."; + const diskManifestsEnabledPrefix = "Disk manifests are enabled. Path = "; + + this.beforeAll(async function() { + await fsextra.remove(testExecDirPath); + await fsextra.mkdir(testExecDirPath); + diskManifestsPathBeforeTests = await devSettings.getDiskManifestsPath(); + await devSettings.disableDiskManifests(); + }); + + this.afterAll(async function() { + await fsextra.remove(testExecDirPath); + if (diskManifestsPathBeforeTests) { + await devSettings.enableDiskManifests(diskManifestsPathBeforeTests); + } else { + await devSettings.disableDiskManifests(); + } + }); + + describe("validate before enabling disk manifests", function() { + it("disk manifests should NOT be enabled", async function() { + assert.strictEqual(await devSettings.areDiskManifestsEnabled(), diskManifestsDisableStr); + }); + }); + + describe("validate enabling disk manifests", function() { + it("enable disk manifests with NO path", async function() { + assert.strictEqual(await devSettings.areDiskManifestsEnabled(), diskManifestsDisableStr); + + let error; + try { + await devSettings.enableDiskManifests(undefined); + } catch (err: any) { + error = err; + } + assert.ok(error instanceof Error, "error expected"); + assert.strictEqual(error.message, enableDiskManifestsError); + }); + + it("enable disk manifests with INVALID path", async function() { + assert.strictEqual(await devSettings.areDiskManifestsEnabled(), diskManifestsDisableStr); + + const diskManifestsPath = fspath.join(testExecDirPath, "doesNotExist"); + + let error; + try { + await devSettings.enableDiskManifests(diskManifestsPath); + } catch (err: any) { + error = err; + } + assert.ok(error instanceof Error, "error expected"); + assert.strictEqual(error.message, enableDiskManifestsError); + }); + + it("enable disk manifests with VALID path", async function() { + assert.strictEqual(await devSettings.areDiskManifestsEnabled(), diskManifestsDisableStr); + + try { + const path = await devSettings.enableDiskManifests(testExecDirPath); + assert.strictEqual(path, testExecDirPath); + } catch (err: any) { + console.log(err); + assert.fail("unexpected error"); + } + }); + }); + + describe("validate disabling disk manifest", async function() { + it("disable disk manifests", async function() { + assert.strictEqual(await devSettings.areDiskManifestsEnabled(), diskManifestsEnabledPrefix + testExecDirPath); + await devSettings.disableDiskManifests(); + assert.strictEqual(await devSettings.areDiskManifestsEnabled(), diskManifestsDisableStr); + }) + }); + } +});