What are some methods to debug Javascript inside of a UIWebView? - javascript

I'm trying to figure out why something with Javascript isn't working inside of a UIWebView. To my knowledge, there is no way to set a breakpoint inside of XCode for a js file. No problemo, I'll just go back to 2004 and use alert statemen-- oh wait they don't seem to work inside of a UIWebView either!
The only thing I could think of is by exporting my HTML And JS files to my desktop and then just doing my debugging inside of Safari. And that works! But of course, the bug I'm fighting with in the UIWebView doesn't occur in Safari.
Are there any other ways for debugging inside of a UIWebView, or any tricks that I can use akin to using the old-school alert method?

If you're using iOS >= 6 and you have mountain lion (10.8) or Safari >= 6, you can just:
Open the application in the simulator (or your device in XCode >= 4.5.x).
Open Safari (go to Preferences -> Advanced and make sure "Show Develop Menu in Menubar" is on.
From the Menu-bar (of Safari) select Develop -> iPhone Simulator -> [your webview page].
That's it !

This query tops google, so worth linking to the remoteInspector hidden in iOS5 - by far the best way found so far to debug your UIWebViews - just conditional compile out before you send to Apple.

alert() certainly works for me.
However, you can also do lots of other things, like make your own DHTML alert that pops up in a layer. This can be nice because you can do multiple alerts to a single div, without stopping your app. You should also be able to write a stack trace to it (the stack trace is in the exception object, and you can always throw your own exceptions).
Alternatively, if running on the simulator your custom "alert()" could call into objective C, and display the string in the iPhone simulator's console window:
document.location.href = "http://debugger/" +
encodeURIComponent(outputString);
and on the objective C side:
//--------------------------------------------------------------------
- (BOOL)webView:(UIWebView*)webView
shouldStartLoadWithRequest: (NSURLRequest*)req
navigationType:(UIWebViewNavigationType)navigationType {
if ([[[req URL] host] isEqualToString:#"debugger"]){
// do stuff with [[req URL] path]
}
}
That said, I have an app that is heavy on the UiWebView / javascript stuff, and I tend to do most javascript dev in Chrome (simulating what is necessary from the iPhone environment)

I get the awesome way to debug UIWebView Or
SFSafariViewController.
I hope It will Help.
Step 1:
Open Safari VC In Your Mac (hahaha Don't make your face, If I am saying in your Macbook just follow this my steps)

Step2: Go at Safari preferences And Click on Advance. 

You will Get this setting on your MacBook Screen.
Now enable the Show to develop menu in menu bar.

 Now Your All work is done. 

Are you thinking I am kidding :P :P no man...


Step3: Run your application in Device or Simulator. (Don’t Think Just run )
And go in your application where you are opening your Webview or SFSafariViewController.
Till now you did not understand I know. Be cool and see my next step.

Step4: Open Safari In your MacBook and Click on Develop Option from the Menu bar. 

Did you get something your MacBook, iPad/ iPhone is Displaying Right?????


Step5: Its Done. click your device and click on URL New popup will come out like This.



Step6: what are you looking now its over here all the steps.
Now debug your Webpage on this console.
Be happy and enjoy your day while doing coding With a cup of tea or
Coffee.
IMP: Don't forget to enable See Below Image









I haven't tried this yet, but take a look at this Weinre
Looks very promising.

This is an old question. But I'll still like to share my two cents.
I have been using jsconsole.com for remote debugging. It's easy. Just include a script tag and use console logs to debug by printing. This can also be used for debugging on a real device.

Old question, but I think I found the best solution, in my case you need to debug uiwebview, but I had no access to the IOS app and only to the html content and I had to view some JS logs, I added the following code to load the light firebug JS and show it automatically:
calling it from JS
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = 'https://getfirebug.com/firebug-lite-debug.js';
document.head.appendChild(script);
or load it from html
<script type="text/javascript" src="https://getfirebug.com/firebug-lite-debug.js"></script>

You can set up a system like that used in PhoneGap to send messages from JavaScript to Objective-C and log from there. In a nutshell, they are setting document.location with a custom scheme and blocking that scheme in the delegate callback.
You can take advantage of the fact that a UIWebView is most of the delegates for a WebView. WebKit is technically undocumented for iPhone, but mostly the same as specified in the desktop WebKit headers, possibly including the WebScriptObject. I use this for debugging, but be sure to strip this code out before submitting to Apple.
To get a WebView from a UIWebView, implement a delegate method like -(void) webView:(id)inWebView didFinishLoadForFrame:(id)inWebFrame in a subclass of UIWebView. Call super if you use that one.

Related

Avoid/Bypass Dev tools detection in Chrome?

I've been trying to get a video source from a web site but when I open the dev tools to do so, It shows me this message: "Dont open Developer Tools".
So far I have tried:
Turn off javascript ->doesn't work, doesn't load the video.
Find the function:
olplayer.src({type:"application/x-mpegURL",src:"https://127.0.0.1/no_video.mp4.m3u8"});
document.body.innerHTML="";
document.write(" Dont open Developer Tools. ");
throw new Error(" Dont open Developer Tools. ");
self.location.replace('https:'+window.location.href.substring(window.location.protocol.length));
set a breakpoint and reload, run:
Object.defineProperty(window, "console", {configurable: false});
Any ideas how to bypass this protection?
You are probably talking about a video hosted on hqq.tv. Their code uses a check() function which does all the nasty magic to block all hacking attempts, so the easiest way to bypass the protection altogether is to disable this function.
Since recently, Chrome supports local overrides for javascript code (I found out about this from this SO thread). A bit nicer explanation on how this works can be found on Medium.
So I went ahead and located the check() function (in my case it was hqq.tv/js/embed.129.js) and added it to Overrides. In the overridden version I found the check() function and added return true; to its beginning:
function check(){return true; var element=new Image(); ...
However, this only disables the Dev Tool protection, but doesn't make your life much easier in terms of saving the video. My own solution doesn't work on hqq.tv, nor had I any luck with the solution suggested on videohelp forum. However, I was able to capture the stream using Stream Recorder Chrome extension.
I Found a bypass for the detection, use FireBug Lite extension for chrome (or the browser u prefer). It bypasses the detection because it is an extension

Facebook app browser debugging [duplicate]

I'm developing website with a lot of HTML5 and CSS3 features. I'm also using iframe to embed several content on my website. It works fine if I open it using Chrome/Firefox/Safari mobile browser. However, if I share on facebook (post/page) and I opened it up with Facebook application with Facebook Internal Browser, my website is messed up.
Is there any tools or way to debug on Facebook Browser? Thanks.
This is how you can do the debugging yourself. It's painful, but the only way I've come across so far.
tl;dr Get the Facebook App loading a page on your local server so you can iterate quickly. Then print debug statements directly to the page until you figure out what is going on.
Get a link to a page on your local server that you can access on your mobile device (test in mobile safari that it works). See this to find out your local IP address How do you access a website running on localhost from iPhone browser. It will look something like this
http://192.xxx.1.127:3000/facebook-test
Post that link on your Facebook page (you can make it private so your friends aren't all like WTF?)
Click the posted link in the Facebook mobile App and it will open up in Facebook's mobile browser
Since you don't have a console, you basically need to print debug statements directly to the page so it is visible. Put debug statements all over your code. If your problems are primarily related to CSS, then you can iteratively comment out stuff until you've found the issue(s) or print the relevant CSS attributes using JavaScript. Eg something like (using JQuery)
function debug(str){$('body').append("<br>"+str);}
Quite possibly the most painful part. The Facebook browser caches very aggressively. If you are making changes and nothing has happened, it's because the content is cached. You can sometimes resolve this by updating the URLs, eg /facebook-test-1, /facebook-test-2, or adding dummy parameters eg /facebook-test?dummy=1. But if the changes are in external css or js sheets it sometimes will still cache. To 100% clear the cache, delete the Facebook App from your mobile device and reinstall.
The internal browser the Facebook app uses is essentially a uiWebView. Paul Irish has made a simple iOS app that lets you load any URL into a uiWebView which you then can debug using Safari's Developer Tools.
https://github.com/paulirish/iOS-WebView-App
I found a way how to debug it easier. You will need to install the Ghostlab app (You have a 7-day free trial there, however it's totally worth paying for).
In Ghostlab, add the website address (or a localhost address) you want to debug and start the session.
Ghostlab will generate a link for access.
Copy that link and post it on Facebook (as a private post)
Open the link on mobile and that's it! Ghostlab will identify you once you open that link, and will allow you to debug the page.
For debugging, you will have all the same tools as in the Chrome devtools (how cool is that!). For example, you can tweak CSS and see the changes applied live.
If you want to debug a possible error, you can try to catch it and display it.
Put this at the very top of your code:
window.onerror = function (msg, url, lineNo, columnNo, error) {
var string = msg.toLowerCase();
var substring = "script error";
if (string.indexOf(substring) > -1){
alert('Script Error: See Browser Console for Detail');
} else {
var message = [
'Message: ' + msg,
'URL: ' + url,
'Line: ' + lineNo,
'Column: ' + columnNo,
'Error object: ' + JSON.stringify(error)
].join(' - ');
alert(message);
}
}
(Source: MDN)
This will catch and alert your errors.
Share a link on Facebook (privately), or send yourself a message on Facebook Messenger (easier). To break the cache, create a new URL every time, e.g. by appending a random string to the URL.
Follow the link and see if you can find any errors.
With help of ngrok create temporary http & https adress instead of your ordinary localhost:3000(or other port) and you could run your app on any devices. It is super easy to use.
and as it was written above all other useful information you should write somewhere inside div element (in case of React I recommend to put onClick on that div with force update or other function for getting info, sometimes it helps because JS in FB could be executed erlier than your information appears). Keep in mind that alerts are not reliable, sometimes they are blocked
bonus from ngrok that in console you will see which files was
requested and response code (it will replace lack of network tab)
and about iFrame.If you use it on other domain and you rely on cookies - you should know that facebook in-app browser blocks 3rd party cookies
test on Android and iOS separately because technicaly they use different browsers

UIWebView Javascript Window to Window Communication

I'm working on an iOS app in which I'm trying to use UIWebView to display a variety of websites. Recently I finished logic to inject Javascript into the UIWebView to catch instances of window.open, window.close, and window.opener.focus. In short, to do so, I inject JS that overrides the aforementioned JS functions, which includes creating an iframe with a specific scheme that I can catch in the app's webView:shouldStartLoadWithRequest:navigationType method. This is all working OK for now, including window.open creating a new UIWebView rather than loading in the same window.
Now though, the issue has come up where there's no feasible solution for JS communication between windows. If the child window tries to call to window.opener or window.parent, it's always returning a null value, and thus, it can't communicate back to the original web view.
In an effort to see what iOS browsers are able to effectively perform window-to-window communication, I found that of the 9 browsers I have on my iPhone, only Safari was able to effectively perform this communication successfully. This leads me to believe that there's something with UIWebView that prevents full JS window-to-window communication from being possible.
Has anyone had any success with getting UIWebView to fully integrate with all JS logic, namely window-to-window communication? Or have proof that JS window-to-window communication isn't possible? Any direction or advice is appreciated. Thanks!
Found possible solution.
Add JavaScriptCore.framework to Linked Frameworks and in your webViewDidFinishLoad:
JSContext *parentCtx = [self.parentWebView valueForKeyPath:#"documentView.webView.mainFrame.javaScriptContext"];
JSContext *childCtx = [self.childWebView valueForKeyPath:#"documentView.webView.mainFrame.javaScriptContext"];
childCtx[#"window"][#"opener"] = parentCtx[#"window"];
Now when you call window.opener.test() from childWebView, it will fire test function in parentWebView!
I'm not sure about private API.
Works on iOS 7 only
Swift version
import JavaScriptCore
let jsContextA = webA.valueForKeyPath("documentView.webView.mainFrame.javaScriptContext")
let jsContextB = webB.valueForKeyPath("documentView.webView.mainFrame.javaScriptContext")
//Original objc code : jsContextB[#"window"][#"opener"] = jsContextA[#"window"];
jsContextB!.setObject("opener", forKeyedSubscript: "window")
jsContextB!.setObject(jsContextA!.objectForKeyedSubscript("window"), forKeyedSubscript: "opener")

how can I force IE9 to "see" the most current javascript when using the debugger?

I'm using IE9 to debug a web app. I made some changes to the javascript after loading the page. I'm not able to get IE9 to stop on the new code. The message is "The code in the document is not loaded". I can set breakpoints when I'm not debugging, but they won't be valid when I start debugging. I'm using IE7 Browswer Mode, IE7 Document Mode.
Things I've tried:
close dev tools window, re-open
stop debugging, start debugging
Ctrl R in dev tools window (same as Clear Browser Cache button)
Ctrl R on the IE9 web page
Ctrl F5 on the Ie9 web page
Clear browser cache for this domain
Check (set) Always refresh cache from server
Next thing to try (I guess) would be closing IE completely. Is that the fix for this? If so, yuck. It takes me a couple of minutes to set the page up so doing that after every JS change really stinks. I can use FF4 to develop the JS, but the JS issue I'm seeing is specific to IE7 so I have to do it this way.
>> How can I get IE9 (running in IE7 mode) to reliably debug the most current JS from the server?
This issue wasn't related to caching etc. IE9 was hitting a script error (missing closing paren) in the new code and not allowing breakpoints anywhere in the script. IE seemed very quiet about the script error though. Anyway, fixing the script error fixed the issues with breakpoints / caching.
If you have access to the code:
In you javascript file reference add a query string, something like this:
<script src="Scripts/main.js?v=1" type="text/javascript"></script>
And every time you change in the js file change the v value to something else, like that the browser will feel that this is a new file and will get it.
Add this:
window.applicationCache.addEventListener('updateready', function (e)
{
if (window.applicationCache.status == window.applicationCache.UPDATEREADY)
{
window.applicationCache.swapCache();
if (confirm('A new version of this site is available. Load it?'))
window.location.reload();
}
}, false);
I found this solution somwhere in the Net. Sorry, but I don't remember the author. It works for me when I debug Web App with JavaScript in Visual Studio and use IE.
I found this question based on the "the code in the document is not loaded" error message. I'm not using IE7 document mode or any of that, just IE9.
Like jcollum, my issue wasn't related to caching.
I'm using MVC.Net, and someone had set up a piece of javascript to rely on a string in the ViewBag. I changed a couple things, and that ViewBag string disappeared, so the resulting javascript looked something like this:
if(!()) {
// Some code
}
Javascript died right here, and wouldn't process the rest of the code in the block. This was confusing, as it was still trying to execute javascript in a different set of script tags, but which relied on a variable set in the other block it wouldn't load.
So, basically, a syntax error was introduced via strange means, and the debugger refused to load some of the code which came after it. Another lesson on the dangers of ViewBag.

Bookmarklet window.open blocked by most browsers, delicious/tumbler's does not

Hey guys --
The website I'm working on requires a bookmarklet launchable from your bookmark toolbar.
I've noticed that some browsers are blocking my bookmarklet.
However, similar bookmarklets such as Tumblr's, Twitter's, and Delicious' have workarounds where their bookmarklet pages are not getting blocked.
My current launch script looks like:
javascript:void(window.open(%22http://mywebsite.com/share/form?
u=%22+encodeURIComponent(location.href)+%22
&t=%22+encodeURIComponent(document.title),
%xz%22,%22status=0,toolbar=0,location=0,menubar=0,resizable=false,scrollbars=false,height=379,width=379%22));
It's a simple window.open, which is clearly not enough to handle certain exceptions
The sites, below is Delicious' launch script, all seem to have workarounds that look very similar to that of below:
javascript:(function(){
f='http://www.delicious.com/save
?url='+encodeURIComponent(window.location.href)+
'&title='+encodeURIComponent(document.title)+
'&notes='+encodeURIComponent(''+(window.getSelection?window.getSelection():document.getSelection?document.getSelection():document.selection.createRange().text))+
'&v=6&';
a=function(){
if(!window.open(f
+'noui=1&jump=doclose','deliciousuiv6','location=yes,links=no,scrollbars=no,toolbar=no,width=550,height=550'))
location.href=f+'jump=yes'};
if(/Firefox/.test(navigator.userAgent))
{setTimeout(a,0)}else{a()}})()
It seems like they append some extra GET parameters to the URL if the user agent is firefox.
I'm assuming then, if that is the case, that the init scripts on the actual page loading from the bookmarklet handles this exception somehow?
Has anyone had any experience with this issue? Would you be able to point me to any resources or tips? I have been stuck with this roadblock for sometime now.
Thanks in advance
the delicious bookmark does not directly invoke the window.open() - it creates a function (called a in there) which is then executed in a setTimeout(a,0) for firefox (i assume the problem you have is in firefox).
You can try a similar method, and see if it works for you.

Categories

Resources