OfficeDev / office-js

A repo and NPM package for Office.js, corresponding to a copy of what gets published to the official "evergreen" Office.js CDN, at https://appsforoffice.microsoft.com/lib/1/hosted/office.js.
https://learn.microsoft.com/javascript/api/overview
Other
685 stars 95 forks source link

Unable to use localStorage in event-based script #2177

Closed barclayadam closed 2 years ago

barclayadam commented 3 years ago

Overview

I am unable to use localStorage in OWA or Windows Outlook. Given the documentation at https://docs.microsoft.com/en-us/office/dev/add-ins/develop/persisting-add-in-state-and-settings I expected to be able to use localStorage in Outlook, in both the task pane and event launched runtime.

I am looking to cache larger amounts of data on a single device that will not reliably fit in the 32kB limit of RoamingSettings.

Your Environment

Expected behavior

To be able to access localStorage

Current behavior

When using localStorage in an event launched context (by which I mean https://docs.microsoft.com/en-us/office/dev/add-ins/outlook/autolaunch) I get:

Steps to reproduce

  1. Use localStorage in event-based activated script
exextoc commented 3 years ago

For Desktop the recommened API is OfficeRuntime.Strorage. See documentation here: https://docs.microsoft.com/en-us/javascript/api/office-runtime/officeruntime.storage?view=excel-js-preview I thas a 10 MB limit per origin.

Note that the SharedRuntime is not required for Outlook Event Based Add-ins.

For OWA, localStorage should work, I will need to follow up with the product team to get more info.

barclayadam commented 3 years ago

@exextoc Thank you for pointing that out. Is the documentation at https://docs.microsoft.com/en-us/office/dev/add-ins/reference/requirement-sets/shared-runtime-requirement-sets incorrect? It has no mention of Outlook.

What is the recommendation for caching in Outlook task panes? Would shared runtime be available there? As above I have the same issue with localStorage in Windows as OWA (different cause, but still no localStorage).

I'm starting to look at what is required here to make this work so may report back later

exextoc commented 3 years ago

We are in the process of updating our documentation for OfficeRuntime.Storage. Outlook does not support the SharedRuntime requirement set, however, Outlook Event-Based Add-Ins have access to OfficeRuntime.Storage.

For Outlook taskpane add-ins, localStorage should be sufficient. However, taskpane add-ins are executed using an underlying web browser as the sandbox whereas Event-Based Add-Ins are executed using a custom sandbox process, which is not a browser. This means that Outlook taskpane add-ins cannot access data locally stored by an Event-Based Add-In, and vice-versa.

Are you trying to find a way to store data locally that is accessible to both taskpane and event-based add-ins?

barclayadam commented 3 years ago

For our current use-case we can get by without sharing the data, but in an ideal world being able to share this data would be great (and given the current size limits of other techniques like RoamingSettings we cannot use those).

We have updated to use OfficeRuntime.Storage and that is working well now but have no solution in OWA because of the above error. The browser(s) that we have tried it on have nothing configured to prevent general use of localStorage, so not sure what the issue with OWA is

exextoc commented 3 years ago

We will keep the ideal case in mind as we work on improving this platform. Thanks! The OWA issue is actively being investigated by the OWA team. I have alerted them to your update to this post.

exextoc commented 3 years ago

For our current use-case we can get by without sharing the data, but in an ideal world being able to share this data would be great (and given the current size limits of other techniques like RoamingSettings we cannot use those).

We have updated to use OfficeRuntime.Storage and that is working well now but have no solution in OWA because of the above error. The browser(s) that we have tried it on have nothing configured to prevent general use of localStorage, so not sure what the issue with OWA is

Can you please share a code snippet which you're using to access the localstorage?

barclayadam commented 3 years ago
try {
    return window.localStorage.getItem('stored-value');
} catch (e) {
    logger.debug('Could not load access token in local storage: %s', e);

    return undefined;
}

The above is the core of accessing localStorage object when it is failing in OWA (and as discussed Desktop). That logger line prints to console with the error from the first post (Failed to read the 'localStorage' property from 'Window': Access is denied for this document).

exextoc commented 3 years ago
try {
    return window.localStorage.getItem('stored-value');
} catch (e) {
    logger.debug('Could not load access token in local storage: %s', e);

    return undefined;
}

The above is the core of accessing localStorage object when it is failing in OWA (and as discussed Desktop). That logger line prints to console with the error from the first post (Failed to read the 'localStorage' property from 'Window': Access is denied for this document).

Hi, thanks for sharing the snippet. We tried this and couldn't repro this issue. Will it be possible to share the addin's manifest with us so that we can try to repro this?

barclayadam commented 3 years ago

To be clear, I am only talking about this code being used from within an event-based activation event handler.

Included below is a code file + manifest. The code file just tries to access localStorage so would not actually output any value. The below results in (in Chrome v95):

Could not load access token in local storage: DOMException: Failed to read the 'localStorage' property from 'Window': Access is denied for this document.
    at o (https://example.com/commandsweb.553a41b4.js:1:963)
    at Object.callback (https://example.com/commandsweb.553a41b4.js:1:1255)
    at https://appsforoffice.microsoft.com/lib/1/hosted/outlook-web-16.01.js:20:175923
// We MUST call this to indicate we are immediately ready to be launched. DO NOT REMOVE
Office.onReady(() => {
    console.log('onReady called');
});

function accessLocalStorage() {
    try {
        const item = window.localStorage.getItem('stored-value');

        console.log('Item found in localStorage was ' + item);
    } catch (e) {
        console.log('Could not load access token in local storage: %s', e);
    }
}

Office.actions.associate('onMessageComposeHandler', () => accessLocalStorage());
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<OfficeApp xmlns="http://schemas.microsoft.com/office/appforoffice/1.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:bt="http://schemas.microsoft.com/office/officeappbasictypes/1.0"
           xmlns:mailappor="http://schemas.microsoft.com/office/mailappversionoverrides/1.0" xsi:type="MailApp">
    <Id>9114d8b7-b30f-4022-a651-3a73e06c1e82</Id>
    <Version>1.0.0</Version>
    <ProviderName>Test</ProviderName>
    <DefaultLocale>en-US</DefaultLocale>
    <DisplayName DefaultValue="Local Storage tester"/>
    <Description DefaultValue="Local Storage tester"/>
    <IconUrl DefaultValue="https://example.com/assets/icon-80.png"/>
    <HighResolutionIconUrl DefaultValue="https://example.com/assets/icon-128.png"/>
    <SupportUrl DefaultValue="https://www.example.com/help"/>
    <Hosts>
        <Host Name="Mailbox"/>
    </Hosts>
    <Requirements>
        <Sets>
            <Set Name="Mailbox" MinVersion="1.3"/>
        </Sets>
    </Requirements>
    <FormSettings>
        <Form xsi:type="ItemEdit">
            <DesktopSettings>
                <SourceLocation DefaultValue="https://example.com/taskpane.html"/>
            </DesktopSettings>
        </Form>
    </FormSettings>
    <Permissions>ReadWriteItem</Permissions>
    <Rule xsi:type="RuleCollection" Mode="Or">
        <Rule xsi:type="ItemIs" ItemType="Message" FormType="Edit"/>
    </Rule>
    <DisableEntityHighlighting>false</DisableEntityHighlighting>
    <VersionOverrides xmlns="http://schemas.microsoft.com/office/mailappversionoverrides" xsi:type="VersionOverridesV1_0">
        <VersionOverrides xmlns="http://schemas.microsoft.com/office/mailappversionoverrides/1.1" xsi:type="VersionOverridesV1_1">
            <Requirements>
                <bt:Sets DefaultMinVersion="1.3">
                    <bt:Set Name="Mailbox"/>
                </bt:Sets>
            </Requirements>
            <Hosts>
                <Host xsi:type="MailHost">
                    <!-- Event-based activation happens in a lightweight runtime.-->
                    <Runtimes>
                        <!-- HTML file including reference to or inline JavaScript event handlers.
                             This is used by Outlook on the web. -->
                        <Runtime resid="WebViewRuntime.Url">
                            <!-- JavaScript file containing event handlers. This is used by Outlook Desktop. -->
                            <Override type="javascript" resid="JSRuntime.Url"/>
                        </Runtime>
                    </Runtimes>

                    <DesktopFormFactor>
                        <!-- Enable launching the add-in on the included events. -->
                        <ExtensionPoint xsi:type="LaunchEvent">
                            <LaunchEvents>
                                <LaunchEvent Type="OnNewMessageCompose" FunctionName="onMessageComposeHandler" />
                            </LaunchEvents>
                            <!-- Identifies the runtime to be used (also referenced by the Runtime element). -->
                            <SourceLocation resid="WebViewRuntime.Url"/>
                        </ExtensionPoint>
                    </DesktopFormFactor>
                </Host>
            </Hosts>
            <Resources>
                <bt:Urls>
                    <bt:Url id="WebViewRuntime.Url" DefaultValue="https://example.com/commands.html"/>

                    <!-- Entry needed for Outlook Desktop. -->
                    <bt:Url id="JSRuntime.Url" DefaultValue="https://example.com/commandsdesktop.js"/>
                </bt:Urls>
            </Resources>
        </VersionOverrides>
    </VersionOverrides>
</OfficeApp>
exextoc commented 3 years ago

Hey @barclayadam ,

Sorry for the delay in response. We are still investigating this issue and we will keep you posted.

exextoc commented 3 years ago

@barclayadam Thanks for your patience. We are unable to reproduce this issue with the manifest that you have shared, as the HTML page rendered points to an expired domain. Can you please verify and share the updated manifest?

And meanwhile, we tested the particular code snippet that you have shared and its working as expected.

try { const item = window.localStorage.getItem('stored-value'); console.log('Item found in localStorage was ' + item); } catch (e) { console.log('Could not load access token in local storage: %s', e); }

Hence it will be better to get the manifest so that we can understand the problem better.

barclayadam commented 2 years ago

This issue is because cookies/local & session storage etc. is blocked by default by Chrome (and assuming other browsers) when using incognito mode within an iframe, which these scripts will be in. I was testing in incognito without giving it much thought.

Could the docs @ https://docs.microsoft.com/en-us/office/dev/add-ins/develop/persisting-add-in-state-and-settings be updated a little to expand on the note at the top, to call our this scenario some more given it can be blocked by default and not just the user explicitly turning off:

image

KishanVaishnani commented 1 year ago

Not working for me. It saying localstorage not defind

hbnrmx commented 8 months ago

@exextoc Sorry for hijacking this thread!

For Desktop the recommened API is OfficeRuntime.Strorage. See documentation here: https://docs.microsoft.com/en-us/javascript/api/office-runtime/officeruntime.storage?view=excel-js-preview I thas a 10 MB limit per origin.

What's the recommended storage for event-based addins in the case of Outlook for MacOS? The docs you link state that

This interface isn't supported in Outlook on Mac or on the web.

Thank you!