Расширение ActiveXObject в javascript
Я хочу добавить некоторые функции отслеживания определенных вызовов методов объектов ActiveX в javascript.
обычно я создаю свой объект activeX следующим образом: var tconn = новый ActiveXObject ("Tconnector");
Мне нужно регистрироваться каждый раз, когда открыть метод вызывается на tconn и всех других экземплярах этого элемента управления activeX.
Я не могу изменить прототип tconn, потому что у него его нет!
Я думаю, что я могу создать манекен Функция ActiveXObject, которая создает прокси-объект для прокси-вызовов реальному. Вы можете мне помочь?
Примечание: написание прямой оболочки не может быть и речи, потому что в приложении уже есть 1000 вызовов этого activeX.
4 ответов
вы можете фактически переопределить ActiveXObject()
.
это означает, что вы можете попытаться построить прозрачный прокси-объект вокруг фактического объекта и подключить вызовы методов. Это означает, что вам придется создавать прокси-сервер вокруг каждого метода и свойства объекта ActiveX, если вы не уверены, что нет кода, вызывающего определенный метод или свойство.
Я построил небольшую обертку для "MSXML2.XMLHTTP"
"объект". Вероятно, есть все виды проблем, которые вы можете запустить в, так что возьмите это с зерном соли:
var ActualActiveXObject = ActiveXObject;
var ActiveXObject = function(progid) {
var ax = new ActualActiveXObject(progid);
if (progid.toLowerCase() == "msxml2.xmlhttp") {
var o = {
_ax: ax,
_status: "fake",
responseText: "",
responseXml: null,
readyState: 0,
status: 0,
statusText: 0,
onReadyStateChange: null
// add the other properties...
};
o._onReadyStateChange = function() {
var self = o;
return function() {
self.readyState = self._ax.readyState;
self.responseText = self._ax.responseText;
self.responseXml = self._ax.responseXml;
self.status = self._ax.status;
self.statusText = self._ax.statusText;
if (self.onReadyStateChange) self.onReadyStateChange();
}
}();
o.open = function(bstrMethod, bstrUrl, varAsync, bstrUser, bstrPassword) {
varAsync = (varAsync !== false);
this._ax.onReadyStateChange = this._onReadyStateChange
return this._ax.open(bstrMethod, bstrUrl, varAsync, bstrUser, bstrPassword);
};
o.send = function(varBody) {
return this._ax.send(varBody);
};
// add the other methods...
}
else {
var o = ax;
}
return o;
}
function Test() {
var r = new ActiveXObject('Msxml2.XMLHTTP');
alert(r._status); // "fake"
r.onReadyStateChange = function() { alert(this.readyState); };
r.open("GET", "z.xml");
r.send();
alert(r.responseText);
}
отказ от ответственности: особенно обработка async/onReadyStateChange, вероятно, не права, и у кода могут быть и другие проблемы. Как я уже сказал, это просто идея. Обращаться с осторожностью.
P. S.: А COM-объект не зависит от регистра, когда дело доходит до Метода и имена свойств. Эта оболочка (как и все JavaScript) чувствительна к регистру. Например, если ваш код вызывает both "Send()"
и "send()"
, вам понадобится скелет Метод" Send () " в обертке также:
o.Send = function() { return this.send.apply(this, arguments); };
большое спасибо за обертку. С вашей помощью я смог создать детектор xmlrequest для IE и FF и остальных.
Я добавил версию (в сочетании с другим примером), которая работает для FF, IE и остальной части банды,
if(window.XMLHttpRequest)
{
var XMLHttpRequest = window.XMLHttpRequest;
// mystery: for some reason, doing "var oldSend = XMLHttpRequest.prototype.send;" and
// calling it at the end of "newSend" doesn't work...
var startTracing = function () {
XMLHttpRequest.prototype.uniqueID = function() {
// each XMLHttpRequest gets assigned a unique ID and memorizes it
// in the "uniqueIDMemo" property
if (!this.uniqueIDMemo) {
this.uniqueIDMemo = Math.floor(Math.random() * 1000);
}
return this.uniqueIDMemo;
}
// backup original "open" function reference
XMLHttpRequest.prototype.oldOpen = XMLHttpRequest.prototype.open;
var newOpen = function(method, url, async, user, password) {
console.log("[" + this.uniqueID() + "] intercepted open (" +
method + " , " +
url + " , " +
async + " , " +
user + " , " +
password + ")");
this.oldOpen(method, url, async, user, password);
}
XMLHttpRequest.prototype.open = newOpen;
// backup original "send" function reference
XMLHttpRequest.prototype.oldSend = XMLHttpRequest.prototype.send;
var newSend = function(a) {
console.log("[" + this.uniqueID() + "] intercepted send (" + a + ")");
var xhr = this;
var onload = function() {
console.log("[" + xhr.uniqueID() + "] intercepted load: " +
xhr.status +
" " + xhr.responseText);
};
var onerror = function() {
console.log("[" + xhr.uniqueID() + "] intercepted error: " +
xhr.status);
};
xhr.addEventListener("load", onload, false);
xhr.addEventListener("error", onerror, false);
this.oldSend(a);
}
XMLHttpRequest.prototype.send = newSend;
}
startTracing();
}
else if (window.ActiveXObject) {
var ActualActiveXObject = ActiveXObject;
var ActiveXObject = function(progid) {
var ax = new ActualActiveXObject(progid);
if (progid.toLowerCase() == "msxml2.xmlhttp") {
var o = {
_ax: ax,
_status: "fake",
responseText: "",
responseXml: null,
readyState: 0,
status: 0,
statusText: 0,
onReadyStateChange: null
};
o._onReadyStateChange = function() {
var self = o;
return function() {
self.readyState = self._ax.readyState;
if (self.readyState == 4) {
self.responseText = self._ax.responseText;
self.responseXml = self._ax.responseXml;
self.status = self._ax.status;
self.statusText = self._ax.statusText;
}
if (self.onReadyStateChange) self.onReadyStateChange();
}
}();
o.open = function(bstrMethod, bstrUrl, varAsync, bstrUser, bstrPassword) {
console.log("intercepted open (" +
bstrMethod + " , " +
bstrUrl + " , " +
varAsync + " , " +
bstrUser + " , " +
bstrPassword + ")");
varAsync = (varAsync !== false);
this._ax.onReadyStateChange = this._onReadyStateChange
return this._ax.open(bstrMethod, bstrUrl, varAsync, bstrUser, bstrPassword);
};
o.send = function(varBody) {
return this._ax.send(varBody);
};
}
else
var o = ax;
return o;
}
}
небольшое исправление для "данные, необходимые для завершения этой операции, еще не доступны" в IE6-ожидание полноты перед заполнением свойств reponse:
self.readyState = self._ax.readyState;
if (self.readyState == 4) {
self.responseText = self._ax.responseText;
self.responseXml = self._ax.responseXml;
self.status = self._ax.status;
self.statusText = self._ax.statusText;
}
if (self.onReadyStateChange) self.onReadyStateChange();
проблема здесь в том, что кажется, что IE не позволит сохранить исходный конструктор activXObject и даст переполнение стека (;-) при создании ActualActiveXObject. кажется, что это специально для ActivX, потому что он работает при этом с другими объектами javascript.