Commit 942e331e authored by reed@reedloden.com's avatar reed@reedloden.com
Browse files

Bug 397073 - "Allow runtime overrides by OS version for chrome" [p=Mossop r=bsmedberg a1.9=schrep]

parent 8e6b2666
Loading
Loading
Loading
Loading
+80 −7
Original line number Diff line number Diff line
@@ -44,6 +44,11 @@

#include "prio.h"
#include "prprf.h"
#if defined(XP_WIN)
#include <windows.h>
#elif defined(XP_MACOSX)
#include <Carbon/Carbon.h>
#endif

#include "nsAppDirectoryServiceDefs.h"
#include "nsArrayEnumerator.h"
@@ -63,6 +68,7 @@
#include "nsWidgetsCID.h"
#include "nsXPIDLString.h"
#include "nsXULAppAPI.h"
#include "nsTextFormatter.h"

#include "nsIAtom.h"
#include "nsICommandLine.h"
@@ -1970,7 +1976,8 @@ CheckStringFlag(const nsSubstring& aFlag, const nsSubstring& aData,
 * @param aFlag The flag to compare.
 * @param aData The tokenized data to check; this is lowercased
 *              before being passed in.
 * @param aValue The value that is expected.
 * @param aValue The value that is expected. If this is empty then no
 *               comparison will match.
 * @param aChecker the version checker to use. If null, aResult will always
 *                 be eBad.
 * @param aResult If this is eOK when passed in, this is left alone.
@@ -1993,6 +2000,12 @@ CheckVersionFlag(const nsSubstring& aFlag, const nsSubstring& aData,
  if (!StringBeginsWith(aData, aFlag))
    return PR_FALSE;

  if (aValue.Length() == 0) {
    if (aResult != eOK)
      aResult = eBad;
    return PR_TRUE;
  }

  PRUint32 comparison;
  nsAutoString testdata;

@@ -2077,6 +2090,8 @@ nsChromeRegistry::ProcessManifestBuffer(char *buf, PRInt32 length,
  NS_NAMED_LITERAL_STRING(kXPCNativeWrappers, "xpcnativewrappers");
  NS_NAMED_LITERAL_STRING(kApplication, "application");
  NS_NAMED_LITERAL_STRING(kAppVersion, "appversion");
  NS_NAMED_LITERAL_STRING(kOs, "os");
  NS_NAMED_LITERAL_STRING(kOsVersion, "osversion");

  nsCOMPtr<nsIIOService> io (do_GetIOService());
  if (!io) return NS_ERROR_FAILURE;
@@ -2090,6 +2105,7 @@ nsChromeRegistry::ProcessManifestBuffer(char *buf, PRInt32 length,

  nsAutoString appID;
  nsAutoString appVersion;
  nsAutoString osTarget;
  nsCOMPtr<nsIXULAppInfo> xapp (do_GetService(XULAPPINFO_SERVICE_CONTRACTID));
  if (xapp) {
    nsCAutoString s;
@@ -2100,7 +2116,34 @@ nsChromeRegistry::ProcessManifestBuffer(char *buf, PRInt32 length,
    rv = xapp->GetVersion(s);
    if (NS_SUCCEEDED(rv))
      CopyUTF8toUTF16(s, appVersion);
    
    nsCOMPtr<nsIXULRuntime> xruntime (do_QueryInterface(xapp));
    if (xruntime) {
      rv = xruntime->GetOS(s);
      if (NS_SUCCEEDED(rv)) {
        CopyUTF8toUTF16(s, osTarget);
        ToLowerCase(osTarget);
      }
    }
  }
  
  nsAutoString osVersion;
#if defined(XP_WIN)
  OSVERSIONINFO info = { sizeof(OSVERSIONINFO) };
  if (GetVersionEx(&info)) {
    nsTextFormatter::ssprintf(osVersion, NS_LITERAL_STRING("%ld.%ld").get(),
                                         info.dwMajorVersion,
                                         info.dwMinorVersion);
  }
#elif defined(XP_MACOSX)
  long majorVersion, minorVersion;
  if ((Gestalt(gestaltSystemVersionMajor, &majorVersion) == noErr) &&
      (Gestalt(gestaltSystemVersionMinor, &minorVersion) == noErr)) {
    nsTextFormatter::ssprintf(osVersion, NS_LITERAL_STRING("%ld.%ld").get(),
                                         majorVersion,
                                         minorVersion);
  }
#endif

  char *token;
  char *newline = buf;
@@ -2140,6 +2183,8 @@ nsChromeRegistry::ProcessManifestBuffer(char *buf, PRInt32 length,
      PRBool xpcNativeWrappers = PR_TRUE;
      TriState stAppVersion = eUnspecified;
      TriState stApp = eUnspecified;
      TriState stOsVersion = eUnspecified;
      TriState stOs = eUnspecified;

      PRBool badFlag = PR_FALSE;

@@ -2151,6 +2196,8 @@ nsChromeRegistry::ProcessManifestBuffer(char *buf, PRInt32 length,
        if (CheckFlag(kPlatform, wtoken, platform) ||
            CheckFlag(kXPCNativeWrappers, wtoken, xpcNativeWrappers) ||
            CheckStringFlag(kApplication, wtoken, appID, stApp) ||
            CheckStringFlag(kOs, wtoken, osTarget, stOs) ||
            CheckVersionFlag(kOsVersion, wtoken, osVersion, vc, stOsVersion) ||
            CheckVersionFlag(kAppVersion, wtoken, appVersion, vc, stAppVersion))
          continue;

@@ -2160,7 +2207,8 @@ nsChromeRegistry::ProcessManifestBuffer(char *buf, PRInt32 length,
        badFlag = PR_TRUE;
      }

      if (badFlag || stApp == eBad || stAppVersion == eBad)
      if (badFlag || stApp == eBad || stAppVersion == eBad || 
          stOs == eBad || stOsVersion == eBad)
        continue;

      nsCOMPtr<nsIURI> resolved;
@@ -2211,6 +2259,8 @@ nsChromeRegistry::ProcessManifestBuffer(char *buf, PRInt32 length,

      TriState stAppVersion = eUnspecified;
      TriState stApp = eUnspecified;
      TriState stOs = eUnspecified;
      TriState stOsVersion = eUnspecified;

      PRBool badFlag = PR_FALSE;

@@ -2220,6 +2270,8 @@ nsChromeRegistry::ProcessManifestBuffer(char *buf, PRInt32 length,
        ToLowerCase(wtoken);

        if (CheckStringFlag(kApplication, wtoken, appID, stApp) ||
            CheckStringFlag(kOs, wtoken, osTarget, stOs) ||
            CheckVersionFlag(kOsVersion, wtoken, osVersion, vc, stOsVersion) ||
            CheckVersionFlag(kAppVersion, wtoken, appVersion, vc, stAppVersion))
          continue;

@@ -2229,7 +2281,8 @@ nsChromeRegistry::ProcessManifestBuffer(char *buf, PRInt32 length,
        badFlag = PR_TRUE;
      }

      if (badFlag || stApp == eBad || stAppVersion == eBad)
      if (badFlag || stApp == eBad || stAppVersion == eBad ||
          stOs == eBad || stOsVersion == eBad)
        continue;

      nsCOMPtr<nsIURI> resolved;
@@ -2261,6 +2314,8 @@ nsChromeRegistry::ProcessManifestBuffer(char *buf, PRInt32 length,

      TriState stAppVersion = eUnspecified;
      TriState stApp = eUnspecified;
      TriState stOs = eUnspecified;
      TriState stOsVersion = eUnspecified;

      PRBool badFlag = PR_FALSE;

@@ -2270,6 +2325,8 @@ nsChromeRegistry::ProcessManifestBuffer(char *buf, PRInt32 length,
        ToLowerCase(wtoken);

        if (CheckStringFlag(kApplication, wtoken, appID, stApp) ||
            CheckStringFlag(kOs, wtoken, osTarget, stOs) ||
            CheckVersionFlag(kOsVersion, wtoken, osVersion, vc, stOsVersion) ||
            CheckVersionFlag(kAppVersion, wtoken, appVersion, vc, stAppVersion))
          continue;

@@ -2279,7 +2336,8 @@ nsChromeRegistry::ProcessManifestBuffer(char *buf, PRInt32 length,
        badFlag = PR_TRUE;
      }

      if (badFlag || stApp == eBad || stAppVersion == eBad)
      if (badFlag || stApp == eBad || stAppVersion == eBad ||
          stOs == eBad || stOsVersion == eBad)
        continue;

      nsCOMPtr<nsIURI> resolved;
@@ -2313,6 +2371,8 @@ nsChromeRegistry::ProcessManifestBuffer(char *buf, PRInt32 length,

      TriState stAppVersion = eUnspecified;
      TriState stApp = eUnspecified;
      TriState stOs = eUnspecified;
      TriState stOsVersion = eUnspecified;

      PRBool badFlag = PR_FALSE;

@@ -2322,6 +2382,8 @@ nsChromeRegistry::ProcessManifestBuffer(char *buf, PRInt32 length,
        ToLowerCase(wtoken);

        if (CheckStringFlag(kApplication, wtoken, appID, stApp) ||
            CheckStringFlag(kOs, wtoken, osTarget, stOs) ||
            CheckVersionFlag(kOsVersion, wtoken, osVersion, vc, stOsVersion) ||
            CheckVersionFlag(kAppVersion, wtoken, appVersion, vc, stAppVersion))
          continue;

@@ -2331,7 +2393,8 @@ nsChromeRegistry::ProcessManifestBuffer(char *buf, PRInt32 length,
        badFlag = PR_TRUE;
      }

      if (badFlag || stApp == eBad || stAppVersion == eBad)
      if (badFlag || stApp == eBad || stAppVersion == eBad ||
          stOs == eBad || stOsVersion == eBad)
        continue;

      nsCOMPtr<nsIURI> baseuri, overlayuri;
@@ -2357,6 +2420,8 @@ nsChromeRegistry::ProcessManifestBuffer(char *buf, PRInt32 length,

      TriState stAppVersion = eUnspecified;
      TriState stApp = eUnspecified;
      TriState stOs = eUnspecified;
      TriState stOsVersion = eUnspecified;

      PRBool badFlag = PR_FALSE;

@@ -2366,6 +2431,8 @@ nsChromeRegistry::ProcessManifestBuffer(char *buf, PRInt32 length,
        ToLowerCase(wtoken);

        if (CheckStringFlag(kApplication, wtoken, appID, stApp) ||
            CheckStringFlag(kOs, wtoken, osTarget, stOs) ||
            CheckVersionFlag(kOsVersion, wtoken, osVersion, vc, stOsVersion) ||
            CheckVersionFlag(kAppVersion, wtoken, appVersion, vc, stAppVersion))
          continue;

@@ -2375,7 +2442,8 @@ nsChromeRegistry::ProcessManifestBuffer(char *buf, PRInt32 length,
        badFlag = PR_TRUE;
      }

      if (badFlag || stApp == eBad || stAppVersion == eBad)
      if (badFlag || stApp == eBad || stAppVersion == eBad ||
          stOs == eBad || stOsVersion == eBad)
        continue;

      nsCOMPtr<nsIURI> baseuri, overlayuri;
@@ -2405,6 +2473,8 @@ nsChromeRegistry::ProcessManifestBuffer(char *buf, PRInt32 length,

      TriState stAppVersion = eUnspecified;
      TriState stApp = eUnspecified;
      TriState stOs = eUnspecified;
      TriState stOsVersion = eUnspecified;

      PRBool badFlag = PR_FALSE;

@@ -2414,6 +2484,8 @@ nsChromeRegistry::ProcessManifestBuffer(char *buf, PRInt32 length,
        ToLowerCase(wtoken);

        if (CheckStringFlag(kApplication, wtoken, appID, stApp) ||
            CheckStringFlag(kOs, wtoken, osTarget, stOs) ||
            CheckVersionFlag(kOsVersion, wtoken, osVersion, vc, stOsVersion) ||
            CheckVersionFlag(kAppVersion, wtoken, appVersion, vc, stAppVersion))
          continue;

@@ -2423,7 +2495,8 @@ nsChromeRegistry::ProcessManifestBuffer(char *buf, PRInt32 length,
        badFlag = PR_TRUE;
      }

      if (badFlag || stApp == eBad || stAppVersion == eBad)
      if (badFlag || stApp == eBad || stAppVersion == eBad ||
          stOs == eBad || stOsVersion == eBad)
        continue;

      nsCOMPtr<nsIURI> chromeuri, resolveduri;
+6 −0
Original line number Diff line number Diff line
# Success cases
content  test1  test/  os=xpcshell
content  test2  test/  os=XPCshell

# Failure cases
content  test3  test/  os=FOOshell
+178 −0
Original line number Diff line number Diff line
/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is mozilla.org code.
 *
 * The Initial Developer of the Original Code is
 *      Dave Townsend <dtownsend@oxymoronical.com>.
 *
 * Portions created by the Initial Developer are Copyright (C) 2007
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK *****
 */

const XULAPPINFO_CONTRACTID = "@mozilla.org/xre/app-info;1";
const XULAPPINFO_CID = Components.ID("{48a4e946-1f9f-4224-b4b0-9a54183cb81e}");

const NS_CHROME_MANIFESTS_FILE_LIST = "ChromeML";

const Cc = Components.classes;
const Ci = Components.interfaces;

var MANIFESTS = [
  do_get_file("chrome/test/unit/data/test_bug397073.manifest")
];

function ArrayEnumerator(array)
{
  this.array = array;
}

ArrayEnumerator.prototype = {
  pos: 0,
  array: null,
  
  hasMoreElements: function() {
    return this.pos < this.array.length;
  },
  
  getNext: function() {
    if (this.pos < this.array.length)
      return this.array[this.pos++];
    throw Components.results.NS_ERROR_FAILURE;
  },

  QueryInterface: function(iid) {
    if (iid.equals(Ci.nsISimpleEnumerator)
     || iid.equals(Ci.nsISupports))
      return this;

    throw Components.results.NS_ERROR_NO_INTERFACE;
  }
};

var ChromeProvider = {
  getFile: function(prop, persistent) {
    throw Components.results.NS_ERROR_FAILURE
  },
  
  getFiles: function(prop) {
    if (prop == NS_CHROME_MANIFESTS_FILE_LIST) {
      return new ArrayEnumerator(MANIFESTS);
    }
    throw Components.results.NS_ERROR_FAILURE
  },
  
  QueryInterface: function(iid) {
    if (iid.equals(Ci.nsIDirectoryServiceProvider)
     || iid.equals(Ci.nsIDirectoryServiceProvider2)
     || iid.equals(Ci.nsISupports))
      return this;

    throw Components.results.NS_ERROR_NO_INTERFACE;
  }
};
var dirSvc = Cc["@mozilla.org/file/directory_service;1"]
              .getService(Ci.nsIDirectoryService);
dirSvc.registerProvider(ChromeProvider);

var XULAppInfo = {
  vendor: "Mozilla",
  name: "XPCShell",
  ID: "{39885e5f-f6b4-4e2a-87e5-6259ecf79011}",
  version: "5",
  appBuildID: "2007010101",
  platformVersion: "1.9",
  platformBuildID: "2007010101",
  inSafeMode: false,
  logConsoleErrors: true,
  OS: "XPCShell",
  XPCOMABI: "noarch-spidermonkey",
  
  QueryInterface: function QueryInterface(iid) {
    if (iid.equals(Ci.nsIXULAppInfo)
     || iid.equals(Ci.nsIXULRuntime)
     || iid.equals(Ci.nsISupports))
      return this;
  
    throw Components.results.NS_ERROR_NO_INTERFACE;
  }
};

var XULAppInfoFactory = {
  createInstance: function (outer, iid) {
    if (outer != null)
      throw Components.results.NS_ERROR_NO_AGGREGATION;
    return XULAppInfo.QueryInterface(iid);
  }
};
var registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar);
registrar.registerFactory(XULAPPINFO_CID, "XULAppInfo",
                          XULAPPINFO_CONTRACTID, XULAppInfoFactory);

var gIOS = Cc["@mozilla.org/network/io-service;1"]
            .getService(Ci.nsIIOService);
var chromeReg = Cc["@mozilla.org/chrome/chrome-registry;1"]
                 .getService(Ci.nsIChromeRegistry);
chromeReg.checkForNewChrome();

var target = gIOS.newFileURI(do_get_file("chrome/test/unit/data"));
target = target.spec + "test/test.xul";

function test_succeeded_mapping(namespace)
{
  var uri = gIOS.newURI("chrome://" + namespace + "/content/test.xul",
                        null, null);
  try {
    var result = chromeReg.convertChromeURL(uri);
    do_check_eq(result.spec, target);
  }
  catch (ex) {
    do_throw(namespace);
  }
}

function test_failed_mapping(namespace)
{
  var uri = gIOS.newURI("chrome://" + namespace + "/content/test.xul",
                        null, null);
  try {
    var result = chromeReg.convertChromeURL(uri);
    do_throw(namespace);
  }
  catch (ex) {
  }
}

function run_test()
{
  test_succeeded_mapping("test1");
  test_succeeded_mapping("test2");

  test_failed_mapping("test3");
}