Merge commit '1aaaebb25db3ae24e6a55f89a1b9e19a8d6c0b99' into HEAD

Change-Id: Ic4d9f6fecaab8f00298d96ce5479ad2f41ea0597
diff --git a/Source/core/dom/ContainerNode.cpp b/Source/core/dom/ContainerNode.cpp
index 8b33eca..5d409c5 100644
--- a/Source/core/dom/ContainerNode.cpp
+++ b/Source/core/dom/ContainerNode.cpp
@@ -431,8 +431,6 @@
     NodeVector children;
     getChildNodes(container, children);
 
-    container->document()->nodeChildrenWillBeRemoved(container);
-
     ChildListMutationScope mutation(container);
     for (NodeVector::const_iterator it = children.begin(); it != children.end(); it++) {
         Node* child = it->get();
@@ -575,6 +573,8 @@
         document()->removeFocusedElementOfSubtree(this, true);
     }
 
+    document()->nodeChildrenWillBeRemoved(this);
+
     NodeVector removedChildren;
     {
         WidgetHierarchyUpdatesSuspensionScope suspendWidgetHierarchyUpdates;
diff --git a/Source/core/dom/Event.cpp b/Source/core/dom/Event.cpp
index 1b714f7..f066f56 100644
--- a/Source/core/dom/Event.cpp
+++ b/Source/core/dom/Event.cpp
@@ -138,6 +138,11 @@
     return false;
 }
 
+bool Event::isGestureEvent() const
+{
+    return false;
+}
+
 bool Event::isDragEvent() const
 {
     return false;
diff --git a/Source/core/dom/Event.h b/Source/core/dom/Event.h
index 7875b1e..3d4695f 100644
--- a/Source/core/dom/Event.h
+++ b/Source/core/dom/Event.h
@@ -126,6 +126,7 @@
     virtual bool isFocusEvent() const;
     virtual bool isKeyboardEvent() const;
     virtual bool isTouchEvent() const;
+    virtual bool isGestureEvent() const;
 
     // Drag events are a subset of mouse events.
     virtual bool isDragEvent() const;
diff --git a/Source/core/dom/GestureEvent.cpp b/Source/core/dom/GestureEvent.cpp
index a4f5cf8..735036e 100644
--- a/Source/core/dom/GestureEvent.cpp
+++ b/Source/core/dom/GestureEvent.cpp
@@ -90,6 +90,11 @@
     return UIEvent::interfaceName();
 }
 
+bool GestureEvent::isGestureEvent() const
+{
+    return true;
+}
+
 GestureEvent::GestureEvent()
     : m_deltaX(0)
     , m_deltaY(0)
@@ -110,7 +115,7 @@
 
 GestureEvent* GestureEventDispatchMediator::event() const
 {
-    return static_cast<GestureEvent*>(EventDispatchMediator::event());
+    return toGestureEvent(EventDispatchMediator::event());
 }
 
 bool GestureEventDispatchMediator::dispatchEvent(EventDispatcher* dispatcher) const
diff --git a/Source/core/dom/GestureEvent.h b/Source/core/dom/GestureEvent.h
index a0d6f2e..b630ae9 100644
--- a/Source/core/dom/GestureEvent.h
+++ b/Source/core/dom/GestureEvent.h
@@ -41,6 +41,8 @@
 
     void initGestureEvent(const AtomicString& type, PassRefPtr<AbstractView>, int screenX, int screenY, int clientX, int clientY, bool ctrlKey, bool altKey, bool shiftKey, bool metaKey, float deltaX, float deltaY);
 
+    virtual bool isGestureEvent() const OVERRIDE;
+
     virtual const AtomicString& interfaceName() const;
 
     float deltaX() const { return m_deltaX; }
@@ -69,6 +71,12 @@
     virtual bool dispatchEvent(EventDispatcher*) const OVERRIDE;
 };
 
+inline GestureEvent* toGestureEvent(Event* event)
+{
+    ASSERT(event && event->isGestureEvent());
+    return static_cast<GestureEvent*>(event);
+}
+
 } // namespace WebCore
 
 #endif // GestureEvent_h
diff --git a/Source/core/dom/Range.cpp b/Source/core/dom/Range.cpp
index 8d1ad9d..64034db 100644
--- a/Source/core/dom/Range.cpp
+++ b/Source/core/dom/Range.cpp
@@ -1034,9 +1034,15 @@
         if (collapsed)
             m_end.setToBeforeChild(newText.get());
     } else {
-        RefPtr<Node> lastChild;
-        if (collapsed)
-            lastChild = (newNodeType == Node::DOCUMENT_FRAGMENT_NODE) ? newNode->lastChild() : newNode;
+        RefPtr<Node> lastChild = (newNodeType == Node::DOCUMENT_FRAGMENT_NODE) ? newNode->lastChild() : newNode;
+        if (lastChild && lastChild == m_start.childBefore()) {
+            // The insertion will do nothing, but we need to extend the range to include
+            // the inserted nodes.
+            Node* firstChild = (newNodeType == Node::DOCUMENT_FRAGMENT_NODE) ? newNode->firstChild() : newNode.get();
+            ASSERT(firstChild);
+            m_start.setToBeforeChild(firstChild);
+            return;
+        }
 
         int startOffset = m_start.offset();
         container = m_start.container();
diff --git a/Source/core/page/PageScaleConstraintsSet.cpp b/Source/core/page/PageScaleConstraintsSet.cpp
index 1e1b1b6..3aecbdf 100644
--- a/Source/core/page/PageScaleConstraintsSet.cpp
+++ b/Source/core/page/PageScaleConstraintsSet.cpp
@@ -162,16 +162,6 @@
             adjustedLayoutSizeWidth /= targetDensityDPIFactor;
             adjustedLayoutSizeHeight /= targetDensityDPIFactor;
         }
-
-        // In the following cases, a bug in the Classic WebView would mean that the viewport meta tag would take
-        // precedence over the app specified setInitialScale value. We keep bugward compatibility with the old
-        // WebView for legacy apps (the supportTargetDensityDPI case). New apps will see that setInitialScale()
-        // overrides what is specified in the viewport tag.
-        if (arguments.width == ViewportArguments::ValueAuto && m_pageDefinedConstraints.initialScale == 1.0f) {
-            m_userAgentConstraints.initialScale = -1;
-        } else if (arguments.width == ViewportArguments::ValueDeviceWidth || arguments.width == 320) {
-            m_userAgentConstraints.initialScale = -1;
-        }
     }
 
     if (wideViewportQuirkEnabled) {
@@ -181,6 +171,8 @@
         } else if (!useWideViewport) {
             const float nonWideScale = arguments.zoom < 1 && arguments.width != ViewportArguments::ValueDeviceWidth ? -1 : oldInitialScale;
             adjustedLayoutSizeWidth = getLayoutWidthForNonWideViewport(viewSize, nonWideScale) / targetDensityDPIFactor;
+            if (m_userAgentConstraints.initialScale != -1 && (arguments.width == ViewportArguments::ValueDeviceWidth || (arguments.width == -1 && arguments.zoom == -1)))
+                adjustedLayoutSizeWidth /= m_userAgentConstraints.initialScale;
             adjustedLayoutSizeHeight = computeHeightByAspectRatio(adjustedLayoutSizeWidth, viewSize);
             if (arguments.zoom < 1) {
                 m_pageDefinedConstraints.initialScale = targetDensityDPIFactor;
@@ -190,6 +182,16 @@
         }
     }
 
+    if (supportTargetDensityDPI && !arguments.userZoom) {
+        m_pageDefinedConstraints.initialScale = targetDensityDPIFactor;
+        m_pageDefinedConstraints.minimumScale = m_pageDefinedConstraints.initialScale;
+        m_pageDefinedConstraints.maximumScale = m_pageDefinedConstraints.initialScale;
+        if (arguments.width == -1 || arguments.width == ViewportArguments::ValueDeviceWidth) {
+            adjustedLayoutSizeWidth = viewSize.width() / targetDensityDPIFactor;
+            adjustedLayoutSizeHeight = computeHeightByAspectRatio(adjustedLayoutSizeWidth, viewSize);
+        }
+    }
+
     m_pageDefinedConstraints.layoutSize.setWidth(adjustedLayoutSizeWidth);
     m_pageDefinedConstraints.layoutSize.setHeight(adjustedLayoutSizeHeight);
 }
diff --git a/Source/core/svg/properties/SVGPropertyTearOff.h b/Source/core/svg/properties/SVGPropertyTearOff.h
index 0d3b45c..a78bdea 100644
--- a/Source/core/svg/properties/SVGPropertyTearOff.h
+++ b/Source/core/svg/properties/SVGPropertyTearOff.h
@@ -56,8 +56,10 @@
 
     void setValue(PropertyType& value)
     {
-        if (m_valueIsCopy)
+        if (m_valueIsCopy) {
+            detachChildren();
             delete m_value;
+        }
         m_valueIsCopy = false;
         m_value = &value;
     }
diff --git a/Source/web/WebPluginContainerImpl.cpp b/Source/web/WebPluginContainerImpl.cpp
index 65d50f5..beaf7dd 100644
--- a/Source/web/WebPluginContainerImpl.cpp
+++ b/Source/web/WebPluginContainerImpl.cpp
@@ -192,10 +192,10 @@
         handleWheelEvent(static_cast<WheelEvent*>(event));
     else if (event->isKeyboardEvent())
         handleKeyboardEvent(toKeyboardEvent(event));
-    else if (eventNames().isTouchEventType(event->type()))
+    else if (event->isTouchEvent())
         handleTouchEvent(static_cast<TouchEvent*>(event));
-    else if (eventNames().isGestureEventType(event->type()))
-        handleGestureEvent(static_cast<GestureEvent*>(event));
+    else if (event->isGestureEvent())
+        handleGestureEvent(toGestureEvent(event));
 
     // FIXME: it would be cleaner if Widget::handleEvent returned true/false and
     // HTMLPluginElement called setDefaultHandled or defaultEventHandler.
diff --git a/Source/web/WebViewImpl.cpp b/Source/web/WebViewImpl.cpp
index 78232be..f123849 100644
--- a/Source/web/WebViewImpl.cpp
+++ b/Source/web/WebViewImpl.cpp
@@ -3069,6 +3069,19 @@
 
     float oldInitialScale = m_pageScaleConstraintsSet.pageDefinedConstraints().initialScale;
     m_pageScaleConstraintsSet.updatePageDefinedConstraints(adjustedArguments, m_size, page()->settings()->layoutFallbackWidth());
+
+    if (settingsImpl()->supportDeprecatedTargetDensityDPI()
+        && m_pageScaleConstraintsSet.userAgentConstraints().initialScale != -1
+        && m_pageScaleConstraintsSet.userAgentConstraints().initialScale * deviceScaleFactor() <= 1.0f) {
+        // In the following cases, a bug in the Classic WebView would mean that the viewport meta tag would take
+        // precedence over the app specified setInitialScale value. We keep bugward compatibility with the old
+        // WebView for legacy apps (the supportTargetDensityDPI case). New apps will see that setInitialScale()
+        // overrides what is specified in the viewport tag.
+        if (adjustedArguments.width == ViewportArguments::ValueDeviceWidth
+            || (adjustedArguments.width == ViewportArguments::ValueAuto && m_pageScaleConstraintsSet.pageDefinedConstraints().initialScale == 1.0f)) {
+            setInitialPageScaleOverride(-1);
+        }
+    }
     m_pageScaleConstraintsSet.adjustForAndroidWebViewQuirks(adjustedArguments, m_size, page()->settings()->layoutFallbackWidth(), deviceScaleFactor(), settingsImpl()->supportDeprecatedTargetDensityDPI(), page()->settings()->wideViewportQuirkEnabled(), page()->settings()->useWideViewport(), page()->settings()->loadWithOverviewMode());
     float newInitialScale = m_pageScaleConstraintsSet.pageDefinedConstraints().initialScale;
     if (oldInitialScale != newInitialScale && newInitialScale != -1)
diff --git a/Source/wtf/PartitionAlloc.h b/Source/wtf/PartitionAlloc.h
index a66ba61..9847430 100644
--- a/Source/wtf/PartitionAlloc.h
+++ b/Source/wtf/PartitionAlloc.h
@@ -80,6 +80,7 @@
 // - No specific protection against corruption of page header metadata.
 
 #include "wtf/Assertions.h"
+#include "wtf/CPU.h"
 #include "wtf/FastMalloc.h"
 #include "wtf/SpinLock.h"
 
@@ -87,8 +88,17 @@
 
 namespace WTF {
 
-// Allocation granularity of sizeof(void*) bytes.
-static const size_t kAllocationGranularity = sizeof(void*);
+#if CPU(MIPS)
+    // Allocation granularity of sizeof(double) bytes.
+    typedef double align_t;
+    #define WTF_ALIGN(n)  __attribute__((__aligned__(n)))
+#else
+    // Allocation granularity of sizeof(void*) bytes.
+    typedef void * align_t;
+    #define WTF_ALIGN(n)
+#endif
+
+static const size_t kAllocationGranularity = sizeof(align_t);
 static const size_t kAllocationGranularityMask = kAllocationGranularity - 1;
 static const size_t kBucketShift = (kAllocationGranularity == 8) ? 3 : 2;
 // Supports allocations up to 4088 (one bucket is used for metadata).
@@ -121,19 +131,19 @@
     PartitionFreelistEntry* freelistHead;
     PartitionPageHeader* next;
     PartitionPageHeader* prev;
-};
+} WTF_ALIGN(sizeof(align_t));
 
 struct PartitionFreepagelistEntry {
     PartitionPageHeader* page;
     PartitionFreepagelistEntry* next;
-};
+} WTF_ALIGN(sizeof(align_t));
 
 struct PartitionBucket {
     PartitionRoot* root;
     PartitionPageHeader* currPage;
     PartitionFreepagelistEntry* freePages;
     size_t numFullPages;
-};
+} WTF_ALIGN(sizeof(align_t));
 
 struct PartitionRoot {
     int lock;
@@ -189,11 +199,19 @@
     return partitionAllocSlowPath(bucket);
 }
 
+ALWAYS_INLINE size_t partitionAllocRoundup(size_t size)
+{
+    return (size + kAllocationGranularityMask) & ~kAllocationGranularityMask;
+}
+
 ALWAYS_INLINE void* partitionAlloc(PartitionRoot* root, size_t size)
 {
 #if defined(MEMORY_TOOL_REPLACES_ALLOCATOR)
     return malloc(size);
 #else
+#if CPU(MIPS)
+    size = partitionAllocRoundup(size);
+#endif
     size_t index = size >> kBucketShift;
     ASSERT(index < kNumBuckets);
     ASSERT(size == index << kBucketShift);
@@ -234,18 +252,13 @@
 #endif
 }
 
-ALWAYS_INLINE size_t partitionAllocRoundup(size_t size)
-{
-    return (size + kAllocationGranularityMask) & ~kAllocationGranularityMask;
-}
-
 ALWAYS_INLINE void* partitionAllocGeneric(PartitionRoot* root, size_t size)
 {
 #if defined(MEMORY_TOOL_REPLACES_ALLOCATOR)
     return malloc(size);
 #else
+    size = partitionAllocRoundup(size);
     if (LIKELY(size <= kMaxAllocation)) {
-        size = partitionAllocRoundup(size);
         spinLockLock(&root->lock);
         void* ret = partitionAlloc(root, size);
         spinLockUnlock(&root->lock);