Uploaded image for project: 'Apache Cordova'
  1. Apache Cordova
  2. CB-6423

(iOS) cordova.js: iOSExec() not working after upgrading from Cordova 3.0 to 3.4

    XMLWordPrintableJSON

Details

    Description

      Hi there,

      I recently upgraded my working PhoneGap app from 3.0 to 3.4. In iOS, the app wouldn't go past the splashscreen. It would get stuck while trying to fetch a local file (in file:/// dir) through an XHR.

      I managed to trace the problem to the iOSExec function in cordova.js. Before the upgrade, it would determine bridgeMode the following way:

      bridgeMode = navigator.userAgent.indexOf(' 4_') == -1 ? jsToNativeModes.XHR_NO_PAYLOAD : jsToNativeModes.IFRAME_NAV;

      In cordova.js 3.4 it is determined the following way:

      bridgeMode = navigator.userAgent.indexOf(' 5_') == -1 ? jsToNativeModes.IFRAME_NAV: jsToNativeModes.XHR_NO_PAYLOAD;

      Notice the switch in the expressions.

      This led to any iOS device with a version other than 5 not working. Using the jsToNativeModes.IFRAME_NAV bridgeMode would lead to the default case in the subsequent switch statement in which it determines what to do according to the bridgeMode.

      switch (bridgeMode) {
      case jsToNativeModes.XHR_NO_PAYLOAD:
      case jsToNativeModes.XHR_WITH_PAYLOAD:
      case jsToNativeModes.XHR_OPTIONAL_PAYLOAD:
      // This prevents sending an XHR when there is already one being sent.
      // This should happen only in rare circumstances (refer to unit tests).
      if (execXhr && execXhr.readyState != 4)

      { execXhr = null; }

      // Re-using the XHR improves exec() performance by about 10%.
      execXhr = execXhr || new XMLHttpRequest();
      // Changing this to a GET will make the XHR reach the URIProtocol on 4.2.
      // For some reason it still doesn't work though...
      // Add a timestamp to the query param to prevent caching.
      execXhr.open('HEAD', "/!gap_exec?" + (+new Date()), true);
      if (!vcHeaderValue)

      { vcHeaderValue = /.*\((.*)\)/.exec(navigator.userAgent)[1]; }

      execXhr.setRequestHeader('vc', vcHeaderValue);
      execXhr.setRequestHeader('rc', ++requestCount);
      if (shouldBundleCommandJson())

      { execXhr.setRequestHeader('cmds', iOSExec.nativeFetchMessages()); }

      execXhr.send(null);
      break;
      case jsToNativeModes.IFRAME_HASH_NO_PAYLOAD:
      case jsToNativeModes.IFRAME_HASH_WITH_PAYLOAD:
      execHashIframe = execHashIframe || createHashIframe();
      // Check if they've removed it from the DOM, and put it back if so.
      if (!execHashIframe.contentWindow)

      { execHashIframe = createHashIframe(); }

      // The delegate method is called only when the hash changes, so toggle it back and forth.
      hashToggle = hashToggle ^ 3;
      var hashValue = '%0' + hashToggle;
      if (bridgeMode === jsToNativeModes.IFRAME_HASH_WITH_PAYLOAD)

      { hashValue += iOSExec.nativeFetchMessages(); }

      execHashIframe.contentWindow.location.hash = hashValue;
      break;
      default:
      execIframe = execIframe || createExecIframe();
      // Check if they've removed it from the DOM, and put it back if so.
      if (!execIframe.contentWindow)

      { execIframe = createExecIframe(); }

      execIframe.src = "gap://ready";
      }

      The default case did nothing.

      Making it always use jsToNativeModes.XHR_NO_PAYLOAD allows my app to work again with any iOS version but I feel like I'm losing certain advantages from the upgrade. Which are they? Why were the Ternary Operator expressions switched around? Which could be a possible reason why my app, which worked just fine before the upgrade, would stop working because of this change? Is there a better solution than the one I implemented?

      Thanks,

      -JR.

      Attachments

        Issue Links

          Activity

            People

              agrieve Andrew Grieve
              joejoerubio Joel Rubio
              Votes:
              0 Vote for this issue
              Watchers:
              4 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved: