Dealing with Ghostery surrogates - javascript

Ghostery implements mock scripts (surrogates) so that pages don't fail on logic expecting tracking code.
In my case I had to write code that tracks asset and outbound clicks. The usual way to do that would be to check if the tracking code is loaded (in my case for _gat exposed by ga.js) but with surrogates this check would pass.
For some use cases that's fine and expected but we are dealing with links here. To ensure that the link is actually logged to GA I pushed a function to _gaq which (given that ga.js is loaded properly) would be executed.
With Ghostery that's not the case. I got links that would not trigger as the function with window.location.href = url would not be executed.
When I looked at the surrogate I found out it can change the location for me but I would have to do _gaq.push(['_link', url]).
I posted an issue and got a response that developers shouldn't bind functionality to third-party scripts. I get that and that's why before doing so I checked if _gat exists.
In the end I had to make a special case for Ghostery and attach their bizzare push to have links working with it.
You can check out the full implementation in this gist. If you want to reuse it and have compatibility with IE8 make sure to include a polyfill for String.trim().
How should I write custom tracking logic that does not rely in any way on the tracking code?
Using timeout for changing the url is out of the question as it would potentially corrupt hits on slow connections.
Also, poking the _gat object is not a reliable way as it's bad to rely on third-party scripts.

Web browsers are currently building a feature that will solve this problem:
https://developer.mozilla.org/en-US/docs/Web/API/navigator.sendBeacon
This won't widely implemented for a couple of months so stay tuned. For now, just add a setTimeout(function(){location.href=url}, 100) to catch errors and still have the link work.

Related

How to determine the line of javascript code which changes the url?

I have an existing site with a lot of javascript included. My javascript is adding a query string parameter (using history.replaceState) but right after the adding, it gets removed. How can I find the line of javascript who is removing my query string parameter? (I've been trying to place breakpoints in the Chrome dev tools on certain method calls but no luck so far.)
There is no real network navigation happening here, all changes come from javascript and angularjs.
With given information I can only say that its probably a redirection that must be removing your query parameter. Try enabling preserve network logs and then track the network calls to see if there are any redirections happening.
Following steps solved my problem:
First I've hijacked the pushState and replaceState methods to see when they are triggered. Everywhere where expected they were triggered. No other known calls are made. The catch is in the AngularJS $location component. It checks what happens onUrlChange and removes data which is no hash and is different from the baseUrl (as far as i can understand from checking briefly)

IE 11 Will not load systemjs

I am working with SystemJS and I have a pseudo-bootstrapper file that I use to check to make sure certain conditions are met before the loading of the main scripts to execute the page load. Here is a snippet of that code.
var obj = document.createElement('script');
obj.src = 'jspm_packages/system.js';
document.body.appendChild(obj);
This code does NOT execute the script, yet it does load it with a 200 code as evidenced by the network tab within the IE dev tools. There should be a global object "System" created, but it does not exist. Looking through the DOM, the object is properly created and appended to the body.
Does anyone know if this is strictly an issue with IE and SystemJS? I have no idea what's going on. I'm pulling my hair out, as per usual with the demon that is IE. I should note that every other browser works as expected, providing the "System" global variable.
EDIT Further testing has assured that this is not an issue with appendChild, as other scripts using the same method, execute on load just fine.
Reading this article tells us that your script may not run in IE11. The line in particular which is of interest is:
"Script elements with external resources should no longer execute during appendChild."
This appears to be what's happening.
EDIT: An alternate approach could be taken.
It would be a good idea to do condition checks on the server side before sending the response if you want to change page loading at the system.js level. If that is not possible then I'd suggest doing a redirect after the condition checks instead of appendChild.
The answer is that IE versions < Edge do not support promises. I needed a polyfill for IE 11.

Browser.ExecScript() stopped working after updating windows

I've set up a simple testbed for WatiN (ver 2.1) which reads:
var browser = new IE();
browser.GoTo("http://www.google.co.il"); // webpage doesn't matter really
browser.RunScript("alert(123)");
This works only if KB3025390 is not installed. Installing it breaks the above test with an UnAuthorizedAccessException which has HRESULT set to E_ACCESSDENIED. What gives? Is there any workaround?
Update: Using IWebBrowser2.Navigate2 along with "javascript:console.log(123)" type of scripts works however
it makes me feel uneasy using such a backchannel
the scripts run through this back-channel of .Navigate2() may only have a max length of about 2070 chars (give or take) otherwise they get forcibly truncated to this length leading to javascript errors upon attempting to run them
using .Navigate2(), even with the most trivial script, will clog the ready state of Internet Explorer for good in the sense that it will be set to READYSTATE_LOADING without any hope of getting rid of it. In simple terms this means that once you use this hack, you either have to perform every single subsequent operation in WatiN in a "dont-wait-for-webpage-to-load" fashion (GoToNoWait, ClickNoWait etc) lest your code freezes upon waiting for the browser to turn back to READYSTATE_COMPLETE (which will never come about ofcourse as already mentioned).
there appears to be a much broader issue here in the sense that I can't even access the properties of an IHtmlWindow2 object p.e. window.document throws an unauthorized exception again making it virtually impossible to transfer over to the C# world the return-values of the scripts I'm running (using Expando etc) for documents other than window.top.document (for the window.top.document window there is IWebBrowser2.Document which does the trick)
Update#2: The folks over at the selenium project have also noticed this issue:
https://code.google.com/p/selenium/issues/detail?id=8302
A bug report has been created as well:
https://connect.microsoft.com/IE/feedback/details/1062093/installation-of-kb3025390-breaks-out-of-process-javascript-execution-in-ie11
Update#3: IHTMLWindow2.setInterval and IHTMLWindow2.setTimeout also throw UnauthorizedAccess exceptions. These methods are not marked as deprecated in:
http://msdn.microsoft.com/ko-kr/library/windows/desktop/aa741505%28v=vs.85%29.aspx
yet they have wounded up suffering from the same cutbacks all the same.
Update#4: I gave the approach recommended in this post a shot:
https://stackoverflow.com/a/18546866/863651
In order to dynamically invoke the "eval" method of the IHTMLWindow2 object (or any other method really). Got the same "System.UnauthorizedAccessException" as above. So no joy here either.
Microsoft recommends using "eval" over "execscript" however after the above experiment I suspect that they are refering to accessing "eval" only from within the browser.
As far as I can tell thus far, when it comes to the full-fledged IE11+ using "eval" out-of-process (via COM) appears to have been completely prohibited along with any other function-invocation of the window object, the only exception being the back-channel of the .Navigate2() mentioned above.
It turns out Microsoft eventually backpedaled on its decision to kill off .execScript at COM-level. Just install the latest updates for Windows including kb3025390: One of the updates for IE that came after kb3025390 brings back .execScript functionality at COM-level
Note, however, that .execScript is not accessible through IE's javascript anymore. In that context it's gone for good.
fyi: this one is also not working
ieInstance.Document.Script.<methodNameString>(<commaSeperatedParameterString>)
try this worked for me at some places but not all places
ieObject.Navigate "javascript:<methodNameString>(<commaSeperatedParameterString>)", Null, "_parent"
or
ieObject.Navigate2 "javascript:"<methodNameString>(<commaSeperatedParameterString>)", Null, "_parent"
now trying to find out solution using eval
I have found a way around the problem of an update installing automatically. You can just create a simple batch file with following content.
{code}
#echo off
wusa /uninstall /kb:3025390/quiet /norestart
END
{code}
Then go to task scheduler, create a new task for this batch file to run every one hour or day as per your requirements. Add it as a system task so it runs in the background and does not affect the running automations.

How do I get the path of the currently running script with Javascript?

We have an IE extension implemented as a Browser Helper Object (BHO). We have a utility function written in C++ that we add to the window object of the page so that other scripts in the page can use it to load local script files dynamically. In order to resolve relative paths to these local script files, however, we need to determine the path of the JavaScript file that calls our function:
myfunc() written in C++ and exposed to the page's JavaScript
file:///path/to/some/javascript.js
(additional stack frames)
From the top frame I want to get the information that the script calling myfunc() is located in file:///path/to/some/javascript.js.
I first expected that we could simply use the IActiveScriptDebug interface to get a stacktrace from our utility function. However, it appears to be impossible to get the IActiveScript interface from an IWebBrowser2 interface or associated document (see Full callstack for multiple frames JS on IE8).
The only thing I can think of is to register our own script debugger implementation and have myfunc() break into the debugger. However, I'm skeptical that this will work without prompting the user about whether they want to break into the debugger.
Before doing more thorough tests of this approach, I wanted to check whether anyone has definitive information about whether this is likely to work and/or can suggest an alternative approach that will enable a function written in C++ to get a stack trace from the scripting engine that invoked it.
Each script you load may have an id and each method of the script calling myfunc() may pass this id to myfunc(). This means that first you have to modify myfunct() and finally alter your scripts and calls.
This answer describes how I solved the actual issue I described in the original question. The question description isn't great since I was making assumptions about how to solve the problem that actually turned out to be unfounded. What I was really trying to do is determine the path of the currently running script. I've changed the title of the question to more accurately reflect this.
This is actually fairly easy to achieve since scripts are executed in an HTML document as they are loaded. So if I am currently executing some JavaScript that is loaded by a script tag, that script tag will always be the last script tag in the document (since the rest of the document hasn't loaded yet). To solve this problem, it is therefore enough just to get the URL of the src attribute of the last script tag and resolve any relative paths based on that.
Of course this doesn't work for script embedded directly in the HTML page, but that is bad practice anyway (IMO) so this doesn't seem like a very important limitation.

New ActiveXObject('Word.Application') creates new winword.exe process when IE security does not allow object to be created

We are using MS Word as a spell checker for a few fields on a private company web site, and when IE security settings are correct it works well. (Zone for the site set to Trusted, and trusted zone modified to allow control to run without prompting.)
The script we are using creates a word object and closes it afterward. While the object exists, a winword.exe process runs, but it is destroyed when the Word object is closed.
If our site is not set in the trusted zone (Internet zone with default security level) the call that creates the Word object fails as expected, but the winword.exe process is still created. I do not have any way to interact with this process in the script, so the process stays around until the user logs off (users have no way to manually destroy the process, and it wouldn't be a good solution even if they did.)
The call that attempts to create the object is...
try {
wordApplication = new ActiveXObject('Word.Application');
} catch(error) {
// irrelevant code removed, described in comments..
// notify user spell check cannot be used
// disable spell check option
}
So every time the page is loaded this code may be run again, creating yet another orphan winword.exe process.
wordApplication is, of course, undefined in the catch block.
I would like to be able to detect the browser security settings beforehand, but I have done some searching on this and do not think that it is possible.
Management here is happy with it as it is. As long as IE security is set correctly it works, and it works well for our purposes. (We may eventually look at other options for spell check functionality, but this was quick, inexpensive, and does everything we need it to do.)
This last problem bugs me and I'd like to do something about it, but I'm out of ideas and I have other things that are more in need of my attention.
Before I put it aside, I thought I'd ask for suggestions here.
I have not found an answer to this problem, and I am disturbed at what the problem implies about Internet Explorer security (I forgot to mention in my previous post the version I am using : IE 7.)
However, I did implement a workaround that I am not happy with, but nevertheless feel more comfortable with than no check at all...
The code now attempts to open another object first, and if that fails the code assumes that Word will not open either and issues an error. From this point on, no more calls to new ActiveXObject() will be made and any attempt at a spell check will result in an error.
try {
oMSInfo = new ActiveXObject('Msinfo32.MSInfo.1');
} catch (error) {
// error handling code not shown...
return;
}
This object does not start a new process when the call to new ActiveXObject() fails. It also does not have a noticable affect on system resources.
If your browser creates an instance of an object, the object itself is not blocked by the browser security policies, except it is a security leak.
Try "application.visible=true", or "application.show()" to find out, where the application is asking for user interaction.
Hint: 'typeof application=="undefined"' means, the variable 'application' is not defined, where 'typeof application=="unknown"' means, more or less, it is a defined variable, stuffed with an external, proprietary object and if you really need to know how to handle it, read the manual -- pressing [F11] in any open window of the mentioned application could help in that case.
Might be a useful resource: https://learn.microsoft.com/en-us/office/vba/api/Word.Application

Categories

Resources