LCOV - code coverage report
Current view: directory - js/xpconnect/shell - xpcshell.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 873 377 43.2 %
Date: 2012-06-02 Functions: 81 35 43.2 %

       1                 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
       2                 :  * vim: set ts=2 sw=4 et tw=80:
       3                 :  *
       4                 :  * ***** BEGIN LICENSE BLOCK *****
       5                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       6                 :  *
       7                 :  * The contents of this file are subject to the Mozilla Public License Version
       8                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       9                 :  * the License. You may obtain a copy of the License at
      10                 :  * http://www.mozilla.org/MPL/
      11                 :  *
      12                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      13                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      14                 :  * for the specific language governing rights and limitations under the
      15                 :  * License.
      16                 :  *
      17                 :  * The Original Code is Mozilla Communicator client code, released
      18                 :  * March 31, 1998.
      19                 :  *
      20                 :  * The Initial Developer of the Original Code is
      21                 :  * Netscape Communications Corporation.
      22                 :  * Portions created by the Initial Developer are Copyright (C) 1998
      23                 :  * the Initial Developer. All Rights Reserved.
      24                 :  *
      25                 :  * Contributor(s):
      26                 :  *   John Bandhauer <jband@netscape.com>
      27                 :  *   Pierre Phaneuf <pp@ludusdesign.com>
      28                 :  *   IBM Corp.
      29                 :  *   Dan Mosedale <dan.mosedale@oracle.com>
      30                 :  *   Serge Gautherie <sgautherie.bz@free.fr>
      31                 :  *
      32                 :  * Alternatively, the contents of this file may be used under the terms of
      33                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      34                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      35                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      36                 :  * of those above. If you wish to allow use of your version of this file only
      37                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      38                 :  * use your version of this file under the terms of the MPL, indicate your
      39                 :  * decision by deleting the provisions above and replace them with the notice
      40                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      41                 :  * the provisions above, a recipient may use your version of this file under
      42                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      43                 :  *
      44                 :  * ***** END LICENSE BLOCK ***** */
      45                 : 
      46                 : /* XPConnect JavaScript interactive shell. */
      47                 : 
      48                 : #include <stdio.h>
      49                 : 
      50                 : #include "mozilla/Util.h"
      51                 : 
      52                 : #include "jsapi.h"
      53                 : #include "jsdbgapi.h"
      54                 : #include "jsfriendapi.h"
      55                 : #include "jsprf.h"
      56                 : #include "nsXULAppAPI.h"
      57                 : #include "nsServiceManagerUtils.h"
      58                 : #include "nsComponentManagerUtils.h"
      59                 : #include "nsStringAPI.h"
      60                 : #include "nsIXPConnect.h"
      61                 : #include "nsIXPCScriptable.h"
      62                 : #include "nsIInterfaceInfo.h"
      63                 : #include "nsIInterfaceInfoManager.h"
      64                 : #include "nsIXPCScriptable.h"
      65                 : #include "nsIServiceManager.h"
      66                 : #include "nsIComponentManager.h"
      67                 : #include "nsIComponentRegistrar.h"
      68                 : #include "nsILocalFile.h"
      69                 : #include "nsStringAPI.h"
      70                 : #include "nsIDirectoryService.h"
      71                 : #include "nsILocalFile.h"
      72                 : #include "nsDirectoryServiceDefs.h"
      73                 : #include "nsAppDirectoryServiceDefs.h"
      74                 : #include "nscore.h"
      75                 : #include "nsArrayEnumerator.h"
      76                 : #include "nsCOMArray.h"
      77                 : #include "nsDirectoryServiceUtils.h"
      78                 : #include "nsMemory.h"
      79                 : #include "nsISupportsImpl.h"
      80                 : #include "nsIJSRuntimeService.h"
      81                 : #include "nsCOMPtr.h"
      82                 : #include "nsAutoPtr.h"
      83                 : #include "nsIXPCSecurityManager.h"
      84                 : #include "nsJSPrincipals.h"
      85                 : #include "xpcpublic.h"
      86                 : #ifdef XP_MACOSX
      87                 : #include "xpcshellMacUtils.h"
      88                 : #endif
      89                 : #ifdef XP_WIN
      90                 : #include <windows.h>
      91                 : #endif
      92                 : 
      93                 : #ifdef ANDROID
      94                 : #include <android/log.h>
      95                 : #endif
      96                 : 
      97                 : #include "nsIScriptSecurityManager.h"
      98                 : #include "nsIPrincipal.h"
      99                 : 
     100                 : // all this crap is needed to do the interactive shell stuff
     101                 : #include <stdlib.h>
     102                 : #include <errno.h>
     103                 : #ifdef HAVE_IO_H
     104                 : #include <io.h>     /* for isatty() */
     105                 : #endif
     106                 : #ifdef HAVE_UNISTD_H
     107                 : #include <unistd.h>     /* for isatty() */
     108                 : #endif
     109                 : 
     110                 : #include "nsIJSContextStack.h"
     111                 : 
     112                 : #ifdef MOZ_CRASHREPORTER
     113                 : #include "nsICrashReporter.h"
     114                 : #endif
     115                 : 
     116                 : using namespace mozilla;
     117                 : 
     118                 : class XPCShellDirProvider : public nsIDirectoryServiceProvider2
     119                 : {
     120                 : public:
     121                 :     NS_DECL_ISUPPORTS_INHERITED
     122                 :     NS_DECL_NSIDIRECTORYSERVICEPROVIDER
     123                 :     NS_DECL_NSIDIRECTORYSERVICEPROVIDER2
     124                 : 
     125            1387 :     XPCShellDirProvider() { }
     126            1387 :     ~XPCShellDirProvider() { }
     127                 : 
     128                 :     bool SetGREDir(const char *dir);
     129            1387 :     void ClearGREDir() { mGREDir = nsnull; }
     130                 : 
     131                 : private:
     132                 :     nsCOMPtr<nsILocalFile> mGREDir;
     133                 : };
     134                 : 
     135                 : /***************************************************************************/
     136                 : 
     137                 : #ifdef JS_THREADSAFE
     138                 : #define DoBeginRequest(cx) JS_BeginRequest((cx))
     139                 : #define DoEndRequest(cx)   JS_EndRequest((cx))
     140                 : #else
     141                 : #define DoBeginRequest(cx) ((void)0)
     142                 : #define DoEndRequest(cx)   ((void)0)
     143                 : #endif
     144                 : 
     145                 : /***************************************************************************/
     146                 : 
     147                 : static const char kXPConnectServiceContractID[] = "@mozilla.org/js/xpc/XPConnect;1";
     148                 : 
     149                 : #define EXITCODE_RUNTIME_ERROR 3
     150                 : #define EXITCODE_FILE_NOT_FOUND 4
     151                 : 
     152                 : FILE *gOutFile = NULL;
     153                 : FILE *gErrFile = NULL;
     154                 : FILE *gInFile = NULL;
     155                 : 
     156                 : int gExitCode = 0;
     157                 : JSBool gQuitting = false;
     158                 : static JSBool reportWarnings = true;
     159                 : static JSBool compileOnly = false;
     160                 : 
     161                 : JSPrincipals *gJSPrincipals = nsnull;
     162                 : nsAutoString *gWorkingDirectory = nsnull;
     163                 : 
     164                 : static JSBool
     165               3 : GetLocationProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
     166                 : {
     167                 : #if !defined(XP_WIN) && !defined(XP_UNIX)
     168                 :     //XXX: your platform should really implement this
     169                 :     return false;
     170                 : #else
     171                 :     JSScript *script;
     172               3 :     JS_DescribeScriptedCaller(cx, &script, NULL);
     173               3 :     const char *filename = JS_GetScriptFilename(cx, script);
     174                 : 
     175               3 :     if (filename) {
     176                 :         nsresult rv;
     177                 :         nsCOMPtr<nsIXPConnect> xpc =
     178               6 :             do_GetService(kXPConnectServiceContractID, &rv);
     179                 : 
     180                 : #if defined(XP_WIN)
     181                 :         // convert from the system codepage to UTF-16
     182                 :         int bufferSize = MultiByteToWideChar(CP_ACP, 0, filename,
     183                 :                                              -1, NULL, 0);
     184                 :         nsAutoString filenameString;
     185                 :         filenameString.SetLength(bufferSize);
     186                 :         MultiByteToWideChar(CP_ACP, 0, filename,
     187                 :                             -1, (LPWSTR)filenameString.BeginWriting(),
     188                 :                             filenameString.Length());
     189                 :         // remove the null terminator
     190                 :         filenameString.SetLength(bufferSize - 1);
     191                 : 
     192                 :         // replace forward slashes with backslashes,
     193                 :         // since nsLocalFileWin chokes on them
     194                 :         PRUnichar *start, *end;
     195                 : 
     196                 :         filenameString.BeginWriting(&start, &end);
     197                 : 
     198                 :         while (start != end) {
     199                 :             if (*start == L'/')
     200                 :                 *start = L'\\';
     201                 :             start++;
     202                 :         }
     203                 : #elif defined(XP_UNIX)
     204               6 :         NS_ConvertUTF8toUTF16 filenameString(filename);
     205                 : #endif
     206                 : 
     207               6 :         nsCOMPtr<nsILocalFile> location;
     208               3 :         if (NS_SUCCEEDED(rv)) {
     209                 :             rv = NS_NewLocalFile(filenameString,
     210               3 :                                  false, getter_AddRefs(location));
     211                 :         }
     212                 : 
     213               3 :         if (!location && gWorkingDirectory) {
     214                 :             // could be a relative path, try appending it to the cwd
     215                 :             // and then normalize
     216               2 :             nsAutoString absolutePath(*gWorkingDirectory);
     217               1 :             absolutePath.Append(filenameString);
     218                 : 
     219                 :             rv = NS_NewLocalFile(absolutePath,
     220               1 :                                  false, getter_AddRefs(location));
     221                 :         }
     222                 : 
     223               3 :         if (location) {
     224               6 :             nsCOMPtr<nsIXPConnectJSObjectHolder> locationHolder;
     225               3 :             JSObject *locationObj = NULL;
     226                 : 
     227                 :             bool symlink;
     228                 :             // don't normalize symlinks, because that's kind of confusing
     229               6 :             if (NS_SUCCEEDED(location->IsSymlink(&symlink)) &&
     230               3 :                 !symlink)
     231               0 :                 location->Normalize();
     232               3 :             rv = xpc->WrapNative(cx, obj, location,
     233                 :                                  NS_GET_IID(nsILocalFile),
     234               3 :                                  getter_AddRefs(locationHolder));
     235                 : 
     236               6 :             if (NS_SUCCEEDED(rv) &&
     237               3 :                 NS_SUCCEEDED(locationHolder->GetJSObject(&locationObj))) {
     238               3 :                 *vp = OBJECT_TO_JSVAL(locationObj);
     239                 :             }
     240                 :         }
     241                 :     }
     242                 : 
     243               3 :     return true;
     244                 : #endif
     245                 : }
     246                 : 
     247                 : #ifdef EDITLINE
     248                 : extern "C" {
     249                 : extern JS_EXPORT_API(char *)   readline(const char *prompt);
     250                 : extern JS_EXPORT_API(void)     add_history(char *line);
     251                 : }
     252                 : #endif
     253                 : 
     254                 : static JSBool
     255               0 : GetLine(JSContext *cx, char *bufp, FILE *file, const char *prompt) {
     256                 : #ifdef EDITLINE
     257                 :     /*
     258                 :      * Use readline only if file is stdin, because there's no way to specify
     259                 :      * another handle.  Are other filehandles interactive?
     260                 :      */
     261                 :     if (file == stdin) {
     262                 :         char *linep = readline(prompt);
     263                 :         if (!linep)
     264                 :             return false;
     265                 :         if (*linep)
     266                 :             add_history(linep);
     267                 :         strcpy(bufp, linep);
     268                 :         JS_free(cx, linep);
     269                 :         bufp += strlen(bufp);
     270                 :         *bufp++ = '\n';
     271                 :         *bufp = '\0';
     272                 :     } else
     273                 : #endif
     274                 :     {
     275               0 :         char line[256] = { '\0' };
     276               0 :         fputs(prompt, gOutFile);
     277               0 :         fflush(gOutFile);
     278               0 :         if ((!fgets(line, sizeof line, file) && errno != EINTR) || feof(file))
     279               0 :             return false;
     280               0 :         strcpy(bufp, line);
     281                 :     }
     282               0 :     return true;
     283                 : }
     284                 : 
     285                 : static void
     286            7902 : my_ErrorReporter(JSContext *cx, const char *message, JSErrorReport *report)
     287                 : {
     288                 :     int i, j, k, n;
     289            7902 :     char *prefix = NULL, *tmp;
     290                 :     const char *ctmp;
     291            7902 :     JSStackFrame * fp = nsnull;
     292           15804 :     nsCOMPtr<nsIXPConnect> xpc;
     293                 : 
     294                 :     // Don't report an exception from inner JS frames as the callers may intend
     295                 :     // to handle it.
     296            7902 :     while ((fp = JS_FrameIterator(cx, &fp))) {
     297            7479 :         if (JS_IsScriptFrame(cx, fp)) {
     298                 :             return;
     299                 :         }
     300                 :     }
     301                 : 
     302                 :     // In some cases cx->fp is null here so use XPConnect to tell us about inner
     303                 :     // frames.
     304             426 :     if ((xpc = do_GetService(nsIXPConnect::GetCID()))) {
     305             426 :         nsAXPCNativeCallContext *cc = nsnull;
     306             426 :         xpc->GetCurrentNativeCallContext(&cc);
     307             426 :         if (cc) {
     308             421 :             nsAXPCNativeCallContext *prev = cc;
     309             842 :             while (NS_SUCCEEDED(prev->GetPreviousCallContext(&prev)) && prev) {
     310                 :                 PRUint16 lang;
     311             397 :                 if (NS_SUCCEEDED(prev->GetLanguage(&lang)) &&
     312                 :                     lang == nsAXPCNativeCallContext::LANG_JS) {
     313                 :                     return;
     314                 :                 }
     315                 :             }
     316                 :         }
     317                 :     }
     318                 : 
     319              29 :     if (!report) {
     320               0 :         fprintf(gErrFile, "%s\n", message);
     321                 :         return;
     322                 :     }
     323                 : 
     324                 :     /* Conditionally ignore reported warnings. */
     325              29 :     if (JSREPORT_IS_WARNING(report->flags) && !reportWarnings)
     326                 :         return;
     327                 : 
     328              29 :     if (report->filename)
     329               6 :         prefix = JS_smprintf("%s:", report->filename);
     330              29 :     if (report->lineno) {
     331               6 :         tmp = prefix;
     332               6 :         prefix = JS_smprintf("%s%u: ", tmp ? tmp : "", report->lineno);
     333               6 :         JS_free(cx, tmp);
     334                 :     }
     335              29 :     if (JSREPORT_IS_WARNING(report->flags)) {
     336               0 :         tmp = prefix;
     337                 :         prefix = JS_smprintf("%s%swarning: ",
     338                 :                              tmp ? tmp : "",
     339               0 :                              JSREPORT_IS_STRICT(report->flags) ? "strict " : "");
     340               0 :         JS_free(cx, tmp);
     341                 :     }
     342                 : 
     343                 :     /* embedded newlines -- argh! */
     344              58 :     while ((ctmp = strchr(message, '\n')) != 0) {
     345               0 :         ctmp++;
     346               0 :         if (prefix) fputs(prefix, gErrFile);
     347               0 :         fwrite(message, 1, ctmp - message, gErrFile);
     348               0 :         message = ctmp;
     349                 :     }
     350                 :     /* If there were no filename or lineno, the prefix might be empty */
     351              29 :     if (prefix)
     352               6 :         fputs(prefix, gErrFile);
     353              29 :     fputs(message, gErrFile);
     354                 : 
     355              29 :     if (!report->linebuf) {
     356              29 :         fputc('\n', gErrFile);
     357              29 :         goto out;
     358                 :     }
     359                 : 
     360               0 :     fprintf(gErrFile, ":\n%s%s\n%s", prefix, report->linebuf, prefix);
     361               0 :     n = report->tokenptr - report->linebuf;
     362               0 :     for (i = j = 0; i < n; i++) {
     363               0 :         if (report->linebuf[i] == '\t') {
     364               0 :             for (k = (j + 8) & ~7; j < k; j++) {
     365               0 :                 fputc('.', gErrFile);
     366                 :             }
     367               0 :             continue;
     368                 :         }
     369               0 :         fputc('.', gErrFile);
     370               0 :         j++;
     371                 :     }
     372               0 :     fputs("^\n", gErrFile);
     373                 :  out:
     374              29 :     if (!JSREPORT_IS_WARNING(report->flags))
     375              29 :         gExitCode = EXITCODE_RUNTIME_ERROR;
     376              29 :     JS_free(cx, prefix);
     377                 : }
     378                 : 
     379                 : static JSBool
     380               0 : ReadLine(JSContext *cx, unsigned argc, jsval *vp)
     381                 : {
     382                 :     // While 4096 might be quite arbitrary, this is something to be fixed in
     383                 :     // bug 105707. It is also the same limit as in ProcessFile.
     384                 :     char buf[4096];
     385                 :     JSString *str;
     386                 : 
     387                 :     /* If a prompt was specified, construct the string */
     388               0 :     if (argc > 0) {
     389               0 :         str = JS_ValueToString(cx, JS_ARGV(cx, vp)[0]);
     390               0 :         if (!str)
     391               0 :             return false;
     392                 :     } else {
     393               0 :         str = JSVAL_TO_STRING(JS_GetEmptyStringValue(cx));
     394                 :     }
     395                 : 
     396                 :     /* Get a line from the infile */
     397               0 :     JSAutoByteString strBytes(cx, str);
     398               0 :     if (!strBytes || !GetLine(cx, buf, gInFile, strBytes.ptr()))
     399               0 :         return false;
     400                 : 
     401                 :     /* Strip newline character added by GetLine() */
     402               0 :     unsigned int buflen = strlen(buf);
     403               0 :     if (buflen == 0) {
     404               0 :         if (feof(gInFile)) {
     405               0 :             JS_SET_RVAL(cx, vp, JSVAL_NULL);
     406               0 :             return true;
     407                 :         }
     408               0 :     } else if (buf[buflen - 1] == '\n') {
     409               0 :         --buflen;
     410                 :     }
     411                 : 
     412                 :     /* Turn buf into a JSString */
     413               0 :     str = JS_NewStringCopyN(cx, buf, buflen);
     414               0 :     if (!str)
     415               0 :         return false;
     416                 : 
     417               0 :     JS_SET_RVAL(cx, vp, STRING_TO_JSVAL(str));
     418               0 :     return true;
     419                 : }
     420                 : 
     421                 : static JSBool
     422           20902 : Print(JSContext *cx, unsigned argc, jsval *vp)
     423                 : {
     424                 :     unsigned i, n;
     425                 :     JSString *str;
     426                 : 
     427           20902 :     jsval *argv = JS_ARGV(cx, vp);
     428           41813 :     for (i = n = 0; i < argc; i++) {
     429           20911 :         str = JS_ValueToString(cx, argv[i]);
     430           20911 :         if (!str)
     431               0 :             return false;
     432           41822 :         JSAutoByteString strBytes(cx, str);
     433           20911 :         if (!strBytes)
     434               0 :             return false;
     435           20911 :         fprintf(gOutFile, "%s%s", i ? " " : "", strBytes.ptr());
     436           41822 :         fflush(gOutFile);
     437                 :     }
     438           20902 :     n++;
     439           20902 :     if (n)
     440           20902 :         fputc('\n', gOutFile);
     441           20902 :     JS_SET_RVAL(cx, vp, JSVAL_VOID);
     442           20902 :     return true;
     443                 : }
     444                 : 
     445                 : static JSBool
     446          235740 : Dump(JSContext *cx, unsigned argc, jsval *vp)
     447                 : {
     448          235740 :     JS_SET_RVAL(cx, vp, JSVAL_VOID);
     449                 : 
     450                 :     JSString *str;
     451          235740 :     if (!argc)
     452               0 :         return true;
     453                 : 
     454          235740 :     str = JS_ValueToString(cx, JS_ARGV(cx, vp)[0]);
     455          235740 :     if (!str)
     456               0 :         return false;
     457                 : 
     458          471480 :     JSAutoByteString bytes(cx, str);
     459          235740 :     if (!bytes)
     460               0 :         return false;
     461                 : 
     462                 : #ifdef ANDROID
     463                 :     __android_log_print(ANDROID_LOG_INFO, "Gecko", bytes.ptr());
     464                 : #endif
     465          235740 :     fputs(bytes.ptr(), gOutFile);
     466          235740 :     fflush(gOutFile);
     467          235740 :     return true;
     468                 : }
     469                 : 
     470                 : static JSBool
     471            3417 : Load(JSContext *cx, unsigned argc, jsval *vp)
     472                 : {
     473            3417 :     JSObject *obj = JS_THIS_OBJECT(cx, vp);
     474            3417 :     if (!obj)
     475               0 :         return false;
     476                 : 
     477            3417 :     jsval *argv = JS_ARGV(cx, vp);
     478            6830 :     for (unsigned i = 0; i < argc; i++) {
     479            3417 :         JSString *str = JS_ValueToString(cx, argv[i]);
     480            3417 :         if (!str)
     481               0 :             return false;
     482            3417 :         argv[i] = STRING_TO_JSVAL(str);
     483            6834 :         JSAutoByteString filename(cx, str);
     484            3417 :         if (!filename)
     485               0 :             return false;
     486            3417 :         FILE *file = fopen(filename.ptr(), "r");
     487            3417 :         if (!file) {
     488                 :             JS_ReportError(cx, "cannot open file '%s' for reading",
     489               1 :                            filename.ptr());
     490               1 :             return false;
     491                 :         }
     492            3416 :         JSScript *script = JS_CompileUTF8FileHandleForPrincipals(cx, obj, filename.ptr(),
     493            6832 :                                                                  file, gJSPrincipals);
     494            3416 :         fclose(file);
     495            3416 :         if (!script)
     496               0 :             return false;
     497                 : 
     498                 :         jsval result;
     499            3416 :         if (!compileOnly && !JS_ExecuteScript(cx, obj, script, &result))
     500               3 :             return false;
     501                 :     }
     502            3413 :     JS_SET_RVAL(cx, vp, JSVAL_VOID);
     503            3413 :     return true;
     504                 : }
     505                 : 
     506                 : static JSBool
     507               1 : Version(JSContext *cx, unsigned argc, jsval *vp)
     508                 : {
     509               1 :     if (argc > 0 && JSVAL_IS_INT(JS_ARGV(cx, vp)[0]))
     510               1 :         JS_SET_RVAL(cx, vp, INT_TO_JSVAL(JS_SetVersion(cx, JSVersion(JSVAL_TO_INT(JS_ARGV(cx, vp)[0])))));
     511                 :     else
     512               0 :         JS_SET_RVAL(cx, vp, INT_TO_JSVAL(JS_GetVersion(cx)));
     513               1 :     return true;
     514                 : }
     515                 : 
     516                 : static JSBool
     517               0 : BuildDate(JSContext *cx, unsigned argc, jsval *vp)
     518                 : {
     519               0 :     fprintf(gOutFile, "built on %s at %s\n", __DATE__, __TIME__);
     520               0 :     JS_SET_RVAL(cx, vp, JSVAL_VOID);
     521               0 :     return true;
     522                 : }
     523                 : 
     524                 : static JSBool
     525            1384 : Quit(JSContext *cx, unsigned argc, jsval *vp)
     526                 : {
     527            1384 :     gExitCode = 0;
     528            1384 :     JS_ConvertArguments(cx, argc, JS_ARGV(cx, vp),"/ i", &gExitCode);
     529                 : 
     530            1384 :     gQuitting = true;
     531                 : //    exit(0);
     532            1384 :     return false;
     533                 : }
     534                 : 
     535                 : static JSBool
     536               0 : DumpXPC(JSContext *cx, unsigned argc, jsval *vp)
     537                 : {
     538               0 :     int32_t depth = 2;
     539                 : 
     540               0 :     if (argc > 0) {
     541               0 :         if (!JS_ValueToInt32(cx, JS_ARGV(cx, vp)[0], &depth))
     542               0 :             return false;
     543                 :     }
     544                 : 
     545               0 :     nsCOMPtr<nsIXPConnect> xpc = do_GetService(nsIXPConnect::GetCID());
     546               0 :     if (xpc)
     547               0 :         xpc->DebugDump(int16_t(depth));
     548               0 :     JS_SET_RVAL(cx, vp, JSVAL_VOID);
     549               0 :     return true;
     550                 : }
     551                 : 
     552                 : static JSBool
     553            2903 : GC(JSContext *cx, unsigned argc, jsval *vp)
     554                 : {
     555            2903 :     JS_GC(cx);
     556                 : #ifdef JS_GCMETER
     557                 :     js_DumpGCStats(JS_GetRuntime(cx), stdout);
     558                 : #endif
     559            2903 :     JS_SET_RVAL(cx, vp, JSVAL_VOID);
     560            2903 :     return true;
     561                 : }
     562                 : 
     563                 : #ifdef JS_GC_ZEAL
     564                 : static JSBool
     565               8 : GCZeal(JSContext *cx, unsigned argc, jsval *vp)
     566                 : {
     567                 :     uint32_t zeal;
     568               8 :     if (!JS_ValueToECMAUint32(cx, argc ? JS_ARGV(cx, vp)[0] : JSVAL_VOID, &zeal))
     569               0 :         return false;
     570                 : 
     571               8 :     JS_SetGCZeal(cx, uint8_t(zeal), JS_DEFAULT_ZEAL_FREQ, false);
     572               8 :     JS_SET_RVAL(cx, vp, JSVAL_VOID);
     573               8 :     return true;
     574                 : }
     575                 : #endif
     576                 : 
     577                 : #ifdef DEBUG
     578                 : 
     579                 : static JSBool
     580               0 : DumpHeap(JSContext *cx, unsigned argc, jsval *vp)
     581                 : {
     582               0 :     void* startThing = NULL;
     583               0 :     JSGCTraceKind startTraceKind = JSTRACE_OBJECT;
     584               0 :     void *thingToFind = NULL;
     585               0 :     size_t maxDepth = (size_t)-1;
     586               0 :     void *thingToIgnore = NULL;
     587                 :     FILE *dumpFile;
     588                 :     JSBool ok;
     589                 : 
     590               0 :     jsval *argv = JS_ARGV(cx, vp);
     591               0 :     JS_SET_RVAL(cx, vp, JSVAL_VOID);
     592                 : 
     593               0 :     vp = argv + 0;
     594               0 :     JSAutoByteString fileName;
     595               0 :     if (argc > 0 && *vp != JSVAL_NULL && *vp != JSVAL_VOID) {
     596                 :         JSString *str;
     597                 : 
     598               0 :         str = JS_ValueToString(cx, *vp);
     599               0 :         if (!str)
     600               0 :             return false;
     601               0 :         *vp = STRING_TO_JSVAL(str);
     602               0 :         if (!fileName.encode(cx, str))
     603               0 :             return false;
     604                 :     }
     605                 : 
     606               0 :     vp = argv + 1;
     607               0 :     if (argc > 1 && *vp != JSVAL_NULL && *vp != JSVAL_VOID) {
     608               0 :         if (!JSVAL_IS_TRACEABLE(*vp))
     609               0 :             goto not_traceable_arg;
     610               0 :         startThing = JSVAL_TO_TRACEABLE(*vp);
     611               0 :         startTraceKind = JSVAL_TRACE_KIND(*vp);
     612                 :     }
     613                 : 
     614               0 :     vp = argv + 2;
     615               0 :     if (argc > 2 && *vp != JSVAL_NULL && *vp != JSVAL_VOID) {
     616               0 :         if (!JSVAL_IS_TRACEABLE(*vp))
     617               0 :             goto not_traceable_arg;
     618               0 :         thingToFind = JSVAL_TO_TRACEABLE(*vp);
     619                 :     }
     620                 : 
     621               0 :     vp = argv + 3;
     622               0 :     if (argc > 3 && *vp != JSVAL_NULL && *vp != JSVAL_VOID) {
     623                 :         uint32_t depth;
     624                 : 
     625               0 :         if (!JS_ValueToECMAUint32(cx, *vp, &depth))
     626               0 :             return false;
     627               0 :         maxDepth = depth;
     628                 :     }
     629                 : 
     630               0 :     vp = argv + 4;
     631               0 :     if (argc > 4 && *vp != JSVAL_NULL && *vp != JSVAL_VOID) {
     632               0 :         if (!JSVAL_IS_TRACEABLE(*vp))
     633               0 :             goto not_traceable_arg;
     634               0 :         thingToIgnore = JSVAL_TO_TRACEABLE(*vp);
     635                 :     }
     636                 : 
     637               0 :     if (!fileName) {
     638               0 :         dumpFile = gOutFile;
     639                 :     } else {
     640               0 :         dumpFile = fopen(fileName.ptr(), "w");
     641               0 :         if (!dumpFile) {
     642                 :             fprintf(gErrFile, "dumpHeap: can't open %s: %s\n",
     643               0 :                     fileName.ptr(), strerror(errno));
     644               0 :             return false;
     645                 :         }
     646                 :     }
     647                 : 
     648                 :     ok = JS_DumpHeap(JS_GetRuntime(cx), dumpFile, startThing, startTraceKind, thingToFind,
     649               0 :                      maxDepth, thingToIgnore);
     650               0 :     if (dumpFile != gOutFile)
     651               0 :         fclose(dumpFile);
     652               0 :     if (!ok)
     653               0 :         JS_ReportOutOfMemory(cx);
     654               0 :     return ok;
     655                 : 
     656                 :   not_traceable_arg:
     657                 :     fprintf(gErrFile,
     658                 :             "dumpHeap: argument %u is not null or a heap-allocated thing\n",
     659               0 :             (unsigned)(vp - argv));
     660               0 :     return false;
     661                 : }
     662                 : 
     663                 : #endif /* DEBUG */
     664                 : 
     665                 : static JSBool
     666               0 : Clear(JSContext *cx, unsigned argc, jsval *vp)
     667                 : {
     668               0 :     if (argc > 0 && !JSVAL_IS_PRIMITIVE(JS_ARGV(cx, vp)[0])) {
     669               0 :         JS_ClearScope(cx, JSVAL_TO_OBJECT(JS_ARGV(cx, vp)[0]));
     670                 :     } else {
     671               0 :         JS_ReportError(cx, "'clear' requires an object");
     672               0 :         return false;
     673                 :     }
     674               0 :     JS_SET_RVAL(cx, vp, JSVAL_VOID);
     675               0 :     return true;
     676                 : }
     677                 : 
     678                 : static JSBool
     679               0 : SendCommand(JSContext* cx,
     680                 :             unsigned argc,
     681                 :             jsval* vp)
     682                 : {
     683               0 :     if (argc == 0) {
     684               0 :         JS_ReportError(cx, "Function takes at least one argument!");
     685               0 :         return false;
     686                 :     }
     687                 : 
     688               0 :     jsval *argv = JS_ARGV(cx, vp);
     689               0 :     JSString* str = JS_ValueToString(cx, argv[0]);
     690               0 :     if (!str) {
     691               0 :         JS_ReportError(cx, "Could not convert argument 1 to string!");
     692               0 :         return false;
     693                 :     }
     694                 : 
     695               0 :     if (argc > 1 && JS_TypeOfValue(cx, argv[1]) != JSTYPE_FUNCTION) {
     696               0 :         JS_ReportError(cx, "Could not convert argument 2 to function!");
     697               0 :         return false;
     698                 :     }
     699                 : 
     700               0 :     if (!XRE_SendTestShellCommand(cx, str, argc > 1 ? &argv[1] : nsnull)) {
     701               0 :         JS_ReportError(cx, "Couldn't send command!");
     702               0 :         return false;
     703                 :     }
     704                 : 
     705               0 :     JS_SET_RVAL(cx, vp, JSVAL_VOID);
     706               0 :     return true;
     707                 : }
     708                 : 
     709                 : static JSBool
     710               0 : GetChildGlobalObject(JSContext* cx,
     711                 :                      unsigned,
     712                 :                      jsval* vp)
     713                 : {
     714                 :     JSObject* global;
     715               0 :     if (XRE_GetChildGlobalObject(cx, &global)) {
     716               0 :         JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(global));
     717               0 :         return true;
     718                 :     }
     719               0 :     return false;
     720                 : }
     721                 : 
     722                 : /*
     723                 :  * JSContext option name to flag map. The option names are in alphabetical
     724                 :  * order for better reporting.
     725                 :  */
     726                 : static const struct JSOption {
     727                 :     const char  *name;
     728                 :     uint32_t    flag;
     729                 : } js_options[] = {
     730                 :     {"atline",          JSOPTION_ATLINE},
     731                 :     {"relimit",         JSOPTION_RELIMIT},
     732                 :     {"strict",          JSOPTION_STRICT},
     733                 :     {"werror",          JSOPTION_WERROR},
     734                 :     {"xml",             JSOPTION_XML},
     735                 : };
     736                 : 
     737                 : static uint32_t
     738               0 : MapContextOptionNameToFlag(JSContext* cx, const char* name)
     739                 : {
     740               0 :     for (size_t i = 0; i < ArrayLength(js_options); ++i) {
     741               0 :         if (strcmp(name, js_options[i].name) == 0)
     742               0 :             return js_options[i].flag;
     743                 :     }
     744                 : 
     745                 :     char* msg = JS_sprintf_append(NULL,
     746                 :                                   "unknown option name '%s'."
     747               0 :                                   " The valid names are ", name);
     748               0 :     for (size_t i = 0; i < ArrayLength(js_options); ++i) {
     749               0 :         if (!msg)
     750               0 :             break;
     751                 :         msg = JS_sprintf_append(msg, "%s%s", js_options[i].name,
     752               0 :                                 (i + 2 < ArrayLength(js_options)
     753                 :                                  ? ", "
     754               0 :                                  : i + 2 == ArrayLength(js_options)
     755                 :                                  ? " and "
     756               0 :                                  : "."));
     757                 :     }
     758               0 :     if (!msg) {
     759               0 :         JS_ReportOutOfMemory(cx);
     760                 :     } else {
     761               0 :         JS_ReportError(cx, msg);
     762               0 :         free(msg);
     763                 :     }
     764               0 :     return 0;
     765                 : }
     766                 : 
     767                 : static JSBool
     768               0 : Options(JSContext *cx, unsigned argc, jsval *vp)
     769                 : {
     770                 :     uint32_t optset, flag;
     771                 :     JSString *str;
     772                 :     char *names;
     773                 :     JSBool found;
     774                 : 
     775               0 :     optset = 0;
     776               0 :     jsval *argv = JS_ARGV(cx, vp);
     777               0 :     for (unsigned i = 0; i < argc; i++) {
     778               0 :         str = JS_ValueToString(cx, argv[i]);
     779               0 :         if (!str)
     780               0 :             return false;
     781               0 :         argv[i] = STRING_TO_JSVAL(str);
     782               0 :         JSAutoByteString opt(cx, str);
     783               0 :         if (!opt)
     784               0 :             return false;
     785               0 :         flag = MapContextOptionNameToFlag(cx,  opt.ptr());
     786               0 :         if (!flag)
     787               0 :             return false;
     788               0 :         optset |= flag;
     789                 :     }
     790               0 :     optset = JS_ToggleOptions(cx, optset);
     791                 : 
     792               0 :     names = NULL;
     793               0 :     found = false;
     794               0 :     for (size_t i = 0; i < ArrayLength(js_options); i++) {
     795               0 :         if (js_options[i].flag & optset) {
     796               0 :             found = true;
     797                 :             names = JS_sprintf_append(names, "%s%s",
     798               0 :                                       names ? "," : "", js_options[i].name);
     799               0 :             if (!names)
     800               0 :                 break;
     801                 :         }
     802                 :     }
     803               0 :     if (!found)
     804               0 :         names = strdup("");
     805               0 :     if (!names) {
     806               0 :         JS_ReportOutOfMemory(cx);
     807               0 :         return false;
     808                 :     }
     809               0 :     str = JS_NewStringCopyZ(cx, names);
     810               0 :     free(names);
     811               0 :     if (!str)
     812               0 :         return false;
     813               0 :     JS_SET_RVAL(cx, vp, STRING_TO_JSVAL(str));
     814               0 :     return true;
     815                 : }
     816                 : 
     817                 : static JSBool
     818             133 : Parent(JSContext *cx, unsigned argc, jsval *vp)
     819                 : {
     820             133 :     if (argc != 1) {
     821               0 :         JS_ReportError(cx, "Wrong number of arguments");
     822               0 :         return false;
     823                 :     }
     824                 : 
     825             133 :     jsval v = JS_ARGV(cx, vp)[0];
     826             133 :     if (JSVAL_IS_PRIMITIVE(v)) {
     827               0 :         JS_ReportError(cx, "Only objects have parents!");
     828               0 :         return false;
     829                 :     }
     830                 : 
     831             133 :     *vp = OBJECT_TO_JSVAL(JS_GetParent(JSVAL_TO_OBJECT(v)));
     832             133 :     return true;
     833                 : }
     834                 : 
     835                 : static JSFunctionSpec glob_functions[] = {
     836                 :     {"print",           Print,          0,0},
     837                 :     {"readline",        ReadLine,       1,0},
     838                 :     {"load",            Load,           1,0},
     839                 :     {"quit",            Quit,           0,0},
     840                 :     {"version",         Version,        1,0},
     841                 :     {"build",           BuildDate,      0,0},
     842                 :     {"dumpXPC",         DumpXPC,        1,0},
     843                 :     {"dump",            Dump,           1,0},
     844                 :     {"gc",              GC,             0,0},
     845                 : #ifdef JS_GC_ZEAL
     846                 :     {"gczeal",          GCZeal,         1,0},
     847                 : #endif
     848                 :     {"clear",           Clear,          1,0},
     849                 :     {"options",         Options,        0,0},
     850                 :     JS_FN("parent",     Parent,         1,0),
     851                 : #ifdef DEBUG
     852                 :     {"dumpHeap",        DumpHeap,       5,0},
     853                 : #endif
     854                 :     {"sendCommand",     SendCommand,    1,0},
     855                 :     {"getChildGlobalObject", GetChildGlobalObject, 0,0},
     856                 :     {nsnull,nsnull,0,0}
     857                 : };
     858                 : 
     859                 : JSClass global_class = {
     860                 :     "global", 0,
     861                 :     JS_PropertyStub,  JS_PropertyStub,  JS_PropertyStub,  JS_StrictPropertyStub,
     862                 :     JS_EnumerateStub, JS_ResolveStub,   JS_ConvertStub,   nsnull
     863                 : };
     864                 : 
     865                 : static JSBool
     866               0 : env_setProperty(JSContext *cx, JSObject *obj, jsid id, JSBool strict, jsval *vp)
     867                 : {
     868                 : /* XXX porting may be easy, but these don't seem to supply setenv by default */
     869                 : #if !defined XP_OS2 && !defined SOLARIS
     870                 :     JSString *idstr, *valstr;
     871                 :     int rv;
     872                 : 
     873                 :     jsval idval;
     874               0 :     if (!JS_IdToValue(cx, id, &idval))
     875               0 :         return false;
     876                 : 
     877               0 :     idstr = JS_ValueToString(cx, idval);
     878               0 :     valstr = JS_ValueToString(cx, *vp);
     879               0 :     if (!idstr || !valstr)
     880               0 :         return false;
     881               0 :     JSAutoByteString name(cx, idstr);
     882               0 :     if (!name)
     883               0 :         return false;
     884               0 :     JSAutoByteString value(cx, valstr);
     885               0 :     if (!value)
     886               0 :         return false;
     887                 : #if defined XP_WIN || defined HPUX || defined OSF1 || defined SCO
     888                 :     {
     889                 :         char *waste = JS_smprintf("%s=%s", name.ptr(), value.ptr());
     890                 :         if (!waste) {
     891                 :             JS_ReportOutOfMemory(cx);
     892                 :             return false;
     893                 :         }
     894                 :         rv = putenv(waste);
     895                 : #ifdef XP_WIN
     896                 :         /*
     897                 :          * HPUX9 at least still has the bad old non-copying putenv.
     898                 :          *
     899                 :          * Per mail from <s.shanmuganathan@digital.com>, OSF1 also has a putenv
     900                 :          * that will crash if you pass it an auto char array (so it must place
     901                 :          * its argument directly in the char *environ[] array).
     902                 :          */
     903                 :         free(waste);
     904                 : #endif
     905                 :     }
     906                 : #else
     907               0 :     rv = setenv(name.ptr(), value.ptr(), 1);
     908                 : #endif
     909               0 :     if (rv < 0) {
     910               0 :         JS_ReportError(cx, "can't set envariable %s to %s", name.ptr(), value.ptr());
     911               0 :         return false;
     912                 :     }
     913               0 :     *vp = STRING_TO_JSVAL(valstr);
     914                 : #endif /* !defined XP_OS2 && !defined SOLARIS */
     915               0 :     return true;
     916                 : }
     917                 : 
     918                 : static JSBool
     919               0 : env_enumerate(JSContext *cx, JSObject *obj)
     920                 : {
     921                 :     static JSBool reflected;
     922                 :     char **evp, *name, *value;
     923                 :     JSString *valstr;
     924                 :     JSBool ok;
     925                 : 
     926               0 :     if (reflected)
     927               0 :         return true;
     928                 : 
     929               0 :     for (evp = (char **)JS_GetPrivate(obj); (name = *evp) != NULL; evp++) {
     930               0 :         value = strchr(name, '=');
     931               0 :         if (!value)
     932               0 :             continue;
     933               0 :         *value++ = '\0';
     934               0 :         valstr = JS_NewStringCopyZ(cx, value);
     935               0 :         if (!valstr) {
     936               0 :             ok = false;
     937                 :         } else {
     938                 :             ok = JS_DefineProperty(cx, obj, name, STRING_TO_JSVAL(valstr),
     939               0 :                                    NULL, NULL, JSPROP_ENUMERATE);
     940                 :         }
     941               0 :         value[-1] = '=';
     942               0 :         if (!ok)
     943               0 :             return false;
     944                 :     }
     945                 : 
     946               0 :     reflected = true;
     947               0 :     return true;
     948                 : }
     949                 : 
     950                 : static JSBool
     951               0 : env_resolve(JSContext *cx, JSObject *obj, jsid id, unsigned flags,
     952                 :             JSObject **objp)
     953                 : {
     954                 :     JSString *idstr, *valstr;
     955                 : 
     956               0 :     if (flags & JSRESOLVE_ASSIGNING)
     957               0 :         return true;
     958                 : 
     959                 :     jsval idval;
     960               0 :     if (!JS_IdToValue(cx, id, &idval))
     961               0 :         return false;
     962                 : 
     963               0 :     idstr = JS_ValueToString(cx, idval);
     964               0 :     if (!idstr)
     965               0 :         return false;
     966               0 :     JSAutoByteString name(cx, idstr);
     967               0 :     if (!name)
     968               0 :         return false;
     969               0 :     const char *value = getenv(name.ptr());
     970               0 :     if (value) {
     971               0 :         valstr = JS_NewStringCopyZ(cx, value);
     972               0 :         if (!valstr)
     973               0 :             return false;
     974               0 :         if (!JS_DefinePropertyById(cx, obj, id, STRING_TO_JSVAL(valstr),
     975               0 :                                    NULL, NULL, JSPROP_ENUMERATE)) {
     976               0 :             return false;
     977                 :         }
     978               0 :         *objp = obj;
     979                 :     }
     980               0 :     return true;
     981                 : }
     982                 : 
     983                 : static JSClass env_class = {
     984                 :     "environment", JSCLASS_HAS_PRIVATE | JSCLASS_NEW_RESOLVE,
     985                 :     JS_PropertyStub,  JS_PropertyStub,
     986                 :     JS_PropertyStub,  env_setProperty,
     987                 :     env_enumerate, (JSResolveOp) env_resolve,
     988                 :     JS_ConvertStub,   nsnull
     989                 : };
     990                 : 
     991                 : /***************************************************************************/
     992                 : 
     993                 : typedef enum JSShellErrNum {
     994                 : #define MSG_DEF(name, number, count, exception, format) \
     995                 :     name = number,
     996                 : #include "jsshell.msg"
     997                 : #undef MSG_DEF
     998                 :     JSShellErr_Limit
     999                 : } JSShellErrNum;
    1000                 : 
    1001                 : JSErrorFormatString jsShell_ErrorFormatString[JSShellErr_Limit] = {
    1002                 : #define MSG_DEF(name, number, count, exception, format) \
    1003                 :     { format, count } ,
    1004                 : #include "jsshell.msg"
    1005                 : #undef MSG_DEF
    1006                 : };
    1007                 : 
    1008                 : static const JSErrorFormatString *
    1009               0 : my_GetErrorMessage(void *userRef, const char *locale, const unsigned errorNumber)
    1010                 : {
    1011               0 :     if (errorNumber == 0 || errorNumber >= JSShellErr_Limit)
    1012               0 :         return NULL;
    1013                 : 
    1014               0 :     return &jsShell_ErrorFormatString[errorNumber];
    1015                 : }
    1016                 : 
    1017                 : static void
    1018            1387 : ProcessFile(JSContext *cx, JSObject *obj, const char *filename, FILE *file,
    1019                 :             JSBool forceTTY)
    1020                 : {
    1021                 :     JSScript *script;
    1022                 :     jsval result;
    1023                 :     int lineno, startline;
    1024                 :     JSBool ok, hitEOF;
    1025                 :     char *bufp, buffer[4096];
    1026                 :     JSString *str;
    1027                 : 
    1028            1387 :     if (forceTTY) {
    1029               0 :         file = stdin;
    1030                 :     } else
    1031                 : #ifdef HAVE_ISATTY
    1032            1387 :     if (!isatty(fileno(file)))
    1033                 : #endif
    1034                 :     {
    1035                 :         /*
    1036                 :          * It's not interactive - just execute it.
    1037                 :          *
    1038                 :          * Support the UNIX #! shell hack; gobble the first line if it starts
    1039                 :          * with '#'.  TODO - this isn't quite compatible with sharp variables,
    1040                 :          * as a legal js program (using sharp variables) might start with '#'.
    1041                 :          * But that would require multi-character lookahead.
    1042                 :          */
    1043            1387 :         int ch = fgetc(file);
    1044            1387 :         if (ch == '#') {
    1045               0 :             while ((ch = fgetc(file)) != EOF) {
    1046               0 :                 if (ch == '\n' || ch == '\r')
    1047               0 :                     break;
    1048                 :             }
    1049                 :         }
    1050            1387 :         ungetc(ch, file);
    1051            1387 :         DoBeginRequest(cx);
    1052                 : 
    1053                 :         script = JS_CompileUTF8FileHandleForPrincipals(cx, obj, filename, file,
    1054            1387 :                                                        gJSPrincipals);
    1055                 : 
    1056            1387 :         if (script && !compileOnly)
    1057            1387 :             (void)JS_ExecuteScript(cx, obj, script, &result);
    1058            1387 :         DoEndRequest(cx);
    1059                 : 
    1060            1387 :         return;
    1061                 :     }
    1062                 : 
    1063                 :     /* It's an interactive filehandle; drop into read-eval-print loop. */
    1064               0 :     lineno = 1;
    1065               0 :     hitEOF = false;
    1066               0 :     do {
    1067               0 :         bufp = buffer;
    1068               0 :         *bufp = '\0';
    1069                 : 
    1070                 :         /*
    1071                 :          * Accumulate lines until we get a 'compilable unit' - one that either
    1072                 :          * generates an error (before running out of source) or that compiles
    1073                 :          * cleanly.  This should be whenever we get a complete statement that
    1074                 :          * coincides with the end of a line.
    1075                 :          */
    1076               0 :         startline = lineno;
    1077               0 :         do {
    1078               0 :             if (!GetLine(cx, bufp, file, startline == lineno ? "js> " : "")) {
    1079               0 :                 hitEOF = true;
    1080               0 :                 break;
    1081                 :             }
    1082               0 :             bufp += strlen(bufp);
    1083               0 :             lineno++;
    1084               0 :         } while (!JS_BufferIsCompilableUnit(cx, false, obj, buffer, strlen(buffer)));
    1085                 : 
    1086               0 :         DoBeginRequest(cx);
    1087                 :         /* Clear any pending exception from previous failed compiles.  */
    1088               0 :         JS_ClearPendingException(cx);
    1089                 :         script = JS_CompileScriptForPrincipals(cx, obj, gJSPrincipals, buffer,
    1090               0 :                                                strlen(buffer), "typein", startline);
    1091               0 :         if (script) {
    1092                 :             JSErrorReporter older;
    1093                 : 
    1094               0 :             if (!compileOnly) {
    1095               0 :                 ok = JS_ExecuteScript(cx, obj, script, &result);
    1096               0 :                 if (ok && result != JSVAL_VOID) {
    1097                 :                     /* Suppress error reports from JS_ValueToString(). */
    1098               0 :                     older = JS_SetErrorReporter(cx, NULL);
    1099               0 :                     str = JS_ValueToString(cx, result);
    1100               0 :                     JS_SetErrorReporter(cx, older);
    1101               0 :                     JSAutoByteString bytes;
    1102               0 :                     if (str && bytes.encode(cx, str))
    1103               0 :                         fprintf(gOutFile, "%s\n", bytes.ptr());
    1104                 :                     else
    1105               0 :                         ok = false;
    1106                 :                 }
    1107                 :             }
    1108                 :         }
    1109               0 :         DoEndRequest(cx);
    1110               0 :     } while (!hitEOF && !gQuitting);
    1111                 : 
    1112               0 :     fprintf(gOutFile, "\n");
    1113                 : }
    1114                 : 
    1115                 : static void
    1116            1387 : Process(JSContext *cx, JSObject *obj, const char *filename, JSBool forceTTY)
    1117                 : {
    1118                 :     FILE *file;
    1119                 : 
    1120            1387 :     if (forceTTY || !filename || strcmp(filename, "-") == 0) {
    1121               0 :         file = stdin;
    1122                 :     } else {
    1123            1387 :         file = fopen(filename, "r");
    1124            1387 :         if (!file) {
    1125                 :             JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL,
    1126                 :                                  JSSMSG_CANT_OPEN,
    1127               0 :                                  filename, strerror(errno));
    1128               0 :             gExitCode = EXITCODE_FILE_NOT_FOUND;
    1129               0 :             return;
    1130                 :         }
    1131                 :     }
    1132                 : 
    1133            1387 :     ProcessFile(cx, obj, filename, file, forceTTY);
    1134            1387 :     if (file != stdin)
    1135            1387 :         fclose(file);
    1136                 : }
    1137                 : 
    1138                 : static int
    1139               0 : usage(void)
    1140                 : {
    1141               0 :     fprintf(gErrFile, "%s\n", JS_GetImplementationVersion());
    1142               0 :     fprintf(gErrFile, "usage: xpcshell [-g gredir] [-a appdir] [-r manifest]... [-PsSwWxCij] [-v version] [-f scriptfile] [-e script] [scriptfile] [scriptarg...]\n");
    1143               0 :     return 2;
    1144                 : }
    1145                 : 
    1146                 : extern JSClass global_class;
    1147                 : 
    1148                 : static int
    1149            1387 : ProcessArgs(JSContext *cx, JSObject *obj, char **argv, int argc)
    1150                 : {
    1151            1387 :     const char rcfilename[] = "xpcshell.js";
    1152                 :     FILE *rcfile;
    1153                 :     int i;
    1154                 :     JSObject *argsObj;
    1155            1387 :     char *filename = NULL;
    1156            1387 :     JSBool isInteractive = true;
    1157            1387 :     JSBool forceTTY = false;
    1158                 : 
    1159            1387 :     rcfile = fopen(rcfilename, "r");
    1160            1387 :     if (rcfile) {
    1161               0 :         printf("[loading '%s'...]\n", rcfilename);
    1162               0 :         ProcessFile(cx, obj, rcfilename, rcfile, false);
    1163               0 :         fclose(rcfile);
    1164                 :     }
    1165                 : 
    1166                 :     /*
    1167                 :      * Scan past all optional arguments so we can create the arguments object
    1168                 :      * before processing any -f options, which must interleave properly with
    1169                 :      * -v and -w options.  This requires two passes, and without getopt, we'll
    1170                 :      * have to keep the option logic here and in the second for loop in sync.
    1171                 :      */
    1172           16913 :     for (i = 0; i < argc; i++) {
    1173           15527 :         if (argv[i][0] != '-' || argv[i][1] == '\0') {
    1174               1 :             ++i;
    1175               1 :             break;
    1176                 :         }
    1177           15526 :         switch (argv[i][1]) {
    1178                 :           case 'v':
    1179                 :           case 'f':
    1180                 :           case 'e':
    1181           11088 :             ++i;
    1182           11088 :             break;
    1183                 :           default:;
    1184                 :         }
    1185                 :     }
    1186                 : 
    1187                 :     /*
    1188                 :      * Create arguments early and define it to root it, so it's safe from any
    1189                 :      * GC calls nested below, and so it is available to -f <file> arguments.
    1190                 :      */
    1191            1387 :     argsObj = JS_NewArrayObject(cx, 0, NULL);
    1192            1387 :     if (!argsObj)
    1193               0 :         return 1;
    1194            1387 :     if (!JS_DefineProperty(cx, obj, "arguments", OBJECT_TO_JSVAL(argsObj),
    1195            1387 :                            NULL, NULL, 0)) {
    1196               0 :         return 1;
    1197                 :     }
    1198                 : 
    1199            1388 :     for (size_t j = 0, length = argc - i; j < length; j++) {
    1200               1 :         JSString *str = JS_NewStringCopyZ(cx, argv[i++]);
    1201               1 :         if (!str)
    1202               0 :             return 1;
    1203               1 :         if (!JS_DefineElement(cx, argsObj, j, STRING_TO_JSVAL(str),
    1204               1 :                               NULL, NULL, JSPROP_ENUMERATE)) {
    1205               0 :             return 1;
    1206                 :         }
    1207                 :     }
    1208                 : 
    1209           16913 :     for (i = 0; i < argc; i++) {
    1210           15527 :         if (argv[i][0] != '-' || argv[i][1] == '\0') {
    1211               1 :             filename = argv[i++];
    1212               1 :             isInteractive = false;
    1213               1 :             break;
    1214                 :         }
    1215           15526 :         switch (argv[i][1]) {
    1216                 :         case 'v':
    1217               0 :             if (++i == argc) {
    1218               0 :                 return usage();
    1219                 :             }
    1220               0 :             JS_SetVersion(cx, JSVersion(atoi(argv[i])));
    1221               0 :             break;
    1222                 :         case 'W':
    1223               0 :             reportWarnings = false;
    1224               0 :             break;
    1225                 :         case 'w':
    1226               0 :             reportWarnings = true;
    1227               0 :             break;
    1228                 :         case 'S':
    1229               0 :             JS_ToggleOptions(cx, JSOPTION_WERROR);
    1230                 :         case 's':
    1231            1386 :             JS_ToggleOptions(cx, JSOPTION_STRICT);
    1232            1386 :             break;
    1233                 :         case 'x':
    1234               0 :             JS_ToggleOptions(cx, JSOPTION_XML);
    1235               0 :             break;
    1236                 :         case 'd':
    1237             280 :             xpc_ActivateDebugMode();
    1238             280 :             break;
    1239                 :         case 'P':
    1240               0 :             if (JS_GetClass(JS_GetPrototype(obj)) != &global_class) {
    1241                 :                 JSObject *gobj;
    1242                 : 
    1243               0 :                 if (!JS_DeepFreezeObject(cx, obj))
    1244               0 :                     return false;
    1245               0 :                 gobj = JS_NewGlobalObject(cx, &global_class);
    1246               0 :                 if (!gobj || !JS_SplicePrototype(cx, gobj, obj))
    1247               0 :                     return false;
    1248               0 :                 JS_SetParent(cx, gobj, NULL);
    1249               0 :                 JS_SetGlobalObject(cx, gobj);
    1250               0 :                 obj = gobj;
    1251                 :             }
    1252               0 :             break;
    1253                 :         case 'f':
    1254            1386 :             if (++i == argc) {
    1255               0 :                 return usage();
    1256                 :             }
    1257            1386 :             Process(cx, obj, argv[i], false);
    1258                 :             /*
    1259                 :              * XXX: js -f foo.js should interpret foo.js and then
    1260                 :              * drop into interactive mode, but that breaks test
    1261                 :              * harness. Just execute foo.js for now.
    1262                 :              */
    1263            1386 :             isInteractive = false;
    1264            1386 :             break;
    1265                 :         case 'i':
    1266               0 :             isInteractive = forceTTY = true;
    1267               0 :             break;
    1268                 :         case 'e':
    1269                 :         {
    1270                 :             jsval rval;
    1271                 : 
    1272            9702 :             if (++i == argc) {
    1273               0 :                 return usage();
    1274                 :             }
    1275                 : 
    1276            9702 :             JS_EvaluateScriptForPrincipals(cx, obj, gJSPrincipals, argv[i],
    1277           19404 :                                            strlen(argv[i]), "-e", 1, &rval);
    1278                 : 
    1279            9702 :             isInteractive = false;
    1280            9702 :             break;
    1281                 :         }
    1282                 :         case 'C':
    1283               0 :             compileOnly = true;
    1284               0 :             isInteractive = false;
    1285               0 :             break;
    1286                 :         case 'm':
    1287            1386 :             JS_ToggleOptions(cx, JSOPTION_METHODJIT);
    1288            1386 :             break;
    1289                 :         case 'n':
    1290            1386 :             JS_ToggleOptions(cx, JSOPTION_TYPE_INFERENCE);
    1291            1386 :             break;
    1292                 :         default:
    1293               0 :             return usage();
    1294                 :         }
    1295                 :     }
    1296                 : 
    1297            1387 :     if (filename || isInteractive)
    1298               1 :         Process(cx, obj, filename, forceTTY);
    1299            1387 :     return gExitCode;
    1300                 : }
    1301                 : 
    1302                 : /***************************************************************************/
    1303                 : 
    1304                 : class FullTrustSecMan
    1305                 :   : public nsIScriptSecurityManager
    1306                 : {
    1307                 : public:
    1308                 :   NS_DECL_ISUPPORTS
    1309                 :   NS_DECL_NSIXPCSECURITYMANAGER
    1310                 :   NS_DECL_NSISCRIPTSECURITYMANAGER
    1311                 : 
    1312                 :   FullTrustSecMan();
    1313                 :   virtual ~FullTrustSecMan();
    1314                 : 
    1315            1387 :   void SetSystemPrincipal(nsIPrincipal *aPrincipal) {
    1316            1387 :     mSystemPrincipal = aPrincipal;
    1317            1387 :   }
    1318                 : 
    1319                 : private:
    1320                 :   nsCOMPtr<nsIPrincipal> mSystemPrincipal;
    1321                 : };
    1322                 : 
    1323               0 : NS_INTERFACE_MAP_BEGIN(FullTrustSecMan)
    1324               0 :   NS_INTERFACE_MAP_ENTRY(nsIXPCSecurityManager)
    1325               0 :   NS_INTERFACE_MAP_ENTRY(nsIScriptSecurityManager)
    1326               0 :   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPCSecurityManager)
    1327               0 : NS_INTERFACE_MAP_END
    1328                 : 
    1329            2774 : NS_IMPL_ADDREF(FullTrustSecMan)
    1330            2774 : NS_IMPL_RELEASE(FullTrustSecMan)
    1331                 : 
    1332            1387 : FullTrustSecMan::FullTrustSecMan()
    1333                 : {
    1334            1387 :   mSystemPrincipal = nsnull;
    1335            1387 : }
    1336                 : 
    1337            2774 : FullTrustSecMan::~FullTrustSecMan()
    1338                 : {
    1339            5548 : }
    1340                 : 
    1341                 : NS_IMETHODIMP
    1342          580210 : FullTrustSecMan::CanCreateWrapper(JSContext * aJSContext, const nsIID & aIID,
    1343                 :                                   nsISupports *aObj, nsIClassInfo *aClassInfo,
    1344                 :                                   void * *aPolicy)
    1345                 : {
    1346          580210 :     return NS_OK;
    1347                 : }
    1348                 : 
    1349                 : NS_IMETHODIMP
    1350          126480 : FullTrustSecMan::CanCreateInstance(JSContext * aJSContext, const nsCID & aCID)
    1351                 : {
    1352          126480 :     return NS_OK;
    1353                 : }
    1354                 : 
    1355                 : NS_IMETHODIMP
    1356               0 : FullTrustSecMan::CanGetService(JSContext * aJSContext, const nsCID & aCID)
    1357                 : {
    1358               0 :     return NS_OK;
    1359                 : }
    1360                 : 
    1361                 : /* void CanAccess (in PRUint32 aAction, in nsIXPCNativeCallContext aCallContext, in JSContextPtr aJSContext, in JSObjectPtr aJSObject, in nsISupports aObj, in nsIClassInfo aClassInfo, in jsval aName, inout voidPtr aPolicy); */
    1362                 : NS_IMETHODIMP
    1363         5519387 : FullTrustSecMan::CanAccess(PRUint32 aAction,
    1364                 :                            nsAXPCNativeCallContext *aCallContext,
    1365                 :                            JSContext * aJSContext, JSObject * aJSObject,
    1366                 :                            nsISupports *aObj, nsIClassInfo *aClassInfo,
    1367                 :                            jsid aName, void * *aPolicy)
    1368                 : {
    1369         5519387 :     return NS_OK;
    1370                 : }
    1371                 : 
    1372                 : /* [noscript] void checkPropertyAccess (in JSContextPtr aJSContext, in JSObjectPtr aJSObject, in string aClassName, in jsid aProperty, in PRUint32 aAction); */
    1373                 : NS_IMETHODIMP
    1374               0 : FullTrustSecMan::CheckPropertyAccess(JSContext * aJSContext,
    1375                 :                                      JSObject * aJSObject,
    1376                 :                                      const char *aClassName,
    1377                 :                                      jsid aProperty, PRUint32 aAction)
    1378                 : {
    1379               0 :     return NS_OK;
    1380                 : }
    1381                 : 
    1382                 : /* [noscript] void checkLoadURIFromScript (in JSContextPtr cx, in nsIURI uri); */
    1383                 : NS_IMETHODIMP
    1384               0 : FullTrustSecMan::CheckLoadURIFromScript(JSContext * cx, nsIURI *uri)
    1385                 : {
    1386               0 :     return NS_OK;
    1387                 : }
    1388                 : 
    1389                 : /* void checkLoadURIWithPrincipal (in nsIPrincipal aPrincipal, in nsIURI uri, in unsigned long flags); */
    1390                 : NS_IMETHODIMP
    1391               0 : FullTrustSecMan::CheckLoadURIWithPrincipal(nsIPrincipal *aPrincipal,
    1392                 :                                            nsIURI *uri, PRUint32 flags)
    1393                 : {
    1394               0 :     return NS_OK;
    1395                 : }
    1396                 : 
    1397                 : /* void checkLoadURI (in nsIURI from, in nsIURI uri, in unsigned long flags); */
    1398                 : NS_IMETHODIMP
    1399               0 : FullTrustSecMan::CheckLoadURI(nsIURI *from, nsIURI *uri, PRUint32 flags)
    1400                 : {
    1401               0 :     return NS_OK;
    1402                 : }
    1403                 : 
    1404                 : /* void checkLoadURIStrWithPrincipal (in nsIPrincipal aPrincipal, in AUTF8String uri, in unsigned long flags); */
    1405                 : NS_IMETHODIMP
    1406               0 : FullTrustSecMan::CheckLoadURIStrWithPrincipal(nsIPrincipal *aPrincipal,
    1407                 :                                               const nsACString & uri,
    1408                 :                                               PRUint32 flags)
    1409                 : {
    1410               0 :     return NS_OK;
    1411                 : }
    1412                 : 
    1413                 : /* void checkLoadURIStr (in AUTF8String from, in AUTF8String uri, in unsigned long flags); */
    1414                 : NS_IMETHODIMP
    1415               0 : FullTrustSecMan::CheckLoadURIStr(const nsACString & from,
    1416                 :                                  const nsACString & uri, PRUint32 flags)
    1417                 : {
    1418               0 :     return NS_OK;
    1419                 : }
    1420                 : 
    1421                 : /* [noscript] void checkFunctionAccess (in JSContextPtr cx, in voidPtr funObj, in voidPtr targetObj); */
    1422                 : NS_IMETHODIMP
    1423               0 : FullTrustSecMan::CheckFunctionAccess(JSContext * cx, void * funObj,
    1424                 :                                      void * targetObj)
    1425                 : {
    1426               0 :     return NS_OK;
    1427                 : }
    1428                 : 
    1429                 : /* [noscript] boolean canExecuteScripts (in JSContextPtr cx, in nsIPrincipal principal); */
    1430                 : NS_IMETHODIMP
    1431               0 : FullTrustSecMan::CanExecuteScripts(JSContext * cx, nsIPrincipal *principal,
    1432                 :                                    bool *_retval)
    1433                 : {
    1434               0 :     *_retval = true;
    1435               0 :     return NS_OK;
    1436                 : }
    1437                 : 
    1438                 : /* [noscript] nsIPrincipal getSubjectPrincipal (); */
    1439                 : NS_IMETHODIMP
    1440               0 : FullTrustSecMan::GetSubjectPrincipal(nsIPrincipal **_retval)
    1441                 : {
    1442               0 :     NS_IF_ADDREF(*_retval = mSystemPrincipal);
    1443               0 :     return *_retval ? NS_OK : NS_ERROR_FAILURE;
    1444                 : }
    1445                 : 
    1446                 : /* [noscript] void pushContextPrincipal (in JSContextPtr cx, in JSStackFramePtr fp, in nsIPrincipal principal); */
    1447                 : NS_IMETHODIMP
    1448               0 : FullTrustSecMan::PushContextPrincipal(JSContext * cx, JSStackFrame * fp, nsIPrincipal *principal)
    1449                 : {
    1450               0 :     return NS_OK;
    1451                 : }
    1452                 : 
    1453                 : /* [noscript] void popContextPrincipal (in JSContextPtr cx); */
    1454                 : NS_IMETHODIMP
    1455               0 : FullTrustSecMan::PopContextPrincipal(JSContext * cx)
    1456                 : {
    1457               0 :     return NS_OK;
    1458                 : }
    1459                 : 
    1460                 : /* [noscript] nsIPrincipal getSystemPrincipal (); */
    1461                 : NS_IMETHODIMP
    1462               0 : FullTrustSecMan::GetSystemPrincipal(nsIPrincipal **_retval)
    1463                 : {
    1464               0 :     NS_IF_ADDREF(*_retval = mSystemPrincipal);
    1465               0 :     return *_retval ? NS_OK : NS_ERROR_FAILURE;
    1466                 : }
    1467                 : 
    1468                 : /* [noscript] nsIPrincipal getCertificatePrincipal (in AUTF8String aCertFingerprint, in AUTF8String aSubjectName, in AUTF8String aPrettyName, in nsISupports aCert, in nsIURI aURI); */
    1469                 : NS_IMETHODIMP
    1470               0 : FullTrustSecMan::GetCertificatePrincipal(const nsACString & aCertFingerprint,
    1471                 :                                          const nsACString & aSubjectName,
    1472                 :                                          const nsACString & aPrettyName,
    1473                 :                                          nsISupports *aCert, nsIURI *aURI,
    1474                 :                                          nsIPrincipal **_retval)
    1475                 : {
    1476               0 :     NS_IF_ADDREF(*_retval = mSystemPrincipal);
    1477               0 :     return *_retval ? NS_OK : NS_ERROR_FAILURE;
    1478                 : }
    1479                 : 
    1480                 : /* [noscript] nsIPrincipal getCodebasePrincipal (in nsIURI aURI); */
    1481                 : NS_IMETHODIMP
    1482               0 : FullTrustSecMan::GetCodebasePrincipal(nsIURI *aURI, nsIPrincipal **_retval)
    1483                 : {
    1484               0 :     NS_IF_ADDREF(*_retval = mSystemPrincipal);
    1485               0 :     return *_retval ? NS_OK : NS_ERROR_FAILURE;
    1486                 : }
    1487                 : 
    1488                 : /* [noscript] short requestCapability (in nsIPrincipal principal, in string capability); */
    1489                 : NS_IMETHODIMP
    1490               0 : FullTrustSecMan::RequestCapability(nsIPrincipal *principal,
    1491                 :                                    const char *capability, PRInt16 *_retval)
    1492                 : {
    1493               0 :     *_retval = nsIPrincipal::ENABLE_GRANTED;
    1494               0 :     return NS_OK;
    1495                 : }
    1496                 : 
    1497                 : /* boolean isCapabilityEnabled (in string capability); */
    1498                 : NS_IMETHODIMP
    1499               0 : FullTrustSecMan::IsCapabilityEnabled(const char *capability, bool *_retval)
    1500                 : {
    1501               0 :     *_retval = true;
    1502               0 :     return NS_OK;
    1503                 : }
    1504                 : 
    1505                 : /* void enableCapability (in string capability); */
    1506                 : NS_IMETHODIMP
    1507               0 : FullTrustSecMan::EnableCapability(const char *capability)
    1508                 : {
    1509               0 :     return NS_OK;;
    1510                 : }
    1511                 : 
    1512                 : /* void revertCapability (in string capability); */
    1513                 : NS_IMETHODIMP
    1514               0 : FullTrustSecMan::RevertCapability(const char *capability)
    1515                 : {
    1516               0 :     return NS_OK;
    1517                 : }
    1518                 : 
    1519                 : /* void disableCapability (in string capability); */
    1520                 : NS_IMETHODIMP
    1521               0 : FullTrustSecMan::DisableCapability(const char *capability)
    1522                 : {
    1523               0 :     return NS_OK;
    1524                 : }
    1525                 : 
    1526                 : /* void setCanEnableCapability (in AUTF8String certificateFingerprint, in string capability, in short canEnable); */
    1527                 : NS_IMETHODIMP
    1528               0 : FullTrustSecMan::SetCanEnableCapability(const nsACString & certificateFingerprint,
    1529                 :                                         const char *capability,
    1530                 :                                         PRInt16 canEnable)
    1531                 : {
    1532               0 :     return NS_OK;
    1533                 : }
    1534                 : 
    1535                 : /* [noscript] nsIPrincipal getObjectPrincipal (in JSContextPtr cx, in JSObjectPtr obj); */
    1536                 : NS_IMETHODIMP
    1537               0 : FullTrustSecMan::GetObjectPrincipal(JSContext * cx, JSObject * obj,
    1538                 :                                     nsIPrincipal **_retval)
    1539                 : {
    1540               0 :     NS_IF_ADDREF(*_retval = mSystemPrincipal);
    1541               0 :     return *_retval ? NS_OK : NS_ERROR_FAILURE;
    1542                 : }
    1543                 : 
    1544                 : /* [noscript] boolean subjectPrincipalIsSystem (); */
    1545                 : NS_IMETHODIMP
    1546               0 : FullTrustSecMan::SubjectPrincipalIsSystem(bool *_retval)
    1547                 : {
    1548               0 :     *_retval = true;
    1549               0 :     return NS_OK;
    1550                 : }
    1551                 : 
    1552                 : /* [noscript] void checkSameOrigin (in JSContextPtr aJSContext, in nsIURI aTargetURI); */
    1553                 : NS_IMETHODIMP
    1554               0 : FullTrustSecMan::CheckSameOrigin(JSContext * aJSContext, nsIURI *aTargetURI)
    1555                 : {
    1556               0 :     return NS_OK;
    1557                 : }
    1558                 : 
    1559                 : /* void checkSameOriginURI (in nsIURI aSourceURI, in nsIURI aTargetURI); */
    1560                 : NS_IMETHODIMP
    1561               0 : FullTrustSecMan::CheckSameOriginURI(nsIURI *aSourceURI, nsIURI *aTargetURI,
    1562                 :                                     bool reportError)
    1563                 : {
    1564               0 :     return NS_OK;
    1565                 : }
    1566                 : 
    1567                 : /* [noscript] nsIPrincipal getPrincipalFromContext (in JSContextPtr cx); */
    1568                 : NS_IMETHODIMP
    1569               0 : FullTrustSecMan::GetPrincipalFromContext(JSContext * cx, nsIPrincipal **_retval)
    1570                 : {
    1571               0 :     NS_IF_ADDREF(*_retval = mSystemPrincipal);
    1572               0 :     return *_retval ? NS_OK : NS_ERROR_FAILURE;
    1573                 : }
    1574                 : 
    1575                 : /* [noscript] nsIPrincipal getChannelPrincipal (in nsIChannel aChannel); */
    1576                 : NS_IMETHODIMP
    1577               0 : FullTrustSecMan::GetChannelPrincipal(nsIChannel *aChannel, nsIPrincipal **_retval)
    1578                 : {
    1579               0 :     NS_IF_ADDREF(*_retval = mSystemPrincipal);
    1580               0 :     return *_retval ? NS_OK : NS_ERROR_FAILURE;
    1581                 : }
    1582                 : 
    1583                 : /* boolean isSystemPrincipal (in nsIPrincipal aPrincipal); */
    1584                 : NS_IMETHODIMP
    1585               0 : FullTrustSecMan::IsSystemPrincipal(nsIPrincipal *aPrincipal, bool *_retval)
    1586                 : {
    1587               0 :     *_retval = aPrincipal == mSystemPrincipal;
    1588               0 :     return NS_OK;
    1589                 : }
    1590                 : 
    1591                 : NS_IMETHODIMP_(nsIPrincipal *)
    1592               0 : FullTrustSecMan::GetCxSubjectPrincipal(JSContext *cx)
    1593                 : {
    1594               0 :     return mSystemPrincipal;
    1595                 : }
    1596                 : 
    1597                 : NS_IMETHODIMP_(nsIPrincipal *)
    1598               0 : FullTrustSecMan::GetCxSubjectPrincipalAndFrame(JSContext *cx, JSStackFrame **fp)
    1599                 : {
    1600               0 :     *fp = nsnull;
    1601               0 :     return mSystemPrincipal;
    1602                 : }
    1603                 : 
    1604                 : /***************************************************************************/
    1605                 : 
    1606                 : // #define TEST_InitClassesWithNewWrappedGlobal
    1607                 : 
    1608                 : #ifdef TEST_InitClassesWithNewWrappedGlobal
    1609                 : // XXX hacky test code...
    1610                 : #include "xpctest.h"
    1611                 : 
    1612                 : class TestGlobal : public nsIXPCTestNoisy, public nsIXPCScriptable
    1613                 : {
    1614                 : public:
    1615                 :     NS_DECL_ISUPPORTS
    1616                 :     NS_DECL_NSIXPCTESTNOISY
    1617                 :     NS_DECL_NSIXPCSCRIPTABLE
    1618                 : 
    1619                 :     TestGlobal(){}
    1620                 : };
    1621                 : 
    1622                 : NS_IMPL_ISUPPORTS2(TestGlobal, nsIXPCTestNoisy, nsIXPCScriptable)
    1623                 : 
    1624                 : // The nsIXPCScriptable map declaration that will generate stubs for us...
    1625                 : #define XPC_MAP_CLASSNAME           TestGlobal
    1626                 : #define XPC_MAP_QUOTED_CLASSNAME   "TestGlobal"
    1627                 : #define XPC_MAP_FLAGS               nsIXPCScriptable::USE_JSSTUB_FOR_ADDPROPERTY |\
    1628                 :                                     nsIXPCScriptable::USE_JSSTUB_FOR_DELPROPERTY |\
    1629                 :                                     nsIXPCScriptable::USE_JSSTUB_FOR_SETPROPERTY
    1630                 : #include "xpc_map_end.h" /* This will #undef the above */
    1631                 : 
    1632                 : NS_IMETHODIMP TestGlobal::Squawk() {return NS_OK;}
    1633                 : 
    1634                 : #endif
    1635                 : 
    1636                 : // uncomment to install the test 'this' translator
    1637                 : // #define TEST_TranslateThis
    1638                 : 
    1639                 : #ifdef TEST_TranslateThis
    1640                 : 
    1641                 : #include "xpctest.h"
    1642                 : 
    1643                 : class nsXPCFunctionThisTranslator : public nsIXPCFunctionThisTranslator
    1644                 : {
    1645                 : public:
    1646                 :   NS_DECL_ISUPPORTS
    1647                 :   NS_DECL_NSIXPCFUNCTIONTHISTRANSLATOR
    1648                 : 
    1649                 :   nsXPCFunctionThisTranslator();
    1650                 :   virtual ~nsXPCFunctionThisTranslator();
    1651                 :   /* additional members */
    1652                 : };
    1653                 : 
    1654                 : /* Implementation file */
    1655                 : NS_IMPL_ISUPPORTS1(nsXPCFunctionThisTranslator, nsIXPCFunctionThisTranslator)
    1656                 : 
    1657                 : nsXPCFunctionThisTranslator::nsXPCFunctionThisTranslator()
    1658                 : {
    1659                 :   /* member initializers and constructor code */
    1660                 : }
    1661                 : 
    1662                 : nsXPCFunctionThisTranslator::~nsXPCFunctionThisTranslator()
    1663                 : {
    1664                 :   /* destructor code */
    1665                 : #ifdef DEBUG_jband
    1666                 :     printf("destroying nsXPCFunctionThisTranslator\n");
    1667                 : #endif
    1668                 : }
    1669                 : 
    1670                 : /* nsISupports TranslateThis (in nsISupports aInitialThis, in nsIInterfaceInfo aInterfaceInfo, in PRUint16 aMethodIndex, out bool aHideFirstParamFromJS, out nsIIDPtr aIIDOfResult); */
    1671                 : NS_IMETHODIMP
    1672                 : nsXPCFunctionThisTranslator::TranslateThis(nsISupports *aInitialThis,
    1673                 :                                            nsIInterfaceInfo *aInterfaceInfo,
    1674                 :                                            PRUint16 aMethodIndex,
    1675                 :                                            bool *aHideFirstParamFromJS,
    1676                 :                                            nsIID * *aIIDOfResult,
    1677                 :                                            nsISupports **_retval)
    1678                 : {
    1679                 :     NS_IF_ADDREF(aInitialThis);
    1680                 :     *_retval = aInitialThis;
    1681                 :     *aHideFirstParamFromJS = false;
    1682                 :     *aIIDOfResult = nsnull;
    1683                 :     return NS_OK;
    1684                 : }
    1685                 : 
    1686                 : #endif
    1687                 : 
    1688                 : // ContextCallback calls are chained
    1689                 : static JSContextCallback gOldJSContextCallback;
    1690                 : 
    1691                 : static JSBool
    1692           13931 : ContextCallback(JSContext *cx, unsigned contextOp)
    1693                 : {
    1694           13931 :     if (gOldJSContextCallback && !gOldJSContextCallback(cx, contextOp))
    1695               0 :         return false;
    1696                 : 
    1697           13931 :     if (contextOp == JSCONTEXT_NEW) {
    1698            6273 :         JS_SetErrorReporter(cx, my_ErrorReporter);
    1699            6273 :         JS_SetVersion(cx, JSVERSION_LATEST);
    1700                 :     }
    1701           13931 :     return true;
    1702                 : }
    1703                 : 
    1704                 : static bool
    1705            1387 : GetCurrentWorkingDirectory(nsAString& workingDirectory)
    1706                 : {
    1707                 : #if !defined(XP_WIN) && !defined(XP_UNIX)
    1708                 :     //XXX: your platform should really implement this
    1709                 :     return false;
    1710                 : #elif XP_WIN
    1711                 :     DWORD requiredLength = GetCurrentDirectoryW(0, NULL);
    1712                 :     workingDirectory.SetLength(requiredLength);
    1713                 :     GetCurrentDirectoryW(workingDirectory.Length(),
    1714                 :                          (LPWSTR)workingDirectory.BeginWriting());
    1715                 :     // we got a trailing null there
    1716                 :     workingDirectory.SetLength(requiredLength);
    1717                 :     workingDirectory.Replace(workingDirectory.Length() - 1, 1, L'\\');
    1718                 : #elif defined(XP_UNIX)
    1719            2774 :     nsCAutoString cwd;
    1720                 :     // 1024 is just a guess at a sane starting value
    1721            1387 :     size_t bufsize = 1024;
    1722            1387 :     char* result = nsnull;
    1723            4161 :     while (result == nsnull) {
    1724            1387 :         if (!cwd.SetLength(bufsize))
    1725               0 :             return false;
    1726            1387 :         result = getcwd(cwd.BeginWriting(), cwd.Length());
    1727            1387 :         if (!result) {
    1728               0 :             if (errno != ERANGE)
    1729               0 :                 return false;
    1730                 :             // need to make the buffer bigger
    1731               0 :             bufsize *= 2;
    1732                 :         }
    1733                 :     }
    1734                 :     // size back down to the actual string length
    1735            1387 :     cwd.SetLength(strlen(result) + 1);
    1736            1387 :     cwd.Replace(cwd.Length() - 1, 1, '/');
    1737            1387 :     workingDirectory = NS_ConvertUTF8toUTF16(cwd);
    1738                 : #endif
    1739            1387 :     return true;
    1740                 : }
    1741                 : 
    1742                 : static JSPrincipals *
    1743             553 : FindObjectPrincipals(JSObject *obj)
    1744                 : {
    1745             553 :     return gJSPrincipals;
    1746                 : }
    1747                 : 
    1748                 : static JSSecurityCallbacks shellSecurityCallbacks;
    1749                 : 
    1750                 : int
    1751            1387 : main(int argc, char **argv, char **envp)
    1752                 : {
    1753                 : #ifdef XP_MACOSX
    1754                 :     InitAutoreleasePool();
    1755                 : #endif
    1756                 :     JSRuntime *rt;
    1757                 :     JSContext *cx;
    1758                 :     JSObject *glob, *envobj;
    1759                 :     int result;
    1760                 :     nsresult rv;
    1761                 : 
    1762                 : #ifdef HAVE_SETBUF
    1763                 :     // unbuffer stdout so that output is in the correct order; note that stderr
    1764                 :     // is unbuffered by default
    1765            1387 :     setbuf(stdout, 0);
    1766                 : #endif
    1767                 : 
    1768                 : #ifdef XRE_HAS_DLL_BLOCKLIST
    1769                 :     XRE_SetupDllBlocklist();
    1770                 : #endif
    1771                 : 
    1772            1387 :     gErrFile = stderr;
    1773            1387 :     gOutFile = stdout;
    1774            1387 :     gInFile = stdin;
    1775                 : 
    1776            1387 :     NS_LogInit();
    1777                 : 
    1778            2774 :     nsCOMPtr<nsILocalFile> appFile;
    1779            1387 :     rv = XRE_GetBinaryPath(argv[0], getter_AddRefs(appFile));
    1780            1387 :     if (NS_FAILED(rv)) {
    1781               0 :         printf("Couldn't find application file.\n");
    1782               0 :         return 1;
    1783                 :     }
    1784            2774 :     nsCOMPtr<nsIFile> appDir;
    1785            1387 :     rv = appFile->GetParent(getter_AddRefs(appDir));
    1786            1387 :     if (NS_FAILED(rv)) {
    1787               0 :         printf("Couldn't get application directory.\n");
    1788               0 :         return 1;
    1789                 :     }
    1790                 : 
    1791            2774 :     XPCShellDirProvider dirprovider;
    1792                 : 
    1793            1387 :     if (argc > 1 && !strcmp(argv[1], "-g")) {
    1794            1386 :         if (argc < 3)
    1795               0 :             return usage();
    1796                 : 
    1797            1386 :         if (!dirprovider.SetGREDir(argv[2])) {
    1798               0 :             printf("SetGREDir failed.\n");
    1799               0 :             return 1;
    1800                 :         }
    1801            1386 :         argc -= 2;
    1802            1386 :         argv += 2;
    1803                 :     }
    1804                 : 
    1805            1387 :     if (argc > 1 && !strcmp(argv[1], "-a")) {
    1806            1386 :         if (argc < 3)
    1807               0 :             return usage();
    1808                 : 
    1809            2772 :         nsCOMPtr<nsILocalFile> dir;
    1810            1386 :         rv = XRE_GetFileFromPath(argv[2], getter_AddRefs(dir));
    1811            1386 :         if (NS_SUCCEEDED(rv)) {
    1812            1386 :             appDir = do_QueryInterface(dir, &rv);
    1813                 :         }
    1814            1386 :         if (NS_FAILED(rv)) {
    1815               0 :             printf("Couldn't use given appdir.\n");
    1816               0 :             return 1;
    1817                 :         }
    1818            1386 :         argc -= 2;
    1819            2772 :         argv += 2;
    1820                 :     }
    1821                 : 
    1822            4160 :     while (argc > 1 && !strcmp(argv[1], "-r")) {
    1823            1386 :         if (argc < 3)
    1824               0 :             return usage();
    1825                 : 
    1826            2772 :         nsCOMPtr<nsILocalFile> lf;
    1827            1386 :         rv = XRE_GetFileFromPath(argv[2], getter_AddRefs(lf));
    1828            1386 :         if (NS_FAILED(rv)) {
    1829               0 :             printf("Couldn't get manifest file.\n");
    1830               0 :             return 1;
    1831                 :         }
    1832            1386 :         XRE_AddManifestLocation(NS_COMPONENT_LOCATION, lf);
    1833                 : 
    1834            1386 :         argc -= 2;
    1835            2772 :         argv += 2;
    1836                 :     }
    1837                 : 
    1838                 :     {
    1839            1387 :         if (argc > 1 && !strcmp(argv[1], "--greomni")) {
    1840               0 :             nsCOMPtr<nsILocalFile> greOmni;
    1841               0 :             nsCOMPtr<nsILocalFile> appOmni;
    1842               0 :             XRE_GetFileFromPath(argv[2], getter_AddRefs(greOmni));
    1843               0 :             if (argc > 3 && !strcmp(argv[3], "--appomni")) {
    1844               0 :                 XRE_GetFileFromPath(argv[4], getter_AddRefs(appOmni));
    1845               0 :                 argc-=2;
    1846               0 :                 argv+=2;
    1847                 :             } else {
    1848               0 :                 appOmni = greOmni;
    1849                 :             }
    1850                 : 
    1851               0 :             XRE_InitOmnijar(greOmni, appOmni);
    1852               0 :             argc-=2;
    1853               0 :             argv+=2;
    1854                 :         }
    1855                 : 
    1856            2774 :         nsCOMPtr<nsIServiceManager> servMan;
    1857            1387 :         rv = NS_InitXPCOM2(getter_AddRefs(servMan), appDir, &dirprovider);
    1858            1387 :         if (NS_FAILED(rv)) {
    1859               0 :             printf("NS_InitXPCOM2 failed!\n");
    1860               0 :             return 1;
    1861                 :         }
    1862                 : 
    1863            2774 :         nsCOMPtr<nsIJSRuntimeService> rtsvc = do_GetService("@mozilla.org/js/xpc/RuntimeService;1");
    1864                 :         // get the JSRuntime from the runtime svc
    1865            1387 :         if (!rtsvc) {
    1866               0 :             printf("failed to get nsJSRuntimeService!\n");
    1867               0 :             return 1;
    1868                 :         }
    1869                 : 
    1870            1387 :         if (NS_FAILED(rtsvc->GetRuntime(&rt)) || !rt) {
    1871               0 :             printf("failed to get JSRuntime from nsJSRuntimeService!\n");
    1872               0 :             return 1;
    1873                 :         }
    1874                 : 
    1875            1387 :         gOldJSContextCallback = JS_SetContextCallback(rt, ContextCallback);
    1876                 : 
    1877            1387 :         cx = JS_NewContext(rt, 8192);
    1878            1387 :         if (!cx) {
    1879               0 :             printf("JS_NewContext failed!\n");
    1880               0 :             return 1;
    1881                 :         }
    1882                 : 
    1883            1387 :         xpc_LocalizeContext(cx);
    1884                 : 
    1885            2774 :         nsCOMPtr<nsIXPConnect> xpc = do_GetService(nsIXPConnect::GetCID());
    1886            1387 :         if (!xpc) {
    1887               0 :             printf("failed to get nsXPConnect service!\n");
    1888               0 :             return 1;
    1889                 :         }
    1890                 : 
    1891                 :         // Since the caps security system might set a default security manager
    1892                 :         // we will be sure that the secman on this context gives full trust.
    1893            2774 :         nsRefPtr<FullTrustSecMan> secman = new FullTrustSecMan();
    1894            1387 :         xpc->SetSecurityManagerForJSContext(cx, secman, 0xFFFF);
    1895                 : 
    1896            2774 :         nsCOMPtr<nsIPrincipal> systemprincipal;
    1897                 : 
    1898                 :         // Fetch the system principal and store it away in a global, to use for
    1899                 :         // script compilation in Load() and ProcessFile() (including interactive
    1900                 :         // eval loop)
    1901                 :         {
    1902                 : 
    1903                 :             nsCOMPtr<nsIScriptSecurityManager> securityManager =
    1904            2774 :                 do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
    1905            1387 :             if (NS_SUCCEEDED(rv) && securityManager) {
    1906            1387 :                 rv = securityManager->GetSystemPrincipal(getter_AddRefs(systemprincipal));
    1907            1387 :                 if (NS_FAILED(rv)) {
    1908               0 :                     fprintf(gErrFile, "+++ Failed to obtain SystemPrincipal from ScriptSecurityManager service.\n");
    1909                 :                 } else {
    1910                 :                     // fetch the JS principals and stick in a global
    1911            1387 :                     gJSPrincipals = nsJSPrincipals::get(systemprincipal);
    1912            1387 :                     JS_HoldPrincipals(gJSPrincipals);
    1913            1387 :                     secman->SetSystemPrincipal(systemprincipal);
    1914                 :                 }
    1915                 :             } else {
    1916               0 :                 fprintf(gErrFile, "+++ Failed to get ScriptSecurityManager service, running without principals");
    1917                 :             }
    1918                 :         }
    1919                 : 
    1920            1387 :         const JSSecurityCallbacks *scb = JS_GetSecurityCallbacks(rt);
    1921            1387 :         NS_ASSERTION(scb, "We are assuming that nsScriptSecurityManager::Init() has been run");
    1922            1387 :         shellSecurityCallbacks = *scb;
    1923            1387 :         shellSecurityCallbacks.findObjectPrincipals = FindObjectPrincipals;
    1924            1387 :         JS_SetSecurityCallbacks(rt, &shellSecurityCallbacks);
    1925                 : 
    1926                 : #ifdef TEST_TranslateThis
    1927                 :         nsCOMPtr<nsIXPCFunctionThisTranslator>
    1928                 :             translator(new nsXPCFunctionThisTranslator);
    1929                 :         xpc->SetFunctionThisTranslator(NS_GET_IID(nsITestXPCFunctionCallback), translator, nsnull);
    1930                 : #endif
    1931                 : 
    1932            2774 :         nsCOMPtr<nsIJSContextStack> cxstack = do_GetService("@mozilla.org/js/xpc/ContextStack;1");
    1933            1387 :         if (!cxstack) {
    1934               0 :             printf("failed to get the nsThreadJSContextStack service!\n");
    1935               0 :             return 1;
    1936                 :         }
    1937                 : 
    1938            1387 :         if (NS_FAILED(cxstack->Push(cx))) {
    1939               0 :             printf("failed to push the current JSContext on the nsThreadJSContextStack!\n");
    1940               0 :             return 1;
    1941                 :         }
    1942                 : 
    1943            2774 :         nsCOMPtr<nsIXPCScriptable> backstagePass;
    1944            1387 :         nsresult rv = rtsvc->GetBackstagePass(getter_AddRefs(backstagePass));
    1945            1387 :         if (NS_FAILED(rv)) {
    1946                 :             fprintf(gErrFile, "+++ Failed to get backstage pass from rtsvc: %8x\n",
    1947               0 :                     rv);
    1948               0 :             return 1;
    1949                 :         }
    1950                 : 
    1951            2774 :         nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
    1952            1387 :         rv = xpc->InitClassesWithNewWrappedGlobal(cx, backstagePass,
    1953                 :                                                   systemprincipal,
    1954                 :                                                   nsIXPConnect::
    1955                 :                                                   FLAG_SYSTEM_GLOBAL_OBJECT,
    1956            1387 :                                                   getter_AddRefs(holder));
    1957            1387 :         if (NS_FAILED(rv))
    1958               0 :             return 1;
    1959                 : 
    1960            1387 :         rv = holder->GetJSObject(&glob);
    1961            1387 :         if (NS_FAILED(rv)) {
    1962               0 :             NS_ASSERTION(glob == nsnull, "bad GetJSObject?");
    1963               0 :             return 1;
    1964                 :         }
    1965                 : 
    1966            1387 :         JS_BeginRequest(cx);
    1967                 :         {
    1968            2774 :             JSAutoEnterCompartment ac;
    1969            1387 :             if (!ac.enter(cx, glob)) {
    1970               0 :                 JS_EndRequest(cx);
    1971               0 :                 return 1;
    1972                 :             }
    1973                 : 
    1974            1387 :             if (!JS_InitReflect(cx, glob)) {
    1975               0 :                 JS_EndRequest(cx);
    1976               0 :                 return 1;
    1977                 :             }
    1978                 : 
    1979            2774 :             if (!JS_DefineFunctions(cx, glob, glob_functions) ||
    1980            1387 :                 !JS_DefineProfilingFunctions(cx, glob)) {
    1981               0 :                 JS_EndRequest(cx);
    1982               0 :                 return 1;
    1983                 :             }
    1984                 : 
    1985            1387 :             envobj = JS_DefineObject(cx, glob, "environment", &env_class, NULL, 0);
    1986            1387 :             if (!envobj) {
    1987               0 :                 JS_EndRequest(cx);
    1988               0 :                 return 1;
    1989                 :             }
    1990                 : 
    1991            1387 :             JS_SetPrivate(envobj, envp);
    1992                 : 
    1993            4161 :             nsAutoString workingDirectory;
    1994            1387 :             if (GetCurrentWorkingDirectory(workingDirectory))
    1995            1387 :                 gWorkingDirectory = &workingDirectory;
    1996                 : 
    1997                 :             JS_DefineProperty(cx, glob, "__LOCATION__", JSVAL_VOID,
    1998            1387 :                               GetLocationProperty, NULL, 0);
    1999                 : 
    2000            1387 :             argc--;
    2001            1387 :             argv++;
    2002                 : 
    2003            1387 :             result = ProcessArgs(cx, glob, argv, argc);
    2004                 : 
    2005                 : 
    2006                 : //#define TEST_CALL_ON_WRAPPED_JS_AFTER_SHUTDOWN 1
    2007                 : 
    2008                 : #ifdef TEST_CALL_ON_WRAPPED_JS_AFTER_SHUTDOWN
    2009                 :             // test of late call and release (see below)
    2010                 :             nsCOMPtr<nsIJSContextStack> bogus;
    2011                 :             xpc->WrapJS(cx, glob, NS_GET_IID(nsIJSContextStack),
    2012                 :                         (void**) getter_AddRefs(bogus));
    2013                 : #endif
    2014            1387 :             JS_DropPrincipals(rt, gJSPrincipals);
    2015            1387 :             JS_ClearScope(cx, glob);
    2016            1387 :             JS_GC(cx);
    2017                 :             JSContext *oldcx;
    2018            1387 :             cxstack->Pop(&oldcx);
    2019            1387 :             NS_ASSERTION(oldcx == cx, "JS thread context push/pop mismatch");
    2020            1387 :             cxstack = nsnull;
    2021            1387 :             JS_GC(cx);
    2022                 :         } //this scopes the JSAutoCrossCompartmentCall
    2023            1387 :         JS_EndRequest(cx);
    2024            2774 :         JS_DestroyContext(cx);
    2025                 :     } // this scopes the nsCOMPtrs
    2026                 : 
    2027            1387 :     if (!XRE_ShutdownTestShell())
    2028               0 :         NS_ERROR("problem shutting down testshell");
    2029                 : 
    2030                 : #ifdef MOZ_CRASHREPORTER
    2031                 :     // Get the crashreporter service while XPCOM is still active.
    2032                 :     // This is a special exception: it will remain usable after NS_ShutdownXPCOM().
    2033                 :     nsCOMPtr<nsICrashReporter> crashReporter =
    2034            2774 :         do_GetService("@mozilla.org/toolkit/crash-reporter;1");
    2035                 : #endif
    2036                 : 
    2037                 :     // no nsCOMPtrs are allowed to be alive when you call NS_ShutdownXPCOM
    2038            1387 :     rv = NS_ShutdownXPCOM( NULL );
    2039            1387 :     NS_ASSERTION(NS_SUCCEEDED(rv), "NS_ShutdownXPCOM failed");
    2040                 : 
    2041                 : #ifdef TEST_CALL_ON_WRAPPED_JS_AFTER_SHUTDOWN
    2042                 :     // test of late call and release (see above)
    2043                 :     JSContext* bogusCX;
    2044                 :     bogus->Peek(&bogusCX);
    2045                 :     bogus = nsnull;
    2046                 : #endif
    2047                 : 
    2048            1387 :     appDir = nsnull;
    2049            1387 :     appFile = nsnull;
    2050            1387 :     dirprovider.ClearGREDir();
    2051                 : 
    2052                 : #ifdef MOZ_CRASHREPORTER
    2053                 :     // Shut down the crashreporter service to prevent leaking some strings it holds.
    2054            1387 :     if (crashReporter) {
    2055            1387 :         crashReporter->SetEnabled(false);
    2056            1387 :         crashReporter = nsnull;
    2057                 :     }
    2058                 : #endif
    2059                 : 
    2060            1387 :     NS_LogTerm();
    2061                 : 
    2062                 : #ifdef XP_MACOSX
    2063                 :     FinishAutoreleasePool();
    2064                 : #endif
    2065                 : 
    2066            1387 :     return result;
    2067                 : }
    2068                 : 
    2069                 : bool
    2070            1386 : XPCShellDirProvider::SetGREDir(const char *dir)
    2071                 : {
    2072            1386 :     nsresult rv = XRE_GetFileFromPath(dir, getter_AddRefs(mGREDir));
    2073            1386 :     return NS_SUCCEEDED(rv);
    2074                 : }
    2075                 : 
    2076                 : NS_IMETHODIMP_(nsrefcnt)
    2077           20955 : XPCShellDirProvider::AddRef()
    2078                 : {
    2079           20955 :     return 2;
    2080                 : }
    2081                 : 
    2082                 : NS_IMETHODIMP_(nsrefcnt)
    2083           20955 : XPCShellDirProvider::Release()
    2084                 : {
    2085           20955 :     return 1;
    2086                 : }
    2087                 : 
    2088           19568 : NS_IMPL_QUERY_INTERFACE2(XPCShellDirProvider,
    2089                 :                          nsIDirectoryServiceProvider,
    2090                 :                          nsIDirectoryServiceProvider2)
    2091                 : 
    2092                 : NS_IMETHODIMP
    2093           15226 : XPCShellDirProvider::GetFile(const char *prop, bool *persistent,
    2094                 :                              nsIFile* *result)
    2095                 : {
    2096           15226 :     if (mGREDir && !strcmp(prop, NS_GRE_DIR)) {
    2097            1386 :         *persistent = true;
    2098            1386 :         return mGREDir->Clone(result);
    2099           13840 :     } else if (mGREDir && !strcmp(prop, NS_APP_PREF_DEFAULTS_50_DIR)) {
    2100            2772 :         nsCOMPtr<nsIFile> file;
    2101            1386 :         *persistent = true;
    2102            8316 :         if (NS_FAILED(mGREDir->Clone(getter_AddRefs(file))) ||
    2103            4158 :             NS_FAILED(file->AppendNative(NS_LITERAL_CSTRING("defaults"))) ||
    2104            4158 :             NS_FAILED(file->AppendNative(NS_LITERAL_CSTRING("pref"))))
    2105               0 :             return NS_ERROR_FAILURE;
    2106            1386 :         NS_ADDREF(*result = file);
    2107            1386 :         return NS_OK;
    2108                 :     }
    2109                 : 
    2110           12454 :     return NS_ERROR_FAILURE;
    2111                 : }
    2112                 : 
    2113                 : NS_IMETHODIMP
    2114            2955 : XPCShellDirProvider::GetFiles(const char *prop, nsISimpleEnumerator* *result)
    2115                 : {
    2116            2955 :     if (mGREDir && !strcmp(prop, "ChromeML")) {
    2117               0 :         nsCOMArray<nsIFile> dirs;
    2118                 : 
    2119               0 :         nsCOMPtr<nsIFile> file;
    2120               0 :         mGREDir->Clone(getter_AddRefs(file));
    2121               0 :         file->AppendNative(NS_LITERAL_CSTRING("chrome"));
    2122               0 :         dirs.AppendObject(file);
    2123                 : 
    2124                 :         nsresult rv = NS_GetSpecialDirectory(NS_APP_CHROME_DIR,
    2125               0 :                                              getter_AddRefs(file));
    2126               0 :         if (NS_SUCCEEDED(rv))
    2127               0 :             dirs.AppendObject(file);
    2128                 : 
    2129               0 :         return NS_NewArrayEnumerator(result, dirs);
    2130            2955 :     } else if (!strcmp(prop, NS_APP_PREFS_DEFAULTS_DIR_LIST)) {
    2131            2778 :         nsCOMArray<nsIFile> dirs;
    2132                 : 
    2133            2778 :         nsCOMPtr<nsIFile> file;
    2134            8334 :         if (NS_FAILED(NS_GetSpecialDirectory(NS_XPCOM_CURRENT_PROCESS_DIR,
    2135                 :                                              getter_AddRefs(file))) ||
    2136            4167 :             NS_FAILED(file->AppendNative(NS_LITERAL_CSTRING("defaults"))) ||
    2137            4167 :             NS_FAILED(file->AppendNative(NS_LITERAL_CSTRING("preferences"))))
    2138               0 :             return NS_ERROR_FAILURE;
    2139                 : 
    2140            1389 :         dirs.AppendObject(file);
    2141            1389 :         return NS_NewArrayEnumerator(result, dirs);
    2142                 :     }
    2143            1566 :     return NS_ERROR_FAILURE;
    2144                 : }

Generated by: LCOV version 1.7