Sat, 03 Jan 2015 20:18:00 +0100
Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.
michael@0 | 1 | /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- |
michael@0 | 2 | * vim: set ts=8 sts=4 et sw=4 tw=99: |
michael@0 | 3 | * This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 5 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 6 | |
michael@0 | 7 | #include "jsfriendapi.h" |
michael@0 | 8 | #include "jsscript.h" |
michael@0 | 9 | #include "jsstr.h" |
michael@0 | 10 | |
michael@0 | 11 | #include "jsapi-tests/tests.h" |
michael@0 | 12 | |
michael@0 | 13 | #include "jsscriptinlines.h" |
michael@0 | 14 | |
michael@0 | 15 | static JSScript * |
michael@0 | 16 | CompileScriptForPrincipalsVersionOrigin(JSContext *cx, JS::HandleObject obj, |
michael@0 | 17 | JSPrincipals *originPrincipals, |
michael@0 | 18 | const char *bytes, size_t nbytes, |
michael@0 | 19 | const char *filename, unsigned lineno, |
michael@0 | 20 | JSVersion version) |
michael@0 | 21 | { |
michael@0 | 22 | size_t nchars; |
michael@0 | 23 | if (!JS_DecodeBytes(cx, bytes, nbytes, nullptr, &nchars)) |
michael@0 | 24 | return nullptr; |
michael@0 | 25 | jschar *chars = static_cast<jschar *>(JS_malloc(cx, nchars * sizeof(jschar))); |
michael@0 | 26 | if (!chars) |
michael@0 | 27 | return nullptr; |
michael@0 | 28 | JS_ALWAYS_TRUE(JS_DecodeBytes(cx, bytes, nbytes, chars, &nchars)); |
michael@0 | 29 | JS::CompileOptions options(cx); |
michael@0 | 30 | options.setOriginPrincipals(originPrincipals) |
michael@0 | 31 | .setFileAndLine(filename, lineno) |
michael@0 | 32 | .setVersion(version); |
michael@0 | 33 | JSScript *script = JS::Compile(cx, obj, options, chars, nchars); |
michael@0 | 34 | free(chars); |
michael@0 | 35 | return script; |
michael@0 | 36 | } |
michael@0 | 37 | |
michael@0 | 38 | static JSScript * |
michael@0 | 39 | FreezeThaw(JSContext *cx, JS::HandleScript script) |
michael@0 | 40 | { |
michael@0 | 41 | // freeze |
michael@0 | 42 | uint32_t nbytes; |
michael@0 | 43 | void *memory = JS_EncodeScript(cx, script, &nbytes); |
michael@0 | 44 | if (!memory) |
michael@0 | 45 | return nullptr; |
michael@0 | 46 | |
michael@0 | 47 | // thaw |
michael@0 | 48 | JSScript *script2 = JS_DecodeScript(cx, memory, nbytes, |
michael@0 | 49 | script->originPrincipals()); |
michael@0 | 50 | js_free(memory); |
michael@0 | 51 | return script2; |
michael@0 | 52 | } |
michael@0 | 53 | |
michael@0 | 54 | static JSScript * |
michael@0 | 55 | GetScript(JSContext *cx, JS::HandleObject funobj) |
michael@0 | 56 | { |
michael@0 | 57 | JS::RootedFunction fun(cx, JS_GetObjectFunction(funobj)); |
michael@0 | 58 | return JS_GetFunctionScript(cx, fun); |
michael@0 | 59 | } |
michael@0 | 60 | |
michael@0 | 61 | static JSObject * |
michael@0 | 62 | FreezeThaw(JSContext *cx, JS::HandleObject funobj) |
michael@0 | 63 | { |
michael@0 | 64 | // freeze |
michael@0 | 65 | uint32_t nbytes; |
michael@0 | 66 | void *memory = JS_EncodeInterpretedFunction(cx, funobj, &nbytes); |
michael@0 | 67 | if (!memory) |
michael@0 | 68 | return nullptr; |
michael@0 | 69 | |
michael@0 | 70 | // thaw |
michael@0 | 71 | JSScript *script = GetScript(cx, funobj); |
michael@0 | 72 | JSObject *funobj2 = JS_DecodeInterpretedFunction(cx, memory, nbytes, |
michael@0 | 73 | script->originPrincipals()); |
michael@0 | 74 | js_free(memory); |
michael@0 | 75 | return funobj2; |
michael@0 | 76 | } |
michael@0 | 77 | |
michael@0 | 78 | static TestJSPrincipals testPrincipal0(1); |
michael@0 | 79 | static TestJSPrincipals testPrincipal1(1); |
michael@0 | 80 | |
michael@0 | 81 | BEGIN_TEST(testXDR_principals) |
michael@0 | 82 | { |
michael@0 | 83 | JSScript *script; |
michael@0 | 84 | JSCompartment *compartment = js::GetContextCompartment(cx); |
michael@0 | 85 | for (int i = TEST_FIRST; i != TEST_END; ++i) { |
michael@0 | 86 | // Appease the new JSAPI assertions. The stuff being tested here is |
michael@0 | 87 | // going away anyway. |
michael@0 | 88 | JS_SetCompartmentPrincipals(compartment, &testPrincipal0); |
michael@0 | 89 | script = createScriptViaXDR(nullptr, i); |
michael@0 | 90 | CHECK(script); |
michael@0 | 91 | CHECK(JS_GetScriptPrincipals(script) == &testPrincipal0); |
michael@0 | 92 | CHECK(JS_GetScriptOriginPrincipals(script) == &testPrincipal0); |
michael@0 | 93 | |
michael@0 | 94 | script = createScriptViaXDR(&testPrincipal0, i); |
michael@0 | 95 | CHECK(script); |
michael@0 | 96 | CHECK(JS_GetScriptPrincipals(script) == &testPrincipal0); |
michael@0 | 97 | CHECK(JS_GetScriptOriginPrincipals(script) == &testPrincipal0); |
michael@0 | 98 | |
michael@0 | 99 | script = createScriptViaXDR(&testPrincipal1, i); |
michael@0 | 100 | CHECK(script); |
michael@0 | 101 | CHECK(JS_GetScriptPrincipals(script) == &testPrincipal0); |
michael@0 | 102 | CHECK(JS_GetScriptOriginPrincipals(script) == &testPrincipal1); |
michael@0 | 103 | } |
michael@0 | 104 | |
michael@0 | 105 | return true; |
michael@0 | 106 | } |
michael@0 | 107 | |
michael@0 | 108 | enum TestCase { |
michael@0 | 109 | TEST_FIRST, |
michael@0 | 110 | TEST_SCRIPT = TEST_FIRST, |
michael@0 | 111 | TEST_FUNCTION, |
michael@0 | 112 | TEST_SERIALIZED_FUNCTION, |
michael@0 | 113 | TEST_END |
michael@0 | 114 | }; |
michael@0 | 115 | |
michael@0 | 116 | JSScript *createScriptViaXDR(JSPrincipals *orig, int testCase) |
michael@0 | 117 | { |
michael@0 | 118 | const char src[] = |
michael@0 | 119 | "function f() { return 1; }\n" |
michael@0 | 120 | "f;\n"; |
michael@0 | 121 | |
michael@0 | 122 | JS::RootedObject global(cx, JS::CurrentGlobalOrNull(cx)); |
michael@0 | 123 | JS::RootedScript script(cx, CompileScriptForPrincipalsVersionOrigin(cx, global, orig, |
michael@0 | 124 | src, strlen(src), "test", 1, |
michael@0 | 125 | JSVERSION_DEFAULT)); |
michael@0 | 126 | if (!script) |
michael@0 | 127 | return nullptr; |
michael@0 | 128 | |
michael@0 | 129 | if (testCase == TEST_SCRIPT || testCase == TEST_SERIALIZED_FUNCTION) { |
michael@0 | 130 | script = FreezeThaw(cx, script); |
michael@0 | 131 | if (!script) |
michael@0 | 132 | return nullptr; |
michael@0 | 133 | if (testCase == TEST_SCRIPT) |
michael@0 | 134 | return script; |
michael@0 | 135 | } |
michael@0 | 136 | |
michael@0 | 137 | JS::RootedValue v(cx); |
michael@0 | 138 | bool ok = JS_ExecuteScript(cx, global, script, &v); |
michael@0 | 139 | if (!ok || !v.isObject()) |
michael@0 | 140 | return nullptr; |
michael@0 | 141 | JS::RootedObject funobj(cx, &v.toObject()); |
michael@0 | 142 | if (testCase == TEST_FUNCTION) { |
michael@0 | 143 | funobj = FreezeThaw(cx, funobj); |
michael@0 | 144 | if (!funobj) |
michael@0 | 145 | return nullptr; |
michael@0 | 146 | } |
michael@0 | 147 | return GetScript(cx, funobj); |
michael@0 | 148 | } |
michael@0 | 149 | |
michael@0 | 150 | END_TEST(testXDR_principals) |
michael@0 | 151 | |
michael@0 | 152 | BEGIN_TEST(testXDR_bug506491) |
michael@0 | 153 | { |
michael@0 | 154 | const char *s = |
michael@0 | 155 | "function makeClosure(s, name, value) {\n" |
michael@0 | 156 | " eval(s);\n" |
michael@0 | 157 | " Math.sin(value);\n" |
michael@0 | 158 | " return let (n = name, v = value) function () { return String(v); };\n" |
michael@0 | 159 | "}\n" |
michael@0 | 160 | "var f = makeClosure('0;', 'status', 'ok');\n"; |
michael@0 | 161 | |
michael@0 | 162 | // compile |
michael@0 | 163 | JS::CompileOptions options(cx); |
michael@0 | 164 | options.setFileAndLine(__FILE__, __LINE__); |
michael@0 | 165 | JS::RootedScript script(cx, JS_CompileScript(cx, global, s, strlen(s), |
michael@0 | 166 | options)); |
michael@0 | 167 | CHECK(script); |
michael@0 | 168 | |
michael@0 | 169 | script = FreezeThaw(cx, script); |
michael@0 | 170 | CHECK(script); |
michael@0 | 171 | |
michael@0 | 172 | // execute |
michael@0 | 173 | JS::RootedValue v2(cx); |
michael@0 | 174 | CHECK(JS_ExecuteScript(cx, global, script, &v2)); |
michael@0 | 175 | |
michael@0 | 176 | // try to break the Block object that is the parent of f |
michael@0 | 177 | JS_GC(rt); |
michael@0 | 178 | |
michael@0 | 179 | // confirm |
michael@0 | 180 | EVAL("f() === 'ok';\n", &v2); |
michael@0 | 181 | JS::RootedValue trueval(cx, JSVAL_TRUE); |
michael@0 | 182 | CHECK_SAME(v2, trueval); |
michael@0 | 183 | return true; |
michael@0 | 184 | } |
michael@0 | 185 | END_TEST(testXDR_bug506491) |
michael@0 | 186 | |
michael@0 | 187 | BEGIN_TEST(testXDR_bug516827) |
michael@0 | 188 | { |
michael@0 | 189 | // compile an empty script |
michael@0 | 190 | JS::CompileOptions options(cx); |
michael@0 | 191 | options.setFileAndLine(__FILE__, __LINE__); |
michael@0 | 192 | JS::RootedScript script(cx, JS_CompileScript(cx, global, "", 0, options)); |
michael@0 | 193 | CHECK(script); |
michael@0 | 194 | |
michael@0 | 195 | script = FreezeThaw(cx, script); |
michael@0 | 196 | CHECK(script); |
michael@0 | 197 | |
michael@0 | 198 | // execute with null result meaning no result wanted |
michael@0 | 199 | CHECK(JS_ExecuteScript(cx, global, script)); |
michael@0 | 200 | return true; |
michael@0 | 201 | } |
michael@0 | 202 | END_TEST(testXDR_bug516827) |
michael@0 | 203 | |
michael@0 | 204 | BEGIN_TEST(testXDR_source) |
michael@0 | 205 | { |
michael@0 | 206 | const char *samples[] = { |
michael@0 | 207 | // This can't possibly fail to compress well, can it? |
michael@0 | 208 | "function f(x) { return x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x }", |
michael@0 | 209 | "short", |
michael@0 | 210 | nullptr |
michael@0 | 211 | }; |
michael@0 | 212 | for (const char **s = samples; *s; s++) { |
michael@0 | 213 | JS::CompileOptions options(cx); |
michael@0 | 214 | options.setFileAndLine(__FILE__, __LINE__); |
michael@0 | 215 | JS::RootedScript script(cx, JS_CompileScript(cx, global, *s, strlen(*s), |
michael@0 | 216 | options)); |
michael@0 | 217 | CHECK(script); |
michael@0 | 218 | script = FreezeThaw(cx, script); |
michael@0 | 219 | CHECK(script); |
michael@0 | 220 | JSString *out = JS_DecompileScript(cx, script, "testing", 0); |
michael@0 | 221 | CHECK(out); |
michael@0 | 222 | bool equal; |
michael@0 | 223 | CHECK(JS_StringEqualsAscii(cx, out, *s, &equal)); |
michael@0 | 224 | CHECK(equal); |
michael@0 | 225 | } |
michael@0 | 226 | return true; |
michael@0 | 227 | } |
michael@0 | 228 | END_TEST(testXDR_source) |
michael@0 | 229 | |
michael@0 | 230 | BEGIN_TEST(testXDR_sourceMap) |
michael@0 | 231 | { |
michael@0 | 232 | const char *sourceMaps[] = { |
michael@0 | 233 | "http://example.com/source-map.json", |
michael@0 | 234 | "file:///var/source-map.json", |
michael@0 | 235 | nullptr |
michael@0 | 236 | }; |
michael@0 | 237 | JS::RootedScript script(cx); |
michael@0 | 238 | for (const char **sm = sourceMaps; *sm; sm++) { |
michael@0 | 239 | JS::CompileOptions options(cx); |
michael@0 | 240 | options.setFileAndLine(__FILE__, __LINE__); |
michael@0 | 241 | script = JS_CompileScript(cx, global, "", 0, options); |
michael@0 | 242 | CHECK(script); |
michael@0 | 243 | |
michael@0 | 244 | size_t len = strlen(*sm); |
michael@0 | 245 | jschar *expected = js::InflateString(cx, *sm, &len); |
michael@0 | 246 | CHECK(expected); |
michael@0 | 247 | |
michael@0 | 248 | // The script source takes responsibility of free'ing |expected|. |
michael@0 | 249 | CHECK(script->scriptSource()->setSourceMapURL(cx, expected)); |
michael@0 | 250 | script = FreezeThaw(cx, script); |
michael@0 | 251 | CHECK(script); |
michael@0 | 252 | CHECK(script->scriptSource()); |
michael@0 | 253 | CHECK(script->scriptSource()->hasSourceMapURL()); |
michael@0 | 254 | |
michael@0 | 255 | const jschar *actual = script->scriptSource()->sourceMapURL(); |
michael@0 | 256 | CHECK(actual); |
michael@0 | 257 | |
michael@0 | 258 | while (*expected) { |
michael@0 | 259 | CHECK(*actual); |
michael@0 | 260 | CHECK(*expected == *actual); |
michael@0 | 261 | expected++; |
michael@0 | 262 | actual++; |
michael@0 | 263 | } |
michael@0 | 264 | CHECK(!*actual); |
michael@0 | 265 | } |
michael@0 | 266 | return true; |
michael@0 | 267 | } |
michael@0 | 268 | END_TEST(testXDR_sourceMap) |