From 08c2cddea2b0732bdad9974052cf7ea71bd22e44 Mon Sep 17 00:00:00 2001
From: Peter Drake <pdrake@allplayers.com>
Date: Wed, 28 Mar 2012 22:16:31 -0400
Subject: [PATCH] Add onAjax and onIframeUpload handlers to ViewSubscriber. 
 Add x-requested-with header to AJAX tests.

---
 core/lib/Drupal/Core/ContentNegotiation.php   | 12 +++-
 .../Core/EventSubscriber/ViewSubscriber.php   | 57 +++++++++++++++++++
 .../simpletest/drupal_web_test_case.php       |  2 +
 3 files changed, 69 insertions(+), 2 deletions(-)

diff --git a/core/lib/Drupal/Core/ContentNegotiation.php b/core/lib/Drupal/Core/ContentNegotiation.php
index f1a33d724d23..ebab1a82da22 100644
--- a/core/lib/Drupal/Core/ContentNegotiation.php
+++ b/core/lib/Drupal/Core/ContentNegotiation.php
@@ -12,10 +12,18 @@ class ContentNegotiation {
 
   public function getContentType(Request $request) {
     $acceptable_content_types = $request->getAcceptableContentTypes();
-    if (in_array('application/json', $request->getAcceptableContentTypes())) {
+    if ($request->isXmlHttpRequest()) {
+      if ($request->get('ajax_iframe_upload', FALSE)) {
+        return 'iframeupload';
+      }
+      else {
+        return 'ajax';
+      }
+    }
+    elseif (in_array('application/json', $request->getAcceptableContentTypes())) {
       return 'json';
     }
-    if(in_array('text/html', $acceptable_content_types) || in_array('*/*', $acceptable_content_types)) {
+    elseif(in_array('text/html', $acceptable_content_types) || in_array('*/*', $acceptable_content_types)) {
       return 'html';
     }
   }
diff --git a/core/lib/Drupal/Core/EventSubscriber/ViewSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/ViewSubscriber.php
index 8ade061551a5..2f22f58bf9d7 100644
--- a/core/lib/Drupal/Core/EventSubscriber/ViewSubscriber.php
+++ b/core/lib/Drupal/Core/EventSubscriber/ViewSubscriber.php
@@ -37,6 +37,27 @@ protected function createJsonResponse() {
     return $response;
   }
 
+  protected function createAjaxResponse(GetResponseEvent $event) {
+    $response = new Response();
+    $response->headers->set('Content-Type', 'application/json; charset=utf-8');
+
+    return $response;
+  }
+
+  protected function createIframeUploadResponse(GetResponseEvent $event) {
+    $response = new Response();
+
+    // Browsers do not allow JavaScript to read the contents of a user's local
+    // files. To work around that, the jQuery Form plugin submits forms containing
+    // a file input element to an IFRAME, instead of using XHR. Browsers do not
+    // normally expect JSON strings as content within an IFRAME, so the response
+    // must be customized accordingly.
+    // @see http://malsup.com/jquery/form/#file-upload
+    // @see Drupal.ajax.prototype.beforeSend()
+    $response->headers->set('Content-Type', 'text/html; charset=utf-8');
+
+    return $response;
+  }
 
   /**
    * Processes a successful controller into an HTTP 200 response.
@@ -75,6 +96,42 @@ public function onJson(GetResponseEvent $event) {
     return $response;
   }
 
+  public function onAjax(GetResponseEvent $event) {
+    $page_callback_result = $event->getControllerResult();
+
+    // Construct the response content from the page callback result.
+    $commands = ajax_prepare_response($page_callback_result);
+    $json = ajax_render($commands);
+
+    // Build the actual response object.
+    $response = $this->createAjaxResponse($event);
+    $response->setContent($json);
+
+    return $response;
+  }
+
+  public function onIframeUpload(GetResponseEvent $event) {
+    $page_callback_result = $event->getControllerResult();
+
+    // Construct the response content from the page callback result.
+    $commands = ajax_prepare_response($page_callback_result);
+    $json = ajax_render($commands);
+
+    // Browser IFRAMEs expect HTML. Browser extensions, such as Linkification
+    // and Skype's Browser Highlighter, convert URLs, phone numbers, etc. into
+    // links. This corrupts the JSON response. Protect the integrity of the
+    // JSON data by making it the value of a textarea.
+    // @see http://malsup.com/jquery/form/#file-upload
+    // @see http://drupal.org/node/1009382
+    $json = '<textarea>' . $json . '</textarea>';
+
+    // Build the actual response object.
+    $response = $this->createIframeUploadResponse($event);
+    $response->setContent($json);
+
+    return $response;
+  }
+
   /**
    * Processes a successful controller into an HTTP 200 response.
    *
diff --git a/core/modules/simpletest/drupal_web_test_case.php b/core/modules/simpletest/drupal_web_test_case.php
index ded4ad0da0cd..3a6e541ed989 100644
--- a/core/modules/simpletest/drupal_web_test_case.php
+++ b/core/modules/simpletest/drupal_web_test_case.php
@@ -1834,6 +1834,7 @@ protected function drupalGet($path, array $options = array(), array $headers = a
    * Retrieve a Drupal path or an absolute path and JSON decode the result.
    */
   protected function drupalGetAJAX($path, array $options = array(), array $headers = array()) {
+    $headers[] = 'X-Requested-With: XMLHttpRequest';
     return drupal_json_decode($this->drupalGet($path, $options, $headers));
   }
 
@@ -2041,6 +2042,7 @@ protected function drupalPostAJAX($path, $edit, $triggering_element, $ajax_path
     }
     $content = $this->content;
     $drupal_settings = $this->drupalSettings;
+    $headers[] = 'X-Requested-With: XMLHttpRequest';
 
     // Get the Ajax settings bound to the triggering element.
     if (!isset($ajax_settings)) {
-- 
GitLab