Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PDF blobs no longer load in v5.0.0 on iOS 14.4.2 #863

Open
3 tasks done
studioromeo opened this issue Apr 8, 2021 · 4 comments
Open
3 tasks done

PDF blobs no longer load in v5.0.0 on iOS 14.4.2 #863

studioromeo opened this issue Apr 8, 2021 · 4 comments

Comments

@studioromeo
Copy link

Bug Report

Problem

I'm not sure if this should have worked to begin with but I was hoping to use the in app browser to display in memory PDFs. In v4.1.0 this seemed to work just fine however in v5.0.0 this no longer renders the PDF. I verified this by switching the plugin between versions and noticing the change in behaviour.

What is expected to happen?

In v4.1.0 the PDF would render in the in app browser window.

Stack trace:

2021-04-08 20:26:30.078627+0100 [656:46453] WF: _userSettingsForUser mobile: {
    filterBlacklist =     (
    );
    filterWhitelist =     (
    );
    restrictWeb = 1;
    useContentFilter = 0;
    useContentFilterOverrides = 0;
    whitelistEnabled = 0;
}
2021-04-08 20:26:30.078706+0100 [656:46453] WF: _WebFilterIsActive returning: NO
2021-04-08 20:26:30.087310+0100 [656:46453] THREAD WARNING: ['InAppBrowser'] took '19.270752' ms. Plugin should use a background thread.
2021-04-08 20:26:30.172211+0100 [656:46453] No
2021-04-08 20:26:30.183759+0100 [656:46453] didStartProvisionalNavigation
2021-04-08 20:26:30.633742+0100 [656:46453] Unbalanced calls to begin/end appearance transitions for <UIViewController: 0x106416a40>.

What does actually happen?

In v5.0.0 displays a blank in app browser window. From reading the stack trace what jumps out at me is WebKitBlobResource (code 1).

Stack trace:

2021-04-08 20:17:19.278086+0100 [637:43483] WF: _userSettingsForUser mobile: {
    filterBlacklist =     (
    );
    filterWhitelist =     (
    );
    restrictWeb = 1;
    useContentFilter = 0;
    useContentFilterOverrides = 0;
    whitelistEnabled = 0;
}
2021-04-08 20:17:19.278183+0100 [637:43483] WF: _WebFilterIsActive returning: NO
2021-04-08 20:17:19.281601+0100 [637:43483] THREAD WARNING: ['InAppBrowser'] took '12.166016' ms. Plugin should use a background thread.
2021-04-08 20:17:19.362538+0100 [637:43483] No
2021-04-08 20:17:19.362796+0100 [637:43483] didStartProvisionalNavigation
2021-04-08 20:17:19.372718+0100 [637:43483] [Process] 0x13c08f018 - [pageProxyID=22, webPageID=23, PID=642] WebPageProxy::didFailProvisionalLoadForFrame: frameID = 3, domain = WebKitBlobResource, code = 1
2021-04-08 20:17:19.373055+0100 [637:43483] webView:didFailProvisionalNavigation - 1: The operation couldn’t be completed. (WebKitBlobResource error 1.)
2021-04-08 20:17:19.823854+0100 [637:43483] Unbalanced calls to begin/end appearance transitions for <UIViewController: 0x13be59db0>.
2021-04-08 20:17:45.559624+0100 [637:43483] Could not signal service com.apple.WebKit.WebContent: 113: Could not find specified service

Information

I think the below code should be all thats needed. You'll need to grab the contents of a PDF and initialise pdf with that.

Command or Code

const blob = new Blob([pdf], {type:'application/pdf'});
const url = URL.createObjectURL(blob);
window.cordova.InAppBrowser.open(url, '_blank');

From reading around mozilla/pdf.js#8152 (comment) it seems that using blobs is unreliable in iOS safari and I guess the in app browser was using wkwebview before which is why this wasn't exhibited before?

Hopefully thats enough info to go on but if you need any more info let me know. I did try and find what was going on myself but I'm a bit out of my depth here 😓

Environment, Platform, Device

iOS 14.4.2

Version information

cordova-plugin-inappbrowser: 5.0.0

Checklist

  • I searched for existing GitHub issues
  • I updated all Cordova tooling to most recent version
  • I included all the necessary information above
@studioromeo studioromeo changed the title blobs no longer load in v5.0.0 PDF blobs no longer load in v5.0.0 on iOS 14.4.2 Apr 8, 2021
@maxcodefaster
Copy link

Have you found a reliable way of using createObjectUrl on ios?

@jmrrgncpz
Copy link

got this error too on ios 12.x and had to downgrade to v.4.1

@jmrrgncpz
Copy link

This is also now a problem for iOS 17.2.x with inappbrowser version v4.1.

v4.1 works until iOS 17.1.X so can we assume this is cordova-ios issue rather than inappbrowser?

I'm currently on cordova-ios@7.0.1 but it doesn't seem to have the support yet.

@breautek
Copy link
Contributor

breautek commented Apr 8, 2024

I think the main issue is trying to share blob urls across different WKWebView instances.

These are browser/webview implementation details but by specification, the browser is suppose t have a blob store, which when you create an object url from a blob, a blob store entry will be created and for as long as that entry exists, so will the blob. These blob store entries are the mapping from a blob url to the location of stored memory for that blob.

In this case, we have 2 wkwebview instances, the main "cordova" app instance, and the in-app browser instance. I feel like they will probably have their own blob store entries and attempting to share a URL created from one instance is not usable.

I think the reason why it seems to "sometimes" work is because both the in-app-browser and the main webview does used a shared process pool which states:

By default, WebKit gives each web view its own process space until it reaches an implementation-defined process limit. After that, web views with the same WKProcessPool object share the same web content process.

I suspect that if that process limit is reached and the webview instances starts sharing the same web content process, then blobs works across webview instances (assuming that the web content process is what contains the aforementioned blob store entries). Despite the use of "By default", I see no public API to adjust this behaviour (and ChatGPT claims there is no such API either, for what that's worth). We also don't know what that process limit means or how it can be reached since that is also not documented.

Potential Workarouds?

Base64 Data URLs

If you're dealing with small files, reading the blobs as base64 data urls could be a valid and simple workaround. Using base64 will expand memory consumption by approximately 33% of the original size, making it slow and risky to use on larger data files potentially loading to OOM (Out of Memory) errors

See FileReader.readAsDataURL for more details.

For larger file sizes

Becomes much more tricky to remain efficient. This would be experimental but I would try reading the blob as a 8int typed array and then slicing the array in chunks. You'll need to create a special HTML document for the in-app-browser to load which will accept these chunks in sequence so that the uint8 array can be rebuilt in the inapp browser instance. Once re-created, the in-app-browser can create its own blob to create blob urls, and maybe navigate to a blob url that it creates?

Reading as a 8int typed array is asynchronous and allows you to create slices and handle the data in a chunk fashion. When sending the chunks via executeScript, you can loop breaks by awaiting on the callback, making that process asynchronous, allowing your UI to render loading progresses or give user feedback.

To keep the memory footprint low, it would be beneficial to discard slices on the cordova webview side once they are "sent" to the in-app-browser, allowing the slices to be garbage collected once they are no longer needed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants