Переопределение open (), send () и связанных с ним методов XMLHttpRequest в мосте JavaScript IOS wkwebview.Это может быть сделано успешно? - PullRequest
0 голосов
/ 23 октября 2018

Идея заключается в том, чтобы собственный код IOS загружался в файл моста javascript до того, как в WKWebView загрузится веб-представление, содержащее потенциально сложный javascript и HTML.Этот мост javascript переопределяет методы open (), send (), fetch () и связанные с ними объекты XMLHttpRequst для маршрутизации всего трафика Http через собственный код IOS, а не напрямую через XHR.Если запрос является асинхронным, то создается Promise, и resolPromise () вызывается собственным кодом IOS, когда ответ готов к возвращению.

XMLHttpRequest.prototype.send =  function(data) {
console.log("Overriden ajax ::XMLHttpRequest.prototype.send:", arguments);
console.log('uri',this.uri);
    console.log("xhrObj::", this);
    if(!this.uri) {
        return this.realSend.apply(this, arguments);
    }

// generate a unique id to reference the promise later from native function
var promiseId = generateUUID();

updateReadyState(this, 2);

delegateHttpToNativeWithPromise(promiseId, this, this.uri, this.httpMethod, data)
.then(function(responseWrapper) {
      console.log('send resolve() - promise returned with responseWrapper',  responseWrapper);

      updateReadyState(responseWrapper.xhrObj, 3)
      updateReadyState(responseWrapper.xhrObj, 4)

      return responseWrapper.response;
      }, function(xhrObj) {
      console.log('send reject() - promise errorred with responseWrapper', responseWrapper);
      updateReadyState(responseWrapper.xhrObj, 3)
      updateReadyState(responseWrapper.xhrObj, 4)

      return responseWrapper.response;

      });

}

function delegateHttpToNativeWithPromise(promiseId, xhrObject, relativeIBAuthUri, methodType, payload) {
var promise = new Promise(function(resolve, reject) {
          methodType = methodType || "get";

          // save reference to promise in the global variable
          promises[promiseId] = { resolve, reject, xhrObject };

          try {
            // call native function
            if(window.webkit) {
                window.webkit.messageHandlers.nativeNetwork.postMessage({
                        promiseId: promiseId,
                        apiUri: relativeIBAuthUri,
                        methodType: methodType,
                        requestHeaders : requestHeaders,
                        payload: payload});
            } 
            requestHeaders = [];
          }
          catch(exception) {
            console.error(exception)
            // handle it somehow
          }
});
return promise;

}

function resolvePromise(promiseId, status, headers, encodedResponse, error) {
var response = atob(encodedResponse);
if(promises[promiseId]) {
    var xhrObj = promises[promiseId].xhrObject || null;
    if(xhrObj != null) {
        setReadOnlyProperty(xhrObj, "response", response);
        setReadOnlyProperty(xhrObj, "responseText", response);
        setReadOnlyProperty(xhrObj, "status", status);
        setReadOnlyProperty(xhrObj, "statusText", "OK");
        setReadOnlyProperty(xhrObj, "responseHeaders",headers);
    }
    if (error){
        console.log('resolvePromise - error', error);
        promises[promiseId].reject({response: response, xhrObj:xhrObj});
    } else{
        console.log('resolvePromise - success, resolving...');
        promises[promiseId].resolve({response: response, xhrObj:xhrObj});
    }
    // remove reference to stored promise
    delete promises[promiseId];
}
else {
    console.log('promiseId not found in ', promises);
}

}

XMLHttpRequest.prototype.getResponseHeader = function(header) {
console.log('getResponseHeader', this);
if(!this.responseHeaders || this.responseHeaders == null) {
    return null;
}
return this.responseHeaders[header];

}

XMLHttpRequest.prototype.getAllResponseHeaders = function() {
if(!this.responseHeaders || this.responseHeaders == null) {
    return "";
}
var response = "";
for(header in this.responseHeaders) {
    response += header+": "+this.responseHeaders[header]+"\r\n";
}
console.log('getAllResponseHeaders',response);
return response;

}

Можно ли успешно переопределить все эти методы?Мои первоначальные результаты указывают на НЕТ, потому что сложности нативных методов XHR не могут быть воспроизведены в Javascript.

...