Index: includes/browser.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/browser.inc,v
retrieving revision 1.3
diff -u -9 -p -r1.3 browser.inc
--- includes/browser.inc	31 Aug 2009 05:56:54 -0000	1.3
+++ includes/browser.inc	6 Sep 2009 13:23:18 -0000
@@ -1087,48 +1087,30 @@ class BrowserPage {
 
   /**
    * Get the base URL of the page.
    *
    * If a 'base' HTML element is defined then the URL it defines is used as the
    * base URL for the page, otherwise the page URL is used to determine the
    * base URL.
    *
    * @return
-   *   The base URL of the page.
+   *   The absolute base URL of the page.
    */
   public function getBaseUrl() {
-    // Check for base element.
-    $elements = $this->xpath('.//base');
-    if ($elements) {
-      // More than one may be specified.
-      foreach ($elements as $element) {
-        if (isset($element['href'])) {
-          $base = (string) $element['href'];
-          break;
-        }
-      }
+    $base = $this->xpath('/html/head/base[@href]');
+    if ($base) {
+      // According to HTML 4.01, section 12.4, the specified base URL must be
+      // an absolute URL.
+      return (string)$base[0]['href'];
     }
     else {
-      $base = $this->url;
-      if ($pos = strpos($base, '?')) {
-        // Remove query string.
-        $base = substr($base, 0, $pos);
-      }
-
-      // Ignore everything after the last forward slash.
-      $base = substr($base, 0, strrpos($base, '/'));
-    }
-
-    // Ensure that the last character is a forward slash.
-    if ($base[strlen($base) - 1] != '/') {
-      $base .= '/';
+      return $this->url;
     }
-    return $base;
   }
 
   /**
    * Extract the text contained by the element.
    *
    * Strips all XML/HTML tags, decodes HTML entities, and trims the result.
    *
    * @param $element
    *   SimpleXMLElement to extract text from.
Index: modules/simpletest/tests/browser.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/simpletest/tests/browser.test,v
retrieving revision 1.1
diff -u -9 -p -r1.1 browser.test
--- modules/simpletest/tests/browser.test	17 Aug 2009 06:08:47 -0000	1.1
+++ modules/simpletest/tests/browser.test	6 Sep 2009 13:23:19 -0000
@@ -113,11 +113,16 @@ class BrowserPageTestCase extends Drupal
 
     $browser = new Browser();
     $browser->setUserAgent(drupal_generate_test_ua($db_prefix));
 
     $browser->get(url('browser_test/print/post', array('absolute' => TRUE)));
     $page = $browser->getPage();
     $input = $page->xpath('//input[@name="foo"]');
     $input = $input[0];
     $this->assertEqual('foo', $input['name'], t('Field "foo" found'));
+    $this->assertEqual($page->getBaseUrl(), $browser->getUrl(), t('Expected base URL was returned.'));
+
+    $browser->get(url('browser_test/base', array('absolute' => TRUE)));
+    $page = $browser->getPage();
+    $this->assertEqual($page->getBaseUrl(), url('', array('query' => 'new_base_url', 'absolute' => TRUE)), t('&lt;base href&gt; was detected.'.$page->getBaseUrl()));
   }
 }
Index: modules/simpletest/tests/browser_test.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/simpletest/tests/browser_test.module,v
retrieving revision 1.1
diff -u -9 -p -r1.1 browser_test.module
--- modules/simpletest/tests/browser_test.module	17 Aug 2009 06:08:47 -0000	1.1
+++ modules/simpletest/tests/browser_test.module	6 Sep 2009 13:23:19 -0000
@@ -16,18 +16,22 @@ function browser_test_menu() {
     'page callback' => 'browser_test_print_get',
     'access arguments' => array('access content'),
   );
   $items['browser_test/print/post'] = array(
     'page callback' => 'drupal_get_form',
     'page arguments' => array('browser_test_print_post_form'),
     'access arguments' => array('access content'),
   );
 
+  $items['browser_test/base'] = array(
+    'page callback' => 'browser_test_base',
+    'access arguments' => array('access content'),
+  );
   $items['browser_test/refresh/meta'] = array(
     'page callback' => 'browser_test_refresh_meta',
     'access arguments' => array('access content'),
   );
   $items['browser_test/refresh/header'] = array(
     'page callback' => 'browser_test_refresh_header',
     'access arguments' => array('access content'),
   );
 
@@ -52,18 +56,23 @@ function browser_test_print_post_form(&$
 
   return $form;
 }
 
 function browser_test_print_post_form_submit($form, &$form_state) {
   echo $form_state['values']['foo'];
   exit;
 }
 
+function browser_test_base() {
+  drupal_add_html_head('<base href="' . check_plain(url('', array('query' => 'new_base_url', 'absolute' => TRUE))) . '" />');
+  return 'Lorem ipsum';
+}
+
 function browser_test_refresh_meta() {
   if (!isset($_GET['refresh'])) {
     $url = url('browser_test/refresh/meta', array('absolute' => TRUE, 'query' => 'refresh=true'));
     drupal_add_html_head('<meta http-equiv="Refresh" content="0; URL=' . $url . '">');
     return '';
   }
   echo 'Refresh successful';
   exit;
 }
