Расширение 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.