iPhone crash for feeding base64 to webview - javascript

I am using UIImagePickerController to choose image/video,upon selection I am converting the resource into base64 string and I am sending that to wkwebview
NSData(contentsOfURL:(info[UIImagePickerControllerMediaURL] as? NSURL)!)?.base64EncodedDataWithOptions(NSDataBase64EncodingOptions.Encoding64CharacterLineLength)
I am sending the base64 string to webview using evaluatejavascript
Here is the JS function
function showResource(base64,type){
if (type == "image"){
document.getElementById("div1").innerHTML="<img src='data:image/jpeg;base64,"+base64+"' width='100' height='100' alt='No Image'/>";
}
else{
document.getElementById("div1").innerHTML="<video width='320' height='240' controls><source src='data:video/x-m4v;base64,"+base64+"'></video>";
}
}.
I am facing the following problems
sometimes the webpage that is in webview becomes blank
sometimes the application gets crashed
sometimes the device goes into multiple
reboot
I couldn't find any memory leak in native code.I tried Instruments.
try loading a video of 25 seconds long first time it won't crash and you can't find a memory leak in Instruments
try loading the same video again the results are same
try doing the same,this time you'll see the device has gone offline
or if we try to load a video that's 60 longs it will crash the first time itself.
I am not sure what's causing the problem.
As the page is turning blank , it could be a javascript memory leak I thought
But I don't think the above function can cause memory leak since we're reassigning the new base64 on the same variable the older base64 should have been released from the memory and moreover javascript is garbage collected language.
so this is contradicting.
so base64 conversion might take more memory which in turn causes iOS to crash the app or crash the iPhone also in worst case but if this is the case why sometime html page is turning blank.
so this is also contradicting.
Any help is appreciated !
Update:
So far in my research it shows the problem is with memory leak in javascript.

If xcode print "pointer being freed was not allocated * set a breakpoint in malloc_error_break to debug" ,try to turn off the safari web viewer.

Related

DOM Parser Chrome extension memory leak

The problem
I have developed an extension that intercepts web requests, gets the HTML the web request originated from and processes it. I have used the DOMParser to parse the HTML and I have realised that the DOMParser is causing massive memory leak issues, which eventually causes the chrome extension to crash.
This is the code that causes the issues.
https://gist.github.com/uche1/20929b6ece7d647250828c63e4a2ffd4
What I've tried
Dev Tools Recorded Performance
I have recorded the chrome extension whilst it's intercepting requests and I noticed that as the DOMParser.parseFromString method was called, the more nodes and documents were created which weren't destroyed.
Dev tools screenshot
https://i.imgur.com/pMY50kR.png
Task Manager Memory Footprint
I looked at the task manager on chrome and saw that it had a huge memory footprint that wouldn't decrease with time (because garbage collection should kick in after a while). When the memory footprint gets too large the extension crashes.
Task manager memory footprint screenshot
https://i.imgur.com/c8fLWCy.png
Heap snapshots
I took some before and after screenshots of the heap and I can see the issue seems to be originating from the HTMLDocuments being allocated that isn't being garbage collected.
Snapshot (before)
https://i.imgur.com/Rg2CRi6.png
Snapshot (after)
https://i.imgur.com/UQgLuT1.png
Expected outcome
I would want to understand why the DOMParser is causing such memory issues, why it isn't being cleaned up by the garbage collector and what to do to resolve it.
Thanks
I have resolved the problem. It seems like the issue was because the DOMParser class for some reason kept the references of the HTML documents it parsed in memory and didn't release it. Because my extension is a Chrome extension that runs in the background, exaggerates this problem.
The solution was to use another method of parsing the HTML document which was to use
let parseHtml = (html) => {
let template = document.createElement('template');
template.innerHTML = html;
return template;
}
This helped resolve the issue.
You are basically replicating the entire DOM in memory and then never releasing the memory.
We get away with this in a client side app because when we navigate away, the memory used by the scripts on that page is recovered.
In a background script, that doesn't happen and is now your responsibility.
So set both parser and document to null when you are done using it.
chrome.webRequest.onCompleted.addListener(async request => {
if (request.tabId !== -1) {
let html = await getHtmlForTab(request.tabId);
let parser = new DOMParser();
let document = parser.parseFromString(html, "text/html");
let title = document.querySelector("title").textContent;
console.log(title);
parser = null; // <----- DO THIS
document = null; // <----- DO THIS
}
}, requestFilter);
I cannot point to a confirmed bug report in Chromium, but we were also hit by the memory leak. If you are developing an extension, DOMParser will leak in background scripts on Chromium based browser, but not on Firefox.
We could not get any of the workarounds mentioned here to solve the leak, so we ended up replacing the native DOMParser with the linkedom library, which provides a drop-in replacement and works in the browser (not only in NodeJs). It solves the leaks, so you might consider it, but there are some aspects that you need to be aware of:
It will not leak, but its initial memory footprint is higher then using the native parser
Performance is most likely slower (but I have not benchmarked it)
The DOM generated by its HTML parser might slightly different from what Firefox or Chrome would produce. The effect is most visible in HTML that is broken and where the browsers will attempt to error correct it.
We also tried jsdom first, which tries to be more compatible with the majors browsers at the cost of higher complexity of its codebase. Unfortunately, we found it difficult to make jsdom work in the browser (but on NodeJs it is works well).

GetJSObject fails when run on Microsoft Surface (Excel-VBA)

I have written a small utility in Excel-VBA that also interacts with Acrobat Javascript in a handful of separate .pdf files.
The code has been tested extensively and runs exactly as intended on my desktop PC. However, I ultimately need to implement this code on a Microsoft Surface platform. When I try to run the same code from an Excel file on a Microsoft Surface, the code balks at any lines utilizing "GetJSObject."
Eg. The following works fine on my PC, but causes an "object or method not supported" error on my Surface.
Set gAPP = CreateObject("AcroExch.App")
Set gPDDOC = CreateObject("AcroExch.PDDoc")
If gPDDoc.Open(pdfFileName) Then Set jso = gPDDOC.GetJSObject
So far, I've been able to find some hints online that GetJSObject doesnt work well in a 64 bit environment and my Surface runs 64 bit Windows 10 and 32 bit Excel.
However, I don't think that this alone can account for the difference in behavior across both machines; my desktop is running 64-bit Windows 7 with 32 bit Excel, and everything works as intended.
Where should I be looking to help discover the source (and solution) of the problem?
EDIT/UPDATE: The getJSObject statement actually works as intended, IF I take the additional step of manually opening a copy of one of the relevant .pdf files in Acrobat prior to running my VBA code. I assume this means that it is somehow the object definitions (e.g. Set gAPP = CreateObject("AcroExch.App")) that are working differently on the Surface relative to my PC--and not the getJSObject command specifically, as originally thought?
So far, it hasnt made much sense to me how/why this could be true (let alone how I could go about resolving the issue).
Not sure if this had been answered yet, however there are two courses of action i'd take for research:
1.
See if you can launch it without the constructor by using:
Set AcroApp = New AcroApp
Rather than
Set AcroApp = CreateObject("AcroExch.App")
2.
Ensure you are using the same version of acrobat, from my research this error occurs from the very first result in Google for the search query:
createobject acroexch.app error 429
You cannot do this with Adobe Reader, you need Adobe Acrobat.
This OLE interface is available with Adobe Acrobat, not Adobe Reader.

Maximum call stack size exceded

I am trying to download encrypted pictures and decrypt them using RNcryptor within a Javascript web application and place them within the html of my app. Everything works perfectly except for when pictures are larger in size and cause the call stack to be exceeded.
This error does not occur when to and from devices such as the Iphone, but when I try to send them to the web app, I get this error from the Iphone 6+ but no other device
This is my function used to convert a byte array to base64 string:
function encode(data)
{
var str = String.fromCharCode.apply(null,data);
return btoa(str).replace(/.{76}(?=.)/g,'$&\n');
}
Is there a more call stack efficient way to convert the data? I am willing to sacrifice speed if necessary.
The reason this is happening on only the Iphone 6 (and I assume it is mainly with pitcures made using its camera) is because the file you are sending is to large. This error probably would not occur with an older model Iphone such as the 5 or the 4 because of the picture quality.
The way that I would fix this is in your app where the picture is originally being encoded and placed on the database, I would resize it before doing so.

Javascript memory leak when navigating

I'm experiencing a huge memory increase when I'm doing a duration test with navigation between our webpages in our webapplication.
It's not a single-page-application, so I'm navigating with:
window.location.href = "linkToOtherPage.html";
This should clear all used memory right? What I notice in Chrome, is that then type=renderer process (the tab in Chrome) claims way too much memory. When navigating once each 2 seconds, it will eat 1000MB overnight. (Starts at 30MB).
Analyzing the js heap will result in a size of 4-5MB, so it's not in the JS-heap.
Is it so that a memory-leak caused in JS/DOM will keep on living till you close the browser? I would've thought it would be cleared when you navigate to another page.
I didn't quite understand the situation but maybe this is useful:
window.location.href actually loads the page from the cache and maybe if you are referring to the same page over and over again and if the audio src is going to be changed through ajax request maybe you are having all the data saved to the cache?! window.location.reload(true) actually does the trick on getting the data again all from the server.
I'm not sure if I helped you in any way. But if not, sorry for the disappointment! ;D

Browser crashes on heavy single page pplication

We have a big single page application, that started to crash from time to time. We were trying to debug it for a while now, but unfortunately, still no results. We used traditional debugging tools, but they were not very useful - perhaps not used correctly.
The app seems to crash most often on Safari, it doesn't crash that often in Chrome, but it still does, so I can't rule out a problem with browser(s).
I have managed to get this crash report, which you can find at the end of this question, unfortunately I don't know what to look for in it. I know it's huge and I'm just throwing it at you saying "here, find a bug", but could you possibly have a look at it and give me some hint what might be wrong or what should I focus on in the report?
Here is the crash report http://pastebin.com/bNxpuS6T
Thanks
What I can see from the crash report and the source code is that your JavaScript code was trying to destroy some DOM objects while still iterating through those, which is the reason of the crash.
I guess you may want to check if any timer associated with the idle tabs is still active.
DETAILS:
The WebKit crashed at
1 com.apple.WebCore 0x00007fff83cace2d WebCore::ScriptExecutionContext::willDestroyActiveDOMObject(WebCore::ActiveDOMObject*) + 45
where the source code is (click here)
void ScriptExecutionContext::willDestroyActiveDOMObject(ActiveDOMObject* object)
{
ASSERT(object);
if (m_iteratingActiveDOMObjects)
CRASH();
m_activeDOMObjects.remove(object);
}

Categories