LCOV - app.info - dom/workers/WorkerScope.cpp

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-07-07 | 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