Line data Source code
1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2; -*- */
2 : /* This Source Code Form is subject to the terms of the Mozilla Public
3 : * License, v. 2.0. If a copy of the MPL was not distributed with this
4 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 :
6 : #include "ctypes.h"
7 : #include "jsapi.h"
8 : #include "mozilla/ModuleUtils.h"
9 : #include "nsMemory.h"
10 : #include "nsString.h"
11 : #include "nsNativeCharsetUtils.h"
12 : #include "mozilla/Preferences.h"
13 : #include "mozJSComponentLoader.h"
14 : #include "nsZipArchive.h"
15 : #include "xpc_make_class.h"
16 :
17 : #define JSCTYPES_CONTRACTID \
18 : "@mozilla.org/jsctypes;1"
19 :
20 :
21 : #define JSCTYPES_CID \
22 : { 0xc797702, 0x1c60, 0x4051, { 0x9d, 0xd7, 0x4d, 0x74, 0x5, 0x60, 0x56, 0x42 } }
23 :
24 : namespace mozilla {
25 : namespace ctypes {
26 :
27 : static char*
28 0 : UnicodeToNative(JSContext *cx, const char16_t *source, size_t slen)
29 : {
30 0 : nsAutoCString native;
31 0 : nsDependentString unicode(reinterpret_cast<const char16_t*>(source), slen);
32 0 : nsresult rv = NS_CopyUnicodeToNative(unicode, native);
33 0 : if (NS_FAILED(rv)) {
34 0 : JS_ReportErrorASCII(cx, "could not convert string to native charset");
35 0 : return nullptr;
36 : }
37 :
38 0 : char* result = static_cast<char*>(JS_malloc(cx, native.Length() + 1));
39 0 : if (!result)
40 0 : return nullptr;
41 :
42 0 : memcpy(result, native.get(), native.Length() + 1);
43 0 : return result;
44 : }
45 :
46 : static JSCTypesCallbacks sCallbacks = {
47 : UnicodeToNative
48 : };
49 :
50 2 : NS_GENERIC_FACTORY_CONSTRUCTOR(Module)
51 :
52 32 : NS_IMPL_ISUPPORTS(Module, nsIXPCScriptable)
53 :
54 : Module::Module() = default;
55 :
56 : Module::~Module() = default;
57 :
58 : #define XPC_MAP_CLASSNAME Module
59 : #define XPC_MAP_QUOTED_CLASSNAME "Module"
60 : #define XPC_MAP_FLAGS XPC_SCRIPTABLE_WANT_CALL
61 : #include "xpc_map_end.h"
62 :
63 : static bool
64 4 : SealObjectAndPrototype(JSContext* cx, JS::Handle<JSObject *> parent, const char* name)
65 : {
66 8 : JS::Rooted<JS::Value> prop(cx);
67 4 : if (!JS_GetProperty(cx, parent, name, &prop))
68 0 : return false;
69 :
70 4 : if (prop.isUndefined()) {
71 : // Pretend we sealed the object.
72 0 : return true;
73 : }
74 :
75 8 : JS::Rooted<JSObject*> obj(cx, prop.toObjectOrNull());
76 4 : if (!JS_GetProperty(cx, obj, "prototype", &prop))
77 0 : return false;
78 :
79 8 : JS::Rooted<JSObject*> prototype(cx, prop.toObjectOrNull());
80 4 : return JS_FreezeObject(cx, obj) && JS_FreezeObject(cx, prototype);
81 : }
82 :
83 : static bool
84 1 : InitAndSealCTypesClass(JSContext* cx, JS::Handle<JSObject*> global)
85 : {
86 : // Init the ctypes object.
87 1 : if (!JS_InitCTypesClass(cx, global))
88 0 : return false;
89 :
90 : // Set callbacks for charset conversion and such.
91 2 : JS::Rooted<JS::Value> ctypes(cx);
92 1 : if (!JS_GetProperty(cx, global, "ctypes", &ctypes))
93 0 : return false;
94 :
95 1 : JS_SetCTypesCallbacks(ctypes.toObjectOrNull(), &sCallbacks);
96 :
97 : // Seal up Object, Function, Array and Error and their prototypes. (This
98 : // single object instance is shared amongst everyone who imports the ctypes
99 : // module.)
100 3 : if (!SealObjectAndPrototype(cx, global, "Object") ||
101 2 : !SealObjectAndPrototype(cx, global, "Function") ||
102 3 : !SealObjectAndPrototype(cx, global, "Array") ||
103 1 : !SealObjectAndPrototype(cx, global, "Error"))
104 0 : return false;
105 :
106 1 : return true;
107 : }
108 :
109 : NS_IMETHODIMP
110 1 : Module::Call(nsIXPConnectWrappedNative* wrapper,
111 : JSContext* cx,
112 : JSObject* obj,
113 : const JS::CallArgs& args,
114 : bool* _retval)
115 : {
116 1 : mozJSComponentLoader* loader = mozJSComponentLoader::Get();
117 2 : JS::Rooted<JSObject*> targetObj(cx);
118 1 : loader->FindTargetObject(cx, &targetObj);
119 :
120 1 : *_retval = InitAndSealCTypesClass(cx, targetObj);
121 2 : return NS_OK;
122 : }
123 :
124 : } // namespace ctypes
125 : } // namespace mozilla
126 :
127 : NS_DEFINE_NAMED_CID(JSCTYPES_CID);
128 :
129 : static const mozilla::Module::CIDEntry kCTypesCIDs[] = {
130 : { &kJSCTYPES_CID, false, nullptr, mozilla::ctypes::ModuleConstructor },
131 : { nullptr }
132 : };
133 :
134 : static const mozilla::Module::ContractIDEntry kCTypesContracts[] = {
135 : { JSCTYPES_CONTRACTID, &kJSCTYPES_CID },
136 : { nullptr }
137 : };
138 :
139 : static const mozilla::Module kCTypesModule = {
140 : mozilla::Module::kVersion,
141 : kCTypesCIDs,
142 : kCTypesContracts
143 : };
144 :
145 : NSMODULE_DEFN(jsctypes) = &kCTypesModule;
|