From be02ee4f0003985f0845c5aa8865f7340d084b1f Mon Sep 17 00:00:00 2001 From: Jeff Gilbert Date: Fri, 14 Sep 2012 16:02:39 -0700 Subject: [PATCH 01/11] Bug 771406 - Add emulation for GLSL faceForward() to ANGLE - r=bjacob --- .../src/compiler/BuiltInFunctionEmulator.cpp | 91 +++++++++++++++++-- .../src/compiler/BuiltInFunctionEmulator.h | 9 ++ 2 files changed, 92 insertions(+), 8 deletions(-) diff --git a/gfx/angle/src/compiler/BuiltInFunctionEmulator.cpp b/gfx/angle/src/compiler/BuiltInFunctionEmulator.cpp index 1c4b25f13f0..24f0f093b30 100644 --- a/gfx/angle/src/compiler/BuiltInFunctionEmulator.cpp +++ b/gfx/angle/src/compiler/BuiltInFunctionEmulator.cpp @@ -31,6 +31,12 @@ const char* kFunctionEmulationVertexSource[] = { "#error no emulation for dot(vec3, vec3)", "#error no emulation for dot(vec4, vec4)", + // |faceforward(N, I, Nref)| is |dot(NRef, I) < 0 ? N : -N| + "#define webgl_faceforward_emu(N, I, Nref) (((Nref) * (I) < 0.0) ? (N) : -(N))", + "#error no emulation for faceforward(vec2, vec2, vec2)", + "#error no emulation for faceforward(vec3, vec3, vec3)", + "#error no emulation for faceforward(vec4, vec4, vec4)", + "#define webgl_length_emu(x) ((x) >= 0.0 ? (x) : -(x))", "#error no emulation for length(vec2)", "#error no emulation for length(vec3)", @@ -63,6 +69,12 @@ const char* kFunctionEmulationFragmentSource[] = { "#error no emulation for dot(vec3, vec3)", "#error no emulation for dot(vec4, vec4)", + // |faceforward(N, I, Nref)| is |dot(NRef, I) < 0 ? N : -N| + "#define webgl_faceforward_emu(N, I, Nref) (((Nref) * (I) < 0.0) ? (N) : -(N))", + "#error no emulation for faceforward(vec2, vec2, vec2)", + "#error no emulation for faceforward(vec3, vec3, vec3)", + "#error no emulation for faceforward(vec4, vec4, vec4)", + "#define webgl_length_emu(x) ((x) >= 0.0 ? (x) : -(x))", "#error no emulation for length(vec2)", "#error no emulation for length(vec3)", @@ -94,6 +106,10 @@ const bool kFunctionEmulationVertexMask[] = { false, // TFunctionDot2_2 false, // TFunctionDot3_3 false, // TFunctionDot4_4 + true, // TFunctionFaceForward1_1_1 + false, // TFunctionFaceForward2_2_2 + false, // TFunctionFaceForward3_3_3 + false, // TFunctionFaceForward4_4_4 true, // TFunctionLength1 false, // TFunctionLength2 false, // TFunctionLength3 @@ -120,6 +136,10 @@ const bool kFunctionEmulationVertexMask[] = { false, // TFunctionDot2_2 false, // TFunctionDot3_3 false, // TFunctionDot4_4 + false, // TFunctionFaceForward1_1_1 + false, // TFunctionFaceForward2_2_2 + false, // TFunctionFaceForward3_3_3 + false, // TFunctionFaceForward4_4_4 false, // TFunctionLength1 false, // TFunctionLength2 false, // TFunctionLength3 @@ -151,6 +171,10 @@ const bool kFunctionEmulationFragmentMask[] = { false, // TFunctionDot2_2 false, // TFunctionDot3_3 false, // TFunctionDot4_4 + true, // TFunctionFaceForward1_1_1 + false, // TFunctionFaceForward2_2_2 + false, // TFunctionFaceForward3_3_3 + false, // TFunctionFaceForward4_4_4 true, // TFunctionLength1 false, // TFunctionLength2 false, // TFunctionLength3 @@ -177,6 +201,10 @@ const bool kFunctionEmulationFragmentMask[] = { false, // TFunctionDot2_2 false, // TFunctionDot3_3 false, // TFunctionDot4_4 + false, // TFunctionFaceForward1_1_1 + false, // TFunctionFaceForward2_2_2 + false, // TFunctionFaceForward3_3_3 + false, // TFunctionFaceForward4_4_4 false, // TFunctionLength1 false, // TFunctionLength2 false, // TFunctionLength3 @@ -244,15 +272,27 @@ public: return true; }; const TIntermSequence& sequence = node->getSequence(); - // Right now we only handle built-in functions with two parameters. - if (sequence.size() != 2) + bool needToEmulate = false; + + if (sequence.size() == 2) { + TIntermTyped* param1 = sequence[0]->getAsTyped(); + TIntermTyped* param2 = sequence[1]->getAsTyped(); + if (!param1 || !param2) + return true; + needToEmulate = mEmulator.SetFunctionCalled( + node->getOp(), param1->getType(), param2->getType()); + } else if (sequence.size() == 3) { + TIntermTyped* param1 = sequence[0]->getAsTyped(); + TIntermTyped* param2 = sequence[1]->getAsTyped(); + TIntermTyped* param3 = sequence[2]->getAsTyped(); + if (!param1 || !param2 || !param3) + return true; + needToEmulate = mEmulator.SetFunctionCalled( + node->getOp(), param1->getType(), param2->getType(), param3->getType()); + } else { return true; - TIntermTyped* param1 = sequence[0]->getAsTyped(); - TIntermTyped* param2 = sequence[1]->getAsTyped(); - if (!param1 || !param2) - return true; - bool needToEmulate = mEmulator.SetFunctionCalled( - node->getOp(), param1->getType(), param2->getType()); + } + if (needToEmulate) node->setUseEmulatedFunction(); } @@ -290,6 +330,13 @@ bool BuiltInFunctionEmulator::SetFunctionCalled( return SetFunctionCalled(function); } +bool BuiltInFunctionEmulator::SetFunctionCalled( + TOperator op, const TType& param1, const TType& param2, const TType& param3) +{ + TBuiltInFunction function = IdentifyFunction(op, param1, param2, param3); + return SetFunctionCalled(function); +} + bool BuiltInFunctionEmulator::SetFunctionCalled( BuiltInFunctionEmulator::TBuiltInFunction function) { if (function == TFunctionUnknown || mFunctionMask[function] == false) @@ -382,6 +429,34 @@ BuiltInFunctionEmulator::IdentifyFunction( return static_cast(function); } +BuiltInFunctionEmulator::TBuiltInFunction +BuiltInFunctionEmulator::IdentifyFunction( + TOperator op, const TType& param1, const TType& param2, const TType& param3) +{ + // Check that all params have the same type, length, + // and that they're not too large. + if (param1.isVector() != param2.isVector() || + param2.isVector() != param3.isVector() || + param1.getNominalSize() != param2.getNominalSize() || + param2.getNominalSize() != param3.getNominalSize() || + param1.getNominalSize() > 4) + return TFunctionUnknown; + + unsigned int function = TFunctionUnknown; + switch (op) { + case EOpFaceForward: + function = TFunctionFaceForward1_1_1; + break; + default: + break; + } + if (function == TFunctionUnknown) + return TFunctionUnknown; + if (param1.isVector()) + function += param1.getNominalSize() - 1; + return static_cast(function); +} + void BuiltInFunctionEmulator::MarkBuiltInFunctionsForEmulation( TIntermNode* root) { diff --git a/gfx/angle/src/compiler/BuiltInFunctionEmulator.h b/gfx/angle/src/compiler/BuiltInFunctionEmulator.h index 0d904f41d09..d70f949f6b2 100644 --- a/gfx/angle/src/compiler/BuiltInFunctionEmulator.h +++ b/gfx/angle/src/compiler/BuiltInFunctionEmulator.h @@ -28,6 +28,8 @@ public: bool SetFunctionCalled(TOperator op, const TType& param); bool SetFunctionCalled( TOperator op, const TType& param1, const TType& param2); + bool SetFunctionCalled( + TOperator op, const TType& param1, const TType& param2, const TType& param3); // Output function emulation definition. This should be before any other // shader source. @@ -60,6 +62,11 @@ private: TFunctionDot3_3, // vec3 dot(vec3, vec3); TFunctionDot4_4, // vec4 dot(vec4, vec4); + TFunctionFaceForward1_1_1, // float faceforward(float, float, float); + TFunctionFaceForward2_2_2, // vec2 faceforward(vec2, vec2, vec2); + TFunctionFaceForward3_3_3, // vec3 faceforward(vec3, vec3, vec3); + TFunctionFaceForward4_4_4, // vec4 faceforward(vec4, vec4, vec4); + TFunctionLength1, // float length(float); TFunctionLength2, // float length(vec2); TFunctionLength3, // float length(vec3); @@ -81,6 +88,8 @@ private: TBuiltInFunction IdentifyFunction(TOperator op, const TType& param); TBuiltInFunction IdentifyFunction( TOperator op, const TType& param1, const TType& param2); + TBuiltInFunction IdentifyFunction( + TOperator op, const TType& param1, const TType& param2, const TType& param3); bool SetFunctionCalled(TBuiltInFunction function); From c19040d78a86a69b89ddc8913d46cd3d8dfcb2c7 Mon Sep 17 00:00:00 2001 From: Jeff Gilbert Date: Fri, 14 Sep 2012 16:02:40 -0700 Subject: [PATCH 02/11] Bug 771406 - Add previous patch to ANGLE patch list - r=bjacob --- gfx/angle/README.mozilla | 4 + gfx/angle/angle-faceforward-emu.patch | 314 ++++++++++++++++++++++++++ 2 files changed, 318 insertions(+) create mode 100644 gfx/angle/angle-faceforward-emu.patch diff --git a/gfx/angle/README.mozilla b/gfx/angle/README.mozilla index 410ce1328b5..d0d22328664 100644 --- a/gfx/angle/README.mozilla +++ b/gfx/angle/README.mozilla @@ -28,6 +28,10 @@ In this order: see bug 680840. Probably not useful anymore now that we're on the new preprocessor, but it doesn't hurt to keep it around a bit longer. + angle-faceforward-emu.patch + See bug 771406. Adds emulation for faceforward(float,float,float), + which is needed to prevent crashing on Mac+Intel. + In addition to these patches, the Makefile.in files are ours, they're not present in upsteam ANGLE. Therefore, changes made to the Makefile.in files should not be stored in the local .patch files. diff --git a/gfx/angle/angle-faceforward-emu.patch b/gfx/angle/angle-faceforward-emu.patch new file mode 100644 index 00000000000..c064d77c458 --- /dev/null +++ b/gfx/angle/angle-faceforward-emu.patch @@ -0,0 +1,314 @@ +From: Jeff Gilbert +Bug 771406 - Add emulation for GLSL faceforward() to ANGLE - r=bjacob + +diff --git a/gfx/angle/src/compiler/BuiltInFunctionEmulator.cpp b/gfx/angle/src/compiler/BuiltInFunctionEmulator.cpp +--- a/gfx/angle/src/compiler/BuiltInFunctionEmulator.cpp ++++ b/gfx/angle/src/compiler/BuiltInFunctionEmulator.cpp +@@ -26,16 +26,22 @@ const char* kFunctionEmulationVertexSour + "#error no emulation for distance(vec3, vec3)", + "#error no emulation for distance(vec4, vec4)", + + "#define webgl_dot_emu(x, y) ((x) * (y))", + "#error no emulation for dot(vec2, vec2)", + "#error no emulation for dot(vec3, vec3)", + "#error no emulation for dot(vec4, vec4)", + ++ // |faceforward(N, I, Nref)| is |dot(NRef, I) < 0 ? N : -N| ++ "#define webgl_faceforward_emu(N, I, Nref) (((Nref) * (I) < 0.0) ? (N) : -(N))", ++ "#error no emulation for faceforward(vec2, vec2, vec2)", ++ "#error no emulation for faceforward(vec3, vec3, vec3)", ++ "#error no emulation for faceforward(vec4, vec4, vec4)", ++ + "#define webgl_length_emu(x) ((x) >= 0.0 ? (x) : -(x))", + "#error no emulation for length(vec2)", + "#error no emulation for length(vec3)", + "#error no emulation for length(vec4)", + + "#define webgl_normalize_emu(x) ((x) == 0.0 ? 0.0 : ((x) > 0.0 ? 1.0 : -1.0))", + "#error no emulation for normalize(vec2)", + "#error no emulation for normalize(vec3)", +@@ -58,16 +64,22 @@ const char* kFunctionEmulationFragmentSo + "#error no emulation for distance(vec3, vec3)", + "#error no emulation for distance(vec4, vec4)", + + "#define webgl_dot_emu(x, y) ((x) * (y))", + "#error no emulation for dot(vec2, vec2)", + "#error no emulation for dot(vec3, vec3)", + "#error no emulation for dot(vec4, vec4)", + ++ // |faceforward(N, I, Nref)| is |dot(NRef, I) < 0 ? N : -N| ++ "#define webgl_faceforward_emu(N, I, Nref) (((Nref) * (I) < 0.0) ? (N) : -(N))", ++ "#error no emulation for faceforward(vec2, vec2, vec2)", ++ "#error no emulation for faceforward(vec3, vec3, vec3)", ++ "#error no emulation for faceforward(vec4, vec4, vec4)", ++ + "#define webgl_length_emu(x) ((x) >= 0.0 ? (x) : -(x))", + "#error no emulation for length(vec2)", + "#error no emulation for length(vec3)", + "#error no emulation for length(vec4)", + + "#define webgl_normalize_emu(x) ((x) == 0.0 ? 0.0 : ((x) > 0.0 ? 1.0 : -1.0))", + "#error no emulation for normalize(vec2)", + "#error no emulation for normalize(vec3)", +@@ -89,16 +101,20 @@ const bool kFunctionEmulationVertexMask[ + true, // TFunctionDistance1_1 + false, // TFunctionDistance2_2 + false, // TFunctionDistance3_3 + false, // TFunctionDistance4_4 + true, // TFunctionDot1_1 + false, // TFunctionDot2_2 + false, // TFunctionDot3_3 + false, // TFunctionDot4_4 ++ true, // TFunctionFaceForward1_1_1 ++ false, // TFunctionFaceForward2_2_2 ++ false, // TFunctionFaceForward3_3_3 ++ false, // TFunctionFaceForward4_4_4 + true, // TFunctionLength1 + false, // TFunctionLength2 + false, // TFunctionLength3 + false, // TFunctionLength4 + true, // TFunctionNormalize1 + false, // TFunctionNormalize2 + false, // TFunctionNormalize3 + false, // TFunctionNormalize4 +@@ -115,16 +131,20 @@ const bool kFunctionEmulationVertexMask[ + false, // TFunctionDistance1_1 + false, // TFunctionDistance2_2 + false, // TFunctionDistance3_3 + false, // TFunctionDistance4_4 + false, // TFunctionDot1_1 + false, // TFunctionDot2_2 + false, // TFunctionDot3_3 + false, // TFunctionDot4_4 ++ false, // TFunctionFaceForward1_1_1 ++ false, // TFunctionFaceForward2_2_2 ++ false, // TFunctionFaceForward3_3_3 ++ false, // TFunctionFaceForward4_4_4 + false, // TFunctionLength1 + false, // TFunctionLength2 + false, // TFunctionLength3 + false, // TFunctionLength4 + false, // TFunctionNormalize1 + false, // TFunctionNormalize2 + false, // TFunctionNormalize3 + false, // TFunctionNormalize4 +@@ -146,16 +166,20 @@ const bool kFunctionEmulationFragmentMas + true, // TFunctionDistance1_1 + false, // TFunctionDistance2_2 + false, // TFunctionDistance3_3 + false, // TFunctionDistance4_4 + true, // TFunctionDot1_1 + false, // TFunctionDot2_2 + false, // TFunctionDot3_3 + false, // TFunctionDot4_4 ++ true, // TFunctionFaceForward1_1_1 ++ false, // TFunctionFaceForward2_2_2 ++ false, // TFunctionFaceForward3_3_3 ++ false, // TFunctionFaceForward4_4_4 + true, // TFunctionLength1 + false, // TFunctionLength2 + false, // TFunctionLength3 + false, // TFunctionLength4 + true, // TFunctionNormalize1 + false, // TFunctionNormalize2 + false, // TFunctionNormalize3 + false, // TFunctionNormalize4 +@@ -172,16 +196,20 @@ const bool kFunctionEmulationFragmentMas + false, // TFunctionDistance1_1 + false, // TFunctionDistance2_2 + false, // TFunctionDistance3_3 + false, // TFunctionDistance4_4 + false, // TFunctionDot1_1 + false, // TFunctionDot2_2 + false, // TFunctionDot3_3 + false, // TFunctionDot4_4 ++ false, // TFunctionFaceForward1_1_1 ++ false, // TFunctionFaceForward2_2_2 ++ false, // TFunctionFaceForward3_3_3 ++ false, // TFunctionFaceForward4_4_4 + false, // TFunctionLength1 + false, // TFunctionLength2 + false, // TFunctionLength3 + false, // TFunctionLength4 + false, // TFunctionNormalize1 + false, // TFunctionNormalize2 + false, // TFunctionNormalize3 + false, // TFunctionNormalize4 +@@ -239,25 +267,37 @@ public: + case EOpReflect: + case EOpRefract: + case EOpMul: + break; + default: + return true; + }; + const TIntermSequence& sequence = node->getSequence(); +- // Right now we only handle built-in functions with two parameters. +- if (sequence.size() != 2) ++ bool needToEmulate = false; ++ ++ if (sequence.size() == 2) { ++ TIntermTyped* param1 = sequence[0]->getAsTyped(); ++ TIntermTyped* param2 = sequence[1]->getAsTyped(); ++ if (!param1 || !param2) ++ return true; ++ needToEmulate = mEmulator.SetFunctionCalled( ++ node->getOp(), param1->getType(), param2->getType()); ++ } else if (sequence.size() == 3) { ++ TIntermTyped* param1 = sequence[0]->getAsTyped(); ++ TIntermTyped* param2 = sequence[1]->getAsTyped(); ++ TIntermTyped* param3 = sequence[2]->getAsTyped(); ++ if (!param1 || !param2 || !param3) ++ return true; ++ needToEmulate = mEmulator.SetFunctionCalled( ++ node->getOp(), param1->getType(), param2->getType(), param3->getType()); ++ } else { + return true; +- TIntermTyped* param1 = sequence[0]->getAsTyped(); +- TIntermTyped* param2 = sequence[1]->getAsTyped(); +- if (!param1 || !param2) +- return true; +- bool needToEmulate = mEmulator.SetFunctionCalled( +- node->getOp(), param1->getType(), param2->getType()); ++ } ++ + if (needToEmulate) + node->setUseEmulatedFunction(); + } + return true; + } + + private: + BuiltInFunctionEmulator& mEmulator; +@@ -286,16 +326,23 @@ bool BuiltInFunctionEmulator::SetFunctio + bool BuiltInFunctionEmulator::SetFunctionCalled( + TOperator op, const TType& param1, const TType& param2) + { + TBuiltInFunction function = IdentifyFunction(op, param1, param2); + return SetFunctionCalled(function); + } + + bool BuiltInFunctionEmulator::SetFunctionCalled( ++ TOperator op, const TType& param1, const TType& param2, const TType& param3) ++{ ++ TBuiltInFunction function = IdentifyFunction(op, param1, param2, param3); ++ return SetFunctionCalled(function); ++} ++ ++bool BuiltInFunctionEmulator::SetFunctionCalled( + BuiltInFunctionEmulator::TBuiltInFunction function) { + if (function == TFunctionUnknown || mFunctionMask[function] == false) + return false; + for (size_t i = 0; i < mFunctions.size(); ++i) { + if (mFunctions[i] == function) + return true; + } + mFunctions.push_back(function); +@@ -377,16 +424,44 @@ BuiltInFunctionEmulator::IdentifyFunctio + } + if (function == TFunctionUnknown) + return TFunctionUnknown; + if (param1.isVector()) + function += param1.getNominalSize() - 1; + return static_cast(function); + } + ++BuiltInFunctionEmulator::TBuiltInFunction ++BuiltInFunctionEmulator::IdentifyFunction( ++ TOperator op, const TType& param1, const TType& param2, const TType& param3) ++{ ++ // Check that all params have the same type, length, ++ // and that they're not too large. ++ if (param1.isVector() != param2.isVector() || ++ param2.isVector() != param3.isVector() || ++ param1.getNominalSize() != param2.getNominalSize() || ++ param2.getNominalSize() != param3.getNominalSize() || ++ param1.getNominalSize() > 4) ++ return TFunctionUnknown; ++ ++ unsigned int function = TFunctionUnknown; ++ switch (op) { ++ case EOpFaceForward: ++ function = TFunctionFaceForward1_1_1; ++ break; ++ default: ++ break; ++ } ++ if (function == TFunctionUnknown) ++ return TFunctionUnknown; ++ if (param1.isVector()) ++ function += param1.getNominalSize() - 1; ++ return static_cast(function); ++} ++ + void BuiltInFunctionEmulator::MarkBuiltInFunctionsForEmulation( + TIntermNode* root) + { + ASSERT(root); + + BuiltInFunctionEmulationMarker marker(*this); + root->traverse(&marker); + } +diff --git a/gfx/angle/src/compiler/BuiltInFunctionEmulator.h b/gfx/angle/src/compiler/BuiltInFunctionEmulator.h +--- a/gfx/angle/src/compiler/BuiltInFunctionEmulator.h ++++ b/gfx/angle/src/compiler/BuiltInFunctionEmulator.h +@@ -23,16 +23,18 @@ public: + // Records that a function is called by the shader and might needs to be + // emulated. If the function's group is not in mFunctionGroupFilter, this + // becomes an no-op. + // Returns true if the function call needs to be replaced with an emulated + // one. + bool SetFunctionCalled(TOperator op, const TType& param); + bool SetFunctionCalled( + TOperator op, const TType& param1, const TType& param2); ++ bool SetFunctionCalled( ++ TOperator op, const TType& param1, const TType& param2, const TType& param3); + + // Output function emulation definition. This should be before any other + // shader source. + void OutputEmulatedFunctionDefinition(TInfoSinkBase& out, bool withPrecision) const; + + void MarkBuiltInFunctionsForEmulation(TIntermNode* root); + + void Cleanup(); +@@ -55,16 +57,21 @@ private: + TFunctionDistance3_3, // vec3 distance(vec3, vec3); + TFunctionDistance4_4, // vec4 distance(vec4, vec4); + + TFunctionDot1_1, // float dot(float, float); + TFunctionDot2_2, // vec2 dot(vec2, vec2); + TFunctionDot3_3, // vec3 dot(vec3, vec3); + TFunctionDot4_4, // vec4 dot(vec4, vec4); + ++ TFunctionFaceForward1_1_1, // float faceforward(float, float, float); ++ TFunctionFaceForward2_2_2, // vec2 faceforward(vec2, vec2, vec2); ++ TFunctionFaceForward3_3_3, // vec3 faceforward(vec3, vec3, vec3); ++ TFunctionFaceForward4_4_4, // vec4 faceforward(vec4, vec4, vec4); ++ + TFunctionLength1, // float length(float); + TFunctionLength2, // float length(vec2); + TFunctionLength3, // float length(vec3); + TFunctionLength4, // float length(vec4); + + TFunctionNormalize1, // float normalize(float); + TFunctionNormalize2, // vec2 normalize(vec2); + TFunctionNormalize3, // vec3 normalize(vec3); +@@ -76,16 +83,18 @@ private: + TFunctionReflect4_4, // vec4 reflect(vec4, vec4); + + TFunctionUnknown + }; + + TBuiltInFunction IdentifyFunction(TOperator op, const TType& param); + TBuiltInFunction IdentifyFunction( + TOperator op, const TType& param1, const TType& param2); ++ TBuiltInFunction IdentifyFunction( ++ TOperator op, const TType& param1, const TType& param2, const TType& param3); + + bool SetFunctionCalled(TBuiltInFunction function); + + std::vector mFunctions; + + const bool* mFunctionMask; // a boolean flag for each function. + const char** mFunctionSource; + }; From 46f7b4814c0131042cecba6ea03d9764ce6b55ab Mon Sep 17 00:00:00 2001 From: Marshall Culpepper Date: Fri, 14 Sep 2012 18:06:22 -0500 Subject: [PATCH 03/11] Bug 787398: Change B2G update prefs for nightly updates. r=cjones --- b2g/app/b2g.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/b2g/app/b2g.js b/b2g/app/b2g.js index 51b8cb6a395..beaac16af61 100644 --- a/b2g/app/b2g.js +++ b/b2g/app/b2g.js @@ -452,13 +452,13 @@ pref("app.update.staging.enabled", true); pref("app.update.service.enabled", true); // The URL hosting the update manifest. -pref("app.update.url", "http://update.boot2gecko.org/m2.5/updates.xml"); +pref("app.update.url", "http://update.boot2gecko.org/nightly/update.xml"); // Interval at which update manifest is fetched. In units of seconds. -pref("app.update.interval", 3600); // 1 hour +pref("app.update.interval", 86400); // 1 day // First interval to elapse before checking for update. In units of // milliseconds. Capped at 10 seconds. -pref("app.update.timerFirstInterval", 30000); -pref("app.update.timerMinimumDelay", 30); // seconds +pref("app.update.timerFirstInterval", 3600000); // 1 hour +pref("app.update.timerMinimumDelay", 3600); // 1 hour in seconds // Don't throttle background updates. pref("app.update.download.backgroundInterval", 0); From 43b37007df80680b6d12c1769e32bcc1ced596e4 Mon Sep 17 00:00:00 2001 From: Devdatta Akhawe Date: Thu, 13 Sep 2012 20:36:35 -0700 Subject: [PATCH 04/11] Bug 790747 Move CSP code to before principal reset (r=bz) --- content/base/src/nsDocument.cpp | 78 ++++++++++++++++----------------- content/base/src/nsDocument.h | 2 +- 2 files changed, 38 insertions(+), 42 deletions(-) diff --git a/content/base/src/nsDocument.cpp b/content/base/src/nsDocument.cpp index c214d1719b9..8319f87afc9 100644 --- a/content/base/src/nsDocument.cpp +++ b/content/base/src/nsDocument.cpp @@ -2394,6 +2394,9 @@ nsDocument::StartDocumentLoad(const char* aCommand, nsIChannel* aChannel, mMayStartLayout = false; mHaveInputEncoding = true; + nsCOMPtr csp; + nsresult rv = InitCSP(aChannel, getter_AddRefs(csp)); + NS_ENSURE_SUCCESS(rv, rv); if (aReset) { Reset(aChannel, aLoadGroup); @@ -2423,29 +2426,39 @@ nsDocument::StartDocumentLoad(const char* aCommand, nsIChannel* aChannel, NS_ENSURE_SUCCESS(rv, rv); } - nsresult rv = InitCSP(); - NS_ENSURE_SUCCESS(rv, rv); + if (csp) { + // Copy into principal + nsIPrincipal* principal = GetPrincipal(); + principal->SetCsp(csp); +#ifdef PR_LOGGING + PR_LOG(gCspPRLog, PR_LOG_DEBUG, + ("Inserted CSP into principal %p", principal)); +#endif + } return NS_OK; } nsresult -nsDocument::InitCSP() +nsDocument::InitCSP(nsIChannel* aChannel, nsIContentSecurityPolicy **aCSP) { + *aCSP = nullptr; if (CSPService::sCSPEnabled) { - nsAutoString cspHeaderValue; - nsAutoString cspROHeaderValue; - - this->GetHeaderData(nsGkAtoms::headerCSP, cspHeaderValue); - this->GetHeaderData(nsGkAtoms::headerCSPReportOnly, cspROHeaderValue); - - bool system = false; - nsIScriptSecurityManager *ssm = nsContentUtils::GetSecurityManager(); - - if (NS_SUCCEEDED(ssm->IsSystemPrincipal(NodePrincipal(), &system)) && system) { - // only makes sense to register new CSP if this document is not priviliged + nsAutoCString tCspHeaderValue, tCspROHeaderValue; + nsCOMPtr httpChannel = do_QueryInterface(aChannel); + if (!httpChannel) { + // no CSP for non http channels return NS_OK; } + httpChannel->GetResponseHeader( + NS_LITERAL_CSTRING("x-content-security-policy"), + tCspHeaderValue); + + httpChannel->GetResponseHeader( + NS_LITERAL_CSTRING("x-content-security-policy-report-only"), + tCspROHeaderValue); + NS_ConvertASCIItoUTF16 cspHeaderValue(tCspHeaderValue); + NS_ConvertASCIItoUTF16 cspROHeaderValue(tCspROHeaderValue); if (cspHeaderValue.IsEmpty() && cspROHeaderValue.IsEmpty()) { // no CSP header present, stop processing @@ -2457,8 +2470,8 @@ nsDocument::InitCSP() #endif nsresult rv; - nsCOMPtr mCSP; - mCSP = do_CreateInstance("@mozilla.org/contentsecuritypolicy;1", &rv); + nsCOMPtr csp; + csp = do_CreateInstance("@mozilla.org/contentsecuritypolicy;1", &rv); if (NS_FAILED(rv)) { #ifdef PR_LOGGING @@ -2468,12 +2481,11 @@ nsDocument::InitCSP() } // Store the request context for violation reports - nsCOMPtr httpChannel = do_QueryInterface(mChannel); - mCSP->ScanRequestData(httpChannel); + csp->ScanRequestData(httpChannel); // Start parsing the policy nsCOMPtr chanURI; - mChannel->GetURI(getter_AddRefs(chanURI)); + aChannel->GetURI(getter_AddRefs(chanURI)); #ifdef PR_LOGGING PR_LOG(gCspPRLog, PR_LOG_DEBUG, ("CSP Loaded")); @@ -2484,7 +2496,7 @@ nsDocument::InitCSP() // toss a warning into the error console, proceeding with enforcing the // regular-strength CSP. if (cspHeaderValue.IsEmpty()) { - mCSP->SetReportOnlyMode(true); + csp->SetReportOnlyMode(true); // Need to tokenize the header value since multiple headers could be // concatenated into one comma-separated list of policies. @@ -2492,7 +2504,7 @@ nsDocument::InitCSP() nsCharSeparatedTokenizer tokenizer(cspROHeaderValue, ','); while (tokenizer.hasMoreTokens()) { const nsSubstring& policy = tokenizer.nextToken(); - mCSP->RefinePolicy(policy, chanURI); + csp->RefinePolicy(policy, chanURI); #ifdef PR_LOGGING { PR_LOG(gCspPRLog, PR_LOG_DEBUG, @@ -2511,7 +2523,7 @@ nsDocument::InitCSP() nsCharSeparatedTokenizer tokenizer(cspHeaderValue, ','); while (tokenizer.hasMoreTokens()) { const nsSubstring& policy = tokenizer.nextToken(); - mCSP->RefinePolicy(policy, chanURI); + csp->RefinePolicy(policy, chanURI); #ifdef PR_LOGGING { PR_LOG(gCspPRLog, PR_LOG_DEBUG, @@ -2528,7 +2540,7 @@ nsDocument::InitCSP() bool safeAncestry = false; // PermitsAncestry sends violation reports when necessary - rv = mCSP->PermitsAncestry(docShell, &safeAncestry); + rv = csp->PermitsAncestry(docShell, &safeAncestry); NS_ENSURE_SUCCESS(rv, rv); if (!safeAncestry) { @@ -2537,24 +2549,10 @@ nsDocument::InitCSP() ("CSP doesn't like frame's ancestry, not loading.")); #endif // stop! ERROR page! - mChannel->Cancel(NS_ERROR_CSP_FRAME_ANCESTOR_VIOLATION); + aChannel->Cancel(NS_ERROR_CSP_FRAME_ANCESTOR_VIOLATION); } } - - //Copy into principal - nsIPrincipal* principal = GetPrincipal(); - - if (principal) { - principal->SetCsp(mCSP); -#ifdef PR_LOGGING - PR_LOG(gCspPRLog, PR_LOG_DEBUG, - ("Inserted CSP into principal %p", principal)); - } - else { - PR_LOG(gCspPRLog, PR_LOG_DEBUG, - ("Couldn't copy CSP into absent principal %p", principal)); -#endif - } + csp.forget(aCSP); } #ifdef PR_LOGGING else { //CSP was not enabled! @@ -6791,8 +6789,6 @@ nsDocument::RetrieveRelevantHeaders(nsIChannel *aChannel) "content-disposition", "refresh", "x-dns-prefetch-control", - "x-content-security-policy", - "x-content-security-policy-report-only", "x-frame-options", // add more http headers if you need // XXXbz don't add content-location support without reading bug diff --git a/content/base/src/nsDocument.h b/content/base/src/nsDocument.h index f46f33b6435..13d6cd57a20 100644 --- a/content/base/src/nsDocument.h +++ b/content/base/src/nsDocument.h @@ -1274,7 +1274,7 @@ private: void DoUnblockOnload(); nsresult CheckFrameOptions(); - nsresult InitCSP(); + nsresult InitCSP(nsIChannel* aChannel, nsIContentSecurityPolicy **aCSP); // Sets aElement to be the pending pointer lock element. Once this document's // node principal's URI is granted the "fullscreen" permission, the pointer From fd2fa1f6ef10dce2f02f789a5efaff4a97b0d14e Mon Sep 17 00:00:00 2001 From: Bill McCloskey Date: Fri, 14 Sep 2012 16:20:04 -0700 Subject: [PATCH 05/11] Bug 791376 - Simplify JSObject::swap (r=bholley) --- js/src/jsobj.cpp | 44 +++++--------------------------------------- 1 file changed, 5 insertions(+), 39 deletions(-) diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp index 238b52ece8a..ac11866e7e4 100644 --- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -2898,53 +2898,19 @@ JSObject::TradeGuts(JSContext *cx, JSObject *a, JSObject *b, TradeGutsReserved & b->type_ = tmp; } -/* - * Use this method with extreme caution. It trades the guts of two objects and updates - * scope ownership. This operation is not thread-safe, just as fast array to slow array - * transitions are inherently not thread-safe. Don't perform a swap operation on objects - * shared across threads or, or bad things will happen. You have been warned. - */ +/* Use this method with extreme caution. It trades the guts of two objects. */ bool JSObject::swap(JSContext *cx, JSObject *other) { // Ensure swap doesn't cause a finalizer to not be run. JS_ASSERT(IsBackgroundFinalized(getAllocKind()) == IsBackgroundFinalized(other->getAllocKind())); + JS_ASSERT(compartment() == other->compartment()); - if (this->compartment() == other->compartment()) { - TradeGutsReserved reserved(cx); - if (!ReserveForTradeGuts(cx, this, other, reserved)) - return false; - TradeGuts(cx, this, other, reserved); - return true; - } - - JSObject *thisClone; - JSObject *otherClone; - { - AutoCompartment ac(cx, other); - thisClone = JS_CloneObject(cx, this, other->getProto(), other->getParent()); - if (!thisClone || !JS_CopyPropertiesFrom(cx, thisClone, this)) - return false; - } - { - AutoCompartment ac(cx, this); - otherClone = JS_CloneObject(cx, other, other->getProto(), other->getParent()); - if (!otherClone || !JS_CopyPropertiesFrom(cx, otherClone, other)) - return false; - } - - TradeGutsReserved reservedThis(cx); - TradeGutsReserved reservedOther(cx); - - if (!ReserveForTradeGuts(cx, this, otherClone, reservedThis) || - !ReserveForTradeGuts(cx, other, thisClone, reservedOther)) { + TradeGutsReserved reserved(cx); + if (!ReserveForTradeGuts(cx, this, other, reserved)) return false; - } - - TradeGuts(cx, this, otherClone, reservedThis); - TradeGuts(cx, other, thisClone, reservedOther); - + TradeGuts(cx, this, other, reserved); return true; } From 65fb8be76c4657b322b01c63dd62dee60b21bff1 Mon Sep 17 00:00:00 2001 From: Bill McCloskey Date: Fri, 14 Sep 2012 16:23:43 -0700 Subject: [PATCH 06/11] Bug 791371 - IonMonkey: ContextStack::currentScript needs check (r=dvander) --- js/src/vm/Stack-inl.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/js/src/vm/Stack-inl.h b/js/src/vm/Stack-inl.h index dd2a87d6844..7304799f202 100644 --- a/js/src/vm/Stack-inl.h +++ b/js/src/vm/Stack-inl.h @@ -531,6 +531,8 @@ ContextStack::currentScript(jsbytecode **ppc) const if (fp->beginsIonActivation()) { JSScript *script = NULL; ion::GetPcScript(cx_, &script, ppc); + if (script->compartment() != cx_->compartment) + return NULL; return script; } #endif From 975e0736e957ccaafa9cfaab7c8b4c7a9a585109 Mon Sep 17 00:00:00 2001 From: Bill McCloskey Date: Fri, 14 Sep 2012 17:19:53 -0700 Subject: [PATCH 07/11] Bug 790865 - Add more compartment assertions (r=terrence) --- js/src/jsgc.cpp | 69 +++++++++++++++++++++++++++++++++++++++++++ js/src/jsinfer.cpp | 11 +++++++ js/src/jsobj.cpp | 3 ++ js/src/jsobjinlines.h | 5 ++++ js/src/jsproxy.cpp | 1 + js/src/jsscope.cpp | 4 +++ 6 files changed, 93 insertions(+) diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp index b3a60f73016..27fac3f7ff4 100644 --- a/js/src/jsgc.cpp +++ b/js/src/jsgc.cpp @@ -3273,11 +3273,80 @@ ShouldPreserveJITCode(JSCompartment *c, int64_t currentTime) return false; } +#ifdef DEBUG +struct CompartmentCheckTracer : public JSTracer +{ + Cell *src; + JSGCTraceKind srcKind; + JSCompartment *compartment; +}; + +static bool +InCrossCompartmentMap(JSObject *src, Cell *dst, JSGCTraceKind dstKind) +{ + JSCompartment *srccomp = src->compartment(); + + if (dstKind == JSTRACE_OBJECT) { + Value key = ObjectValue(*static_cast(dst)); + WrapperMap::Ptr p = srccomp->crossCompartmentWrappers.lookup(key); + if (*p->value.unsafeGet() == ObjectValue(*src)) + return true; + } + + /* + * If the cross-compartment edge is caused by the debugger, then we don't + * know the right hashtable key, so we have to iterate. + */ + for (WrapperMap::Enum e(srccomp->crossCompartmentWrappers); !e.empty(); e.popFront()) { + if (e.front().key.wrapped == dst && ToMarkable(e.front().value) == src) + return true; + } + + return false; +} + +static void +CheckCompartmentCallback(JSTracer *trcArg, void **thingp, JSGCTraceKind kind) +{ + CompartmentCheckTracer *trc = static_cast(trcArg); + Cell *thing = (Cell *)*thingp; + JS_ASSERT(thing->compartment() == trc->compartment || + thing->compartment() == trc->runtime->atomsCompartment || + (trc->srcKind == JSTRACE_OBJECT && + InCrossCompartmentMap((JSObject *)trc->src, thing, kind))); +} + +static void +CheckForCompartmentMismatches(JSRuntime *rt) +{ + if (rt->gcDisableStrictProxyCheckingCount) + return; + + CompartmentCheckTracer trc; + JS_TracerInit(&trc, rt, CheckCompartmentCallback); + + for (CompartmentsIter c(rt); !c.done(); c.next()) { + trc.compartment = c; + for (size_t thingKind = 0; thingKind < FINALIZE_LAST; thingKind++) { + for (CellIterUnderGC i(c, AllocKind(thingKind)); !i.done(); i.next()) { + trc.src = i.getCell(); + trc.srcKind = MapAllocToTraceKind(AllocKind(thingKind)); + JS_TraceChildren(&trc, trc.src, trc.srcKind); + } + } + } +} +#endif + static void BeginMarkPhase(JSRuntime *rt) { int64_t currentTime = PRMJ_Now(); +#ifdef DEBUG + CheckForCompartmentMismatches(rt); +#endif + rt->gcIsFull = true; DebugOnly any = false; for (CompartmentsIter c(rt); !c.done(); c.next()) { diff --git a/js/src/jsinfer.cpp b/js/src/jsinfer.cpp index 648d686bc6d..bb0b6ac876b 100644 --- a/js/src/jsinfer.cpp +++ b/js/src/jsinfer.cpp @@ -2063,6 +2063,9 @@ TypeCompartment::newTypeObject(JSContext *cx, JSScript *script, JSProtoKey key, JSObject *proto_, bool unknown, bool isDOM) { + JS_ASSERT_IF(script, cx->compartment == script->compartment()); + JS_ASSERT_IF(proto_, cx->compartment == proto_->compartment()); + RootedObject proto(cx, proto_); TypeObject *object = gc::NewGCThing(cx, gc::FINALIZE_TYPE_OBJECT, sizeof(TypeObject)); if (!object) @@ -5579,6 +5582,8 @@ JSObject::shouldSplicePrototype(JSContext *cx) bool JSObject::splicePrototype(JSContext *cx, JSObject *proto_) { + JS_ASSERT(cx->compartment == compartment()); + RootedObject proto(cx, proto_); RootedObject self(cx, this); @@ -5639,6 +5644,7 @@ TypeObject * JSObject::makeLazyType(JSContext *cx) { JS_ASSERT(hasLazyType()); + JS_ASSERT(cx->compartment == compartment()); RootedObject self(cx, this); JSProtoKey key = JSCLASS_CACHED_PROTO_KEY(getClass()); @@ -5749,6 +5755,8 @@ JSObject::setNewTypeUnknown(JSContext *cx) TypeObject * JSObject::getNewType(JSContext *cx, JSFunction *fun_, bool isDOM) { + JS_ASSERT(cx->compartment == compartment()); + TypeObjectSet &table = cx->compartment->newTypeObjects; if (!table.initialized() && !table.init()) @@ -5837,6 +5845,9 @@ JSObject::getNewType(JSContext *cx, JSFunction *fun_, bool isDOM) TypeObject * JSCompartment::getLazyType(JSContext *cx, JSObject *proto_) { + JS_ASSERT(cx->compartment == this); + JS_ASSERT_IF(proto_, cx->compartment == proto_->compartment()); + RootedObject proto(cx, proto_); MaybeCheckStackRoots(cx); diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp index ac11866e7e4..e023188ab21 100644 --- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -2660,6 +2660,9 @@ bool JSObject::ReserveForTradeGuts(JSContext *cx, JSObject *a, JSObject *b, TradeGutsReserved &reserved) { + JS_ASSERT(a->compartment() == b->compartment()); + AutoCompartment ac(cx, a); + /* * When performing multiple swaps between objects which may have different * numbers of fixed slots, we reserve all space ahead of time so that the diff --git a/js/src/jsobjinlines.h b/js/src/jsobjinlines.h index a3078db662c..1e87265c022 100644 --- a/js/src/jsobjinlines.h +++ b/js/src/jsobjinlines.h @@ -663,6 +663,7 @@ JSObject::setSingletonType(JSContext *cx, js::HandleObject obj) inline js::types::TypeObject * JSObject::getType(JSContext *cx) { + JS_ASSERT(cx->compartment == compartment()); if (hasLazyType()) return makeLazyType(cx); return type_; @@ -672,6 +673,7 @@ JSObject::getType(JSContext *cx) JSObject::clearType(JSContext *cx, js::HandleObject obj) { JS_ASSERT(!obj->hasSingletonType()); + JS_ASSERT(cx->compartment == obj->compartment()); js::types::TypeObject *type = cx->compartment->getEmptyType(cx); if (!type) @@ -692,6 +694,7 @@ JSObject::setType(js::types::TypeObject *newType) JS_ASSERT_IF(hasSpecialEquality(), newType->hasAnyFlags(js::types::OBJECT_FLAG_SPECIAL_EQUALITY)); JS_ASSERT(!hasSingletonType()); + JS_ASSERT(compartment() == newType->compartment()); type_ = newType; } @@ -824,6 +827,7 @@ JSObject::create(JSContext *cx, js::gc::AllocKind kind, JS_ASSERT(shape && type); JS_ASSERT(!!dynamicSlotsCount(shape->numFixedSlots(), shape->slotSpan()) == !!slots); JS_ASSERT(js::gc::GetGCKindSlots(kind, shape->getObjectClass()) == shape->numFixedSlots()); + JS_ASSERT(cx->compartment == type->compartment()); JSObject *obj = js_NewGCObject(cx, kind); if (!obj) @@ -852,6 +856,7 @@ JSObject::createDenseArray(JSContext *cx, js::gc::AllocKind kind, { JS_ASSERT(shape && type); JS_ASSERT(shape->getObjectClass() == &js::ArrayClass); + JS_ASSERT(cx->compartment == type->compartment()); /* * Dense arrays are non-native, and never have properties to store. diff --git a/js/src/jsproxy.cpp b/js/src/jsproxy.cpp index 86253bbbb82..4cd8e6098be 100644 --- a/js/src/jsproxy.cpp +++ b/js/src/jsproxy.cpp @@ -3059,6 +3059,7 @@ js::NewProxyObject(JSContext *cx, BaseProxyHandler *handler, const Value &priv_, JS_ASSERT_IF(proto, cx->compartment == proto->compartment()); JS_ASSERT_IF(parent, cx->compartment == parent->compartment()); JS_ASSERT_IF(construct, cx->compartment == construct->compartment()); + JS_ASSERT_IF(call && cx->compartment != call->compartment(), priv.get() == ObjectValue(*call)); bool fun = call || construct; Class *clasp; if (fun) diff --git a/js/src/jsscope.cpp b/js/src/jsscope.cpp index 43fa8b0788a..0cc4e86d9b0 100644 --- a/js/src/jsscope.cpp +++ b/js/src/jsscope.cpp @@ -928,6 +928,7 @@ JSObject::rollbackProperties(JSContext *cx, uint32_t slotSpan) Shape * JSObject::replaceWithNewEquivalentShape(JSContext *cx, Shape *oldShape, Shape *newShape) { + JS_ASSERT(cx->compartment == oldShape->compartment()); JS_ASSERT_IF(oldShape != lastProperty(), inDictionaryMode() && nativeLookupNoAllocation(oldShape->propidRef()) == oldShape); @@ -1202,6 +1203,9 @@ InitialShapeEntry::match(const InitialShapeEntry &key, const Lookup &lookup) EmptyShape::getInitialShape(JSContext *cx, Class *clasp, JSObject *proto, JSObject *parent, AllocKind kind, uint32_t objectFlags) { + JS_ASSERT_IF(proto, cx->compartment == proto->compartment()); + JS_ASSERT_IF(parent, cx->compartment == parent->compartment()); + InitialShapeSet &table = cx->compartment->initialShapes; if (!table.initialized() && !table.init()) From 2d4610aea1946d4b454d0a75d28a14ee25352be9 Mon Sep 17 00:00:00 2001 From: Doug Sherk Date: Fri, 14 Sep 2012 21:16:32 -0400 Subject: [PATCH 08/11] Bug 787549 - B2G: Stop simulating mouse events unless there's a tap. r=cjones --- dom/ipc/PBrowser.ipdl | 7 ++ dom/ipc/TabChild.cpp | 99 ++++++++++++++--------- dom/ipc/TabChild.h | 4 + dom/ipc/TabParent.cpp | 5 ++ dom/ipc/TabParent.h | 1 + gfx/layers/ipc/AsyncPanZoomController.cpp | 12 ++- gfx/layers/ipc/GeckoContentController.h | 7 ++ layout/ipc/RenderFrameParent.cpp | 17 ++++ 8 files changed, 111 insertions(+), 41 deletions(-) diff --git a/dom/ipc/PBrowser.ipdl b/dom/ipc/PBrowser.ipdl index e00924b66f1..daf7715f6b7 100644 --- a/dom/ipc/PBrowser.ipdl +++ b/dom/ipc/PBrowser.ipdl @@ -292,6 +292,13 @@ child: */ HandleDoubleTap(nsIntPoint point); + /** + * Requests handling of a single tap. |point| is in CSS pixels, relative to + * the scroll offset. This message is expected to send a "mousedown" and + * "mouseup" series of events at this point. + */ + HandleSingleTap(nsIntPoint point); + /** * Sending an activate message moves focus to the child. */ diff --git a/dom/ipc/TabChild.cpp b/dom/ipc/TabChild.cpp index 9e13e061528..f9c7cd0233f 100644 --- a/dom/ipc/TabChild.cpp +++ b/dom/ipc/TabChild.cpp @@ -888,6 +888,19 @@ TabChild::RecvHandleDoubleTap(const nsIntPoint& aPoint) return true; } +bool +TabChild::RecvHandleSingleTap(const nsIntPoint& aPoint) +{ + if (!mCx || !mTabChildGlobal) { + return true; + } + + RecvMouseEvent(NS_LITERAL_STRING("mousedown"), aPoint.x, aPoint.y, 0, 1, 0, false); + RecvMouseEvent(NS_LITERAL_STRING("mouseup"), aPoint.x, aPoint.y, 0, 1, 0, false); + + return true; +} + bool TabChild::RecvActivate() { @@ -936,61 +949,67 @@ TabChild::RecvMouseWheelEvent(const WheelEvent& event) return true; } +void +TabChild::DispatchSynthesizedMouseEvent(const nsTouchEvent& aEvent) +{ + // Synthesize a phony mouse event. + uint32_t msg; + switch (aEvent.message) { + case NS_TOUCH_START: + msg = NS_MOUSE_BUTTON_DOWN; + break; + case NS_TOUCH_MOVE: + msg = NS_MOUSE_MOVE; + break; + case NS_TOUCH_END: + case NS_TOUCH_CANCEL: + msg = NS_MOUSE_BUTTON_UP; + break; + default: + MOZ_NOT_REACHED("Unknown touch event message"); + } + + nsIntPoint refPoint(0, 0); + if (aEvent.touches.Length()) { + refPoint = aEvent.touches[0]->mRefPoint; + } + + nsMouseEvent event(true, msg, NULL, + nsMouseEvent::eReal, nsMouseEvent::eNormal); + event.refPoint = refPoint; + event.time = aEvent.time; + event.button = nsMouseEvent::eLeftButton; + if (msg != NS_MOUSE_MOVE) { + event.clickCount = 1; + } + + DispatchWidgetEvent(event); +} + bool TabChild::RecvRealTouchEvent(const nsTouchEvent& aEvent) { - nsTouchEvent localEvent(aEvent); - nsEventStatus status = DispatchWidgetEvent(localEvent); + nsTouchEvent localEvent(aEvent); + nsEventStatus status = DispatchWidgetEvent(localEvent); + if (IsAsyncPanZoomEnabled()) { nsCOMPtr outerWindow = do_GetInterface(mWebNav); nsCOMPtr innerWindow = outerWindow->GetCurrentInnerWindow(); + if (innerWindow && innerWindow->HasTouchEventListeners()) { SendContentReceivedTouch(nsIPresShell::gPreventMouseEvents); } + } else if (status != nsEventStatus_eConsumeNoDefault) { + DispatchSynthesizedMouseEvent(aEvent); + } - if (status == nsEventStatus_eConsumeNoDefault) { - return true; - } - - // Synthesize a phony mouse event. - uint32_t msg; - switch (aEvent.message) { - case NS_TOUCH_START: - msg = NS_MOUSE_BUTTON_DOWN; - break; - case NS_TOUCH_MOVE: - msg = NS_MOUSE_MOVE; - break; - case NS_TOUCH_END: - case NS_TOUCH_CANCEL: - msg = NS_MOUSE_BUTTON_UP; - break; - default: - MOZ_NOT_REACHED("Unknown touch event message"); - } - - nsIntPoint refPoint(0, 0); - if (aEvent.touches.Length()) { - refPoint = aEvent.touches[0]->mRefPoint; - } - - nsMouseEvent event(true, msg, NULL, - nsMouseEvent::eReal, nsMouseEvent::eNormal); - event.refPoint = refPoint; - event.time = aEvent.time; - event.button = nsMouseEvent::eLeftButton; - if (msg != NS_MOUSE_MOVE) { - event.clickCount = 1; - } - - DispatchWidgetEvent(event); - return true; + return true; } bool TabChild::RecvRealTouchMoveEvent(const nsTouchEvent& aEvent) { - return RecvRealTouchEvent(aEvent); + return RecvRealTouchEvent(aEvent); } bool diff --git a/dom/ipc/TabChild.h b/dom/ipc/TabChild.h index 00016c11ebb..fdaae34a1ac 100644 --- a/dom/ipc/TabChild.h +++ b/dom/ipc/TabChild.h @@ -183,6 +183,7 @@ public: virtual bool RecvUpdateDimensions(const nsRect& rect, const nsIntSize& size); virtual bool RecvUpdateFrame(const mozilla::layers::FrameMetrics& aFrameMetrics); virtual bool RecvHandleDoubleTap(const nsIntPoint& aPoint); + virtual bool RecvHandleSingleTap(const nsIntPoint& aPoint); virtual bool RecvActivate(); virtual bool RecvDeactivate(); virtual bool RecvMouseEvent(const nsString& aType, @@ -323,6 +324,9 @@ private: void DispatchMessageManagerMessage(const nsAString& aMessageName, const nsACString& aJSONData); + // Sends a simulated mouse event from a touch event for compatibility. + void DispatchSynthesizedMouseEvent(const nsTouchEvent& aEvent); + nsresult BrowserFrameProvideWindow(nsIDOMWindow* aOpener, nsIURI* aURI, diff --git a/dom/ipc/TabParent.cpp b/dom/ipc/TabParent.cpp index 48489552a03..94018ef3b79 100644 --- a/dom/ipc/TabParent.cpp +++ b/dom/ipc/TabParent.cpp @@ -252,6 +252,11 @@ void TabParent::HandleDoubleTap(const nsIntPoint& aPoint) unused << SendHandleDoubleTap(aPoint); } +void TabParent::HandleSingleTap(const nsIntPoint& aPoint) +{ + unused << SendHandleSingleTap(aPoint); +} + void TabParent::Activate() { diff --git a/dom/ipc/TabParent.h b/dom/ipc/TabParent.h index 22ebd186a5a..74bd7f80e5c 100644 --- a/dom/ipc/TabParent.h +++ b/dom/ipc/TabParent.h @@ -152,6 +152,7 @@ public: void UpdateDimensions(const nsRect& rect, const nsIntSize& size); void UpdateFrame(const layers::FrameMetrics& aFrameMetrics); void HandleDoubleTap(const nsIntPoint& aPoint); + void HandleSingleTap(const nsIntPoint& aPoint); void Activate(); void Deactivate(); diff --git a/gfx/layers/ipc/AsyncPanZoomController.cpp b/gfx/layers/ipc/AsyncPanZoomController.cpp index 51a27a1c488..216e5d5ae7a 100644 --- a/gfx/layers/ipc/AsyncPanZoomController.cpp +++ b/gfx/layers/ipc/AsyncPanZoomController.cpp @@ -524,7 +524,15 @@ nsEventStatus AsyncPanZoomController::OnLongPress(const TapGestureInput& aEvent) } nsEventStatus AsyncPanZoomController::OnSingleTapUp(const TapGestureInput& aEvent) { - // XXX: Implement this. + if (mGeckoContentController) { + MonitorAutoLock monitor(mMonitor); + + gfx::Point point = WidgetSpaceToCompensatedViewportSpace( + gfx::Point(aEvent.mPoint.x, aEvent.mPoint.y), + mFrameMetrics.mResolution.width); + mGeckoContentController->HandleSingleTap(nsIntPoint(NS_lround(point.x), NS_lround(point.y))); + return nsEventStatus_eConsumeNoDefault; + } return nsEventStatus_eIgnore; } @@ -989,6 +997,8 @@ void AsyncPanZoomController::NotifyLayersUpdated(const FrameMetrics& aViewportFr // we get a larger displayport. This is very bad because we're wasting a // paint and not initializating the displayport correctly. RequestContentRepaint(); + + mState = NOTHING; } else if (!mFrameMetrics.mCSSContentRect.IsEqualEdges(aViewportFrame.mCSSContentRect)) { mFrameMetrics.mCSSContentRect = aViewportFrame.mCSSContentRect; SetPageRect(mFrameMetrics.mCSSContentRect); diff --git a/gfx/layers/ipc/GeckoContentController.h b/gfx/layers/ipc/GeckoContentController.h index 66a7b5762b6..c14869ad39e 100644 --- a/gfx/layers/ipc/GeckoContentController.h +++ b/gfx/layers/ipc/GeckoContentController.h @@ -31,6 +31,13 @@ public: */ virtual void HandleDoubleTap(const nsIntPoint& aPoint) = 0; + /** + * Requests handling a single tap. |aPoint| is in CSS pixels, relative to the + * current scroll offset. This should simulate and send to content a mouse + * button down, then mouse button up at |aPoint|. + */ + virtual void HandleSingleTap(const nsIntPoint& aPoint) = 0; + GeckoContentController() {} virtual ~GeckoContentController() {} }; diff --git a/layout/ipc/RenderFrameParent.cpp b/layout/ipc/RenderFrameParent.cpp index 70a0f5c0ffe..7fc3d2ede4c 100644 --- a/layout/ipc/RenderFrameParent.cpp +++ b/layout/ipc/RenderFrameParent.cpp @@ -511,6 +511,23 @@ public: } } + virtual void HandleSingleTap(const nsIntPoint& aPoint) MOZ_OVERRIDE + { + if (MessageLoop::current() != mUILoop) { + // We have to send this message from the "UI thread" (main + // thread). + mUILoop->PostTask( + FROM_HERE, + NewRunnableMethod(this, &RemoteContentController::HandleSingleTap, + aPoint)); + return; + } + if (mRenderFrame) { + TabParent* browser = static_cast(mRenderFrame->Manager()); + browser->HandleSingleTap(aPoint); + } + } + void ClearRenderFrame() { mRenderFrame = nullptr; } private: From 11702b078bc58393d4df8ae10ebad5f05e44a708 Mon Sep 17 00:00:00 2001 From: Geoff Brown Date: Fri, 14 Sep 2012 21:50:30 -0600 Subject: [PATCH 09/11] Bug 767215 - Robocop: increase wait time for paint events; r=jmaher --- mobile/android/base/tests/PixelTest.java.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mobile/android/base/tests/PixelTest.java.in b/mobile/android/base/tests/PixelTest.java.in index 17793df4c08..4a8efd40b35 100644 --- a/mobile/android/base/tests/PixelTest.java.in +++ b/mobile/android/base/tests/PixelTest.java.in @@ -4,7 +4,7 @@ package @ANDROID_PACKAGE_NAME@.tests; import @ANDROID_PACKAGE_NAME@.*; abstract class PixelTest extends BaseTest { - private static final long PAINT_CLEAR_DELAY = 1000; // milliseconds + private static final long PAINT_CLEAR_DELAY = 3000; // milliseconds protected final PaintedSurface loadAndGetPainted(String url) { Actions.RepeatedEventExpecter paintExpecter = mActions.expectPaint(); From a189fa8e21effa6e91fc1e1e86fc0df40cb975d0 Mon Sep 17 00:00:00 2001 From: Kyle Machulis Date: Fri, 14 Sep 2012 23:47:01 -0700 Subject: [PATCH 10/11] Bug 791189: Exit signal filters early when signal not handled, remove service reg/unreg to fix bt crashes; r=dhylands --- dom/bluetooth/linux/BluetoothDBusService.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/dom/bluetooth/linux/BluetoothDBusService.cpp b/dom/bluetooth/linux/BluetoothDBusService.cpp index 8309e6632fa..3c679d9fc1d 100644 --- a/dom/bluetooth/linux/BluetoothDBusService.cpp +++ b/dom/bluetooth/linux/BluetoothDBusService.cpp @@ -440,7 +440,10 @@ AgentEventFilter(DBusConnection *conn, DBusMessage *msg, void *data) return DBUS_HANDLER_RESULT_HANDLED; } } else { +#ifdef DEBUG LOG("agent handler %s: Unhandled event. Ignore.", __FUNCTION__); +#endif + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } if (!errorStr.IsEmpty()) { @@ -982,6 +985,7 @@ EventFilter(DBusConnection* aConn, DBusMessage* aMsg, void* aData) signalStr += " Signal not handled!"; NS_WARNING(signalStr.get()); #endif + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } if (!errorStr.IsEmpty()) { @@ -1077,8 +1081,6 @@ BluetoothDBusService::StopInternal() return NS_OK; } - RemoveReservedServicesInternal(sDefaultAdapterPath, sServiceHandles); - DBusError err; dbus_error_init(&err); for (uint32_t i = 0; i < ArrayLength(sBluetoothDBusSignals); ++i) { @@ -1167,7 +1169,6 @@ public: path)); RegisterAgent(path); - AddReservedServices(path); DispatchBluetoothReply(mRunnable, v, replyError); From 959e5ab98e88fb57c2c2980cd31cae56aed948c5 Mon Sep 17 00:00:00 2001 From: Kyle Machulis Date: Sat, 15 Sep 2012 00:39:21 -0700 Subject: [PATCH 11/11] Bug 791413: Exit early when bluetooth property types don't match; r=cjones --- dom/bluetooth/linux/BluetoothDBusService.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/dom/bluetooth/linux/BluetoothDBusService.cpp b/dom/bluetooth/linux/BluetoothDBusService.cpp index 3c679d9fc1d..275dc061a07 100644 --- a/dom/bluetooth/linux/BluetoothDBusService.cpp +++ b/dom/bluetooth/linux/BluetoothDBusService.cpp @@ -672,8 +672,18 @@ GetProperty(DBusMessageIter aIter, Properties* aPropertyTypes, dbus_message_iter_recurse(&aIter, &prop_val); type = aPropertyTypes[*aPropIndex].type; - NS_ASSERTION(dbus_message_iter_get_arg_type(&prop_val) == type, - "Iterator not type we expect!"); + if(dbus_message_iter_get_arg_type(&prop_val) != type) { + NS_WARNING("Iterator not type we expect!"); + nsAutoCString str; + str += "Property Name: ;"; + str += NS_ConvertUTF16toUTF8(propertyName); + str += " Property Type Expected: ;"; + str += type; + str += " Property Type Received: "; + str += dbus_message_iter_get_arg_type(&prop_val); + NS_WARNING(str.get()); + return false; + } BluetoothValue propertyValue; switch (type) {