I have a fairly complicated page built using JSP, JavaScript, jQuery, and css. It works fine in Chrome, Firefox, and IE10. However, it doesn't work in IE8 - JavaScript specific to that particular page doesn't load, the HTML is broken, some css is loaded, but not all.
The page called via an AJAX call:
jQuery.ajax({
url : url,
dataType: "html",
cache : false,
beforeSend : ...
Capturing network activity in Developer tools shows that the relevant script files have started to arrive, but only 155B-157B were received. Result code is 304, time is shown as under 1ms.
Same reporting for Chrome shows that the same JS files are 3-7-12KB in size, took 3-10ms to arrive, with HTTP code 200.
The same page requested via a regular GET request loads normally.
The problem looks like a known aggressive-caching issue in IE8, but somehow setting cache : false doesn't prevent 304 from happening.
How can I make this work?
Using jQuery version 1.4.2, IE8 on Win7. tc Developer server 2.8.2.
One of the JavaScript files being retrieved via the AJAX call contained, among other code, this method:
jQuery(document).ready(function() {
return validate...();
}
IE8 was not able to process it, and discarded all surrounding JavaScript.
I removed the lines above, and moved the validation method to the function that was called on Complete: of that AJAX call, and everything started working.
Related
I want to create a custom profiler for Javascript as a Chrome DevTools Extension. To do so, I'd have to instrument all Javascript code of a website (parse to AST, inject hooks, generate new source). This should've been easily possible using chrome.devtools.inspectedWindow.reload() and its parameter preprocessorScript described here: https://developer.chrome.com/extensions/devtools_inspectedWindow.
Unfortunately, this feature has been removed (https://bugs.chromium.org/p/chromium/issues/detail?id=438626) because nobody was using it.
Do you know of any other way I could achieve the same thing with a Chrome Extension? Is there any other way I can replace an incoming Javascript source with a changed version? This question is very specific to Chrome Extensions (and maybe extensions to other browsers), I'm asking this as a last resort before going a different route (e.g. dedicated app).
Use the Chrome Debugging Protocol.
First, use DOMDebugger.setInstrumentationBreakpoint with eventName: "scriptFirstStatement" as a parameter to add a break-point to the first statement of each script.
Second, in the Debugger Domain, there is an event called scriptParsed. Listen to it and if called, use Debugger.setScriptSource to change the source.
Finally, call Debugger.resume each time after you edited a source file with setScriptSource.
Example in semi-pseudo-code:
// Prevent code being executed
cdp.sendCommand("DOMDebugger.setInstrumentationBreakpoint", {
eventName: "scriptFirstStatement"
});
// Enable Debugger domain to receive its events
cdp.sendCommand("Debugger.enable");
cdp.addListener("message", (event, method, params) => {
// Script is ready to be edited
if (method === "Debugger.scriptParsed") {
cdp.sendCommand("Debugger.setScriptSource", {
scriptId: params.scriptId,
scriptSource: `console.log("edited script ${params.url}");`
}, (err, msg) => {
// After editing, resume code execution.
cdg.sendCommand("Debugger.resume");
});
}
});
The implementation above is not ideal. It should probably listen to the breakpoint event, get to the script using the associated event data, edit the script and then resume. Listening to scriptParsed and then resuming the debugger are two things that shouldn't be together, it could create problems. It makes for a simpler example, though.
On HTTP you can use the chrome.webRequest API to redirect requests for JS code to data URLs containing the processed JavaScript code.
However, this won't work for inline script tags. It also won't work on HTTPS, since the data URLs are considered unsafe. And data URLs are can't be longer than 2MB in Chrome, so you won't be able to redirect to large JS files.
If the exact order of execution of each script isn't important you could cancel the script requests and then later send a message with the script content to the page. This would make it work on HTTPS.
To address both issues you could redirect the HTML page itself to a data URL, in order to gain more control. That has a few negative consequences though:
Can't reload page because URL is fixed to data URL
Need to add or update <base> tag to make sure stylesheet/image URLs go to the correct URL
Breaks ajax requests that require cookies/authentication (not sure if this can be fixed)
No support for localStorage on data URLs
Not sure if this works: in order to fix #1 and #4 you could consider setting up an HTML page within your Chrome extension and then using that as the base page instead of a data URL.
Another idea that may or may not work: Use chrome.debugger to modify the source code.
I am writing a chrome extension that injects a div into a website with a content script. The content script makes an AJAX request to a website that I cleared in the manifest.json file and it inserts the data into the div with innerHTML. Part of what the AJAX request returns is javascript that needs to be executed. The AJAX request from within the content script works fine.
When I make the same AJAX request from a regular website, the javascript that is returned executes just fine, but when I make the AJAX request from the content script it does not execute. No errors are displayed in the console. I don't want to reload the website, if possible.
I assume that this is a security 'feature' and not a bug. How can I turn off or circumvent this behavior?
First off what Rob W said is very important, if you don't already know it, a good explanation of the different environment a content script runs in is useful.
You might want to check this out. It's not 100% what you're looking for but the main part is there. Basically from your background page (if you don't have one already create one), you use chrome.tabs.executeScript() to execute the script you've downloaded. That runs the javascript in the real page context instead of the "content script" context. All you need now is to get that script (in string form) to the background page, and determine the tabId to execute it on (from the sender tab)
You can use chrome.extension.sendMessage to send it to the background page, and in the background.js, use chrome.extension.onMessage to receive the message with your script. From there use the sender argument to get the tabId (sender.tab.id), and build your executeScript call.
One more helpful hint, page scripts (dynamic javascript executions) in chrome by default don't show up in any set way in the chrome debugger, but you can append something like this to the string of your javascript:
"\n//# sourceURL=/myFolder/myDynamicJavascript.js"
This will make this script always show up with the "/myFolder/myDynamicJavascript.js" path for the chrome debugger, allowing you to set breakpoints in the js code you've inserted. It's a lifesaver.
Here I am, with another problem. :) Maybe this time I'll get some responses. :P I'm using jquery.form.js plugin, to process forms with file fields. It's simple implementation.
$this.ajaxSubmit({
data: { 'ajax' : 'true' },
dataType: 'html',
success: parseRsp,
error: parseErr
});
It works on Chrome, Opera and new Firefoxes. It doesnt on Firefox 3.x and all versions of IE. Plugin throws some Server abort problem, but after some changes in code to debug it, I get it. Function getDoc(iframe) throws Permission denied in IE. But why? It's not cross-domain or something? I even add <script>document.domain = 'mydomain.com';</script> but that doesn't work either. Any ideas?
BTW. we are using APE Project. It probably makes some document.domain modifications, but on Chrome console, on page where is form, when I type document.domain i'm still getting mydomain.com, so...
I had a similar issue just now.
The problem was that I was setting the document.domain property in the parent document. The api document that is inside the iframe is vanilla json, and, as such, has no opportunity of setting a document.domain. Hence the permission issue.
So I had to remove the document.domain assignment from the parent.
I'm using xmlhttprequest to call servlet. It is working fine in Firefox. But, in IE, only if I click refresh button, it is working(that too sometimes). Otherwise, it is not triggering. Moreover, the response text is displayed without calling the servlet. Is that using Cache or what? I don't have any idea . Help me out please.
MSIE is too eager in caching XHR requests. The only feasible way to get around this is to add a querystring with a timestamp to the XHR URL.
var url = '/url/to/your/servlet?' + new Date().getTime();
Thanks one and all. Actually, I used "GET" instead of "POST" while calling the servlet in javascript. When I tried POST, it is working fine.
To get around IEs over zelous caching of xhr you must get your servlet to add
Cach-Control:max-age=0
to the response headers of all html and .js files served up.
This will cause a revalidate of all files with this response, next time they are requested from IE including XHR. (must-revalidate did not seem to work on xhr loaded java script file, not sure why)
Be sure to clear the IE cache after this is done for it to take effect the next load.
IE will behave nicely with this setting. But dont put this into production of course.
Ok, so all the rage these days is having a site like this:
mysite.com/
mysite.com/about
mysite.com/contact
But then if the user has Javascript enabled, then to have them browse those pages with Ajax:
mysite.com/#/
mysite.com/#/about
mysite.com/#/contact
That's all well and good. I have that all working perfectly well.
My question is, if the user arrives at "mysite.com/about", I want to automatically redirect them to "mysite.com/#/about" immediately if they have Javascript.
I have it working so if they arrive at "mysite.com/about", that page will load fine on its own (no redirects) and then all clicks after that load via ajax, but the pre-fragment URL doens't change. e.g. if they arrive on "mysite.com/about" and then click "contact", the new URL will be "mysite.com/about#/contact". I really don't like that though, it's very ugly.
The only way I can think of to automatically redirect a user arriving at "mysite.com/about" to "mysite.com/#/about" is to have some javascript in the header that is ONLY run if the page is NOT being loaded via ajax. That code looks like this ($ = jQuery):
$(function(){
if( !location.hash || location.hash.substr(1,1) != '/' ) {
location.replace( location.protocol+'//'+location.hostname+'/#'+location.pathname+location.search );
}
});
That technically works, but it causes some very strange behavior. For example, normally when you "view source" for a page that has some ajax content, that ajax content will not be in the source because you're viewing the original page's source. Well, when I view source after redirecting like this, then the code I see is ONLY the code that was loaded via Ajax - I've never seen anything like that before. This happens in both Firefox 3.6 and Chrome 6.0. I haven't verified it with other browsers yet but the fact that two browsers using completely different engines exhibit the same behavior indicates I am doing something bad (e.g. not just a bug with FF or Chrome).
So somehow the browser thinks the page I'm on "is" the Ajax page. I can continue to browse around and it works fine, but if I e.g. close Firefox and re-open it (and it re-opens the pages I was on), it only reloads the Ajax fragment of the page, and not the whole wrapper, until I do a manual refresh. (Chrome doesn't do this though, only Firefox). I've never seen anything like that.
I've tried using setTimeout so it does not do the redirect until after the page has fully loaded, but the same thing happens. Basically, as far as I can tell, this only works if the fragment is put there as the result of a user action (click), and not automatically.
So my question is - what's the best way to automatically redirect a Javascript capable browser from a "normal" URL to an Ajax URL? Anyone have experience doing this? I know there are sites that do this - e.g., http://rdio.com (a music site). No weirdness happens there, but I can't figure out how they're doing it.
Thanks for any advice.
This behavior is like the new twitter. If you type the URL:
http://twitter.com/dinizz
You will be redirected to:
http://twitter.com/#!/dinizz
I realize that this is done, not with javascript but in the server side. I am looking for a solution to implements this using ruby on rails.
Although I suggest you to take a look on this article: Making AJAX Applications Crawlable