0

Background

  • In our company, we install our offline documentation topics (thousands of .htm files in a folder) on our users' computers. Users view our documentation offline through their browser using the file:/// protocol.
  • I have a banner that appears in the footer of each .htm file that asks users to decide whether we can track user analytics (via Application Insights). Once they make their choice, we don't show the banner.

My Goal and Overall Problem

My goal is to store their choice in the browser's local storage. I can do that just fine, but the problem is this:

These are offline .htm files. There is no website domain. So, the key and value for any local storage is stored only for the .htm file they are on at the time they make their choice. If they come back to a topic they made their choice on, then yes, my script can retrieve their choice. But if they navigate to another topic in our documentation system (another .htm file), the local storage key and value don't persist to those other topics, and my script doesn't know what they chose--so then the banner pops up again.

My Workaround Idea

I doubt this is the best approach, but not having a lot of experience and not knowing what else to try, necessity becomes the mother of invention.

Here's what I'm trying:

  • Have my local storage requests go through a single .htm file called storage.htm, thereby getting around the above problem by always having a single point of contact (storage.htm) with the local storage.
  • storage.htm loads via a blank iframe.
  • The iframe is tacked onto each .htm topic.
  • When a topic .htm loads, the iframe also loads and any functions inside it become (hopefully) available for use by my main script.
  • When users click on the banner, I send the choice as query parameters through my main script to the iframe's src.
  • storage.htm contains a parseQuery() function, and inside that function, it parses any query params and then does the actual localStorage.getValue(key) and localStorage.setValue(key,value) requests.
  • I then want to somehow force the iframe to refresh with those parameters and then call the parseQuery() function there from my main script.

My Code

From my main script:

Attempt 1: I've tried the top-voted item from this thread, How to check if iframe is loaded or it has a content? but I get stuck inside the checkIfFrameLoaded() function, and it continues to loop through the check to see if the iframe is loaded. It never loads. I think it's because the contentWindow and/or contentDocument don't work with my offline files, so I won't bore you with that code.

Attempt 2: This is what I'd like to do as it seems cleaner:

function doIframeStorage(type,key,value){
   // We get a handle on the iframe's id of 'storage'.
    let storage = document.querySelector('#storage');
    const src = storage.getAttribute('src'); 
    let query = src;
    if (type==='get'){
        query = src + `?type=${type}&key=${key}`; 
    } else if (type==='set'){
        query = src + `?type=${type}&key=${key}&value=${value}`; 
    }
    storage.src = query;
    storage.addEventListener('load', (e) => parseQuery());
}


But I'm running into a problem where my parseQuery() function (from storage.htm) is always undefined:

Uncaught ReferenceError: parseQuery is not defined

Is it possible to load and access my parseQuery() function from my main script like I'm doing? If so, how? I thought the addEventListener would ensure it was loaded and therefore the parseQuery() function would then be available.

Or Is there a better way to do what I'm attempting?

Jared
  • 179
  • 1
  • 10
  • Browsers consider separate local URLs to be separate domains. You cannot override that behavior. – Pointy Sep 24 '21 at 21:09
  • Thanks @Pointy. Which is why I'm trying to handle all my storage requests through a single iframe URL... But maybe what I'm attempting isn't possible either? – Jared Sep 27 '21 at 15:38
  • 1
    *Every* distinct local file is considered to be a separate domain. That's a security precaution designed for the possibility that documentation (like yours, in fact) could be corrupted with an attack that attempts to load other local files. Chrome can be launched with a command line flag that tells it to disable that security check, but other browsers don't have that feature. (The flag is "--allow-file-access-from-file".) – Pointy Sep 27 '21 at 15:47
  • I understand that. I'm not trying to override the behavior. I'm trying to work within it, by going through a single URL (my storage.htm file). I don't want users to have to disable any security features. – Jared Sep 27 '21 at 16:24
  • 1
    Well I'm not sure I completely understand, but the ` – Pointy Sep 27 '21 at 16:25
  • Thanks @Pointy. That answers my question I think. Oh well. It appears I'd have to turn this offline documentation site into some kind of installable app that could access the file system for me to be able to retain and access user choices across all the topics. – Jared Sep 28 '21 at 20:24
  • 1
    there are some really simple and compact web server kits designed for exactly this kind of purpose. I haven't used one in many years so anything I could name is probably out of date, but they exist. – Pointy Sep 28 '21 at 20:25

0 Answers0