LCOV - code coverage report
Current view: directory - dom/workers - WorkerScope.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 346 6 1.7 %
Date: 2012-06-02 Functions: 42 2 4.8 %

       1                 : /* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
       2                 : /* vim: set ts=2 et sw=2 tw=80: */
       3                 : /* ***** BEGIN LICENSE BLOCK *****
       4                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       5                 :  *
       6                 :  * The contents of this file are subject to the Mozilla Public License Version
       7                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       8                 :  * the License. You may obtain a copy of the License at
       9                 :  * http://www.mozilla.org/MPL/
      10                 :  *
      11                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      12                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      13                 :  * for the specific language governing rights and limitations under the
      14                 :  * License.
      15                 :  *
      16                 :  * The Original Code is Web Workers.
      17                 :  *
      18                 :  * The Initial Developer of the Original Code is
      19                 :  *   The Mozilla Foundation.
      20                 :  * Portions created by the Initial Developer are Copyright (C) 2011
      21                 :  * the Initial Developer. All Rights Reserved.
      22                 :  *
      23                 :  * Contributor(s):
      24                 :  *   Ben Turner <bent.mozilla@gmail.com> (Original Author)
      25                 :  *
      26                 :  * Alternatively, the contents of this file may be used under the terms of
      27                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
      28                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      29                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      30                 :  * of those above. If you wish to allow use of your version of this file only
      31                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      32                 :  * use your version of this file under the terms of the MPL, indicate your
      33                 :  * decision by deleting the provisions above and replace them with the notice
      34                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      35                 :  * the provisions above, a recipient may use your version of this file under
      36                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      37                 :  *
      38                 :  * ***** END LICENSE BLOCK ***** */
      39                 : 
      40                 : #include "mozilla/Util.h"
      41                 : 
      42                 : #include "WorkerScope.h"
      43                 : 
      44                 : #include "jsapi.h"
      45                 : #include "jsdbgapi.h"
      46                 : 
      47                 : #include "nsTraceRefcnt.h"
      48                 : #include "xpcpublic.h"
      49                 : 
      50                 : #include "ChromeWorkerScope.h"
      51                 : #include "Events.h"
      52                 : #include "EventTarget.h"
      53                 : #include "Exceptions.h"
      54                 : #include "File.h"
      55                 : #include "FileReaderSync.h"
      56                 : #include "ListenerManager.h"
      57                 : #include "Location.h"
      58                 : #include "Navigator.h"
      59                 : #include "Principal.h"
      60                 : #include "ScriptLoader.h"
      61                 : #include "Worker.h"
      62                 : #include "WorkerPrivate.h"
      63                 : #include "XMLHttpRequest.h"
      64                 : #ifdef ANDROID
      65                 : #include <android/log.h>
      66                 : #endif
      67                 : 
      68                 : #include "WorkerInlines.h"
      69                 : 
      70                 : #define PROPERTY_FLAGS \
      71                 :   (JSPROP_ENUMERATE | JSPROP_SHARED)
      72                 : 
      73                 : #define FUNCTION_FLAGS \
      74                 :   JSPROP_ENUMERATE
      75                 : 
      76                 : using namespace mozilla;
      77                 : USING_WORKERS_NAMESPACE
      78                 : 
      79                 : namespace {
      80                 : 
      81                 : class WorkerGlobalScope : public events::EventTarget
      82                 : {
      83                 :   static JSClass sClass;
      84                 :   static JSPropertySpec sProperties[];
      85                 :   static JSFunctionSpec sFunctions[];
      86                 : 
      87                 :   enum
      88                 :   {
      89                 :     SLOT_wrappedScope = 0,
      90                 :     SLOT_wrappedFunction
      91                 :   };
      92                 : 
      93                 :   enum
      94                 :   {
      95                 :     SLOT_location = 0,
      96                 :     SLOT_navigator,
      97                 : 
      98                 :     SLOT_COUNT
      99                 :   };
     100                 : 
     101                 :   // Must be traced!
     102                 :   jsval mSlots[SLOT_COUNT];
     103                 : 
     104                 :   enum
     105                 :   {
     106                 :     STRING_onerror = 0,
     107                 :     STRING_onclose,
     108                 : 
     109                 :     STRING_COUNT
     110                 :   };
     111                 : 
     112                 :   static const char* const sEventStrings[STRING_COUNT];
     113                 : 
     114                 : protected:
     115                 :   WorkerPrivate* mWorker;
     116                 : 
     117                 : public:
     118                 :   static JSClass*
     119               0 :   Class()
     120                 :   {
     121               0 :     return &sClass;
     122                 :   }
     123                 : 
     124                 :   static JSObject*
     125               0 :   InitClass(JSContext* aCx, JSObject* aObj, JSObject* aParentProto)
     126                 :   {
     127                 :     return JS_InitClass(aCx, aObj, aParentProto, &sClass, Construct, 0,
     128               0 :                         sProperties, sFunctions, NULL, NULL);
     129                 :   }
     130                 : 
     131                 : protected:
     132               0 :   WorkerGlobalScope(WorkerPrivate* aWorker)
     133               0 :   : mWorker(aWorker)
     134                 :   {
     135               0 :     MOZ_COUNT_CTOR(mozilla::dom::workers::WorkerGlobalScope);
     136               0 :     for (int32 i = 0; i < SLOT_COUNT; i++) {
     137               0 :       mSlots[i] = JSVAL_VOID;
     138                 :     }
     139               0 :   }
     140                 : 
     141               0 :   ~WorkerGlobalScope()
     142               0 :   {
     143               0 :     MOZ_COUNT_DTOR(mozilla::dom::workers::WorkerGlobalScope);
     144               0 :   }
     145                 : 
     146                 :   void
     147               0 :   TraceInstance(JSTracer* aTrc)
     148                 :   {
     149               0 :     for (int32 i = 0; i < SLOT_COUNT; i++) {
     150               0 :       JS_CALL_VALUE_TRACER(aTrc, mSlots[i], "WorkerGlobalScope instance slot");
     151                 :     }
     152               0 :     mWorker->TraceInternal(aTrc);
     153               0 :     events::EventTarget::TraceInstance(aTrc);
     154               0 :   }
     155                 : 
     156                 :   void
     157               0 :   FinalizeInstance(JSContext* aCx)
     158                 :   {
     159               0 :     events::EventTarget::FinalizeInstance(aCx);
     160               0 :   }
     161                 : 
     162                 : private:
     163                 :   static JSBool
     164               0 :   GetEventListener(JSContext* aCx, JSObject* aObj, jsid aIdval, jsval* aVp)
     165                 :   {
     166               0 :     JS_ASSERT(JSID_IS_INT(aIdval));
     167               0 :     JS_ASSERT(JSID_TO_INT(aIdval) >= 0 && JSID_TO_INT(aIdval) < STRING_COUNT);
     168                 : 
     169               0 :     const char* name = sEventStrings[JSID_TO_INT(aIdval)];
     170               0 :     WorkerGlobalScope* scope = GetInstancePrivate(aCx, aObj, name);
     171               0 :     if (!scope) {
     172               0 :       return false;
     173                 :     }
     174                 : 
     175               0 :     return scope->GetEventListenerOnEventTarget(aCx, name + 2, aVp);
     176                 :   }
     177                 : 
     178                 :   static JSBool
     179               0 :   SetEventListener(JSContext* aCx, JSObject* aObj, jsid aIdval, JSBool aStrict,
     180                 :                    jsval* aVp)
     181                 :   {
     182               0 :     JS_ASSERT(JSID_IS_INT(aIdval));
     183               0 :     JS_ASSERT(JSID_TO_INT(aIdval) >= 0 && JSID_TO_INT(aIdval) < STRING_COUNT);
     184                 : 
     185               0 :     const char* name = sEventStrings[JSID_TO_INT(aIdval)];
     186               0 :     WorkerGlobalScope* scope = GetInstancePrivate(aCx, aObj, name);
     187               0 :     if (!scope) {
     188               0 :       return false;
     189                 :     }
     190                 : 
     191               0 :     return scope->SetEventListenerOnEventTarget(aCx, name + 2, aVp);
     192                 :   }
     193                 : 
     194                 :   static WorkerGlobalScope*
     195                 :   GetInstancePrivate(JSContext* aCx, JSObject* aObj, const char* aFunctionName);
     196                 : 
     197                 :   static JSBool
     198               0 :   Construct(JSContext* aCx, unsigned aArgc, jsval* aVp)
     199                 :   {
     200                 :     JS_ReportErrorNumber(aCx, js_GetErrorMessage, NULL, JSMSG_WRONG_CONSTRUCTOR,
     201               0 :                          sClass.name);
     202               0 :     return false;
     203                 :   }
     204                 : 
     205                 :   static JSBool
     206               0 :   GetSelf(JSContext* aCx, JSObject* aObj, jsid aIdval, jsval* aVp)
     207                 :   {
     208               0 :     if (!GetInstancePrivate(aCx, aObj, "self")) {
     209               0 :       return false;
     210                 :     }
     211                 : 
     212               0 :     *aVp = OBJECT_TO_JSVAL(aObj);
     213               0 :     return true;
     214                 :   }
     215                 : 
     216                 :   static JSBool
     217               0 :   GetLocation(JSContext* aCx, JSObject* aObj, jsid aIdval, jsval* aVp)
     218                 :   {
     219                 :     WorkerGlobalScope* scope =
     220               0 :       GetInstancePrivate(aCx, aObj, sProperties[SLOT_location].name);
     221               0 :     if (!scope) {
     222               0 :       return false;
     223                 :     }
     224                 : 
     225               0 :     if (JSVAL_IS_VOID(scope->mSlots[SLOT_location])) {
     226                 :       JSString* href, *protocol, *host, *hostname;
     227                 :       JSString* port, *pathname, *search, *hash;
     228                 : 
     229               0 :       WorkerPrivate::LocationInfo& info = scope->mWorker->GetLocationInfo();
     230                 : 
     231                 : #define COPY_STRING(_jsstr, _cstr)                                             \
     232                 :   if (info. _cstr .IsEmpty()) {                                                \
     233                 :     _jsstr = NULL;                                                             \
     234                 :   }                                                                            \
     235                 :   else {                                                                       \
     236                 :     if (!(_jsstr = JS_NewStringCopyN(aCx, info. _cstr .get(),                  \
     237                 :                                      info. _cstr .Length()))) {                \
     238                 :       return false;                                                            \
     239                 :     }                                                                          \
     240                 :     info. _cstr .Truncate();                                                   \
     241                 :   }
     242                 : 
     243               0 :       COPY_STRING(href, mHref);
     244               0 :       COPY_STRING(protocol, mProtocol);
     245               0 :       COPY_STRING(host, mHost);
     246               0 :       COPY_STRING(hostname, mHostname);
     247               0 :       COPY_STRING(port, mPort);
     248               0 :       COPY_STRING(pathname, mPathname);
     249               0 :       COPY_STRING(search, mSearch);
     250               0 :       COPY_STRING(hash, mHash);
     251                 : 
     252                 : #undef COPY_STRING
     253                 : 
     254                 :       JSObject* location = location::Create(aCx, href, protocol, host, hostname,
     255               0 :                                             port, pathname, search, hash);
     256               0 :       if (!location) {
     257               0 :         return false;
     258                 :       }
     259                 : 
     260               0 :       scope->mSlots[SLOT_location] = OBJECT_TO_JSVAL(location);
     261                 :     }
     262                 : 
     263               0 :     *aVp = scope->mSlots[SLOT_location];
     264               0 :     return true;
     265                 :   }
     266                 : 
     267                 :   static JSBool
     268               0 :   UnwrapErrorEvent(JSContext* aCx, unsigned aArgc, jsval* aVp)
     269                 :   {
     270               0 :     JS_ASSERT(JSVAL_IS_OBJECT(JS_CALLEE(aCx, aVp)));
     271               0 :     JS_ASSERT(aArgc == 1);
     272               0 :     JS_ASSERT(JSVAL_IS_OBJECT(JS_ARGV(aCx, aVp)[0]));
     273                 : 
     274               0 :     JSObject* wrapper = JSVAL_TO_OBJECT(JS_CALLEE(aCx, aVp));
     275               0 :     JS_ASSERT(JS_ObjectIsFunction(aCx, wrapper));
     276                 : 
     277               0 :     jsval scope = js::GetFunctionNativeReserved(wrapper, SLOT_wrappedScope);
     278               0 :     jsval listener = js::GetFunctionNativeReserved(wrapper, SLOT_wrappedFunction);
     279                 : 
     280               0 :     JS_ASSERT(JSVAL_IS_OBJECT(scope));
     281                 : 
     282               0 :     JSObject* event = JSVAL_TO_OBJECT(JS_ARGV(aCx, aVp)[0]);
     283                 : 
     284               0 :     jsval argv[3] = { JSVAL_VOID, JSVAL_VOID, JSVAL_VOID };
     285               0 :     if (!JS_GetProperty(aCx, event, "message", &argv[0]) ||
     286               0 :         !JS_GetProperty(aCx, event, "filename", &argv[1]) ||
     287               0 :         !JS_GetProperty(aCx, event, "lineno", &argv[2])) {
     288               0 :       return false;
     289                 :     }
     290                 : 
     291               0 :     jsval rval = JSVAL_VOID;
     292               0 :     if (!JS_CallFunctionValue(aCx, JSVAL_TO_OBJECT(scope), listener,
     293               0 :                               ArrayLength(argv), argv, &rval)) {
     294               0 :       JS_ReportPendingException(aCx);
     295               0 :       return false;
     296                 :     }
     297                 : 
     298               0 :     if (JSVAL_IS_BOOLEAN(rval) && JSVAL_TO_BOOLEAN(rval) &&
     299               0 :         !JS_CallFunctionName(aCx, event, "preventDefault", 0, NULL, &rval)) {
     300               0 :       return false;
     301                 :     }
     302                 : 
     303               0 :     return true;
     304                 :   }
     305                 : 
     306                 :   static JSBool
     307               0 :   GetOnErrorListener(JSContext* aCx, JSObject* aObj, jsid aIdval, jsval* aVp)
     308                 :   {
     309               0 :     const char* name = sEventStrings[STRING_onerror];
     310               0 :     WorkerGlobalScope* scope = GetInstancePrivate(aCx, aObj, name);
     311               0 :     if (!scope) {
     312               0 :       return false;
     313                 :     }
     314                 : 
     315                 :     jsval adaptor;
     316               0 :     if (!scope->GetEventListenerOnEventTarget(aCx, name + 2, &adaptor)) {
     317               0 :       return false;
     318                 :     }
     319                 : 
     320               0 :     if (JSVAL_IS_VOID(adaptor)) {
     321               0 :       *aVp = JSVAL_NULL;
     322               0 :       return true;
     323                 :     }
     324                 : 
     325               0 :     JS_ASSERT(JSVAL_IS_OBJECT(adaptor));
     326                 : 
     327                 :     jsval listener = js::GetFunctionNativeReserved(JSVAL_TO_OBJECT(adaptor),
     328               0 :                                                    SLOT_wrappedFunction);
     329                 : 
     330               0 :     *aVp = listener;
     331               0 :     return true;
     332                 :   }
     333                 : 
     334                 :   static JSBool
     335               0 :   SetOnErrorListener(JSContext* aCx, JSObject* aObj, jsid aIdval,
     336                 :                      JSBool aStrict, jsval* aVp)
     337                 :   {
     338               0 :     const char* name = sEventStrings[STRING_onerror];
     339               0 :     WorkerGlobalScope* scope = GetInstancePrivate(aCx, aObj, name);
     340               0 :     if (!scope) {
     341               0 :       return false;
     342                 :     }
     343                 : 
     344                 :     JSFunction* adaptor = js::NewFunctionWithReserved(aCx, UnwrapErrorEvent, 1, 0,
     345               0 :                                                       JS_GetGlobalObject(aCx), "unwrap");
     346               0 :     if (!adaptor) {
     347               0 :       return false;
     348                 :     }
     349                 : 
     350               0 :     JSObject* listener = JS_GetFunctionObject(adaptor);
     351               0 :     if (!listener) {
     352               0 :       return false;
     353                 :     }
     354                 : 
     355                 :     js::SetFunctionNativeReserved(listener, SLOT_wrappedScope,
     356               0 :                                   OBJECT_TO_JSVAL(aObj));
     357               0 :     js::SetFunctionNativeReserved(listener, SLOT_wrappedFunction, *aVp);
     358                 : 
     359               0 :     jsval val = OBJECT_TO_JSVAL(listener);
     360               0 :     return scope->SetEventListenerOnEventTarget(aCx, name + 2, &val);
     361                 :   }
     362                 : 
     363                 :   static JSBool
     364               0 :   GetNavigator(JSContext* aCx, JSObject* aObj, jsid aIdval, jsval* aVp)
     365                 :   {
     366                 :     WorkerGlobalScope* scope =
     367               0 :       GetInstancePrivate(aCx, aObj, sProperties[SLOT_navigator].name);
     368               0 :     if (!scope) {
     369               0 :       return false;
     370                 :     }
     371                 : 
     372               0 :     if (JSVAL_IS_VOID(scope->mSlots[SLOT_navigator])) {
     373               0 :       JSObject* navigator = navigator::Create(aCx);
     374               0 :       if (!navigator) {
     375               0 :         return false;
     376                 :       }
     377                 : 
     378               0 :       scope->mSlots[SLOT_navigator] = OBJECT_TO_JSVAL(navigator);
     379                 :     }
     380                 : 
     381               0 :     *aVp = scope->mSlots[SLOT_navigator];
     382               0 :     return true;
     383                 :   }
     384                 : 
     385                 :   static JSBool
     386               0 :   Close(JSContext* aCx, unsigned aArgc, jsval* aVp)
     387                 :   {
     388               0 :     JSObject* obj = JS_THIS_OBJECT(aCx, aVp);
     389               0 :     if (!obj) {
     390               0 :       return false;
     391                 :     }
     392                 : 
     393               0 :     WorkerGlobalScope* scope = GetInstancePrivate(aCx, obj, sFunctions[0].name);
     394               0 :     if (!scope) {
     395               0 :       return false;
     396                 :     }
     397                 : 
     398               0 :     return scope->mWorker->CloseInternal(aCx);
     399                 :   }
     400                 : 
     401                 :   static JSBool
     402               0 :   ImportScripts(JSContext* aCx, unsigned aArgc, jsval* aVp)
     403                 :   {
     404               0 :     JSObject* obj = JS_THIS_OBJECT(aCx, aVp);
     405               0 :     if (!obj) {
     406               0 :       return false;
     407                 :     }
     408                 : 
     409               0 :     WorkerGlobalScope* scope = GetInstancePrivate(aCx, obj, sFunctions[1].name);
     410               0 :     if (!scope) {
     411               0 :       return false;
     412                 :     }
     413                 : 
     414               0 :     if (aArgc && !scriptloader::Load(aCx, aArgc, JS_ARGV(aCx, aVp))) {
     415               0 :       return false;
     416                 :     }
     417                 : 
     418               0 :     return true;
     419                 :   }
     420                 : 
     421                 :   static JSBool
     422               0 :   SetTimeout(JSContext* aCx, unsigned aArgc, jsval* aVp)
     423                 :   {
     424               0 :     JSObject* obj = JS_THIS_OBJECT(aCx, aVp);
     425               0 :     if (!obj) {
     426               0 :       return false;
     427                 :     }
     428                 : 
     429               0 :     WorkerGlobalScope* scope = GetInstancePrivate(aCx, obj, sFunctions[2].name);
     430               0 :     if (!scope) {
     431               0 :       return false;
     432                 :     }
     433                 : 
     434                 :     jsval dummy;
     435               0 :     if (!JS_ConvertArguments(aCx, aArgc, JS_ARGV(aCx, aVp), "v", &dummy)) {
     436               0 :       return false;
     437                 :     }
     438                 : 
     439               0 :     return scope->mWorker->SetTimeout(aCx, aArgc, aVp, false);
     440                 :   }
     441                 : 
     442                 :   static JSBool
     443               0 :   ClearTimeout(JSContext* aCx, unsigned aArgc, jsval* aVp)
     444                 :   {
     445               0 :     JSObject* obj = JS_THIS_OBJECT(aCx, aVp);
     446               0 :     if (!obj) {
     447               0 :       return false;
     448                 :     }
     449                 : 
     450               0 :     WorkerGlobalScope* scope = GetInstancePrivate(aCx, obj, sFunctions[3].name);
     451               0 :     if (!scope) {
     452               0 :       return false;
     453                 :     }
     454                 : 
     455                 :     uint32_t id;
     456               0 :     if (!JS_ConvertArguments(aCx, aArgc, JS_ARGV(aCx, aVp), "u", &id)) {
     457               0 :       return false;
     458                 :     }
     459                 : 
     460               0 :     return scope->mWorker->ClearTimeout(aCx, id);
     461                 :   }
     462                 : 
     463                 :   static JSBool
     464               0 :   SetInterval(JSContext* aCx, unsigned aArgc, jsval* aVp)
     465                 :   {
     466               0 :     JSObject* obj = JS_THIS_OBJECT(aCx, aVp);
     467               0 :     if (!obj) {
     468               0 :       return false;
     469                 :     }
     470                 : 
     471               0 :     WorkerGlobalScope* scope = GetInstancePrivate(aCx, obj, sFunctions[4].name);
     472               0 :     if (!scope) {
     473               0 :       return false;
     474                 :     }
     475                 : 
     476                 :     jsval dummy;
     477               0 :     if (!JS_ConvertArguments(aCx, aArgc, JS_ARGV(aCx, aVp), "v", &dummy)) {
     478               0 :       return false;
     479                 :     }
     480                 : 
     481               0 :     return scope->mWorker->SetTimeout(aCx, aArgc, aVp, true);
     482                 :   }
     483                 : 
     484                 :   static JSBool
     485                 :   ClearInterval(JSContext* aCx, unsigned aArgc, jsval* aVp)
     486                 :   {
     487                 :     JSObject* obj = JS_THIS_OBJECT(aCx, aVp);
     488                 :     if (!obj) {
     489                 :       return false;
     490                 :     }
     491                 : 
     492                 :     WorkerGlobalScope* scope = GetInstancePrivate(aCx, obj, sFunctions[5].name);
     493                 :     if (!scope) {
     494                 :       return false;
     495                 :     }
     496                 : 
     497                 :     uint32_t id;
     498                 :     if (!JS_ConvertArguments(aCx, aArgc, JS_ARGV(aCx, aVp), "u", &id)) {
     499                 :       return false;
     500                 :     }
     501                 : 
     502                 :     return scope->mWorker->ClearTimeout(aCx, id);
     503                 :   }
     504                 : 
     505                 :   static JSBool
     506               0 :   Dump(JSContext* aCx, unsigned aArgc, jsval* aVp)
     507                 :   {
     508               0 :     JSObject* obj = JS_THIS_OBJECT(aCx, aVp);
     509               0 :     if (!obj) {
     510               0 :       return false;
     511                 :     }
     512                 : 
     513               0 :     if (!GetInstancePrivate(aCx, obj, sFunctions[6].name)) {
     514               0 :       return false;
     515                 :     }
     516                 : 
     517               0 :     if (aArgc) {
     518               0 :       JSString* str = JS_ValueToString(aCx, JS_ARGV(aCx, aVp)[0]);
     519               0 :       if (!str) {
     520               0 :         return false;
     521                 :       }
     522                 : 
     523               0 :       JSAutoByteString buffer(aCx, str);
     524               0 :       if (!buffer) {
     525               0 :         return false;
     526                 :       }
     527                 : 
     528                 : #ifdef ANDROID
     529                 :       __android_log_print(ANDROID_LOG_INFO, "Gecko", buffer.ptr());
     530                 : #endif
     531               0 :       fputs(buffer.ptr(), stdout);
     532               0 :       fflush(stdout);
     533                 :     }
     534                 : 
     535               0 :     return true;
     536                 :   }
     537                 : 
     538                 :   static JSBool
     539               0 :   AtoB(JSContext* aCx, unsigned aArgc, jsval* aVp)
     540                 :   {
     541               0 :     JSObject* obj = JS_THIS_OBJECT(aCx, aVp);
     542               0 :     if (!obj) {
     543               0 :       return false;
     544                 :     }
     545                 : 
     546               0 :     if (!GetInstancePrivate(aCx, obj, sFunctions[7].name)) {
     547               0 :       return false;
     548                 :     }
     549                 : 
     550                 :     jsval string;
     551               0 :     if (!JS_ConvertArguments(aCx, aArgc, JS_ARGV(aCx, aVp), "v", &string)) {
     552               0 :       return false;
     553                 :     }
     554                 : 
     555                 :     jsval result;
     556               0 :     if (!xpc::Base64Decode(aCx, string, &result)) {
     557               0 :       return false;
     558                 :     }
     559                 : 
     560               0 :     JS_SET_RVAL(aCx, aVp, result);
     561               0 :     return true;
     562                 :   }
     563                 : 
     564                 :   static JSBool
     565               0 :   BtoA(JSContext* aCx, unsigned aArgc, jsval* aVp)
     566                 :   {
     567               0 :     JSObject* obj = JS_THIS_OBJECT(aCx, aVp);
     568               0 :     if (!obj) {
     569               0 :       return false;
     570                 :     }
     571                 : 
     572               0 :     if (!GetInstancePrivate(aCx, obj, sFunctions[8].name)) {
     573               0 :       return false;
     574                 :     }
     575                 : 
     576                 :     jsval binary;
     577               0 :     if (!JS_ConvertArguments(aCx, aArgc, JS_ARGV(aCx, aVp), "v", &binary)) {
     578               0 :       return false;
     579                 :     }
     580                 : 
     581                 :     jsval result;
     582               0 :     if (!xpc::Base64Encode(aCx, binary, &result)) {
     583               0 :       return false;
     584                 :     }
     585                 : 
     586               0 :     JS_SET_RVAL(aCx, aVp, result);
     587               0 :     return true;
     588                 :   }
     589                 : };
     590                 : 
     591                 : JSClass WorkerGlobalScope::sClass = {
     592                 :   "WorkerGlobalScope",
     593                 :   0,
     594                 :   JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
     595                 :   JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
     596                 :   JSCLASS_NO_OPTIONAL_MEMBERS
     597                 : };
     598                 : 
     599                 : JSPropertySpec WorkerGlobalScope::sProperties[] = {
     600                 :   { "location", SLOT_location, PROPERTY_FLAGS, GetLocation, 
     601                 :     js_GetterOnlyPropertyStub },
     602            1464 :   { sEventStrings[STRING_onerror], STRING_onerror, PROPERTY_FLAGS,
     603                 :     GetOnErrorListener, SetOnErrorListener },
     604            1464 :   { sEventStrings[STRING_onclose], STRING_onclose, PROPERTY_FLAGS,
     605                 :     GetEventListener, SetEventListener },
     606                 :   { "navigator", SLOT_navigator, PROPERTY_FLAGS, GetNavigator, 
     607                 :     js_GetterOnlyPropertyStub },
     608                 :   { "self", 0, PROPERTY_FLAGS, GetSelf, js_GetterOnlyPropertyStub },
     609                 :   { 0, 0, 0, NULL, NULL }
     610            2928 : };
     611                 : 
     612                 : JSFunctionSpec WorkerGlobalScope::sFunctions[] = {
     613                 :   JS_FN("close", Close, 0, FUNCTION_FLAGS),
     614                 :   JS_FN("importScripts", ImportScripts, 1, FUNCTION_FLAGS),
     615                 :   JS_FN("setTimeout", SetTimeout, 1, FUNCTION_FLAGS),
     616                 :   JS_FN("clearTimeout", ClearTimeout, 1, FUNCTION_FLAGS),
     617                 :   JS_FN("setInterval", SetInterval, 1, FUNCTION_FLAGS),
     618                 :   JS_FN("clearInterval", ClearTimeout, 1, FUNCTION_FLAGS),
     619                 :   JS_FN("dump", Dump, 1, FUNCTION_FLAGS),
     620                 :   JS_FN("atob", AtoB, 1, FUNCTION_FLAGS),
     621                 :   JS_FN("btoa", BtoA, 1, FUNCTION_FLAGS),
     622                 :   JS_FS_END
     623                 : };
     624                 : 
     625                 : const char* const WorkerGlobalScope::sEventStrings[STRING_COUNT] = {
     626                 :   "onerror",
     627                 :   "onclose"
     628                 : };
     629                 : 
     630                 : class DedicatedWorkerGlobalScope : public WorkerGlobalScope
     631                 : {
     632                 :   static JSClass sClass;
     633                 :   static JSPropertySpec sProperties[];
     634                 :   static JSFunctionSpec sFunctions[];
     635                 : 
     636                 :   enum
     637                 :   {
     638                 :     STRING_onmessage = 0,
     639                 : 
     640                 :     STRING_COUNT
     641                 :   };
     642                 : 
     643                 :   static const char* const sEventStrings[STRING_COUNT];
     644                 : 
     645                 : public:
     646                 :   static JSClass*
     647               0 :   Class()
     648                 :   {
     649               0 :     return &sClass;
     650                 :   }
     651                 : 
     652                 :   static JSObject*
     653               0 :   InitClass(JSContext* aCx, JSObject* aObj, JSObject* aParentProto)
     654                 :   {
     655                 :     return JS_InitClass(aCx, aObj, aParentProto, &sClass, Construct, 0,
     656               0 :                         sProperties, sFunctions, NULL, NULL);
     657                 :   }
     658                 : 
     659                 :   static JSBool
     660               0 :   InitPrivate(JSContext* aCx, JSObject* aObj, WorkerPrivate* aWorkerPrivate)
     661                 :   {
     662               0 :     JS_ASSERT(JS_GetClass(aObj) == &sClass);
     663               0 :     JS_ASSERT(!GetJSPrivateSafeish<DedicatedWorkerGlobalScope>(aObj));
     664                 : 
     665                 :     DedicatedWorkerGlobalScope* priv =
     666               0 :       new DedicatedWorkerGlobalScope(aWorkerPrivate);
     667               0 :     SetJSPrivateSafeish(aObj, priv);
     668                 : 
     669               0 :     return true;
     670                 :   }
     671                 : 
     672                 : protected:
     673               0 :   DedicatedWorkerGlobalScope(WorkerPrivate* aWorker)
     674               0 :   : WorkerGlobalScope(aWorker)
     675                 :   {
     676               0 :     MOZ_COUNT_CTOR(mozilla::dom::workers::DedicatedWorkerGlobalScope);
     677               0 :   }
     678                 : 
     679               0 :   ~DedicatedWorkerGlobalScope()
     680               0 :   {
     681               0 :     MOZ_COUNT_DTOR(mozilla::dom::workers::DedicatedWorkerGlobalScope);
     682               0 :   }
     683                 : 
     684                 :   using WorkerGlobalScope::TraceInstance;
     685                 :   using WorkerGlobalScope::FinalizeInstance;
     686                 : 
     687                 : private:
     688                 :   static JSBool
     689               0 :   GetEventListener(JSContext* aCx, JSObject* aObj, jsid aIdval, jsval* aVp)
     690                 :   {
     691               0 :     JS_ASSERT(JSID_IS_INT(aIdval));
     692               0 :     JS_ASSERT(JSID_TO_INT(aIdval) >= 0 && JSID_TO_INT(aIdval) < STRING_COUNT);
     693                 : 
     694               0 :     const char* name = sEventStrings[JSID_TO_INT(aIdval)];
     695               0 :     DedicatedWorkerGlobalScope* scope = GetInstancePrivate(aCx, aObj, name);
     696               0 :     if (!scope) {
     697               0 :       return false;
     698                 :     }
     699                 : 
     700               0 :     return scope->GetEventListenerOnEventTarget(aCx, name + 2, aVp);
     701                 :   }
     702                 : 
     703                 :   static JSBool
     704               0 :   SetEventListener(JSContext* aCx, JSObject* aObj, jsid aIdval, JSBool aStrict,
     705                 :                    jsval* aVp)
     706                 :   {
     707               0 :     JS_ASSERT(JSID_IS_INT(aIdval));
     708               0 :     JS_ASSERT(JSID_TO_INT(aIdval) >= 0 && JSID_TO_INT(aIdval) < STRING_COUNT);
     709                 : 
     710               0 :     const char* name = sEventStrings[JSID_TO_INT(aIdval)];
     711               0 :     DedicatedWorkerGlobalScope* scope = GetInstancePrivate(aCx, aObj, name);
     712               0 :     if (!scope) {
     713               0 :       return false;
     714                 :     }
     715                 : 
     716               0 :     return scope->SetEventListenerOnEventTarget(aCx, name + 2, aVp);
     717                 :   }
     718                 : 
     719                 :   static DedicatedWorkerGlobalScope*
     720               0 :   GetInstancePrivate(JSContext* aCx, JSObject* aObj, const char* aFunctionName)
     721                 :   {
     722               0 :     JSClass* classPtr = JS_GetClass(aObj);
     723               0 :     if (classPtr == &sClass) {
     724               0 :       return GetJSPrivateSafeish<DedicatedWorkerGlobalScope>(aObj);
     725                 :     }
     726                 : 
     727                 :     JS_ReportErrorNumber(aCx, js_GetErrorMessage, NULL,
     728                 :                          JSMSG_INCOMPATIBLE_PROTO, sClass.name, aFunctionName,
     729               0 :                          classPtr->name);
     730               0 :     return NULL;
     731                 :   }
     732                 : 
     733                 :   static JSBool
     734               0 :   Construct(JSContext* aCx, unsigned aArgc, jsval* aVp)
     735                 :   {
     736                 :     JS_ReportErrorNumber(aCx, js_GetErrorMessage, NULL, JSMSG_WRONG_CONSTRUCTOR,
     737               0 :                          sClass.name);
     738               0 :     return false;
     739                 :   }
     740                 : 
     741                 :   static JSBool
     742               0 :   Resolve(JSContext* aCx, JSObject* aObj, jsid aId, unsigned aFlags,
     743                 :           JSObject** aObjp)
     744                 :   {
     745                 :     JSBool resolved;
     746               0 :     if (!JS_ResolveStandardClass(aCx, aObj, aId, &resolved)) {
     747               0 :       return false;
     748                 :     }
     749                 : 
     750               0 :     *aObjp = resolved ? aObj : NULL;
     751               0 :     return true;
     752                 :   }
     753                 : 
     754                 :   static void
     755               0 :   Finalize(JSContext* aCx, JSObject* aObj)
     756                 :   {
     757               0 :     JS_ASSERT(JS_GetClass(aObj) == &sClass);
     758                 :     DedicatedWorkerGlobalScope* scope =
     759               0 :       GetJSPrivateSafeish<DedicatedWorkerGlobalScope>(aObj);
     760               0 :     if (scope) {
     761               0 :       scope->FinalizeInstance(aCx);
     762               0 :       delete scope;
     763                 :     }
     764               0 :   }
     765                 : 
     766                 :   static void
     767               0 :   Trace(JSTracer* aTrc, JSObject* aObj)
     768                 :   {
     769               0 :     JS_ASSERT(JS_GetClass(aObj) == &sClass);
     770                 :     DedicatedWorkerGlobalScope* scope =
     771               0 :       GetJSPrivateSafeish<DedicatedWorkerGlobalScope>(aObj);
     772               0 :     if (scope) {
     773               0 :       scope->TraceInstance(aTrc);
     774                 :     }
     775               0 :   }
     776                 : 
     777                 :   static JSBool
     778               0 :   PostMessage(JSContext* aCx, unsigned aArgc, jsval* aVp)
     779                 :   {
     780               0 :     JSObject* obj = JS_THIS_OBJECT(aCx, aVp);
     781               0 :     if (!obj) {
     782               0 :       return false;
     783                 :     }
     784                 : 
     785               0 :     const char*& name = sFunctions[0].name;
     786               0 :     DedicatedWorkerGlobalScope* scope = GetInstancePrivate(aCx, obj, name);
     787               0 :     if (!scope) {
     788               0 :       return false;
     789                 :     }
     790                 : 
     791                 :     jsval message;
     792               0 :     if (!JS_ConvertArguments(aCx, aArgc, JS_ARGV(aCx, aVp), "v", &message)) {
     793               0 :       return false;
     794                 :     }
     795                 : 
     796               0 :     return scope->mWorker->PostMessageToParent(aCx, message);
     797                 :   }
     798                 : };
     799                 : 
     800                 : JSClass DedicatedWorkerGlobalScope::sClass = {
     801                 :   "DedicatedWorkerGlobalScope",
     802                 :   JSCLASS_GLOBAL_FLAGS | JSCLASS_HAS_PRIVATE | JSCLASS_IMPLEMENTS_BARRIERS | JSCLASS_NEW_RESOLVE,
     803                 :   JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
     804                 :   JS_EnumerateStub, reinterpret_cast<JSResolveOp>(Resolve), JS_ConvertStub,
     805                 :   Finalize, NULL, NULL, NULL, NULL, Trace
     806                 : };
     807                 : 
     808                 : JSPropertySpec DedicatedWorkerGlobalScope::sProperties[] = {
     809            1464 :   { sEventStrings[STRING_onmessage], STRING_onmessage, PROPERTY_FLAGS,
     810                 :     GetEventListener, SetEventListener },
     811                 :   { 0, 0, 0, NULL, NULL }
     812            1464 : };
     813                 : 
     814                 : JSFunctionSpec DedicatedWorkerGlobalScope::sFunctions[] = {
     815                 :   JS_FN("postMessage", PostMessage, 1, FUNCTION_FLAGS),
     816                 :   JS_FS_END
     817                 : };
     818                 : 
     819                 : const char* const DedicatedWorkerGlobalScope::sEventStrings[STRING_COUNT] = {
     820                 :   "onmessage",
     821                 : };
     822                 : 
     823                 : WorkerGlobalScope*
     824               0 : WorkerGlobalScope::GetInstancePrivate(JSContext* aCx, JSObject* aObj,
     825                 :                                       const char* aFunctionName)
     826                 : {
     827               0 :   JSClass* classPtr = JS_GetClass(aObj);
     828               0 :   if (classPtr == &sClass || classPtr == DedicatedWorkerGlobalScope::Class()) {
     829               0 :     return GetJSPrivateSafeish<WorkerGlobalScope>(aObj);
     830                 :   }
     831                 : 
     832                 :   JS_ReportErrorNumber(aCx, js_GetErrorMessage, NULL, JSMSG_INCOMPATIBLE_PROTO,
     833               0 :                        sClass.name, aFunctionName, classPtr->name);
     834               0 :   return NULL;
     835                 : }
     836                 : 
     837                 : } /* anonymous namespace */
     838                 : 
     839                 : BEGIN_WORKERS_NAMESPACE
     840                 : 
     841                 : JSObject*
     842               0 : CreateDedicatedWorkerGlobalScope(JSContext* aCx)
     843                 : {
     844               0 :   WorkerPrivate* worker = GetWorkerPrivateFromContext(aCx);
     845               0 :   JS_ASSERT(worker);
     846                 : 
     847                 :   JSObject* global =
     848                 :     JS_NewCompartmentAndGlobalObject(aCx, DedicatedWorkerGlobalScope::Class(),
     849               0 :                                      GetWorkerPrincipal());
     850               0 :   if (!global) {
     851               0 :     return NULL;
     852                 :   }
     853                 : 
     854               0 :   JSAutoEnterCompartment ac;
     855               0 :   if (!ac.enter(aCx, global)) {
     856               0 :     return NULL;
     857                 :   }
     858                 : 
     859                 :   // Make the private slots now so that all our instance checks succeed.
     860               0 :   if (!DedicatedWorkerGlobalScope::InitPrivate(aCx, global, worker)) {
     861               0 :     return NULL;
     862                 :   }
     863                 : 
     864                 :   // Proto chain should be:
     865                 :   //   global -> DedicatedWorkerGlobalScope
     866                 :   //          -> WorkerGlobalScope
     867                 :   //          -> EventTarget
     868                 :   //          -> Object
     869                 : 
     870                 :   JSObject* eventTargetProto =
     871               0 :     events::InitEventTargetClass(aCx, global, nsnull);
     872               0 :   if (!eventTargetProto) {
     873               0 :     return NULL;
     874                 :   }
     875                 : 
     876                 :   JSObject* scopeProto =
     877               0 :     WorkerGlobalScope::InitClass(aCx, global, eventTargetProto);
     878               0 :   if (!scopeProto) {
     879               0 :     return NULL;
     880                 :   }
     881                 : 
     882                 :   JSObject* dedicatedScopeProto =
     883               0 :     DedicatedWorkerGlobalScope::InitClass(aCx, global, scopeProto);
     884               0 :   if (!dedicatedScopeProto) {
     885               0 :     return NULL;
     886                 :   }
     887                 : 
     888               0 :   if (!JS_SetPrototype(aCx, global, dedicatedScopeProto)) {
     889               0 :     return NULL;
     890                 :   }
     891                 : 
     892                 :   JSObject* workerProto = worker::InitClass(aCx, global, eventTargetProto,
     893               0 :                                             false);
     894               0 :   if (!workerProto) {
     895               0 :     return NULL;
     896                 :   }
     897                 : 
     898               0 :   if (worker->IsChromeWorker()) {
     899               0 :     if (!chromeworker::InitClass(aCx, global, workerProto, false) ||
     900               0 :         !chromeworker::DefineChromeWorkerFunctions(aCx, global)) {
     901               0 :       return NULL;
     902                 :     }
     903                 :   }
     904                 : 
     905                 :   // Init other classes we care about.
     906               0 :   if (!events::InitClasses(aCx, global, false) ||
     907               0 :       !file::InitClasses(aCx, global) ||
     908               0 :       !filereadersync::InitClass(aCx, global) ||
     909               0 :       !exceptions::InitClasses(aCx, global) ||
     910               0 :       !xhr::InitClasses(aCx, global, eventTargetProto) ||
     911               0 :       !location::InitClass(aCx, global) ||
     912               0 :       !navigator::InitClass(aCx, global)) {
     913               0 :     return NULL;
     914                 :   }
     915                 : 
     916               0 :   if (!JS_DefineProfilingFunctions(aCx, global)) {
     917               0 :     return NULL;
     918                 :   }
     919                 : 
     920               0 :   return global;
     921                 : }
     922                 : 
     923                 : bool
     924               0 : ClassIsWorkerGlobalScope(JSClass* aClass)
     925                 : {
     926               0 :   return WorkerGlobalScope::Class() == aClass ||
     927               0 :          DedicatedWorkerGlobalScope::Class() == aClass;
     928                 : }
     929                 : 
     930            4392 : END_WORKERS_NAMESPACE

Generated by: LCOV version 1.7