new ActiveXObject("InternetExplorer.Application") missing window.document object - javascript

I have a weird problem with this code. Basically I am loading a new ActiveXObject ("InternetExplorer.Application") and putting a reference to it onto the IE window object. I then load up an HTML file and wait for it to finish loading before trying to run script against the new window. When I launch IE via VS2010 with or without debugging (i.e. F5 or CTRL-F5) this code works and I get a reference to lDebugWindow.document.documentElement object.
The problem -- But when I just launch IE from the WIN7 taskbar, lDebugWindow.document is always undefined. Any ideas what is different about IE when launched from VS2010 versus the taskbar? Here is the code with the line highlighted that behaves differently from VS2010 vs. taskbar launch of IE:
function wfDebugXml(pNode)
{
window.lDebugWindow = new ActiveXObject("InternetExplorer.Application");
lDebugWindow.navigate(sFrameworkBase + "/GlobalDebugger/Debug.htm");
lReady = false;
for (var i = 0; i < 40; i++)
{
if (!lReady)
{
try
{
lDebugWindow.onreadystatechange = wfDebugRenderXml(pNode);
}
catch (e) { };
}
}
}
function wfDebugRenderXml(pNode)
{
// THE NEXT LINE IS THE ONE THAT HAS THE PROBLEM
var lDocumentElement = lDebugWindow.document.documentElement;
var lXsltDoc = Sarissa.getDomDocument();
lXsltDoc.async = false;
lXsltDoc.load("GlobalDebugger/Debug.xsl");
var lXslt = new XSLTProcessor();
lXslt.importStylesheet(lXsltDoc);
var lXmlDoc = Sarissa.getDomDocument();
lXmlDoc.loadXML(pNode.xml);
var lXmlOutput = lXslt.transformToFragment(lXmlDoc, lDebugWindow.document);
while (lDocumentElement.childNodes.length > 0)
{
lDocumentElement.removeChild(lDocumentElement.lastChild);
}
lDocumentElement.appendChild(lXmlOutput);
lDebugWindow.Visible = true;
}

I suppose your problem is gone now. For anyone else, it might be a right access issue :
Under Win7 IE runs in a low integrity processus. I suppose it might not be possible to get COM pointers between processus with different levels of integrity.
I used ChangeWindowMessageFilter to fix my issue but I was communicating via messages. It might be a good point to start Googling though.

Related

Cannot get ExecuteScriptAsync() to work as expected

I'm trying to set a HTML input to read-only using ExecuteScriptAsync. I can make it work, but it's not an ideal scenario, so I'm wondering if anyone knows why it doesn't work the way I would expect it to.
I'm using Cef3, version 63.
I tried to see if it's a timing issue and doesn't appear to be.
I tried invalidating the view of the browser but that doesn't seem to help.
The code I currently have, which works:
public void SetReadOnly()
{
var script = #"
(function(){
var labelTags = document.getElementsByTagName('label');
var searchingText = 'Notification Initiator';
var found;
for (var i=0; i<labelTags.length; i++)
{
if(labelTags[i].textContent == searchingText)
{
found = labelTags[i]
break;
}
}
if(found)
{
found.innerHTML='Notification Initiator (Automatic)';
var input;
input = found.nextElementSibling;
if(input)
{
input.setAttribute('readonly', 'readonly');
}
}})()
";
_viewer.Browser.ExecuteScriptAsync(script);
_viewer.Browser.ExecuteScriptAsync(script);
}
now, if I remove
found.innerHTML='Notification Initiator (Automatic)';
the input is no longer shown as read-only. The HTML source of the loaded webpage does show it as read-only, but it seems like the frame doesn't get re-rendered once that property is set.
Another issue is that I'm executing the script twice. If I run it only once I don't get the desired result. I'm thinking this could be a problem with V8 Context that is required for the script to run. Apparently running the script will create the context, so that could be the reason why running it twice works.
I have been trying to figure this out for hours, haven't found anything that would explain this weird behaviour. Does anyone have a clue?
Thanks!

Why/How is my code causing a memory leak?

I have written the following JavaScipt code within a Spotfire TextArea. I include the application and tag for completeness, but I don't believe my issue is Spotfire-specific. Essentially, I have a timer which runs every 5 minutes, and clicks on a link (clickLink('Foo');) to trigger execution of some Python code elsewhere in the application. If the application also contains a timestamp of the last full update, which occurs every 30 minutes in the same manner (clickLink('Foo');):
function reportTimestamp() {
var timeNow = new Date();
var hoursNow = timeNow.getHours();
var minutesNow = timeNow.getMinutes();
var secondsNow = timeNow.getSeconds();
return hoursNow + ":" + minutesNow + ":" + secondsNow;
};
function timeBasedReaction(timestampAge){
if (timestampAge >= 1800) {
clickLink('Foo');
clickLink('Bar');
} else if (timestampAge >= 300) {
clickLink('Foo');
};
};
/*
function timeBasedReaction_B(timestampAge){
if (timestampAge >= 300) {
clickLink('Foo');
if (timestampAge >= 1800) {
clickLink('Bar');
};
};
};
*/
function clickLink(linkName) {
var clickTarget = document.getElementById(linkName).children[0];
clickTarget.click();
};
function checkTimestampAge() {
console.log(reportTimestamp());
var myTimeStamp = document.getElementById('Timestamp').children[0]
var timeStampMS = new Date(myTimeStamp.textContent).getTime();
var currentDateMS = new Date().getTime();
var timestampAgeSeconds = (currentDateMS - timeStampMS)/1000;
timeBasedReaction(timestampAgeSeconds);
};
function pageInitialization() {
checkTimestampAge();
var myTimer = null;
var timerInterval = 300000;
myTimer = setInterval(function(){checkTimestampAge()},timerInterval);
}
pageInitialization();
For reasons unclear to me, running this code in the application or in a web browser starts off fine, but eventually leads to very large memory allocation.
I've tried to read
4 Types of Memory Leaks in JavaScript and How to Get Rid Of Them,
JS setInterval/setTimeout Tutorial, and
An interesting kind of JavaScript memory leak, and it's a start, but I don't know enough to really understand what I'm doing wrong and how to correct it.
Thanks, and sorry for the huge block of text.
This causes a memory leak because of how Spotfire handles Javascript which has been associated with/loaded into a TextArea.
Both in the desktop client, as well as in the Webplayer instance, when the page is loaded, all the portions of that page are loaded, include the TextArea and including the Javascript associated therein. My previous understanding in the comments above:
"the code is intended to run when the page loads, and it was my understanding that it would stop/be cleared if the page was re-loaded or someone navigated away from it"
was incorrect. One of the script's actions was to update/redraw the HTML location in the TextArea. This, in turn, reloads the TextArea but does not clear the existing Javascript code. However, it's not really accessible anymore, either, since var myTimer = null actually creates a new myTimer rather than nulling-out the existing one. In this way, instances of myTimer increase geometrically as instances of function timeBasedReaction run and continually update the underlying TextArea and load in more of the same Javascript.
To anyone who ha a similar issue and come here, it's been over 3 months and I haven't figured out how to solve this once and for all. If I do, I'll try to come back with another update.

Debugging Web Workers in Safari Web Inspector

Chrome's Dev Tools are great for debugging web workers as I can "browse" into that JavaScript environment and set break points. Even the console works as expected.
On Safari, it is a completely different story. console.log from the web worker doesn't even print in the console. I see the worker script loaded and I put a break point on it, but it doesn't break. I don't even see the scripts that were loaded with importScripts.
How can I use Safari's Web Inspector to troubleshoot problems?
Not that I think it matters, but I'm using Safari 8.
Insert the debugger; code in your source
Usage: Insert it anywhere you want to add a breakpoint and when developer console is open automatically execution will pause at that line
var a = 50;
a = a + 5;
debugger; //--> execution is paused here
a = a - 5;
For more info see the Debugger Documentation on mozilla.org
In lieu of console.log, you can use postMessage. postMessage should allow you to send debug messages to the safari console.
Here is a great example on how to do that, I pasted the main idea below:
//
// In the Main thread
//
var worker = new Worker('/path/of/webworker/code.js')
worker.onmessage = function (e) {
var result = JSON.parse(e.data);
if(result.type == 'debug') {
console.log(result.msg);
} else if(result.type == 'response') {
// ... use result.answer ...
}
}
//
// In the WebWorker
//
function debug(msg) {
postMessage(JSON.stringify({type:'debug',msg:msg}));
}
onmessage = function (e) {
var inputData = e.data;
// work on input data
debug('Working OK');
// work some more
// ...
postMessage(JSON.stringify({type:'response', answer:42}));
};
If you don't want to play around with postMessage though, David Flanagan made a wrapper for it here that should allow you to at least do debugging with console.log

IE 10 + jQuery - Not able to use "append" function

I am running an HTML 5 application using the KendoUI framework. Once of the screens deal with XML data that needs to be parsed and processed.
This screen needs to be shown as a popup and that data is shown in a grid inside this popup. To do this, I am calling a function on clicking the "show-popup" button inside which I have the following piece of code :
var tTranslationXML = XMLFromString(_SelectedCategoryValueRecord.DisplayTextTranslation);
.
.
.
// other stuff but nothing that changes "tTranslationXML"
.
.
if (_SelectedCategoryValueRecord.DisplayTextTranslation) // and there are values in the translation field
{
var $language = $(tTranslationXML).find('Language');
var $oldTranslation = $($language).find("en-US");
if ($oldTranslation.length == 0)
$oldTranslation = $($language).find(GetCorrectedCase("en-US"));
if ($oldTranslation.length == 0) {
var $newTranslation = $.createElementNS("en-US").text(_UpdatedDisplayText);
$language.append($newTranslation);
}
}
And if you are wondering what "XMLFromString" is, its nothing but a simple helper to parse the XML data from a string variable
function XMLFromString(pXMLString)
{
if (!pXMLString)
pXMLString = "<Language></Language>";
if (window.ActiveXObject) {
var oXML = new ActiveXObject("Microsoft.XMLDOM");
oXML.loadXML(pXMLString);
return oXML;
} else {
return (new DOMParser()).parseFromString(pXMLString, "text/xml");
}
}
My issue is that this works fine on Chrome and Firefox but I get an error in IE10 when this particular line executes -
"$language.append($newTranslation);"
I am basically trying to append a new translation value to the contents of my variable here.
The error is as follows :
SCRIPT13: Type mismatch
jquery-1.8.3.min.js, line 2 character 71981
Any ideas on how to solve this?
Sorry for the delayed response.
I figured out that the issue was to avoid using the method "createElementNS" and instead use the "createElement" method when creating the parent node. Subsequent appendages to this node do not throw up any issues. However there will issues when you append to a node that was originally created using "createElementNS".
This seems specific to IE10 because the NS method worked fine on chrome, FF and Safari.
Thank you all for the tips and ideas.

help with Firefox extension in multiple windows

I'm writing a Firefox extension that creates a socket server which will output the active tab's URL when a client makes a connection to it. I have the following code in my javascript file:
var serverSocket;
function startServer()
{
var listener =
{
onSocketAccepted : function(socket, transport)
{
try {
var outputString = gBrowser.currentURI.spec + "\n";
var stream = transport.openOutputStream(0,0,0);
stream.write(outputString,outputString.length);
stream.close();
} catch(ex2){ dump("::"+ex2); }
},
onStopListening : function(socket, status){}
};
try {
serverSocket = Components.classes["#mozilla.org/network/server-socket;1"]
.createInstance(Components.interfaces.nsIServerSocket);
serverSocket.init(7055,true,-1);
serverSocket.asyncListen(listener);
} catch(ex){ dump(ex); }
document.getElementById("status").value = "Started";
}
function stopServer ()
{
if (serverSocket)
serverSocket.close();
}
window.addEventListener("load", function() { startServer(); }, false);
window.addEventListener("unload", function() { stopServer(); }, false);
As it is, it works for multiple tabs in a single window. If I open multiple windows, it ignores the additional windows. I think it is creating a server socket for each window, but since they are using the same port, the additional sockets fail to initialize. I need it to create a server socket when the browser launches and continue running when I close the windows (Mac OS X). As it is, when I close a window but Firefox remains running, the socket closes and I have to restart firefox to get it up an running. How do I go about that?
Firefox extension overlays bind to window objects. One way around this is to create an XPCOM component or find one that someone else already created to allow you to build functionality without binding it to the window objects.
Of course, section #2 below on Observer Notifications may be helpful as well.
Possible workaround: #1
Instead of calling "startServer()" each time a window is opened, you could have a flag called windowCount that you could increment each time you open a new window. If windowCount is greater than 0, don't call startServer().
As windows close, you could decrement the count. Once it hits 0, stop the server.
Here is information from the Mozilla forums on this problem:
http://forums.mozillazine.org/viewtopic.php?f=19&t=2030279
Possible workaround #2:
With that said, I've also found documentation for Observer Notifications, which may be helpful as there is a section on Application Startup and Shutdown:
https://developer.mozilla.org/en/Observer_Notifications
UPDATE:
Here are some resources on creating XPCOM components in JavaScript and in C++:
https://developer.mozilla.org/en/how_to_build_an_xpcom_component_in_javascript
http://www.codeproject.com/KB/miscctrl/XPCOM_Creation.aspx
https://developer.mozilla.org/en/creating_xpcom_components
You probably want to:
Move your code into a JavaScript component
Register your component as a profile-after-change observer
Whenever someone makes a connection to your socket, find the active window and return its URL.
Use something like
var wm = Components.classes["#mozilla.org/appshell/window-mediator;1"]
.getService(Components.interfaces.nsIWindowMediator);
var win = wm.getMostRecentWindow("navigator:browser");
var spec = win ? win.getBrowser().currentURI.spec : "";
var outputString = spec + "\n";
etc.

Categories

Resources