Fix XHR interceptor in CC RCE thread page

The XHR interceptor stopped working in the redesigned Community Console
thread pages (aka RCE/interop thread page). This is due to the fact that
the Javascript loaded before the XHR interceptor was set, and because
the requests differed in the Javascript types used, and the format of
the requests (an array to encode protobuf messages is used instead of
objects in the RCE thread page).

This CL fixes these issues.

Change-Id: I591d58f5f597a71a2794ee59b2c5cb9dd88cca9f
diff --git a/src/injections/xhrInterceptor.js b/src/injections/xhrInterceptor.js
index 3ea4474..071daf5 100644
--- a/src/injections/xhrInterceptor.js
+++ b/src/injections/xhrInterceptor.js
@@ -1,11 +1,14 @@
+import {correctArrayKeys} from '../common/protojs';
 import * as utils from '../common/xhrInterceptorUtils.js';
 
-const originalOpen = XMLHttpRequest.prototype.open;
-const originalSend = XMLHttpRequest.prototype.send;
+const originalOpen = window.XMLHttpRequest.prototype.open;
+const originalSetRequestHeader =
+    window.XMLHttpRequest.prototype.setRequestHeader;
+const originalSend = window.XMLHttpRequest.prototype.send;
 
 let messageID = 0;
 
-XMLHttpRequest.prototype.open = function() {
+window.XMLHttpRequest.prototype.open = function() {
   this.$TWPTRequestURL = arguments[1] || location.href;
   this.$TWPTID = messageID++;
 
@@ -23,24 +26,39 @@
   originalOpen.apply(this, arguments);
 };
 
-XMLHttpRequest.prototype.send = function() {
+window.XMLHttpRequest.prototype.setRequestHeader = function() {
+  originalSetRequestHeader.apply(this, arguments);
+
+  let header = arguments[0];
+  let value = arguments[1];
+  if ('Content-Type'.localeCompare(
+          header, undefined, {sensitivity: 'accent'}) == 0)
+    this.$isArrayProto = (value == 'application/json+protobuf');
+};
+
+window.XMLHttpRequest.prototype.send = function() {
   originalSend.apply(this, arguments);
 
   let interceptors =
       utils.matchInterceptors('request', this.$TWPTRequestURL || location.href);
   if (interceptors.length > 0) {
-    var rawBody = arguments[0];
-    if (typeof (rawBody) !== 'object' ||
-        !(rawBody instanceof Object.getPrototypeOf(Uint8Array))) {
+    let rawBody = arguments[0];
+    let body;
+    if (typeof (rawBody) === 'object' &&
+        (rawBody instanceof Object.getPrototypeOf(Uint8Array))) {
+      let dec = new TextDecoder('utf-8');
+      body = dec.decode(rawBody);
+    } else if (typeof (rawBody) === 'string') {
+      body = rawBody;
+    } else {
       console.error(
-          'Request body is not Uint8Array, but ' + typeof (rawBody) + '.',
-          this.$TWPTRequestUrl);
+          'Unexpected type of request body (' + typeof (rawBody) + ').',
+          this.$TWPTRequestURL);
       return;
     }
 
-    var dec = new TextDecoder('utf-8');
-    var body = dec.decode(rawBody);
-    var JSONBody = JSON.parse(body);
+    let JSONBody = JSON.parse(body);
+    if (this.$isArrayProto) JSONBody = correctArrayKeys(JSONBody);
 
     interceptors.forEach(i => {
       utils.triggerEvent(i.eventName, JSONBody, this.$TWPTID);