将IMYWebLoader添加到蚂蚁mpaas框架中引发的问题和解决的问题

 

IMYWebLoader(WKHookAjax)是解决hook ajax请求参数丢失问题的开源框架。

解析:https://www.jianshu.com/p/4c33d6b05c4c

 

当把它加入到蚂蚁框架中会出现一些问题也会解决一些问题。

 

1.比如蚂蚁框架引入社保sdk:社保sdk有自己的wkwebview展示与ajax请求。加到蚂蚁工程里,社保sdk的webview发请求就被拦截了,按照蚂蚁框架的思路拦截后将走的是

EESBWebJSVCHandler.m

- (void)userContentController:(nonnull WKUserContentController *)arg1 didReceiveScriptMessageS:(nonnull WKScriptMessage *)arg2;{
    if( [arg2.name isEqualToString:@"PSDXMLHTTPREQUESTMESSAGE"]){
        //用于三方页面ajax请求
}
}

这个方法发请求与返回数据。但社保sdk是没有加载h5_message_channel.js的,而且也没有注册PSDXMLHTTPREQUESTMESSAGE,也没有实现原生请求的方法,所以社保webview就出现了问题。

解决这个问题的办法:

1.进社保前unregisterSchemeForCustomProtocol: 出社保后registerSchemeForCustomProtocol:

2.使用IMYWebLoader 将请求再次拦截并正常返回

代码是 [self.userContentController imy_installHookAjax];

需要判断社保webview

.h
#import <WebKit/WebKit.h>

NS_ASSUME_NONNULL_BEGIN

@interface WKWebViewConfiguration (PC)

@end

NS_ASSUME_NONNULL_END
.m

#import "WKWebViewConfiguration+PC.h"
#import <objc/runtime.h>
#import "IMYWebLoader.h"

@implementation WKWebViewConfiguration (PC)
+ (void)load{
    {
        Method originalMethod = class_getInstanceMethod([NSClassFromString(@"WKWebViewConfiguration") class], @selector(setUserContentController:));
        Method swizzledMethod = class_getInstanceMethod([self class], @selector(setUserContentControllerS:));
        method_exchangeImplementations(originalMethod, swizzledMethod);
    }
}
-(void)setUserContentControllerS:(WKUserContentController *)userContentController{
    [self setUserContentControllerS:userContentController];
if(isSdk){
    [self.userContentController imy_installHookAjax];
}

}

 

2.引入IMYWebLoader后蚂蚁容器加载离线包都没有问题。

 

3.引入IMYWebLoader后如果把蚂蚁容器的userContentController也imy_installHookAjax了,会影响到“蚂蚁容器加载三方链接”。

原因:因为蚂蚁框架ajax请求已经被原生PSDXMLHTTPREQUESTMESSAGE拦截替换了而且得由他返回数据,IMYWebLoader再次拦截后出现问题。

 

 

 

 

与PSDXMLHTTPREQUESTMESSAGE相关的js文件是h5_message_channel.js

h5_message_channel.js

(function(){
  var tkReplace = "NEBULA_BRIDGE_JS_REPLACE_STRING";

/**********************js fetch************************/
(function(self) {
  'use strict';

  var support = {
    searchParams: 'URLSearchParams' in self,
    iterable: 'Symbol' in self && 'iterator' in Symbol,
    blob: 'FileReader' in self && 'Blob' in self && (function() {
      try {
        new Blob()
        return true
      } catch(e) {
        return false
      }
    })(),
    formData: 'FormData' in self,
    arrayBuffer: 'ArrayBuffer' in self
  }

  if (support.arrayBuffer) {
    var viewClasses = [
      '[object Int8Array]',
      '[object Uint8Array]',
      '[object Uint8ClampedArray]',
      '[object Int16Array]',
      '[object Uint16Array]',
      '[object Int32Array]',
      '[object Uint32Array]',
      '[object Float32Array]',
      '[object Float64Array]'
    ]

    var isDataView = function(obj) {
      return obj && DataView.prototype.isPrototypeOf(obj)
    }

    var isArrayBufferView = ArrayBuffer.isView || function(obj) {
      return obj && viewClasses.indexOf(Object.prototype.toString.call(obj)) > -1
    }
  }

  function normalizeName(name) {
    if (typeof name !== 'string') {
      name = String(name)
    }
    if (/[^a-z0-9\-#$%&'*+.\^_`|~]/i.test(name)) {
      throw new TypeError('Invalid character in header field name')
    }
    return name.toLowerCase()
  }

  function normalizeValue(value) {
    if (typeof value !== 'string') {
      value = String(value)
    }
    return value
  }

  // Build a destructive iterator for the value list
  function iteratorFor(items) {
    var iterator = {
      next: function() {
        var value = items.shift()
        return {done: value === undefined, value: value}
      }
    }

    if (support.iterable) {
      iterator[Symbol.iterator] = function() {
        return iterator
      }
    }

    return iterator
  }

  function Headers(headers) {
    this.map = {}

    if (headers instanceof Headers) {
      headers.forEach(function(value, name) {
        this.append(name, value)
      }, this)
    } else if (Array.isArray(headers)) {
      headers.forEach(function(header) {
        this.append(header[0], header[1])
      }, this)
    } else if (headers) {
      Object.getOwnPropertyNames(headers).forEach(function(name) {
        this.append(name, headers[name])
      }, this)
    }
  }

  Headers.prototype.append = function(name, value) {
    name = normalizeName(name)
    value = normalizeValue(value)
    var oldValue = this.map[name]
    this.map[name] = oldValue ? oldValue+','+value : value
  }

  Headers.prototype['delete'] = function(name) {
    delete this.map[normalizeName(name)]
  }

  Headers.prototype.get = function(name) {
    name = normalizeName(name)
    return this.has(name) ? this.map[name] : null
  }

  Headers.prototype.has = function(name) {
    return this.map.hasOwnProperty(normalizeName(name))
  }

  Headers.prototype.set = function(name, value) {
    this.map[normalizeName(name)] = normalizeValue(value)
  }

  Headers.prototype.forEach = function(callback, thisArg) {
    for (var name in this.map) {
      if (this.map.hasOwnProperty(name)) {
        callback.call(thisArg, this.map[name], name, this)
      }
    }
  }

  Headers.prototype.keys = function() {
    var items = []
    this.forEach(function(value, name) { items.push(name) })
    return iteratorFor(items)
  }

  Headers.prototype.values = function() {
    var items = []
    this.forEach(function(value) { items.push(value) })
    return iteratorFor(items)
  }

  Headers.prototype.entries = function() {
    var items = []
    this.forEach(function(value, name) { items.push([name, value]) })
    return iteratorFor(items)
  }

  if (support.iterable) {
    Headers.prototype[Symbol.iterator] = Headers.prototype.entries
  }

  function consumed(body) {
    if (body.bodyUsed) {
      return Promise.reject(new TypeError('Already read'))
    }
    body.bodyUsed = true
  }

  function fileReaderReady(reader) {
    return new Promise(function(resolve, reject) {
      reader.onload = function() {
        resolve(reader.result)
      }
      reader.onerror = function() {
        reject(reader.error)
      }
    })
  }

  function readBlobAsArrayBuffer(blob) {
    var reader = new FileReader()
    var promise = fileReaderReady(reader)
    reader.readAsArrayBuffer(blob)
    return promise
  }

  function readBlobAsText(blob) {
    var reader = new FileReader()
    var promise = fileReaderReady(reader)
    reader.readAsText(blob)
    return promise
  }

  function readArrayBufferAsText(buf) {
    var view = new Uint8Array(buf)
    var chars = new Array(view.length)

    for (var i = 0; i < view.length; i++) {
      chars[i] = String.fromCharCode(view[i])
    }
    return chars.join('')
  }

  function bufferClone(buf) {
    if (buf.slice) {
      return buf.slice(0)
    } else {
      var view = new Uint8Array(buf.byteLength)
      view.set(new Uint8Array(buf))
      return view.buffer
    }
  }

  function Body() {
    this.bodyUsed = false

    this._initBody = function(body) {
      this._bodyInit = body
      if (!body) {
        this._bodyText = ''
      } else if (typeof body === 'string') {
        this._bodyText = body
      } else if (support.blob && Blob.prototype.isPrototypeOf(body)) {
        this._bodyBlob = body
      } else if (support.formData && FormData.prototype.isPrototypeOf(body)) {
        this._bodyFormData = body
      } else if (support.searchParams && URLSearchParams.prototype.isPrototypeOf(body)) {
        this._bodyText = body.toString()
      } else if (support.arrayBuffer && support.blob && isDataView(body)) {
        this._bodyArrayBuffer = bufferClone(body.buffer)
        // IE 10-11 can't handle a DataView body.
        this._bodyInit = new Blob([this._bodyArrayBuffer])
      } else if (support.arrayBuffer && (ArrayBuffer.prototype.isPrototypeOf(body) || isArrayBufferView(body))) {
        this._bodyArrayBuffer = bufferClone(body)
      } else {
        throw new Error('unsupported BodyInit type')
      }

      if (!this.headers.get('content-type')) {
        if (typeof body === 'string') {
          this.headers.set('content-type', 'text/plain;charset=UTF-8')
        } else if (this._bodyBlob && this._bodyBlob.type) {
          this.headers.set('content-type', this._bodyBlob.type)
        } else if (support.searchParams && URLSearchParams.prototype.isPrototypeOf(body)) {
          this.headers.set('content-type', 'application/x-www-form-urlencoded;charset=UTF-8')
        }
      }
    }

    if (support.blob) {
      this.blob = function() {
        var rejected = consumed(this)
        if (rejected) {
          return rejected
        }

        if (this._bodyBlob) {
          return Promise.resolve(this._bodyBlob)
        } else if (this._bodyArrayBuffer) {
          return Promise.resolve(new Blob([this._bodyArrayBuffer]))
        } else if (this._bodyFormData) {
          throw new Error('could not read FormData body as blob')
        } else {
          return Promise.resolve(new Blob([this._bodyText]))
        }
      }

      this.arrayBuffer = function() {
        if (this._bodyArrayBuffer) {
          return consumed(this) || Promise.resolve(this._bodyArrayBuffer)
        } else {
          return this.blob().then(readBlobAsArrayBuffer)
        }
      }
    }

    this.text = function() {
      var rejected = consumed(this)
      if (rejected) {
        return rejected
      }

      if (this._bodyBlob) {
        return readBlobAsText(this._bodyBlob)
      } else if (this._bodyArrayBuffer) {
        return Promise.resolve(readArrayBufferAsText(this._bodyArrayBuffer))
      } else if (this._bodyFormData) {
        throw new Error('could not read FormData body as text')
      } else {
        return Promise.resolve(this._bodyText)
      }
    }

    if (support.formData) {
      this.formData = function() {
        return this.text().then(decode)
      }
    }

    this.json = function() {
      return this.text().then(JSON.parse)
    }

    return this
  }

  // HTTP methods whose capitalization should be normalized
  var methods = ['DELETE', 'GET', 'HEAD', 'OPTIONS', 'POST', 'PUT']

  function normalizeMethod(method) {
    var upcased = method.toUpperCase()
    return (methods.indexOf(upcased) > -1) ? upcased : method
  }

  function Request(input, options) {
    options = options || {}
    var body = options.body

    if (input instanceof Request) {
      if (input.bodyUsed) {
        throw new TypeError('Already read')
      }
      this.url = input.url
      this.credentials = input.credentials
      if (!options.headers) {
        this.headers = new Headers(input.headers)
      }
      this.method = input.method
      this.mode = input.mode
      if (!body && input._bodyInit != null) {
        body = input._bodyInit
        input.bodyUsed = true
      }
    } else {
      this.url = String(input)
    }

    this.credentials = options.credentials || this.credentials || 'omit'
    if (options.headers || !this.headers) {
      this.headers = new Headers(options.headers)
    }
    this.method = normalizeMethod(options.method || this.method || 'GET')
    this.mode = options.mode || this.mode || null
    this.referrer = null

    if ((this.method === 'GET' || this.method === 'HEAD') && body) {
      throw new TypeError('Body not allowed for GET or HEAD requests')
    }
    this._initBody(body)
  }

  Request.prototype.clone = function() {
    return new Request(this, { body: this._bodyInit })
  }

  function decode(body) {
    var form = new FormData()
    body.trim().split('&').forEach(function(bytes) {
      if (bytes) {
        var split = bytes.split('=')
        var name = split.shift().replace(/\+/g, ' ')
        var value = split.join('=').replace(/\+/g, ' ')
        form.append(decodeURIComponent(name), decodeURIComponent(value))
      }
    })
    return form
  }

  function parseHeaders(rawHeaders) {
    var headers = new Headers()
    // Replace instances of \r\n and \n followed by at least one space or horizontal tab with a space
    // https://tools.ietf.org/html/rfc7230#section-3.2
    var preProcessedHeaders = rawHeaders.replace(/\r?\n[\t ]+/g, ' ')
    preProcessedHeaders.split(/\r?\n/).forEach(function(line) {
      var parts = line.split(':')
      var key = parts.shift().trim()
      if (key) {
        var value = parts.join(':').trim()
        headers.append(key, value)
      }
    })
    return headers
  }

  Body.call(Request.prototype)

  function Response(bodyInit, options) {
    if (!options) {
      options = {}
    }

    this.type = 'default'
    this.status = options.status === undefined ? 200 : options.status
    this.ok = this.status >= 200 && this.status < 300
    this.statusText = 'statusText' in options ? options.statusText : 'OK'
    this.headers = new Headers(options.headers)
    this.url = options.url || ''
    this._initBody(bodyInit)
  }

  Body.call(Response.prototype)

  Response.prototype.clone = function() {
    return new Response(this._bodyInit, {
      status: this.status,
      statusText: this.statusText,
      headers: new Headers(this.headers),
      url: this.url
    })
  }

  Response.error = function() {
    var response = new Response(null, {status: 0, statusText: ''})
    response.type = 'error'
    return response
  }

  var redirectStatuses = [301, 302, 303, 307, 308]

  Response.redirect = function(url, status) {
    if (redirectStatuses.indexOf(status) === -1) {
      throw new RangeError('Invalid status code')
    }

    return new Response(null, {status: status, headers: {location: url}})
  }

  self.Headers = Headers
  self.Request = Request
  self.Response = Response

  self.fetch = function(input, init) {
    return new Promise(function(resolve, reject) {
      var request = new Request(input, init)
      var xhr = new XMLHttpRequest()

      xhr.onload = function() {
        var options = {
          status: xhr.status,
          statusText: xhr.statusText,
          headers: parseHeaders(xhr.getAllResponseHeaders() || '')
        }
        options.url = 'responseURL' in xhr ? xhr.responseURL : options.headers.get('X-Request-URL')
        var body = 'response' in xhr ? xhr.response : xhr.responseText
        resolve(new Response(body, options))
      }

      xhr.onerror = function() {
        reject(new TypeError('Network request failed'))
      }

      xhr.ontimeout = function() {
        reject(new TypeError('Network request failed'))
      }

      xhr.open(request.method, request.url, true)

      if (request.credentials === 'include') {
        xhr.withCredentials = true
      } else if (request.credentials === 'omit') {
        xhr.withCredentials = false
      }

      if ('responseType' in xhr && support.blob) {
        xhr.responseType = 'blob'
      }

      request.headers.forEach(function(value, name) {
        xhr.setRequestHeader(name, value)
      })

      xhr.send(typeof request._bodyInit === 'undefined' ? null : request._bodyInit)
    })
  }
  self.fetch.polyfill = true
})(typeof self !== 'undefined' ? self : this);

/**********************from serializes************************/
(function(){
    // get successful control from form and assemble into object
    // http://www.w3.org/TR/html401/interact/forms.html#h-17.13.2

    // types which indicate a submit action and are not successful controls
    // these will be ignored
    var k_r_submitter = /^(?:button|image|reset|file)$/i;

    // node names which could be successful controls
    var k_r_success_contrls = /^(?:input|select|textarea|keygen)/i;

    // Matches bracket notation.
    var brackets = /(\[[^\[\]]*\])/g;

    // serializes form fields
    // @param form MUST be an HTMLForm element
    // @param options is an optional argument to configure the serialization. Default output
    // with no options specified is a url encoded string
    //    - hash: [true | false] Configure the output type. If true, the output will
    //    be a js object.
    //    - serializer: [function] Optional serializer function to override the default one.
    //    The function takes 3 arguments (result, key, value) and should return new result
    //    hash and url encoded str serializers are provided with this module
    //    - disabled: [true | false]. If true serialize disabled fields.
    //    - empty: [true | false]. If true serialize empty fields
    function serialize(form, options) {
        if (typeof options != 'object') {
            options = { hash: !!options };
        }
        else if (options.hash === undefined) {
            options.hash = true;
        }

        var result = (options.hash) ? {} : '';
        var serializer = options.serializer || ((options.hash) ? hash_serializer : str_serialize);

        var elements = form && form.elements ? form.elements : [];

        //Object store each radio and set if it's empty or not
        var radio_store = Object.create(null);

        for (var i=0 ; i<elements.length ; ++i) {
            var element = elements[i];

            // ingore disabled fields
            if ((!options.disabled && element.disabled) || !element.name) {
                continue;
            }
            // ignore anyhting that is not considered a success field
            if (!k_r_success_contrls.test(element.nodeName) ||
                k_r_submitter.test(element.type)) {
                continue;
            }

            if (/submit/.test(element.type) && (document.activeElement !== element && window.lastClickElement !== element)) {
            	continue;
            }

            var key = element.name;
            var val = element.value;

            // we can't just use element.value for checkboxes cause some browsers lie to us
            // they say "on" for value when the box isn't checked
            if ((element.type === 'checkbox' || element.type === 'radio') && !element.checked) {
                val = undefined;
            }

            // If we want empty elements
            if (options.empty) {
                // for checkbox
                if (element.type === 'checkbox' && !element.checked) {
                    continue;
                }

                // for radio
                if (element.type === 'radio' && !element.checked) {
                    continue;
                }

                // for radio
                if (element.type === 'radio') {
                    if (!radio_store[element.name] && !element.checked) {
                        radio_store[element.name] = false;
                    }
                    else if (element.checked) {
                        radio_store[element.name] = true;
                    }
                }

                // if options empty is true, continue only if its radio
                if (val == undefined && element.type == 'radio') {
                    continue;
                }
            }
            else {
                // value-less fields are ignored unless options.empty is true
                if (!val) {
                    continue;
                }
            }

            // multi select boxes
            if (element.type === 'select-multiple') {
                val = [];

                var selectOptions = element.options;
                var isSelectedOptions = false;
                for (var j=0 ; j<selectOptions.length ; ++j) {
                    var option = selectOptions[j];
                    var allowedEmpty = options.empty && !option.value;
                    var hasValue = (option.value || allowedEmpty);
                    if (option.selected && hasValue) {
                        isSelectedOptions = true;

                        result = serializer(result, key, option.value);

                    }
                }

                // // Serialize if no selected options and options.empty is true
                // if (!isSelectedOptions && options.empty) {
                //     result = serializer(result, key, '');
                // }

                continue;
            }

            result = serializer(result, key, val);
        }

        // Check for all empty radio buttons and serialize them with key=""
        if (options.empty) {
            for (var key in radio_store) {
                if (!radio_store[key]) {
                    result = serializer(result, key, '');
                }
            }
        }

        return result;
    }

    function parse_keys(string) {
        var keys = [];
        var prefix = /^([^\[\]]*)/;
        var children = new RegExp(brackets);
        var match = prefix.exec(string);

        if (match[1]) {
            keys.push(match[1]);
        }

        while ((match = children.exec(string)) !== null) {
            keys.push(match[1]);
        }

        return keys;
    }

    function hash_assign(result, keys, value) {
        if (keys.length === 0) {
            result = value;
            return result;
        }

        var key = keys.shift();
        var between = key.match(/^\[(.+?)\]$/);

        if (key === '[]') {
            result = result || [];

            if (Array.isArray(result)) {
                result.push(hash_assign(null, keys, value));
            }
            else {
                // This might be the result of bad name attributes like "[][foo]",
                // in this case the original `result` object will already be
                // assigned to an object literal. Rather than coerce the object to
                // an array, or cause an exception the attribute "_values" is
                // assigned as an array.
                result._values = result._values || [];
                result._values.push(hash_assign(null, keys, value));
            }

            return result;
        }

        // Key is an attribute name and can be assigned directly.
        if (!between) {
            result[key] = hash_assign(result[key], keys, value);
        }
        else {
            var string = between[1];
            // +var converts the variable into a number
            // better than parseInt because it doesn't truncate away trailing
            // letters and actually fails if whole thing is not a number
            var index = +string;

            // If the characters between the brackets is not a number it is an
            // attribute name and can be assigned directly.
            if (isNaN(index)) {
                result = result || {};
                result[string] = hash_assign(result[string], keys, value);
            }
            else {
                result = result || [];
                result[index] = hash_assign(result[index], keys, value);
            }
        }

        return result;
    }

    // Object/hash encoding serializer.
    function hash_serializer(result, key, value) {
        var matches = key.match(brackets);

        // Has brackets? Use the recursive assignment function to walk the keys,
        // construct any missing objects in the result tree and make the assignment
        // at the end of the chain.
        // not to change filename so use false
        if (false) {
            var keys = parse_keys(key);
            hash_assign(result, keys, value);
        }
        else {
            // Non bracket notation can make assignments directly.
            var existing = result[key];

            // If the value has been assigned already (for instance when a radio and
            // a checkbox have the same name attribute) convert the previous value
            // into an array before pushing into it.
            //
            // NOTE: If this requirement were removed all hash creation and
            // assignment could go through `hash_assign`.
            if (existing) {
                if (!Array.isArray(existing)) {
                    result[key] = [ existing ];
                }

                result[key].push(value);
            }
            else {
                result[key] = value;
            }
        }

        return result;
    }

    // urlform encoding serializer
    function str_serialize(result, key, value) {
        // encode newlines as \r\n cause the html spec says so
        value = value.replace(/(\r)?\n/g, '\r\n');
        value = encodeURIComponent(value);

        // spaces should be '+' rather than '%20'.
        value = value.replace(/%20/g, '+');
        return result + (result ? '&' : '') + encodeURIComponent(key) + '=' + value;
    }

    window.NebulaSerialize = serialize;
})();

(function(){
    var ktnebula = tkReplace;
    var webkit = window.webkit;
    var postMessage = webkit.messageHandlers.PSDXMLHTTPREQUESTMESSAGE.postMessage;
    var PSDXMLHTTPREQUESTMESSAGE = webkit.messageHandlers.PSDXMLHTTPREQUESTMESSAGE;

    function safeCallMessage(message){
        return postMessage.apply(PSDXMLHTTPREQUESTMESSAGE,[message]);
    }
    /**********************rewrite cookie************************/

    var cookieOriginSetter = document.__lookupSetter__('cookie'),
    cookieOriginGetter = document.__lookupGetter__('cookie');
    var NebulaUpdateCookies;
    if (cookieOriginSetter && cookieOriginGetter) {
        Object.defineProperty(document, 'cookie', {
            set: function(cookstr) {
                if (typeof cookstr !== 'string') {
                      return;
                };
                var message = {};
                message[msgType] = "cookie";
                message["cookie"] = cookstr;
                message["url"] = document.location.href;
                message["msgKt"] = ktnebula;
                //iOS 10 and iOS 11 if call this on unload event,window.webkit can be null
                if (webkit && webkit.messageHandlers && webkit.messageHandlers.PSDXMLHTTPREQUESTMESSAGE && webkit.messageHandlers.PSDXMLHTTPREQUESTMESSAGE.postMessage) {
                    safeCallMessage(message);
                }
                cookieOriginSetter.apply(document,[cookstr]);
            },
            get: function(){
                return cookieOriginGetter.apply(document,[]);
            },
            configurable: false
        });
    }else{
      if (window.SHOULDNEBULADORWC) {
          var cookieNameMap = {
                  Version: 'version',
                  Name: 'name',
                  Value: 'value',
                  MaxAge: 'maxAge',
                  MaxAgeDate: 'maxAgeDate',
                  ExpiresDate: 'expiresDate',
                  Domain: 'domain',
                  Path: 'path',
                  Secure: 'secure',
                  HttpOnly: 'httpOnly'
          }

          function idIPAddress(address) {
              return /^(d+).(d+).(d+).(d+)$/.test(address);
          };

          function isRegExp(value, rule) {
              if (rule && typeof rule === "string" && rule.length > 0) {
                  var reg = new RegExp(rule + '$');
                  return reg.test(value);
              }else{
                  return false;
              }
          };

          function hasPrefix(value, rule){
              if (rule.length > 0) {
                var reg = new RegExp("^" + rule);
                return reg.test(value);
              }else{
                return false;
              }
          }

          function domianMatch(value){
            var hostMatch = (value && isRegExp(document.location.hostname.toLowerCase(),value));
            var isRootDomain = false;
            var p = value.split('.');
            var q = p.length;
            if (q == 2 || (q == 3 && p[1] === 'com')) {
                isRootDomain = true;
            }
            return (hostMatch && !isRootDomain);
          }

          function getPath() {
              var k = document.location.pathname;
              var l = k.lastIndexOf('/');
              var result = k.substring(0, l);
              if (result.length == 0) {
                return "/";
              }else{
                return result;
              }
          };

        var cookieStore = [];

        function isCookieExpired(cookieObj) {
              var l = typeof cookieObj[cookieNameMap.MaxAgeDate] == 'object';
              if (l && cookieObj[cookieNameMap.MaxAge] <= 0) {
                  return true
              } else {
                  if (l) {
                      return cookieObj[cookieNameMap.MaxAgeDate] < new Date()
                  } else {
                      if (typeof cookieObj[cookieNameMap.ExpiresDate] == 'object') {
                          return cookieObj[cookieNameMap.ExpiresDate] < new Date()
                      } else {
                          return false
                      }
                  }
              }
          };



        function getCookieStr() {
              var length = cookieStore.length,
              index = 0, item, result = [];
              for (; index < length; index ++) {
                  item = cookieStore[index];
                  if (!isCookieExpired(item)) {
                      result.push(item[cookieNameMap.Name] + '=' + item[cookieNameMap.Value])
                  }
              };
              return result.join('; ')
          };

         function updateAllCookie(cookieObj) {
              var length = cookieStore.length,
              index=0, item, result = [];
              for (; index < length; index ++) {
                  item = cookieStore[index];
                  if (!(item[cookieNameMap.Name] === cookieObj[cookieNameMap.Name] && item[cookieNameMap.Path] === cookieObj[cookieNameMap.Path] && item[cookieNameMap.Domain] === cookieObj[cookieNameMap.Domain])) {
                      result.push(item);
                  }
              };
              cookieStore = result;
          };

          function updateCookie(cookieObj) {
              //if path not match just return
              var cookiePath = cookieObj[cookieNameMap.Path];
              var isPrefixWithCookiePath = (hasPrefix(getPath(),cookiePath) || hasPrefix(document.location.pathname,cookiePath));
              if (!isPrefixWithCookiePath) {
                  return;
              }
              updateAllCookie(cookieObj);
              cookieStore.unshift(cookieObj);
          };


         function parseOthers(name, value, cookieObj) {
              var name = name.toLowerCase();
              var o;
              value = value.trim();
              switch (name) {
              case 'expires':
                  {
                      var date = new Date(value);
                      if (!isNaN(date.getTime())) {
                          cookieObj[cookieNameMap.ExpiresDate] = date;
                      }
                  };
                  break;
              case 'max-age':
                  {
                      if (!isNaN(value)) {
                          var p = Number(parseInt(value));
                          var q = new Date();
                          q.setTime(q.getTime() + p * 1000);
                          cookieObj[cookieNameMap.MaxAge] = p;
                          cookieObj[cookieNameMap.MaxAgeDate] = q
                      }
                  };
                  break;
              case 'domain':
                  {
                      hostName = document.location.hostname.toLowerCase();
                      if (idIPAddress(hostName)) {
                          cookieObj[cookieNameMap.Domain] = hostName;
                      } else {
                          if (value.length > 0) {
                              if (value.charAt(0) != '.') {
                                  value = '.' + value
                              };
                              if (isRegExp(hostName, value)) {
                                  var p = value.split('.');
                                  var q = p.length;
                                  if (q == 2 || (q == 3 && p[1] === 'com')) {
                                      cookieObj[cookieNameMap.Domain] = '.' + hostName
                                  } else {
                                      cookieObj[cookieNameMap.Domain] = value
                                  }
                              } else {
                                  cookieObj[cookieNameMap.Domain] = '.' + hostName
                              }
                          }
                      }
                  };
                  break;
              case 'path':
                  {
                      if (value.length == 0 || value.charAt(0) !== '/') {
                          cookieObj[cookieNameMap.Path] = getPath();
                      } else {
                          cookieObj[cookieNameMap.Path] = value;
                      }
                  };
                  break;
              case 'secure':
                  {
                      cookieObj[cookieNameMap.Secure] = true;
                  };
                  break;
              default:
                  {}
                  break
              }
          };

          function saveCookieOtherPart(cookie, cookieObj) {
              var name, value = '';
              var item;
              var length = cookie.length;
              for (var index = 0; index < length; index++) {
                  item = cookie[index];
                  var splitObj = item.split('=');
                  name = splitObj[0];
                  if (splitObj.length > 1) {
                      value = splitObj[1];
                  };
                  name = name.trim();
                  if (name.length == 0) {
                      continue
                  };
                  value = value.trim();
                  if (name.toLowerCase() === "httponly") {
                    return false;
                  }else if(name.toLowerCase() === "path"){
                    var isPrefixWithCookiePath = (hasPrefix(getPath(),value) || hasPrefix(document.location.pathname,value));
                    if (!isPrefixWithCookiePath) {
                      return false;
                    }else{
                      parseOthers(name, value, cookieObj);
                    }
                  }else if(name.toLowerCase() === "domain"){
                    if (!(domianMatch(value))) {
                       return false;
                    }else{
                       parseOthers(name, value, cookieObj);
                    }
                  }else{
                    parseOthers(name, value, cookieObj);
                  }
              };
              if (typeof cookieObj['domain'] == 'undefined') {
                  cookieObj['domain'] = document.location.hostname.toLowerCase()
              }
              return true;
          };

          function saveCookieNameAndValue(cookie, cookieObj) {
              cookie = cookie.trim();
              if (cookie.length <= 0) {
                  return false
              };
              var eq_idx = cookie.indexOf('=');
              // skip things that don't look like key=value
              if (eq_idx < 0) {
                return false;
              }
              var key = cookie.substr(0, eq_idx).trim();
              var val = cookie.substr(++eq_idx, cookie.length).trim();
              // quoted values
              if ('"' == val[0]) {
                val = val.slice(1, -1);
              }
              cookieObj[cookieNameMap.Name] = key;
              cookieObj[cookieNameMap.Value] = val;
              return true;
          }

          function saveCookieStr(cookieStr) {
              var hostname = document.location.hostname.toLowerCase(),cookie = {
                  name: '',
                  value: '',
                  secure: false,
                  httpOnly: false,
                  path:getPath(),
                  domain:hostname
              };
              var cookieSplit = cookieStr.split(';');
              if (cookieSplit.length > 0) {
                  var name = cookieSplit[0];
                  if (!saveCookieNameAndValue(name, cookie)) {
                      return null;
                  };
                  if (!saveCookieOtherPart(cookieSplit.slice(1, cookieSplit.length), cookie)) {
                      return null;
                  }
                  if (isCookieExpired(cookie)) {
                      updateAllCookie(cookie);
                  } else {
                      updateCookie(cookie);
                  };
                  return cookie;
              };
              return null
          };

        var getCookieSuc = false;
        function getCurrentCookie(){
          var protocol = document.location.protocol,host = document.location.host;
              if (protocol && host) {
                try{
                  doCookieSyncRequest(protocol + '//' + host + '/'+requestTK+'/?' + document.location.href);
                }catch(ex){

                }
              }
        };

        function doCookieSyncRequest(url) {
              var xmlHttprequest = new XMLHttpRequest();
              xmlHttprequest.open('GET', url, false);
              xmlHttprequest.setRequestHeader('Content-Type', "text/plain");
              xmlHttprequest.send(null); 
              if (xmlHttprequest.status == 200) {
                var result = xmlHttprequest.responseText;
                if ( !result || result.length == 0) {
                    return
                };
                try{
                  var cookieJSON = JSON.parse(result);
                  if (typeof cookieJSON === 'object') {
                      getCookieSuc = true;
                      saveCookies(cookieJSON);
                  }
                }catch(ex){

                }
              }    
          };


        function saveCookies(cookies) {
              cookieStore = [];
              var index = 0, 
              length = cookies.length,item;
              for ( ; index < length; index ++) {
                  item = cookies[index];
                  if (typeof item[cookieNameMap.ExpiresDate] != 'undefined') {
                      item[cookieNameMap.ExpiresDate] = new Date(item[cookieNameMap.ExpiresDate]);
                  };
                  cookieStore.push(item);
              }
          };

          function updateIfameCookie(message) {
              var iframes = document.querySelectorAll('iframe');
              if (!iframes) {
                  return
              };
              var length = iframes.length;
              var index;
              var iframe;
              if (length > 0) {
                  for (index = 0; index < length; index++) {
                      iframe = iframes[index];
                      iframe.contentWindow.postMessage(message, '*');
                  }
              }
          };

          function updateCookies(cookies,host){
            for(var i = 0;i < cookies.length; i++){
                 var item = cookies[i],domain;
                if (domianMatch(item[cookieNameMap.Domain])) {
                    updateCookie(item);
                }
            }
          }

          if (top != this) {
              window.addEventListener('message',function(event) {
                  var data = event['data'];
                  if (((typeof data) === 'object')) {
                      if (typeof data['host'] === 'string' &&  data['nebula_data']) {
                          updateCookies(data['nebula_data'], data['host']);
                          updateIfameCookie(data);
                          if (event.stopImmediatePropagation) {
                              event.stopImmediatePropagation();
                          };
                          return false
                      }
                }
              },true)
          } else {
            //use this function to update cookiess
            NebulaUpdateCookies = function(cookies,host,tk) {
                //native inject token and check this token for forbidden other one call this method
                if (ktnebula === tk) {
                    updateCookies(cookies,host);
                    var message = {};
                    message["host"] = host;
                    message["nebula_data"] = cookies;
                    updateIfameCookie(message);
                }         
            }
          };

          getCurrentCookie();

          if (getCookieSuc) {
            Object.defineProperty(document, 'cookie', {
                get: function() {
                    var cookieStr = getCookieStr();
                    return cookieStr;
                },
                set: function(cookieStr) {
                    if (typeof cookieStr !== 'string') {
                        return
                    };
                    saveCookieStr(cookieStr);
                    var message = {};
                    message[msgType] = "cookie";
                    message["cookie"] = cookieStr;
                    message["url"] = document.location.href;
                    message["msgKt"] = ktnebula;
                    //iOS 10 and iOS 11 if call this on unload event,window.webkit can be null
                    if (webkit && webkit.messageHandlers && webkit.messageHandlers.PSDXMLHTTPREQUESTMESSAGE && webkit.messageHandlers.PSDXMLHTTPREQUESTMESSAGE.postMessage) {
                        safeCallMessage(message);
                    }
                },
                configurable: false
            });
          }   

      } 
    }
    /**********************Util************************/
    function getAllHTMLFormData(element, fromAjax){
        var result = [];
        if (element.nodeName.toLowerCase() == "form") {
            var serializeResult = NebulaSerialize(element, { hash: true , empty: true });
            var inputs = [].slice.call(element.querySelectorAll('input'));
            for(var i = 0; i < inputs.length ; i++){
                var field = inputs[i];
                var type = field.type, name = field.name;
              if(type == 'file' && field.files && field.files.length > 0){
                var filesLength = field.files.length;
                for(var j = 0; j < filesLength; j++){
                    //if get file data
                    if ((element.enctype.toLowerCase() == "application/x-www-form-urlencoded" || element.enctype.toLowerCase() == "text/plain") && !fromAjax) {
                        result.push({"name" : name, "value" : field.files[j].name});
                    }else if (formElemntList[name] && formElemntList[name][j]) {
                        result.push({"name" : name, "value" : formElemntList[name][j]});
                    }else{
                        result.push({"name" : name, "value" : field.files[j]});
                    }
                }
              }
            }
            for(var key in serializeResult){
                if (serializeResult.hasOwnProperty(key)) {
                    result.push({"name" : key, "value" : serializeResult[key]});
                }
            }
        }
        return  result;    
    }

    function serializeFormData(data) {
        return new Promise(function (resolve, reject) {
            var dataVal = data["value"];
            if (typeof(dataVal) === "string") {
                resolve(data);
            }else if(dataVal instanceof Blob || dataVal instanceof File){
                var reader = new FileReader();
                reader.onload = function (event) {
                    var result = event.target.result;
                    if (result.length > 0) {
                        data["value"] = result;
                        resolve(data);
                    }else{
                        reject(new Error(""));
                    }
                }
                reader.onerror = function(){
                    reject(new Error(""));
                }
                reader.onabort = function(){
                    reject(new Error(""));
                }
                reader.readAsDataURL(dataVal);
            }else{
                resolve(data);
            }
        });
    }
        
    function arrayBufferToBase64(buffer) {
        var binary = '';
        var bytes = new Uint8Array(buffer);
        var len = bytes.byteLength;
        for (var i = 0; i < len; i++) {
            binary += String.fromCharCode(bytes[i]);
        }
        return window.btoa(binary);
    }

    var serializeData = function(data,callback){
        var reader = new FileReader();
        reader.onload = function (event) {
            var result = event.target.result;
            callback(result);
        }
        reader.readAsDataURL(data);
    }

    function recordError(error){
        if (error instanceof Error) {
            var message = {};
            message[msgType] = "error";
            message["errorInfo"] = error.message;
            message["msgKt"] = ktnebula;
            safeCallMessage(message);
        }
    }

    function isFormUseGetMethod(element){
    		var item = element;
    		if (item && item.nodeName && (typeof item.nodeName === "string") && item.nodeName.toLowerCase() == "form") {
    			var methodStr = item.method;
    	        if (typeof methodStr !== "string") {
    	        	methodStr = item.getAttribute("method");
    	        }
    	        if (methodStr && methodStr.toLowerCase() === "get") {
    	            return true;
    	        }
    		}
        return false;
    }

    function generateFormTargetUrlWithRadom(url,radom){
      var urlParse = document.createElement('a');
      urlParse.href = url;
      var originUrlSearch = urlParse.search ? urlParse.search : "";
      var originUrlHash = urlParse.hash ? urlParse.hash : "";
      if (!/X-NEBULAXMLHTTPREQUEST/.test(url)) {
          if (urlParse.search && urlParse.search.length > 0) {
              var hrefSearch =  urlParse.search;
              if (/X-NEBULAXMLHTTPREQUEST/.test(hrefSearch)) {
                urlParse.search = hrefSearch.replace(/X-NEBULAXMLHTTPREQUEST=(\d+)/,"X-NEBULAXMLHTTPREQUEST="+radom);
              }else{
                urlParse.search = hrefSearch + "&X-NEBULAXMLHTTPREQUEST="+radom;
              }
          }else{
              urlParse.search = "?X-NEBULAXMLHTTPREQUEST="+radom;
          }
      }else{
          urlParse.search = urlParse.search.replace(/X-NEBULAXMLHTTPREQUEST=(\d+)/,"X-NEBULAXMLHTTPREQUEST="+radom);
      }
 
      var path = url.replace(originUrlSearch,"").replace(originUrlHash,"");
      if (path.trim() === '#') {
          path='';
      }
 
      return {targetUrl:path+urlParse.search+urlParse.hash,fullTargetUrl:urlParse.href};
    }

    function addFormExtraInfoWithElement(element){
        var item = element;
        if (isFormUseGetMethod(item)) {
        	return;
        }
        var radom = (+new Date()) +""+ Math.round((Math.random()*(100000)));
        //change form element method url for inject
        var methodUrl = item.getAttribute("action");
        if (!methodUrl) {
            methodUrl = "";
        }
        //if has no param add flag
        var urlObj = generateFormTargetUrlWithRadom(methodUrl,radom);
        item.setAttribute("action", urlObj.targetUrl);
        item.setAttribute("data-fullactionurl", urlObj.fullTargetUrl);
        item.setAttribute("data-nebulaId",radom);   
    }

    

    /**********************FormData************************/

    var  FakeFormData = (function(fn){
    window.originFormData = fn;
        return function(form){
            this.realFormData = new fn(form);  
            if (form) {
               this.targetForm = form; 
            }
            this.appendData = [];
        }
    })(FormData);

    FakeFormData.prototype.constructor = window.originFormData;
    FakeFormData.prototype.append = function(name, value, filename){
        var filenameInValue = (value!=undefined ? value.name : undefined);
        this.appendData.push({"name":name,"value":value,"fileName":filename||filenameInValue});
        //this.realFormData.append(name,value,filename);
    }

    FormData = FakeFormData;

    /**********************Message************************/
    var messageList = {};
    var msgId = "msgId",
    msgCookie = "msgCookie",
    msgMainUrl = "msgMainUrl",
    msgRequestUrl = "msgRequestUrl",
    msgKt = "msgKt",
    msgVal = "val", 
    msgType = 'type',
    msgEnctype = 'FormEnctype',
    msgAcceptCharset = "AcceptCharset",
    msgErrorMessage = "errorMessage",
    msgDocumentCharset = "DocumentCharset",
    msgIsStream = "IsStream";
    var NEBULAXMLHTTPREQUESTMESSAGEHANDLER = {
        cacheMessage:function(xmlhttprequest, callFn, args, msgId, kt){
          if (ktnebula === kt) {
            messageList[msgId] = {
                msgId:msgId,
                callBack:function(){
                    var that = xmlhttprequest;
                    try{
                        return callFn.apply(that, args);
                    }catch(ex){
                        recordError(ex);
                    }
                }
            };
            //if mainProcess message not come back deply 500ms do really call
            setTimeout(function(){
                NEBULAXMLHTTPREQUESTMESSAGEHANDLER.triggerMessageCallBack(msgId, kt);
            },500);
          }
        },
        triggerMessageCallBack:function(msgId, kt){
          if (ktnebula === kt) {
           if (messageList[msgId]){
               messageList[msgId]["callBack"]();
               delete  messageList[msgId];
            }
          }
        },
        addFormExtraInfoToElement:function(target, kt){
          if (ktnebula === kt) {
            var message = {};
            message[msgType] = "FormElement";
            message[msgKt] = kt;
            var element = getFormWithElement(target ? target : document.activeElement);
            //if is get request we should not send message to main process
            if (isFormUseGetMethod(element)) {
                return;
            }
            if (element) {
            	var dataNebulaId = element.getAttribute("data-nebulaId");
                var requestUrl = element.getAttribute("data-fullactionurl");
                var datas = getAllHTMLFormData(element,false);
                Promise.all(datas.map(function(data){
                    return serializeFormData(data);
                })).then(function (value) {
                	message[msgId] = dataNebulaId;
                    message[msgVal] = value;
                    message[msgType] = "FormElement";
                    message[msgEnctype] = element.enctype;
                    message[msgAcceptCharset] = element.acceptCharset;
                    message[msgDocumentCharset] = document.charset;
                    message[msgRequestUrl] = requestUrl;
                    safeCallMessage(message);
                }).catch(function(error){
                    recordError(error);
                }); 
                return  dataNebulaId;
            }
          }
        },
        updateCookies:NebulaUpdateCookies
    }

    window.NebulaXMLHttpRequestMessageBridge = NEBULAXMLHTTPREQUESTMESSAGEHANDLER;
    Object.freeze(window.NebulaXMLHttpRequestMessageBridge);
    Object.defineProperty(window,"NebulaXMLHttpRequestMessageBridge",{configurable:false,writable:false});

    /**********************XMLHttpRequest************************/
    // ReWrite send method
    // https://developer.mozilla.org/zh-CN/docs/Web/API/XMLHttpRequest
    // void send();
    // void send(ArrayBuffer data);
    // void send(Blob data);
    // void send(Document data);
    // void send(DOMString? data);
    // void send(FormData data);
    //if should stop request inject
    var generateTargetHash = function(hash){
      return "^^^^"+ hash +"^^^^";
    }

    var hashRegExp = /\^\^\^\^(\d+)\^\^\^\^/;
    function generateTargetUrlWithRadom(url,radom){
      var urlParse = document.createElement('a');
      urlParse.href = url;
      var originHash = urlParse.hash ? urlParse.hash : "";
      if (!hashRegExp.test(urlParse.hash)) {
          if (urlParse.hash && urlParse.hash.length > 0) {
              urlParse.hash = urlParse.hash + generateTargetHash(radom);
          }else{
              urlParse.hash = generateTargetHash(radom);
          }
      }else{
          urlParse.hash = urlParse.hash.replace(hashRegExp, generateTargetHash(radom));
      }

      var urlWithoutHash = url.replace(originHash,"");
      if (urlWithoutHash.trim() === '#') {
          urlWithoutHash ='';
      }

      return {targetUrl:urlWithoutHash + urlParse.hash,fullTargetUrl:urlParse.href};
    }

    var HttpMethods = ['POST', 'PUT', 'PATCH', 'DELETE', 'COPY', 'OPTIONS', 'LINK', 'UNLINK', 'PURGE','TRACE','LOCK', 'UNLOCK', 'VIEW', 'PROPFIND']
    var isTargetHttpMethod = function(method){
        if (typeof method == "string") {
          if (HttpMethods.indexOf(method.toUpperCase()) == -1) {
            return false;
          }else{
            return true;
          }
        }
        return false;
    }

    XMLHttpRequest.prototype.open = (function(fn) {
        return function(method, url, async, username, password) {
            var args = [].slice.call(arguments);
            var requestAsync = true;
            if (args.length > 2) {
                  requestAsync = !!args[2];
            }
            this.requestAsync = requestAsync;
            var radom = (+new Date()) +""+Math.round((Math.random()*(100000)));
            this.requestId = radom;
            var fullUrl = "";
            if (method && isTargetHttpMethod(method)) {
                var urlObj = generateTargetUrlWithRadom(url,radom);
                url = urlObj.targetUrl;
                fullUrl = urlObj.fullTargetUrl;
            }
            this.requestUrl = fullUrl;
            args[1] = url;
            return fn.apply(this, args);
        }
    })(XMLHttpRequest.prototype.open);

    //XMLHttpRequest rewrite send method
    XMLHttpRequest.prototype.send = (function(fn) {
        return function(e) {

            var radom = this.requestId;
            var message = {};
            var that = this;
            var args = [].slice.call(arguments);
            message[msgId] = radom;
            message[msgKt] = ktnebula;
            message[msgMainUrl] = document.location.href;
            message[msgRequestUrl] = this.requestUrl;
            //if sync request
            if (!e) {
                return fn.apply(this,args);
            }else if (typeof(e) === 'string' && e.length > 0) {
                message[msgVal] = e;
                message[msgType] = "String";
                safeCallMessage(message);
            } else if(e instanceof Blob){
                message[msgType] = "Blob";
                if (this.requestAsync) {
                   serializeData(e,function(result){
                        message[msgVal] = result;
                        safeCallMessage(message);
                        NEBULAXMLHTTPREQUESTMESSAGEHANDLER.cacheMessage(that,fn,args,radom,ktnebula);
                    });
                    return;
                }else{
                    message["error"] = "NOTSUPPORT";
                    safeCallMessage(message);
                }
            } else if(e instanceof FormData){
                message[msgType] = "FormData";
                if (this.requestAsync) {
                    message[msgType] = "FormData";
                    var datas = e.appendData;
                    if (e.targetForm) {
                        datas = datas.concat(getAllHTMLFormData(e.targetForm,true));
                    }
                    Promise.all(datas.map(function(data){
                        return serializeFormData(data);
                    })).then(function (value) {
                        message[msgVal] = value;
                        safeCallMessage(message);
                        NEBULAXMLHTTPREQUESTMESSAGEHANDLER.cacheMessage(that,fn,e.realFormData,radom,ktnebula);
                    }).catch(function(error){
                        recordError(error);
                    })
                    return;
                }else{
                    message["error"] = "NOTSUPPORT";
                    safeCallMessage(message);
                }
            } else if(e.nodeType){
                message[msgType] = "Document";
                if (e === document) {
                   message[msgVal] = (new XMLSerializer()).serializeToString(document);
                }else{
                   message[msgVal] = e.toString();
                }
                safeCallMessage(message);
            } else if(e instanceof ArrayBuffer){
                //transfor ArrayBuffer to base64
                message[msgVal] = arrayBufferToBase64(e);
                message[msgType] = "ArrayBuffer";
                safeCallMessage(message);
            } else if(e.buffer){
                message[msgVal] = arrayBufferToBase64(e.buffer);
                message[msgType] = "ArrayBuffer";
                safeCallMessage(message);
            } else {
                return fn.apply(this,args);
            }

            if (this.requestAsync) {
                return NEBULAXMLHTTPREQUESTMESSAGEHANDLER.cacheMessage(that,fn,args,radom,ktnebula);
            }else{
                return fn.apply(this,args);
            }
        }
    })(XMLHttpRequest.prototype.send);

    /**********************FormElement************************/
    var formElemntList = {};
    window.lastClickElement = null;
    function getFormWithElement(element){
        if (element && element.nodeType) {
            var parentNode = element;
            while (parentNode) {
                if (parentNode.nodeName.toLowerCase() === "form") {
                    return parentNode;
                } else if (parentNode === document || parentNode === document.documentElement || parentNode === document.body) {
                    break;
                }
                parentNode = parentNode.parentNode;
            }
            return null;
        }
    }

    document.addEventListener("DOMContentLoaded",function(){
        //inject a hidden input to form element
        // addFormExtraInfoToElement();
        //add input file change  and read file data
        document.addEventListener("change",function(e){
            var targetElement = e.target;
            if (targetElement.nodeName && targetElement.nodeName.toLowerCase() && targetElement.type && targetElement.type === "file") {
               var that = targetElement;
               for(var i = 0; i < that.files.length; i++){
                   (function(fileItem){
                        serializeFormData({name:that.name, value:fileItem}).then(function(value ){
                            //we save files in array
                            if (!formElemntList[that.name]) {
                                formElemntList[that.name] = [];
                            }
                            formElemntList[that.name].push({name:that.name,value:value["value"],fileName:fileItem.name});
                       }).catch(function(error){
                            recordError(error);
                       });
                   })(that.files[i])
               }
            }
        },false);

        document.addEventListener("click",function(e){
            window.lastClickElement = e.target;
        },true);
    },false);

    //before form form submit to add extraInfo
    document.addEventListener("submit",function(e){
        if (e.target &&  e.target.nodeName && typeof e.target.nodeName === "string" && e.target.nodeName.toLowerCase() == "form") {
          addFormExtraInfoWithElement(e.target);
          NEBULAXMLHTTPREQUESTMESSAGEHANDLER.addFormExtraInfoToElement(e.target,ktnebula);
        }
    },true);

    HTMLFormElement.prototype.submit = (function(fn){
        return function(){
            //if submit from js method, we send method to main process
            var that = this;
            var args = [].slice.call(arguments);
            var datas = getAllHTMLFormData(this,false);
            var message = {};
            //for dynamic form
            addFormExtraInfoWithElement(this);
            window.lastClickElement = this;
            NEBULAXMLHTTPREQUESTMESSAGEHANDLER.addFormExtraInfoToElement(this,ktnebula);
            fn.apply(that,args);
        }
    })(HTMLFormElement.prototype.submit);
})();

})();

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值