Index: modules/system/system.js
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.js,v
retrieving revision 1.35
diff -u -p -r1.35 system.js
--- modules/system/system.js	9 Sep 2009 21:53:15 -0000	1.35
+++ modules/system/system.js	27 Sep 2009 21:58:35 -0000
@@ -164,6 +164,22 @@ Drupal.behaviors.pageCache = {
 };
 
 /**
+ * Checks to see if the cron should be automatically run.
+ */
+Drupal.behaviors.cronCheck = {
+  attach: function(context, settings) {
+    if (settings.cronCheck || false) {
+      $('body').once('cron-check', function() {
+        // Only execute the cron check if its the right time.
+        if (Math.round(new Date().getTime() / 1000.0) > settings.cronCheck) {
+          $.get(settings.basePath + 'system/run-cron-check');
+        }
+      });
+    }
+  }
+};
+
+/**
  * Attach the auto machine readable name behavior.
  *
  * Settings are expected to be an object of elements to process, where the key
@@ -226,4 +242,3 @@ Drupal.behaviors.machineReadableValue = 
 };
 
 })(jQuery);
-
Index: modules/system/system.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.module,v
retrieving revision 1.796
diff -u -p -r1.796 system.module
--- modules/system/system.module	25 Sep 2009 23:48:24 -0000	1.796
+++ modules/system/system.module	27 Sep 2009 21:58:36 -0000
@@ -201,9 +201,6 @@ function system_theme() {
       'arguments' => array('version' => NULL),
     ),
     'system_compact_link' => array(),
-    'system_run_cron_image' => array(
-      'arguments' => array('image_path' => NULL),
-    ),
   ));
 }
 
@@ -496,10 +493,10 @@ function system_menu() {
     'type' => MENU_CALLBACK,
     'file' => 'system.admin.inc',
   );
-  $items['system/run-cron-image'] = array(
+  $items['system/run-cron-check'] = array(
     'title' => 'Execute cron',
-    'page callback' => 'system_run_cron_image',
-    'access callback' => 'system_run_cron_image_access',
+    'page callback' => 'system_run_cron_check',
+    'access callback' => 'system_run_cron_check_access',
     'type' => MENU_CALLBACK,
     'file' => 'system.admin.inc',
   );
@@ -1666,7 +1663,7 @@ function system_admin_menu_block($item) 
   $has_subitems = FALSE;
   $result = db_query("
     SELECT m.load_functions, m.to_arg_functions, m.access_callback, m.access_arguments, m.page_callback, m.page_arguments, m.title, m.title_callback, m.title_arguments, m.type, m.description, m.path, m.weight as router_weight, ml.*
-    FROM {menu_router} m 
+    FROM {menu_router} m
     LEFT JOIN {menu_links} ml ON m.path = ml.router_path
     WHERE (ml.plid = :plid AND ml.menu_name = :name AND hidden = 0) OR (m.tab_parent = :path AND m.type IN (:local_task, :default_task))", array(':plid' => $item['mlid'], ':name' => $item['menu_name'], ':path' => $item['path'], ':local_task' => MENU_LOCAL_TASK, ':default_task' => MENU_DEFAULT_LOCAL_TASK), array('fetch' => PDO::FETCH_ASSOC));
   foreach ($result as $link) {
@@ -1700,7 +1697,7 @@ function system_admin_menu_block($item) 
     }
   }
   if ($has_subitems) {
-    // If we've had at least one non-tab subitem, remove the link for the 
+    // If we've had at least one non-tab subitem, remove the link for the
     // default task, since that is already broken down to subitems.
     unset($content[$default_task]);
   }
@@ -2790,43 +2787,38 @@ function system_retrieve_file($url, $des
  */
 function system_page_build(&$page) {
   // Automatic cron runs.
-  // @see system_run_cron_image()
-  if (system_run_cron_image_access()) {
+  if (system_run_cron_check_access()) {
     $page['page_bottom']['run_cron'] = array(
-      // Trigger cron run via AJAX.
       '#attached' => array(
         'js' => array(
-          '(function($){ $.get(' . drupal_json_encode(url('system/run-cron-image')) . '); })(jQuery);' => array('type' => 'inline', 'scope' => 'header'),
+          drupal_get_path('module', 'system') . '/system.js' => array('weight' => JS_DEFAULT - 5),
+          array(
+            'data' => array(
+              // Add the timestamp for when the next automatic cron run should
+              // happen.
+              'cronCheck' => variable_get('cron_last', 0) + variable_get('cron_safe_threshold', DRUPAL_CRON_DEFAULT_THRESHOLD),
+            ),
+            'type' => 'setting',
+          ),
         ),
       ),
-      // Trigger cron run for clients not supporting JavaScript (fall-back).
-      '#markup' => theme('system_run_cron_image', 'system/run-cron-image'),
     );
   }
 }
 
 /**
- * Menu callback; executes cron via an image callback.
+ * Menu callback; executes cron via an AJAX callback.
  *
  * This callback runs cron in a separate HTTP request to prevent "mysterious"
- * slow-downs of regular HTTP requests. It is either invoked via an AJAX request
- * (if the client's browser supports JavaScript) or by an IMG tag directly in
- * the page output (for clients not supporting JavaScript). For the latter case,
- * we need to output a transparent 1x1 image, so the browser does not render the
- * image's alternate text or a 'missing image placeholder'. The AJAX request
- * does not process the returned output.
+ * slow-downs of regular HTTP requests. It is invoked via an AJAX request
+ * (if the client's browser supports JavaScript)
  *
  * @see system_page_alter()
- * @see theme_system_run_cron_image()
- * @see system_run_cron_image_access()
+ * @see system_run_cron_check_access()
  */
-function system_run_cron_image() {
+function system_run_cron_check() {
   drupal_page_is_cacheable(FALSE);
-
-  // Output a transparent 1x1 image to the browser; required for clients not
-  // supporting JavaScript.
-  drupal_set_header('Content-Type', 'image/gif');
-  echo "\x47\x49\x46\x38\x39\x61\x1\x0\x1\x0\x80\xff\x0\xc0\xc0\xc0\x0\x0\x0\x21\xf9\x4\x1\x0\x0\x0\x0\x2c\x0\x0\x0\x0\x1\x0\x1\x0\x0\x2\x2\x44\x1\x0\x3b";
+  $cron_run = FALSE;
 
   // Cron threshold semaphore is used to avoid errors every time the image
   // callback is displayed when a previous cron is still running.
@@ -2848,12 +2840,13 @@ function system_run_cron_image() {
     if (!isset($cron_last) || (REQUEST_TIME - $cron_last > $cron_threshold)) {
       // Lock cron threshold semaphore.
       variable_set('cron_threshold_semaphore', REQUEST_TIME);
-      drupal_cron_run();
+      $cron_run = drupal_cron_run();
       // Release the cron threshold semaphore.
       variable_del('cron_threshold_semaphore');
     }
   }
 
+  drupal_json_output(array('cron_run' => $cron_run));
   exit;
 }
 
@@ -2865,25 +2858,9 @@ function system_run_cron_image() {
  * @return
  *   TRUE if cron threshold is enabled, FALSE otherwise.
  *
- * @see system_run_cron_image()
+ * @see system_run_cron_check()
  * @see system_page_alter()
  */
-function system_run_cron_image_access() {
+function system_run_cron_check_access() {
   return variable_get('cron_safe_threshold', DRUPAL_CRON_DEFAULT_THRESHOLD) > 0;
 }
-
-/**
- * Display image used to run cron automatically.
- *
- * Renders an image pointing to the automatic cron run menu callback for
- * graceful degradation when Javascript is not available. The wrapping NOSCRIPT
- * tag ensures that only browsers not supporting JavaScript render the image.
- *
- * @see system_page_alter()
- * @see system_run_cron_image()
- * @ingroup themeable
- */
-function theme_system_run_cron_image($image_path) {
-  return '<noscript><div id="system-cron-image">' . theme('image', $image_path, '', '', array(), FALSE) . '</div></noscript>';
-}
-
Index: modules/system/system.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.test,v
retrieving revision 1.77
diff -u -p -r1.77 system.test
--- modules/system/system.test	21 Sep 2009 06:44:14 -0000	1.77
+++ modules/system/system.test	27 Sep 2009 21:58:36 -0000
@@ -361,8 +361,8 @@ class CronRunTestCase extends DrupalWebT
    */
   public static function getInfo() {
     return array(
-      'name' => 'Cron run',
-      'description' => 'Test cron run.',
+      'name' => 'Cron functionality',
+      'description' => 'Test cron runs and access to cron.php.',
       'group' => 'System'
     );
   }
@@ -392,48 +392,45 @@ class CronRunTestCase extends DrupalWebT
   }
 
   /**
-   * Follow every image paths in the previously retrieved content.
-   */
-  function drupalGetAllImages() {
-    foreach ($this->xpath('//img') as $image) {
-      $this->drupalGet($this->getAbsoluteUrl($image['src']));
-    }
-  }
-
-  /**
-   * Ensure that the cron image callback to run it automatically is working.
+   * Ensure that the automatic cron run callback is working.
    *
    * In these tests we do not use REQUEST_TIME to track start time, because we
    * need the exact time when cron is triggered.
    */
-  function testCronThreshold() {
+  function testAutomaticCron() {
     // Ensure cron does not run when the cron threshold is enabled and was
     // not passed.
-    $start_cron_last = time();
-    variable_set('cron_last', $start_cron_last);
-    variable_set('cron_safe_threshold', 10);
+    $cron_last = time();
+    $cron_safe_threshold = 100;
+    variable_set('cron_last', $cron_last);
+    variable_set('cron_safe_threshold', $cron_safe_threshold);
     $this->drupalGet('');
-    // Follow every image path on the page.
-    $this->drupalGetAllImages();
-    $this->assertTrue($start_cron_last == variable_get('cron_last', NULL), t('Cron does not run when the cron threshold is not passed.'));
+    $this->assertRaw('"cronCheck":' . ($cron_last + $cron_safe_threshold));
+    $this->drupalGet('system/run-cron-check');
+    $this->assertTrue($cron_last == variable_get('cron_last', NULL), t('Cron does not run when the cron threshold is not passed.'));
 
     // Test if cron runs when the cron threshold was passed.
-    $start_cron_last = time() - 15;
-    variable_set('cron_last', $start_cron_last);
+    $cron_last = time() - 200;
+    variable_set('cron_last', $cron_last);
     $this->drupalGet('');
-    // Follow every image path on the page.
-    $this->drupalGetAllImages();
-    $this->assertTrue(variable_get('cron_last', NULL) > $start_cron_last, t('Cron runs when the cron threshold is passed.'));
-
-    // Test if cron does not run when the cron threshold was is disabled.
-    $start_cron_last = time() - 15;
-    variable_set('cron_safe_threshold', 0);
-    variable_set('cron_last', $start_cron_last);
+    $this->assertRaw('"cronCheck":' . ($cron_last + $cron_safe_threshold));
+    $this->drupalGet('system/run-cron-check');
+    $this->assertTrue($cron_last < variable_get('cron_last', NULL), t('Cron runs when the cron threshold is passed.'));
+
+    // Disable the cron threshold through the interface.
+    $admin_user = $this->drupalCreateUser(array('administer site configuration'));
+    $this->drupalLogin($admin_user);
+    $this->drupalPost('admin/config/system/site-information', array('cron_safe_threshold' => 0), t('Save configuration'));
+    $this->assertText(t('The configuration options have been saved.'));
+
+    // Test if cron does not run when the cron threshold is disabled.
+    $cron_last = time() - 200;
+    variable_set('cron_last', $cron_last);
     $this->drupalGet('');
-    // Follow every image path on the page.
-    $this->drupalGetAllImages();
-    $this->assertTrue($start_cron_last == variable_get('cron_last', NULL), t('Cron does not run when the cron threshold is disabled.'));
-  }
+    $this->assertNoRaw('cronCheck');
+    $this->drupalGet('system/run-cron-check');
+    $this->assertTrue($cron_last == variable_get('cron_last', NULL), t('Cron does not run when the cron threshold is disabled.'));
+    }
 
   /**
    * Ensure that temporary files are removed.
@@ -1210,7 +1207,7 @@ class TokenReplaceTestCase extends Drupa
     // passed properly through the call stack and being handled correctly by a 'known'
     // token, [node:title].
     $this->assertFalse(strcmp($target, $result), t('Basic placeholder tokens replaced.'));
-    
+
     $raw_tokens = array('title' => '[node:title]');
     $generated = token_generate('node', $raw_tokens, array('node' => $node));
     $this->assertFalse(strcmp($generated['[node:title]'], check_plain($node->title)), t('Token sanitized.'));
