diff --git a/WKC/WTF/wtf/WKC/ThreadingWKC.cpp b/WKC/WTF/wtf/WKC/ThreadingWKC.cpp index 93bca8feb..e7d2f61a4 100755 --- a/WKC/WTF/wtf/WKC/ThreadingWKC.cpp +++ b/WKC/WTF/wtf/WKC/ThreadingWKC.cpp @@ -1,7 +1,7 @@ /* * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. * Copyright (C) 2007 Justin Haygood (jhaygood@reaktix.com) - * Copyright (c) 2010-2016 ACCESS CO., LTD. All rights reserved. + * Copyright (c) 2010-2017 ACCESS CO., LTD. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -159,6 +159,8 @@ removeThreadIdentifier(ThreadIdentifier id) int waitForThreadCompletion(ThreadIdentifier threadID) { void* instance = getThreadInstance(threadID); + if (!instance) + return 0; int ret = wkcThreadJoinPeer(instance, 0); removeThreadIdentifier(threadID); return ret; diff --git a/WKC/WebCore/platform/WKC/GamepadProviderWKC.cpp b/WKC/WebCore/platform/WKC/GamepadProviderWKC.cpp index a9e885082..254aab25b 100755 --- a/WKC/WebCore/platform/WKC/GamepadProviderWKC.cpp +++ b/WKC/WebCore/platform/WKC/GamepadProviderWKC.cpp @@ -116,7 +116,7 @@ GamepadProviderWKC::updateGamepadValue(unsigned int in_index, long long timestam gamepad->updateValue(timestamp, vaxes, vbuttons); for (auto& client : m_clients) - client->platformGamepadInputActivity(); + client->platformGamepadInputActivity(true); } } // namespace WebCore diff --git a/WKC/WebCore/platform/WKC/RenderThemeWKC.cpp b/WKC/WebCore/platform/WKC/RenderThemeWKC.cpp index 6dfa493e2..81a677a3d 100755 --- a/WKC/WebCore/platform/WKC/RenderThemeWKC.cpp +++ b/WKC/WebCore/platform/WKC/RenderThemeWKC.cpp @@ -1,6 +1,6 @@ /* * Copyright (C) 2007 Kevin Ollivier - * Copyright (c) 2010-2016 ACCESS CO., LTD. All rights reserved. + * Copyright (c) 2010-2017 ACCESS CO., LTD. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -1220,16 +1220,52 @@ Color RenderThemeWKC::platformInactiveSelectionForegroundColor() const int RenderThemeWKC::popupInternalPaddingLeft(RenderStyle& style) const { - return cPopupInternalPaddingLeft; + int width = 0; + + switch (style.appearance()) { + case MenulistPart: // default + width += 1; + // fall through + case MenulistButtonPart: + width += cPopupInternalPaddingLeft; + break; + case ButtonPart: + width = 1; + break; + default: + break; + } + + return width; } int RenderThemeWKC::popupInternalPaddingRight(RenderStyle& style) const { - unsigned int w=0, h=0; - float scale = wkcStockImageGetImageScalePeer(); - wkcStockImageGetSizePeer(WKC_IMAGE_MENU_LIST_BUTTON, &w, &h); - w *= scale; - return w + cPopupInternalPaddingRight; + int width = 0; + + switch (style.appearance()) { + case MenulistPart: // default + width += 1; + // fall through + case MenulistButtonPart: + { + unsigned int w=0, h=0; + float scale = wkcStockImageGetImageScalePeer(); + wkcStockImageGetSizePeer(WKC_IMAGE_MENU_LIST_BUTTON, &w, &h); + w *= scale; + + width += cPopupInternalPaddingRight; + width += w; + } + break; + case ButtonPart: + width = 1; + break; + default: + break; + } + + return width; } int RenderThemeWKC::popupInternalPaddingTop(RenderStyle& style) const diff --git a/WKC/WebCore/platform/audio/WKC/AudioDestinationWKC.cpp b/WKC/WebCore/platform/audio/WKC/AudioDestinationWKC.cpp index a3e58e6bd..3c873f293 100755 --- a/WKC/WebCore/platform/audio/WKC/AudioDestinationWKC.cpp +++ b/WKC/WebCore/platform/audio/WKC/AudioDestinationWKC.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2016 ACCESS CO., LTD. All rights reserved. + * Copyright (c) 2012-2017 ACCESS CO., LTD. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -39,7 +39,6 @@ namespace WebCore { static const unsigned int c_busFrameSize = 128; // 3ms window -static const int c_drainBuffers = 3; // 9ms flush interval class AudioDestinationWKC : public AudioDestination, AudioSourceProviderClient { @@ -75,10 +74,6 @@ class AudioDestinationWKC : public AudioDestination, AudioSourceProviderClient ThreadIdentifier m_thread; bool m_quit; - - float m_drainBuffer0[c_busFrameSize * c_drainBuffers]; - float m_drainBuffer1[c_busFrameSize * c_drainBuffers]; - int m_drainCount = 0; }; AudioDestinationWKC::AudioDestinationWKC(AudioIOCallback& cb, float sampleRate) @@ -118,9 +113,6 @@ AudioDestinationWKC::create(AudioIOCallback& cb, float sampleRate) bool AudioDestinationWKC::construct() { - m_peer = wkcAudioOpenPeer(wkcAudioPreferredSampleRatePeer(), 16, 2, 0); - - //Prevents crashing, but audio won't play if m_peer==nullptr return true; } @@ -134,8 +126,19 @@ AudioDestinationWKC::setFormat(size_t numberOfChannels, float sampleRate) void AudioDestinationWKC::start() { + m_peer = wkcAudioOpenPeer(wkcAudioPreferredSampleRatePeer(), 16, 2, 0); + + if (!m_peer) { + return; + } + m_quit = false; m_thread = createThread(threadProc, this, "WKC: AudioDestination"); + + if (!m_thread) { + wkcAudioClosePeer(m_peer); + m_peer = 0; + } } void @@ -148,6 +151,11 @@ AudioDestinationWKC::stop() waitForThreadCompletion(m_thread); m_thread = 0; } + + if (m_peer) { + wkcAudioClosePeer(m_peer); + m_peer = 0; + } } bool @@ -164,76 +172,35 @@ AudioDestinationWKC::sampleRate() const void AudioDestinationWKC::drain() { - if (m_quit) + if (m_quit || !m_peer) return; - float* sampleMatrix[2] = { m_drainBuffer0, m_drainBuffer1 }; - const size_t sampleCount = c_busFrameSize * c_drainBuffers; - const size_t len = sampleCount * 2 * sizeof(int16_t); - int16_t* pcm = static_cast(WTF::fastMalloc(len)); + float** dataArray = static_cast(WTF::fastMalloc(m_channels * sizeof(float*))); + float* maxAbsValueArray = static_cast(WTF::fastMalloc(m_channels * sizeof(float))); + + unsigned int channels = 0; + bool shouldDrainNextData = true; while (!m_quit) { wkcThreadCheckAlivePeer(); + wkc_usleep(1000); - // Update on a 3ms window - m_audioIOCallback.render(0, m_bus.get(), c_busFrameSize); - - if (m_peer) { - int channels = 1; + if (shouldDrainNextData) { + // Update on a 3ms window + m_audioIOCallback.render(0, m_bus.get(), c_busFrameSize); - // Copy the samples into the drainBuffer - float * sampleData0 = m_bus->channel(0)->mutableData(); - float * sampleData1 = sampleData0; channels = m_bus->numberOfChannels(); - - if (channels > 1) { - sampleData1 = m_bus->channel(1)->mutableData(); - } - - for (int i = 0; i < m_bus->channel(0)->length(); i++) { - m_drainBuffer0[(m_drainCount*c_busFrameSize) + i] = sampleData0[i]; - m_drainBuffer1[(m_drainCount*c_busFrameSize) + i] = sampleData1[i]; - } - - m_drainCount++; - - // Flush on a 3ms * c_drainBuffers interval to compensate for HW flushing perf - if (m_drainCount >= c_drainBuffers) { - // Convert float to pcm16 - int16_t scaler = std::numeric_limits::max(); - float sample = 0.0f; - for (auto i = 0; i < sampleCount; ++i) { - sample = sampleMatrix[0][i]; - -#ifdef ENABLE_SOFTWARE_CLAMPING - if (sample > 1.0f) { - sample = 1.0f; - } else if (sample < -1.0f) { - sample = -1.0f; - } -#endif - pcm[i * 2] = static_cast(scaler * sample); - - sample = sampleMatrix[1][i]; -#ifdef ENABLE_SOFTWARE_CLAMPING - if (sample > 1.0f) { - sample = 1.0f; - } else if (sample < -1.0f) { - sample = -1.0f; - } -#endif - pcm[i * 2 + 1] = static_cast(scaler * sample); - } - - wkcAudioWritePeer(m_peer, pcm, len); - m_drainCount = 0; + for (unsigned int i = 0; i < channels; ++i) { + dataArray[i] = m_bus->channel(i)->mutableData(); + maxAbsValueArray[i] = m_bus->channel(i)->maxAbsValue(); } } - wkc_usleep(1000); + shouldDrainNextData = wkcAudioWriteRawPeer(m_peer, dataArray, channels, c_busFrameSize, maxAbsValueArray); } - WTF::fastFree(pcm); + WTF::fastFree(maxAbsValueArray); + WTF::fastFree(dataArray); } std::unique_ptr AudioDestination::create(AudioIOCallback& cb, const String& inputDeviceId, unsigned numberOfInputChannels, unsigned numberOfOutputChannels, float sampleRate) diff --git a/WKC/WebCore/platform/graphics/WKC/GraphicsContext3DWKC.cpp b/WKC/WebCore/platform/graphics/WKC/GraphicsContext3DWKC.cpp index 9c4d82f80..3f217fe4b 100755 --- a/WKC/WebCore/platform/graphics/WKC/GraphicsContext3DWKC.cpp +++ b/WKC/WebCore/platform/graphics/WKC/GraphicsContext3DWKC.cpp @@ -3,7 +3,7 @@ * Copyright (C) 2011 Google Inc. All rights reserved. * Copyright (C) 2012 ChangSeok Oh * Copyright (C) 2012 Research In Motion Limited. All rights reserved. - * Copyright (c) 2011-2015 ACCESS CO., LTD. All rights reserved. + * Copyright (c) 2011-2017 ACCESS CO., LTD. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -252,7 +252,11 @@ GraphicsContext3DPrivate::create(GraphicsContext3D* parent, GraphicsContext3D::A attrs.preserveDrawingBuffer, attrs.noExtensions, attrs.shareResources, - attrs.preferDiscreteGPU, + attrs.preferLowPowerToHighPerformance, + attrs.forceSoftwareRenderer, + attrs.failIfMajorPerformanceCaveat, + attrs.useGLES3, + attrs.devicePixelRatio, }; GraphicsContext3DPrivate* v = new GraphicsContext3DPrivate(); @@ -260,7 +264,7 @@ GraphicsContext3DPrivate::create(GraphicsContext3D* parent, GraphicsContext3D::A std::unique_ptr self; self.reset(v); - self->m_peer = wkcGLCreateContextPeer(&ga, (void *)hostwindow); + self->m_peer = wkcGLCreateContextPeer(&ga, (void *)hostwindow, self->m_layer); if (!self->m_peer) { return nullptr; } @@ -2373,14 +2377,21 @@ GraphicsContext3D::vertexAttribDivisor(GC3Duint index, GC3Duint divisor) #include "GraphicsContext3D.h" +#include "Extensions3D.h" +#if USE(OPENGL_ES_2) +#include "Extensions3DOpenGLES.h" +#else +#include "Extensions3DOpenGL.h" +#endif + namespace WebCore { class GraphicsContext3DPrivate { public: - static PassOwnPtr create(GraphicsContext3D::Attributes& attrs, HostWindow* hostwindow, bool in_direct) + static std::unique_ptr create(GraphicsContext3D::Attributes& attrs, HostWindow* hostwindow, bool in_direct) { - return 0; + return nullptr; } ~GraphicsContext3DPrivate() {} diff --git a/WKC/WebCore/platform/graphics/WKC/ImageDecoderWKC.cpp b/WKC/WebCore/platform/graphics/WKC/ImageDecoderWKC.cpp index 7a55bb1d1..49a043a9b 100755 --- a/WKC/WebCore/platform/graphics/WKC/ImageDecoderWKC.cpp +++ b/WKC/WebCore/platform/graphics/WKC/ImageDecoderWKC.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2015 ACCESS CO., LTD. All rights reserved. + * Copyright (c) 2010-2017 ACCESS CO., LTD. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -36,6 +36,10 @@ ImageFrame::ImageFrame() , m_duration(0) , m_disposalMethod(DisposeNotSpecified) , m_premultiplyAlpha(true) +#if ENABLE(WKC_BLINK_AWEBP) + , m_alphaBlendSource(BlendAtopPreviousFrame) + , m_requiredPreviousFrameIndex(-1) +#endif { m_image = ImageWKC::create(); } diff --git a/WKC/WebCore/platform/graphics/WKC/SourceBufferPrivateWKC.cpp b/WKC/WebCore/platform/graphics/WKC/SourceBufferPrivateWKC.cpp index 709c16d6f..ff968e31d 100755 --- a/WKC/WebCore/platform/graphics/WKC/SourceBufferPrivateWKC.cpp +++ b/WKC/WebCore/platform/graphics/WKC/SourceBufferPrivateWKC.cpp @@ -176,6 +176,13 @@ SourceBufferPrivateWKC::abort() (void)wkcMediaPlayerAbortSBPeer(m_peer, m_sourcebuffer); } +void +SourceBufferPrivateWKC::resetParserState() +{ + // TODO + abort(); +} + bool SourceBufferPrivateWKC::setTimestampOffset(double timestamp_offset) { diff --git a/WKC/WebCore/platform/graphics/WKC/SourceBufferPrivateWKC.h b/WKC/WebCore/platform/graphics/WKC/SourceBufferPrivateWKC.h index 8b3401e0f..cbf11e2b7 100755 --- a/WKC/WebCore/platform/graphics/WKC/SourceBufferPrivateWKC.h +++ b/WKC/WebCore/platform/graphics/WKC/SourceBufferPrivateWKC.h @@ -42,6 +42,7 @@ class SourceBufferPrivateWKC : public SourceBufferPrivate { virtual void setClient(SourceBufferPrivateClient*); virtual void append(const unsigned char* data, unsigned length); virtual void abort(); + virtual void resetParserState(); virtual bool setTimestampOffset(double); #if PLATFORM(WKC) virtual bool removedFromMediaSource(); diff --git a/WKC/WebCore/platform/network/WKC/ResourceHandleManagerWKC.cpp b/WKC/WebCore/platform/network/WKC/ResourceHandleManagerWKC.cpp index 1280dc95d..3dd1bfb88 100755 --- a/WKC/WebCore/platform/network/WKC/ResourceHandleManagerWKC.cpp +++ b/WKC/WebCore/platform/network/WKC/ResourceHandleManagerWKC.cpp @@ -1676,6 +1676,14 @@ bool ResourceHandleManager::finalizingResourceHandle(ResourceHandle* job, Resour } } if (httpCode == 401 || 407 == httpCode) { + if (d->m_msgDataResult != CURLE_OK){ + finishLoadingResourceHandle(job, d); + if (d->client()){ + ResourceError err(String(), d->m_msgDataResult, String(d->m_url), String(curl_easy_strerror((CURLcode)d->m_msgDataResult)), job); + d->client()->didFail(job, err); + } + return true; + } didReceiveAuthenticationChallenge(job, d->m_currentWebChallenge); if (d->m_cancelled || d->m_didAuthChallenge) { finishLoadingResourceHandle(job, d); @@ -3102,6 +3110,9 @@ void ResourceHandleManager::initializeHandle(ResourceHandle* job) // if file/data scheme loading, do not set proxy/authenticate if (d->m_fileLoading || d->m_dataLoading) { d->m_response.setResourceHandle(job); + if (d->m_fileLoading) { + handleLocalReceiveResponse(d->m_handle, job, d); + } nxLog_out(""); return; } diff --git a/WKC/WebCore/platform/network/WKC/SocketStreamHandle.h b/WKC/WebCore/platform/network/WKC/SocketStreamHandle.h index cadbd9f97..d9c4cf2d5 100755 --- a/WKC/WebCore/platform/network/WKC/SocketStreamHandle.h +++ b/WKC/WebCore/platform/network/WKC/SocketStreamHandle.h @@ -1,7 +1,7 @@ /* * Copyright (C) 2009 Apple Inc. All rights reserved. * Copyright (C) 2009 Google Inc. All rights reserved. - * Copyright (c) 2012, 2015 ACCESS CO., LTD. All rights reserved. + * Copyright (c) 2012-2017 ACCESS CO., LTD. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -91,6 +91,9 @@ namespace WebCore { private: bool m_constructed; + bool m_needClosing; + bool m_clientCallingFromTimer; + int m_socketState; int m_socket; diff --git a/WKC/WebCore/platform/network/WKC/SocketStreamHandleWKC.cpp b/WKC/WebCore/platform/network/WKC/SocketStreamHandleWKC.cpp index bdd069a4d..47b22f924 100755 --- a/WKC/WebCore/platform/network/WKC/SocketStreamHandleWKC.cpp +++ b/WKC/WebCore/platform/network/WKC/SocketStreamHandleWKC.cpp @@ -1,7 +1,7 @@ /* * Copyright (C) 2009 Brent Fulgham. All rights reserved. * Copyright (C) 2009 Google Inc. All rights reserved. - * Copyright (c) 2012-2015 ACCESS CO., LTD. All rights reserved. + * Copyright (c) 2012-2017 ACCESS CO., LTD. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -65,6 +65,8 @@ namespace WebCore { SocketStreamHandle::SocketStreamHandle(const URL& url, SocketStreamHandleClient* client, NetworkingContext& networkingContext) : SocketStreamHandleBase(url, client) , m_constructed(false) + , m_clientCallingFromTimer(false) + , m_needClosing(false) , m_socketState(None) , m_socket(-1) , m_progressTimer(*this, &SocketStreamHandle::progressTimerFired) @@ -334,6 +336,12 @@ SocketStreamHandle::progressTimerFired() return; } + if (m_needClosing) { + RefPtr protect(static_cast(this)); // platformClose calls the client, which may make the handle get deallocated immediately. + platformClose(); + return; + } + switch (m_state) { case Connecting: { @@ -343,8 +351,11 @@ SocketStreamHandle::progressTimerFired() } if (!m_handle || !m_multiHandle) { m_state = Open; - if (m_client) + if (m_client) { + m_clientCallingFromTimer = true; m_client->didOpenSocketStream(this); + m_clientCallingFromTimer = false; + } return; } @@ -367,9 +378,13 @@ SocketStreamHandle::progressTimerFired() // socket opened RefPtr protect(static_cast(this)); // platformClose calls the client, which may make the handle get deallocated immediately. m_state = Open; - if (m_client) + if (m_client) { + m_clientCallingFromTimer = true; m_client->didOpenSocketStream(this); - m_socketState = Connected; + m_clientCallingFromTimer = false; + } + if (!m_needClosing) + m_socketState = Connected; nextProgress(true); break; } @@ -400,8 +415,11 @@ SocketStreamHandle::progressTimerFired() RefPtr protect(static_cast(this)); // platformClose calls the client, which may make the handle get deallocated immediately. if (CURLE_OK == ret) { _LOG(Network, "SocketStreamHandle::progressTimerFired() Recved(%d)", inoutLen); - if (0 < inoutLen && m_client) + if (0 < inoutLen && m_client) { + m_clientCallingFromTimer = true; m_client->didReceiveSocketStreamData(this, (const char*)m_recvData, inoutLen); + m_clientCallingFromTimer = false; + } nextProgress(true); } else if (CURLE_AGAIN == ret) { @@ -460,6 +478,7 @@ int SocketStreamHandle::platformSend(const char* data, int len) // for check receiveing FIN // Expect m_socket is non-blocking socket. outLen = wkcNetRecvPeer(m_socket, (void*)m_recvData, 2048, 0); + recverror = wkcNetGetLastErrorPeer(); if (0 < outLen) { if (m_client) { m_client->didReceiveSocketStreamData(this, (const char*)m_recvData, outLen); @@ -495,6 +514,14 @@ void SocketStreamHandle::platformClose() return; } + if (m_clientCallingFromTimer) { + m_needClosing = true; + return; + } + + if (m_needClosing) + m_needClosing = false; + CURL* handle = (CURL*)m_handle; CURLM* multiHandle = (CURLM*)m_multiHandle; diff --git a/WKC/WebKit/WKC/WebCoreSupport/EditorClientWKC.cpp b/WKC/WebKit/WKC/WebCoreSupport/EditorClientWKC.cpp index d5d14a2be..65c7c4615 100755 --- a/WKC/WebKit/WKC/WebCoreSupport/EditorClientWKC.cpp +++ b/WKC/WebKit/WKC/WebCoreSupport/EditorClientWKC.cpp @@ -4,7 +4,7 @@ * Copyright (C) 2009 Diego Escalante Urrelo * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. * Copyright (C) 2009, Igalia S.L. - * Copyright (c) 2010-2016 ACCESS CO., LTD. All rights reserved. + * Copyright (c) 2010-2017 ACCESS CO., LTD. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -450,5 +450,11 @@ EditorClientWKC::didChangeSelectionAndUpdateLayout() notImplemented(); } +void +EditorClientWKC::updateEditorStateAfterLayoutIfEditabilityChanged() +{ + notImplemented(); +} + } // namespace diff --git a/WKC/WebKit/WKC/WebCoreSupport/EditorClientWKC.h b/WKC/WebKit/WKC/WebCoreSupport/EditorClientWKC.h index 98458ee6d..780d034d1 100755 --- a/WKC/WebKit/WKC/WebCoreSupport/EditorClientWKC.h +++ b/WKC/WebKit/WKC/WebCoreSupport/EditorClientWKC.h @@ -3,7 +3,7 @@ * Copyright (C) 2006 Zack Rusin * Copyright (C) 2006 Apple Computer, Inc. * All rights reserved. - * Copyright (c) 2010-2015 ACCESS CO., LTD. All rights reserved. + * Copyright (c) 2010-2017 ACCESS CO., LTD. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -75,6 +75,7 @@ class EditorClientWKC : public WebCore::EditorClient { virtual void respondToChangedContents() override; virtual void respondToChangedSelection(WebCore::Frame*) override; virtual void didChangeSelectionAndUpdateLayout() override; + virtual void updateEditorStateAfterLayoutIfEditabilityChanged() override; virtual void didEndEditing() override; virtual void didWriteSelectionToPasteboard() override; diff --git a/WKC/WebKit/WKC/WebCoreSupport/FrameLoaderClientWKC.cpp b/WKC/WebKit/WKC/WebCoreSupport/FrameLoaderClientWKC.cpp index 92fa5928a..c7fc5811f 100755 --- a/WKC/WebKit/WKC/WebCoreSupport/FrameLoaderClientWKC.cpp +++ b/WKC/WebKit/WKC/WebCoreSupport/FrameLoaderClientWKC.cpp @@ -530,9 +530,9 @@ FrameLoaderClientWKC::dispatchDidLayout() } void -FrameLoaderClientWKC::dispatchDidLayout(WebCore::LayoutMilestones milestones) +FrameLoaderClientWKC::dispatchDidReachLayoutMilestone(WebCore::LayoutMilestones milestones) { - m_appClient->dispatchDidLayout((int)milestones); + m_appClient->dispatchDidReachLayoutMilestone((int)milestones); } // WKC extension diff --git a/WKC/WebKit/WKC/WebCoreSupport/FrameLoaderClientWKC.h b/WKC/WebKit/WKC/WebCoreSupport/FrameLoaderClientWKC.h index dc90f36be..880462aaf 100755 --- a/WKC/WebKit/WKC/WebCoreSupport/FrameLoaderClientWKC.h +++ b/WKC/WebKit/WKC/WebCoreSupport/FrameLoaderClientWKC.h @@ -102,7 +102,7 @@ class FrameLoaderClientWKC : public WebCore::FrameLoaderClient { virtual void dispatchDidFinishDocumentLoad() override; virtual void dispatchDidFinishLoad() override; virtual void dispatchDidLayout() override; - virtual void dispatchDidLayout(WebCore::LayoutMilestones) override; + virtual void dispatchDidReachLayoutMilestone(WebCore::LayoutMilestones) override; virtual WebCore::Frame* dispatchCreatePage(const WebCore::NavigationAction&) override; virtual void dispatchShow() override; diff --git a/WKC/WebKit/WKC/accessor/privates/wkc_ConstNodeAccessor.cpp b/WKC/WebKit/WKC/accessor/privates/wkc_ConstNodeAccessor.cpp index 790b323ab..4f96c53ab 100755 --- a/WKC/WebKit/WKC/accessor/privates/wkc_ConstNodeAccessor.cpp +++ b/WKC/WebKit/WKC/accessor/privates/wkc_ConstNodeAccessor.cpp @@ -1,7 +1,7 @@ /* * wkc_ConstNodeAccessor.cpp * - * Copyright (c) 2012-2014 ACCESS CO., LTD. All rights reserved. + * Copyright (c) 2012-2017 ACCESS CO., LTD. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -162,6 +162,8 @@ ConstNodeAccessor::hasTagName(int id) const switch (id) { case HTMLNames_inputTag: return ptr()->hasTagName(WebCore::HTMLNames::inputTag); + case HTMLNames_buttonTag: + return ptr()->hasTagName(WebCore::HTMLNames::buttonTag); case HTMLNames_textareaTag: return ptr()->hasTagName(WebCore::HTMLNames::textareaTag); case HTMLNames_selectTag: @@ -176,6 +178,8 @@ ConstNodeAccessor::hasTagName(int id) const return ptr()->hasTagName(WebCore::HTMLNames::videoTag); case HTMLNames_areaTag: return ptr()->hasTagName(WebCore::HTMLNames::areaTag); + case HTMLNames_aTag: + return ptr()->hasTagName(WebCore::HTMLNames::aTag); default: return false; } diff --git a/WKC/WebKit/WKC/accessor/privates/wkc_NodeAccessor.cpp b/WKC/WebKit/WKC/accessor/privates/wkc_NodeAccessor.cpp index 44c915544..6777815e6 100755 --- a/WKC/WebKit/WKC/accessor/privates/wkc_NodeAccessor.cpp +++ b/WKC/WebKit/WKC/accessor/privates/wkc_NodeAccessor.cpp @@ -1,7 +1,7 @@ /* * wkc_NodeAccessor.cpp * - * Copyright (c) 2012-2014 ACCESS CO., LTD. All rights reserved. + * Copyright (c) 2012-2017 ACCESS CO., LTD. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -205,6 +205,8 @@ NodeAccessor::hasTagName(int id) const switch (id) { case HTMLNames_inputTag: return ptr()->hasTagName(WebCore::HTMLNames::inputTag); + case HTMLNames_buttonTag: + return ptr()->hasTagName(WebCore::HTMLNames::buttonTag); case HTMLNames_textareaTag: return ptr()->hasTagName(WebCore::HTMLNames::textareaTag); case HTMLNames_selectTag: @@ -219,6 +221,8 @@ NodeAccessor::hasTagName(int id) const return ptr()->hasTagName(WebCore::HTMLNames::videoTag); case HTMLNames_areaTag: return ptr()->hasTagName(WebCore::HTMLNames::areaTag); + case HTMLNames_aTag: + return ptr()->hasTagName(WebCore::HTMLNames::aTag); default: return false; } diff --git a/WKC/WebKit/WKC/helpers/FrameLoaderClientIf.h b/WKC/WebKit/WKC/helpers/FrameLoaderClientIf.h index 3a12ef107..d0581e240 100755 --- a/WKC/WebKit/WKC/helpers/FrameLoaderClientIf.h +++ b/WKC/WebKit/WKC/helpers/FrameLoaderClientIf.h @@ -433,7 +433,7 @@ class WKC_API FrameLoaderClientIf { @return None @endcond */ - virtual void dispatchDidLayout(int) = 0; + virtual void dispatchDidReachLayoutMilestone(int) = 0; /** @cond WKC_PRIVATE_DOCUMENT diff --git a/WKC/WebKit/WKC/helpers/WKCElement.h b/WKC/WebKit/WKC/helpers/WKCElement.h index 25f444635..ea2bbfba6 100755 --- a/WKC/WebKit/WKC/helpers/WKCElement.h +++ b/WKC/WebKit/WKC/helpers/WKCElement.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2015 ACCESS CO., LTD. All rights reserved. + * Copyright (c) 2011-2017 ACCESS CO., LTD. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -25,6 +25,7 @@ #include "WKCNode.h" namespace WKC { +class AtomicString; class Attribute; class QualifiedName; class ElementPrivate; @@ -39,6 +40,7 @@ class WKC_API Element : public WKC::Node { void focus(bool restorePreviousSelection = true); void updateFocusAppearance(bool restorePreviousSelection); void blur(); + const AtomicString& computeInheritedLanguage() const; bool isFocusable() const; diff --git a/WKC/WebKit/WKC/helpers/WKCFocusController.h b/WKC/WebKit/WKC/helpers/WKCFocusController.h index 380a19324..962cbc82f 100755 --- a/WKC/WebKit/WKC/helpers/WKCFocusController.h +++ b/WKC/WebKit/WKC/helpers/WKCFocusController.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2016 ACCESS CO., LTD. All rights reserved. + * Copyright (c) 2011-2017 ACCESS CO., LTD. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -37,6 +37,7 @@ class WKC_API FocusController { Element* findNextFocusableElement(const FocusDirection& direction, const WKCRect* scope = 0, Element* base = 0); Element* findNearestFocusableElementFromPoint(const WKCPoint& point, const WKCRect* scope = 0); + Element* findNearestClickableElementFromPoint(const WKCPoint& point, const WKCRect* scope = 0); protected: // Applications must not create/destroy WKC helper instances by new/delete. diff --git a/WKC/WebKit/WKC/helpers/WKCHTMLButtonElement.h b/WKC/WebKit/WKC/helpers/WKCHTMLButtonElement.h new file mode 100755 index 000000000..9ae667a7a --- /dev/null +++ b/WKC/WebKit/WKC/helpers/WKCHTMLButtonElement.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2017 ACCESS CO., LTD. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef _WKC_HELPERS_WKC_HTMLBUTTONELEMENT_H_ +#define _WKC_HELPERS_WKC_HTMLBUTTONELEMENT_H_ + +#include + +#include "WKCHTMLFormControlElement.h" + +namespace WKC { +class HTMLButtonElementPrivate; + +class WKC_API HTMLButtonElement : public WKC::HTMLFormControlElement { +public: + +protected: + // Applications must not create/destroy WKC helper instances by new/delete. + // Or, it causes memory leaks or crashes. + HTMLButtonElement(HTMLButtonElementPrivate&); + virtual ~HTMLButtonElement() {} + +private: + HTMLButtonElement(const HTMLButtonElement&); + HTMLButtonElement& operator=(const HTMLButtonElement&); +}; +} // namespace + +#endif // _WKC_HELPERS_WKC_HTMLBUTTONELEMENT_H_ diff --git a/WKC/WebKit/WKC/helpers/WKCHTMLFormControlElement.h b/WKC/WebKit/WKC/helpers/WKCHTMLFormControlElement.h index a7c3d7083..1f9840d2c 100755 --- a/WKC/WebKit/WKC/helpers/WKCHTMLFormControlElement.h +++ b/WKC/WebKit/WKC/helpers/WKCHTMLFormControlElement.h @@ -25,6 +25,7 @@ #include "helpers/WKCHTMLElement.h" namespace WKC { +class AtomicString; class HTMLFormControlElementPrivate; class HTMLFormElement; @@ -33,6 +34,7 @@ class WKC_API HTMLFormControlElement : public HTMLElement { void dispatchFormControlInputEvent(); void dispatchFormControlChangeEvent(); bool isSuccessfulSubmitButton() const; + const AtomicString& type() const; HTMLFormElement* form() const; diff --git a/WKC/WebKit/WKC/helpers/WKCHTMLSelectElement.h b/WKC/WebKit/WKC/helpers/WKCHTMLSelectElement.h index f5d8a4ed6..ef4fcfc9a 100755 --- a/WKC/WebKit/WKC/helpers/WKCHTMLSelectElement.h +++ b/WKC/WebKit/WKC/helpers/WKCHTMLSelectElement.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013 ACCESS CO., LTD. All rights reserved. + * Copyright (c) 2013-2017 ACCESS CO., LTD. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -22,12 +22,12 @@ #include -#include "helpers/WKCHTMLElement.h" +#include "helpers/WKCHTMLFormControlElement.h" namespace WKC { class HTMLSelectElementPrivate; -class WKC_API HTMLSelectElement : public HTMLElement { +class WKC_API HTMLSelectElement : public WKC::HTMLFormControlElement { public: HTMLSelectElement(HTMLSelectElementPrivate&); diff --git a/WKC/WebKit/WKC/helpers/WKCKURL.h b/WKC/WebKit/WKC/helpers/WKCKURL.h index 05b3b9d02..dfc44b0b7 100755 --- a/WKC/WebKit/WKC/helpers/WKCKURL.h +++ b/WKC/WebKit/WKC/helpers/WKCKURL.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2014 ACCESS CO., LTD. All rights reserved. + * Copyright (c) 2011-2017 ACCESS CO., LTD. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -50,6 +50,8 @@ class WKC_API KURL { const String path() const; const String lastPathComponent() const; + bool setProtocol(const String&); + KURLPrivate* parent() const { return m_parent; } private: diff --git a/WKC/WebKit/WKC/helpers/WKCNode.h b/WKC/WebKit/WKC/helpers/WKCNode.h index a65e8f3ba..1ee1da1dc 100755 --- a/WKC/WebKit/WKC/helpers/WKCNode.h +++ b/WKC/WebKit/WKC/helpers/WKCNode.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2016 ACCESS CO., LTD. All rights reserved. + * Copyright (c) 2011-2017 ACCESS CO., LTD. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -38,6 +38,7 @@ class GraphicsLayer; enum { HTMLNames_inputTag, + HTMLNames_buttonTag, HTMLNames_textareaTag, HTMLNames_selectTag, HTMLNames_formTag, @@ -45,6 +46,7 @@ enum { HTMLNames_iframeTag, HTMLNames_videoTag, HTMLNames_areaTag, + HTMLNames_aTag, }; enum { @@ -105,6 +107,8 @@ class WKC_API Node { NodeList* getElementsByTagName(const String&); NodeList* querySelectorAll(const String&); + Element* parentOrShadowHostElement(); + protected: // Applications must not create/destroy WKC helper instances by new/delete. // Or, it causes memory leaks or crashes. diff --git a/WKC/WebKit/WKC/helpers/WKCString.h b/WKC/WebKit/WKC/helpers/WKCString.h index 1cb4ad316..7f3912a38 100755 --- a/WKC/WebKit/WKC/helpers/WKCString.h +++ b/WKC/WebKit/WKC/helpers/WKCString.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2014 ACCESS CO., LTD. All rights reserved. + * Copyright (c) 2011-2017 ACCESS CO., LTD. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -114,6 +114,8 @@ class WKC_API String { bool isNull() const; bool isEmpty() const; + bool endsWith(const String&) const; + StringPrivate* impl() const { return m_private; } private: diff --git a/WKC/WebKit/WKC/helpers/privates/WKCElement.cpp b/WKC/WebKit/WKC/helpers/privates/WKCElement.cpp index 89331d0ff..3ea1ea52e 100755 --- a/WKC/WebKit/WKC/helpers/privates/WKCElement.cpp +++ b/WKC/WebKit/WKC/helpers/privates/WKCElement.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2015 ACCESS CO., LTD. All rights reserved. + * Copyright (c) 2011-2017 ACCESS CO., LTD. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -28,11 +28,14 @@ #include "helpers/WKCNode.h" #include "helpers/WKCQualifiedName.h" #include "helpers/WKCString.h" +#include "helpers/privates/WKCAtomicStringPrivate.h" #include "helpers/privates/WKCAttributePrivate.h" #include "helpers/privates/WKCHTMLElementPrivate.h" #include "helpers/privates/WKCNodePrivate.h" #include "helpers/privates/WKCQualifiedNamePrivate.h" +#include "utils/nxDebugPrint.h" + namespace WKC { ElementPrivate* @@ -52,6 +55,8 @@ ElementPrivate::ElementPrivate(WebCore::Element* parent) , m_wkc(*this) , m_attr(0) , m_traverseChildAt(0) + , m_lang() + , m_atomicstring_priv(0) { } @@ -59,6 +64,8 @@ ElementPrivate::~ElementPrivate() { delete m_traverseChildAt; delete m_attr; + if (m_atomicstring_priv) + delete m_atomicstring_priv; } WebCore::Element* @@ -70,7 +77,27 @@ ElementPrivate::webcore() const bool ElementPrivate::isFormControlElement() const { - return webcore()->isFormControlElement(); + if (!webcore()->isFormControlElement()) { + return false; + } + + // Returns true only if WKC has a implementation for its element. + if (webcore()->hasTagName(WebCore::HTMLNames::inputTag)) { + return true; + } + if (webcore()->hasTagName(WebCore::HTMLNames::buttonTag)) { + return true; + } + if (webcore()->hasTagName(WebCore::HTMLNames::textareaTag)) { + return true; + } + if (webcore()->hasTagName(WebCore::HTMLNames::selectTag)) { + return true; + } + + nxLog_e("\"%s\" has not yet been implemented as HTMLFormControlElement in WKC layer.", webcore()->tagName().utf8().data()); + + return false; } void @@ -110,6 +137,18 @@ ElementPrivate::getAttributeItem(const QualifiedName* name) return &m_attr->wkc(); } +const AtomicString& +ElementPrivate::computeInheritedLanguage() +{ + m_lang = webcore()->computeInheritedLanguage(); + + if (m_atomicstring_priv) + delete m_atomicstring_priv; + + m_atomicstring_priv = new AtomicStringPrivate(&m_lang); + return m_atomicstring_priv->wkc(); +} + bool ElementPrivate::isFocusable() const { @@ -197,6 +236,12 @@ Element::getAttributeItem(const QualifiedName& name) const return static_cast(priv()).getAttributeItem(&name); } +const AtomicString& +Element::computeInheritedLanguage() const +{ + return static_cast(priv()).computeInheritedLanguage(); +} + bool Element::isFocusable() const { diff --git a/WKC/WebKit/WKC/helpers/privates/WKCElementPrivate.h b/WKC/WebKit/WKC/helpers/privates/WKCElementPrivate.h index c3b38eb22..a98f5d216 100755 --- a/WKC/WebKit/WKC/helpers/privates/WKCElementPrivate.h +++ b/WKC/WebKit/WKC/helpers/privates/WKCElementPrivate.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2015 ACCESS CO., LTD. All rights reserved. + * Copyright (c) 2011-2017 ACCESS CO., LTD. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -22,12 +22,14 @@ #include "helpers/WKCElement.h" #include "WKCNodePrivate.h" +#include "AtomicString.h" namespace WebCore { class Element; } // namespace namespace WKC { +class AtomicStringPrivate; class Attribute; class AttributePrivate; } // namespace @@ -58,6 +60,7 @@ WTF_MAKE_FAST_ALLOCATED; bool hasAttributes() const; bool hasAttribute(const String& name) const; Attribute* getAttributeItem(const QualifiedName* name); + const AtomicString& computeInheritedLanguage(); bool isFocusable() const; void focus(bool restorePreviousSelection = true); @@ -71,6 +74,9 @@ WTF_MAKE_FAST_ALLOCATED; AttributePrivate* m_attr; NodePrivate* m_traverseChildAt; + + WTF::AtomicString m_lang; + AtomicStringPrivate* m_atomicstring_priv; }; } // namespace diff --git a/WKC/WebKit/WKC/helpers/privates/WKCFocusController.cpp b/WKC/WebKit/WKC/helpers/privates/WKCFocusController.cpp index 90c5e247e..075bc1c93 100755 --- a/WKC/WebKit/WKC/helpers/privates/WKCFocusController.cpp +++ b/WKC/WebKit/WKC/helpers/privates/WKCFocusController.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2016 ACCESS CO., LTD. All rights reserved. + * Copyright (c) 2011-2017 ACCESS CO., LTD. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -40,11 +40,13 @@ FocusControllerPrivate::FocusControllerPrivate(WebCore::FocusController* parent) , m_wkc(*this) , m_focusedFrame(0) , m_focusableElement(0) + , m_clickableElement(0) { } FocusControllerPrivate::~FocusControllerPrivate() { + delete m_clickableElement; delete m_focusableElement; delete m_focusedFrame; } @@ -109,6 +111,29 @@ FocusControllerPrivate::findNearestFocusableElementFromPoint(const WKCPoint& poi return &m_focusableElement->wkc(); } +Element* +FocusControllerPrivate::findNearestClickableElementFromPoint(const WKCPoint& point, const WKCRect* scope) +{ + WebCore::IntPoint p(point.fX, point.fY); + WebCore::Element* element; + if (scope) { + WebCore::IntRect r(scope->fX, scope->fY, scope->fWidth, scope->fHeight); + element = m_webcore->findNearestClickableElementFromPoint(p, &r); + } else { + element = m_webcore->findNearestClickableElementFromPoint(p, 0); + } + if (!element) + return 0; + + if (m_clickableElement) + delete m_clickableElement; + m_clickableElement = ElementPrivate::create(element); + if (!m_clickableElement) + return 0; + + return &m_clickableElement->wkc(); +} + bool isScrollableContainerNode(Node* node) { @@ -153,4 +178,10 @@ FocusController::findNearestFocusableElementFromPoint(const WKCPoint& point, con return m_private.findNearestFocusableElementFromPoint(point, scope); } +Element* +FocusController::findNearestClickableElementFromPoint(const WKCPoint& point, const WKCRect* scope) +{ + return m_private.findNearestClickableElementFromPoint(point, scope); +} + } // namespace diff --git a/WKC/WebKit/WKC/helpers/privates/WKCFocusControllerPrivate.h b/WKC/WebKit/WKC/helpers/privates/WKCFocusControllerPrivate.h index 29d29f2bc..7bb0f3d35 100755 --- a/WKC/WebKit/WKC/helpers/privates/WKCFocusControllerPrivate.h +++ b/WKC/WebKit/WKC/helpers/privates/WKCFocusControllerPrivate.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2016 ACCESS CO., LTD. All rights reserved. + * Copyright (c) 2011-2017 ACCESS CO., LTD. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -49,6 +49,7 @@ WTF_MAKE_FAST_ALLOCATED; Element* findNextFocusableElement(const FocusDirection& direction, const WKCRect* scope = 0, Element* base = 0); Element* findNearestFocusableElementFromPoint(const WKCPoint& point, const WKCRect* scope = 0); + Element* findNearestClickableElementFromPoint(const WKCPoint& point, const WKCRect* scope = 0); Frame* focusedOrMainFrame(); @@ -58,6 +59,7 @@ WTF_MAKE_FAST_ALLOCATED; FramePrivate* m_focusedFrame; ElementPrivate* m_focusableElement; + ElementPrivate* m_clickableElement; }; } // namespace diff --git a/WKC/WebKit/WKC/helpers/privates/WKCHTMLButtonElement.cpp b/WKC/WebKit/WKC/helpers/privates/WKCHTMLButtonElement.cpp new file mode 100755 index 000000000..ff964735e --- /dev/null +++ b/WKC/WebKit/WKC/helpers/privates/WKCHTMLButtonElement.cpp @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2017 ACCESS CO., LTD. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "config.h" + +#include "helpers/WKCHTMLButtonElement.h" +#include "helpers/privates/WKCHTMLButtonElementPrivate.h" + +#include "HTMLButtonElement.h" + +namespace WKC { + +HTMLButtonElementPrivate::HTMLButtonElementPrivate(WebCore::HTMLButtonElement* parent) + : HTMLFormControlElementPrivate(parent) + , m_wkc(*this) +{ +} + +HTMLButtonElementPrivate::~HTMLButtonElementPrivate() +{ +} + +//////////////////////////////////////////////////////////////////////////////// + +HTMLButtonElement::HTMLButtonElement(HTMLButtonElementPrivate& parent) + : HTMLFormControlElement(parent) +{ +} + +} // namespace diff --git a/WKC/WebKit/WKC/helpers/privates/WKCHTMLButtonElementPrivate.h b/WKC/WebKit/WKC/helpers/privates/WKCHTMLButtonElementPrivate.h new file mode 100755 index 000000000..fcbb2f761 --- /dev/null +++ b/WKC/WebKit/WKC/helpers/privates/WKCHTMLButtonElementPrivate.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2017 ACCESS CO., LTD. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef _WKC_HELPERS_PRIVATE_HTMLBUTTONELEMENT_H_ +#define _WKC_HELPERS_PRIVATE_HTMLBUTTONELEMENT_H_ + +#include "helpers/WKCHTMLButtonElement.h" +#include "helpers/privates/WKCHTMLFormControlElementPrivate.h" + +namespace WebCore { +class HTMLButtonElement; +} // namespace + +namespace WKC { + +class HTMLButtonElementWrap : public HTMLButtonElement { +WTF_MAKE_FAST_ALLOCATED; +public: + HTMLButtonElementWrap(HTMLButtonElementPrivate& parent) : HTMLButtonElement(parent) {} + ~HTMLButtonElementWrap() {} +}; + +class HTMLButtonElementPrivate : public HTMLFormControlElementPrivate { +WTF_MAKE_FAST_ALLOCATED; +public: + HTMLButtonElementPrivate(WebCore::HTMLButtonElement*); + virtual ~HTMLButtonElementPrivate(); + +private: + HTMLButtonElementWrap m_wkc; +}; +} // namespace + +#endif // _WKC_HELPERS_PRIVATE_HTMLBUTTONELEMENT_H_ diff --git a/WKC/WebKit/WKC/helpers/privates/WKCHTMLElement.cpp b/WKC/WebKit/WKC/helpers/privates/WKCHTMLElement.cpp index 9f42849bf..165561583 100755 --- a/WKC/WebKit/WKC/helpers/privates/WKCHTMLElement.cpp +++ b/WKC/WebKit/WKC/helpers/privates/WKCHTMLElement.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2013 ACCESS CO., LTD. All rights reserved. + * Copyright (c) 2011-2017 ACCESS CO., LTD. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -23,6 +23,7 @@ #include "helpers/privates/WKCHTMLElementPrivate.h" #include "helpers/WKCString.h" #include "helpers/privates/WKCHTMLInputElementPrivate.h" +#include "helpers/privates/WKCHTMLButtonElementPrivate.h" #include "helpers/privates/WKCHTMLTextAreaElementPrivate.h" #include "helpers/privates/WKCHTMLAreaElementPrivate.h" #include "helpers/privates/WKCHTMLFormElementPrivate.h" @@ -33,6 +34,7 @@ #include "HTMLElement.h" #include "HTMLInputElement.h" +#include "HTMLButtonElement.h" #include "HTMLTextAreaElement.h" #include "HTMLAreaElement.h" #include "HTMLFormElement.h" @@ -50,6 +52,8 @@ HTMLElementPrivate::create(WebCore::HTMLElement* parent) if (parent->hasTagName(WebCore::HTMLNames::inputTag)) { return new HTMLInputElementPrivate(static_cast(parent)); + } else if (parent->hasTagName(WebCore::HTMLNames::buttonTag)) { + return new HTMLButtonElementPrivate(static_cast(parent)); } else if (parent->hasTagName(WebCore::HTMLNames::textareaTag)) { return new HTMLTextAreaElementPrivate(static_cast(parent)); } else if (parent->hasTagName(WebCore::HTMLNames::areaTag)) { diff --git a/WKC/WebKit/WKC/helpers/privates/WKCHTMLFormControlElement.cpp b/WKC/WebKit/WKC/helpers/privates/WKCHTMLFormControlElement.cpp index 05110e210..942f38b46 100755 --- a/WKC/WebKit/WKC/helpers/privates/WKCHTMLFormControlElement.cpp +++ b/WKC/WebKit/WKC/helpers/privates/WKCHTMLFormControlElement.cpp @@ -23,6 +23,7 @@ #include "helpers/privates/WKCHTMLFormControlElementPrivate.h" #include "HTMLFormControlElement.h" +#include "helpers/privates/WKCAtomicStringPrivate.h" #include "helpers/privates/WKCHTMLFormElementPrivate.h" namespace WKC { @@ -31,12 +32,16 @@ HTMLFormControlElementPrivate::HTMLFormControlElementPrivate(WebCore::HTMLFormCo : HTMLElementPrivate(parent) , m_wkc(*this) , m_formElement(0) + , m_type() + , m_atomicstring_priv(0) { } HTMLFormControlElementPrivate::~HTMLFormControlElementPrivate() { delete m_formElement; + if (m_atomicstring_priv) + delete m_atomicstring_priv; } WebCore::HTMLFormControlElement* @@ -76,6 +81,18 @@ HTMLFormControlElementPrivate::isSuccessfulSubmitButton() const return webcore()->isSuccessfulSubmitButton(); } +const AtomicString& +HTMLFormControlElementPrivate::type() +{ + m_type = webcore()->type(); + + if (m_atomicstring_priv) + delete m_atomicstring_priv; + + m_atomicstring_priv = new AtomicStringPrivate(&m_type); + return m_atomicstring_priv->wkc(); +} + //////////////////////////////////////////////////////////////////////////////// HTMLFormControlElement::HTMLFormControlElement(HTMLFormControlElementPrivate& parent) @@ -101,6 +118,12 @@ HTMLFormControlElement::isSuccessfulSubmitButton() const return static_cast(priv()).isSuccessfulSubmitButton(); } +const AtomicString& +HTMLFormControlElement::type() const +{ + return static_cast(priv()).type(); +} + HTMLFormElement* HTMLFormControlElement::form() const { diff --git a/WKC/WebKit/WKC/helpers/privates/WKCHTMLFormControlElementPrivate.h b/WKC/WebKit/WKC/helpers/privates/WKCHTMLFormControlElementPrivate.h index 884006d4e..12bfaffb4 100755 --- a/WKC/WebKit/WKC/helpers/privates/WKCHTMLFormControlElementPrivate.h +++ b/WKC/WebKit/WKC/helpers/privates/WKCHTMLFormControlElementPrivate.h @@ -22,12 +22,14 @@ #include "helpers/WKCHTMLFormControlElement.h" #include "helpers/privates/WKCHTMLElementPrivate.h" +#include "AtomicString.h" namespace WebCore { class HTMLFormControlElement; } // namespace namespace WKC { +class AtomicStringPrivate; class HTMLFormElementPrivate; class HTMLFormControlElementWrap : public HTMLFormControlElement { @@ -51,10 +53,13 @@ WTF_MAKE_FAST_ALLOCATED; void dispatchFormControlInputEvent(); void dispatchFormControlChangeEvent(); bool isSuccessfulSubmitButton() const; + const AtomicString& type(); private: HTMLFormControlElementWrap m_wkc; HTMLFormElementPrivate* m_formElement; + WTF::AtomicString m_type; + AtomicStringPrivate* m_atomicstring_priv; }; } // namespace diff --git a/WKC/WebKit/WKC/helpers/privates/WKCHTMLSelectElement.cpp b/WKC/WebKit/WKC/helpers/privates/WKCHTMLSelectElement.cpp index 40f3262e5..0877fcea1 100755 --- a/WKC/WebKit/WKC/helpers/privates/WKCHTMLSelectElement.cpp +++ b/WKC/WebKit/WKC/helpers/privates/WKCHTMLSelectElement.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013 ACCESS CO., LTD. All rights reserved. + * Copyright (c) 2013-2017 ACCESS CO., LTD. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -27,7 +27,7 @@ namespace WKC { HTMLSelectElementPrivate::HTMLSelectElementPrivate(WebCore::HTMLSelectElement* parent) - : HTMLElementPrivate(parent) + : HTMLFormControlElementPrivate(parent) { } @@ -42,7 +42,7 @@ HTMLSelectElementPrivate::showPopup() } HTMLSelectElement::HTMLSelectElement(HTMLSelectElementPrivate& parent) - : HTMLElement(parent) + : HTMLFormControlElement(parent) { } diff --git a/WKC/WebKit/WKC/helpers/privates/WKCHTMLSelectElementPrivate.h b/WKC/WebKit/WKC/helpers/privates/WKCHTMLSelectElementPrivate.h index 068e84a6d..474764bf4 100755 --- a/WKC/WebKit/WKC/helpers/privates/WKCHTMLSelectElementPrivate.h +++ b/WKC/WebKit/WKC/helpers/privates/WKCHTMLSelectElementPrivate.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013 ACCESS CO., LTD. All rights reserved. + * Copyright (c) 2013-2017 ACCESS CO., LTD. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -21,14 +21,14 @@ #define _WKC_HELPERS_PRIVATE_HTMLSELECTELEMENT_H_ #include "helpers/WKCHTMLSElectElement.h" -#include "helpers/privates/WKCHTMLElementPrivate.h" +#include "helpers/privates/WKCHTMLFormControlElementPrivate.h" namespace WebCore { class HTMLSelectElement; } // namespace namespace WKC { -class HTMLSelectElementPrivate : public HTMLElementPrivate { +class HTMLSelectElementPrivate : public HTMLFormControlElementPrivate { public: HTMLSelectElementPrivate(WebCore::HTMLSelectElement*); ~HTMLSelectElementPrivate(); diff --git a/WKC/WebKit/WKC/helpers/privates/WKCKURL.cpp b/WKC/WebKit/WKC/helpers/privates/WKCKURL.cpp index 38acc7252..9f978596a 100755 --- a/WKC/WebKit/WKC/helpers/privates/WKCKURL.cpp +++ b/WKC/WebKit/WKC/helpers/privates/WKCKURL.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2015 ACCESS CO., LTD. All rights reserved. + * Copyright (c) 2011-2017 ACCESS CO., LTD. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -114,6 +114,12 @@ WKC::KURL::lastPathComponent() const return PARENT()->lastPathComponent(); } +bool +WKC::KURL::setProtocol(const String& str) +{ + return PARENT()->setProtocol(str); +} + String decodeURLEscapeSequences(const String& str) { diff --git a/WKC/WebKit/WKC/helpers/privates/WKCNode.cpp b/WKC/WebKit/WKC/helpers/privates/WKCNode.cpp index 3cb31fbf4..6731872ff 100755 --- a/WKC/WebKit/WKC/helpers/privates/WKCNode.cpp +++ b/WKC/WebKit/WKC/helpers/privates/WKCNode.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2016 ACCESS CO., LTD. All rights reserved. + * Copyright (c) 2011-2017 ACCESS CO., LTD. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -27,6 +27,7 @@ #include "HTMLNames.h" #include "Element.h" #include "HTMLInputElement.h" +#include "HTMLButtonElement.h" #include "HTMLTextAreaElement.h" #include "HTMLAreaElement.h" #include "HTMLFormControlElement.h" @@ -106,6 +107,7 @@ NodePrivate::NodePrivate(WebCore::Node* parent) , m_traverseNextSibling(0) , m_shadowHost(0) , m_HTMLElement(0) + , m_parentOrShadowHostElement(0) { } @@ -134,6 +136,8 @@ NodePrivate::~NodePrivate() delete m_parentNamedNodeMap; if (m_HTMLElement) delete m_HTMLElement; + if (m_parentOrShadowHostElement) + delete m_parentOrShadowHostElement; } WebCore::Node* @@ -154,6 +158,8 @@ NodePrivate::hasTagName(int id) const switch (id) { case HTMLNames_inputTag: return webcore()->hasTagName(WebCore::HTMLNames::inputTag); + case HTMLNames_buttonTag: + return webcore()->hasTagName(WebCore::HTMLNames::buttonTag); case HTMLNames_textareaTag: return webcore()->hasTagName(WebCore::HTMLNames::textareaTag); case HTMLNames_selectTag: @@ -168,6 +174,8 @@ NodePrivate::hasTagName(int id) const return m_webcore->hasTagName(WebCore::HTMLNames::videoTag); case HTMLNames_areaTag: return webcore()->hasTagName(WebCore::HTMLNames::areaTag); + case HTMLNames_aTag: + return webcore()->hasTagName(WebCore::HTMLNames::aTag); default: return false; } @@ -475,6 +483,19 @@ NodePrivate::getNodeCompositeRect(WKCRect* rect, int tx, int ty) rect->fWidth = core_rect.width(); rect->fHeight = core_rect.height(); } + +Element* +NodePrivate::parentOrShadowHostElement() +{ + WebCore::Element* elem = webcore()->parentOrShadowHostElement(); + if (!elem) + return 0; + if (!m_parentOrShadowHostElement || m_parentOrShadowHostElement->webcore() != elem) { + delete m_parentOrShadowHostElement; + m_parentOrShadowHostElement = ElementPrivate::create(elem); + } + return &m_parentOrShadowHostElement->wkc(); +} //////////////////////////////////////////////////////////////////////////////// @@ -689,4 +710,10 @@ Node::querySelectorAll(const String& selectors) return m_private.querySelectorAll(selectors); } +Element* +Node::parentOrShadowHostElement() +{ + return priv().parentOrShadowHostElement(); +} + } // namespace diff --git a/WKC/WebKit/WKC/helpers/privates/WKCNodePrivate.h b/WKC/WebKit/WKC/helpers/privates/WKCNodePrivate.h index 334a73b82..47342867d 100755 --- a/WKC/WebKit/WKC/helpers/privates/WKCNodePrivate.h +++ b/WKC/WebKit/WKC/helpers/privates/WKCNodePrivate.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2016 ACCESS CO., LTD. All rights reserved. + * Copyright (c) 2011-2017 ACCESS CO., LTD. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -95,6 +95,8 @@ WTF_MAKE_FAST_ALLOCATED; NodeList* getElementsByTagName(const String&); NodeList* querySelectorAll(const String&); + Element* parentOrShadowHostElement(); + private: friend class ElementPrivate; friend class DocumentPrivate; @@ -119,6 +121,8 @@ WTF_MAKE_FAST_ALLOCATED; HTMLElementPrivate* m_HTMLElement; NodeListPrivate* m_nodeList; NodeListPrivate* m_querySelectorNodeList; + + ElementPrivate* m_parentOrShadowHostElement; }; } // namespace diff --git a/WKC/WebKit/WKC/helpers/privates/WKCString.cpp b/WKC/WebKit/WKC/helpers/privates/WKCString.cpp index 836aec295..91608dbcf 100755 --- a/WKC/WebKit/WKC/helpers/privates/WKCString.cpp +++ b/WKC/WebKit/WKC/helpers/privates/WKCString.cpp @@ -3,7 +3,7 @@ * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. * Copyright (C) 2007-2009 Torch Mobile, Inc. * Copyright (C) 2011 Torch Mobile, Inc. - * Copyright (c) 2011-2016 ACCESS CO., LTD. All rights reserved. + * Copyright (c) 2011-2017 ACCESS CO., LTD. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -548,6 +548,13 @@ String::isEmpty() const return a.isEmpty(); } +bool +String::endsWith(const String& str) const +{ + const WTF::String a(IMPL()); + return a.endsWith(str); +} + TextDirection String::direction() const { diff --git a/WKC/WebKit/WKC/webkit/WKCPrefs.cpp b/WKC/WebKit/WKC/webkit/WKCPrefs.cpp index 83cd55afe..4a6b06ab2 100755 --- a/WKC/WebKit/WKC/webkit/WKCPrefs.cpp +++ b/WKC/WebKit/WKC/webkit/WKCPrefs.cpp @@ -1,7 +1,7 @@ /* * WKCPrefs.cpp * - * Copyright (c) 2011-2016 ACCESS CO., LTD. All rights reserved. + * Copyright (c) 2011-2017 ACCESS CO., LTD. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -40,6 +40,7 @@ #include "platform/ScrollView.h" #include +#include #include #include "NotImplemented.h" @@ -525,6 +526,14 @@ setUseNearestFilter(bool flag) wkcDrawContexCairoSetUseFilterNearestPeer(flag); } +void +activateWebGL() +{ +#if ENABLE(WEBGL) + bool ret = wkcGLActivatePeer(); +#endif +} + void forceTerminate() { diff --git a/WKC/WebKit/WKC/webkit/WKCPrefs.h b/WKC/WebKit/WKC/webkit/WKCPrefs.h index 49e352cf8..acef5495d 100755 --- a/WKC/WebKit/WKC/webkit/WKCPrefs.h +++ b/WKC/WebKit/WKC/webkit/WKCPrefs.h @@ -1,7 +1,7 @@ /* * WKCPrefs.h * - * Copyright (c) 2011-2016 ACCESS CO., LTD. All rights reserved. + * Copyright (c) 2011-2017 ACCESS CO., LTD. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -592,6 +592,13 @@ namespace WKCPrefs { */ WKC_API void setUseNearestFilter(bool flag); + /** + @brief activate WebGL + @details + Activates WebGL functions. + */ + WKC_API void activateWebGL(); + /*@}*/ } // namespace diff --git a/WKC/WebKit/WKC/webkit/WKCVersion.h b/WKC/WebKit/WKC/webkit/WKCVersion.h index 41c13f5c7..5d5631a86 100755 --- a/WKC/WebKit/WKC/webkit/WKCVersion.h +++ b/WKC/WebKit/WKC/webkit/WKCVersion.h @@ -29,7 +29,7 @@ #define WKC_VERSION_CHECK(major, minor, micro) \ (((major)*10000) + ((minor)*100) + (micro)) >= ((WKC_VERSION_MAJOR*10000) + (WKC_VERSION_MINOR*100) + (WKC_VERSION_MICRO)) -#define WKC_CUSTOMER_RELEASE_VERSION "0.5.10" +#define WKC_CUSTOMER_RELEASE_VERSION "0.6.9" #define WKC_WEBKIT_VERSION "601.6" diff --git a/WKC/WebKit/WKC/webkit/WKCWebFrame.cpp b/WKC/WebKit/WKC/webkit/WKCWebFrame.cpp index 8fe3d771f..e50b5c14e 100755 --- a/WKC/WebKit/WKC/webkit/WKCWebFrame.cpp +++ b/WKC/WebKit/WKC/webkit/WKCWebFrame.cpp @@ -1,7 +1,7 @@ /* * WKCWebFrame.cpp * - * Copyright (c) 2010-2016 ACCESS CO., LTD. All rights reserved. + * Copyright (c) 2010-2017 ACCESS CO., LTD. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -49,9 +49,7 @@ #include "IconLoader.h" #include "ImageWKC.h" #include -#ifdef WKC_ENABLE_CUSTOMJS -#include "ScriptValue.h" -#endif // WKC_ENABLE_CUSTOMJS +#include "bindings/ScriptValue.h" #if ENABLE(MHTML) #include "MHTMLArchive.h" #endif @@ -843,6 +841,8 @@ WKCWebFrame::setForcedSandboxNavigation() coreFrame->loader().forceSandboxFlags(WebCore::SandboxNavigation); } +#endif // WKC_ENABLE_CUSTOMJS + void WKCWebFrame::executeScript(const char* script) { @@ -854,8 +854,6 @@ WKCWebFrame::executeScript(const char* script) coreFrame->script().executeScript(WTF::String::fromUTF8(script), true); } -#endif // WKC_ENABLE_CUSTOMJS - void WKCWebFrame::setJavaScriptPaused(bool pause) { diff --git a/WKC/WebKit/WKC/webkit/WKCWebFrame.h b/WKC/WebKit/WKC/webkit/WKCWebFrame.h index d5c000421..a351caf95 100755 --- a/WKC/WebKit/WKC/webkit/WKCWebFrame.h +++ b/WKC/WebKit/WKC/webkit/WKCWebFrame.h @@ -1,7 +1,7 @@ /* * WKCWebFrame.h * - * Copyright (c) 2010-2015 ACCESS CO., LTD. All rights reserved. + * Copyright (c) 2010-2017 ACCESS CO., LTD. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -274,8 +274,8 @@ class WKC_API WKCWebFrame WKCCustomJSAPIList* getCustomJSStringAPIInternal(const char* api_name); void setForcedSandboxNavigation(); - void executeScript(const char* script); #endif // WKC_ENABLE_CUSTOMJS + void executeScript(const char* script); /** @brief Pause or restart JavaScripts executions. diff --git a/WKC/WebKit/WKC/webkit/WKCWebView.cpp b/WKC/WebKit/WKC/webkit/WKCWebView.cpp index d1505fab0..56b244d32 100755 --- a/WKC/WebKit/WKC/webkit/WKCWebView.cpp +++ b/WKC/WebKit/WKC/webkit/WKCWebView.cpp @@ -1106,10 +1106,14 @@ WKCWebViewPrivate::notifyServiceScriptedAnimations() WebCore::MainFrame& frame = core()->mainFrame(); if (!frame.view()) return; double cur = WTF::monotonicallyIncreasingTime(); +#if ENABLE(WEBGL) wkcGLBeginPaintPeer(); +#endif frame.view()->serviceScriptedAnimations(cur); +#if ENABLE(WEBGL) wkcGLEndPaintPeer(); #endif +#endif } void @@ -1442,13 +1446,13 @@ void WKCWebView::notifyRelayout(bool force) { if (force) { - WebCore::Frame* frame = (WebCore::Frame *)&m_private->core()->mainFrame(); - if (!frame) return; - WebCore::Document* document = frame->document(); - if (!document) return; - WebCore::RenderView* renderView = document->renderView(); - if (!renderView) return; - renderView->setNeedsLayout(); + WebCore::Frame* mainFrame = (WebCore::Frame *)&m_private->core()->mainFrame(); + for (WebCore::Frame* frame = mainFrame; frame; frame = frame->tree().traverseNext()) { + WebCore::RenderView* renderView = frame->contentRenderer(); + if (!renderView) + continue; + renderView->setNeedsLayout(); + } } m_private->notifyRelayout(); } @@ -1713,13 +1717,6 @@ WKCWebView::notifyMouseMoveTest(const WKCPoint& pos, WKC::MouseButton button, Mo if (!renderer || !targetNode) return notifyMouseMove(pos, button, modifiers); - for (WebCore::Node* n = linkNode; n && n != targetNode; n = n->parentNode()) { - if (n->hasEventListeners(WebCore::eventNames().mouseoverEvent) && - n->hasEventListeners(WebCore::eventNames().mousemoveEvent)) { - contentChanged = true; - return notifyMouseMove(pos, button, modifiers); - } - } for (WebCore::Node* n = targetNode; n; n = n->parentNode()) { if (n == linkNode) return notifyMouseMove(pos, button, modifiers); @@ -1755,14 +1752,6 @@ WKCWebView::notifyMouseMoveTest(const WKCPoint& pos, WKC::MouseButton button, Mo renderer = targetNode->renderer(); - for (WebCore::Node* n = linkNode; n && n != targetNode; n = n->parentNode()) { - if (n->hasEventListeners(WebCore::eventNames().mouseoverEvent) && - n->hasEventListeners(WebCore::eventNames().mousemoveEvent)) { - contentChanged = true; - goto exit; - } - } - if (getRendererCount(renderer, linkNode) != rendererCount) { contentChanged = true; goto exit; @@ -2835,7 +2824,7 @@ WKCWebView::releaseMemory(ReleaseMemoryType type, bool is_synchronous) #if ENABLE(WKC_HTTPCACHE) if (type & EMemoryTypeNoncriticalHTTPCache) { - WebCore::ResourceHandleManager::sharedInstance()->clearHTTPCache(); + WebCore::ResourceHandleManager::sharedInstance()->resetHTTPCache(); } #endif @@ -3058,14 +3047,16 @@ bool WKCWebView::clickableFromPoint(int x, int y) { WKC::Element* pelement = getElementFromPoint(x, y); + return isClickableElement(pelement); +} - if (pelement) { - WebCore::Element* element = (WebCore::Element *)pelement->priv().webcore(); - if (element->hasEventListeners(WebCore::eventNames().clickEvent)) { - return true; - } +bool +WKCWebView::isClickableElement(WKC::Element* element) +{ + if (!element) { + return false; } - return false; + return m_private->core()->focusController().isClickableElement((WebCore::Element *)element->priv().webcore()); } bool @@ -3462,7 +3453,8 @@ static void WKCWebkitPrepareRestart() { if (!wkcThreadCurrentIsMainThreadPeer()) { - if (WebCore::ResourceHandleManager::sharedInstance()->isNetworkThread()) { + if (WebCore::ResourceHandleManager::isExistSharedInstance() && + WebCore::ResourceHandleManager::sharedInstance()->isNetworkThread()) { WebCore::ResourceHandleManager::sharedInstance()->notifyRequestRestartInNetworkThread(); } } @@ -3961,12 +3953,23 @@ WKCWebKitSetLayerCallbacks(const LayerCallbacks* callbacks) callbacks->fTextureUpdateProc, callbacks->fTextureChangeProc, callbacks->fDidChangeParentProc, - callbacks->fCanAllocateProc); + callbacks->fCanAllocateProc, + callbacks->fAttachedGlTexturesProc); #endif } void -WKCWebKitGetLayerProperties(void* layer, void** opaque_texture, int* width, int* height, bool* need_yflip, void** out_offscreen, int* offscreenwidth, int* offscreenheight) +WKCWebKitSetWebGLTextureCallbacks(const WebGLTextureCallbacks* callbacks) +{ +#if ENABLE(WEBGL) + wkcGLRegisterTextureCallbacksPeer(callbacks->fTextureMakeProc, + callbacks->fTextureDeleteProc, + callbacks->fTextureChangeProc); +#endif +} + +void +WKCWebKitGetLayerProperties(void* layer, void** opaque_texture, int* width, int* height, bool* need_yflip, void** out_offscreen, int* offscreenwidth, int* offscreenheight, bool* is_3dcanvas) { #if USE(ACCELERATED_COMPOSITING) if (opaque_texture) @@ -3979,6 +3982,10 @@ WKCWebKitGetLayerProperties(void* layer, void** opaque_texture, int* width, int* *out_offscreen = wkcLayerGetOffscreenPeer(layer); if (offscreenwidth && offscreenheight) wkcLayerGetOriginalSizePeer(layer, offscreenwidth, offscreenheight); + if (is_3dcanvas) { + *is_3dcanvas = (wkcLayerGetTypePeer(layer) == WKC_LAYER_TYPE_3DCANVAS) ? true : false; + } + #else if (opaque_texture) *opaque_texture = 0; @@ -4255,6 +4262,12 @@ void WKCWebKitSetPasteboardProcs(const WKC::PasteboardProcs* procs) wkcPasteboardCallbackSetPeer(static_cast(procs)); } +// Thread +void WKCWebKitSetThreadProcs(const WKC::ThreadProcs* procs) +{ + wkcThreadCallbackSetPeer(static_cast(procs)); +} + // glyph / image cache bool WKCWebKitSetGlyphCache(int format, void* cache, const WKCSize* size) { @@ -5169,13 +5182,6 @@ WKCWebView::recalcStyleSheet() m_private->recalcStyleSheet(); } -// thread priority -void -WKCWebkitSetThreadPriorityCallback(WKC::SetThreadPriorityProc in_proc) -{ - wkcThreadSetThreadPriorityProcPeer(in_proc); -} - // cancel range input dragging mode. void diff --git a/WKC/WebKit/WKC/webkit/WKCWebView.h b/WKC/WebKit/WKC/webkit/WKCWebView.h index a2f173c2d..6ed77bc6a 100755 --- a/WKC/WebKit/WKC/webkit/WKCWebView.h +++ b/WKC/WebKit/WKC/webkit/WKCWebView.h @@ -40,6 +40,7 @@ #include #include #include +#include // prototypes namespace WKC { @@ -75,6 +76,7 @@ namespace WKC { typedef WKCMediaPlayerProcs MediaPlayerProcs; /** @brief Type definition of PasteboardProcs. For more information, see the section "Structure - WKCPasteboardProcs_" in "NetFront Browser NX $(NETFRONT_NX_VERSION) WKC Peer API Reference". */ typedef WKCPasteboardProcs PasteboardProcs; + typedef WKCThreadProcs ThreadProcs; /** @brief Structure for storing client certificate informations */ struct clientCertInfo_ { @@ -163,12 +165,13 @@ namespace WKC { } WKCEPUBData; typedef struct LayerCallbacks_ { - bool (*fTextureMakeProc)(void* in_layer, int in_width, int in_height, int in_bpp, void** out_bitmap, int* out_rowbytes, int* out_width, int* out_height, void** out_opaque_texture); + bool (*fTextureMakeProc)(void* in_layer, int in_width, int in_height, int in_bpp, void** out_bitmap, int* out_rowbytes, int* out_width, int* out_height, void** out_opaque_texture, bool is_3dcanvas); void (*fTextureDeleteProc)(void *in_layer, void* in_bitmap); - void (*fTextureUpdateProc)(void *in_opaque, int in_width, int in_height, void *in_bitmap); - bool (*fTextureChangeProc)(void* in_layer, int in_width, int in_height, int in_bpp, void** out_bitmap, int* out_rowbytes, int* out_width, int* out_height, void** out_opaque_texture); + void (*fTextureUpdateProc)(void *in_opaque, int in_width, int in_height, void *in_bitmap, int in_texture); + bool (*fTextureChangeProc)(void* in_layer, int in_width, int in_height, int in_bpp, void** out_bitmap, int* out_rowbytes, int* out_width, int* out_height, void** out_opaque_texture, bool is_3dcanvas); void (*fDidChangeParentProc)(void *in_layer); bool (*fCanAllocateProc)(int in_width, int in_height, int in_blendmode); + void (*fAttachedGlTexturesProc)(void* in_layer, int* in_textures, int in_num); } LayerCallbacks; enum { @@ -186,6 +189,12 @@ namespace WKC { typedef void (*SetThreadPriorityProc)(const char* in_name, int* out_priority, int* out_core); typedef void (*FontNoMemoryProc)(); typedef void (*GetCurrentTimeProc)(wkc_int64* out_posixtime); + + typedef struct WebGLTextureCallbacks_ { + bool (*fTextureMakeProc)(int num, unsigned int* out_textures); + void (*fTextureDeleteProc)(int num, unsigned int* in_textures); + bool (*fTextureChangeProc)(int num, unsigned int* inout_textures); + } WebGLTextureCallbacks; } /*@}*/ @@ -394,6 +403,19 @@ WKC_API void WKCWebKitSetHWOffscreenDeviceParams(const HWOffscreenDeviceParams* Sets layer callbacks. This function is needed for specific targets. */ WKC_API void WKCWebKitSetLayerCallbacks(const LayerCallbacks* callbacks); + +/** +@brief Sets WebGL texture callbacks +@param callbacks Callbacks +@details +Sets WebGL texture creation related callbacks. +If the application have to manage OpenGL texture creation/destruction, +then register callbacks with this API. +Or the textures will be created/destroyed inside the engine. +This function must be called before loading any WebGL contents. +*/ +WKC_API void WKCWebKitSetWebGLTextureCallbacks(const WebGLTextureCallbacks* callbacks); + /** @brief Gets layer infos @param layer Layer @@ -404,10 +426,11 @@ WKC_API void WKCWebKitSetLayerCallbacks(const LayerCallbacks* callbacks); @param offscreen Offscreen @param offscreenwidth Offscreen width @param offscreenheight Offscreen height +@param is_3dcanvas whether 3d canvas or not @details Obtains layer infos */ -WKC_API void WKCWebKitGetLayerProperties(void* layer, void** opaque_texture, int* width, int* height, bool* need_yflip, void** offscreen, int*offscreenwidth, int* offscreenheight); +WKC_API void WKCWebKitGetLayerProperties(void* layer, void** opaque_texture, int* width, int* height, bool* need_yflip, void** offscreen, int*offscreenwidth, int* offscreenheight, bool* is_3dcanvas); /** @brief Create an offscreen @@ -646,6 +669,7 @@ Registers callback to set processing for the platform pasteboard. All WKC::PasteboardProcs member callbacks must be implemented. */ WKC_API void WKCWebKitSetPasteboardProcs(const WKC::PasteboardProcs* procs); +WKC_API void WKCWebKitSetThreadProcs(const WKC::ThreadProcs* procs); /** @brief get server certificate chian @param in_url url @@ -874,14 +898,6 @@ Set performance mode. */ WKC_API void WKCWebKitSetPerformanceMode(int in_mode); -/** -@brief Set thread priority proc. -@param in_proc Callback of set thread priority. -@details -Set thread priority callback. -*/ -WKC_API void WKCWebkitSetThreadPriorityCallback(WKC::SetThreadPriorityProc in_proc); - /** @brief Cancel dragging mode of range input element. @details @@ -1961,7 +1977,7 @@ class WKC_API WKCWebView */ WKC::Element* getElementFromPoint(int x, int y); /** - @brief Gets information about whether element below pointer is clickable or not (whether there is a click event listener) using specified coordinates + @brief Gets information about whether element below pointer is clickable or not using specified coordinates @param x X coordinate @param y Y coordinate @retval "!= false" Clickable @@ -1970,6 +1986,13 @@ class WKC_API WKCWebView Every coordinate value must be specified using the same coordinate system as WKC::WKCWebView::notifyMouseDown (Move, Up). */ bool clickableFromPoint(int x, int y); + /** + @brief Gets information about whether specified element is clickable or not + @param element Pointer to element + @retval "!= false" Clickable + @retval "== false" Not clickable + */ + bool isClickableElement(WKC::Element* element); /** @brief Gets information about whether element below pointer is draggable or not (whether there is an ondrag, dragstart, or dragend event listener) using specified coordinates @param x X coordinate diff --git a/WKC/include/wkc/wkcglpeer.h b/WKC/include/wkc/wkcglpeer.h index 52a3846c5..879ce3958 100755 --- a/WKC/include/wkc/wkcglpeer.h +++ b/WKC/include/wkc/wkcglpeer.h @@ -1,7 +1,7 @@ /* * wkcglpeer.h * - * Copyright(c) 2009-2015 ACCESS CO., LTD. All rights reserved. + * Copyright(c) 2009-2017 ACCESS CO., LTD. All rights reserved. */ #ifndef _WKC_GL_PEER_H_ @@ -45,15 +45,29 @@ struct WKCGLAttributes_ { bool fStencil; bool fAntialias; bool fPremultipliedAlpha; - bool fCanRecoverFromContextLoss; bool fPreserveDrawingBuffer; bool fNoExtensions; bool fShareResources; - bool fPreferDiscreteGPU; + bool fPreferLowPowerToHighPerformance; + bool fForceSoftwareRenderer; + bool fFailIfMajorPerformanceCaveat; + bool fUseGLES3; + float fDevicePixelRatio; }; /** @brief Type definitions of WKCGLAttributes */ typedef struct WKCGLAttributes_ WKCGLAttributes; + +/** @brief callback definitions for wkcGLRegisterTextureCallbacksPeer */ +typedef bool (*wkcGLTextureMakeProc)(int num, unsigned int* out_textures); +typedef void (*wkcGLTextureDeleteProc)(int num, unsigned int* in_textures); +typedef bool (*wkcGLTextureChangeProc)(int num, unsigned int* inout_textures); + +/** @brief callback definitions for wkcGLRegisterOffscreenBufferCallbacksPeer */ +typedef bool (*wkcGLOffscreenBufferMakeProc)(int in_width, int in_height, int in_bpp, void** out_buffer); +typedef void (*wkcGLOffscreenBufferDeleteProc)(void* in_buffer); +typedef bool (*wkcGLOffscreenBufferChangeProc)(int in_width, int in_height, int in_bpp, void** inout_buffer); + /* initialize / finalize / force-terminate GL peers */ @@ -65,6 +79,39 @@ typedef struct WKCGLAttributes_ WKCGLAttributes; Write the necessary processes for initializing the GL peer layer. */ WKC_PEER_API bool wkcGLInitializePeer(void); + +/** +@brief Enable GL peer +@retval !=false Succeeded +@retval ==false Failed +@details +This API must be called after wkcGLInitializePeer +*/ +WKC_PEER_API bool wkcGLActivatePeer(); + +/** +@brief Registeres callbacks for texture creation in peers +@details +This API must call before loading any WebGL contents. +*/ +WKC_PEER_API void wkcGLRegisterTextureCallbacksPeer( + wkcGLTextureMakeProc in_texture_maker_proc, + wkcGLTextureDeleteProc in_texture_deleter_proc, + wkcGLTextureChangeProc in_texture_changer_proc + ); + +/** +@brief Registeres callbacks for offscreen buffer for GL peers +@details +This API must call before loading any WebGL contents. +This buffer is used for showing gl texture without AC layers. +*/ +WKC_PEER_API void wkcGLRegisterOffscreenBufferCallbacksPeer( + wkcGLOffscreenBufferMakeProc in_buf_creater_proc, + wkcGLOffscreenBufferDeleteProc in_buf_deleter_proc, + wkcGLOffscreenBufferChangeProc in_buf_changer_proc + ); + /** @brief Finalizes GL peer @details @@ -92,10 +139,11 @@ WKC_PEER_API void wkcGLRegisterDeviceLockProcsPeer(void(*in_lock)(void*), void(* @brief Create GL peer instances @param inout_attr HW attributes @param in_hostwindow WebCore::HostWindow itself +@param in_layer WKCGenericLayer @details Creates GL context. */ -WKC_PEER_API void* wkcGLCreateContextPeer(WKCGLAttributes* inout_attr, void* in_hostwindow); +WKC_PEER_API void* wkcGLCreateContextPeer(WKCGLAttributes* inout_attr, void* in_hostwindow, void* in_layer); /** @brief Delete GL peer instances @param in_context context diff --git a/WKC/include/wkc/wkcgpeer.h b/WKC/include/wkc/wkcgpeer.h index 06be121bd..4271ba322 100755 --- a/WKC/include/wkc/wkcgpeer.h +++ b/WKC/include/wkc/wkcgpeer.h @@ -1,7 +1,7 @@ /* * wkcgpeer.h * - * Copyright(c) 2009-2016 ACCESS CO., LTD. All rights reserved. + * Copyright(c) 2009-2017 ACCESS CO., LTD. All rights reserved. */ #ifndef _WKC_G_PEER_H_ @@ -1215,21 +1215,23 @@ enum { WKC_LAYER_BLENDMODE_PLUSLIGHTER }; -typedef bool (*wkcLayerTextureMakeProc)(void* in_layer, int in_width, int in_height, int in_bpp, void** out_bitmap, int* out_rowbytes, int* out_width, int* out_height, void** out_opaque_texture); +typedef bool (*wkcLayerTextureMakeProc)(void* in_layer, int in_width, int in_height, int in_bpp, void** out_bitmap, int* out_rowbytes, int* out_width, int* out_height, void** out_opaque_texture, bool is_3dcanvas); typedef void (*wkcLayerTextureDeleteProc)(void *in_layer, void* in_bitmap); -typedef void (*wkcLayerTextureUpdateProc)(void *in_opaque, int in_width, int in_height, void *in_bitmap); +typedef void (*wkcLayerTextureUpdateProc)(void *in_opaque, int in_width, int in_height, void *in_bitmap, int in_texture); typedef void (*wkcLayerDidChangeParentProc)(void *in_layer); typedef bool (*wkcLayerCanAllocateProc)(int in_width, int in_height, int blendmode); typedef wkcLayerTextureMakeProc wkcLayerTextureChangeProc; typedef void (*wkcLayerDidChangeParentProc)(void *in_layer); +typedef void (*wkcLayerAttachedGlTexturesProc)(void *in_layer, int* in_textures, int in_num); WKC_PEER_API void wkcLayerInitializePeer(void); WKC_PEER_API void wkcLayerFinalizePeer(void); WKC_PEER_API void wkcLayerForceTerminatePeer(void); -WKC_PEER_API void wkcLayerInitializeCallbacksPeer(wkcLayerTextureMakeProc in_texture_maker_proc, wkcLayerTextureDeleteProc in_texture_deleter_proc, wkcLayerTextureUpdateProc in_texture_updater_proc, wkcLayerTextureChangeProc in_texture_changer_proc, wkcLayerDidChangeParentProc in_did_change_parent_proc, wkcLayerCanAllocateProc in_can_allocate_proc); +WKC_PEER_API void wkcLayerInitializeCallbacksPeer(wkcLayerTextureMakeProc in_texture_maker_proc, wkcLayerTextureDeleteProc in_texture_deleter_proc, wkcLayerTextureUpdateProc in_texture_updater_proc, wkcLayerTextureChangeProc in_texture_changer_proc, wkcLayerDidChangeParentProc in_did_change_parent_proc, wkcLayerCanAllocateProc in_can_allocate_proc, wkcLayerAttachedGlTexturesProc in_attached_gl_textures_proc); WKC_PEER_API void* wkcLayerNewPeer(int in_type, const WKCSize* in_size, float in_opticalzoomlevel); WKC_PEER_API void wkcLayerDeletePeer(void* in_layer); +WKC_PEER_API void wkcLayerAttachGLTexturesPeer(void* in_layer, int* in_textures, int in_num); WKC_PEER_API int wkcLayerGetTypePeer(void* in_layer); WKC_PEER_API int wkcLayerGetTexturePeer(void* in_layer); WKC_PEER_API void* wkcLayerGetOffscreenPeer(void* in_layer); diff --git a/WKC/include/wkc/wkcmediapeer.h b/WKC/include/wkc/wkcmediapeer.h index 353e929b3..faa7a2f91 100755 --- a/WKC/include/wkc/wkcmediapeer.h +++ b/WKC/include/wkc/wkcmediapeer.h @@ -1322,12 +1322,26 @@ WKC_PEER_API float wkcAudioGetVolumePeer(void* in_self); @param in_self Device descriptor @param in_data Stream @param in_len Stream length -@retval WKC_MEDIA_ERROR_OK Succeeded -@retval WKC_MEDIA_ERROR_GENERIC Failed +@retval Size of consumed data @details Write the process for outputting the stream specified by in_data and in_len to the device. */ -WKC_PEER_API int wkcAudioWritePeer(void* in_self, void* in_data, unsigned int in_len); +WKC_PEER_API unsigned int wkcAudioWritePeer(void* in_self, void* in_data, unsigned int in_len); +/** +@brief Outputs to audio device +@param in_self Device descriptor +@param in_data Pointer to array of channel data +@param in_channels Number of channels +@param in_frame_count Count of frames in each channel data +@param in_max_abs_value Pointer to array of the maximum absolute value in each channel data +@retval !=false Succeeded +@retval ==false Failed +@details +Write the process for outputting the stream specified by in_data to the device. +If the return value is not false, wkcAudioWriteRawPeer will be called again with the next data after some sleep. +If the return value is false, wkcAudioWriteRawPeer will be called again with the same data after some sleep. +*/ +WKC_PEER_API bool wkcAudioWriteRawPeer(void* in_self, float** in_data, unsigned int in_channels, unsigned int in_frame_count, float* in_max_abs_value); /** @brief Returns preferred sample rate of audio device @retval Preferred sample rate of audio device diff --git a/WKC/include/wkc/wkcpeer.h b/WKC/include/wkc/wkcpeer.h index 6a396e729..cad6f6183 100755 --- a/WKC/include/wkc/wkcpeer.h +++ b/WKC/include/wkc/wkcpeer.h @@ -1,7 +1,7 @@ /* * wkcpeer.h * - * Copyright(c) 2009-2016 ACCESS CO., LTD. All rights reserved. + * Copyright(c) 2009-2017 ACCESS CO., LTD. All rights reserved. */ #ifndef _WKC_PEER_H_ @@ -10,6 +10,7 @@ #include #include +#include /** @file @@ -226,8 +227,13 @@ WKC_PEER_API double wkcGetMonotonicallyIncreasingTimePeer(void); /** @brief Function that is executed in generated thread */ typedef void* (*wkcThreadProc)(void *); -/** @brief Function that is set thread priority. */ -typedef void (*wkcSetThreadPriorityProc)(const char* in_name, int* out_priority, int* out_core); +/** +@brief Set callback function for threads. +@param in_proc Pointer to callback function. +@details +Set callback function for threads. +*/ +WKC_PEER_API void wkcThreadCallbackSetPeer(const WKCThreadProcs* in_procs); /** @brief Initializes Thread Peer layer @@ -635,14 +641,6 @@ The behavior must be the same as the pthread_once() function. */ WKC_PEER_API void wkcThreadOncePeer(void* in_key, void(*in_func)(void)); -/** -@brief Set callback function that sets thread priority -@param in_proc Callback function pointer for set thread priority. -@details -Set the function that sets thread priority. -*/ -WKC_PEER_API void wkcThreadSetThreadPriorityProcPeer(wkcSetThreadPriorityProc in_proc); - #ifdef WKC_LIGHTMUTEX_TYPE typedef WKC_LIGHTMUTEX_TYPE WKCLightMutex; #else diff --git a/WKC/include/wkcplatform.h b/WKC/include/wkcplatform.h index 04d7d0af1..55936b159 100755 --- a/WKC/include/wkcplatform.h +++ b/WKC/include/wkcplatform.h @@ -4,7 +4,7 @@ * Copyright (C) 2006-2009, 2013-2015 Apple Inc. All rights reserved. * Copyright (C) 2007-2009 Torch Mobile, Inc. * Copyright (C) 2010, 2011 Research In Motion Limited. All rights reserved. - * Copyright (c) 2010-2016 ACCESS CO., LTD. All rights reserved. + * Copyright (c) 2010-2017 ACCESS CO., LTD. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -133,7 +133,7 @@ #define ENABLE_MEDIA_CONTROLS_SCRIPT 1 #define ENABLE_ENCRYPTED_MEDIA 0 #define ENABLE_ENCRYPTED_MEDIA_V2 0 -#define ENABLE_WEB_AUDIO 0 +#define ENABLE_WEB_AUDIO 1 #define ENABLE_FILTERS_LEVEL_2 0 #define ENABLE_SVG_FONTS 1 @@ -190,6 +190,7 @@ #define ENABLE_APNG 1 #define USE_WEBP 1 +#define ENABLE_WKC_BLINK_AWEBP 1 #define ENABLE_WKC_WEB_NFC 0 diff --git a/webkit/JavaScriptCore/API/JSObjectRef.cpp b/webkit/JavaScriptCore/API/JSObjectRef.cpp index faf38ff8c..afcb2be29 100755 --- a/webkit/JavaScriptCore/API/JSObjectRef.cpp +++ b/webkit/JavaScriptCore/API/JSObjectRef.cpp @@ -423,19 +423,19 @@ bool JSObjectSetPrivate(JSObjectRef object, void* data) // Get wrapped object if proxied if (jsObject->inherits(JSProxy::info())) - jsObject = jsCast(jsObject)->target(); + jsObject = static_cast(jsObject)->target(); if (jsObject->inherits(JSCallbackObject::info())) { - jsCast*>(jsObject)->setPrivate(data); + static_cast*>(jsObject)->setPrivate(data); return true; } if (jsObject->inherits(JSCallbackObject::info())) { - jsCast*>(jsObject)->setPrivate(data); + static_cast*>(jsObject)->setPrivate(data); return true; } #if JSC_OBJC_API_ENABLED if (jsObject->inherits(JSCallbackObject::info())) { - jsCast*>(jsObject)->setPrivate(data); + static_cast*>(jsObject)->setPrivate(data); return true; } #endif diff --git a/webkit/JavaScriptCore/API/JSVirtualMachine.mm b/webkit/JavaScriptCore/API/JSVirtualMachine.mm index d4995ad92..5acf3f7cf 100755 --- a/webkit/JavaScriptCore/API/JSVirtualMachine.mm +++ b/webkit/JavaScriptCore/API/JSVirtualMachine.mm @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Apple Inc. All rights reserved. + * Copyright (C) 2013-2017 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -159,6 +159,7 @@ - (bool)isOldExternalObject:(id)object - (void)addExternalRememberedObject:(id)object { + auto locker = holdLock(m_externalDataMutex); ASSERT([self isOldExternalObject:object]); [m_externalRememberedSet setObject:[NSNumber numberWithBool:true] forKey:object]; } @@ -178,6 +179,7 @@ - (void)addManagedReference:(id)object withOwner:(id)owner if ([self isOldExternalObject:owner] && ![self isOldExternalObject:object]) [self addExternalRememberedObject:owner]; + auto externalDataMutexLocker = holdLock(m_externalDataMutex); NSMapTable *ownedObjects = [m_externalObjectGraph objectForKey:owner]; if (!ownedObjects) { NSPointerFunctionsOptions weakIDOptions = NSPointerFunctionsWeakMemory | NSPointerFunctionsObjectPersonality; @@ -205,6 +207,7 @@ - (void)removeManagedReference:(id)object withOwner:(id)owner JSC::JSLockHolder locker(toJS(m_group)); + auto externalDataMutexLocker = holdLock(m_externalDataMutex); NSMapTable *ownedObjects = [m_externalObjectGraph objectForKey:owner]; if (!ownedObjects) return; @@ -251,6 +254,11 @@ - (void)addContext:(JSContext *)wrapper forGlobalContextRef:(JSGlobalContextRef) NSMapInsert(m_contextCache, globalContext, wrapper); } +- (Lock&)externalDataMutex +{ + return m_externalDataMutex; +} + - (NSMapTable *)externalObjectGraph { return m_externalObjectGraph; @@ -263,13 +271,14 @@ - (NSMapTable *)externalRememberedSet @end -void scanExternalObjectGraph(JSC::VM& vm, JSC::SlotVisitor& visitor, void* root) +static void scanExternalObjectGraph(JSC::VM& vm, JSC::SlotVisitor& visitor, void* root, bool lockAcquired) { @autoreleasepool { JSVirtualMachine *virtualMachine = [JSVMWrapperCache wrapperForJSContextGroupRef:toRef(&vm)]; if (!virtualMachine) return; NSMapTable *externalObjectGraph = [virtualMachine externalObjectGraph]; + Lock& externalDataMutex = [virtualMachine externalDataMutex]; Vector stack; stack.append(root); while (!stack.isEmpty()) { @@ -278,26 +287,44 @@ void scanExternalObjectGraph(JSC::VM& vm, JSC::SlotVisitor& visitor, void* root) if (visitor.containsOpaqueRootTriState(nextRoot) == TrueTriState) continue; visitor.addOpaqueRoot(nextRoot); - - NSMapTable *ownedObjects = [externalObjectGraph objectForKey:static_cast(nextRoot)]; - for (id ownedObject in ownedObjects) - stack.append(static_cast(ownedObject)); + + auto appendOwnedObjects = [&] { + NSMapTable *ownedObjects = [externalObjectGraph objectForKey:static_cast(nextRoot)]; + for (id ownedObject in ownedObjects) + stack.append(static_cast(ownedObject)); + }; + + if (lockAcquired) + appendOwnedObjects(); + else { + auto locker = holdLock(externalDataMutex); + appendOwnedObjects(); + } } } } +void scanExternalObjectGraph(JSC::VM& vm, JSC::SlotVisitor& visitor, void* root) +{ + bool lockAcquired = false; + scanExternalObjectGraph(vm, visitor, root, lockAcquired); +} + void scanExternalRememberedSet(JSC::VM& vm, JSC::SlotVisitor& visitor) { @autoreleasepool { JSVirtualMachine *virtualMachine = [JSVMWrapperCache wrapperForJSContextGroupRef:toRef(&vm)]; if (!virtualMachine) return; + Lock& externalDataMutex = [virtualMachine externalDataMutex]; + auto locker = holdLock(externalDataMutex); NSMapTable *externalObjectGraph = [virtualMachine externalObjectGraph]; NSMapTable *externalRememberedSet = [virtualMachine externalRememberedSet]; for (id key in externalRememberedSet) { NSMapTable *ownedObjects = [externalObjectGraph objectForKey:key]; + bool lockAcquired = true; for (id ownedObject in ownedObjects) - scanExternalObjectGraph(vm, visitor, ownedObject); + scanExternalObjectGraph(vm, visitor, ownedObject, lockAcquired); } [externalRememberedSet removeAllObjects]; } diff --git a/webkit/JavaScriptCore/API/JSVirtualMachineInternal.h b/webkit/JavaScriptCore/API/JSVirtualMachineInternal.h index 5a4fbefa5..5ca9a7f4a 100755 --- a/webkit/JavaScriptCore/API/JSVirtualMachineInternal.h +++ b/webkit/JavaScriptCore/API/JSVirtualMachineInternal.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Apple Inc. All rights reserved. + * Copyright (C) 2013, 2017 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -47,8 +47,6 @@ JSContextGroupRef getGroupFromVirtualMachine(JSVirtualMachine *); - (JSContext *)contextForGlobalContextRef:(JSGlobalContextRef)globalContext; - (void)addContext:(JSContext *)wrapper forGlobalContextRef:(JSGlobalContextRef)globalContext; -- (NSMapTable *)externalObjectGraph; - @end #endif // defined(__OBJC__) diff --git a/webkit/JavaScriptCore/API/tests/testapi.mm b/webkit/JavaScriptCore/API/tests/testapi.mm index 01bb7d76b..ad0f79776 100755 --- a/webkit/JavaScriptCore/API/tests/testapi.mm +++ b/webkit/JavaScriptCore/API/tests/testapi.mm @@ -545,6 +545,15 @@ static void testObjectiveCAPIMain() checkResult(@"typeof Promise is 'undefined'", result.isString && [result isEqualToObject:@"undefined"]); } + @autoreleasepool { + JSVirtualMachine* vm = [[JSVirtualMachine alloc] init]; + JSContext* context = [[JSContext alloc] initWithVirtualMachine:vm]; + TestObject* testObject = [TestObject testObject]; + context[@"testObject"] = testObject; + [context evaluateScript:@"result = 0; callbackResult = 0; Promise.resolve(42).then(function (value) { result = value; }); callbackResult = testObject.getString();"]; + checkResult(@"Microtask is drained with same VM", [context[@"result"] isEqualToObject:@42] && [context[@"callbackResult"] isEqualToObject:@"42"]); + } + @autoreleasepool { JSContext *context = [[JSContext alloc] init]; JSValue *result = [context evaluateScript:@"({ x:42 })"]; diff --git a/webkit/JavaScriptCore/ChangeLog b/webkit/JavaScriptCore/ChangeLog index 780ed7353..5ff064a69 100755 --- a/webkit/JavaScriptCore/ChangeLog +++ b/webkit/JavaScriptCore/ChangeLog @@ -1,3 +1,771 @@ +2017-04-05 Guilherme Iscaro + + Do not use BLX for immediates (ARM-32) + + https://bugs.webkit.org/show_bug.cgi?id=170351 + + Reviewed by Mark Lam. + + Currently the offline asm generator for 32-bit ARM code translates the + 'call' meta-instruction (which may be found in LowLevelInterpreter.asm + and friends) to the ARM's BLX instrunction. The BLX instruction may be + used for labels (immediates) and registers and one side effect of BLX + is that it may switch the processor's instruction set. + A 'BLX register' instruction will change/remain the processor state to + ARM if the register_bit[0] is set to 0 or change/remain to Thumb if + register_bit[0] is set to 1. However, a 'BLX label' instruction will + always switch the processor state. It switches ARM to thumb and vice-versa. + This behaviour is unwanted, since the C++ code and the offlineasm generated code + are both compiled using the same instruction set, thus a instruction + set change will likely produce a crash. In order to fix the problem the + BL instruction can be used for labels. It will branch just like BLX, + but it won't change the instruction set. It's important to note that + Darwin is not affected by this problem, thus to minimize the impact of + this change the BL instruction will only be used on non-darwin targets. + + BLX reference: http://infocenter.arm.com/help/topic/com.arm.doc.dui0489i/CIHBJCDC.html?resultof=%22%62%6c%78%22%20 + + * offlineasm/arm.rb: + +2016-12-23 Mark Lam + + Using Option::breakOnThrow() shouldn't crash while printing a null CodeBlock. + https://bugs.webkit.org/show_bug.cgi?id=166466 + + Reviewed by Keith Miller. + + * runtime/VM.cpp: + (JSC::VM::throwException): + +2017-05-09 Jason Marcell + + Cherry-pick r215748. rdar://problem/31971413 + + 2017-04-25 Mark Lam + + Local CSE wrongly CSEs array accesses with different result types. + https://bugs.webkit.org/show_bug.cgi?id=170990 + + + Reviewed by Saam Barati. + + The fix is to use different LocationKind enums for the different type of array + result types. This makes the HeapLocation values different based on the result + types, and allows CSE to discern between them. + + * dfg/DFGCSEPhase.cpp: + * dfg/DFGClobberize.h: + (JSC::DFG::clobberize): + * dfg/DFGHeapLocation.cpp: + (WTF::printInternal): + * dfg/DFGHeapLocation.h: + (JSC::DFG::indexedPropertyLocForResultType): + +2017-05-09 Matthew Hanson + + Cherry-pick r215351. rdar://problem/31631922 + + 2017-04-13 Mark Lam + + Should use flushDirect() when flushing the scopeRegister due to needsScopeRegister(). + https://bugs.webkit.org/show_bug.cgi?id=170661 + + + Reviewed by Filip Pizlo. + + Previously, we were using flush() to flush the outermost frame's scopeRegister. + This is incorrect because flush() expects the VirtualRegister value passed to + it to be that of the top most inlined frame. In the event that we reach a + terminal condition while inside an inlined frame, flush() will end up flushing + the wrong register. The fix is simply to use flushDirect() instead. + + * dfg/DFGByteCodeParser.cpp: + (JSC::DFG::ByteCodeParser::flush): + +2016-10-11 Mark Lam + + Array.prototype.concat should not modify frozen objects. + https://bugs.webkit.org/show_bug.cgi?id=163302 + + Reviewed by Filip Pizlo. + + The ES6 spec for Array.prototype.concat states that it uses the + CreateDataPropertyOrThrow() to add items to the result array. The spec for + CreateDataPropertyOrThrow states: + + "This abstract operation creates a property whose attributes are set to the same + defaults used for properties created by the ECMAScript language assignment + operator. Normally, the property will not already exist. If it does exist and is + not configurable or if O is not extensible, [[DefineOwnProperty]] will return + false causing this operation to throw a TypeError exception." + + Since the properties of frozen objects are not extensible, not configurable, and + not writable, Array.prototype.concat should fail to write to the result array if + it is frozen. + + Ref: https://tc39.github.io/ecma262/#sec-array.prototype.concat, + https://tc39.github.io/ecma262/#sec-createdatapropertyorthrow, and + https://tc39.github.io/ecma262/#sec-createdataproperty. + + The fix consists of 2 parts: + 1. moveElement() should use the PutDirectIndexShouldThrow mode when invoking + putDirectIndex(), and + 2. SparseArrayValueMap::putDirect() should check for the case where the property + is read only. + + (2) ensures that we don't write into a non-writable property. + (1) ensures that we throw a TypeError for attempts to write to a non-writeable + property. + + * runtime/ArrayPrototype.cpp: + (JSC::moveElements): + * runtime/SparseArrayValueMap.cpp: + (JSC::SparseArrayValueMap::putDirect): + +2017-03-28 Jason Marcell + + Merge r214240. rdar://problem/31178794 + + 2017-03-21 Mark Lam + + The DFG Integer Check Combining phase should force an OSR exit for CheckInBounds on a negative constant min bound. + https://bugs.webkit.org/show_bug.cgi?id=169933 + + + Reviewed by Filip Pizlo and Geoffrey Garen. + + Also fixed the bit-rotted RangeKey::dump() function. + + * dfg/DFGIntegerCheckCombiningPhase.cpp: + (JSC::DFG::IntegerCheckCombiningPhase::handleBlock): + +2017-02-23 Filip Pizlo + + verifyEdges should not run in release + + + Reviewed by Keith Miller and Mark Lam. + + * dfg/DFGAbstractInterpreterInlines.h: + (JSC::DFG::AbstractInterpreter::executeEffects): + +2017-02-23 Filip Pizlo + + Disable concurrent GC A:B testing. + + * runtime/Options.h: + +2017-02-16 Keith Miller + + Fix merge issue with r212085 (rdar://problem/29939864). + + * runtime/JSFunction.cpp: + (JSC::JSFunction::callerGetter): + +2017-02-09 Matthew Hanson + + Merge r212023. rdar://problem/30041640 + + 2017-02-09 Brent Fulgham + + Handle synchronous layout when setting a selection range + https://bugs.webkit.org/show_bug.cgi?id=167092 + + + Reviewed by Antti Koivisto. + + The 'innerTextElement' of a form control can change during layout due + to arbitrary JavaScript executing. Handle the case where the inner text + element has changed so that current render box height is while setting + a selection range. + + Test: fast/forms/input-type-change-during-selection.html + + * html/HTMLTextFormControlElement.cpp: + (WebCore::HTMLTextFormControlElement::setSelectionRange): + +2017-02-09 Matthew Hanson + + Merge r212009. rdar://problem/29939864 + + 2017-02-09 Keith Miller + + We should not allow Function.caller to be used on native functions + https://bugs.webkit.org/show_bug.cgi?id=165628 + + Reviewed by Mark Lam. + + Also remove unneeded dynamic cast. + + * runtime/JSFunction.cpp: + (JSC::RetrieveCallerFunctionFunctor::RetrieveCallerFunctionFunctor): + (JSC::JSFunction::callerGetter): + +2017-02-02 Matthew Hanson + + Merge r211463. rdar://problem/30296879 + + 2017-01-31 Filip Pizlo + + Make verifyEdge a RELEASE_ASSERT + + + Rubber stamped by Saam Barati. + + * dfg/DFGAbstractInterpreterInlines.h: + (JSC::DFG::AbstractInterpreter::executeEffects): + +2017-01-24 Matthew Hanson + + Merge r210971. rdar://problem/30115838 + + 2017-01-20 Saam Barati + + We should flash a safepoint before each DFG/FTL phase + https://bugs.webkit.org/show_bug.cgi?id=167234 + + Reviewed by Filip Pizlo. + + The recent GC changes caused us to regress Kraken because of a + longstanding issue that happened to be hit with higher frequency because + of a change in timing between when a particular GC was happening and + when a particular FTL compilation was happening. The regression is caused + by the GC was waiting for a large function to make it through the DFG portion + of an FTL compilation. This was taking 20ms-30ms and started happened during a + particular test with much higher frequency. + + This means that anytime the GC waits for this compilation, the test ran at least + ~20ms slower because the GC waits for the compiler threads the mutator is stopped. + + It's good that we have such an easily reproducible case of this performance + issue because it will effect many real JS programs, especially ones with + large functions that get hot. + + The most straight forward solution to fix this is to flash a safepoint before + each phase, allowing the GC to suspend the compiler if needed. In my testing, + this progresses Kraken in the browser, and doesn't regress anything else. This + solution also makes the most sense. I did some analysis on the compilation time + of this function that took ~20-30ms to pass through the DFG phases, and + the phase times were mostly evenly distributed. Some took longer than others, + but no phase was longer than 3ms. Most were in the 0.25ms to 1.5ms range. + + * dfg/DFGPlan.cpp: + (JSC::DFG::Plan::compileInThreadImpl): + * dfg/DFGSafepoint.cpp: + (JSC::DFG::Safepoint::begin): + * runtime/Options.h: + +2017-01-18 Matthew Hanson + + Merge r210858. rdar://problem/30069096 + + 2017-01-18 Filip Pizlo + + JSObjectSetPrivate should not use jsCast<> + rdar://problem/30069096 + + Reviewed by Keith Miller. + + * API/JSObjectRef.cpp: + (JSObjectSetPrivate): + +2017-01-09 Babak Shafiei + + Merge r210458. rdar://problem/29911919 + + 2017-01-06 Mark Lam + + The ObjC API's JSVirtualMachine's map tables need to be guarded by a lock. + https://bugs.webkit.org/show_bug.cgi?id=166778 + + + Reviewed by Filip Pizlo. + + Now that we have a concurrent GC, access to JSVirtualMachine's + m_externalObjectGraph and m_externalRememberedSet need to be guarded by a lock + since both the GC marker thread and the mutator thread may access them at the + same time. + + * API/JSVirtualMachine.mm: + (-[JSVirtualMachine addExternalRememberedObject:]): + (-[JSVirtualMachine addManagedReference:withOwner:]): + (-[JSVirtualMachine removeManagedReference:withOwner:]): + (-[JSVirtualMachine externalDataMutex]): + (scanExternalObjectGraph): + (scanExternalRememberedSet): + + * API/JSVirtualMachineInternal.h: + - Deleted externalObjectGraph method. There's no need to expose this. + +2017-01-06 Matthew Hanson + + Merge r210276. rdar://problem/28867002 + + 2017-01-04 Saam Barati + + We don't properly handle exceptions inside the nativeCallTrampoline macro in the LLInt + https://bugs.webkit.org/show_bug.cgi?id=163720 + + Reviewed by Mark Lam. + + In the LLInt, we were incorrectly doing the exception check after the call. + Before the exception check, we were unwinding to our caller's + frame under the assumption that our caller was always a JS frame. + This is incorrect, however, because our caller might be a C frame. + One way that it can be a C frame is when C calls to JS, and JS tail + calls to native. This patch fixes this bug by doing unwinding from + the native callee's frame instead of its callers. + + * llint/LowLevelInterpreter32_64.asm: + * llint/LowLevelInterpreter64.asm: + +2017-01-06 Matthew Hanson + + Merge r210221. rdar://problem/29449474 + + 2017-01-01 Jeff Miller + + Update user-visible copyright strings to include 2017 + https://bugs.webkit.org/show_bug.cgi?id=166278 + + Reviewed by Dan Bernstein. + + * Info.plist: + +2016-10-27 Mark Lam + + Merge r207518. rdar://problem/28216050, rdar://problem/28216232 + + 2016-10-18 Mark Lam + + Invoking Object.prototype.__proto__ accessors directly should throw a TypeError. + https://bugs.webkit.org/show_bug.cgi?id=154377 + + + Reviewed by Filip Pizlo and Saam Barati. + + In a scenario where we cache the __proto__ accessors in global variables, and + later explicitly invoke those accessors as functions, the spec for Function Calls + (see https://tc39.github.io/ecma262/#sec-function-calls) states that the function + ref value is of type Reference, and base of ref is an Environment Record. Then, + it follows that the thisValue should be set to refEnv.WithBaseObject() + (see section 4.b.ii of 12.3.4.1 at + https://tc39.github.io/ecma262/#sec-function-calls-runtime-semantics-evaluation). + + refEnv in this case is the environment record that the cached accessors were + found in i.e. the global object. The WithBaseObject() of the global object is + undefined (see details about WithBaseObject at + https://tc39.github.io/ecma262/#sec-environment-records). + + Hence, the __proto__ accessors should see a thisValue of undefined, and throw + TypeErrors. See https://tc39.github.io/ecma262/#sec-get-object.prototype.__proto__, + https://tc39.github.io/ecma262/#sec-set-object.prototype.__proto__, + https://tc39.github.io/ecma262/#sec-toobject, and + https://tc39.github.io/ecma262/#sec-requireobjectcoercible. + + In JSC's implementation, the callee needs to do a ToThis operation on the + incoming "this" argument in order to get the specified thisValue. The + implementations of the __proto__ accessors were not doing this correctly. This + has now been fixed. + + * runtime/JSGlobalObjectFunctions.cpp: + (JSC::globalFuncProtoGetter): + (JSC::globalFuncProtoSetter): + +2016-10-24 Matthew Hanson + + Merge r207623. rdar://problem/28857477 + + 2016-10-20 Keith Miller + + Invalid assertion in arguments elimination + https://bugs.webkit.org/show_bug.cgi?id=163740 + + + Reviewed by Michael Saboff. + + The DFGFTL's arguments elimination phase incorrectly asserted that a GetFromArguments' first + child would always be a CreateDirectArguments. While we only create the + op_get_from_arguments bytecode pointing to a create_direct_arguments, its possible for a + number of reasons that a DFG GetFromArguments may not point to a CreateDirectArguments. For + example, if we are OSR entering in some function with direct arguments the + CreateDirectArguments node might become ExtractOSREntryLocals. + + * dfg/DFGArgumentsEliminationPhase.cpp: + +2016-10-12 Matthew Hanson + + Merge r206955. rdar://problem/28216236 + + 2016-10-08 Saam Barati + + HasIndexedProperty clobberize rule is wrong for Array::ForceOSRExit + https://bugs.webkit.org/show_bug.cgi?id=159942 + + + Reviewed by Filip Pizlo. + + When HasIndexedProperty has a ForceOSRExit array mode, it should + report to write to side state, like the ForceOSRExit node, and the + other nodes with ForceOSRExit array mode. + + * dfg/DFGClobberize.h: + (JSC::DFG::clobberize): + +2016-10-12 Matthew Hanson + + Merge r204612. rdar://problem/28216278 + + 2016-08-18 Mark Lam + + ScopedArguments is using the wrong owner object for a write barrier. + https://bugs.webkit.org/show_bug.cgi?id=160976 + + + Reviewed by Keith Miller. + + * runtime/ScopedArguments.h: + (JSC::ScopedArguments::setIndexQuickly): + +2016-09-14 Babak Shafiei + + Merge r205882. rdar://problem/28233331 + + 2016-09-13 Mark Lam + + DFG NewArrayBuffer node should watch for "have a bad time" state change. + https://bugs.webkit.org/show_bug.cgi?id=161927 + + + Reviewed by Geoffrey Garen. + + * dfg/DFGFixupPhase.cpp: + (JSC::DFG::FixupPhase::fixupNode): + +2016-09-13 Babak Shafiei + + Merge r205895. rdar://problem/28287070 + + 2016-09-13 Michael Saboff + + Promises aren't resolved properly when making a ObjC API callback + https://bugs.webkit.org/show_bug.cgi?id=161929 + + Reviewed by Geoffrey Garen. + + When we go to call out to an Objective C function registered via the API, + we first drop all JSC locks to make the call. As part of dropping the locks, + we drain the microtask queue that is used among other things for handling deferred + promise resolution. The DropAllLocks scope class that drops the locks while in + scope, resets the current thread's AtomicStringTable to the default table. This + is wrong for two reasons, first it happens before we drain the microtask queue and + second it isn't needed as JSLock::willReleaseLock() restores the current thread's + AtomicStringTable to the table before the lock was acquired. + + In fact, the manipulation of the current thread's AtomicStringTable is already + properly handled as a stack in JSLock::didAcquireLock() and willReleaseLock(). + Therefore the manipulation of the AtomicStringTable in DropAllLocks constructor + and destructor should be removed. + + * API/tests/testapi.mm: + (testObjectiveCAPIMain): Added a new test. + * runtime/JSLock.cpp: + (JSC::JSLock::DropAllLocks::DropAllLocks): + (JSC::JSLock::DropAllLocks::~DropAllLocks): + +2016-09-09 Babak Shafiei + + Merge r204485. rdar://problem/27991572 + + 2016-08-15 Mark Lam + + Make JSValue::strictEqual() handle failures to resolve JSRopeStrings. + https://bugs.webkit.org/show_bug.cgi?id=160832 + + + Reviewed by Geoffrey Garen. + + Currently, JSValue::strictEqualSlowCaseInline() (and peers) will blindly try to + access the StringImpl of a JSRopeString that fails to resolve its rope. As a + result, we'll crash with null pointer dereferences. + + We can fix this by introducing a JSString::equal() method that will do the + equality comparison, but is aware of the potential failures to resolve ropes. + JSValue::strictEqualSlowCaseInline() (and peers) will now call JSString::equal() + instead of accessing the underlying StringImpl directly. + + Also added some exception checks. + + * JavaScriptCore.xcodeproj/project.pbxproj: + * jit/JITOperations.cpp: + * runtime/ArrayPrototype.cpp: + (JSC::arrayProtoFuncIndexOf): + (JSC::arrayProtoFuncLastIndexOf): + * runtime/JSCJSValueInlines.h: + (JSC::JSValue::equalSlowCaseInline): + (JSC::JSValue::strictEqualSlowCaseInline): + * runtime/JSString.cpp: + (JSC::JSString::equalSlowCase): + * runtime/JSString.h: + * runtime/JSStringInlines.h: Added. + (JSC::JSString::equal): + +2016-09-09 Babak Shafiei + + Merge r203381. rdar://problem/27860536 + + 2016-07-18 Anders Carlsson + + WebKit nightly fails to build on macOS Sierra + https://bugs.webkit.org/show_bug.cgi?id=159902 + rdar://problem/27365672 + + Reviewed by Tim Horton. + + * icu/unicode/ucurr.h: Added. + Add ucurr.h from ICU. + +2016-09-09 Babak Shafiei + + Merge r205192. rdar://problem/28097740 + + 2016-08-30 Alex Christensen + + Fix WebInspectorUI in internal Windows build + https://bugs.webkit.org/show_bug.cgi?id=161221 + rdar://problem/28019023 + + Reviewed by Brent Fulgham and Joseph Pecoraro. + + * JavaScriptCore.vcxproj/JavaScriptCore.proj: + +2016-08-30 Babak Shafiei + + Merge r204570. rdar://problem/27991567 + + 2016-08-17 Mark Lam + + Remove an invalid assertion in the DFG backend's GetById emitter. + https://bugs.webkit.org/show_bug.cgi?id=160925 + + + Reviewed by Filip Pizlo. + + The DFG backend's GetById assertion that the node's prediction not be SpecNone + is just plain wrong. It assumes that we can never have a GetById node without a + type prediction, but this is not true. The following test case proves otherwise: + + function foo() { + "use strict"; + return --arguments["callee"]; + } + + Will remove the assertion. Nothing else needs to change as the DFG is working + correctly without the assertion. + + * dfg/DFGSpeculativeJIT32_64.cpp: + (JSC::DFG::SpeculativeJIT::compile): + * dfg/DFGSpeculativeJIT64.cpp: + (JSC::DFG::SpeculativeJIT::compile): + +2016-08-30 Babak Shafiei + + Merge r204362. rdar://problem/27991421 + + 2016-08-10 Michael Saboff + + Baseline GetByVal and PutByVal for cache ID stubs need to handle exceptions + https://bugs.webkit.org/show_bug.cgi?id=160749 + + Reviewed by Filip Pizlo. + + We were emitting "callOperation()" calls in emitGetByValWithCachedId() and + emitPutByValWithCachedId() without linking the exception checks created by the + code emitted. This manifested itself in various ways depending on the processor. + This is due to what the destination is for an unlinked branch. On X86, an unlinked + branch goes tot he next instructions. On ARM64, we end up with an infinite loop + as we branch to the same instruction. On ARM we branch to 0 as the branch is to + an absolute address of 0. + + Now we save the exception handler address for the original generated function and + link the exception cases for these by-val stubs to this handler. + + * bytecode/ByValInfo.h: + (JSC::ByValInfo::ByValInfo): Added the address of the exception handler we should + link to. + + * jit/JIT.cpp: + (JSC::JIT::link): Compute the linked exception handler address and pass it to + the ByValInfo constructor. + (JSC::JIT::privateCompileExceptionHandlers): Make sure that we generate the + exception handler if we have any by-val handlers. + + * jit/JIT.h: + Added a label for the exception handler. We'll link this later for the + by value handlers. + + * jit/JITPropertyAccess.cpp: + (JSC::JIT::privateCompileGetByValWithCachedId): + (JSC::JIT::privateCompilePutByValWithCachedId): + Link exception branches to the exception handler for the main function. + +2016-08-30 Babak Shafiei + + Merge r204360. rdar://problem/27991577 + + 2016-08-10 Mark Lam + + DFG's flushForTerminal() needs to add PhantomLocals for bytecode live locals. + https://bugs.webkit.org/show_bug.cgi?id=160755 + + + Reviewed by Filip Pizlo. + + If the DFG sees that an inlined function will result in an OSR exit every time, + it will treat all downstream blocks as dead. However, it still needs to keep + locals that are alive in the bytecode alive for the compiled function so that + those locals are properly written to the stack by the OSR exit ramp. + + The existing code neglected to do this. This patch remedies this issue. + + * dfg/DFGByteCodeParser.cpp: + (JSC::DFG::ByteCodeParser::flushDirect): + (JSC::DFG::ByteCodeParser::addFlushOrPhantomLocal): + (JSC::DFG::ByteCodeParser::phantomLocalDirect): + (JSC::DFG::ByteCodeParser::flushForTerminal): + +2016-08-30 Babak Shafiei + + Merge r203952. rdar://problem/27991571 + + 2016-07-30 Mark Lam + + Assertion failure while setting the length of an ArrayClass array. + https://bugs.webkit.org/show_bug.cgi?id=160381 + + + Reviewed by Filip Pizlo. + + When setting large length values, we're currently treating ArrayClass as a + ContiguousIndexingType array. This results in an assertion failure. This is + now fixed. + + There are currently only 2 places where we create arrays with indexing type + ArrayClass: ArrayPrototype and RuntimeArray. The fix in JSArray:;setLength() + takes care of ArrayPrototype. + + RuntimeArray already checks for the setting of its length property, and will + throw a RangeError. Hence, there's no change is needed for the RuntimeArray. + Instead, I added some test cases ensure that the check and throw behavior does + not change without notice. + + * runtime/JSArray.cpp: + (JSC::JSArray::setLength): + * tests/stress/array-setLength-on-ArrayClass-with-large-length.js: Added. + (toString): + (assertEqual): + * tests/stress/array-setLength-on-ArrayClass-with-small-length.js: Added. + (toString): + (assertEqual): + +2016-08-30 Babak Shafiei + + Merge r203853. rdar://problem/27991580 + + 2016-07-28 Mark Lam + + ASSERTION FAILED in errorProtoFuncToString() when Error name is a single char string. + https://bugs.webkit.org/show_bug.cgi?id=160324 + + + Reviewed by Keith Miller. + + The issue is that errorProtoFuncToString() was using jsNontrivialString() to + generate the error string even when the name string can be a single character + string. This is incorrect. We should be using jsString() instead. + + * runtime/ErrorPrototype.cpp: + (JSC::errorProtoFuncToString): + * tests/stress/errors-with-simple-names-or-messages-should-not-crash-toString.js: Added. + +2016-08-30 Babak Shafiei + + Merge r203834. rdar://problem/27991582 + + 2016-07-28 Mark Lam + + StringView should have an explicit m_is8Bit field. + https://bugs.webkit.org/show_bug.cgi?id=160282 + + + Reviewed by Benjamin Poulain. + + * tests/stress/string-joining-long-strings-should-not-crash.js: Added. + (catch): + +2016-08-30 Babak Shafiei + + Merge r203802. rdar://problem/27991569 + + 2016-07-27 Benjamin Poulain + + [JSC] Fix a bunch of use-after-free of DFG::Node + https://bugs.webkit.org/show_bug.cgi?id=160228 + + Reviewed by Mark Lam. + + FTL had a few places where we use a node after it has been + deleted. The dangling pointers come from the SSA liveness information + kept on the basic blocks. + + This patch fixes the issues I could find and adds liveness invalidation + to help finding dependencies like these. + + * dfg/DFGBasicBlock.h: + (JSC::DFG::BasicBlock::SSAData::invalidate): + + * dfg/DFGConstantFoldingPhase.cpp: + (JSC::DFG::ConstantFoldingPhase::run): + Constant folding phase was deleting nodes in the loop over basic blocks. + The problem is the deleted nodes can be referenced by other blocks. + When the abstract interpreter was manipulating the abstract values of those + it was doing so on the dead nodes. + + * dfg/DFGConstantHoistingPhase.cpp: + Just invalidation. Nothing wrong here since the useless nodes were + kept live while iterating the blocks. + + * dfg/DFGGraph.cpp: + (JSC::DFG::Graph::killBlockAndItsContents): + (JSC::DFG::Graph::killUnreachableBlocks): + (JSC::DFG::Graph::invalidateNodeLiveness): + + * dfg/DFGGraph.h: + * dfg/DFGPlan.cpp: + (JSC::DFG::Plan::compileInThreadImpl): + We had a lot of use-after-free in LCIM because we were using the stale + live nodes deleted by previous phases. + +2016-08-30 Babak Shafiei + + Merge r203798. rdar://problem/27991578 + + 2016-07-27 Keith Miller + + concatAppendOne should allocate using the indexing type of the array if it cannot merge + https://bugs.webkit.org/show_bug.cgi?id=160261 + + + Reviewed by Mark Lam. + + Before, if we could not merge the indexing types for copying, we would allocate the + the array as ArrayWithUndecided. Instead, we should allocate an array with the original + array's indexing type. + + * runtime/ArrayPrototype.cpp: + (JSC::concatAppendOne): + * tests/stress/concat-append-one-with-sparse-array.js: Added. + 2016-08-29 Babak Shafiei Merge r204572. diff --git a/webkit/JavaScriptCore/Info.plist b/webkit/JavaScriptCore/Info.plist index 41323e4be..5f9024642 100755 --- a/webkit/JavaScriptCore/Info.plist +++ b/webkit/JavaScriptCore/Info.plist @@ -7,7 +7,7 @@ CFBundleExecutable ${PRODUCT_NAME} CFBundleGetInfoString - ${BUNDLE_VERSION}, Copyright 2003-2016 Apple Inc.; Copyright 1999-2001 Harri Porten <porten@kde.org>; Copyright 2001 Peter Kelly <pmk@post.com>; Copyright 1997-2005 University of Cambridge; Copyright 1991, 2000, 2001 by Lucent Technologies. + ${BUNDLE_VERSION}, Copyright 2003-2017 Apple Inc.; Copyright 1999-2001 Harri Porten <porten@kde.org>; Copyright 2001 Peter Kelly <pmk@post.com>; Copyright 1997-2005 University of Cambridge; Copyright 1991, 2000, 2001 by Lucent Technologies. CFBundleIdentifier com.apple.${PRODUCT_NAME} CFBundleInfoDictionaryVersion diff --git a/webkit/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.proj b/webkit/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.proj index b24dfd9a1..70c487c3e 100755 --- a/webkit/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.proj +++ b/webkit/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.proj @@ -73,6 +73,9 @@ + + + @@ -117,6 +120,7 @@ + diff --git a/webkit/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj b/webkit/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj index 71ada7e19..9171b2616 100755 --- a/webkit/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj +++ b/webkit/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj @@ -760,6 +760,7 @@ 0FFFC95E14EF90B700C72532 /* DFGPredictionPropagationPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FFFC95214EF909500C72532 /* DFGPredictionPropagationPhase.h */; settings = {ATTRIBUTES = (Private, ); }; }; 0FFFC95F14EF90BB00C72532 /* DFGVirtualRegisterAllocationPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FFFC95314EF909500C72532 /* DFGVirtualRegisterAllocationPhase.cpp */; }; 0FFFC96014EF90BD00C72532 /* DFGVirtualRegisterAllocationPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FFFC95414EF909500C72532 /* DFGVirtualRegisterAllocationPhase.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 13FECE06D3B445FCB6C93461 /* JSModuleLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1879510614C540FFB561C124 /* JSModuleLoader.cpp */; }; 140566C4107EC255005DBC8D /* JSAPIValueWrapper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC0894D50FAFBA2D00001865 /* JSAPIValueWrapper.cpp */; }; 140566D6107EC271005DBC8D /* JSFunction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F692A85E0255597D01FF60F7 /* JSFunction.cpp */; }; 140B7D1D0DC69AF7009C42B8 /* JSLexicalEnvironment.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 14DA818F0D99FD2000B0A4FB /* JSLexicalEnvironment.cpp */; }; @@ -1653,6 +1654,7 @@ C4F4B6F41A05C944005CAB76 /* cpp_generator.py in Headers */ = {isa = PBXBuildFile; fileRef = C4F4B6D01A05C76F005CAB76 /* cpp_generator.py */; settings = {ATTRIBUTES = (Private, ); }; }; C4F4B6F51A05C984005CAB76 /* generate_objc_protocol_types_implementation.py in Headers */ = {isa = PBXBuildFile; fileRef = C4F4B6D71A05C76F005CAB76 /* generate_objc_protocol_types_implementation.py */; settings = {ATTRIBUTES = (Private, ); }; }; C4F4B6F61A05C984005CAB76 /* objc_generator_templates.py in Headers */ = {isa = PBXBuildFile; fileRef = C4F4B6D81A05C76F005CAB76 /* objc_generator_templates.py */; settings = {ATTRIBUTES = (Private, ); }; }; + D9722752DC54459B9125B539 /* JSModuleLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 77B25CB2C3094A92A38E1DB3 /* JSModuleLoader.h */; }; DC00039319D8BE6F00023EB0 /* DFGPreciseLocalClobberize.h in Headers */ = {isa = PBXBuildFile; fileRef = DC00039019D8BE6F00023EB0 /* DFGPreciseLocalClobberize.h */; settings = {ATTRIBUTES = (Private, ); }; }; E124A8F70E555775003091F1 /* OpaqueJSString.h in Headers */ = {isa = PBXBuildFile; fileRef = E124A8F50E555775003091F1 /* OpaqueJSString.h */; settings = {ATTRIBUTES = (Private, ); }; }; E124A8F80E555775003091F1 /* OpaqueJSString.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E124A8F60E555775003091F1 /* OpaqueJSString.cpp */; }; @@ -1693,6 +1695,7 @@ FED94F2F171E3E2300BE77A4 /* Watchdog.h in Headers */ = {isa = PBXBuildFile; fileRef = FED94F2C171E3E2300BE77A4 /* Watchdog.h */; settings = {ATTRIBUTES = (Private, ); }; }; FED94F30171E3E2300BE77A4 /* WatchdogMac.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FED94F2D171E3E2300BE77A4 /* WatchdogMac.cpp */; }; FEF040511AAE662D00BD28B0 /* CompareAndSwapTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FEF040501AAE662D00BD28B0 /* CompareAndSwapTest.cpp */; }; + FEFD6FC61D5E7992008F2F0B /* JSStringInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = FEFD6FC51D5E7970008F2F0B /* JSStringInlines.h */; settings = {ATTRIBUTES = (Private, ); }; }; FEF6835E174343CC00A32E25 /* JITStubsARM.h in Headers */ = {isa = PBXBuildFile; fileRef = FEF6835A174343CC00A32E25 /* JITStubsARM.h */; settings = {ATTRIBUTES = (Private, ); }; }; FEF6835F174343CC00A32E25 /* JITStubsARMv7.h in Headers */ = {isa = PBXBuildFile; fileRef = FEF6835B174343CC00A32E25 /* JITStubsARMv7.h */; settings = {ATTRIBUTES = (Private, ); }; }; FEF68360174343CC00A32E25 /* JITStubsX86_64.h in Headers */ = {isa = PBXBuildFile; fileRef = FEF6835C174343CC00A32E25 /* JITStubsX86_64.h */; settings = {ATTRIBUTES = (Private, ); }; }; @@ -2623,6 +2626,7 @@ 14F7256314EE265E00B1652B /* WeakHandleOwner.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WeakHandleOwner.cpp; sourceTree = ""; }; 14F7256414EE265E00B1652B /* WeakHandleOwner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WeakHandleOwner.h; sourceTree = ""; }; 14F97446138C853E00DA1C67 /* HeapRootVisitor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HeapRootVisitor.h; sourceTree = ""; }; + 1879510614C540FFB561C124 /* JSModuleLoader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSModuleLoader.cpp; sourceTree = ""; }; 1A28D4A7177B71C80007FA3C /* JSStringRefPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSStringRefPrivate.h; sourceTree = ""; }; 1ACF7376171CA6FB00C9BB1E /* Weak.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Weak.cpp; sourceTree = ""; }; 1C9051420BA9E8A70081E9D0 /* Version.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Version.xcconfig; sourceTree = ""; }; @@ -2774,6 +2778,7 @@ 70ECA6021AFDBEA200449739 /* TemplateRegistry.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TemplateRegistry.cpp; sourceTree = ""; }; 70ECA6031AFDBEA200449739 /* TemplateRegistry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TemplateRegistry.h; sourceTree = ""; }; 70ECA6041AFDBEA200449739 /* TemplateRegistryKey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TemplateRegistryKey.h; sourceTree = ""; }; + 77B25CB2C3094A92A38E1DB3 /* JSModuleLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSModuleLoader.h; sourceTree = ""; }; 7C008CD8187124BB00955C24 /* JSPromiseDeferred.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSPromiseDeferred.cpp; sourceTree = ""; }; 7C008CD9187124BB00955C24 /* JSPromiseDeferred.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSPromiseDeferred.h; sourceTree = ""; }; 7C008CE5187631B600955C24 /* Microtask.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Microtask.h; sourceTree = ""; }; @@ -3504,6 +3509,7 @@ FEDA50D51B97F4D9009A3B4F /* PingPongStackOverflowTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PingPongStackOverflowTest.h; path = API/tests/PingPongStackOverflowTest.h; sourceTree = ""; }; FEF040501AAE662D00BD28B0 /* CompareAndSwapTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CompareAndSwapTest.cpp; path = API/tests/CompareAndSwapTest.cpp; sourceTree = ""; }; FEF040521AAEC4ED00BD28B0 /* CompareAndSwapTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CompareAndSwapTest.h; path = API/tests/CompareAndSwapTest.h; sourceTree = ""; }; + FEFD6FC51D5E7970008F2F0B /* JSStringInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSStringInlines.h; sourceTree = ""; }; FEF6835A174343CC00A32E25 /* JITStubsARM.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITStubsARM.h; sourceTree = ""; }; FEF6835B174343CC00A32E25 /* JITStubsARMv7.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITStubsARMv7.h; sourceTree = ""; }; FEF6835C174343CC00A32E25 /* JITStubsX86_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITStubsX86_64.h; sourceTree = ""; }; @@ -4593,6 +4599,7 @@ BC02E9B60E1842FA000F9297 /* JSString.cpp */, F692A8620255597D01FF60F7 /* JSString.h */, 86E85538111B9968001AF51E /* JSStringBuilder.h */, + FEFD6FC51D5E7970008F2F0B /* JSStringInlines.h */, 70EC0EBC1AA0D7DA00B6AAFA /* JSStringIterator.cpp */, 70EC0EBD1AA0D7DA00B6AAFA /* JSStringIterator.h */, 2600B5A4152BAAA70091EE5F /* JSStringJoiner.cpp */, @@ -6356,6 +6363,7 @@ BC18C4460E16F5CD00B34460 /* ObjectPrototype.h in Headers */, E124A8F70E555775003091F1 /* OpaqueJSString.h in Headers */, 969A079B0ED1D3AE00F1F681 /* Opcode.h in Headers */, + FEFD6FC61D5E7992008F2F0B /* JSStringInlines.h in Headers */, 0F2BDC2C151FDE9100CD8910 /* Operands.h in Headers */, A70447EA17A0BD4600F5898E /* OperandsInlines.h in Headers */, 0F2D4DDE19832D34007D4B19 /* DebuggerScope.h in Headers */, diff --git a/webkit/JavaScriptCore/bytecode/ByValInfo.h b/webkit/JavaScriptCore/bytecode/ByValInfo.h index d98851613..396be7bab 100755 --- a/webkit/JavaScriptCore/bytecode/ByValInfo.h +++ b/webkit/JavaScriptCore/bytecode/ByValInfo.h @@ -202,9 +202,10 @@ inline JITArrayMode jitArrayModeForStructure(Structure* structure) struct ByValInfo { ByValInfo() { } - ByValInfo(unsigned bytecodeIndex, CodeLocationJump badTypeJump, JITArrayMode arrayMode, int16_t badTypeJumpToDone, int16_t returnAddressToSlowPath) + ByValInfo(unsigned bytecodeIndex, CodeLocationJump badTypeJump, CodeLocationLabel exceptionHandler, JITArrayMode arrayMode, int16_t badTypeJumpToDone, int16_t returnAddressToSlowPath) : bytecodeIndex(bytecodeIndex) , badTypeJump(badTypeJump) + , exceptionHandler(exceptionHandler) , arrayMode(arrayMode) , badTypeJumpToDone(badTypeJumpToDone) , returnAddressToSlowPath(returnAddressToSlowPath) @@ -214,6 +215,7 @@ struct ByValInfo { unsigned bytecodeIndex; CodeLocationJump badTypeJump; + CodeLocationLabel exceptionHandler; JITArrayMode arrayMode; // The array mode that was baked into the inline JIT code. int16_t badTypeJumpToDone; int16_t returnAddressToSlowPath; diff --git a/webkit/JavaScriptCore/dfg/DFGArgumentsEliminationPhase.cpp b/webkit/JavaScriptCore/dfg/DFGArgumentsEliminationPhase.cpp index 29ca2b1d5..f4eaf0a65 100755 --- a/webkit/JavaScriptCore/dfg/DFGArgumentsEliminationPhase.cpp +++ b/webkit/JavaScriptCore/dfg/DFGArgumentsEliminationPhase.cpp @@ -152,7 +152,6 @@ class ArgumentsEliminationPhase : public Phase { for (Node* node : *block) { switch (node->op()) { case GetFromArguments: - DFG_ASSERT(m_graph, node, node->child1()->op() == CreateDirectArguments); break; case GetByVal: diff --git a/webkit/JavaScriptCore/dfg/DFGBasicBlock.h b/webkit/JavaScriptCore/dfg/DFGBasicBlock.h index 420ff511c..e8519d545 100755 --- a/webkit/JavaScriptCore/dfg/DFGBasicBlock.h +++ b/webkit/JavaScriptCore/dfg/DFGBasicBlock.h @@ -237,6 +237,13 @@ struct BasicBlock : RefCounted { unsigned innerMostLoopIndices[numberOfInnerMostLoopIndices]; struct SSAData { + { + liveAtTail.clear(); + liveAtHead.clear(); + valuesAtHead.clear(); + valuesAtTail.clear(); + } + AvailabilityMap availabilityAtHead; AvailabilityMap availabilityAtTail; diff --git a/webkit/JavaScriptCore/dfg/DFGByteCodeParser.cpp b/webkit/JavaScriptCore/dfg/DFGByteCodeParser.cpp index 7ca15696b..593e17c1a 100755 --- a/webkit/JavaScriptCore/dfg/DFGByteCodeParser.cpp +++ b/webkit/JavaScriptCore/dfg/DFGByteCodeParser.cpp @@ -511,8 +511,14 @@ class ByteCodeParser { { flushDirect(operand, findArgumentPosition(operand)); } - + void flushDirect(VirtualRegister operand, ArgumentPosition* argumentPosition) + { + addFlushOrPhantomLocal(operand, argumentPosition); + } + + template + void addFlushOrPhantomLocal(VirtualRegister operand, ArgumentPosition* argumentPosition) { ASSERT(!operand.isConstant()); @@ -525,12 +531,17 @@ class ByteCodeParser { else variable = newVariableAccessData(operand); - node = addToGraph(Flush, OpInfo(variable)); + node = addToGraph(nodeType, OpInfo(variable)); m_currentBlock->variablesAtTail.operand(operand) = node; if (argumentPosition) argumentPosition->addVariable(variable); } - + + void phantomLocalDirect(VirtualRegister operand) + { + addFlushOrPhantomLocal(operand, findArgumentPosition(operand)); + } + void flush(InlineStackEntry* inlineStackEntry) { int numArguments; @@ -546,13 +557,37 @@ class ByteCodeParser { for (unsigned argument = numArguments; argument-- > 1;) flushDirect(inlineStackEntry->remapOperand(virtualRegisterForArgument(argument))); if (m_hasDebuggerEnabled) - flush(m_codeBlock->scopeRegister()); + flushDirect(m_codeBlock->scopeRegister()); } void flushForTerminal() { - for (InlineStackEntry* inlineStackEntry = m_inlineStackTop; inlineStackEntry; inlineStackEntry = inlineStackEntry->m_caller) + CodeOrigin origin = currentCodeOrigin(); + unsigned bytecodeIndex = origin.bytecodeIndex; + + for (InlineStackEntry* inlineStackEntry = m_inlineStackTop; inlineStackEntry; inlineStackEntry = inlineStackEntry->m_caller) { flush(inlineStackEntry); + + ASSERT(origin.inlineCallFrame == inlineStackEntry->m_inlineCallFrame); + InlineCallFrame* inlineCallFrame = inlineStackEntry->m_inlineCallFrame; + CodeBlock* codeBlock = m_graph.baselineCodeBlockFor(inlineCallFrame); + FullBytecodeLiveness& fullLiveness = m_graph.livenessFor(codeBlock); + const FastBitVector& livenessAtBytecode = fullLiveness.getLiveness(bytecodeIndex); + + for (unsigned local = codeBlock->m_numCalleeLocals; local--;) { + if (livenessAtBytecode.get(local)) { + VirtualRegister reg = virtualRegisterForLocal(local); + if (inlineCallFrame) + reg = inlineStackEntry->remapOperand(reg); + phantomLocalDirect(reg); + } + } + + if (inlineCallFrame) { + bytecodeIndex = inlineCallFrame->directCaller.bytecodeIndex; + origin = inlineCallFrame->directCaller; + } + } } void flushForReturn() diff --git a/webkit/JavaScriptCore/dfg/DFGCSEPhase.cpp b/webkit/JavaScriptCore/dfg/DFGCSEPhase.cpp index a3b867616..cd1338d78 100755 --- a/webkit/JavaScriptCore/dfg/DFGCSEPhase.cpp +++ b/webkit/JavaScriptCore/dfg/DFGCSEPhase.cpp @@ -253,6 +253,7 @@ class LocalCSEPhase : public Phase { Node* base = m_graph.varArgChild(m_node, 0).node(); Node* index = m_graph.varArgChild(m_node, 1).node(); + LocationKind indexedPropertyLoc = indexedPropertyLocForResultType(m_node->result()); ArrayMode mode = m_node->arrayMode(); switch (mode.type()) { @@ -260,21 +261,21 @@ class LocalCSEPhase : public Phase { if (!mode.isInBounds()) break; heap = HeapLocation( - IndexedPropertyLoc, IndexedInt32Properties, base, index); + indexedPropertyLoc, IndexedInt32Properties, base, index); break; case Array::Double: if (!mode.isInBounds()) break; heap = HeapLocation( - IndexedPropertyLoc, IndexedDoubleProperties, base, index); + indexedPropertyLoc, IndexedDoubleProperties, base, index); break; case Array::Contiguous: if (!mode.isInBounds()) break; heap = HeapLocation( - IndexedPropertyLoc, IndexedContiguousProperties, base, index); + indexedPropertyLoc, IndexedContiguousProperties, base, index); break; case Array::Int8Array: @@ -289,7 +290,7 @@ class LocalCSEPhase : public Phase { if (!mode.isInBounds()) break; heap = HeapLocation( - IndexedPropertyLoc, TypedArrayProperties, base, index); + indexedPropertyLoc, TypedArrayProperties, base, index); break; default: diff --git a/webkit/JavaScriptCore/dfg/DFGClobberize.h b/webkit/JavaScriptCore/dfg/DFGClobberize.h index 0c20895a2..3a14dad3c 100755 --- a/webkit/JavaScriptCore/dfg/DFGClobberize.h +++ b/webkit/JavaScriptCore/dfg/DFGClobberize.h @@ -192,6 +192,10 @@ void clobberize(Graph& graph, Node* node, const ReadFunctor& read, const WriteFu read(JSObject_butterfly); ArrayMode mode = node->arrayMode(); switch (mode.type()) { + case Array::ForceExit: { + write(SideState); + return; + } case Array::Int32: { if (mode.isInBounds()) { read(Butterfly_publicLength); @@ -462,6 +466,7 @@ void clobberize(Graph& graph, Node* node, const ReadFunctor& read, const WriteFu case GetByVal: { ArrayMode mode = node->arrayMode(); + LocationKind indexedPropertyLoc = indexedPropertyLocForResultType(node->result()); switch (mode.type()) { case Array::SelectUsingPredictions: case Array::Unprofiled: @@ -492,19 +497,19 @@ void clobberize(Graph& graph, Node* node, const ReadFunctor& read, const WriteFu case Array::DirectArguments: read(DirectArgumentsProperties); - def(HeapLocation(IndexedPropertyLoc, DirectArgumentsProperties, node->child1(), node->child2()), LazyNode(node)); + def(HeapLocation(indexedPropertyLoc, DirectArgumentsProperties, node->child1(), node->child2()), LazyNode(node)); return; case Array::ScopedArguments: read(ScopeProperties); - def(HeapLocation(IndexedPropertyLoc, ScopeProperties, node->child1(), node->child2()), LazyNode(node)); + def(HeapLocation(indexedPropertyLoc, ScopeProperties, node->child1(), node->child2()), LazyNode(node)); return; case Array::Int32: if (mode.isInBounds()) { read(Butterfly_publicLength); read(IndexedInt32Properties); - def(HeapLocation(IndexedPropertyLoc, IndexedInt32Properties, node->child1(), node->child2()), LazyNode(node)); + def(HeapLocation(indexedPropertyLoc, IndexedInt32Properties, node->child1(), node->child2()), LazyNode(node)); return; } read(World); @@ -515,7 +520,7 @@ void clobberize(Graph& graph, Node* node, const ReadFunctor& read, const WriteFu if (mode.isInBounds()) { read(Butterfly_publicLength); read(IndexedDoubleProperties); - def(HeapLocation(IndexedPropertyLoc, IndexedDoubleProperties, node->child1(), node->child2()), LazyNode(node)); + def(HeapLocation(indexedPropertyLoc, IndexedDoubleProperties, node->child1(), node->child2()), LazyNode(node)); return; } read(World); @@ -526,7 +531,7 @@ void clobberize(Graph& graph, Node* node, const ReadFunctor& read, const WriteFu if (mode.isInBounds()) { read(Butterfly_publicLength); read(IndexedContiguousProperties); - def(HeapLocation(IndexedPropertyLoc, IndexedContiguousProperties, node->child1(), node->child2()), LazyNode(node)); + def(HeapLocation(indexedPropertyLoc, IndexedContiguousProperties, node->child1(), node->child2()), LazyNode(node)); return; } read(World); @@ -555,7 +560,7 @@ void clobberize(Graph& graph, Node* node, const ReadFunctor& read, const WriteFu case Array::Float64Array: read(TypedArrayProperties); read(MiscFields); - def(HeapLocation(IndexedPropertyLoc, TypedArrayProperties, node->child1(), node->child2()), LazyNode(node)); + def(HeapLocation(indexedPropertyLoc, TypedArrayProperties, node->child1(), node->child2()), LazyNode(node)); return; } RELEASE_ASSERT_NOT_REACHED(); @@ -576,6 +581,8 @@ void clobberize(Graph& graph, Node* node, const ReadFunctor& read, const WriteFu Node* base = graph.varArgChild(node, 0).node(); Node* index = graph.varArgChild(node, 1).node(); Node* value = graph.varArgChild(node, 2).node(); + LocationKind indexedPropertyLoc = indexedPropertyLocForResultType(node->result()); + switch (mode.modeForPut().type()) { case Array::SelectUsingPredictions: case Array::Unprofiled: @@ -606,7 +613,7 @@ void clobberize(Graph& graph, Node* node, const ReadFunctor& read, const WriteFu write(IndexedInt32Properties); if (node->arrayMode().mayStoreToHole()) write(Butterfly_publicLength); - def(HeapLocation(IndexedPropertyLoc, IndexedInt32Properties, base, index), LazyNode(value)); + def(HeapLocation(indexedPropertyLoc, IndexedInt32Properties, base, index), LazyNode(value)); return; case Array::Double: @@ -621,7 +628,7 @@ void clobberize(Graph& graph, Node* node, const ReadFunctor& read, const WriteFu write(IndexedDoubleProperties); if (node->arrayMode().mayStoreToHole()) write(Butterfly_publicLength); - def(HeapLocation(IndexedPropertyLoc, IndexedDoubleProperties, base, index), LazyNode(value)); + def(HeapLocation(indexedPropertyLoc, IndexedDoubleProperties, base, index), LazyNode(value)); return; case Array::Contiguous: @@ -636,7 +643,7 @@ void clobberize(Graph& graph, Node* node, const ReadFunctor& read, const WriteFu write(IndexedContiguousProperties); if (node->arrayMode().mayStoreToHole()) write(Butterfly_publicLength); - def(HeapLocation(IndexedPropertyLoc, IndexedContiguousProperties, base, index), LazyNode(value)); + def(HeapLocation(indexedPropertyLoc, IndexedContiguousProperties, base, index), LazyNode(value)); return; case Array::ArrayStorage: @@ -860,17 +867,21 @@ void clobberize(Graph& graph, Node* node, const ReadFunctor& read, const WriteFu return; AbstractHeap heap; + LocationKind indexedPropertyLoc; switch (node->indexingType()) { case ALL_DOUBLE_INDEXING_TYPES: heap = IndexedDoubleProperties; + indexedPropertyLoc = IndexedPropertyDoubleLoc; break; case ALL_INT32_INDEXING_TYPES: heap = IndexedInt32Properties; + indexedPropertyLoc = IndexedPropertyJSLoc; break; case ALL_CONTIGUOUS_INDEXING_TYPES: heap = IndexedContiguousProperties; + indexedPropertyLoc = IndexedPropertyJSLoc; break; default: @@ -880,7 +891,7 @@ void clobberize(Graph& graph, Node* node, const ReadFunctor& read, const WriteFu if (numElements < graph.m_uint32ValuesInUse.size()) { for (unsigned operandIdx = 0; operandIdx < numElements; ++operandIdx) { Edge use = graph.m_varArgChildren[node->firstChild() + operandIdx]; - def(HeapLocation(IndexedPropertyLoc, heap, node, LazyNode(graph.freeze(jsNumber(operandIdx)))), + def(HeapLocation(indexedPropertyLoc, heap, node, LazyNode(graph.freeze(jsNumber(operandIdx)))), LazyNode(use.node())); } } else { @@ -889,7 +900,7 @@ void clobberize(Graph& graph, Node* node, const ReadFunctor& read, const WriteFu continue; Edge use = graph.m_varArgChildren[node->firstChild() + operandIdx]; // operandIdx comes from graph.m_uint32ValuesInUse and thus is guaranteed to be already frozen - def(HeapLocation(IndexedPropertyLoc, heap, node, LazyNode(graph.freeze(jsNumber(operandIdx)))), + def(HeapLocation(indexedPropertyLoc, heap, node, LazyNode(graph.freeze(jsNumber(operandIdx)))), LazyNode(use.node())); } } @@ -905,19 +916,23 @@ void clobberize(Graph& graph, Node* node, const ReadFunctor& read, const WriteFu LazyNode(graph.freeze(jsNumber(numElements)))); AbstractHeap heap; + LocationKind indexedPropertyLoc; NodeType op = JSConstant; switch (node->indexingType()) { case ALL_DOUBLE_INDEXING_TYPES: heap = IndexedDoubleProperties; + indexedPropertyLoc = IndexedPropertyDoubleLoc; op = DoubleConstant; break; case ALL_INT32_INDEXING_TYPES: heap = IndexedInt32Properties; + indexedPropertyLoc = IndexedPropertyJSLoc; break; case ALL_CONTIGUOUS_INDEXING_TYPES: heap = IndexedContiguousProperties; + indexedPropertyLoc = IndexedPropertyJSLoc; break; default: @@ -927,7 +942,7 @@ void clobberize(Graph& graph, Node* node, const ReadFunctor& read, const WriteFu JSValue* data = graph.m_codeBlock->constantBuffer(node->startConstant()); if (numElements < graph.m_uint32ValuesInUse.size()) { for (unsigned index = 0; index < numElements; ++index) { - def(HeapLocation(IndexedPropertyLoc, heap, node, LazyNode(graph.freeze(jsNumber(index)))), + def(HeapLocation(indexedPropertyLoc, heap, node, LazyNode(graph.freeze(jsNumber(index)))), LazyNode(graph.freeze(data[index]), op)); } } else { @@ -938,7 +953,7 @@ void clobberize(Graph& graph, Node* node, const ReadFunctor& read, const WriteFu possibleIndices.append(index); } for (uint32_t index : possibleIndices) { - def(HeapLocation(IndexedPropertyLoc, heap, node, LazyNode(graph.freeze(jsNumber(index)))), + def(HeapLocation(indexedPropertyLoc, heap, node, LazyNode(graph.freeze(jsNumber(index)))), LazyNode(graph.freeze(data[index]), op)); } } diff --git a/webkit/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp b/webkit/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp index fd8df4d99..102aef5eb 100755 --- a/webkit/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp +++ b/webkit/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp @@ -54,22 +54,57 @@ class ConstantFoldingPhase : public Phase { bool run() { bool changed = false; - - for (BlockIndex blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex) { - BasicBlock* block = m_graph.block(blockIndex); - if (!block) - continue; + + for (BasicBlock* block : m_graph.blocksInNaturalOrder()) { if (block->cfaFoundConstants) changed |= foldConstants(block); } if (changed && m_graph.m_form == SSA) { // It's now possible that we have Upsilons pointed at JSConstants. Fix that. - for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;) { - BasicBlock* block = m_graph.block(blockIndex); - if (!block) - continue; + for (BasicBlock* block : m_graph.blocksInNaturalOrder()) fixUpsilons(block); + } + + if (m_graph.m_form == SSA) { + // It's now possible to simplify basic blocks by placing an Unreachable terminator right + // after anything that invalidates AI. + bool didClipBlock = false; + Vector nodesToDelete; + for (BasicBlock* block : m_graph.blocksInNaturalOrder()) { + m_state.beginBasicBlock(block); + for (unsigned nodeIndex = 0; nodeIndex < block->size(); ++nodeIndex) { + if (block->at(nodeIndex)->isTerminal()) { + // It's possible that we have something after the terminal. It could be a + // no-op Check node, for example. We don't want the logic below to turn that + // node into Unreachable, since then we'd have two terminators. + break; + } + if (!m_state.isValid()) { + NodeOrigin origin = block->at(nodeIndex)->origin; + for (unsigned killIndex = nodeIndex; killIndex < block->size(); ++killIndex) + nodesToDelete.append(block->at(killIndex)); + block->resize(nodeIndex); + block->appendNode(m_graph, SpecNone, Unreachable, origin); + didClipBlock = true; + break; + } + m_interpreter.execute(nodeIndex); + } + m_state.reset(); + } + + if (didClipBlock) { + changed = true; + + m_graph.invalidateNodeLiveness(); + + for (Node* node : nodesToDelete) + m_graph.m_allocator.free(node); + + m_graph.invalidateCFG(); + m_graph.resetReachability(); + m_graph.killUnreachableBlocks(); } } diff --git a/webkit/JavaScriptCore/dfg/DFGConstantHoistingPhase.cpp b/webkit/JavaScriptCore/dfg/DFGConstantHoistingPhase.cpp index 68f3651c5..5b1170c04 100755 --- a/webkit/JavaScriptCore/dfg/DFGConstantHoistingPhase.cpp +++ b/webkit/JavaScriptCore/dfg/DFGConstantHoistingPhase.cpp @@ -128,6 +128,7 @@ class ConstantHoistingPhase : public Phase { } // And finally free the constants that we removed. + m_graph.invalidateNodeLiveness(); for (Node* node : toFree) m_graph.m_allocator.free(node); diff --git a/webkit/JavaScriptCore/dfg/DFGFixupPhase.cpp b/webkit/JavaScriptCore/dfg/DFGFixupPhase.cpp index d8a2c25e0..080bcca18 100755 --- a/webkit/JavaScriptCore/dfg/DFGFixupPhase.cpp +++ b/webkit/JavaScriptCore/dfg/DFGFixupPhase.cpp @@ -908,6 +908,11 @@ class FixupPhase : public Phase { break; } + case NewArrayBuffer: { + watchHavingABadTime(node); + break; + } + case ToThis: { ECMAMode ecmaMode = m_graph.executableFor(node->origin.semantic)->isStrictMode() ? StrictMode : NotStrictMode; @@ -1293,7 +1298,6 @@ class FixupPhase : public Phase { case NativeCall: case NativeConstruct: case NewObject: - case NewArrayBuffer: case NewRegexp: case Breakpoint: case ProfileWillCall: diff --git a/webkit/JavaScriptCore/dfg/DFGGraph.cpp b/webkit/JavaScriptCore/dfg/DFGGraph.cpp index c1172922b..a5af58f9f 100755 --- a/webkit/JavaScriptCore/dfg/DFGGraph.cpp +++ b/webkit/JavaScriptCore/dfg/DFGGraph.cpp @@ -704,6 +704,8 @@ void Graph::computeRefCounts() void Graph::killBlockAndItsContents(BasicBlock* block) { + if (auto& ssaData = block->ssa) + ssaData->invalidate(); for (unsigned phiIndex = block->phis.size(); phiIndex--;) m_allocator.free(block->phis[phiIndex]); for (unsigned nodeIndex = block->size(); nodeIndex--;) @@ -714,6 +716,8 @@ void Graph::killBlockAndItsContents(BasicBlock* block) void Graph::killUnreachableBlocks() { + invalidateNodeLiveness(); + for (BlockIndex blockIndex = 0; blockIndex < numBlocks(); ++blockIndex) { BasicBlock* block = this->block(blockIndex); if (!block) @@ -732,6 +736,15 @@ void Graph::invalidateCFG() m_prePostNumbering.invalidate(); } +void Graph::invalidateNodeLiveness() +{ + if (m_form != SSA) + return; + + for (BasicBlock* block : blocksInNaturalOrder()) + block->ssa->invalidate(); +} + void Graph::substituteGetLocal(BasicBlock& block, unsigned startIndexInBlock, VariableAccessData* variableAccessData, Node* newGetLocal) { for (unsigned indexInBlock = startIndexInBlock; indexInBlock < block.size(); ++indexInBlock) { diff --git a/webkit/JavaScriptCore/dfg/DFGGraph.h b/webkit/JavaScriptCore/dfg/DFGGraph.h index fd6d6966a..29df7d216 100755 --- a/webkit/JavaScriptCore/dfg/DFGGraph.h +++ b/webkit/JavaScriptCore/dfg/DFGGraph.h @@ -562,6 +562,7 @@ class Graph : public virtual Scannable { void substituteGetLocal(BasicBlock& block, unsigned startIndexInBlock, VariableAccessData* variableAccessData, Node* newGetLocal); void invalidateCFG(); + void invalidateNodeLiveness(); void clearFlagsOnAllNodes(NodeFlags); diff --git a/webkit/JavaScriptCore/dfg/DFGHeapLocation.cpp b/webkit/JavaScriptCore/dfg/DFGHeapLocation.cpp index 2ca344a53..628998ff5 100755 --- a/webkit/JavaScriptCore/dfg/DFGHeapLocation.cpp +++ b/webkit/JavaScriptCore/dfg/DFGHeapLocation.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014, 2015 Apple Inc. All rights reserved. + * Copyright (C) 2014-2017 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -111,11 +111,19 @@ void printInternal(PrintStream& out, LocationKind kind) case HasIndexedPropertyLoc: out.print("HasIndexedPorpertyLoc"); return; - - case IndexedPropertyLoc: - out.print("IndexedPorpertyLoc"); + + case IndexedPropertyDoubleLoc: + out.print("IndexedPropertyDoubleLoc"); return; - + + case IndexedPropertyInt52Loc: + out.print("IndexedPropertyInt52Loc"); + return; + + case IndexedPropertyJSLoc: + out.print("IndexedPropertyJSLoc"); + return; + case IndexedPropertyStorageLoc: out.print("IndexedPropertyStorageLoc"); return; diff --git a/webkit/JavaScriptCore/dfg/DFGHeapLocation.h b/webkit/JavaScriptCore/dfg/DFGHeapLocation.h index 3d3a94ccf..d98a31ee6 100755 --- a/webkit/JavaScriptCore/dfg/DFGHeapLocation.h +++ b/webkit/JavaScriptCore/dfg/DFGHeapLocation.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014, 2015 Apple Inc. All rights reserved. + * Copyright (C) 2014-2017 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -45,7 +45,9 @@ enum LocationKind { GetterLoc, GlobalVariableLoc, HasIndexedPropertyLoc, - IndexedPropertyLoc, + IndexedPropertyDoubleLoc, + IndexedPropertyInt52Loc, + IndexedPropertyJSLoc, IndexedPropertyStorageLoc, InstanceOfLoc, InvalidationPointLoc, @@ -134,6 +136,29 @@ struct HeapLocationHash { static const bool safeToCompareToEmptyOrDeleted = true; }; +LocationKind indexedPropertyLocForResultType(NodeFlags); + +inline LocationKind indexedPropertyLocForResultType(NodeFlags canonicalResultRepresentation) +{ + if (!canonicalResultRepresentation) + return IndexedPropertyJSLoc; + + ASSERT((canonicalResultRepresentation & NodeResultMask) == canonicalResultRepresentation); + switch (canonicalResultRepresentation) { + case NodeResultDouble: + return IndexedPropertyDoubleLoc; + case NodeResultInt52: + return IndexedPropertyInt52Loc; + case NodeResultJS: + return IndexedPropertyJSLoc; + case NodeResultStorage: + RELEASE_ASSERT_NOT_REACHED(); + default: + break; + } + RELEASE_ASSERT_NOT_REACHED(); +} + } } // namespace JSC::DFG namespace WTF { diff --git a/webkit/JavaScriptCore/dfg/DFGIntegerCheckCombiningPhase.cpp b/webkit/JavaScriptCore/dfg/DFGIntegerCheckCombiningPhase.cpp index 5ddda089d..27a02a217 100755 --- a/webkit/JavaScriptCore/dfg/DFGIntegerCheckCombiningPhase.cpp +++ b/webkit/JavaScriptCore/dfg/DFGIntegerCheckCombiningPhase.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014 Apple Inc. All rights reserved. + * Copyright (C) 2014-2017 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -105,7 +105,16 @@ struct RangeKey { out.print("ArrayBounds("); break; } - out.print(m_source, ", ", m_key, ")"); + if (m_source) + out.print(m_source); + else + out.print("null"); + out.print(", "); + if (m_key) + out.print(m_key); + else + out.print("null"); + out.print(")"); } RangeKind m_kind; @@ -253,7 +262,13 @@ class IntegerCheckCombiningPhase : public Phase { Node* maxNode; if (!data.m_key.m_source) { - minNode = 0; + // data.m_key.m_source being null means that we're comparing against int32 constants (see rangeKeyAndAddend()). + // Since CheckInBounds does an unsigned comparison, if the minBound >= 0, it is also covered by the + // maxBound comparison. However, if minBound < 0, then CheckInBounds should always fail its speculation check. + // We'll force an OSR exit in that case. + minNode = nullptr; + if (range.m_minBound < 0) + m_insertionSet.insertNode(nodeIndex, SpecNone, ForceOSRExit, node->origin); maxNode = m_insertionSet.insertConstant( nodeIndex, range.m_maxOrigin, jsNumber(range.m_maxBound)); } else { diff --git a/webkit/JavaScriptCore/dfg/DFGPlan.cpp b/webkit/JavaScriptCore/dfg/DFGPlan.cpp index 1bd900c6c..2d3ee558c 100755 --- a/webkit/JavaScriptCore/dfg/DFGPlan.cpp +++ b/webkit/JavaScriptCore/dfg/DFGPlan.cpp @@ -215,6 +215,21 @@ Plan::CompilationPath Plan::compileInThreadImpl(LongLivedState& longLivedState) return FailPath; } + bool changed = false; + +#define RUN_PHASE(phase) \ + do { \ + if (Options::safepointBeforeEachPhase()) { \ + Safepoint::Result safepointResult; \ + { \ + GraphSafepoint safepoint(dfg, safepointResult); \ + } \ + if (safepointResult.didGetCancelled()) \ + return CancelPath; \ + } \ + changed |= phase(dfg); \ + } while (false); \ + // By this point the DFG bytecode parser will have potentially mutated various tables // in the CodeBlock. This is a good time to perform an early shrink, which is more // powerful than a late one. It's safe to do so because we haven't generated any code @@ -229,11 +244,16 @@ Plan::CompilationPath Plan::compileInThreadImpl(LongLivedState& longLivedState) dfg.dump(); } - performCPSRethreading(dfg); - performUnification(dfg); - performPredictionInjection(dfg); + RUN_PHASE(performLiveCatchVariablePreservationPhase); + + if (Options::useMaximalFlushInsertionPhase()) + RUN_PHASE(performMaximalFlushInsertion); + + RUN_PHASE(performCPSRethreading); + RUN_PHASE(performUnification); + RUN_PHASE(performPredictionInjection); - performStaticExecutionCountEstimation(dfg); + RUN_PHASE(performStaticExecutionCountEstimation); if (mode == FTLForOSREntryMode) { bool result = performOSREntrypointCreation(dfg); @@ -241,18 +261,18 @@ Plan::CompilationPath Plan::compileInThreadImpl(LongLivedState& longLivedState) finalizer = std::make_unique(*this); return FailPath; } - performCPSRethreading(dfg); + RUN_PHASE(performCPSRethreading); } if (validationEnabled()) validate(dfg); - performBackwardsPropagation(dfg); - performPredictionPropagation(dfg); - performFixup(dfg); - performStructureRegistration(dfg); - performInvalidationPointInjection(dfg); - performTypeCheckHoisting(dfg); + RUN_PHASE(performBackwardsPropagation); + RUN_PHASE(performPredictionPropagation); + RUN_PHASE(performFixup); + RUN_PHASE(performStructureRegistration); + RUN_PHASE(performInvalidationPointInjection); + RUN_PHASE(performTypeCheckHoisting); dfg.m_fixpointState = FixpointNotConverged; @@ -264,19 +284,18 @@ Plan::CompilationPath Plan::compileInThreadImpl(LongLivedState& longLivedState) if (validationEnabled()) validate(dfg); - performStrengthReduction(dfg); - performLocalCSE(dfg); - performCPSRethreading(dfg); - performCFA(dfg); - performConstantFolding(dfg); - bool changed = false; - changed |= performCFGSimplification(dfg); - changed |= performLocalCSE(dfg); + RUN_PHASE(performStrengthReduction); + RUN_PHASE(performCPSRethreading); + RUN_PHASE(performCFA); + RUN_PHASE(performConstantFolding); + changed = false; + RUN_PHASE(performCFGSimplification); + RUN_PHASE(performLocalCSE); if (validationEnabled()) validate(dfg); - performCPSRethreading(dfg); + RUN_PHASE(performCPSRethreading); if (!isFTL(mode)) { // Only run this if we're not FTLing, because currently for a LoadVarargs that is forwardable and // in a non-varargs inlined call frame, this will generate ForwardVarargs while the FTL @@ -297,11 +316,11 @@ Plan::CompilationPath Plan::compileInThreadImpl(LongLivedState& longLivedState) // ArgumentsEliminationPhase does everything that this phase does, and it doesn't introduce this // pathology. - changed |= performVarargsForwarding(dfg); // Do this after CFG simplification and CPS rethreading. + RUN_PHASE(performVarargsForwarding); // Do this after CFG simplification and CPS rethreading. } if (changed) { - performCFA(dfg); - performConstantFolding(dfg); + RUN_PHASE(performCFA); + RUN_PHASE(performConstantFolding); } // If we're doing validation, then run some analyses, to give them an opportunity @@ -316,16 +335,17 @@ Plan::CompilationPath Plan::compileInThreadImpl(LongLivedState& longLivedState) case DFGMode: { dfg.m_fixpointState = FixpointConverged; - performTierUpCheckInjection(dfg); - - performFastStoreBarrierInsertion(dfg); - performCleanUp(dfg); - performCPSRethreading(dfg); - performDCE(dfg); - performPhantomInsertion(dfg); - performStackLayout(dfg); - performVirtualRegisterAllocation(dfg); - performWatchpointCollection(dfg); + RUN_PHASE(performTierUpCheckInjection); + + RUN_PHASE(performFastStoreBarrierInsertion); + RUN_PHASE(performStoreBarrierClustering); + RUN_PHASE(performCleanUp); + RUN_PHASE(performCPSRethreading); + RUN_PHASE(performDCE); + RUN_PHASE(performPhantomInsertion); + RUN_PHASE(performStackLayout); + RUN_PHASE(performVirtualRegisterAllocation); + RUN_PHASE(performWatchpointCollection); dumpAndVerifyGraph(dfg, "Graph after optimization:"); JITCompiler dataFlowJIT(dfg); @@ -345,38 +365,37 @@ Plan::CompilationPath Plan::compileInThreadImpl(LongLivedState& longLivedState) return FailPath; } - performCleanUp(dfg); // Reduce the graph size a bit. - performCriticalEdgeBreaking(dfg); - performLoopPreHeaderCreation(dfg); - performCPSRethreading(dfg); - performSSAConversion(dfg); - performSSALowering(dfg); + RUN_PHASE(performCleanUp); // Reduce the graph size a bit. + RUN_PHASE(performCriticalEdgeBreaking); + if (Options::createPreHeaders()) + RUN_PHASE(performLoopPreHeaderCreation); + RUN_PHASE(performCPSRethreading); + RUN_PHASE(performSSAConversion); + RUN_PHASE(performSSALowering); // Ideally, these would be run to fixpoint with the object allocation sinking phase. - performArgumentsElimination(dfg); + RUN_PHASE(performArgumentsElimination); if (Options::usePutStackSinking()) - performPutStackSinking(dfg); + RUN_PHASE(performPutStackSinking); - performConstantHoisting(dfg); - performGlobalCSE(dfg); - performLivenessAnalysis(dfg); - performIntegerRangeOptimization(dfg); - performLivenessAnalysis(dfg); - performCFA(dfg); - performConstantFolding(dfg); - performCleanUp(dfg); // Reduce the graph size a lot. + RUN_PHASE(performConstantHoisting); + RUN_PHASE(performGlobalCSE); + RUN_PHASE(performLivenessAnalysis); + RUN_PHASE(performCFA); + RUN_PHASE(performConstantFolding); + RUN_PHASE(performCleanUp); // Reduce the graph size a lot. changed = false; - changed |= performStrengthReduction(dfg); + RUN_PHASE(performStrengthReduction); if (Options::enableObjectAllocationSinking()) { - changed |= performCriticalEdgeBreaking(dfg); - changed |= performObjectAllocationSinking(dfg); + RUN_PHASE(performCriticalEdgeBreaking); + RUN_PHASE(performObjectAllocationSinking); } if (changed) { // State-at-tail and state-at-head will be invalid if we did strength reduction since // it might increase live ranges. - performLivenessAnalysis(dfg); - performCFA(dfg); - performConstantFolding(dfg); + RUN_PHASE(performLivenessAnalysis); + RUN_PHASE(performCFA); + RUN_PHASE(performConstantFolding); } // Currently, this relies on pre-headers still being valid. That precludes running CFG @@ -384,27 +403,40 @@ Plan::CompilationPath Plan::compileInThreadImpl(LongLivedState& longLivedState) // wrong with running LICM earlier, if we wanted to put other CFG transforms above this point. // Alternatively, we could run loop pre-header creation after SSA conversion - but if we did that // then we'd need to do some simple SSA fix-up. - performLICM(dfg); + RUN_PHASE(performLivenessAnalysis); + RUN_PHASE(performCFA); + RUN_PHASE(performLICM); - performCleanUp(dfg); - performIntegerCheckCombining(dfg); - performGlobalCSE(dfg); + // FIXME: Currently: IntegerRangeOptimization *must* be run after LICM. + // + // IntegerRangeOptimization makes changes on nodes based on preceding blocks + // and nodes. LICM moves nodes which can invalidates assumptions used + // by IntegerRangeOptimization. + // + // Ideally, the dependencies should be explicit. See https://bugs.webkit.org/show_bug.cgi?id=157534. + RUN_PHASE(performLivenessAnalysis); + RUN_PHASE(performIntegerRangeOptimization); + + RUN_PHASE(performCleanUp); + RUN_PHASE(performIntegerCheckCombining); + RUN_PHASE(performGlobalCSE); // At this point we're not allowed to do any further code motion because our reasoning // about code motion assumes that it's OK to insert GC points in random places. dfg.m_fixpointState = FixpointConverged; - performLivenessAnalysis(dfg); - performCFA(dfg); - performGlobalStoreBarrierInsertion(dfg); + RUN_PHASE(performLivenessAnalysis); + RUN_PHASE(performCFA); + RUN_PHASE(performGlobalStoreBarrierInsertion); + RUN_PHASE(performStoreBarrierClustering); if (Options::enableMovHintRemoval()) - performMovHintRemoval(dfg); - performCleanUp(dfg); - performDCE(dfg); // We rely on this to kill dead code that won't be recognized as dead by LLVM. - performStackLayout(dfg); - performLivenessAnalysis(dfg); - performOSRAvailabilityAnalysis(dfg); - performWatchpointCollection(dfg); + RUN_PHASE(performMovHintRemoval); + RUN_PHASE(performCleanUp); + RUN_PHASE(performDCE); // We rely on this to kill dead code that won't be recognized as dead by B3. + RUN_PHASE(performStackLayout); + RUN_PHASE(performLivenessAnalysis); + RUN_PHASE(performOSRAvailabilityAnalysis); + RUN_PHASE(performWatchpointCollection); if (FTL::canCompile(dfg) == FTL::CannotCompile) { finalizer = std::make_unique(*this); @@ -479,6 +511,8 @@ Plan::CompilationPath Plan::compileInThreadImpl(LongLivedState& longLivedState) RELEASE_ASSERT_NOT_REACHED(); return FailPath; } + +#undef RUN_PHASE } bool Plan::isStillValid() diff --git a/webkit/JavaScriptCore/dfg/DFGSafepoint.cpp b/webkit/JavaScriptCore/dfg/DFGSafepoint.cpp index 11ba5ad9b..8cf03f49f 100755 --- a/webkit/JavaScriptCore/dfg/DFGSafepoint.cpp +++ b/webkit/JavaScriptCore/dfg/DFGSafepoint.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014 Apple Inc. All rights reserved. + * Copyright (C) 2014-2017 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -79,7 +79,7 @@ void Safepoint::begin() if (ThreadData* data = m_plan.threadData) { RELEASE_ASSERT(!data->m_safepoint); data->m_safepoint = this; - data->m_rightToRun.unlock(); + data->m_rightToRun.unlockFairly(); } } diff --git a/webkit/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp b/webkit/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp index 7e08d9bfd..f969b840f 100755 --- a/webkit/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp +++ b/webkit/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp @@ -3698,8 +3698,6 @@ void SpeculativeJIT::compile(Node* node) } case GetById: { - ASSERT(node->prediction()); - switch (node->child1().useKind()) { case CellUse: { SpeculateCellOperand base(this, node->child1()); diff --git a/webkit/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp b/webkit/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp index 2c78f9a22..7727ef974 100755 --- a/webkit/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp +++ b/webkit/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp @@ -3739,8 +3739,6 @@ void SpeculativeJIT::compile(Node* node) break; } case GetById: { - ASSERT(node->prediction()); - switch (node->child1().useKind()) { case CellUse: { SpeculateCellOperand base(this, node->child1()); diff --git a/webkit/JavaScriptCore/heap/Heap.cpp b/webkit/JavaScriptCore/heap/Heap.cpp index e58a60936..4df7d139f 100755 --- a/webkit/JavaScriptCore/heap/Heap.cpp +++ b/webkit/JavaScriptCore/heap/Heap.cpp @@ -1079,7 +1079,9 @@ NEVER_INLINE void Heap::collectImpl(HeapOperation collectionType, void* stackOri removeDeadCompilerWorklistEntries(); deleteUnmarkedCompiledCode(); deleteSourceProviderCaches(); +#if !PLATFORM(WKC) notifyIncrementalSweeper(); +#endif rememberCurrentlyExecutingCodeBlocks(); resetAllocators(); @@ -1087,6 +1089,10 @@ NEVER_INLINE void Heap::collectImpl(HeapOperation collectionType, void* stackOri didFinishCollection(gcStartTime); resumeCompilerThreads(); +#if PLATFORM(WKC) + notifyIncrementalSweeper(); +#endif + if (m_verifier) { m_verifier->trimDeadObjects(); m_verifier->verify(HeapVerifier::Phase::AfterGC); diff --git a/webkit/JavaScriptCore/icu/unicode/ucurr.h b/webkit/JavaScriptCore/icu/unicode/ucurr.h new file mode 100755 index 000000000..27698133e --- /dev/null +++ b/webkit/JavaScriptCore/icu/unicode/ucurr.h @@ -0,0 +1,360 @@ +/* +********************************************************************** +* Copyright (c) 2002-2013, International Business Machines +* Corporation and others. All Rights Reserved. +********************************************************************** +*/ +#ifndef _UCURR_H_ +#define _UCURR_H_ + +#include "unicode/utypes.h" +#include "unicode/uenum.h" + +/** + * \file + * \brief C API: Encapsulates information about a currency. + */ + +#if !UCONFIG_NO_FORMATTING + +/** + * The ucurr API encapsulates information about a currency, as defined by + * ISO 4217. A currency is represented by a 3-character string + * containing its ISO 4217 code. This API can return various data + * necessary the proper display of a currency: + * + *
  • A display symbol, for a specific locale + *
  • The number of fraction digits to display + *
  • A rounding increment + *
+ * + * The DecimalFormat class uses these data to display + * currencies. + * @author Alan Liu + * @since ICU 2.2 + */ + +/** + * Finds a currency code for the given locale. + * @param locale the locale for which to retrieve a currency code. + * Currency can be specified by the "currency" keyword + * in which case it overrides the default currency code + * @param buff fill in buffer. Can be NULL for preflighting. + * @param buffCapacity capacity of the fill in buffer. Can be 0 for + * preflighting. If it is non-zero, the buff parameter + * must not be NULL. + * @param ec error code + * @return length of the currency string. It should always be 3. If 0, + * currency couldn't be found or the input values are + * invalid. + * @stable ICU 2.8 + */ +U_STABLE int32_t U_EXPORT2 +ucurr_forLocale(const char* locale, + UChar* buff, + int32_t buffCapacity, + UErrorCode* ec); + +/** + * Selector constants for ucurr_getName(). + * + * @see ucurr_getName + * @stable ICU 2.6 + */ +typedef enum UCurrNameStyle { + /** + * Selector for ucurr_getName indicating a symbolic name for a + * currency, such as "$" for USD. + * @stable ICU 2.6 + */ + UCURR_SYMBOL_NAME, + + /** + * Selector for ucurr_getName indicating the long name for a + * currency, such as "US Dollar" for USD. + * @stable ICU 2.6 + */ + UCURR_LONG_NAME +} UCurrNameStyle; + +#if !UCONFIG_NO_SERVICE +/** + * @stable ICU 2.6 + */ +typedef const void* UCurrRegistryKey; + +/** + * Register an (existing) ISO 4217 currency code for the given locale. + * Only the country code and the two variants EURO and PRE_EURO are + * recognized. + * @param isoCode the three-letter ISO 4217 currency code + * @param locale the locale for which to register this currency code + * @param status the in/out status code + * @return a registry key that can be used to unregister this currency code, or NULL + * if there was an error. + * @stable ICU 2.6 + */ +U_STABLE UCurrRegistryKey U_EXPORT2 +ucurr_register(const UChar* isoCode, + const char* locale, + UErrorCode* status); +/** + * Unregister the previously-registered currency definitions using the + * URegistryKey returned from ucurr_register. Key becomes invalid after + * a successful call and should not be used again. Any currency + * that might have been hidden by the original ucurr_register call is + * restored. + * @param key the registry key returned by a previous call to ucurr_register + * @param status the in/out status code, no special meanings are assigned + * @return TRUE if the currency for this key was successfully unregistered + * @stable ICU 2.6 + */ +U_STABLE UBool U_EXPORT2 +ucurr_unregister(UCurrRegistryKey key, UErrorCode* status); +#endif /* UCONFIG_NO_SERVICE */ + +/** + * Returns the display name for the given currency in the + * given locale. For example, the display name for the USD + * currency object in the en_US locale is "$". + * @param currency null-terminated 3-letter ISO 4217 code + * @param locale locale in which to display currency + * @param nameStyle selector for which kind of name to return + * @param isChoiceFormat fill-in set to TRUE if the returned value + * is a ChoiceFormat pattern; otherwise it is a static string + * @param len fill-in parameter to receive length of result + * @param ec error code + * @return pointer to display string of 'len' UChars. If the resource + * data contains no entry for 'currency', then 'currency' itself is + * returned. If *isChoiceFormat is TRUE, then the result is a + * ChoiceFormat pattern. Otherwise it is a static string. + * @stable ICU 2.6 + */ +U_STABLE const UChar* U_EXPORT2 +ucurr_getName(const UChar* currency, + const char* locale, + UCurrNameStyle nameStyle, + UBool* isChoiceFormat, + int32_t* len, + UErrorCode* ec); + +/** + * Returns the plural name for the given currency in the + * given locale. For example, the plural name for the USD + * currency object in the en_US locale is "US dollar" or "US dollars". + * @param currency null-terminated 3-letter ISO 4217 code + * @param locale locale in which to display currency + * @param isChoiceFormat fill-in set to TRUE if the returned value + * is a ChoiceFormat pattern; otherwise it is a static string + * @param pluralCount plural count + * @param len fill-in parameter to receive length of result + * @param ec error code + * @return pointer to display string of 'len' UChars. If the resource + * data contains no entry for 'currency', then 'currency' itself is + * returned. + * @stable ICU 4.2 + */ +U_STABLE const UChar* U_EXPORT2 +ucurr_getPluralName(const UChar* currency, + const char* locale, + UBool* isChoiceFormat, + const char* pluralCount, + int32_t* len, + UErrorCode* ec); + +/** + * Returns the number of the number of fraction digits that should + * be displayed for the given currency. + * @param currency null-terminated 3-letter ISO 4217 code + * @param ec input-output error code + * @return a non-negative number of fraction digits to be + * displayed, or 0 if there is an error + * @stable ICU 3.0 + */ +U_STABLE int32_t U_EXPORT2 +ucurr_getDefaultFractionDigits(const UChar* currency, + UErrorCode* ec); + +/** + * Returns the rounding increment for the given currency, or 0.0 if no + * rounding is done by the currency. + * @param currency null-terminated 3-letter ISO 4217 code + * @param ec input-output error code + * @return the non-negative rounding increment, or 0.0 if none, + * or 0.0 if there is an error + * @stable ICU 3.0 + */ +U_STABLE double U_EXPORT2 +ucurr_getRoundingIncrement(const UChar* currency, + UErrorCode* ec); + +/** + * Selector constants for ucurr_openCurrencies(). + * + * @see ucurr_openCurrencies + * @stable ICU 3.2 + */ +typedef enum UCurrCurrencyType { + /** + * Select all ISO-4217 currency codes. + * @stable ICU 3.2 + */ + UCURR_ALL = INT32_MAX, + /** + * Select only ISO-4217 commonly used currency codes. + * These currencies can be found in common use, and they usually have + * bank notes or coins associated with the currency code. + * This does not include fund codes, precious metals and other + * various ISO-4217 codes limited to special financial products. + * @stable ICU 3.2 + */ + UCURR_COMMON = 1, + /** + * Select ISO-4217 uncommon currency codes. + * These codes respresent fund codes, precious metals and other + * various ISO-4217 codes limited to special financial products. + * A fund code is a monetary resource associated with a currency. + * @stable ICU 3.2 + */ + UCURR_UNCOMMON = 2, + /** + * Select only deprecated ISO-4217 codes. + * These codes are no longer in general public use. + * @stable ICU 3.2 + */ + UCURR_DEPRECATED = 4, + /** + * Select only non-deprecated ISO-4217 codes. + * These codes are in general public use. + * @stable ICU 3.2 + */ + UCURR_NON_DEPRECATED = 8 +} UCurrCurrencyType; + +/** + * Provides a UEnumeration object for listing ISO-4217 codes. + * @param currType You can use one of several UCurrCurrencyType values for this + * variable. You can also | (or) them together to get a specific list of + * currencies. Most people will want to use the (UCURR_CURRENCY|UCURR_NON_DEPRECATED) value to + * get a list of current currencies. + * @param pErrorCode Error code + * @stable ICU 3.2 + */ +U_STABLE UEnumeration * U_EXPORT2 +ucurr_openISOCurrencies(uint32_t currType, UErrorCode *pErrorCode); + +/** + * Queries if the given ISO 4217 3-letter code is available on the specified date range. + * + * Note: For checking availability of a currency on a specific date, specify the date on both 'from' and 'to' + * + * When 'from' is U_DATE_MIN and 'to' is U_DATE_MAX, this method checks if the specified currency is available any time. + * If 'from' and 'to' are same UDate value, this method checks if the specified currency is available on that date. + * + * @param isoCode + * The ISO 4217 3-letter code. + * + * @param from + * The lower bound of the date range, inclusive. When 'from' is U_DATE_MIN, check the availability + * of the currency any date before 'to' + * + * @param to + * The upper bound of the date range, inclusive. When 'to' is U_DATE_MAX, check the availability of + * the currency any date after 'from' + * + * @param errorCode + * ICU error code + * + * @return TRUE if the given ISO 4217 3-letter code is supported on the specified date range. + * + * @stable ICU 4.8 + */ +U_STABLE UBool U_EXPORT2 +ucurr_isAvailable(const UChar* isoCode, + UDate from, + UDate to, + UErrorCode* errorCode); + +/** + * Finds the number of valid currency codes for the + * given locale and date. + * @param locale the locale for which to retrieve the + * currency count. + * @param date the date for which to retrieve the + * currency count for the given locale. + * @param ec error code + * @return the number of currency codes for the + * given locale and date. If 0, currency + * codes couldn't be found for the input + * values are invalid. + * @stable ICU 4.0 + */ +U_STABLE int32_t U_EXPORT2 +ucurr_countCurrencies(const char* locale, + UDate date, + UErrorCode* ec); + +/** + * Finds a currency code for the given locale and date + * @param locale the locale for which to retrieve a currency code. + * Currency can be specified by the "currency" keyword + * in which case it overrides the default currency code + * @param date the date for which to retrieve a currency code for + * the given locale. + * @param index the index within the available list of currency codes + * for the given locale on the given date. + * @param buff fill in buffer. Can be NULL for preflighting. + * @param buffCapacity capacity of the fill in buffer. Can be 0 for + * preflighting. If it is non-zero, the buff parameter + * must not be NULL. + * @param ec error code + * @return length of the currency string. It should always be 3. + * If 0, currency couldn't be found or the input values are + * invalid. + * @stable ICU 4.0 + */ +U_STABLE int32_t U_EXPORT2 +ucurr_forLocaleAndDate(const char* locale, + UDate date, + int32_t index, + UChar* buff, + int32_t buffCapacity, + UErrorCode* ec); + +/** + * Given a key and a locale, returns an array of string values in a preferred + * order that would make a difference. These are all and only those values where + * the open (creation) of the service with the locale formed from the input locale + * plus input keyword and that value has different behavior than creation with the + * input locale alone. + * @param key one of the keys supported by this service. For now, only + * "currency" is supported. + * @param locale the locale + * @param commonlyUsed if set to true it will return only commonly used values + * with the given locale in preferred order. Otherwise, + * it will return all the available values for the locale. + * @param status error status + * @return a string enumeration over keyword values for the given key and the locale. + * @stable ICU 4.2 + */ +U_STABLE UEnumeration* U_EXPORT2 +ucurr_getKeywordValuesForLocale(const char* key, + const char* locale, + UBool commonlyUsed, + UErrorCode* status); + +/** + * Returns the ISO 4217 numeric code for the currency. + *

Note: If the ISO 4217 numeric code is not assigned for the currency or + * the currency is unknown, this function returns 0. + * + * @param currency null-terminated 3-letter ISO 4217 code + * @return The ISO 4217 numeric code of the currency + * @stable ICU 49 + */ +U_STABLE int32_t U_EXPORT2 +ucurr_getNumericCode(const UChar* currency); + +#endif /* #if !UCONFIG_NO_FORMATTING */ + +#endif diff --git a/webkit/JavaScriptCore/jit/JIT.cpp b/webkit/JavaScriptCore/jit/JIT.cpp index 23d31da56..70a64db72 100755 --- a/webkit/JavaScriptCore/jit/JIT.cpp +++ b/webkit/JavaScriptCore/jit/JIT.cpp @@ -662,19 +662,33 @@ CompilationResult JIT::privateCompile(JITCompilationEffort effort) m_putByIds[i].finalize(patchBuffer); m_codeBlock->setNumberOfByValInfos(m_byValCompilationInfo.size()); - for (unsigned i = 0; i < m_byValCompilationInfo.size(); ++i) { - CodeLocationJump badTypeJump = CodeLocationJump(patchBuffer.locationOf(m_byValCompilationInfo[i].badTypeJump)); - CodeLocationLabel doneTarget = patchBuffer.locationOf(m_byValCompilationInfo[i].doneTarget); - CodeLocationLabel slowPathTarget = patchBuffer.locationOf(m_byValCompilationInfo[i].slowPathTarget); - CodeLocationCall returnAddress = patchBuffer.locationOf(m_byValCompilationInfo[i].returnAddress); + if (m_byValCompilationInfo.size()) { + CodeLocationLabel exceptionHandler = patchBuffer.locationOf(m_exceptionHandler); - m_codeBlock->byValInfo(i) = ByValInfo( - m_byValCompilationInfo[i].bytecodeIndex, - badTypeJump, - m_byValCompilationInfo[i].arrayMode, - differenceBetweenCodePtr(badTypeJump, doneTarget), - differenceBetweenCodePtr(returnAddress, slowPathTarget)); + for (const auto& byValCompilationInfo : m_byValCompilationInfo) { + PatchableJump patchableNotIndexJump = byValCompilationInfo.notIndexJump; + CodeLocationJump notIndexJump = CodeLocationJump(); + if (Jump(patchableNotIndexJump).isSet()) + notIndexJump = CodeLocationJump(patchBuffer.locationOf(patchableNotIndexJump)); + CodeLocationJump badTypeJump = CodeLocationJump(patchBuffer.locationOf(byValCompilationInfo.badTypeJump)); + CodeLocationLabel doneTarget = patchBuffer.locationOf(byValCompilationInfo.doneTarget); + CodeLocationLabel nextHotPathTarget = patchBuffer.locationOf(byValCompilationInfo.nextHotPathTarget); + CodeLocationLabel slowPathTarget = patchBuffer.locationOf(byValCompilationInfo.slowPathTarget); + CodeLocationCall returnAddress = patchBuffer.locationOf(byValCompilationInfo.returnAddress); + + *byValCompilationInfo.byValInfo = ByValInfo( + byValCompilationInfo.bytecodeIndex, + notIndexJump, + badTypeJump, + exceptionHandler, + byValCompilationInfo.arrayMode, + byValCompilationInfo.arrayProfile, + differenceBetweenCodePtr(badTypeJump, doneTarget), + differenceBetweenCodePtr(badTypeJump, nextHotPathTarget), + differenceBetweenCodePtr(returnAddress, slowPathTarget)); + } } + for (unsigned i = 0; i < m_callCompilationInfo.size(); ++i) { CallCompilationInfo& compilationInfo = m_callCompilationInfo[i]; CallLinkInfo& info = *compilationInfo.callLinkInfo; @@ -741,7 +755,8 @@ void JIT::privateCompileExceptionHandlers() jumpToExceptionHandler(); } - if (!m_exceptionChecks.empty()) { + if (!m_exceptionChecks.empty() || m_byValCompilationInfo.size()) { + m_exceptionHandler = label(); m_exceptionChecks.link(this); // lookupExceptionHandler is passed two arguments, the VM and the exec (the CallFrame*). diff --git a/webkit/JavaScriptCore/jit/JIT.h b/webkit/JavaScriptCore/jit/JIT.h index 2c433b871..45220235d 100755 --- a/webkit/JavaScriptCore/jit/JIT.h +++ b/webkit/JavaScriptCore/jit/JIT.h @@ -839,6 +839,7 @@ namespace JSC { JumpList m_exceptionChecks; JumpList m_exceptionChecksWithCallFrameRollback; + Label m_exceptionHandler; unsigned m_getByIdIndex; unsigned m_putByIdIndex; diff --git a/webkit/JavaScriptCore/jit/JITOperations.cpp b/webkit/JavaScriptCore/jit/JITOperations.cpp index e6e7de5f4..d7ef50b76 100755 --- a/webkit/JavaScriptCore/jit/JITOperations.cpp +++ b/webkit/JavaScriptCore/jit/JITOperations.cpp @@ -964,7 +964,7 @@ size_t JIT_OPERATION operationCompareStringEq(ExecState* exec, JSCell* left, JSC VM* vm = &exec->vm(); NativeCallFrameTracer tracer(vm, exec); - bool result = WTF::equal(*asString(left)->value(exec).impl(), *asString(right)->value(exec).impl()); + bool result = asString(left)->equal(exec, asString(right)); #if USE(JSVALUE64) return JSValue::encode(jsBoolean(result)); #else diff --git a/webkit/JavaScriptCore/llint/LowLevelInterpreter32_64.asm b/webkit/JavaScriptCore/llint/LowLevelInterpreter32_64.asm index 848ccdc94..b6cd708e5 100755 --- a/webkit/JavaScriptCore/llint/LowLevelInterpreter32_64.asm +++ b/webkit/JavaScriptCore/llint/LowLevelInterpreter32_64.asm @@ -2040,13 +2040,13 @@ macro nativeCallTrampoline(executableOffsetToFunction) error end - functionEpilogue() btinz VM::m_exception[t3], .handleException + + functionEpilogue() ret .handleException: storep cfr, VM::topCallFrame[t3] - restoreStackPointerAfterCall() jmp _llint_throw_from_slow_path_trampoline end diff --git a/webkit/JavaScriptCore/llint/LowLevelInterpreter64.asm b/webkit/JavaScriptCore/llint/LowLevelInterpreter64.asm index 5e0717517..841bc6f94 100755 --- a/webkit/JavaScriptCore/llint/LowLevelInterpreter64.asm +++ b/webkit/JavaScriptCore/llint/LowLevelInterpreter64.asm @@ -1913,14 +1913,13 @@ macro nativeCallTrampoline(executableOffsetToFunction) error end - functionEpilogue() - btqnz VM::m_exception[t3], .handleException + + functionEpilogue() ret .handleException: storep cfr, VM::topCallFrame[t3] - restoreStackPointerAfterCall() jmp _llint_throw_from_slow_path_trampoline end diff --git a/webkit/JavaScriptCore/offlineasm/arm.rb b/webkit/JavaScriptCore/offlineasm/arm.rb index 44cfbe5c9..457da4f93 100755 --- a/webkit/JavaScriptCore/offlineasm/arm.rb +++ b/webkit/JavaScriptCore/offlineasm/arm.rb @@ -66,6 +66,7 @@ def armOperand ARM_EXTRA_GPRS = [SpecialRegister.new("r6"), SpecialRegister.new("r10"), SpecialRegister.new("r12")] ARM_EXTRA_FPRS = [SpecialRegister.new("d7")] ARM_SCRATCH_FPR = SpecialRegister.new("d6") +OS_DARWIN = ((RUBY_PLATFORM =~ /darwin/i) != nil) def armMoveImmediate(value, register) # Currently we only handle the simple cases, and fall back to mov/movt for the complex ones. diff --git a/webkit/JavaScriptCore/runtime/ArrayPrototype.cpp b/webkit/JavaScriptCore/runtime/ArrayPrototype.cpp index edc0bc5ce..708a90b9c 100755 --- a/webkit/JavaScriptCore/runtime/ArrayPrototype.cpp +++ b/webkit/JavaScriptCore/runtime/ArrayPrototype.cpp @@ -842,20 +842,23 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncIndexOf(ExecState* exec) { // 15.4.4.14 JSObject* thisObj = exec->thisValue().toThis(exec, StrictMode).toObject(exec); + VM& vm = exec->vm(); unsigned length = getLength(exec, thisObj); - if (exec->hadException()) + if (UNLIKELY(vm.exception())) return JSValue::encode(jsUndefined()); unsigned index = argumentClampedIndexFromStartOrEnd(exec, 1, length); JSValue searchElement = exec->argument(0); for (; index < length; ++index) { JSValue e = getProperty(exec, thisObj, index); - if (exec->hadException()) + if (UNLIKELY(vm.exception())) return JSValue::encode(jsUndefined()); if (!e) continue; if (JSValue::strictEqual(exec, searchElement, e)) return JSValue::encode(jsNumber(index)); + if (UNLIKELY(vm.exception())) + return JSValue::encode(jsUndefined()); } return JSValue::encode(jsNumber(-1)); @@ -882,16 +885,19 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncLastIndexOf(ExecState* exec) index = static_cast(fromDouble); } + VM& vm = exec->vm(); JSValue searchElement = exec->argument(0); do { RELEASE_ASSERT(index < length); JSValue e = getProperty(exec, thisObj, index); - if (exec->hadException()) + if (UNLIKELY(vm.exception())) return JSValue::encode(jsUndefined()); if (!e) continue; if (JSValue::strictEqual(exec, searchElement, e)) return JSValue::encode(jsNumber(index)); + if (UNLIKELY(vm.exception())) + return JSValue::encode(jsUndefined()); } while (index--); return JSValue::encode(jsNumber(-1)); diff --git a/webkit/JavaScriptCore/runtime/ErrorPrototype.cpp b/webkit/JavaScriptCore/runtime/ErrorPrototype.cpp index c3c6420fa..38bd24c73 100755 --- a/webkit/JavaScriptCore/runtime/ErrorPrototype.cpp +++ b/webkit/JavaScriptCore/runtime/ErrorPrototype.cpp @@ -129,7 +129,7 @@ EncodedJSValue JSC_HOST_CALL errorProtoFuncToString(ExecState* exec) // 9. If msg is the empty String, return name. if (!messageString.length()) - return JSValue::encode(name.isString() ? name : jsNontrivialString(exec, nameString)); + return JSValue::encode(name.isString() ? name : jsString(exec, nameString)); // 10. Return the result of concatenating name, ":", a single space character, and msg. return JSValue::encode(jsMakeNontrivialString(exec, nameString, ": ", messageString)); diff --git a/webkit/JavaScriptCore/runtime/JSArray.cpp b/webkit/JavaScriptCore/runtime/JSArray.cpp index 72f87059a..168d3648e 100755 --- a/webkit/JavaScriptCore/runtime/JSArray.cpp +++ b/webkit/JavaScriptCore/runtime/JSArray.cpp @@ -398,7 +398,7 @@ bool JSArray::setLength(ExecState* exec, unsigned newLength, bool throwException if (newLength >= MIN_SPARSE_ARRAY_INDEX) { return setLengthWithArrayStorage( exec, newLength, throwException, - convertContiguousToArrayStorage(exec->vm())); + ensureArrayStorage(exec->vm())); } createInitialUndecided(exec->vm(), newLength); return true; diff --git a/webkit/JavaScriptCore/runtime/JSCJSValueInlines.h b/webkit/JavaScriptCore/runtime/JSCJSValueInlines.h index 1824a0f54..2b2cdab77 100755 --- a/webkit/JavaScriptCore/runtime/JSCJSValueInlines.h +++ b/webkit/JavaScriptCore/runtime/JSCJSValueInlines.h @@ -32,6 +32,7 @@ #include "JSCJSValue.h" #include "JSCellInlines.h" #include "JSFunction.h" +#include "JSStringInlines.h" #include namespace JSC { @@ -786,7 +787,7 @@ ALWAYS_INLINE bool JSValue::equalSlowCaseInline(ExecState* exec, JSValue v1, JSV bool s1 = v1.isString(); bool s2 = v2.isString(); if (s1 && s2) - return WTF::equal(*asString(v1)->value(exec).impl(), *asString(v2)->value(exec).impl()); + return asString(v1)->equal(exec, asString(v2)); if (v1.isUndefinedOrNull()) { if (v2.isUndefinedOrNull()) @@ -856,7 +857,7 @@ ALWAYS_INLINE bool JSValue::strictEqualSlowCaseInline(ExecState* exec, JSValue v ASSERT(v1.isCell() && v2.isCell()); if (v1.asCell()->isString() && v2.asCell()->isString()) - return WTF::equal(*asString(v1)->value(exec).impl(), *asString(v2)->value(exec).impl()); + return asString(v1)->equal(exec, asString(v2)); if (v1.asCell()->isSymbol() && v2.asCell()->isSymbol()) return asSymbol(v1)->privateName() == asSymbol(v2)->privateName(); diff --git a/webkit/JavaScriptCore/runtime/JSFunction.cpp b/webkit/JavaScriptCore/runtime/JSFunction.cpp index 1b8c407ec..1224a2b24 100755 --- a/webkit/JavaScriptCore/runtime/JSFunction.cpp +++ b/webkit/JavaScriptCore/runtime/JSFunction.cpp @@ -1,7 +1,7 @@ /* * Copyright (C) 1999-2002 Harri Porten (porten@kde.org) * Copyright (C) 2001 Peter Kelly (pmk@post.com) - * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2015 Apple Inc. All rights reserved. + * Copyright (C) 2003-2009, 2015-2017 Apple Inc. All rights reserved. * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca) * Copyright (C) 2007 Maks Orlovich * Copyright (C) 2015 Canon Inc. All rights reserved. @@ -327,13 +327,17 @@ EncodedJSValue JSFunction::callerGetter(ExecState* exec, JSObject* slotBase, Enc // See ES5.1 15.3.5.4 - Function.caller may not be used to retrieve a strict caller. if (!caller.isObject() || !asObject(caller)->inherits(JSFunction::info())) { - // It isn't a JSFunction, but if it is a JSCallee from a program or call eval, return null. - if (jsDynamicCast(caller)) + // It isn't a JSFunction, but if it is a JSCallee from a program or eval call or an internal constructor, return null. + if (jsDynamicCast(caller) || jsDynamicCast(caller)) return JSValue::encode(jsNull()); return JSValue::encode(caller); } JSFunction* function = jsCast(caller); - if (function->isHostOrBuiltinFunction() || !function->jsExecutable()->isStrictMode()) + + // Firefox returns null for native code callers, so we match that behavior. + if (function->isHostOrBuiltinFunction()) + return JSValue::encode(jsNull()); + if (!function->jsExecutable()->isStrictMode()) return JSValue::encode(caller); return JSValue::encode(throwTypeError(exec, ASCIILiteral("Function.caller used to retrieve strict caller"))); } diff --git a/webkit/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp b/webkit/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp index 8de527d69..4a19a66dc 100755 --- a/webkit/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp +++ b/webkit/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp @@ -53,6 +53,8 @@ using namespace Unicode; namespace JSC { +static const char* const ObjectProtoCalledOnNullOrUndefinedError = "Object.prototype.__proto__ called on null or undefined"; + template static Bitmap<256> makeCharacterBitmap(const char (&characters)[charactersCount]) { @@ -861,11 +863,11 @@ class GlobalFuncProtoGetterFunctor { EncodedJSValue JSC_HOST_CALL globalFuncProtoGetter(ExecState* exec) { - if (exec->thisValue().isUndefinedOrNull()) - return throwVMError(exec, createTypeError(exec, "Can't convert undefined or null to object")); - - JSObject* thisObject = jsDynamicCast(exec->thisValue().toThis(exec, NotStrictMode)); + JSValue thisValue = exec->thisValue().toThis(exec, StrictMode); + if (thisValue.isUndefinedOrNull()) + return throwVMTypeError(exec, ASCIILiteral(ObjectProtoCalledOnNullOrUndefinedError)); + JSObject* thisObject = jsDynamicCast(thisValue); if (!thisObject) return JSValue::encode(exec->thisValue().synthesizePrototype(exec)); @@ -911,12 +913,13 @@ bool checkProtoSetterAccessAllowed(ExecState* exec, JSObject* object) EncodedJSValue JSC_HOST_CALL globalFuncProtoSetter(ExecState* exec) { - if (exec->thisValue().isUndefinedOrNull()) - return throwVMError(exec, createTypeError(exec, "Can't convert undefined or null to object")); + JSValue thisValue = exec->thisValue().toThis(exec, StrictMode); + if (thisValue.isUndefinedOrNull()) + return throwVMTypeError(exec, ASCIILiteral(ObjectProtoCalledOnNullOrUndefinedError)); JSValue value = exec->argument(0); - JSObject* thisObject = jsDynamicCast(exec->thisValue().toThis(exec, NotStrictMode)); + JSObject* thisObject = jsDynamicCast(thisValue); // Setting __proto__ of a primitive should have no effect. if (!thisObject) diff --git a/webkit/JavaScriptCore/runtime/JSLock.cpp b/webkit/JavaScriptCore/runtime/JSLock.cpp index 499576b43..8c34c23a3 100755 --- a/webkit/JavaScriptCore/runtime/JSLock.cpp +++ b/webkit/JavaScriptCore/runtime/JSLock.cpp @@ -275,7 +275,6 @@ JSLock::DropAllLocks::DropAllLocks(VM* vm) { if (!m_vm) return; - wtfThreadData().resetCurrentAtomicStringTable(); RELEASE_ASSERT(!m_vm->apiLock().currentThreadIsHoldingLock() || !m_vm->isCollectorBusy()); m_droppedLockCount = m_vm->apiLock().dropAllLocks(this); } @@ -295,7 +294,6 @@ JSLock::DropAllLocks::~DropAllLocks() if (!m_vm) return; m_vm->apiLock().grabAllLocks(this, m_droppedLockCount); - wtfThreadData().setCurrentAtomicStringTable(m_vm->atomicStringTable()); } } // namespace JSC diff --git a/webkit/JavaScriptCore/runtime/JSString.cpp b/webkit/JavaScriptCore/runtime/JSString.cpp index eb046ed2d..c51979467 100755 --- a/webkit/JavaScriptCore/runtime/JSString.cpp +++ b/webkit/JavaScriptCore/runtime/JSString.cpp @@ -67,6 +67,15 @@ void JSString::dumpToStream(const JSCell* cell, PrintStream& out) out.printf(">"); } +bool JSString::equalSlowCase(ExecState* exec, JSString* other) const +{ + String str1 = value(exec); + String str2 = other->value(exec); + if (exec->hadException()) + return false; + return WTF::equal(*str1.impl(), *str2.impl()); +} + void JSString::visitChildren(JSCell* cell, SlotVisitor& visitor) { JSString* thisObject = jsCast(cell); diff --git a/webkit/JavaScriptCore/runtime/JSString.h b/webkit/JavaScriptCore/runtime/JSString.h index 068f52fbb..f688f4960 100755 --- a/webkit/JavaScriptCore/runtime/JSString.h +++ b/webkit/JavaScriptCore/runtime/JSString.h @@ -158,6 +158,7 @@ class JSString : public JSCell { SafeView view(ExecState*) const; StringViewWithUnderlyingString viewWithUnderlyingString(ExecState&) const; + inline bool equal(ExecState*, JSString* other) const; const String& value(ExecState*) const; const String& tryGetValue() const; const StringImpl* tryGetValueImpl() const; @@ -199,6 +200,7 @@ class JSString : public JSCell { protected: friend class JSValue; + JS_EXPORT_PRIVATE bool equalSlowCase(ExecState*, JSString* other) const; bool isRope() const { return m_value.isNull(); } bool isSubstring() const; bool is8Bit() const { return m_flags & Is8Bit; } diff --git a/webkit/JavaScriptCore/runtime/JSStringInlines.h b/webkit/JavaScriptCore/runtime/JSStringInlines.h new file mode 100755 index 000000000..bf21c4dba --- /dev/null +++ b/webkit/JavaScriptCore/runtime/JSStringInlines.h @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "JSString.h" + +namespace JSC { + +bool JSString::equal(ExecState* exec, JSString* other) const +{ + if (isRope() || other->isRope()) + return equalSlowCase(exec, other); + return WTF::equal(*m_value.impl(), *other->m_value.impl()); +} + +} // namespace JSC diff --git a/webkit/JavaScriptCore/runtime/Options.h b/webkit/JavaScriptCore/runtime/Options.h index fe78ac19a..ce7ba2e0d 100755 --- a/webkit/JavaScriptCore/runtime/Options.h +++ b/webkit/JavaScriptCore/runtime/Options.h @@ -135,6 +135,7 @@ typedef const char* optionString; v(bool, dumpGraphAfterParsing, false, nullptr) \ v(bool, dumpGraphAtEachPhase, false, nullptr) \ v(bool, verboseDFGByteCodeParsing, false, nullptr) \ + v(bool, safepointBeforeEachPhase, true, nullptr) \ v(bool, verboseCompilation, false, nullptr) \ v(bool, verboseFTLCompilation, false, nullptr) \ v(bool, logCompilationChanges, false, nullptr) \ @@ -321,6 +322,8 @@ typedef const char* optionString; \ v(bool, enableDollarVM, false, "installs the $vm debugging tool in global objects") \ v(optionString, functionOverrides, nullptr, "file with debugging overrides for function bodies") \ + \ + v(bool, useConcurrentGCSplitTesting, false, "If true, A/B split testing will be performed on the concurrent GC, yielding a 50% chance that concurrent GC is disabled.") \ class Options { public: diff --git a/webkit/JavaScriptCore/runtime/ScopedArguments.h b/webkit/JavaScriptCore/runtime/ScopedArguments.h index 8d36a1bab..5e2df3cc9 100755 --- a/webkit/JavaScriptCore/runtime/ScopedArguments.h +++ b/webkit/JavaScriptCore/runtime/ScopedArguments.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 Apple Inc. All rights reserved. + * Copyright (C) 2015-2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -100,7 +100,7 @@ class ScopedArguments : public GenericArguments { ASSERT_WITH_SECURITY_IMPLICATION(canAccessIndexQuickly(i)); unsigned namedLength = m_table->length(); if (i < namedLength) - m_scope->variableAt(m_table->get(i)).set(vm, this, value); + m_scope->variableAt(m_table->get(i)).set(vm, m_scope.get(), value); else overflowStorage()[i - namedLength].set(vm, this, value); } diff --git a/webkit/JavaScriptCore/runtime/SparseArrayValueMap.cpp b/webkit/JavaScriptCore/runtime/SparseArrayValueMap.cpp index bc88ad038..e3f984faf 100755 --- a/webkit/JavaScriptCore/runtime/SparseArrayValueMap.cpp +++ b/webkit/JavaScriptCore/runtime/SparseArrayValueMap.cpp @@ -123,6 +123,9 @@ bool SparseArrayValueMap::putDirect(ExecState* exec, JSObject* array, unsigned i return reject(exec, mode == PutDirectIndexShouldThrow, "Attempting to define property on object that is not extensible."); } + if (entry.attributes & ReadOnly) + return reject(exec, mode == PutDirectIndexShouldThrow, StrictModeReadonlyPropertyWriteError); + entry.attributes = attributes; entry.set(exec->vm(), this, value); return true; diff --git a/webkit/JavaScriptCore/runtime/VM.cpp b/webkit/JavaScriptCore/runtime/VM.cpp index ac8c5cc3d..6ccdbf446 100755 --- a/webkit/JavaScriptCore/runtime/VM.cpp +++ b/webkit/JavaScriptCore/runtime/VM.cpp @@ -552,7 +552,12 @@ void VM::releaseExecutableMemory() void VM::throwException(ExecState* exec, Exception* exception) { if (Options::breakOnThrow()) { - dataLog("In call frame ", RawPointer(exec), " for code block ", *exec->codeBlock(), "\n"); + CodeBlock* codeBlock = exec->codeBlock(); + dataLog("Throwing exception in call frame ", RawPointer(exec), " for code block "); + if (codeBlock) + dataLog(*codeBlock, "\n"); + else + dataLog("\n"); CRASH(); } diff --git a/webkit/JavaScriptCore/tests/stress/array-setLength-on-ArrayClass-with-large-length.js b/webkit/JavaScriptCore/tests/stress/array-setLength-on-ArrayClass-with-large-length.js new file mode 100755 index 000000000..c534a3a7a --- /dev/null +++ b/webkit/JavaScriptCore/tests/stress/array-setLength-on-ArrayClass-with-large-length.js @@ -0,0 +1,19 @@ +//@ runDefault +// This test should not crash + +function assertEqual(actual, expected) { + function toString(x) { + return '' + x; + } + if (typeof actual != typeof expected) + throw Error("Failed: typeof expected: '" + typeof(expected) + "', typeof actual: '" + typeof(actual) + "'");; + + if (toString(actual) != toString(expected)) + throw Error("Failed: expected: '" + toString(expected) + "', actual: '" + toString(actual) + "'");; +} + +assertEqual(Array.prototype.length, 0); + +Array.prototype.length = 0x40000000; + +assertEqual(Array.prototype.length, 0x40000000); diff --git a/webkit/JavaScriptCore/tests/stress/array-setLength-on-ArrayClass-with-small-length.js b/webkit/JavaScriptCore/tests/stress/array-setLength-on-ArrayClass-with-small-length.js new file mode 100755 index 000000000..5ac4c8c31 --- /dev/null +++ b/webkit/JavaScriptCore/tests/stress/array-setLength-on-ArrayClass-with-small-length.js @@ -0,0 +1,19 @@ +//@ runDefault +// This test should not crash + +function assertEqual(actual, expected) { + function toString(x) { + return '' + x; + } + if (typeof actual != typeof expected) + throw Error("Failed: typeof expected: '" + typeof(expected) + "', typeof actual: '" + typeof(actual) + "'");; + + if (toString(actual) != toString(expected)) + throw Error("Failed: expected: '" + toString(expected) + "', actual: '" + toString(actual) + "'");; +} + +assertEqual(Array.prototype.length, 0); + +Array.prototype.length = 5; + +assertEqual(Array.prototype.length, 5); diff --git a/webkit/JavaScriptCore/tests/stress/concat-append-one-with-sparse-array.js b/webkit/JavaScriptCore/tests/stress/concat-append-one-with-sparse-array.js new file mode 100755 index 000000000..2451330fa --- /dev/null +++ b/webkit/JavaScriptCore/tests/stress/concat-append-one-with-sparse-array.js @@ -0,0 +1,6 @@ +//@ skip + +let length = 0x10001000; + +let foo = new Array(length); +foo.concat(1); diff --git a/webkit/JavaScriptCore/tests/stress/errors-with-simple-names-or-messages-should-not-crash-toString.js b/webkit/JavaScriptCore/tests/stress/errors-with-simple-names-or-messages-should-not-crash-toString.js new file mode 100755 index 000000000..b0f912bd5 --- /dev/null +++ b/webkit/JavaScriptCore/tests/stress/errors-with-simple-names-or-messages-should-not-crash-toString.js @@ -0,0 +1,12 @@ +//@ runDefault +// This test should not crash. + +Error.prototype.name = 0 +Error().toString(); +Error("1").toString(); +Error(0).toString(); + +Error.prototype.name = "" +Error().toString(); +Error("1").toString(); +Error(0).toString(); diff --git a/webkit/JavaScriptCore/tests/stress/string-joining-long-strings-should-not-crash.js b/webkit/JavaScriptCore/tests/stress/string-joining-long-strings-should-not-crash.js new file mode 100755 index 000000000..62afaed84 --- /dev/null +++ b/webkit/JavaScriptCore/tests/stress/string-joining-long-strings-should-not-crash.js @@ -0,0 +1,15 @@ +//@ runDefault +// This test should not crash. + +var error; +let str = ''; +let arr = [{}, 2, 3]; +try { + for (let z = 0; z < 30; z++) + str = arr.join(str); // exponentially grow length of string. +} catch(e) { + error = e; +} + +if (!error) + throw Error("Failed"); diff --git a/webkit/WTF/ChangeLog b/webkit/WTF/ChangeLog index eec5cf10f..ad520ce8b 100755 --- a/webkit/WTF/ChangeLog +++ b/webkit/WTF/ChangeLog @@ -1,3 +1,176 @@ +2017-04-07 Ting-Wei Lan + + Include cstdio before using sscanf and stderr + https://bugs.webkit.org/show_bug.cgi?id=170098 + + Reviewed by Michael Catanzaro. + + * wtf/NumberOfCores.cpp: + +2017-03-22 Jason Marcell + + Merge r214125. rdar://problem/30921831 + + 2017-03-17 Said Abou-Hallawa + + Time channel attack on SVG Filters + https://bugs.webkit.org/show_bug.cgi?id=118689 + + Reviewed by Simon Fraser. + + Performing arithmetic operations on subnormal floating-point numbers is + very expensive. Normalizing the floating-point number to the minimum normal + value should accelerate the calculations and there won't be a noticeable + difference in the result since all the subnormal values and the minimum + normal value are all very close to zero. + + * wtf/MathExtras.h: + (normalizedFloat): + +2017-02-05 Matthew Hanson + + Merge r211482. rdar://problem/29711409 + + 2017-02-01 Andreas Kling + + Implement the alwaysRunsAtBackgroundPriority WK2 setting using thread QoS. + + + + Reviewed by Antti Koivisto. + + Add a new mechanism for overriding the max thread QoS level globally: + + void setGlobalMaxQOSClass(qos_class_t) + qos_class_t adjustedQOSClass(qos_class_t) + + The QoS cap applies to all newly created threads, threads that try to override + their QoS class manually, and also passed down to bmalloc. + + * wtf/Threading.cpp: + (WTF::setCurrentThreadIsUserInteractive): + (WTF::setCurrentThreadIsUserInitiated): + (WTF::setGlobalMaxQOSClass): + (WTF::adjustedQOSClass): + * wtf/Threading.h: + * wtf/ThreadingPthreads.cpp: + (WTF::createThreadInternal): + * wtf/cocoa/WorkQueueCocoa.cpp: + (WTF::dispatchQOSClass): + +2017-01-26 Matthew Hanson + + Merge r211168. rdar://problem/30154148 + + 2017-01-25 Chris Dumez + + Disable Download attribute support on iOS + https://bugs.webkit.org/show_bug.cgi?id=167337 + + + Reviewed by Alexey Proskuryakov. + + Disable Download attribute support on iOS as it currently does not work. + + * wtf/FeatureDefines.h: + +2016-09-16 Babak Shafiei + + Merge r204916. rdar://problem/27991573 + + 2016-08-23 Anders Carlsson + + Add enum traits and use them in the IPC::Decoder + https://bugs.webkit.org/show_bug.cgi?id=161103 + + Reviewed by Sam Weinig. + + Add EnumTraits.h which provides a forward declaration for WTF::EnumTraits as well as + the WTF::isValidEnum function. + + * WTF.xcodeproj/project.pbxproj: + * wtf/EnumTraits.h: Added. + +2016-09-13 Babak Shafiei + + Merge r205895. rdar://problem/28287070 + + 2016-09-13 Michael Saboff + + Promises aren't resolved properly when making a ObjC API callback + https://bugs.webkit.org/show_bug.cgi?id=161929 + + Reviewed by Geoffrey Garen. + + Removed resetCurrentAtomicStringTable() which is no longer referenced. + + * wtf/WTFThreadData.h: + (WTF::WTFThreadData::resetCurrentAtomicStringTable): Deleted. + +2016-09-09 Babak Shafiei + + Merge r203381. rdar://problem/27860536 + + 2016-07-18 Anders Carlsson + + WebKit nightly fails to build on macOS Sierra + https://bugs.webkit.org/show_bug.cgi?id=159902 + rdar://problem/27365672 + + Reviewed by Tim Horton. + + * icu/unicode/ucurr.h: Added. + Add ucurr.h from ICU. + +2016-08-30 Babak Shafiei + + Merge r203834. rdar://problem/27991582 + + 2016-07-28 Mark Lam + + StringView should have an explicit m_is8Bit field. + https://bugs.webkit.org/show_bug.cgi?id=160282 + + + Reviewed by Benjamin Poulain. + + The current implementation reserves 1 bit in the 32-bit m_length field as an + is16Bit flag. As a result, a StringView is incapable of handling strings that + have a length of 32-bit in size. This results in a mismatch with the + expectations of String, StringImpl, and JavaScriptCore's JSString which all + support a 32-bit unsigned length. + + This patch fixes this issue by introducing an explicit m_is8Bit field, thereby + allowing m_length to be a full 32-bit again. + + We also introduced a clear() convenience method to set the fields of StringView + to empty values. Previously, we were duplicating the code for clearing those + fields. We now call clear() in all those places instead. + + Note: in clear(), we set m_is8Bit to true because we want an empty StringView + to be 8-bit rather than 16-bit. This is consistent with what the empty() method + returns. + + * wtf/text/StringView.h: + (WTF::StringView::setUnderlyingString): + (WTF::StringView::StringView): + (WTF::StringView::operator=): + (WTF::StringView::initialize): + (WTF::StringView::clear): + (WTF::StringView::empty): + (WTF::StringView::length): + (WTF::StringView::operator bool): + (WTF::StringView::is8Bit): + (WTF::StringView::substring): + (WTF::StringView::getCharactersWithUpconvert): + (WTF::StringView::toString): + (WTF::StringView::toAtomicString): + (WTF::StringView::toFloat): + (WTF::StringView::toInt): + (WTF::StringView::toIntStrict): + (WTF::StringView::toStringWithoutCopying): + (WTF::StringView::find): + 2016-02-26 Tim Horton Fix the Mavericks build. @@ -199,7 +372,7 @@ Re-enable WebGL on WinCairo https://bugs.webkit.org/show_bug.cgi?id=146537 - Reviewed by Csaba Osztrogon@c. + Reviewed by Csaba Osztrogon�@c. * wtf/FeatureDefines.h: Enable WebGL on WinCairo again. @@ -343,7 +516,7 @@ [WTF] Platform.h: use _ABI64 instead of _MIPS_SIM_ABI64 to determine MIPS N64 https://bugs.webkit.org/show_bug.cgi?id=145113 - Reviewed by Csaba Osztrogon@c. + Reviewed by Csaba Osztrogon�@c. * wtf/Platform.h: @@ -461,7 +634,7 @@ (WTF::Checked::operator UnspecifiedBoolType*): Deleted. -2015-06-19 Csaba Osztrogon@c +2015-06-19 Csaba Osztrogon�@c [WK2] Fix unused-private-field warning in WebProcess/Plugins/PluginView. https://bugs.webkit.org/show_bug.cgi?id=145252 @@ -747,7 +920,7 @@ * wtf/TinyPtrSet.h: (WTF::TinyPtrSet::iterator::operator*): s/at(index)/at(m_index)/ -2015-06-09 Csaba Osztrogon@c +2015-06-09 Csaba Osztrogon�@c [cmake] Fix the style issues in cmake project files https://bugs.webkit.org/show_bug.cgi?id=145755 @@ -1073,7 +1246,7 @@ [GTK] Move MainThreadGtk, RunLoopGtk, WorkQueueGtk under Source/WTF/wtf/glib/ https://bugs.webkit.org/show_bug.cgi?id=145117 - Reviewed by Csaba Osztrogon@c. + Reviewed by Csaba Osztrogon�@c. Move the MainThreadGtk, RunLoopGtk and WorkQueueGtk implementation files from Source/WTF/wtf/gtk/ to Source/WTF/wtf/glib/. These implementations are not @@ -1264,7 +1437,7 @@ [EFL] Remove unnecessary PLATFORM(EFL) macro in EFL specific files https://bugs.webkit.org/show_bug.cgi?id=145160 - Reviewed by Csaba Osztrogon@c. + Reviewed by Csaba Osztrogon�@c. * wtf/efl/EflTypedefs.h: Remove PLATFORM(EFL). * wtf/efl/UniquePtrEfl.h: ditto. @@ -1365,7 +1538,7 @@ * wtf/text/WTFString.h: (WTF::equalIgnoringASCIICase): Delegate to StringImpl's implementation. -2015-05-14 \an Dober@ek +2015-05-14 �\an Dober�@ek [GTK] RunLoop constructor should properly retrieve or establish the thread-default GMainContext https://bugs.webkit.org/show_bug.cgi?id=144732 @@ -1470,7 +1643,7 @@ [GTK] WorkQueue objects are not released https://bugs.webkit.org/show_bug.cgi?id=144824 - Reviewed by \an Dober@ek. + Reviewed by �\an Dober�@ek. Do not keep a reference of the WorkQueue for the entire life of its worker thread, since every task scheduled on the WorkQueue @@ -2209,7 +2382,7 @@ * config.h: -2015-04-15 ЄIwq|pr +2015-04-15 ЄI�w�q���|�p�����r Harmonize binary semaphore ifdefs @@ -5239,7 +5412,7 @@ Unreviewed, revert r176293 & r176275 changing the Vector API to use unsigned type instead of size_t. There is some disagreement regarding the long-term direction - of the API and we shouldnft leave the API partly transitioned to unsigned type + of the API and we shouldn�ft leave the API partly transitioned to unsigned type while making a decision. * wtf/Forward.h: @@ -6189,7 +6362,7 @@ 2014-10-18 Dan Bernstein - WorkQueue dispatches functions but isnft a FunctionDispatcher + WorkQueue dispatches functions but isn�ft a FunctionDispatcher https://bugs.webkit.org/show_bug.cgi?id=137853 Reviewed by Anders Carlsson. @@ -7462,7 +7635,7 @@ Reviewed by Tim Horton. - * wtf/Platform.h: Moved the definition of HAVE_VOUCHERS from WebKit2fs config.h here. + * wtf/Platform.h: Moved the definition of HAVE_VOUCHERS from WebKit2�fs config.h here. 2014-09-08 Tim Horton @@ -8954,7 +9127,7 @@ 2014-06-17 Dan Bernstein - String::isolatedCopy doesnft return an isolated copy when used on an rvalue reference + String::isolatedCopy doesn�ft return an isolated copy when used on an rvalue reference https://bugs.webkit.org/show_bug.cgi?id=133968 Reviewed by Anders Carlsson. @@ -11451,7 +11624,7 @@ Stop using String::deprecatedCharacters to call WTF::Collator https://bugs.webkit.org/show_bug.cgi?id=128517 - WTF passes ICUfs deprecated ULOC_REQUESTED_LOCALE to ucol_getLocaleByType() + WTF passes ICU�fs deprecated ULOC_REQUESTED_LOCALE to ucol_getLocaleByType() rdar://problem/15183390 Reviewed by Alexey Proskuryakov. @@ -11910,12 +12083,12 @@ 2014-02-02 Dan Bernstein - Stop using PLATFORM(MAC) in WTF except where it means gOS X but not iOSh + Stop using PLATFORM(MAC) in WTF except where it means �gOS X but not iOS�h https://bugs.webkit.org/show_bug.cgi?id=128089 Reviewed by Darin Adler. - Replaced all uses of PLATFORM(MAC) that werenft accompanied by !PLATFORM(IOS) with + Replaced all uses of PLATFORM(MAC) that weren�ft accompanied by !PLATFORM(IOS) with equivalent(*) tests that are more idiomatic and will not change once PLATFORM(MAC) changes to be false when building for iOS. diff --git a/webkit/WTF/WTF.xcodeproj/project.pbxproj b/webkit/WTF/WTF.xcodeproj/project.pbxproj index 4269944dc..8804a0240 100755 --- a/webkit/WTF/WTF.xcodeproj/project.pbxproj +++ b/webkit/WTF/WTF.xcodeproj/project.pbxproj @@ -63,6 +63,7 @@ 1A6BB769162F300500DD16DB /* StreamBuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A6BB768162F300500DD16DB /* StreamBuffer.h */; }; 1A6EB1E0187D0BD30030126F /* StringView.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A6EB1DF187D0BD30030126F /* StringView.h */; }; 1ACADD841884480100D8B71D /* DeprecatedSymbolsUsedBySafari.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1ACADD821884480100D8B71D /* DeprecatedSymbolsUsedBySafari.mm */; }; + 1AEA88E21D6BBCF400E5AD64 /* EnumTraits.h in Headers */ = {isa = PBXBuildFile; fileRef = 1AEA88E11D6BBCF400E5AD64 /* EnumTraits.h */; }; 1AFDE648195201C300C48FFA /* TypeCastsCF.h in Headers */ = {isa = PBXBuildFile; fileRef = 1AFDE647195201C300C48FFA /* TypeCastsCF.h */; }; 1AFDE6531953B23D00C48FFA /* Optional.h in Headers */ = {isa = PBXBuildFile; fileRef = 1AFDE6521953B23D00C48FFA /* Optional.h */; }; 1FA47C8A152502DA00568D1B /* WebCoreThread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1FA47C88152502DA00568D1B /* WebCoreThread.cpp */; }; @@ -348,6 +349,7 @@ 1A6BB768162F300500DD16DB /* StreamBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StreamBuffer.h; sourceTree = ""; }; 1A6EB1DF187D0BD30030126F /* StringView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StringView.h; sourceTree = ""; }; 1ACADD821884480100D8B71D /* DeprecatedSymbolsUsedBySafari.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = DeprecatedSymbolsUsedBySafari.mm; sourceTree = ""; }; + 1AEA88E11D6BBCF400E5AD64 /* EnumTraits.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EnumTraits.h; sourceTree = ""; }; 1AFDE647195201C300C48FFA /* TypeCastsCF.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TypeCastsCF.h; sourceTree = ""; }; 1AFDE6521953B23D00C48FFA /* Optional.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Optional.h; sourceTree = ""; }; 1FA47C88152502DA00568D1B /* WebCoreThread.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebCoreThread.cpp; sourceTree = ""; }; @@ -740,6 +742,7 @@ A8A47280151A825A004123FF /* DoublyLinkedList.h */, A8A47297151A825A004123FF /* dtoa.cpp */, A8A47298151A825A004123FF /* dtoa.h */, + 1AEA88E11D6BBCF400E5AD64 /* EnumTraits.h */, A8A4729F151A825A004123FF /* ExportMacros.h */, 0F885E0E1845AE9F00F1E3FA /* FastBitVector.cpp */, 0FD81AC4154FB22E00983E72 /* FastBitVector.h */, @@ -1188,6 +1191,7 @@ FE8225311B2A1E5B00BA68FD /* NakedPtr.h in Headers */, A748745417A0BDAE00FA04CB /* StringHashDumpContext.h in Headers */, A8A4742D151A825B004123FF /* StringHasher.h in Headers */, + 1AEA88E21D6BBCF400E5AD64 /* EnumTraits.h in Headers */, A8A47441151A825B004123FF /* StringImpl.h in Headers */, A8A47442151A825B004123FF /* StringOperators.h in Headers */, 0FDDBFA81666DFA300C55FEF /* StringPrintStream.h in Headers */, diff --git a/webkit/WTF/icu/unicode/ucurr.h b/webkit/WTF/icu/unicode/ucurr.h new file mode 100755 index 000000000..27698133e --- /dev/null +++ b/webkit/WTF/icu/unicode/ucurr.h @@ -0,0 +1,360 @@ +/* +********************************************************************** +* Copyright (c) 2002-2013, International Business Machines +* Corporation and others. All Rights Reserved. +********************************************************************** +*/ +#ifndef _UCURR_H_ +#define _UCURR_H_ + +#include "unicode/utypes.h" +#include "unicode/uenum.h" + +/** + * \file + * \brief C API: Encapsulates information about a currency. + */ + +#if !UCONFIG_NO_FORMATTING + +/** + * The ucurr API encapsulates information about a currency, as defined by + * ISO 4217. A currency is represented by a 3-character string + * containing its ISO 4217 code. This API can return various data + * necessary the proper display of a currency: + * + *

  • A display symbol, for a specific locale + *
  • The number of fraction digits to display + *
  • A rounding increment + *
+ * + * The DecimalFormat class uses these data to display + * currencies. + * @author Alan Liu + * @since ICU 2.2 + */ + +/** + * Finds a currency code for the given locale. + * @param locale the locale for which to retrieve a currency code. + * Currency can be specified by the "currency" keyword + * in which case it overrides the default currency code + * @param buff fill in buffer. Can be NULL for preflighting. + * @param buffCapacity capacity of the fill in buffer. Can be 0 for + * preflighting. If it is non-zero, the buff parameter + * must not be NULL. + * @param ec error code + * @return length of the currency string. It should always be 3. If 0, + * currency couldn't be found or the input values are + * invalid. + * @stable ICU 2.8 + */ +U_STABLE int32_t U_EXPORT2 +ucurr_forLocale(const char* locale, + UChar* buff, + int32_t buffCapacity, + UErrorCode* ec); + +/** + * Selector constants for ucurr_getName(). + * + * @see ucurr_getName + * @stable ICU 2.6 + */ +typedef enum UCurrNameStyle { + /** + * Selector for ucurr_getName indicating a symbolic name for a + * currency, such as "$" for USD. + * @stable ICU 2.6 + */ + UCURR_SYMBOL_NAME, + + /** + * Selector for ucurr_getName indicating the long name for a + * currency, such as "US Dollar" for USD. + * @stable ICU 2.6 + */ + UCURR_LONG_NAME +} UCurrNameStyle; + +#if !UCONFIG_NO_SERVICE +/** + * @stable ICU 2.6 + */ +typedef const void* UCurrRegistryKey; + +/** + * Register an (existing) ISO 4217 currency code for the given locale. + * Only the country code and the two variants EURO and PRE_EURO are + * recognized. + * @param isoCode the three-letter ISO 4217 currency code + * @param locale the locale for which to register this currency code + * @param status the in/out status code + * @return a registry key that can be used to unregister this currency code, or NULL + * if there was an error. + * @stable ICU 2.6 + */ +U_STABLE UCurrRegistryKey U_EXPORT2 +ucurr_register(const UChar* isoCode, + const char* locale, + UErrorCode* status); +/** + * Unregister the previously-registered currency definitions using the + * URegistryKey returned from ucurr_register. Key becomes invalid after + * a successful call and should not be used again. Any currency + * that might have been hidden by the original ucurr_register call is + * restored. + * @param key the registry key returned by a previous call to ucurr_register + * @param status the in/out status code, no special meanings are assigned + * @return TRUE if the currency for this key was successfully unregistered + * @stable ICU 2.6 + */ +U_STABLE UBool U_EXPORT2 +ucurr_unregister(UCurrRegistryKey key, UErrorCode* status); +#endif /* UCONFIG_NO_SERVICE */ + +/** + * Returns the display name for the given currency in the + * given locale. For example, the display name for the USD + * currency object in the en_US locale is "$". + * @param currency null-terminated 3-letter ISO 4217 code + * @param locale locale in which to display currency + * @param nameStyle selector for which kind of name to return + * @param isChoiceFormat fill-in set to TRUE if the returned value + * is a ChoiceFormat pattern; otherwise it is a static string + * @param len fill-in parameter to receive length of result + * @param ec error code + * @return pointer to display string of 'len' UChars. If the resource + * data contains no entry for 'currency', then 'currency' itself is + * returned. If *isChoiceFormat is TRUE, then the result is a + * ChoiceFormat pattern. Otherwise it is a static string. + * @stable ICU 2.6 + */ +U_STABLE const UChar* U_EXPORT2 +ucurr_getName(const UChar* currency, + const char* locale, + UCurrNameStyle nameStyle, + UBool* isChoiceFormat, + int32_t* len, + UErrorCode* ec); + +/** + * Returns the plural name for the given currency in the + * given locale. For example, the plural name for the USD + * currency object in the en_US locale is "US dollar" or "US dollars". + * @param currency null-terminated 3-letter ISO 4217 code + * @param locale locale in which to display currency + * @param isChoiceFormat fill-in set to TRUE if the returned value + * is a ChoiceFormat pattern; otherwise it is a static string + * @param pluralCount plural count + * @param len fill-in parameter to receive length of result + * @param ec error code + * @return pointer to display string of 'len' UChars. If the resource + * data contains no entry for 'currency', then 'currency' itself is + * returned. + * @stable ICU 4.2 + */ +U_STABLE const UChar* U_EXPORT2 +ucurr_getPluralName(const UChar* currency, + const char* locale, + UBool* isChoiceFormat, + const char* pluralCount, + int32_t* len, + UErrorCode* ec); + +/** + * Returns the number of the number of fraction digits that should + * be displayed for the given currency. + * @param currency null-terminated 3-letter ISO 4217 code + * @param ec input-output error code + * @return a non-negative number of fraction digits to be + * displayed, or 0 if there is an error + * @stable ICU 3.0 + */ +U_STABLE int32_t U_EXPORT2 +ucurr_getDefaultFractionDigits(const UChar* currency, + UErrorCode* ec); + +/** + * Returns the rounding increment for the given currency, or 0.0 if no + * rounding is done by the currency. + * @param currency null-terminated 3-letter ISO 4217 code + * @param ec input-output error code + * @return the non-negative rounding increment, or 0.0 if none, + * or 0.0 if there is an error + * @stable ICU 3.0 + */ +U_STABLE double U_EXPORT2 +ucurr_getRoundingIncrement(const UChar* currency, + UErrorCode* ec); + +/** + * Selector constants for ucurr_openCurrencies(). + * + * @see ucurr_openCurrencies + * @stable ICU 3.2 + */ +typedef enum UCurrCurrencyType { + /** + * Select all ISO-4217 currency codes. + * @stable ICU 3.2 + */ + UCURR_ALL = INT32_MAX, + /** + * Select only ISO-4217 commonly used currency codes. + * These currencies can be found in common use, and they usually have + * bank notes or coins associated with the currency code. + * This does not include fund codes, precious metals and other + * various ISO-4217 codes limited to special financial products. + * @stable ICU 3.2 + */ + UCURR_COMMON = 1, + /** + * Select ISO-4217 uncommon currency codes. + * These codes respresent fund codes, precious metals and other + * various ISO-4217 codes limited to special financial products. + * A fund code is a monetary resource associated with a currency. + * @stable ICU 3.2 + */ + UCURR_UNCOMMON = 2, + /** + * Select only deprecated ISO-4217 codes. + * These codes are no longer in general public use. + * @stable ICU 3.2 + */ + UCURR_DEPRECATED = 4, + /** + * Select only non-deprecated ISO-4217 codes. + * These codes are in general public use. + * @stable ICU 3.2 + */ + UCURR_NON_DEPRECATED = 8 +} UCurrCurrencyType; + +/** + * Provides a UEnumeration object for listing ISO-4217 codes. + * @param currType You can use one of several UCurrCurrencyType values for this + * variable. You can also | (or) them together to get a specific list of + * currencies. Most people will want to use the (UCURR_CURRENCY|UCURR_NON_DEPRECATED) value to + * get a list of current currencies. + * @param pErrorCode Error code + * @stable ICU 3.2 + */ +U_STABLE UEnumeration * U_EXPORT2 +ucurr_openISOCurrencies(uint32_t currType, UErrorCode *pErrorCode); + +/** + * Queries if the given ISO 4217 3-letter code is available on the specified date range. + * + * Note: For checking availability of a currency on a specific date, specify the date on both 'from' and 'to' + * + * When 'from' is U_DATE_MIN and 'to' is U_DATE_MAX, this method checks if the specified currency is available any time. + * If 'from' and 'to' are same UDate value, this method checks if the specified currency is available on that date. + * + * @param isoCode + * The ISO 4217 3-letter code. + * + * @param from + * The lower bound of the date range, inclusive. When 'from' is U_DATE_MIN, check the availability + * of the currency any date before 'to' + * + * @param to + * The upper bound of the date range, inclusive. When 'to' is U_DATE_MAX, check the availability of + * the currency any date after 'from' + * + * @param errorCode + * ICU error code + * + * @return TRUE if the given ISO 4217 3-letter code is supported on the specified date range. + * + * @stable ICU 4.8 + */ +U_STABLE UBool U_EXPORT2 +ucurr_isAvailable(const UChar* isoCode, + UDate from, + UDate to, + UErrorCode* errorCode); + +/** + * Finds the number of valid currency codes for the + * given locale and date. + * @param locale the locale for which to retrieve the + * currency count. + * @param date the date for which to retrieve the + * currency count for the given locale. + * @param ec error code + * @return the number of currency codes for the + * given locale and date. If 0, currency + * codes couldn't be found for the input + * values are invalid. + * @stable ICU 4.0 + */ +U_STABLE int32_t U_EXPORT2 +ucurr_countCurrencies(const char* locale, + UDate date, + UErrorCode* ec); + +/** + * Finds a currency code for the given locale and date + * @param locale the locale for which to retrieve a currency code. + * Currency can be specified by the "currency" keyword + * in which case it overrides the default currency code + * @param date the date for which to retrieve a currency code for + * the given locale. + * @param index the index within the available list of currency codes + * for the given locale on the given date. + * @param buff fill in buffer. Can be NULL for preflighting. + * @param buffCapacity capacity of the fill in buffer. Can be 0 for + * preflighting. If it is non-zero, the buff parameter + * must not be NULL. + * @param ec error code + * @return length of the currency string. It should always be 3. + * If 0, currency couldn't be found or the input values are + * invalid. + * @stable ICU 4.0 + */ +U_STABLE int32_t U_EXPORT2 +ucurr_forLocaleAndDate(const char* locale, + UDate date, + int32_t index, + UChar* buff, + int32_t buffCapacity, + UErrorCode* ec); + +/** + * Given a key and a locale, returns an array of string values in a preferred + * order that would make a difference. These are all and only those values where + * the open (creation) of the service with the locale formed from the input locale + * plus input keyword and that value has different behavior than creation with the + * input locale alone. + * @param key one of the keys supported by this service. For now, only + * "currency" is supported. + * @param locale the locale + * @param commonlyUsed if set to true it will return only commonly used values + * with the given locale in preferred order. Otherwise, + * it will return all the available values for the locale. + * @param status error status + * @return a string enumeration over keyword values for the given key and the locale. + * @stable ICU 4.2 + */ +U_STABLE UEnumeration* U_EXPORT2 +ucurr_getKeywordValuesForLocale(const char* key, + const char* locale, + UBool commonlyUsed, + UErrorCode* status); + +/** + * Returns the ISO 4217 numeric code for the currency. + *

Note: If the ISO 4217 numeric code is not assigned for the currency or + * the currency is unknown, this function returns 0. + * + * @param currency null-terminated 3-letter ISO 4217 code + * @return The ISO 4217 numeric code of the currency + * @stable ICU 49 + */ +U_STABLE int32_t U_EXPORT2 +ucurr_getNumericCode(const UChar* currency); + +#endif /* #if !UCONFIG_NO_FORMATTING */ + +#endif diff --git a/webkit/WTF/wtf/EnumTraits.h b/webkit/WTF/wtf/EnumTraits.h new file mode 100755 index 000000000..09295eea4 --- /dev/null +++ b/webkit/WTF/wtf/EnumTraits.h @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include + +namespace WTF { + +template struct EnumTraits; + +template struct EnumValues; + +template struct EnumValueChecker; + +template +struct EnumValueChecker> { + static constexpr bool isValidEnum(T t) + { + if (static_cast(e) == t) + return true; + + return EnumValueChecker>::isValidEnum(t); + } +}; + +template +struct EnumValueChecker> { + static constexpr bool isValidEnum(T t) + { + return false; + } +}; + +template +constexpr auto isValidEnum(T t) -> std::enable_if_t::value, bool> +{ + static_assert(sizeof(T) >= std::underlying_type_t(), "Integral type must be at least the size of the underlying enum type"); + + return EnumValueChecker::values>::isValidEnum(t); +} + +} + +using WTF::isValidEnum; diff --git a/webkit/WTF/wtf/FeatureDefines.h b/webkit/WTF/wtf/FeatureDefines.h index 7d460d141..036090aa1 100755 --- a/webkit/WTF/wtf/FeatureDefines.h +++ b/webkit/WTF/wtf/FeatureDefines.h @@ -174,6 +174,10 @@ the public iOS SDK. We will also need to update the FeatureDefines.xcconfig file #define ENABLE_PRIMARY_SNAPSHOTTED_PLUGIN_HEURISTIC 1 #endif +#if !defined(ENABLE_DOWNLOAD_ATTRIBUTE) +#define ENABLE_DOWNLOAD_ATTRIBUTE 0 +#endif + #endif /* PLATFORM(IOS) */ /* --------- Apple MAC port (not IOS) --------- */ diff --git a/webkit/WTF/wtf/MainThread.cpp b/webkit/WTF/wtf/MainThread.cpp index 98f7e8e99..7828addd0 100755 --- a/webkit/WTF/wtf/MainThread.cpp +++ b/webkit/WTF/wtf/MainThread.cpp @@ -241,6 +241,7 @@ static void callFunctionObject(void* context) auto function = std::unique_ptr>(static_cast*>(context)); (*function)(); #if PLATFORM(WKC) + function->~function(); WTF::fastFree(function.release()); #endif } diff --git a/webkit/WTF/wtf/MathExtras.h b/webkit/WTF/wtf/MathExtras.h index 6cd35f7ae..9e1ed5f49 100755 --- a/webkit/WTF/wtf/MathExtras.h +++ b/webkit/WTF/wtf/MathExtras.h @@ -261,6 +261,15 @@ inline bool isWithinIntRange(float x) return x > static_cast(std::numeric_limits::min()) && x < static_cast(std::numeric_limits::max()); } +inline float normalizedFloat(float value) +{ + if (value > 0 && value < std::numeric_limits::min()) + return std::numeric_limits::min(); + if (value < 0 && value > -std::numeric_limits::min()) + return -std::numeric_limits::min(); + return value; +} + template inline bool hasOneBitSet(T value) { return !((value - 1) & value) && value; diff --git a/webkit/WTF/wtf/NumberOfCores.cpp b/webkit/WTF/wtf/NumberOfCores.cpp index 58054469d..d623d2674 100755 --- a/webkit/WTF/wtf/NumberOfCores.cpp +++ b/webkit/WTF/wtf/NumberOfCores.cpp @@ -26,6 +26,8 @@ #include "config.h" #include "NumberOfCores.h" +#include + #if OS(DARWIN) #include // sys/types.h must come before sys/sysctl.h because the latter uses diff --git a/webkit/WTF/wtf/Threading.cpp b/webkit/WTF/wtf/Threading.cpp index e8d03a58c..567ccd7c1 100755 --- a/webkit/WTF/wtf/Threading.cpp +++ b/webkit/WTF/wtf/Threading.cpp @@ -28,6 +28,10 @@ #include +#if HAVE(QOS_CLASSES) +#include +#endif + namespace WTF { struct NewThreadContext { @@ -92,15 +96,32 @@ ThreadIdentifier createThread(ThreadFunction entryPoint, void* data, const char* void setCurrentThreadIsUserInteractive() { #if HAVE(QOS_CLASSES) - pthread_set_qos_class_self_np(QOS_CLASS_USER_INTERACTIVE, 0); + pthread_set_qos_class_self_np(adjustedQOSClass(QOS_CLASS_USER_INTERACTIVE), relativePriority); #endif } void setCurrentThreadIsUserInitiated() { #if HAVE(QOS_CLASSES) - pthread_set_qos_class_self_np(QOS_CLASS_USER_INITIATED, 0); + pthread_set_qos_class_self_np(adjustedQOSClass(QOS_CLASS_USER_INITIATED), relativePriority); #endif } +#if HAVE(QOS_CLASSES) +static qos_class_t globalMaxQOSclass { QOS_CLASS_UNSPECIFIED }; + +void setGlobalMaxQOSClass(qos_class_t maxClass) +{ + bmalloc::api::setScavengerThreadQOSClass(maxClass); + globalMaxQOSclass = maxClass; +} + +qos_class_t adjustedQOSClass(qos_class_t originalClass) +{ + if (globalMaxQOSclass != QOS_CLASS_UNSPECIFIED) + return std::min(originalClass, globalMaxQOSclass); + return originalClass; +} +#endif + } // namespace WTF diff --git a/webkit/WTF/wtf/Threading.h b/webkit/WTF/wtf/Threading.h index 5906ff74a..d29ae3aaa 100755 --- a/webkit/WTF/wtf/Threading.h +++ b/webkit/WTF/wtf/Threading.h @@ -76,6 +76,11 @@ ThreadIdentifier createThreadInternal(ThreadFunction, void*, const char* threadN // Helpful for platforms where the thread name must be set from within the thread. void initializeCurrentThreadInternal(const char* threadName); +#if HAVE(QOS_CLASSES) +WTF_EXPORT_PRIVATE void setGlobalMaxQOSClass(qos_class_t); +WTF_EXPORT_PRIVATE qos_class_t adjustedQOSClass(qos_class_t); +#endif + } // namespace WTF using WTF::ThreadIdentifier; @@ -85,4 +90,9 @@ using WTF::changeThreadPriority; using WTF::detachThread; using WTF::waitForThreadCompletion; +#if HAVE(QOS_CLASSES) +using WTF::setGlobalMaxQOSClass; +using WTF::adjustedQOSClass; +#endif + #endif // Threading_h diff --git a/webkit/WTF/wtf/ThreadingPthreads.cpp b/webkit/WTF/wtf/ThreadingPthreads.cpp index 106ed96ec..2ec63a8df 100755 --- a/webkit/WTF/wtf/ThreadingPthreads.cpp +++ b/webkit/WTF/wtf/ThreadingPthreads.cpp @@ -178,7 +178,7 @@ ThreadIdentifier createThreadInternal(ThreadFunction entryPoint, void* data, con pthread_attr_t attr; pthread_attr_init(&attr); #if HAVE(QOS_CLASSES) - pthread_attr_set_qos_class_np(&attr, QOS_CLASS_USER_INITIATED, 0); + pthread_attr_set_qos_class_np(&attr, adjustedQOSClass(QOS_CLASS_USER_INITIATED), 0); #endif int error = pthread_create(&threadHandle, &attr, wtfThreadEntryPoint, invocation.get()); pthread_attr_destroy(&attr); diff --git a/webkit/WTF/wtf/WTFThreadData.h b/webkit/WTF/wtf/WTFThreadData.h index d86931874..d726dda5a 100755 --- a/webkit/WTF/wtf/WTFThreadData.h +++ b/webkit/WTF/wtf/WTFThreadData.h @@ -73,11 +73,6 @@ class WTFThreadData { return oldAtomicStringTable; } - void resetCurrentAtomicStringTable() - { - m_currentAtomicStringTable = m_defaultAtomicStringTable; - } - const StackBounds& stack() { // We need to always get a fresh StackBounds from the OS due to how fibers work. diff --git a/webkit/WTF/wtf/cocoa/WorkQueueCocoa.cpp b/webkit/WTF/wtf/cocoa/WorkQueueCocoa.cpp index 1901b6059..6f734752f 100755 --- a/webkit/WTF/wtf/cocoa/WorkQueueCocoa.cpp +++ b/webkit/WTF/wtf/cocoa/WorkQueueCocoa.cpp @@ -51,15 +51,15 @@ static dispatch_qos_class_t dispatchQOSClass(WorkQueue::QOS qos) { switch (qos) { case WorkQueue::QOS::UserInteractive: - return QOS_CLASS_USER_INTERACTIVE; + return adjustedQOSClass(QOS_CLASS_USER_INTERACTIVE); case WorkQueue::QOS::UserInitiated: - return QOS_CLASS_USER_INITIATED; + return adjustedQOSClass(QOS_CLASS_USER_INITIATED); case WorkQueue::QOS::Default: - return QOS_CLASS_DEFAULT; + return adjustedQOSClass(QOS_CLASS_DEFAULT); case WorkQueue::QOS::Utility: - return QOS_CLASS_UTILITY; + return adjustedQOSClass(QOS_CLASS_UTILITY); case WorkQueue::QOS::Background: - return QOS_CLASS_BACKGROUND; + return adjustedQOSClass(QOS_CLASS_BACKGROUND); } } #else diff --git a/webkit/WTF/wtf/text/StringView.h b/webkit/WTF/wtf/text/StringView.h index 667e67902..23b537581 100755 --- a/webkit/WTF/wtf/text/StringView.h +++ b/webkit/WTF/wtf/text/StringView.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014-2015 Apple Inc. All rights reserved. + * Copyright (C) 2014-2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -146,11 +146,11 @@ class StringView { void setUnderlyingString(const StringImpl*) { } void setUnderlyingString(const StringView&) { } #endif - - static const unsigned is16BitStringFlag = 1u << 31; + void clear(); const void* m_characters { nullptr }; unsigned m_length { 0 }; + bool m_is8Bit { true }; #if CHECK_STRINGVIEW_LIFETIME void adoptUnderlyingString(UnderlyingString*); @@ -202,11 +202,11 @@ inline StringView::~StringView() inline StringView::StringView(StringView&& other) : m_characters(other.m_characters) , m_length(other.m_length) + , m_is8Bit(other.m_is8Bit) { ASSERT(other.underlyingStringIsValid()); - other.m_characters = nullptr; - other.m_length = 0; + other.clear(); setUnderlyingString(other); other.setUnderlyingString(nullptr); @@ -215,6 +215,7 @@ inline StringView::StringView(StringView&& other) inline StringView::StringView(const StringView& other) : m_characters(other.m_characters) , m_length(other.m_length) + , m_is8Bit(other.m_is8Bit) { ASSERT(other.underlyingStringIsValid()); @@ -227,9 +228,9 @@ inline StringView& StringView::operator=(StringView&& other) m_characters = other.m_characters; m_length = other.m_length; + m_is8Bit = other.m_is8Bit; - other.m_characters = nullptr; - other.m_length = 0; + other.clear(); setUnderlyingString(other); other.setUnderlyingString(nullptr); @@ -243,6 +244,7 @@ inline StringView& StringView::operator=(const StringView& other) m_characters = other.m_characters; m_length = other.m_length; + m_is8Bit = other.m_is8Bit; setUnderlyingString(other); @@ -251,20 +253,16 @@ inline StringView& StringView::operator=(const StringView& other) inline void StringView::initialize(const LChar* characters, unsigned length) { - // FIXME: We need a better solution here, because there is no guarantee that - // the length here won't be too long. Maybe at least a RELEASE_ASSERT? - ASSERT(!(length & is16BitStringFlag)); m_characters = characters; m_length = length; + m_is8Bit = true; } inline void StringView::initialize(const UChar* characters, unsigned length) { - // FIXME: We need a better solution here, because there is no guarantee that - // the length here won't be too long. Maybe at least a RELEASE_ASSERT? - ASSERT(!(length & is16BitStringFlag)); m_characters = characters; - m_length = is16BitStringFlag | length; + m_length = length; + m_is8Bit = false; } inline StringView::StringView(const LChar* characters, unsigned length) @@ -302,8 +300,7 @@ inline StringView::StringView(const String& string) { setUnderlyingString(string.impl()); if (!string.impl()) { - m_characters = nullptr; - m_length = 0; + clear(); return; } if (string.is8Bit()) { @@ -313,6 +310,13 @@ inline StringView::StringView(const String& string) initialize(string.characters16(), string.length()); } +inline void StringView::clear() +{ + m_characters = nullptr; + m_length = 0; + m_is8Bit = true; +} + inline StringView StringView::empty() { return StringView(reinterpret_cast(""), 0); @@ -359,7 +363,7 @@ inline bool StringView::isEmpty() const inline unsigned StringView::length() const { - return m_length & ~is16BitStringFlag; + return m_length; } inline StringView::operator bool() const @@ -369,7 +373,7 @@ inline StringView::operator bool() const inline bool StringView::is8Bit() const { - return !(m_length & is16BitStringFlag); + return m_is8Bit; } inline StringView StringView::substring(unsigned start, unsigned length) const @@ -424,8 +428,7 @@ inline void StringView::getCharactersWithUpconvert(UChar* destination) const return; } auto characters16 = this->characters16(); - unsigned length = this->length(); - for (unsigned i = 0; i < length; ++i) + for (unsigned i = 0; i < m_length; ++i) destination[i] = characters16[i]; } @@ -447,35 +450,35 @@ inline String StringView::toString() const { if (is8Bit()) return String(characters8(), m_length); - return String(characters16(), length()); + return String(characters16(), m_length); } inline float StringView::toFloat(bool& isValid) const { if (is8Bit()) return charactersToFloat(characters8(), m_length, &isValid); - return charactersToFloat(characters16(), length(), &isValid); + return charactersToFloat(characters16(), m_length, &isValid); } inline int StringView::toInt(bool& isValid) const { if (is8Bit()) return charactersToInt(characters8(), m_length, &isValid); - return charactersToInt(characters16(), length(), &isValid); + return charactersToInt(characters16(), m_length, &isValid); } inline String StringView::toStringWithoutCopying() const { if (is8Bit()) return StringImpl::createWithoutCopying(characters8(), m_length); - return StringImpl::createWithoutCopying(characters16(), length()); + return StringImpl::createWithoutCopying(characters16(), m_length); } inline size_t StringView::find(UChar character, unsigned start) const { if (is8Bit()) return WTF::find(characters8(), m_length, character, start); - return WTF::find(characters16(), length(), character, start); + return WTF::find(characters16(), m_length, character, start); } #if !CHECK_STRINGVIEW_LIFETIME diff --git a/webkit/WebCore/CMakeLists.txt b/webkit/WebCore/CMakeLists.txt index 2b4b67b57..1e3fda6a5 100755 --- a/webkit/WebCore/CMakeLists.txt +++ b/webkit/WebCore/CMakeLists.txt @@ -1,4 +1,5 @@ set(WebCore_INCLUDE_DIRECTORIES + "${CMAKE_BINARY_DIR}" "${WEBCORE_DIR}" "${WEBCORE_DIR}/Modules/airplay" "${WEBCORE_DIR}/Modules/battery" diff --git a/webkit/WebCore/ChangeLog b/webkit/WebCore/ChangeLog index 46fd411f6..a861d26d8 100755 --- a/webkit/WebCore/ChangeLog +++ b/webkit/WebCore/ChangeLog @@ -1,3 +1,3923 @@ +2017-03-30 Eric Carlson + + [Crash] WebCore::AudioBuffer::AudioBuffer don't checking illegal value + https://bugs.webkit.org/show_bug.cgi?id=169956 + + Reviewed by Youenn Fablet. + + Test: webaudio/audiobuffer-crash.html + + * Modules/webaudio/AudioBuffer.cpp: + (WebCore::AudioBuffer::AudioBuffer): Invalidate the object and return early if the channel + array allocation fails. + (WebCore::AudioBuffer::AudioBuffer): Ditto. + (WebCore::AudioBuffer::invalidate): Invalidate the object. + * Modules/webaudio/AudioBuffer.h: + +2017-01-24 Miguel Gomez + + [GTK] Do not paint non composited content into the window when using the threaded compositor + https://bugs.webkit.org/show_bug.cgi?id=167367 + + Reviewed by Carlos Garcia Campos. + + When using the threaded compositor we need to send the non composited content for compositing as well, + not painting it directly into the window. + + No new tests. + + * rendering/RenderLayerBacking.cpp: + (WebCore::RenderLayerBacking::paintsIntoWindow): + +2016-10-27 Myles C. Maxfield + + [macOS] [WebGL2] Temporarily upgrade WebGL 2's internal OpenGL context from version 2.1 to 3.2 + https://bugs.webkit.org/show_bug.cgi?id=164091 + + Reviewed by Dean Jackson. + + In order to test WebGL2 correctly, I had to upgrade the macOS's OpenGL + context to a 3.2-compatible context to make sure the new symbols are + accepted. Eventually, this 3.2-compatible context will have to be + reverted and replaced with an ANGLE context. The current 3.2-compatible + context is just for testing. + + Test: fast/canvas/webgl/webgl2-context-creation.html + + * html/canvas/WebGLBuffer.cpp: Use "nullptr" instead of 0. + (WebCore::WebGLBuffer::associateBufferData): + * html/canvas/WebGLRenderingContextBase.cpp: Use make_unique() instead + of the unique_ptr constructor. + (WebCore::WebGLRenderingContextBase::create): + * platform/graphics/GraphicsContext3D.h: GraphicsContext should know + if it is using a 3.2-compatible context because some parts of 2.1 are + removed in these contexts, and replaced with new things which aren't + in 2.1. + * platform/graphics/mac/GraphicsContext3DMac.mm: + (WebCore::setPixelFormat): Use kCGLPFAOpenGLProfile to specify an + OpenGL 3.2 context. + (WebCore::GraphicsContext3D::GraphicsContext3D): GL_CLAMP is deprecated + in OpenGL 3.2. Fortunately, GL_CLAMP_TO_EDGE isn't deprecated and does + exactly what we want. In OpenGL3.2, point sprites are always enabled, + so there's no need to enable them in those contexts. + (WebCore::GraphicsContext3D::isGLES2Compliant): + * platform/graphics/opengl/Extensions3DOpenGL.cpp: In OpenGL 3.2, + glGetString() no longer accepts GL_EXTENSIONS. Instead, glGetStringi() + is used instead. Unfortunately, glGetString() is not available in + OpenGL 2.1 contexts, so we need to use one or the other based on the + version of the context we're using. + (WebCore::Extensions3DOpenGL::Extensions3DOpenGL): + (WebCore::Extensions3DOpenGL::getExtensions): + * platform/graphics/opengl/Extensions3DOpenGL.h: + * platform/graphics/opengl/Extensions3DOpenGLCommon.cpp: + (WebCore::Extensions3DOpenGLCommon::Extensions3DOpenGLCommon): + (WebCore::Extensions3DOpenGLCommon::initializeAvailableExtensions): + Instead of modifying getExtensions() to use glGetStringi(), it makes + better sense to modify this function because getExtensions() returns + a string. Building up a string just to split it up again is silly, so + modifying this function instead makes more sense. + * platform/graphics/opengl/Extensions3DOpenGLCommon.h: + * platform/graphics/opengl/GraphicsContext3DOpenGL.cpp: + (WebCore::GraphicsContext3D::getIntegerv): GL_MAX_VARYING_FLOATS is + removed in OpenGL 3.2 contexts. However, it is replaced by + GL_MAX_VARYING_COMPONENTS, though this is deprecated but not removed. + In the more recent OpenGL context versions, GL_MAX_VARYING_VECTORS is + recommended instead, but that isn't available in OpenGL 3.2. + (WebCore::GraphicsContext3D::getExtensions): + +2016-10-28 Alex Christensen + + Fix Windows WebGL build after r208022 + https://bugs.webkit.org/show_bug.cgi?id=164091 + + * platform/graphics/opengl/Extensions3DOpenGLCommon.h: + * platform/graphics/opengl/Extensions3DOpenGLES.cpp: + (WebCore::Extensions3DOpenGLES::Extensions3DOpenGLES): + * platform/graphics/opengl/Extensions3DOpenGLES.h: + * platform/graphics/opengl/GraphicsContext3DOpenGLES.cpp: + (WebCore::GraphicsContext3D::getExtensions): + +2017-05-17 Jason Marcell + + Cherry-pick r216978. rdar://problem/31971195 + + 2017-05-17 Ryosuke Niwa + + getElementById can return a wrong elemnt when a matching element is removed during beforeload event + https://bugs.webkit.org/show_bug.cgi?id=171374 + + Reviewed by Brent Fulgham. + + The bug was caused by HTMLLinkElement firing beforeload event inside insertedInto before the tree state is updated. + Delay the event dispatch to the post insertion callback. + + Test: fast/html/link-element-removal-during-beforeload.html + + * html/HTMLLinkElement.cpp: + (WebCore::HTMLLinkElement::insertedInto): + (WebCore::HTMLLinkElement::finishedInsertingSubtree): + * html/HTMLLinkElement.h: + +2017-05-17 Jason Marcell + + Cherry-pick r216813. rdar://problem/31971160 + + 2017-05-12 Jiewen Tan + + Elements should be inserted into a template element as its content's last child + https://bugs.webkit.org/show_bug.cgi?id=171373 + + + Reviewed by Ryosuke Niwa. + + Before this change, our HTML parser obeys the following premises: + 1) A fostering child whose parent is a table should be inserted before its parent and under its grandparent. + 2) When inserting into a template element, an element should be inserted into its content. + + Let's walk through the example: + a) Before eventhandler takes place + template + table + svg <- parser + b) After eventhandler takes place + template + table + svg <- parser + c) after parsing svg + template + content + svg + (table) + table + + Finally, in the example, the svg element will be inserted into the content of the template element while + having its next sibling point to the table element. However, the table element is actually under the + template element not its content. + + This messy tree is constructed because the second premise is incompleted. It should be: When inserting into + a template element, an element should be inserted into its content as its last child. + Quoted from Step 3 of https://html.spec.whatwg.org/multipage/syntax.html#appropriate-place-for-inserting-a-node + A correct tree will then looks like: + template + content + svg + table + + Tests: fast/dom/HTMLTemplateElement/insert-fostering-child-crash.html + fast/dom/HTMLTemplateElement/insert-fostering-child.html + + * html/parser/HTMLConstructionSite.cpp: + (WebCore::insert): + By nullifying task.nextChild, it will force the parser to append the element as task.parent's last child. + +2017-05-09 Matthew Hanson + + Cherry-pick r216131. rdar://problem/31967895 + + 2017-05-03 Zalan Bujtas + + RenderSearchField should not use isTextField() in SPECIALIZE_TYPE_TRAITS_RENDER_OBJECT + https://bugs.webkit.org/show_bug.cgi?id=171608 + + Reviewed by Simon Fraser. + + isTextField() is true for any generic single line text control. + + * rendering/RenderObject.h: + (WebCore::RenderObject::isSearchField): + * rendering/RenderSearchField.h: + +2017-05-09 Jason Marcell + + Cherry-pick r216443. rdar://problem/31971375 + + 2017-05-04 Jiewen Tan + + Search events should not fire synchronously for search type input elements with incremental attribute set + https://bugs.webkit.org/show_bug.cgi?id=171376 + + + Reviewed by Chris Dumez. + + For some reasons, we fire search events immediately for search type input elements with incremental + attribute set only when the length of the input equals to zero. This behaviour should be prevented + as event listeners in the middle might perform unexpectedly. + + Test: fast/forms/search/search-incremental-crash.html + + * html/SearchInputType.cpp: + (WebCore::SearchInputType::startSearchEventTimer): + +2017-05-09 Jason Marcell + + Cherry-pick r216159. rdar://problem/31971329 + + 2017-05-03 Zalan Bujtas + + SearchInputType could end up with a mismatched renderer. + https://bugs.webkit.org/show_bug.cgi?id=171547 + + + Reviewed by Antti Koivisto. + + Normally we've got the correct renderer by the time we call into SearchInputType. + However, since HTMLInputElement::updateType() eagerly updates the type while the associated renderers are done lazily + (so we don't get them updated until after the next tree update), we could actually end up + with a mismatched renderer (e.g. through form submission). + + Test: fast/forms/change-input-type-and-submit-form-crash.html + + * html/SearchInputType.cpp: + (WebCore::SearchInputType::addSearchResult): + (WebCore::SearchInputType::didSetValueByUserEdit): + +2017-05-09 Matthew Hanson + + Cherry-pick r216120. rdar://problem/31970955 + + 2017-05-03 Daniel Bates + + Abandon the current load once the provisional loader detaches from the frame + https://bugs.webkit.org/show_bug.cgi?id=171577 + + + Reviewed by Brent Fulgham and Brady Eidson. + + We detach all child frames as part of setting our document loader to the provisional + document loader when committing a load for a frame. Detaching child frames invokes + the unload event handler on the child frames that can run arbitrary JavaScript script. + Among other things, such script can initiate a new load in the frame whose current + load is being committed. We should stop processing the current load as soon as we + detect that updating our document loader has started a new provisional load. + + Test: fast/loader/inner-iframe-loads-data-url-into-parent-on-unload-crash.html + + * loader/FrameLoader.cpp: + (WebCore::FrameLoader::transitionToCommitted): + +2017-05-09 Matthew Hanson + + Cherry-pick r216023. rdar://problem/31971371 + + 2017-05-01 Chris Dumez + + Do not dispatch SVG load event in frameless documents + https://bugs.webkit.org/show_bug.cgi?id=171505 + + + Reviewed by Andreas Kling. + + We should not dispatch SVG load events in frameless documents. + took care of most load events but forgot the SVG load event. + + Test: fast/dom/domparser-parsefromstring-svg-load-event.html + + * dom/Document.cpp: + (WebCore::Document::implicitClose): + +2017-04-11 Jason Marcell + + Cherry-pick 214358. rdar://problem/31502340 + + 2017-03-24 Alex Christensen + + REGRESSION: Content Blocker: Blocking "a[href*=randomString]" doesn't work + https://bugs.webkit.org/show_bug.cgi?id=169167 + + Reviewed by Simon Fraser. + + When testing content extensions, we have always called an API function that internally + has called AtomicString::init somewhere before we start compiling the content extension. + On iOS, though, we call [_WKUserContentExtensionStore compileContentExtensionForIdentifier:...] + without having already called anything that calls AtomicString::init. The new CSS parser is now + failing to parse some selectors because CSSSelectorParser::defaultNamespace is returning starAtom, + which is a null atomic string before AtomicString::init is called. + + Covered by a new API test. + + * contentextensions/ContentExtensionParser.cpp: + (WebCore::ContentExtensions::isValidCSSSelector): + (WebCore::ContentExtensions::loadAction): + (WebCore::ContentExtensions::isValidSelector): Deleted. + * contentextensions/ContentExtensionParser.h: + Call AtomicString::init before checking if a css selector is valid. + +2017-04-03 Jason Marcell + + Cherry-pick r214703. rdar://problem/31407633 + + 2017-03-31 Simon Fraser + + Rename DOMWindow's m_touchEventListenerCount to m_touchAndGestureEventListenerCount + https://bugs.webkit.org/show_bug.cgi?id=170371 + + Reviewed by Tim Horton. + + This count tracks touch and gesture event listeners, so name it appropriately. + + * page/DOMWindow.cpp: + (WebCore::DOMWindow::addEventListener): + (WebCore::DOMWindow::removeEventListener): + (WebCore::DOMWindow::removeAllEventListeners): + * page/DOMWindow.h: + +2017-04-03 Jason Marcell + + Cherry-pick r214702. rdar://problem/31407633 + + 2017-03-31 Simon Fraser + + When destroying a Node, assert that it's been removed from all the touch handler maps + https://bugs.webkit.org/show_bug.cgi?id=170363 + rdar://problem/31377469 + + Reviewed by Tim Horton. + + Assert that the Node has been removed from the touch handler maps in all documents on destruction. + + * dom/Document.h: + (WebCore::Document::hasTouchEventHandlers): + (WebCore::Document::touchEventTargetsContain): + * dom/Node.cpp: + (WebCore::Node::~Node): + +2017-01-05 Matthew Hanson + + Merge r210369. rdar://problem/29100419 + + 2017-01-05 Zalan Bujtas + + Mark the dedicated root linebox for trailing floats in empty inlines dirty. + https://bugs.webkit.org/show_bug.cgi?id=166732 + + + Reviewed by Antti Koivisto. + + We normally attach floating boxes to the last root linebox. However when the floatbox is preceded by a
+ we generate a dedicated root linebox (TrailingFloatsRootInlineBox) for the floatbox. + When this floatbox is a RenderInline descendant and this RenderInline does not generate lineboxes (it's ancestor RenderBlockFlow does) + we have to make sure that this special root linebox gets marked dirty when the associated floatbox changes. + (Unfortunately through the recursive calls on dirtyLinesFromChangedChild(), we lose the information about + the "changed child" since the inlines propagates the marking logic to the RenderBlockFlow, see FIXME.) + + Test: fast/inline/trailing-floats-inline-crash2.html + + * rendering/RenderLineBoxList.cpp: + (WebCore::RenderLineBoxList::dirtyLinesFromChangedChild): + +2017-04-03 Jason Marcell + + Cherry-pick r214648. rdar://problem/31408453 + + 2017-03-30 Simon Fraser + + Minor cleanup checking for gesture event names + https://bugs.webkit.org/show_bug.cgi?id=170319 + + Reviewed by Tim Horton. + + Just use isGestureEventType() in a couple of places. + + * dom/Node.cpp: + (WebCore::tryAddEventListener): + (WebCore::tryRemoveEventListener): + +2017-04-03 Jason Marcell + + Cherry-pick r214640. rdar://problem/31408453 + + 2017-03-30 Simon Fraser + + Rename a touch event function, and new touch region test results + https://bugs.webkit.org/show_bug.cgi?id=170309 + rdar://problem/31329520 + + Reviewed by Chris Dumez. + + Adapt to a naming change in WebKitAdditions. + + * dom/Document.cpp: + (WebCore::Document::removeAllEventListeners): + * page/FrameView.cpp: + (WebCore::FrameView::layout): + * rendering/RenderElement.cpp: + (WebCore::RenderElement::styleWillChange): + * rendering/RenderLayer.cpp: + (WebCore::RenderLayer::scrollTo): + (WebCore::RenderLayer::calculateClipRects): + +2017-03-30 Jason Marcell + + Merge r214392. rdar://problem/31356105 + + 2017-03-24 Daniel Bates + + media/restore-from-page-cache.html causes NoEventDispatchAssertion::isEventAllowedInMainThread() assertion failure + https://bugs.webkit.org/show_bug.cgi?id=170087 + + + Reviewed by Simon Fraser. + + Reduce the scope of code that should never dispatch DOM events so as to allow updating contents size + after restoring a page from the page cache. + + In r214014 we instantiate a NoEventDispatchAssertion in FrameLoader::commitProvisionalLoad() + around the call to CachedPage::restore() to assert when a DOM event is dispatched during + page restoration as such events can cause re-entrancy into the page cache. As it turns out + it is sufficient to ensure that no DOM events are dispatched after restoring all cached frames + as opposed to after CachedPage::restore() returns. + + Also rename Document::enqueue{Pageshow, Popstate}Event() to dispatch{Pageshow, Popstate}Event(), + respectively, since they synchronously dispatch events :(. We hope in the future to make them + asynchronously dispatch events. + + * dom/Document.cpp: + (WebCore::Document::implicitClose): Update for renaming. + (WebCore::Document::statePopped): Ditto. + (WebCore::Document::dispatchPageshowEvent): Renamed; formerly named enqueuePageshowEvent(). + (WebCore::Document::dispatchPopstateEvent): Renamed; formerly named enqueuePopstateEvent(). + (WebCore::Document::enqueuePageshowEvent): Deleted. + (WebCore::Document::enqueuePopstateEvent): Deleted. + * dom/Document.h: + * history/CachedPage.cpp: + (WebCore::firePageShowAndPopStateEvents): Moved logic from FrameLoader::didRestoreFromCachedPage() to here. + (WebCore::CachedPage::restore): Modified to call firePageShowAndPopStateEvents(). + * loader/FrameLoader.cpp: + (WebCore::FrameLoader::commitProvisionalLoad): Removed use of NoEventDispatchAssertion RAII object. We + will instantiate it in CachedPage::restore() with a smaller scope. + (WebCore::FrameLoader::didRestoreFromCachedPage): Deleted; moved logic from here to WebCore::firePageShowAndPopStateEvents(). + * loader/FrameLoader.h: + +2017-03-30 Jason Marcell + + Merge r214510. rdar://problem/31356107 + + 2017-03-27 Brent Fulgham + + Only attach Attributes to a given element one time + https://bugs.webkit.org/show_bug.cgi?id=170125 + + + Reviewed by Chris Dumez. + + Attach the attribute node to the Element before calling 'setAttributeInternal', since that method may cause + arbitrary JavaScript events to fire. + + Test: fast/dom/Attr/only-attach-attr-once.html + + * dom/Element.cpp: + (WebCore::Element::attachAttributeNodeIfNeeded): Added. + (WebCore::Element::setAttributeNode): Use new method. Revise to attach attribute before calling 'setAttributeInternal'. + (WebCore::Element::setAttributeNodeNS): Ditto. + * dom/Element.h: + +2017-03-30 Jason Marcell + + Merge r214086. rdar://problem/31356102 + + 2017-03-16 Dean Jackson + + WebGL: Improve index validation when using uint index values + https://bugs.webkit.org/show_bug.cgi?id=169798 + + Reviewed by Simon Fraser. + + Make sure that we test index validation with the correct type. + Also stop using -1 in WebGLBuffer to indicate non-existant values. + + Test: fast/canvas/webgl/draw-elements-out-of-bounds-uint-index.html + + * html/canvas/WebGL2RenderingContext.cpp: + (WebCore::WebGL2RenderingContext::validateIndexArrayConservative): Use optional<> and + unsigned values. + * html/canvas/WebGLBuffer.cpp: Use unsigned for maxIndex (they can't be negative) + and optional<> to indicate unknown value. + (WebCore::WebGLBuffer::getCachedMaxIndex): + (WebCore::WebGLBuffer::setCachedMaxIndex): + * html/canvas/WebGLBuffer.h: + * html/canvas/WebGLRenderingContext.cpp: + (WebCore::WebGLRenderingContext::validateIndexArrayConservative): Use optional<> and + unsigned values. + * html/canvas/WebGLRenderingContextBase.cpp: + (WebCore::WebGLRenderingContextBase::validateVertexAttributes): No need to check if + an unsigned value is less than zero. + +2017-03-29 Jason Marcell + + Merge r214291. rdar://problem/30922110 + + 2017-03-22 Jiewen Tan + + ASSERT_WITH_SECURITY_IMPLICATION hit when removing an while dragging on iOS + https://bugs.webkit.org/show_bug.cgi?id=165535 + + + Reviewed by Ryosuke Niwa. + + Utimately we should prevent SliderThumbElement::unregisterForTouchEvents() being called while + updating render tree. A quick fix for this is to move dispatchFormControlChangeEvent for input + from stopDragging up to the callers which really needs to dispatch this event, i.e., finishing + dragging the slider. It is clear that not every caller of stopDragging wants to + dispatchFormControlChangeEvent. + + Test: fast/forms/range/range-remove-on-drag.html + + * html/shadow/SliderThumbElement.cpp: + (WebCore::SliderThumbElement::stopDragging): + (WebCore::SliderThumbElement::defaultEventHandler): + (WebCore::SliderThumbElement::handleTouchEndAndCancel): + +2016-07-07 Antti Koivisto + + REGRESSION (r199054): CrashTracer: [USER] parseWebKit at WebCore: WebCore::RenderBlockFlow::checkFloatsInCleanLine + 107 + https://bugs.webkit.org/show_bug.cgi?id=159519 + + Reviewed by Zalan Bujtas. + + Test: fast/inline/trailing-floats-inline-crash.html + + * rendering/RenderBlockLineLayout.cpp: + (WebCore::RenderBlockFlow::checkFloatsInCleanLine): + + Use the existing deletionHasBegun bit in RenderStyle to assert against this reliably. + + * rendering/RenderLineBoxList.cpp: + (WebCore::RenderLineBoxList::dirtyLinesFromChangedChild): + + In some cases a special TrailingFloatsRootInlineBox may be added as the last root linebox of a flow. + If it is combined with br the existing invalidation that invalidates the next and previous line may + not be sufficient. Test for this case and invalidate the TrailingFloatsRootInlineBox too if it exists. + + * rendering/RootInlineBox.h: + (WebCore::RootInlineBox::isTrailingFloatsRootInlineBox): + * rendering/TrailingFloatsRootInlineBox.h: + * rendering/style/RenderStyle.h: + (WebCore::RenderStyle::deletionHasBegun): + + Expose the bit in debug. + +2017-03-28 Jason Marcell + + Merge r214194. rdar://problem/31101594 + + 2017-03-20 Daniel Bates + + Prevent new navigations from onbeforeunload handler + https://bugs.webkit.org/show_bug.cgi?id=169891 + + + Reviewed by Ryosuke Niwa. + + Ensure that all navigations initiated from an onbeforeunload handler are disallowed + regardless of how they were scheduled. Such navigations go against the expectation + of a user. + + * loader/FrameLoader.cpp: + (WebCore::FrameLoader::isNavigationAllowed): Added. + (WebCore::FrameLoader::loadURL): Modified code to call FrameLoader::isNavigationAllowed(). + (WebCore::FrameLoader::loadWithDocumentLoader): Ditto. + (WebCore::FrameLoader::stopAllLoaders): Ditto. + * loader/FrameLoader.h: + +2017-03-28 Jason Marcell + + Merge r214237. rdar://problem/31178134 + + 2017-03-21 Brady Eidson + + Disable all virtual tables. + and https://bugs.webkit.org/show_bug.cgi?id=169928 + + Reviewed by Jer Noble. + + No new tests (Covered by changes to existing test). + + * Modules/webdatabase/DatabaseAuthorizer.cpp: + (WebCore::DatabaseAuthorizer::createVTable): + (WebCore::DatabaseAuthorizer::dropVTable): + +2017-03-28 Jason Marcell + + Merge r211645. rdar://problem/30922105 + + 2017-02-03 Chris Dumez + + Fix bad assertion under HTMLTreeBuilder::processStartTagForInBody() + https://bugs.webkit.org/show_bug.cgi?id=167799 + + + Reviewed by Brent Fulgham. + + Fix bad assertion under HTMLTreeBuilder::processStartTagForInBody() that was + expecting the root element to be an element when parsing a . + While this assertion is true in theory and as per the specification, it does + not hold in WebKit when parsing a DocumentFragment. This is because WebKit + has an optimization causing us to have a DocumentFragment as root element + when parsing a fragment. See the following constructor: + "HTMLTreeBuilder(HTMLDocumentParser&, DocumentFragment&, Element&, ParserContentPolicy, const HTMLParserOptions&)" + + which has the following code: + """ + // https://html.spec.whatwg.org/multipage/syntax.html#parsing-html-fragments + // For efficiency, we skip step 5 ("Let root be a new html element with no attributes") and instead use the DocumentFragment as a root node. + m_tree.openElements().pushRootNode(HTMLStackItem::create(fragment)); + """ + + Update the assertion to expect a DocumentFragment as root element when parsing + a fragment, and keep expecting an element otherwise. + + Test: fast/parser/fragment-with-frameset-crash.html + + * html/parser/HTMLTreeBuilder.cpp: + (WebCore::HTMLTreeBuilder::processStartTagForInBody): + +2017-03-22 Jason Marcell + + Merge r214125. rdar://problem/30921831 + + 2017-03-17 Said Abou-Hallawa + + Time channel attack on SVG Filters + https://bugs.webkit.org/show_bug.cgi?id=118689 + + Reviewed by Simon Fraser. + + The time channel attack can happen if the attacker applies FEColorMatrix + or FEConvolveMatrix and provides a matrix which is filled with subnormal + floating point values. Performing floating-point operations on subnormals + is very expensive unless the pixel in the source graphics is black (or + zero). By measuring the time a filter takes to be applied, the attacker + can know whether the pixel he wants to steal from an iframe is black or + white. By repeating the same process on all the pixels in the iframe, the + attacker can reconstruct the whole page of the iframe. + + To fix this issue, the values in the matrices of these filters will clamped + to FLT_MIN. We do not want to consume too much time calculating filtered + pixels because of such tiny values. The difference between applying FLT_MIN + and applying a subnormal should not be even noticeable. Normalizing the + floating-point matrices should happen only at the beginning of the filter + platformApplySoftware(). + + * platform/graphics/filters/FEColorMatrix.cpp: + (WebCore::FEColorMatrix::platformApplySoftware): + * platform/graphics/filters/FEConvolveMatrix.cpp: + (WebCore::FEConvolveMatrix::fastSetInteriorPixels): + (WebCore::FEConvolveMatrix::fastSetOuterPixels): + (WebCore::FEConvolveMatrix::platformApplySoftware): + * platform/graphics/filters/FEConvolveMatrix.h: + * platform/graphics/filters/FilterEffect.h: + (WebCore::FilterEffect::normalizedFloats): + +2017-03-21 Jason Marcell + + Merge r214014. rdar://problem/30921815 + + 2017-03-15 Daniel Bates + + Iteratively dispatch DOM events after restoring a cached page + https://bugs.webkit.org/show_bug.cgi?id=169703 + + + Reviewed by Brady Eidson. + + Make dispatching of DOM events when restoring a page from the page cache symmetric with + dispatching of events when saving a page to the page cache. + + * history/CachedFrame.cpp: + (WebCore::CachedFrameBase::restore): Move code to dispatch events from here to FrameLoader::didRestoreFromCachedPage(). + * loader/FrameLoader.cpp: + (WebCore::FrameLoader::commitProvisionalLoad): Ensure that no DOM events are dispatched during + restoration of a cached page. Call didRestoreFromCachedPage() after restoring the page to + dispatch DOM events on the restored frames. + (WebCore::FrameLoader::willRestoreFromCachedPage): Renamed; formerly named prepareForCachedPageRestore(). + (WebCore::FrameLoader::didRestoreFromCachedPage): Added. + (WebCore::FrameLoader::prepareForCachedPageRestore): Renamed to willRestoreFromCachedPage(). + * loader/FrameLoader.h: + * page/FrameTree.cpp: + (WebCore::FrameTree::traverseNextInPostOrderWithWrap): Returns the next Frame* in a post-order + traversal of the frame tree optionally wrapping around to the deepest first child in the tree. + (WebCore::FrameTree::deepFirstChild): Added. + * page/FrameTree.h: + +2017-03-16 Jason Marcell + + Merge r214023. rdar://problem/31091039 + + 2017-03-15 Zalan Bujtas + + Do not reparent floating object until after intruding/overhanging dependency is cleared. + https://bugs.webkit.org/show_bug.cgi?id=169711 + + + Reviewed by Simon Fraser. + + This patch ensures that we cleanup the m_floatingObjects for siblings before reparenting the fresh float. + + Test: fast/block/float/inline-becomes-float-and-moves-around.html + + * rendering/RenderBlockFlow.cpp: + (WebCore::RenderBlockFlow::styleDidChange): + * rendering/RenderElement.cpp: + (WebCore::RenderElement::styleDidChange): + * rendering/RenderElement.h: + (WebCore::RenderElement::noLongerAffectsParentBlock): + +2017-03-16 Jason Marcell + + Merge r213897. rdar://problem/30921833 + + 2017-03-13 Wenson Hsieh + + Make RepaintRegionAccumulator hold a WeakPtr to its root RenderView + https://bugs.webkit.org/show_bug.cgi?id=168480 + + + Reviewed by Antti Koivisto. + + Implements two mitigations to prevent the symptoms of the bug from occurring (see the bugzilla for more details). + + Test: editing/execCommand/show-modal-dialog-during-execCommand.html + + * editing/EditorCommand.cpp: + (WebCore::Editor::Command::execute): + + Do not allow edit commands to execute if the frame's document before and after layout differ (that is, edit commands + triggered by a certain document should not run on a different document). + + * rendering/RenderView.cpp: + (WebCore::RenderView::RenderView): + (WebCore::RenderView::RepaintRegionAccumulator::RepaintRegionAccumulator): + + Turns RepaintRegionAccumulator's reference to its root RenderView into a WeakPtr to gracefully handle the case + where its RenderView is destroyed before RepaintRegionAccumulator's destructor gets a chance to flush the + RenderView's repaint regions. + + * rendering/RenderView.h: + +2017-03-16 Jason Marcell + + Merge r213501. rdar://problem/30921830 + + 2017-03-06 Brent Fulgham + + Validate DOM after potentially destructive actions during parser insert operations + https://bugs.webkit.org/show_bug.cgi?id=169222 + + + Reviewed by Ryosuke Niwa. + + Do not perform an insert operation if the next child's parent is no longer + part of the tree. This can happen if JavaScript runs during node removal + events and modifies the contents of the document. + + This patch was inspired by a similar Blink change by Marius Mlynski: + + + Tests: fast/parser/scriptexec-during-parserInsertBefore.html + + * html/parser/HTMLConstructionSite.cpp: + (WebCore::executeReparentTask): + (WebCore::executeInsertAlreadyParsedChildTask): + +2017-03-16 Jason Marcell + + Merge r213311. rdar://problem/30812769 + + 2017-03-02 Chris Dumez + + We should prevent load of subframes inserted during FrameTree deconstruction + https://bugs.webkit.org/show_bug.cgi?id=169095 + + Reviewed by Brent Fulgham. + + When deconstructing the FrameTree, we fire the unload event in each subframe. + Such unload event handler may insert a new frame, we would previously load + such new frame which was unsafe as we would end up with an attached subframe + on a detached tree. To address the issue, we prevent new subframes from loading + while deconstructing the FrameTree and firing the unload events. This new + behavior is consistent with Chrome and should therefore be safe from a + compatibility standpoint. + + Test: fast/frames/insert-frame-unload-handler.html + + * dom/ContainerNodeAlgorithms.cpp: + (WebCore::disconnectSubframes): + Update SubframeLoadingDisabler call site now that the constructor takes in + a pointer instead of a reference. + + * html/HTMLFrameOwnerElement.h: + (WebCore::SubframeLoadingDisabler::SubframeLoadingDisabler): + (WebCore::SubframeLoadingDisabler::~SubframeLoadingDisabler): + Update SubframeLoadingDisabler constructor to take in a pointer instead + of a reference, for convenience. + + * loader/FrameLoader.cpp: + (WebCore::FrameLoader::detachChildren): + Prevent loads in subframes while detaching the subframes. It would be unsafe + as we copy the list of frames before iterating to fire the unload events. + Therefore, newly inserted frames would not get unloaded. + +2017-03-02 Matthew Hanson + + Rollout r212893. rdar://problem/30812551 + +2017-02-28 Matthew Hanson + + Merge r213077. rdar://problem/30704432 + + 2017-02-27 Matthew Hanson + + Merge r212987. rdar://problem/30704432 + + 2017-02-24 Chris Dumez + + Unreviewed, follow-up fix after r212972. + + Fixes a few assertions on the debug build bots. + URL needs to be exactly the same as the parsed one given + that we are calling the ParsedURLString constructor. + + * platform/network/ResourceResponseBase.cpp: + (WebCore::ResourceResponseBase::sanitizeSuggestedFilename): + +2017-02-28 Matthew Hanson + + Merge r213076. rdar://problem/30704432 + + 2017-02-27 Matthew Hanson + + Merge r212972. rdar://problem/30704432 + + 2017-02-24 Chris Dumez + + Download attribute should be sanitized before being used as suggested filename + https://bugs.webkit.org/show_bug.cgi?id=168839 + + + Reviewed by Darin Adler. + + Sanitize Download attribute before using it as a suggested filename for the download. + We rely on ResourceResponse's sanitizing of the suggested filename to do so, which has + the benefit of being consistent with downloads without the download attribute. + + Tests: fast/dom/HTMLAnchorElement/anchor-file-blob-download-includes-doublequote.html + fast/dom/HTMLAnchorElement/anchor-file-blob-download-includes-slashes.html + fast/dom/HTMLAnchorElement/anchor-file-blob-download-includes-unicode.html + + * html/HTMLAnchorElement.cpp: + (WebCore::HTMLAnchorElement::handleClick): + * platform/network/ResourceResponseBase.cpp: + (WebCore::ResourceResponseBase::sanitizeSuggestedFilename): + * platform/network/ResourceResponseBase.h: + +2017-02-22 Brent Fulgham + + Merge r212554. rdar://problem/30636115 + + 2017-02-16 Brent Fulgham + + RenderView needs to be updated when FrameView changes + https://bugs.webkit.org/show_bug.cgi?id=168481 + + + Reviewed by Andreas Kling. + + The state of the Document's RenderView can get out of sync with the Frame's FrameView. + We need a notification mechanism so that modifications to the Frame's view are properly + relayed to Document so that it can have a correct RenderView. + + * dom/Document.cpp: + (WebCore::Document::didBecomeCurrentDocumentInView): Create an updated render tree (if + one does not already exist). + (WebCore::Document::destroyRenderTree): Remove an incorrect ASSERT. We may enter this + code when the Frame uses 'setView(nullptr)', which happens during certain updates. + * dom/Document.h: + * page/Frame.cpp: + (WebCore::Frame::setView): Destroy the old render tree (if present) before switching to + the new view. Then notify the document that it is now the current document in the new view. + +2017-02-22 Matthew Hanson + + Merge r212730. rdar://problem/30515072 + + 2017-02-21 Per Arne Vollan + + [Win] WebView is not painting in accelerated compositing mode. + https://bugs.webkit.org/show_bug.cgi?id=168654 + + Reviewed by Brent Fulgham. + + Initializing the uncommitted layer change flags to CoverageRectChanged in GraphicsLayerCA, + stops WebView painting in accelerated mode. + + Covered by existing tests. + + * platform/graphics/ca/GraphicsLayerCA.h: + +2017-02-21 Matthew Hanson + + Merge r212667. rdar://problem/29852056 + + 2017-02-20 Brent Fulgham + + Nullptr dereferences when stopping a load + https://bugs.webkit.org/show_bug.cgi?id=168608 + + + Reviewed by Ryosuke Niwa. + + Don't attempt to notify a detached frame's load client that the load is + stopped. + + * loader/DocumentLoader.cpp: + (WebCore::DocumentLoader::stopLoading): Check for null frame loader and + bypass dereferencing it. + +2017-02-18 Ryosuke Niwa + + REGRESSION(r212218): Assertion failures in and after parserRemoveChild + https://bugs.webkit.org/show_bug.cgi?id=168458 + + Reviewed by Antti Koivisto. + + The bug was caused by parserRemoveChild not preceeding to remove oldChild even when + oldChild had been inserted elsewhere during unload evnets of the disconnected frames. + Fixed the bug by checking this condition and exiting early. + + Also fixed various callers of parserRemoveChild to not call parserAppendChild when + the removed node had already been inserted elsewhere by scripts. + + Tests: fast/parser/adoption-agency-unload-iframe-3.html + fast/parser/adoption-agency-unload-iframe-4.html + fast/parser/xml-error-unload-iframe.html + + * dom/ContainerNode.cpp: + (WebCore::ContainerNode::parserRemoveChild): Exit early when the node had been + inserted elsewhere while firing unload events. Also moved the call to + notifyRemovePendingSheetIfNeeded outside NoEventDispatchAssertion since it can + synchrnously fire a focus event. + (WebCore::ContainerNode::parserAppendChild): Moved adoptNode call to inside + NoEventDispatchAssertion since adoptNode call here should never mutate DOM. + * html/parser/HTMLConstructionSite.cpp: + (WebCore::executeReparentTask): Added an early exit when the node had already been + inserted elsewhere. + (WebCore::executeInsertAlreadyParsedChildTask): Ditto. + * xml/XMLErrors.cpp: + (WebCore::XMLErrors::insertErrorMessageBlock): Ditto. + * xml/parser/XMLDocumentParser.cpp: + (WebCore::XMLDocumentParser::end): Fixed a crash unveiled by one of the test cases. + Exit early when insertErrorMessageBlock detached the parser (by author scripts). + (WebCore::XMLDocumentParser::finish): Keep the parser alive until we exit. + +2017-02-20 Ryosuke Niwa + + HTMLConstructionSiteTask::Insert should never be called on a node with a parent + https://bugs.webkit.org/show_bug.cgi?id=168099 + + Reviewed by Sam Weinig. + + insertAlreadyParsedChild always use HTMLConstructionSiteTask::InsertAlreadyParsedChild instead + of using HTMLConstructionSiteTask::Insert when fostering a child. + + Also combine the step to take all children and re-parenting into a single task instead of + separately issuing TakeAllChildren and Reparent tasks. + + No new tests since this is a refactoring. + + * html/parser/HTMLConstructionSite.cpp: + (WebCore::insert): Now asserts that the child node never have a parent. + (WebCore::executeInsertAlreadyParsedChildTask): Moved the code to remove the parent here. + (WebCore::executeTakeAllChildrenAndReparentTask): Renamed from executeTakeAllChildrenTask + now that this function also does the reparenting. + (WebCore::executeTask): + (WebCore::HTMLConstructionSite::reparent): Removed the variant only used with takeAllChildren. + (WebCore::HTMLConstructionSite::insertAlreadyParsedChild): Always use InsertAlreadyParsedChild + instead of calling fosterParent which uses Insert when fostering parents. + (WebCore::HTMLConstructionSite::takeAllChildrenAndReparent): Renamed from takeAllChildren. + * html/parser/HTMLConstructionSite.h: + (WebCore::HTMLConstructionSiteTask:Operation): + * html/parser/HTMLTreeBuilder.cpp: + (WebCore::HTMLTreeBuilder::callTheAdoptionAgency): + +2017-02-20 Matthew Hanson + + Rollout r212601. rdar://problem/30339638 + +2017-02-20 Matthew Hanson + + Rollout r212647. rdar://problem/30563318 + +2017-02-20 Matthew Hanson + + Rollout r212538. rdar://problem/30541748 + +2017-02-20 Matthew Hanson + + Merge r212621. rdar://problem/30563318 + + 2017-02-18 Ryosuke Niwa + + REGRESSION(r212218): Assertion failures in and after parserRemoveChild + https://bugs.webkit.org/show_bug.cgi?id=168458 + + Reviewed by Antti Koivisto. + + The bug was caused by parserRemoveChild not preceeding to remove oldChild even when + oldChild had been inserted elsewhere during unload evnets of the disconnected frames. + Fixed the bug by checking this condition and exiting early. + + Also fixed various callers of parserRemoveChild to not call parserAppendChild when + the removed node had already been inserted elsewhere by scripts. + + Tests: fast/parser/adoption-agency-unload-iframe-3.html + fast/parser/adoption-agency-unload-iframe-4.html + fast/parser/xml-error-unload-iframe.html + + * dom/ContainerNode.cpp: + (WebCore::ContainerNode::parserRemoveChild): Exit early when the node had been + inserted elsewhere while firing unload events. Also moved the call to + notifyRemovePendingSheetIfNeeded outside NoEventDispatchAssertion since it can + synchrnously fire a focus event. + (WebCore::ContainerNode::parserAppendChild): Moved adoptNode call to inside + NoEventDispatchAssertion since adoptNode call here should never mutate DOM. + * html/parser/HTMLConstructionSite.cpp: + (WebCore::executeReparentTask): Added an early exit when the node had already been + inserted elsewhere. + (WebCore::executeInsertAlreadyParsedChildTask): Ditto. + * xml/XMLErrors.cpp: + (WebCore::XMLErrors::insertErrorMessageBlock): Ditto. + * xml/parser/XMLDocumentParser.cpp: + (WebCore::XMLDocumentParser::end): Fixed a crash unveiled by one of the test cases. + Exit early when insertErrorMessageBlock detached the parser (by author scripts). + (WebCore::XMLDocumentParser::finish): Keep the parser alive until we exit. + +2017-02-17 Matthew Hanson + + Merge r212554. rdar://problem/30339638 + + 2017-02-16 Brent Fulgham + + RenderView needs to be updated when FrameView changes + https://bugs.webkit.org/show_bug.cgi?id=168481 + + + Reviewed by Andreas Kling. + + The state of the Document's RenderView can get out of sync with the Frame's FrameView. + We need a notification mechanism so that modifications to the Frame's view are properly + relayed to Document so that it can have a correct RenderView. + + * dom/Document.cpp: + (WebCore::Document::didBecomeCurrentDocumentInView): Create an updated render tree (if + one does not already exist). + (WebCore::Document::destroyRenderTree): Remove an incorrect ASSERT. We may enter this + code when the Frame uses 'setView(nullptr)', which happens during certain updates. + * dom/Document.h: + * page/Frame.cpp: + (WebCore::Frame::setView): Destroy the old render tree (if present) before switching to + the new view. Then notify the document that it is now the current document in the new view. + +2017-02-17 Matthew Hanson + ++ Rollout r212488. rdar://problem/29904368 ++ +2017-02-16 Matthew Hanson + + Merge r212518. rdar://problem/30541748 + + 2017-02-16 Daniel Bates + + Remove Chromium-specific code to call FrameLoaderClient::redirectDataToPlugin(nullptr) + https://bugs.webkit.org/show_bug.cgi?id=168417 + + + Reviewed by Brent Fulgham. + + Remove Chromium-specific code that was added in r125500 to call FrameLoaderClient::redirectDataToPlugin(nullptr) + in PluginDocument::detachFromPluginElement(). Calling redirectDataToPlugin() with nullptr was used by the + Chromium port to signify that the plugin document was being destroyed so that they could tear down their + plugin widget. And PluginDocument::detachFromPluginElement() is the only place that calls redirectDataToPlugin() + passing nullptr. No other port made use of this machinery and the Chromium port has long since been removed + from the Open Source WebKit Project. We should remove this code. + + * html/PluginDocument.cpp: + (WebCore::PluginDocumentParser::appendBytes): Pass the plugin widget by reference. + (WebCore::PluginDocument::detachFromPluginElement): Remove call to FrameLoaderClient::redirectDataToPlugin(). + This call was only used by the Chromium port as means to be notified when the plugin document was being + destroyed. No other port made use of this notification or needed such a notification. + * loader/EmptyClients.cpp: Change argument of redirectDataToPlugin() from Widget* to Widget& to convey + that this function always takes a valid Widget. Also remove unnecessary argument name as the data type + of the argument and the name of the function sufficiently describes the purpose of the argument. + * loader/FrameLoaderClient.h: Ditto. + +2017-02-16 Matthew Hanson + + Merge r212350. rdar://problem/30450379 + + 2017-02-14 Brent Fulgham + + Revalidate URL after events that could trigger navigations + https://bugs.webkit.org/show_bug.cgi?id=168071 + + + Reviewed by Ryosuke Niwa. + + When arbitary javascript runs during a load, we should revalidate + the URLs involved to make sure they are still valid. + + Tests: http/tests/plugins/navigation-during-load-embed.html + http/tests/plugins/navigation-during-load.html + + * html/HTMLEmbedElement.cpp: + (WebCore::HTMLEmbedElement::updateWidget): Confirm we are still allowed to + load the URL after executing JS callbacks. + * html/HTMLFrameElementBase.cpp: + (WebCore::HTMLFrameElementBase::isURLAllowed): Split existing function into + existing protected method, and a new public method that checks a passed URL + for validity. + * html/HTMLFrameElementBase.h: + * html/HTMLFrameOwnerElement.h: + (WebCore::HTMLFrameOwnerElement::isURLAllowed): + * html/HTMLObjectElement.cpp: + (WebCore::HTMLObjectElement::updateWidget): Confirm we are still allowed to + load the URL after executing JS callbacks. + * loader/SubframeLoader.cpp: + (WebCore::SubframeLoader::requestFrame): Ditto. + +2017-02-16 Matthew Hanson + + Merge r212335. rdar://problem/29899473 + + 2017-02-14 Brady Eidson + + Unreviewed followup to r212330 to fix Debug builds + + * loader/DocumentThreadableLoader.cpp: + (WebCore::DocumentThreadableLoader::DocumentThreadableLoader): Add call to relaxAdoptionRequirement(). + +2017-02-16 Matthew Hanson + + Merge r212330. rdar://problem/29899473 + + 2017-02-14 Brady Eidson + + Speculative fix for: Crash in DocumentThreadableLoader::redirectReceived. + and https://bugs.webkit.org/show_bug.cgi?id=168337 + + Reviewed by Geoffrey Garen. + + No new tests (Unable to find a reproduction). + + * loader/DocumentThreadableLoader.cpp: + (WebCore::DocumentThreadableLoader::loadRequest): + +2017-02-16 Matthew Hanson + + Merge r212172. rdar://problem/30476807 + + 2017-02-10 Simon Fraser + + REGRESSION (r211845): [ios-simulator] LayoutTest compositing/masks/solid-color-masked.html is a flaky failure + https://bugs.webkit.org/show_bug.cgi?id=168054 + + Reviewed by Tim Horton. + + When adding mask layers, there was an ordering dependency. There was a hack in GraphicsLayerCA::setVisibleAndCoverageRects() + to propagate m_intersectsCoverageRect to masks. However, if GraphicsLayerCA::setVisibleAndCoverageRects() + ran on the masked layer before the mask was added, nothing updated the "m_intersectsCoverageRect" state of the mask layer. + + Fix by explicitly calling setVisibleAndCoverageRects() on the mask layer, passing the same rects and + viewport-constrained state as for its host layer (we already assume that their geometry matches). + + Tested by compositing/masks/solid-color-masked.html + + * platform/graphics/ca/GraphicsLayerCA.cpp: + (WebCore::GraphicsLayerCA::setVisibleAndCoverageRects): + (WebCore::GraphicsLayerCA::recursiveCommitChanges): + +2017-02-16 Matthew Hanson + + Merge r212152. rdar://problem/30459055 + + 2017-02-09 Simon Fraser + + Tiled layers are sometimes left with some tiles when outside the viewport + https://bugs.webkit.org/show_bug.cgi?id=168104 + rdar://problem/30459055 + + Reviewed by Tim Horton. + + When the coverage rect of a TiledBacking goes from a non-empty rect to an empty rect, we + shouldn't just early return from TileGrid::revalidateTiles(), otherwise we are left with some + tiles. Run through the function as normal, which will remove all the tiles for an empty coverage rect. + + Minor logging changes. + + Test: tiled-drawing/tile-coverage-iframe-to-zero-coverage.html + + * platform/graphics/ca/TileGrid.cpp: + (WebCore::TileGrid::revalidateTiles): + +2017-02-16 Matthew Hanson + + Merge r212151. rdar://problem/30090186 + + 2017-02-10 Zalan Bujtas + + Mail hangs when removing multiple rows from large table. + https://bugs.webkit.org/show_bug.cgi?id=168103 + + + Reviewed by Ryosuke Niwa. + + DeleteSelectionCommand::removeNode doesn't actually destroy table structure items, + but instead it removes their content. In order to be able to continue editing the table after + the delete, we need to ensure that its cells' width and height are > 0. Currently we issue layout on + each table item recursively. + This patch delays the layout until after we've finished with the entire subtree delete (10x progression). + + Performance test added. + + * editing/DeleteSelectionCommand.cpp: + (WebCore::DeleteSelectionCommand::insertBlockPlaceholderForTableCellIfNeeded): + (WebCore::DeleteSelectionCommand::removeNodeUpdatingStates): + (WebCore::shouldRemoveContentOnly): + (WebCore::DeleteSelectionCommand::removeNode): + * editing/DeleteSelectionCommand.h: + +2017-02-16 Matthew Hanson + + Merge r211766. rdar://problem/30467124 + + 2017-02-06 Simon Fraser + + Re-land r210095 (avoid a tile revalidation on scale change) + https://bugs.webkit.org/show_bug.cgi?id=167866 + + Reviewed by Tim Horton. + + r210095 was rolled out in r211230 but now that all TileControllers unparent + offscreen tiles, we can roll it back it. + + Also add more Tiling logging. + + * platform/graphics/ca/TileGrid.cpp: + (WebCore::validationPolicyAsString): + (WebCore::TileGrid::setScale): + (WebCore::TileGrid::prepopulateRect): + (WebCore::TileGrid::revalidateTiles): + (WebCore::TileGrid::ensureTilesForRect): + +2017-02-16 Matthew Hanson + + Merge r211501. rdar://problem/29904368 + + 2017-02-01 Antoine Quint + + [mac-wk1] LayoutTest media/modern-media-controls/tracks-support/tracks-support-click-track-in-panel.html is a flaky timeout + https://bugs.webkit.org/show_bug.cgi?id=165319 + + + Reviewed by Dean Jackson. + + Running media/controls/track-menu.html before media/modern-media-controls/tracks-support/tracks- + support-click-track-in-panel.html makes that test time out in all test runs. The root of the issue + is that animations are suspended by media/controls/track-menu.html with a call to + internals.suspendAnimations(), and that state isn't reset with a call to internals.resumeAnimations(). + Then, media/modern-media-controls/tracks-support/tracks-support-click-track-in-panel.html fails because + the selection animation for the tracks panel menu item that is clicked never completes and the delegate + to notify that an item in the tracks panel was selected is never fired, which leads to the test failure. + + We change Internals::suspendAnimations() and Internals::resumeAnimations() to only affect the current + document, rather than calling into AnimationController::suspendAnimations() which would do just that, + but also set a Frame-wide flag that would prevent further animations from running, even in a subsequent + document load. + + * dom/Document.cpp: + (WebCore::Document::prepareForDestruction): Ensure the document that is about to be destroyed is no longer + associated with an AnimationController. + * page/animation/AnimationController.cpp: + (WebCore::AnimationControllerPrivate::ensureCompositeAnimation): Update the animation's suspend state in case + the document its renderer is associated with is suspended. This is required since previously CompositeAnimations + would set their suspend state in their constructor, based on the Frame-wide suspended state, but there is no + document to use as a basis to query its suspended state in that constructor. + (WebCore::AnimationControllerPrivate::animationsAreSuspendedForDocument): + (WebCore::AnimationControllerPrivate::detachFromDocument): + (WebCore::AnimationControllerPrivate::suspendAnimationsForDocument): + (WebCore::AnimationControllerPrivate::resumeAnimationsForDocument): + (WebCore::AnimationControllerPrivate::startAnimationsIfNotSuspended): + (WebCore::AnimationController::animationsAreSuspendedForDocument): + (WebCore::AnimationController::detachFromDocument): + * page/animation/AnimationController.h: + * page/animation/AnimationControllerPrivate.h: + * testing/Internals.cpp: + (WebCore::Internals::animationsAreSuspended): + (WebCore::Internals::suspendAnimations): + (WebCore::Internals::resumeAnimations): + +2017-02-10 Matthew Hanson + + Merge r211495. rdar://problem/30106362 + + 2017-02-01 Jer Noble + + NULL-deref crash in TextTrack::removeCue() + https://bugs.webkit.org/show_bug.cgi?id=167615 + + Reviewed by Eric Carlson. + + Test: http/tests/media/track-in-band-hls-metadata-crash.html + + Follow-up to r211401. When passing around a reference to an object, the assumption is that + the caller is retaining the underlying object. This breaks down for + InbandDataTextTrack::removeDataCue(), which releases its own ownership of the cue object, + then passes the reference to that object to its superclass to do further remove steps. The + retain count of the cue can thus drop to zero within the scope of + InbandTextTrack::removeCue(). Use "take" semantics to remove the cue from the + m_incompleteCueMap without releasing ownership, and pass a reference to that retained object + on to removeCue(), guaranteeing that the cue will not be destroyed until after the + romeveDataCue() method returns. + + * html/track/InbandDataTextTrack.cpp: + (WebCore::InbandDataTextTrack::removeDataCue): + +2017-02-10 Matthew Hanson + + Merge r211650. rdar://problem/30268004 + + 2017-02-03 Jeremy Jones + + Pointer lock events should be delivered directly to the target element + https://bugs.webkit.org/show_bug.cgi?id=167134 + rdar://problem/30268004 + + Reviewed by Dean Jackson. + + pointer-lock/mouse-event-delivery.html: Enabled for mac, added wheel event tests. + + When pointer is locked on an element, route mouse events directly to the target element, instead of + doing the normal event disptach. + + * page/EventHandler.cpp: + (WebCore::EventHandler::handleMousePressEvent): + (WebCore::EventHandler::handleMouseDoubleClickEvent): + (WebCore::EventHandler::handleMouseMoveEvent): + (WebCore::EventHandler::handleMouseReleaseEvent): + (WebCore::EventHandler::handleMouseForceEvent): + (WebCore::EventHandler::handleWheelEvent): + * page/PointerLockController.cpp: + (WebCore::PointerLockController::isLocked): Added. + (WebCore::PointerLockController::dispatchLockedWheelEvent): Added. + * page/PointerLockController.h: + +2017-02-10 Matthew Hanson + + Merge r211375. rdar://problem/30268004 + + 2017-01-30 Ryan Haddad + + Unreviewed, rollout r211235 Pointer lock events should be delivered directly to the target element. + + The LayoutTest for this change is frequently failing. + + * page/EventHandler.cpp: + (WebCore::EventHandler::handleMousePressEvent): + (WebCore::EventHandler::handleMouseDoubleClickEvent): + (WebCore::EventHandler::handleMouseMoveEvent): + (WebCore::EventHandler::handleMouseReleaseEvent): + (WebCore::EventHandler::handleMouseForceEvent): + (WebCore::EventHandler::handleWheelEvent): + * page/PointerLockController.cpp: + (WebCore::PointerLockController::isLocked): Deleted. + (WebCore::PointerLockController::dispatchLockedWheelEvent): Deleted. + * page/PointerLockController.h: + +2017-02-09 Matthew Hanson + + Merge r212029. rdar://problem/30376972 + + 2017-02-09 Chris Dumez + + Make sure Event keeps its current target element alive + https://bugs.webkit.org/show_bug.cgi?id=167885 + + + Reviewed by Brent Fulgham. + + Make sure Event keeps its current target element alive to avoid + crashes if it is accessed by JS after it has been garbage collected. + + Test: fast/events/currentTarget-gc-crash.html + + * dom/Event.cpp: + (WebCore::Event::setCurrentTarget): + * dom/Event.h: + (WebCore::Event::currentTarget): + +2017-02-09 Matthew Hanson + + Merge r211999. rdar://problem/29930443 + + 2017-02-09 Brent Fulgham + + Disconnect shadow children of root when detaching a frame + https://bugs.webkit.org/show_bug.cgi?id=166851 + + + Reviewed by Andy Estes. + + If the root of the tree we are disconnecting has a shadow element, include it in the set of + things to disconnect. + + Tests: fast/shadow-dom/shadow-at-root-during-disconnect.html + + * dom/ContainerNodeAlgorithms.cpp: + (WebCore::disconnectSubframes): + +2017-02-09 Matthew Hanson + + Merge r211382. rdar://problem/29738514 + + 2017-01-30 Myles C. Maxfield + + Correct spacing regression on inter-element complex path shaping on some fonts + https://bugs.webkit.org/show_bug.cgi?id=166013 + + Reviewed by Simon Fraser. + + This patch brings the implementation of ComplexTextController in-line with the + design at https://trac.webkit.org/wiki/ComplexTextController. Previously, + ComplexTextController had a few problems: + - The total width computed by ComplexTextController didn't match the width if + you iterated over the entire string and added up the advances + - FontCascade::getGlyphsAndAdvancesForComplexText() tried to compensate for + the above by construing the concepts of paint advances as distinct from layout + advances + - Initial advances were considered part of layout sometimes and part of painting + other times, depending on which function reports the information + - For RTL runs, the wrong origin was added to the initial advance, and the origin + should have been subtracted instead of added + + This patch exhaustively updates every function in ComplexTextController to be + consistent with the design linked to above. This design solves all of these + problems. + + Tests: ComplexTextControllerTest.InitialAdvanceWithLeftRunInRTL + ComplexTextControllerTest.InitialAdvanceInRTL + ComplexTextControllerTest.InitialAdvanceWithLeftRunInLTR + ComplexTextControllerTest.InitialAdvanceInLTR + ComplexTextControllerTest.InitialAdvanceInRTLNoOrigins + ComplexTextControllerTest.LeadingExpansion + ComplexTextControllerTest.VerticalAdvances + + * platform/graphics/GlyphBuffer.h: + (WebCore::GlyphBuffer::setLeadingExpansion): Deleted. No longer necessary. + (WebCore::GlyphBuffer::leadingExpansion): Deleted. Ditto. + * platform/graphics/cocoa/FontCascadeCocoa.mm: + (WebCore::FontCascade::adjustSelectionRectForComplexText): Removed use of + unnecessary leadingExpansion(). + (WebCore::FontCascade::getGlyphsAndAdvancesForComplexText): This function needs + to compute paint advances, which means that it can't base this information off + of layout advances. This function uses the trick mentioned at the end of the + above link to compute the paint offset of an arbitrary glyph in the middle of + an RTL run. + * platform/graphics/mac/ComplexTextController.cpp: + (WebCore::ComplexTextController::computeExpansionOpportunity): Refactored for + testing. + (WebCore::ComplexTextController::ComplexTextController): Ditto. + (WebCore::ComplexTextController::finishConstruction): Ditto. + (WebCore::ComplexTextController::offsetForPosition): This function operates on + layout advances, and the initial layout advance is already added into the + m_adjustedBaseAdvances vector by adjustGlyphsAndAdvances(). Therefore, there is + no need to add it again here. + (WebCore::ComplexTextController::advance): This function had completely busted + logic about the relationship between initial advances and the first origin in + each run. Because of the fortunate choice of only representing layout advances + in m_adjustedBaseAdvances, this entire block can be removed and the raw paint + initial advance can be reported to the GlyphBuffer. Later in the function, we + have to update the logic about how to compute a paint advance given a layout + advance and some origins. In particular, there are two tricky pieces here: 1. + The layout advance for the first glyph is equal to (initial advance - first + origin + first Core Text advance, so computing the paint offset must cancel out + the initial layout offset, and 2. the last paint advance in a run must actually + end up at the position of the first glyph in the next run, so the next run's + initial advance must be queried. + (WebCore::ComplexTextController::adjustGlyphsAndAdvances): Previously, we + represented an initial advance of a successive run by just adding it to the + previous run's last advance. However, this is incompatible with the new model + presented in the link above, so we remove this section. We also have to add in + the logic that the layout advance for the first glyph is equal to the formula + presented above. + * platform/graphics/mac/ComplexTextController.h: + (WebCore::ComplexTextController::ComplexTextRun::initialAdvance): Adjust comment + to reflect reality. + (WebCore::ComplexTextController::leadingExpansion): Deleted. + +2017-02-09 Matthew Hanson + + Merge r211845. rdar://problem/30187368 + + 2017-02-06 Ryosuke Niwa + + WebContent process repeatedly jetsams on BuzzFeed's Another Round page + https://bugs.webkit.org/show_bug.cgi?id=167830 + + + Reviewed by Simon Fraser. + + The jetsams on https://www.buzzfeed.com/anotherround were caused by WebKit creating the backing store + for every iframe's layer on the page regardless of whether they're in the viewport or not. + + This was caused by GraphicsLayerCA's setVisibleAndCoverageRects not setting CoverageRectChanged on + m_uncommittedChanges on the very first call. Fixed the bug by initializing m_uncommittedChanges + to always have CoverageRectChanged so that the coverage rect would get updated properly. + + Unfortunately, no new tests since somehow the backing store doesn't get created inside the test runner. + + * platform/graphics/ca/GraphicsLayerCA.h: + (WebCore::GraphicsLayerCA): + +2017-02-09 Matthew Hanson + + Merge r211835. rdar://problem/27439617 + + 2017-02-07 Alex Christensen + + Revert r166597 + https://bugs.webkit.org/show_bug.cgi?id=167951 + + Reviewed by Andreas Kling. + + * platform/spi/cf/CFNetworkSPI.h: + Remove now-unused SPI declaration. + +2017-02-09 Matthew Hanson + + Merge r211625. rdar://problem/29168795 + + 2017-02-03 Antti Koivisto + + WebContent crash when pasting into input fields at com.apple.WebCore: WebCore::ResourceRequestBase::url const + 9 + https://bugs.webkit.org/show_bug.cgi?id=167787 + rdar://problem/29168795 + + Reviewed by Andreas Kling. + + No test, don't know how to get here. + + * page/animation/CSSPropertyAnimation.cpp: + (WebCore::crossfadeBlend): Null check. + +2017-02-09 Matthew Hanson + + Merge r211564. rdar://problem/29012252 + + 2017-02-02 Antti Koivisto + + Column progression wrong after enabling pagination on RTL document + https://bugs.webkit.org/show_bug.cgi?id=167733 + + + Reviewed by Zalan Bujtas. + + Column progression depends on document direction but was not updated when direction changed. + + Test: fast/multicol/pagination/pagination-dynamic-rtl.html + + * rendering/RenderBox.cpp: + (WebCore::RenderBox::styleDidChange): + + Update column styles if document direction changes. + +2017-02-06 Matthew Hanson + + Merge r211653. rdar://problem/29872943 + + 2017-02-03 Chris Dumez + + Dismiss HTML form validation popover when pressing Escape key + https://bugs.webkit.org/show_bug.cgi?id=167716 + + + Reviewed by Simon Fraser. + + Dismiss any visible HTML form validation popover when pressing + the Escape key. + + Test: fast/forms/validation-bubble-escape-key-dismiss.html + + * page/EventHandler.cpp: + (WebCore::EventHandler::keyEvent): + * page/ValidationMessageClient.h: + +2017-02-05 Matthew Hanson + + Merge r211659. rdar://problem/28725791 + + 2017-02-03 Jer Noble + + ASSERT in HTMLMediaElement::~HTMLMediaElement + https://bugs.webkit.org/show_bug.cgi?id=167818 + + Reviewed by Brent Fulgham. + + Test: media/audio-dealloc-crash.html + + HTMLMediaElement's MediaElementSession can nominate the HTMLMediaElement itself + to become the playback controls session from inside the HTMLMediaElement destructor. Protect + against this by clearing out the session before calling updatePlaybackControlsManager(). + + * html/HTMLMediaElement.cpp: + (WebCore::HTMLMediaElement::~HTMLMediaElement): + +2017-02-05 Matthew Hanson + + Merge r211676. rdar://problem/30229990 + + 2017-02-04 Chris Dumez + + Unreviewed, fix mistake in comment added in r211569. + + * history/PageCache.cpp: + (WebCore::PageCache::removeAllItemsForPage): + +2017-02-05 Matthew Hanson + + Merge r211569. rdar://problem/30229990 + + 2017-02-02 Chris Dumez + + [Crash] com.apple.WebKit.WebContent at WebKit: WebKit::WebPage::fromCorePage() + https://bugs.webkit.org/show_bug.cgi?id=167738 + + + Reviewed by Andreas Kling. + + Upon destruction of a Page, we destroy the BackForwardClient, which is supposed + to keep track of HistoryItems associated to this particular page and remove them + from the PageCache. Given the crash trace, the issue seems to be that some + HistoryItems associated with the Page sometimes linger in the PageCache *after* + the Page has been destroyed, which leads to crashes later on when pruning the + PageCache. + + In order to make the process more robust, this patch refactors the code so that + the Page is now in charge of removing all its associated HistoryItems from the + PageCache instead of relying on the BackForwardClient. Also, instead of having + the Page keep track of which HistoryItems are associated with it (which is + error prone), we now scan all PageCache entries instead to find which ones are + associated with the Page. While this is in theory slower, this is much safer + and in practice not an issue because the PageCache usually has 3-5 entries. + + No new tests, could not reproduce. + + * history/CachedPage.cpp: + (WebCore::CachedPage::CachedPage): + * history/CachedPage.h: + (WebCore::CachedPage::page): + * history/PageCache.cpp: + (WebCore::PageCache::removeAllItemsForPage): + * history/PageCache.h: + * page/Page.cpp: + (WebCore::Page::~Page): + +2017-01-31 Matthew Hanson + + Merge r211387. rdar://problem/29500273 + + 2017-01-30 Simon Fraser + + [iOS] position:fixed inside touch-scrollable overflow is mispositioned + https://bugs.webkit.org/show_bug.cgi?id=167604 + rdar://problem/29500273 + + Reviewed by Zalan Bujtas. + + For layers inside touch-scrollable overflow, RenderLayerBacking::computeParentGraphicsLayerRect() needs + to account for the offset from the ancestor compositing layer's origin, to handle scrollable elements with + box-shadow, for example. + + Also make the compositing log output a little easier to read. + + Test: compositing/scrolling/fixed-inside-scroll.html + + * rendering/RenderLayerBacking.cpp: + (WebCore::RenderLayerBacking::computeParentGraphicsLayerRect): + * rendering/RenderLayerCompositor.cpp: + (WebCore::RenderLayerCompositor::logLayerInfo): + +2017-01-31 Matthew Hanson + + Merge r211337. rdar://problem/30126535 + + 2017-01-28 Zalan Bujtas + + Resolve beforeChild's render tree position before calling addChildIgnoringContinuation. + https://bugs.webkit.org/show_bug.cgi?id=167540 + + + Reviewed by Simon Fraser. + + Use the actual render tree position for the beforeChild when inside a flow thread. + + Test: fast/multicol/assert-on-continuation-with-spanner.html + + * rendering/RenderBlockFlow.cpp: + (WebCore::RenderBlockFlow::addChild): + * rendering/RenderInline.cpp: + (WebCore::RenderInline::addChild): + * rendering/RenderMultiColumnFlowThread.cpp: + (WebCore::RenderMultiColumnFlowThread::resolveMovedChild): + +2017-01-31 Matthew Hanson + + Merge r211305. rdar://problem/29320059 + + 2017-01-27 Simon Fraser + + Element with a backdrop-filter and a mask may not correctly mask the backdrop + https://bugs.webkit.org/show_bug.cgi?id=167456 + rdar://problem/29320059 + + Reviewed by Antoine Quint. + + If a layer had a backdrop filter, but also corner radii that triggered using a mask layer, + then the call to updateClippingStrategy() in GraphicsLayerCA::updateBackdropFiltersRect() would + set the backdrop layer's mask, but GraphicsLayerCA::updateMaskLayer() would promptly then set + the mask layer back to nil. + + Fix by having GraphicsLayerCA::updateMaskLayer() put the mask on the structural layer, if there + is one. We always have a structural layer with backdrops, so this will mask both the layer + and the backdrop. + + Test: css3/filters/backdrop/backdrop-filter-uneven-corner-radii.html + + * platform/graphics/ca/GraphicsLayerCA.cpp: + (WebCore::GraphicsLayerCA::updateMaskLayer): + * platform/graphics/mac/WebLayer.mm: + (-[CALayer _descriptionWithPrefix:]): Dump the mask layer. + +2017-01-26 Matthew Hanson + + Merge r211235. rdar://problem/30058933 + + 2017-01-26 Jeremy Jones + + Pointer lock events should be delivered directly to the target element + https://bugs.webkit.org/show_bug.cgi?id=167134 + + Reviewed by Jon Lee. + + pointer-lock/mouse-event-delivery.html: Enabled for mac, added wheel event tests. + + When pointer is locked on an element, route mouse events directly to the target element, instead of + doing the normal event disptach. + + * page/EventHandler.cpp: + (WebCore::EventHandler::handleMousePressEvent): + (WebCore::EventHandler::handleMouseDoubleClickEvent): + (WebCore::EventHandler::handleMouseMoveEvent): + (WebCore::EventHandler::handleMouseReleaseEvent): + (WebCore::EventHandler::handleMouseForceEvent): + (WebCore::EventHandler::handleWheelEvent): + * page/PointerLockController.cpp: + (WebCore::PointerLockController::isLocked): Added. + (WebCore::PointerLockController::dispatchLockedWheelEvent): Added. + * page/PointerLockController.h: + +2017-01-26 Matthew Hanson + + Merge r211230. rdar://problem/30009849 + + 2017-01-26 Commit Queue + + Unreviewed, rolling out r210095. + https://bugs.webkit.org/show_bug.cgi?id=167464 + + broke tiling on mac (Requested by thorton on #webkit). + + Reverted changeset: + + "TileGrid revalidates tiles twice during flush, first with + wrong visible rect" + https://bugs.webkit.org/show_bug.cgi?id=166406 + http://trac.webkit.org/changeset/210095 + +2017-01-26 Matthew Hanson + + Merge r211201. rdar://problem/30134866 + + 2017-01-25 Ryosuke Niwa + + Crash under DOMSelection::deleteFromDocument() + https://bugs.webkit.org/show_bug.cgi?id=167232 + + Reviewed by Chris Dumez. + + The crash was caused by DOMSelection's deleteFromDocument() mutating contents inside the user-agent + shadow tree of an input element when the text field is readonly. Fixed the bug by exiting early + whenever the selection is inside a shadow tree since getSelection().getRangeAt(0) always returns + a range outside the input element or any shadow tree for that matter. + + New behavior matches that of Gecko. The working draft spec of which I'm the editor states that + deleteFromDocument() must invoke Range's deleteContents() on the associated range, which is + the collapsed range returned by getSelection().getRangeAt(0) in the spec: + https://www.w3.org/TR/2016/WD-selection-api-20160921/#widl-Selection-deleteFromDocument-void + And Range's deleteContents() immediately terminates in step 1 when start and end are identical: + https://dom.spec.whatwg.org/commit-snapshots/6b7621282c2e3b222ac585650e484abf4c0a416b/ + + Note that Range's DOM mutating methods are not available inside an user-agent shadow tree because + WebKit never returns a Range whose end boundary points are inside the tree to author scripts. + Editing commands (ones executable from document.execCommand) that mutate DOM like this check whether + the content is editable or not. Since VisibleSelection's validate() function makes sure the selection + is either entirely within or outside of an root editable element (editing host in the W3C spec lingo), + editing commands should never mutate a random node inside an user-agent shadow tree. + + Test: editing/selection/deleteFromDocument-shadow-tree-crash.html + + * page/DOMSelection.cpp: + (WebCore::DOMSelection::deleteFromDocument): + +2017-01-26 Andreas Kling + + Branch-specific fix for a crash seen after merging r201777. + + + Reviewed by Andy Estes. + + Add null checking of the FrameView in Document::destroyRenderTree() before + calling functions on it. This is not necessary in trunk, as the FrameView + is guaranteed to be present there. + + FrameView can be missing on the branch, since render trees for page cached documents + are destroyed when leaving the page cache, not when entering it (trunk behavior.) + When leaving the page cache, the FrameView is already detached, hence the bug. + + * dom/Document.cpp: + (WebCore::Document::destroyRenderTree): + +2017-01-25 Matthew Hanson + + Merge 210777. rdar://problem/30186526 + + 2017-01-15 Andreas Kling + + FrameView shouldn't keep dangling pointers into dead render trees. + + + Reviewed by Antti Koivisto. + + Added some pretty paranoid assertions to FrameView that verify all of its raw pointers + into the render tree are gone after the render tree has been destroyed. + They immediately caught two bugs, also fixed in this patch. + + * page/FrameView.h: + * page/FrameView.cpp: + (WebCore::FrameView::willDestroyRenderTree): + (WebCore::FrameView::didDestroyRenderTree): Added these two callbacks for before/after + Document tears down its render tree. The former clears the layout root, and detaches + custom scrollbars. The latter contains a bunch of sanity assertions that pointers into + the now-destroyed render tree are gone. + + * dom/Document.cpp: + (WebCore::Document::destroyRenderTree): Notify FrameView before/after teardown. + + * page/animation/AnimationController.h: + * page/animation/AnimationController.cpp: + (WebCore::AnimationController::hasAnimations): Added a helper to check if there are + any composite animations around, as these contain raw pointers to renderers. + + * rendering/RenderElement.cpp: + (WebCore::RenderElement::willBeRemovedFromTree): + (WebCore::RenderElement::willBeDestroyed): Moved slow repaint object unregistration + from willBeRemovedFromTree() to willBeDestroyed(). The willBeRemovedFromTree() callback + is skipped as an optimization during full tree teardown, but willBeDestroyed() always + gets called. This fixes a bug where we'd fail to remove dangling pointers. + +2017-01-24 Matthew Hanson + + Merge r211007. rdar://problem/28620919 + + 2017-01-20 Brady Eidson + + Require a button press on a gamepad for them to be exposed to the DOM. + and https://bugs.webkit.org/show_bug.cgi?id=167272 + + Reviewed by Alex Christensen. + + Test: gamepad/gamepad-visibility-1.html + + * Modules/gamepad/GamepadManager.cpp: + (WebCore::GamepadManager::platformGamepadInputActivity): + * Modules/gamepad/GamepadManager.h: + + * platform/gamepad/GamepadProvider.cpp: + (WebCore::GamepadProvider::dispatchPlatformGamepadInputActivity): + * platform/gamepad/GamepadProvider.h: + (WebCore::GamepadProvider::~GamepadProvider): Deleted. + (WebCore::GamepadProvider::isMockGamepadProvider): Deleted. + + * platform/gamepad/GamepadProviderClient.h: + + * platform/gamepad/cocoa/GameControllerGamepad.h: + * platform/gamepad/cocoa/GameControllerGamepad.mm: + (WebCore::GameControllerGamepad::setupAsExtendedGamepad): + (WebCore::GameControllerGamepad::setupAsGamepad): + + * platform/gamepad/cocoa/GameControllerGamepadProvider.h: + * platform/gamepad/cocoa/GameControllerGamepadProvider.mm: + (WebCore::GameControllerGamepadProvider::gamepadHadInput): + (WebCore::GameControllerGamepadProvider::inputNotificationTimerFired): + + * platform/gamepad/mac/HIDGamepad.cpp: + (WebCore::HIDGamepad::valueChanged): + * platform/gamepad/mac/HIDGamepad.h: + + * platform/gamepad/mac/HIDGamepadProvider.cpp: + (WebCore::HIDGamepadProvider::valuesChanged): + (WebCore::HIDGamepadProvider::inputNotificationTimerFired): + * platform/gamepad/mac/HIDGamepadProvider.h: + + * testing/MockGamepadProvider.cpp: + (WebCore::MockGamepadProvider::setMockGamepadButtonValue): + (WebCore::MockGamepadProvider::gamepadInputActivity): + * testing/MockGamepadProvider.h: + +2017-01-20 Matthew Hanson + + Merge r210945. rdar://problem/28745101 + + 2017-01-19 Jer Noble + + CRASH at WebCore::TrackListBase::remove + https://bugs.webkit.org/show_bug.cgi?id=167217 + + Reviewed by Brent Fulgham. + + Test: media/media-source/media-source-error-crash.html + + In very specific conditions, a HTMLMediaElement backed by a MediaSource can try to remove + the same track from its track list twice. If there are two SourceBuffers attached to a + HTMLMediaElement, and one has not yet been initialized, when the second fails to parse an + appended buffer after receiving an initialization segment, the HTMLMediaElement will remove + all its tracks in mediaLoadingFailed(), then MediaSource object itself will attempt remove + the same track in removeSourceBuffer(). + + Solving this the safest way possible: bail early from TrackListBase if asked to remove a + track which the list does not contain. + + * html/track/TrackListBase.cpp: + (TrackListBase::remove): + +2017-01-20 Matthew Hanson + + Merge r210939. rdar://problem/29885052 + + 2017-01-19 Chris Dumez + + Make sure HTML validation bubble gets dismissed when its associated element's frame gets detached + https://bugs.webkit.org/show_bug.cgi?id=167215 + + + Reviewed by Andreas Kling. + + Make sure HTML validation bubble gets dismissed when its associated + element's frame gets detached and that we do not crash. + + Tests: fast/forms/validation-message-detached-iframe.html + fast/forms/validation-message-detached-iframe2.html + + * dom/Document.cpp: + (WebCore::Document::prepareForDestruction): + * page/ValidationMessageClient.h: + +2017-01-12 Matthew Hanson + + Merge r210447. rdar://problem/29872292 + + 2017-01-06 Chris Dumez + + [Form Validation] "character" in maxlength validation message should be singular when maxlength is 1 + https://bugs.webkit.org/show_bug.cgi?id=166712 + + + Reviewed by Darin Adler. + + Fix validation message to use singular form of "character" when maxLength value is 1. + + Test: fast/forms/validation-message-maxLength.html + + * English.lproj/Localizable.strings: + * English.lproj/Localizable.stringsdict: Added. + * WebCore.xcodeproj/project.pbxproj: + * extract-localizable-strings.pl: + * platform/LocalizedStrings.cpp: + * platform/LocalizedStrings.h: + * platform/cocoa/LocalizedStringsCocoa.mm: + (WebCore::localizedNString): + (WebCore::localizedString): + (WebCore::validationMessageTooLongText): + +2017-01-12 Matthew Hanson + + Merge r210536. rdar://problem/29939970 + + 2017-01-09 Chris Dumez + + REGRESSION(r189555): ImageDocument title no longer includes the size of the image + https://bugs.webkit.org/show_bug.cgi?id=166876 + + + Reviewed by Tim Horton. + + ImageDocument title no longer included the size of the image after r189555. + This is because Document::setTitle() is a no-op if the document does not + have a element. To address the issue, we now include a + element in ImageDocuments so that their title element properly gets added + to it. + + Test: fast/images/imageDocument-title.html + + * html/ImageDocument.cpp: + (WebCore::ImageDocument::createDocumentStructure): + +2017-01-12 Matthew Hanson + + Merge r210679. rdar://problem/29910273 + + 2017-01-12 Youenn Fablet + + OneDrive application crashes upon launch + https://bugs.webkit.org/show_bug.cgi?id=166975 + + Reviewed by Brady Eidson. + + Checking whether load is terminated just after calling ResourceLoader::willSendRequestInternal. + The reason is that delegate call may actually cancel the load at that point. + + * loader/SubresourceLoader.cpp: + (WebCore::SubresourceLoader::willSendRequestInternal): + +2017-01-12 Matthew Hanson + + Merge r210378. rdar://problem/29024384 + + 2017-01-05 Zalan Bujtas + + Start hittesting a clean tree in RenderEmbeddedObject::isReplacementObscured + https://bugs.webkit.org/show_bug.cgi?id=166743 + + + Reviewed by Simon Fraser. + + Unable to reproduce. + + * rendering/RenderEmbeddedObject.cpp: + (WebCore::RenderEmbeddedObject::isReplacementObscured): + +2017-01-12 Matthew Hanson + + Merge r210095. rdar://problem/29912221 + + 2016-12-21 Tim Horton + + TileGrid revalidates tiles twice during flush, first with wrong visible rect + https://bugs.webkit.org/show_bug.cgi?id=166406 + + Reviewed by Simon Fraser. + + No new tests; existing tests cover this code, this is just a perf win, + specifically reducing the amount of layer churn during zooming. + + * platform/graphics/ca/TileGrid.cpp: + (WebCore::TileGrid::setScale): + Schedule a revalidation, which will happen later in the same flush, + instead of doing it immediately. Doing it immediately is problematic, + because we're currently in the middle of a GraphicsLayer tree flush, + and don't have the complete picture of the new state yet. We're guaranteed + to get the new scale *before* the flush calls revalidateTiles. + +2017-01-12 Matthew Hanson + + Merge r210131. rdar://problem/29633667 + + 2016-12-23 Ryosuke Niwa + + Eliminate the use of lastChild in TextIterator + https://bugs.webkit.org/show_bug.cgi?id=166456 + + Reviewed by Antti Koivisto. + + Just use the node we just existed in TextIterator::exitNode and in emitting additional new line + to eliminate the use of Node::lastChild. + + Also initialize member variables in the declaration instead of the constructor to modernize the code. + + * editing/TextIterator.cpp: + (WebCore::TextIterator::TextIterator): + (WebCore::TextIterator::advance): + (WebCore::TextIterator::exitNode): + * editing/TextIterator.h: + +2017-01-12 Matthew Hanson + + Merge r210094. rdar://problem/29912214 + + 2016-12-21 Tim Horton + + TileGrid creates new tiles when there are recyclable tiles about to be removed + https://bugs.webkit.org/show_bug.cgi?id=166408 + + Reviewed by Simon Fraser. + + No new tests; existing tests cover this code, this is just a perf win, + specifically reducing the amount of layer churn during zooming. + + * platform/graphics/ca/TileGrid.cpp: + (WebCore::TileGrid::revalidateTiles): + Remove all the tiles that will be removed first, then add new tiles. + Strictly ordering it this way means that tiles will be removed, go into + the LayerPool, then be pulled back out of the LayerPool to sit in the + newly-covered areas. Previously, we would sometimes make new layers + for newly-covered areas, and then remove unneeded but otherwise recyclable + tiles, which would then just go sit in the LayerPool (and often get + pruned, wastefully). + +2017-01-06 Matthew Hanson + + Merge r210221. rdar://problem/29449474 + + 2017-01-01 Jeff Miller + + Update user-visible copyright strings to include 2017 + https://bugs.webkit.org/show_bug.cgi?id=166278 + + Reviewed by Dan Bernstein. + + * Info.plist: + +2017-01-05 Matthew Hanson + + Merge r210361. rdar://problem/29870245 + + 2017-01-05 Chris Dumez + + Form validation: Align email validation with the latest HTML specification + https://bugs.webkit.org/show_bug.cgi?id=166697 + + + Reviewed by Alex Christensen. + + Align email validation with the latest HTML specification: + - https://html.spec.whatwg.org/#valid-e-mail-address + + It particular, the following changes were made: + - The first and last character of the domain now needs to be a letter or a digit + - Parts of the domain can only be 63 characters in length + + No new tests, extended existing test. + + * html/EmailInputType.cpp: + +2017-01-05 Matthew Hanson + + Merge r210360. rdar://problem/19595567 + + 2017-01-05 Enrica Casucci + + Support File Promise during drag for macOS. + https://bugs.webkit.org/show_bug.cgi?id=165204 + rdar://problem/19595567 + + Reviewed by Tim Horton. + + Adds the support for handling File Promise type during + drag. DragData now has the knowledge of the NSFilesPromisePboardType and + checks for the data type during drag. + + * page/mac/DragControllerMac.mm: + (WebCore::DragController::dragOperation): + * platform/DragData.h: + (WebCore::DragData::setFileNames): + (WebCore::DragData::fileNames): + * platform/mac/DragDataMac.mm: + (WebCore::DragData::containsFiles): + (WebCore::DragData::numberOfFiles): + (WebCore::DragData::asFilenames): + (WebCore::DragData::containsCompatibleContent): + (WebCore::DragData::containsPromise): + (WebCore::DragData::asURL): + +2017-01-05 Matthew Hanson + + Merge r210359. rdar://problem/29882478 + + 2017-01-05 Per Arne Vollan + + [Win] Compile error. + https://bugs.webkit.org/show_bug.cgi?id=166726 + + Reviewed by Alex Christensen. + + Add include folder. + + * CMakeLists.txt: + +2017-01-05 Babak Shafiei + + Merge r210372. + + 2017-01-05 Chris Dumez + + Turn preferLowPowerWebGLRendering setting on by default + https://bugs.webkit.org/show_bug.cgi?id=166737 + + + Reviewed by Dean Jackson. + + Temporarily turn preferLowPowerWebGLRendering setting on by default until + we deal better with WebGL content in background tabs. + + * page/Settings.in: + +2017-01-04 Babak Shafiei + + Build fix for r210288. + +2017-01-04 Babak Shafiei + + Merge patch for r210288. + + 2016-12-22 Brent Fulgham + + Correct DOMWindow handling during FrameLoader::clear + https://bugs.webkit.org/show_bug.cgi?id=166357 + + + Reviewed by Andy Estes. + + Make sure that we always clean up the DOM window when clearing Window properties, even if the document will + remain in the page cache. Since 'clearWindowShell' is only used in FrameLoader, divide it's beahvior into + two steps: + + 1. Rename 'clearWindowShell' to 'clearWIndowShellsNotMatchingDOMWindow' to better describe its function. + Switch to a modern C++ loop. Do not switch to the new DOMWindow here, but detach and clear existing + DOMWindow connections. + + 2. Add a new method 'setDOMWindowForWindowShell'. Complete switch to the new DOMWindow. + + This change allows us to disconnect the old DOMWindow, perform the 'setDocument(nullptr)' operation, and then + connect to the new Window without leaving the loader in an inconsistent state. + + * loader/bindings/js/ScriptController.cpp: + (WebCore::clearWindowShellsNotMatchingDOMWindow): Renamed from 'clearWindowShell' + (WebCore::setDOMWindowForWindowShell): Added. + * loader/bindings/js/ScriptController.h: + * loader/FrameLoader.cpp: + (WebCore::FrameLoader::clear): Revise to use the new two-step DOMWindow switch logic. + +2017-01-04 Babak Shafiei + + Merge r210273. + + 2017-01-04 Tim Horton + + Provide a setting for clients to always prefer low-power WebGL + https://bugs.webkit.org/show_bug.cgi?id=166675 + + + Reviewed by Dan Bernstein. + + No new tests; as noted in r204664, we don't know how to reliably test + automatic graphics switching. One could use the manual test introduced + in that commit; after this commit, with the setting switched on, on a + dual-GPU machine that is actively using integrated graphics, that test + should return the same result for both contexts. + + * page/Settings.in: + Add a setting to prefer low-power WebGL. + + * html/canvas/WebGLRenderingContextBase.cpp: + (WebCore::WebGLRenderingContextBase::create): + If said setting is enabled, set preferLowPowerToHighPerformance. + +2017-01-03 Babak Shafiei + + Merge r210112. + + 2016-12-22 Daniel Bates + + Bypass pop-up blocker from cross-origin or sandboxed frame + https://bugs.webkit.org/show_bug.cgi?id=166290 + + + Reviewed by Darin Adler. + + Tests: fast/events/popup-blocked-from-sandboxed-frame-via-window-open-named-sibling-frame.html + fast/events/popup-blocked-from-sandboxed-frame-via-window-open-named-sibling-frame2.html + fast/events/popup-blocked-from-unique-frame-via-window-open-named-sibling-frame.html + + * page/DOMWindow.cpp: + (WebCore::DOMWindow::open): Use FrameLoader::findFrameForNavigation() to find the + target frame to navigate with respect to the active document just as we do in WebCore::createWindow(). + +2017-01-03 Babak Shafiei + + Merge r210122. + + 2016-12-22 Brent Fulgham + + Nested calls to setDocument can omit firing 'unload' events + https://bugs.webkit.org/show_bug.cgi?id=166422 + + + Reviewed by Alex Christensen. + + Test: fast/loader/nested-document-handling.html + + Only allow a single document change to be taking place during a given runloop cycle. + + * bindings/js/ScriptController.cpp: + (WebCore::ScriptController::executeIfJavaScriptURL): Block script changing the document + when we are in the middle of changing the document. + * page/Frame.cpp: + (WebCore::Frame::setDocument): Keep track of document change state. + * page/Frame.h: + +2017-01-03 Babak Shafiei + + Merge r210120. + + 2016-12-22 Zalan Bujtas + + Do not destroy the RenderNamedFlowFragment as leftover anonymous block. + https://bugs.webkit.org/show_bug.cgi?id=166436 + rdar://problem/29772233 + + Reviewed by Simon Fraser. + + When as the result of certain style change, the generated anonymous block is not needed anymore, we + move its descendants up to the parent and destroy the generated box. While RenderNamedFlowFragment is a generated + block, the cleanup code should just ignore it the same way we ignore boxes like multicolumn, mathml etc. + + Test: fast/regions/flow-fragment-as-anonymous-block-crash.html + + * rendering/RenderObject.h: + (WebCore::RenderObject::isAnonymousBlock): + +2016-12-19 Babak Shafiei + + Build fix for rdar://problem/29737358. + +2016-12-19 Babak Shafiei + + Merge r209990. + + 2016-12-18 Brent Fulgham + + Side effects while restting form elements + https://bugs.webkit.org/show_bug.cgi?id=165959 + + + Reviewed by Anders Carlsson. + + JavaScript logic can run while resetting FormElement objects. This can + lead to unintended side-effets and other unwanted behavior. We should + protect these elements during the reset. + + Test: fast/html/form-mutate.html + + * html/HTMLFormElement.cpp: + (WebCore::HTMLFormElement::HTMLFormElement): Switch to C++11 initialization. + (WebCore::HTMLFormElement::reset): Protect elements until the reset + operation is finished. + (WebCore::HTMLFormElement::resetAssociatedFormControlElements): Added to share + code with 'resumeFromDocument'. + (WebCore::HTMLFormElement::resumeFromDocument): Protect elements until the + reset operation is finished. + +2016-12-15 Babak Shafiei + + Merge r204618. + + 2016-08-18 Dean Jackson + + Support passing preferLowPowerToHighPerformance and failIfMajorPerformanceCaveat + https://bugs.webkit.org/show_bug.cgi?id=160982 + + + Reviewed by Simon Fraser. + + Update WebGLContextAttributes to be compliant with the specification, + by adding preferLowPowerToHighPerformance and failIfMajorPerformanceCaveat. + They are not implemented yet, so asking the created context what + values it used should give the default. + + Test: fast/canvas/webgl/context-creation-attributes.html + + * html/canvas/WebGLContextAttributes.cpp: + (WebCore::WebGLContextAttributes::preferLowPowerToHighPerformance): + (WebCore::WebGLContextAttributes::setPreferLowPowerToHighPerformance): + (WebCore::WebGLContextAttributes::failIfMajorPerformanceCaveat): + (WebCore::WebGLContextAttributes::setFailIfMajorPerformanceCaveat): + * html/canvas/WebGLContextAttributes.h: + * html/canvas/WebGLContextAttributes.idl: + * html/canvas/WebGLRenderingContextBase.cpp: + (WebCore::WebGLRenderingContextBase::create): Deleted. + * platform/graphics/GraphicsContext3D.h: + (WebCore::GraphicsContext3D::Attributes::Attributes): Deleted. + +2016-12-15 Babak Shafiei + + Merge r209819. + + 2016-12-14 Alex Christensen + + REGRESSION (r209776): [ios-simulator] LayoutTest http/tests/xmlhttprequest/on-network-timeout-error-during-preflight.html is timing out + https://bugs.webkit.org/show_bug.cgi?id=165836 + + Reviewed by Brady Eidson. + + * loader/CrossOriginAccessControl.cpp: + (WebCore::createAccessControlPreflightRequest): + Use the platform default timeout for CORS preflight requests. + +2016-12-15 Babak Shafiei + + Merge r209776. + + 2016-12-13 Alex Christensen + + Restore NSURLRequest's default time interval to match behavior before NSURLSession adoption + https://bugs.webkit.org/show_bug.cgi?id=165821 + + + Reviewed by Brady Eidson. + + Before adopting NSURLSession, iOS used CFURLConnection, not NSURLConnection. + iOS used to have a default timeout of INT_MAX and it now has a default timeout of 0, which means use the + default NSURLRequest timeout, which is 60 seconds. This is not enough for some slow mobile networks, + so we want to match behavior of our CFURLConnection code here. + + * platform/network/ResourceRequestBase.cpp: + Use INT_MAX as the default timeout of requests on iOS. + +2016-12-07 Matthew Hanson + + Merge r209462. rdar://problem/29556990 + + 2016-12-06 Geoffrey Garen + + performance.now() should truncate to 100us + https://bugs.webkit.org/show_bug.cgi?id=165503 + + + Reviewed by Mark Lam. + + * page/Performance.cpp: + (WebCore::Performance::reduceTimeResolution): + +2016-12-01 Matthew Hanson + + Merge r209145. rdar://problem/29404231 + + 2016-11-30 Brent Fulgham + + Use 'childOfType' template when retrieving Shadow DOM elements + https://bugs.webkit.org/show_bug.cgi?id=165145 + + + Reviewed by Antti Koivisto. + + Tests: fast/shadow-dom/color-input-element-shadow-manipulation.html + fast/shadow-dom/file-input-element-shadow-manipulation.html + fast/shadow-dom/keygen-shadow-manipulation.html + fast/shadow-dom/media-shadow-manipulation.html + fast/shadow-dom/range-input-element-shadow-manipulation.html + fast/shadow-dom/textarea-shadow-manipulation.html + + Switch to using 'childOfType' when retrieving Shadow DOM elements, rather + than relying on expected element positions, as these can be changed by + JavaScript. + + Drive by fix: Make more use of is<> and downcast<> templates rather than blindly casting. + + * dom/Element.h: + (WebCore::Element::isUploadButton): Added. + (WebCore::Element::isSliderContainerElement): Added. + * html/ColorInputType.cpp: + (WebCore::ColorInputType::shadowColorSwatch): Use 'childOfType' rather than assuming + the first child is the one we want. + * html/FileInputType.cpp: + (isType): Added. + (WebCore::FileInputType::disabledAttributeChanged): Use 'childOfType' rather than assuming + the first child is the one we want. + (WebCore::FileInputType::multipleAttributeChanged): Ditto. + * html/HTMLKeygenElement.cpp: + (WebCore::HTMLKeygenElement::shadowSelect): Ditto. + * html/HTMLMediaElement.cpp: + (WebCore::HTMLMediaElement::mediaControls): Ditto. + (WebCore::HTMLMediaElement::hasMediaControls): Ditto. + * html/HTMLTextAreaElement.cpp: + (WebCore::HTMLTextAreaElement::innerTextElement): Ditto. + * html/RangeInputType.cpp: + (WebCore::RangeInputType::sliderTrackElement): Ditto. + * html/shadow/SliderThumbElement.h: + (isType): Added. + * svg/SVGUseElement.cpp: + (WebCore::SVGUseElement::targetClone): Use 'childOfType' rather than assuming + the first child is the one we want. + +2016-12-01 Matthew Hanson + + Merge r208745. rdar://problem/29277336 + + 2016-11-14 Brent Fulgham + + Correct handling of changing input type + https://bugs.webkit.org/show_bug.cgi?id=164759 + + + Reviewed by Darin Adler. + + Test: fast/forms/search-cancel-button-change-input.html + + It is possible for JavaScript to change the type property of an input field. WebKit + needs to gracefully handle this case. + + Add a type traits specialization so we can properly downcast InputType elements. + Use this to only call search functions on actual search input types. + + * html/HTMLInputElement.cpp: + (WebCore::HTMLInputElement::onSearch): Only perform search functions if the + input type is actually a search field. + * html/InputType.h: Add type traits specialization for 'downcast' template. + * html/SearchInputType.h: Ditto. + +2016-12-01 Matthew Hanson + + Merge r208629. rdar://problem/29277337 + + 2016-11-11 Brent Fulgham + + Unreviewed build fix after r208628 + + * bindings/js/SerializedScriptValue.cpp: + (WebCore::CloneDeserializer::readTerminal): Cast pointer arithmetic to + uint32_t to avoid warning. + +2016-11-14 Matthew Hanson + + Merge r208691. rdar://problem/29250304 + + 2016-11-14 David Kilzer + + Bug 164702: WebContent crash due to checked unsigned overflow in WebCore: WebCore::RenderLayerCompositor::requiresCompositingLayer const + 1104 + + + + Reviewed by Darin Adler. + + Test: inspector/layers/layers-compositing-reasons.html + + * rendering/RenderLayerCompositor.cpp: + (WebCore::RenderLayerCompositor::requiresCompositingForCanvas): + Don't composite if the canvas area overflows. + +2016-11-03 Matthew Hanson + + Merge r208328. rdar://problem/29084886 + + 2016-11-03 Dan Bernstein + + REGRESSION (r206247): Painting milestones can be delayed until the next layer flush + https://bugs.webkit.org/show_bug.cgi?id=164340 + + + Reviewed by Tim Horton. + + To give WebKit a chance to deliver the painting milestones to its client after the commit, + we must tell it about them before or during the commit. To that end, we should not defer + the call to firePaintRelatedMilestonesIfNeeded until after the commit. + + * rendering/RenderLayerCompositor.cpp: + (WebCore::RenderLayerCompositor::RenderLayerCompositor): Removed + m_paintRelatedMilestonesTimer initializer. + (WebCore::RenderLayerCompositor::didPaintBacking): Call + FrameView::firePaintRelatedMilestonesIfNeeded directly from here. + (WebCore::RenderLayerCompositor::paintRelatedMilestonesTimerFired): Deleted. + * rendering/RenderLayerCompositor.h: + +2016-11-03 Matthew Hanson + + Merge r208307. rdar://problem/29078457 + + 2016-11-02 David Kilzer + + Bug 164333: Add logging for "WebKit encountered an internal error" messages due to Network process crashes + + + + Reviewed by Alex Christensen. + + * page/DiagnosticLoggingKeys.cpp: + (WebCore::DiagnosticLoggingKeys::networkProcessCrashedKey): + - Add implementation for new key method. + * page/DiagnosticLoggingKeys.h: + (WebCore::DiagnosticLoggingKeys::networkProcessCrashedKey): + - Add declaration for new key method. + +2016-11-03 Matthew Hanson + + Merge r208286. rdar://problem/28634857 + + 2016-11-02 David Kilzer + + Add logging for "WebKit encountered an internal error" messages + + + + Reviewed by Alex Christensen. + + * page/DiagnosticLoggingKeys.cpp: + (WebCore::DiagnosticLoggingKeys::internalErrorKey): + (WebCore::DiagnosticLoggingKeys::invalidSessionIDKey): + (WebCore::DiagnosticLoggingKeys::createSharedBufferFailedKey): + (WebCore::DiagnosticLoggingKeys::synchronousMessageFailedKey): + - Add implementations for new key methods. + + * page/DiagnosticLoggingKeys.h: + (WebCore::DiagnosticLoggingKeys::internalErrorKey): + (WebCore::DiagnosticLoggingKeys::invalidSessionIDKey): + (WebCore::DiagnosticLoggingKeys::createSharedBufferFailedKey): + (WebCore::DiagnosticLoggingKeys::synchronousMessageFailedKey): + - Add declarations for new key methods. + +2016-11-01 Matthew Hanson + + Rollout r208255. rdar://problem/28962886 + +2016-11-01 Matthew Hanson + + Rollout r208173. rdar://problem/28962886 + +2016-11-01 Matthew Hanson + + Merge r206637. rdar://problem/28718754 + + 2016-09-30 Said Abou-Hallawa + + Unreviewed, fix 32-bit build. + + * loader/cache/CachedImage.cpp: + (WebCore::CachedImage::decodedSizeChanged): + +2016-10-31 Matthew Hanson + + Merge r208151. rdar://problem/29032335 + + 2016-10-31 Jer Noble + + Opt-out of AVPlayer automatic sleep disabling + https://bugs.webkit.org/show_bug.cgi?id=163983 + + Reviewed by Eric Carlson. + + In addition to the DisplaySleepDisabler, notify the MediaPlayerPrivateAVFoundationObjC object whether + it should disable display sleep. Provide all the necessary boilerplate to allow the media player private + to query the HTMLMediaPlayer so that the correct value can be set on AVPlayer upon creation. + + * html/HTMLMediaElement.cpp: + (WebCore::HTMLMediaElement::updateSleepDisabling): + * html/HTMLMediaElement.h: + * platform/graphics/MediaPlayer.cpp: + (WebCore::MediaPlayer::setShouldDisableSleep): + (WebCore::MediaPlayer::shouldDisableSleep): + * platform/graphics/MediaPlayer.h: + (WebCore::MediaPlayerClient::mediaPlayerShouldDisableSleep): + * platform/graphics/MediaPlayerPrivate.h: + (WebCore::MediaPlayerPrivateInterface::setShouldDisableSleep): + * platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.h: + * platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm: + (WebCore::MediaPlayerPrivateAVFoundationObjC::createAVPlayer): + (WebCore::MediaPlayerPrivateAVFoundationObjC::setShouldDisableSleep): + + Drive-by fix: Re-organize the contents of AVFoundationSPI.h so that there's a single top-level + #if USE(APPLE_INTERNAL_SDK) statement, rather than that conditional being sprinkled about the + file. + + * platform/spi/mac/AVFoundationSPI.h: + +2016-10-31 Matthew Hanson + + Merge r208168. rdar://problem/28962886 + + 2016-10-28 Brent Fulgham + + Do a better job of protecting Frame objects in the context of JavaScript calls + https://bugs.webkit.org/show_bug.cgi?id=164163 + + + Reviewed by Darin Adler. + + * editing/AlternativeTextController.cpp: + (WebCore::AlternativeTextController::respondToUnappliedSpellCorrection): Protected the Frame. + * editing/Editor.cpp: + (WebCore::Editor::setTextAsChildOfElement): Ditto. + * editing/EditorCommand.cpp: + (WebCore::executeSwapWithMark): Ditto. + * editing/TypingCommand.cpp: + (WebCore::TypingCommand::deleteKeyPressed): Ditto. + (WebCore::TypingCommand::forwardDeleteKeyPressed): Ditto. + * editing/mac/EditorMac.mm: + (WebCore::Editor::replaceNodeFromPasteboard): Ditto. + * page/ContextMenuController.cpp: + (WebCore::ContextMenuController::contextMenuItemSelected): Ditto. + * page/DOMSelection.cpp: + (WebCore::DOMSelection::collapse): Ditto. + (WebCore::DOMSelection::collapseToEnd): Ditto. + (WebCore::DOMSelection::collapseToStart): Ditto. + (WebCore::DOMSelection::setBaseAndExtent): Ditto. + (WebCore::DOMSelection::setPosition): Ditto. + (WebCore::DOMSelection::modify): Ditto. + (WebCore::DOMSelection::extend): Ditto. + (WebCore::DOMSelection::addRange): Ditto. + (WebCore::DOMSelection::deleteFromDocument): Ditto. + * page/DragController.cpp: + (WebCore::setSelectionToDragCaret): Ditto. + (WebCore::DragController::startDrag): Ditto. + * page/Frame.cpp: + (WebCore::Frame::checkOverflowScroll): Ditto. + * page/TextIndicator.cpp: + (WebCore::TextIndicator::createWithRange): Ditto. + +2016-10-31 Matthew Hanson + + Merge r208003. rdar://problem/28811878 + + 2016-10-27 Brent Fulgham + + Prevent hit tests from being performed on an invalid render tree + https://bugs.webkit.org/show_bug.cgi?id=163877 + + + Reviewed by Simon Fraser. + + Changeset r200971 added code to ensure that layout is up-to-date before hit testing, but did + so only for the main frame. It was still possible to enter cross-frame hit testing with a + subframe needing style recalc. In that situation, the subframe's updateLayout() would get + called, which could trigger a compositing change that marked the parent frame as needing style + recalc. A subsequent layout on the parent frame (for example by hit testing traversing into + a second subframe) could then mutate the parent frame's layer tree while hit testing was + traversing it. + + This patch modifies the hit test logic to ensure that a recursive layout is performed so that + we always perform hit tests on a clean set of frames. It also adds some assertions to warn + us if we encounter this invalid state. + + Tested by fast/layers/prevent-hit-test-during-layout.html. + + * dom/Document.cpp: + (WebCore::Document::scheduleStyleRecalc): Assert that we are not hit testing + during style recalculation. + * page/EventHandler.cpp: + (WebCore::EventHandler::hitTestResultAtPoint): Ensure that we have a clean render tree + when hit testing. + * page/FrameView.cpp: + (WebCore::FrameView::setNeedsLayout): Assert that we are not in the process of hit testing + when we schedule a layout. + * rendering/RenderView.cpp: + (WebCore::RenderView::hitTest): Mark RenderView as in an active hit test. + * rendering/RenderView.h: + +2016-10-31 Matthew Hanson + + Merge r206802. rdar://problem/28409525 + + 2016-10-28 Said Abou-Hallawa + + The dragged image should be the current frame only of the animated image + https://bugs.webkit.org/show_bug.cgi?id=162109 + + Instead of creating an NSImage with all the frames for the dragImage, + create an NSImage with the current frame only. + + * bindings/objc/DOM.mm: + (-[DOMElement image]): Call the Image function with its new name. + (-[DOMElement _imageTIFFRepresentation]): Ditto. + * dom/DataTransferMac.mm: + (WebCore::DataTransfer::createDragImage): Call snapshotNSImage() to create the dragImage. + * editing/cocoa/HTMLConverter.mm: + (fileWrapperForElement): Call the Image function with its new name. + * platform/graphics/BitmapImage.cpp: + (WebCore::BitmapImage::framesNativeImages): Added. + * platform/graphics/BitmapImage.h: + * platform/graphics/Image.h: + (WebCore::Image::framesNativeImages): Added. + (WebCore::Image::nsImage): Rename getNSImage() to nsImage(). + (WebCore::Image::snapshotNSImage): Returns the NSImage of the current frame. + (WebCore::Image::tiffRepresentation): Rename getTIFFRepresentation() to tiffRepresentation(). + (WebCore::Image::getNSImage): Deleted. + (WebCore::Image::getTIFFRepresentation): Deleted. + * platform/graphics/mac/ImageMac.mm: + (WebCore::BitmapImage::tiffRepresentation): Rename getTIFFRepresentation() to tiffRepresentation(). + (WebCore::BitmapImage::nsImage): Rename getNSImage() to nsImage(). + (WebCore::BitmapImage::snapshotNSImage): Returns the NSImage of the current frame. + (WebCore::BitmapImage::getTIFFRepresentation): Deleted. + (WebCore::BitmapImage::getNSImage): Deleted. + * platform/mac/CursorMac.mm: + (WebCore::createCustomCursor): Call snapshotNSImage() since the cursor does not animate anyway. + * platform/mac/DragImageMac.mm: + (WebCore::createDragImageFromImage): Use snapshotNSImage() for the dragImage. + * platform/mac/PasteboardMac.mm: + (WebCore::Pasteboard::write): Call the Image function with its new name. + +2016-10-27 Daniel Bates + + Merge r207848. rdar://problem/28216276 + + 2016-10-25 Daniel Bates + + REGRESSION (r178265): XSS Auditor fails to block document.write() of incomplete tag + https://bugs.webkit.org/show_bug.cgi?id=163978 + + + Reviewed by Darin Adler. + + During the tokenization process of an HTML tag the start and end positions of each of its + attributes is tracked so that the XSS Auditor can request a snippet around a suspected + injected attribute. We need to take care to consider document.write() boundaries when + tracking the start and end positions of each HTML tag and attribute so that the XSS Auditor + receives the correct snippet. Following r178265 we no longer consider document.write() + boundaries when tracking the start and end positions of attributes. So, the substring + represented by the start and end positions of an attribute may correspond to some other + attribute in the tag. Therefore the XSS Auditor may fail to block an injection because the + snippet it requested may not be the snippet that it intended to request. + + Tests: http/tests/security/xssAuditor/dom-write-location-dom-write-open-img-onerror.html + http/tests/security/xssAuditor/dom-write-location-open-img-onerror.html + http/tests/security/xssAuditor/nested-dom-write-location-open-img-onerror.html + + * html/parser/HTMLSourceTracker.cpp: + (WebCore::HTMLSourceTracker::startToken): Set the attribute base offset to be the token + start position. + (WebCore::HTMLSourceTracker::source): Use the specified attribute start position as-is. We no + longer adjust it here because it was adjusted with respect to the attribute base offset, which + takes into account document.write() boundaries. + * html/parser/HTMLToken.h: + (WebCore::HTMLToken::setAttributeBaseOffset): Added. + (WebCore::HTMLToken::beginAttribute): Subtract attribute base offset from the specified offset. + (WebCore::HTMLToken::endAttribute): Ditto. + * html/parser/HTMLTokenizer.h: + (WebCore::HTMLTokenizer::setTokenAttributeBaseOffset): Added. + +2016-10-26 Matthew Hanson + + Merge r207692. rdar://problem/28810751 + + 2016-10-20 Dean Jackson + + SVG should not paint selection within a mask + https://bugs.webkit.org/show_bug.cgi?id=163772 + + + Reviewed by Simon Fraser. + + When masking content, we shouldn't paint the text + selection as we are rendering into the masking + offscreen buffer. + + Test: svg/masking/mask-should-not-paint-selection.html + + * rendering/PaintPhase.h: Add a new behavior - PaintBehaviorSkipSelectionHighlight. + * rendering/svg/SVGInlineTextBox.cpp: + (WebCore::SVGInlineTextBox::paint): Don't update the selectionStyle if + PaintBehaviorSkipSelectionHighlight is true. + * rendering/svg/SVGRenderingContext.cpp: + (WebCore::SVGRenderingContext::renderSubtreeToImageBuffer): Add PaintBehaviorSkipSelectionHighlight + to the PaintInfo. + +2016-10-26 Matthew Hanson + + Merge r207661. rdar://problem/28857478 + + 2016-10-21 Jer Noble + + CRASH in SourceBuffer::sourceBufferPrivateDidReceiveSample + 2169 + https://bugs.webkit.org/show_bug.cgi?id=163735 + + Reviewed by Eric Carlson. + + Test: media/media-source/media-source-sample-wrong-track-id.html + + When SourceBuffer receives a sample in sourceBufferPrivateDidReceiveSample() containing + a trackID not previously seen in an initialization segment, it creates a default TrackBuffer + object to contain that track's samples. One of the fields in TrackBuffer, description, is + normally filled out when an initialization segment is received, but with this default + TrackBuffer, it's still null when it's checked later in sourceBufferPrivateDidReceiveSample(). + + Rather than adding a null-check on trackBuffer.description, drop any sample that has a + trackID which was not present during a previous initialization segment. + + * Modules/mediasource/SourceBuffer.cpp: + (WebCore::SourceBuffer::sourceBufferPrivateDidReceiveSample): + +2016-10-26 Matthew Hanson + + Merge r207631. rdar://problem/28810750 + + 2016-10-20 Zalan Bujtas + + Stop searching for first-letter containers at multi-column boundary. + https://bugs.webkit.org/show_bug.cgi?id=163739 + + + We should not cross the multi-column boundary while searching for the first-letter container. + While moving first-letter renderers to a multi-column parent, it could result in finding the wrong + container and end up adding a new wrapper under the original container (from where we are moving the renderers). + + Reviewed by David Hyatt. + + Test: fast/css-generated-content/first-letter-move-to-multicolumn-crash.html + + * rendering/RenderBoxModelObject.cpp: + (WebCore::RenderBoxModelObject::moveChildrenTo): + * rendering/RenderTextFragment.cpp: + (WebCore::RenderTextFragment::blockForAccompanyingFirstLetter): + +2016-10-26 Matthew Hanson + + Merge r207477. rdar://problem/28810756 + + 2016-10-18 Brent Fulgham + + Correct Document::removeAllEventListeners + https://bugs.webkit.org/show_bug.cgi?id=163558 + + + Reviewed by Chris Dumez. + + Tested by fast/dom/node-move-to-new-document-crash-main.html. + + * dom/Document.cpp: + (WebCore::Document::removeAllEventListeners): Clear out the wheel and + touch event targets when clearing all data. + +2016-10-26 Matthew Hanson + + Merge r207221. rdar://problem/28894492 + + 2016-10-12 Brent Fulgham + + [WebGL] Revise vertex array attribute checks to account for lazy memory allocation. + https://bugs.webkit.org/show_bug.cgi?id=163149 + + + Reviewed by Dean Jackson. + + Tested by fast/canvas/webgl/webgl-drawarrays-crash-2.html + + * html/canvas/WebGLRenderingContextBase.cpp: + (WebCore::WebGLRenderingContextBase::validateVertexAttributes): + +2016-10-20 Matthew Hanson + + Merge r206771. rdar://problem/28811939 + + 2016-10-04 Wenson Hsieh + + Media controls are displayed in the incorrect state momentarily after switching between tabs playing media + https://bugs.webkit.org/show_bug.cgi?id=162766 + + + Reviewed by Jer Noble. + + When showing Now Playing controls for a media session, we should first set up the Now Playing info and + playback state before telling MediaRemote to make the session visible. This is WebKit work in ensuring that + when switching Now Playing sessions by switching tabs, we do not first display an invalid Now Playing state + before updating to the expected state. + + Adds 2 new WebKit API tests in NowPlayingControlsTests: NowPlayingControlsHideAfterShowingClearsInfo and + NowPlayingControlsClearInfoAfterSessionIsNoLongerValid. + + * platform/audio/PlatformMediaSessionManager.h: + (WebCore::PlatformMediaSessionManager::lastUpdatedNowPlayingTitle): + (WebCore::PlatformMediaSessionManager::lastUpdatedNowPlayingDuration): + (WebCore::PlatformMediaSessionManager::lastUpdatedNowPlayingElapsedTime): + (WebCore::PlatformMediaSessionManager::hasActiveNowPlayingSession): Deleted. + * platform/audio/mac/MediaSessionManagerMac.h: + * platform/audio/mac/MediaSessionManagerMac.mm: + (WebCore::MediaSessionManagerMac::updateNowPlayingInfo): + +2016-10-20 Matthew Hanson + + Merge r207275. rdar://problem/28810752 + + 2016-10-12 Zalan Bujtas + + RenderRubyRun should not mark child renderers dirty at the end of layout. + https://bugs.webkit.org/show_bug.cgi?id=163359 + + + Reviewed by David Hyatt. + + The current layout logic does not support marking renderers dirty for subsequent layouts. + Layout needs to exit with a clean tree. + Should relayoutChild be insufficient, we could also mark the base/text dirty for the justified content. + + Test: fast/ruby/rubyrun-has-bad-child.html + + * rendering/RenderBlockLineLayout.cpp: + (WebCore::RenderBlockFlow::updateRubyForJustifiedText): + * rendering/RenderRubyRun.cpp: + (WebCore::RenderRubyRun::layout): + (WebCore::RenderRubyRun::layoutBlock): + * rendering/RenderRubyRun.h: + +2016-10-20 Matthew Hanson + + Merge r206712. rdar://problem/28216065 + + 2016-10-01 Simon Fraser + + Bad cast when CSS position programmatically changed from -webkit-sticky to fixed + https://bugs.webkit.org/show_bug.cgi?id=160826 + + Reviewed by Zalan Bujtas. + + If a scrolling state tree node changed type (e.g. from sticky to fixed), we'd fail + to recreate the node so keep a node with the wrong type. + + Fix by destroying the node and making a new one with a new ID in this case. The + new ID is necessary to ensure that the scrolling tree is updated. + + Test: fast/scrolling/sticky-to-fixed.html + + * page/scrolling/ScrollingStateTree.cpp: + (WebCore::ScrollingStateTree::nodeTypeAndParentMatch): + (WebCore::ScrollingStateTree::attachNode): + (WebCore::ScrollingStateTree::stateNodeForID): + * page/scrolling/ScrollingStateTree.h: + +2016-10-20 Matthew Hanson + + Merge r206217. rdar://problem/28811877 + + 2016-09-21 Daniel Bates + + REGRESSION (r201090): Setting style.webkitTextSizeAdjust does not change text change on iPad + https://bugs.webkit.org/show_bug.cgi?id=162227 + + + Reviewed by Simon Fraser. + + The CSS property -webkit-text-size-adjust should be respected on all iOS devices. Following + r201090 we respect it only on iPhone and in iPhone-apps run on iPad. + + Tests: fast/text-autosizing/ios/ipad/programmatic-text-size-adjust.html + fast/text-autosizing/ios/ipad/text-size-adjust-inline-style.html + fast/text-autosizing/ios/programmatic-text-size-adjust.html + fast/text-autosizing/ios/text-size-adjust-inline-style.html + fast/text-autosizing/text-size-adjust-inline-style.html + + * css/parser/CSSParser.cpp: + (WebCore::isValidKeywordPropertyAndValue): Remove unused code to validate -webkit-text-size-adjust. + This code is never used because -webkit-text-size-adjust is a value property (since it accepts a + as a value and CSSParserFastPaths::isKeywordPropertyID(CSSPropertyWebkitTextSizeAdjust) + returns false). That is, it is not a keyword property. + (WebCore::CSSParser::parseValue): Always enable the -webkit-text-size-adjust CSS property when + building for iOS regardless of whether Settings:textAutosizingEnabled() is enabled. + +2016-10-20 Matthew Hanson + + Merge r204637. rdar://problem/28216256 + + 2016-08-16 Simon Fraser + + Rename didLayout(LayoutMilestones) to didReachLayoutMilestone(), and related WK2 functions + https://bugs.webkit.org/show_bug.cgi?id=160923 + + Reviewed by Tim Horton. + + didLayout(LayoutMilestones) -> didReachLayoutMilestone(LayoutMilestones) + dispatchDidLayout(LayoutMilestones) -> dispatchDidReachLayoutMilestone(LayoutMilestones) + + * dom/Document.cpp: + (WebCore::Document::setVisualUpdatesAllowed): + * loader/EmptyClients.h: + * loader/FrameLoader.cpp: + (WebCore::FrameLoader::didReachLayoutMilestone): + (WebCore::FrameLoader::didLayout): Deleted. + * loader/FrameLoader.h: + * loader/FrameLoaderClient.h: + * page/FrameView.cpp: + (WebCore::FrameView::fireLayoutRelatedMilestonesIfNeeded): + (WebCore::FrameView::firePaintRelatedMilestonesIfNeeded): + * page/LayoutMilestones.h: Formatting + * page/Page.cpp: + (WebCore::Page::addRelevantRepaintedObject): + +2016-10-20 Matthew Hanson + + Merge r207157. rdar://problem/28857500 + + 2016-10-11 Daniel Bates + + [iOS] Sandbox QuickLook previews + https://bugs.webkit.org/show_bug.cgi?id=163240 + + + Fix bad merge following r207151. + + * platform/network/cf/ResourceResponse.h: Define m_isQuickLook. + +2016-10-20 Matthew Hanson + + Merge r206132. rdar://problem/28634856 + + 2016-09-19 Anders Carlsson + + Suppress JavaScript prompts early on in certain cases + https://bugs.webkit.org/show_bug.cgi?id=162243 + rdar://problem/27661602 + + Reviewed by Geoffrey Garen. + + Export symbols needed by WebKit2. + + * loader/FrameLoader.h: + * loader/FrameLoaderStateMachine.h: + +2016-10-20 Matthew Hanson + + Merge r205326. rdar://problem/28476952 + + 2016-09-01 Ricky Mondello + + YouTube Flash plug-in replacement facility should not insert showinfo=0 into iframe URLs + https://bugs.webkit.org/show_bug.cgi?id=161478 + + + Reviewed by Eric Carlson. + + * Modules/plugins/YouTubePluginReplacement.cpp: + (WebCore::YouTubePluginReplacement::youTubeURLFromAbsoluteURL): Stop adding the query parameter. + +2016-10-20 Matthew Hanson + + Merge r205306. rdar://problem/28476952 + + 2016-09-01 Ricky Mondello + + YouTube Flash plug-in replacement facility should more gracefully handle malformed queries + https://bugs.webkit.org/show_bug.cgi?id=161476 + + + Reviewed by Eric Carlson. + + Some YouTube Flash embeds use '&' instead of '?' to start the query portion of the URL. Before this patch, + our implementation discards all parts of the path after the '&', which could drop important query information + like the start time for the video. This patch treats anything after that '&' as a "malformed query" and uses + it as the query to restore to the transformed URL if there was no actual query in the original URL. + + * Modules/plugins/YouTubePluginReplacement.cpp: + (WebCore::processAndCreateYouTubeURL): Add an out-parameter for the path after the first ampersand. + (WebCore::YouTubePluginReplacement::youTubeURLFromAbsoluteURL): If the input URL had no query, append + the possibly malformed one found after the first ampersand to the replacement URL. + +2016-10-20 Matthew Hanson + + Merge r205274. rdar://problem/28476952 + + 2016-08-31 Ricky Mondello + + Enable the YouTube Flash plug-in replacement behavior on all Cocoa ports + https://bugs.webkit.org/show_bug.cgi?id=161453 + + + Reviewed by Eric Carlson. + + Now that we have some tests for the URL transformation logic (r205212) and the ability to enable the YouTube + Flash plug-in replacement behavior independently from the QuickTime plug-in replacement behavior (r205214 and + r205271), enable the YouTube Flash plug-in replacement behavior for Cocoa ports. We can and will continue to + improve it. + + * page/Settings.cpp: Enable the feature for PLATFORM(COCOA), rather than just PLATFORM(IOS). + +2016-10-20 Matthew Hanson + + Merge r205271. rdar://problem/28476952 + + 2016-08-31 Ricky Mondello + + Break pluginReplacementEnabled into youTubeFlashPluginReplacementEnabled and quickTimePluginReplacementEnabled + https://bugs.webkit.org/show_bug.cgi?id=161424 + + + Reviewed by Dean Jackson. + + Replace the single pluginReplacementEnabled setting with individual settings for the YouTube Flash plug-in + behavior and the QuickTime plug-in behavior. Unless otherwise noted, this change copies the existing plumbing + for pluginReplacementEnabled and renames it twice. The default values for these settings remain the same. + + * Modules/plugins/PluginReplacement.h: + (WebCore::ReplacementPlugin::ReplacementPlugin): Augment the constructor. + (WebCore::ReplacementPlugin::isEnabledBySettings): Added. + * Modules/plugins/QuickTimePluginReplacement.h: Declare a static member function. + * Modules/plugins/QuickTimePluginReplacement.mm: + (WebCore::QuickTimePluginReplacement::registerPluginReplacement): Properly create a ReplacementPlugin instance. + (WebCore::QuickTimePluginReplacement::isEnabledBySettings): Added. + * Modules/plugins/YouTubePluginReplacement.cpp: + (WebCore::YouTubePluginReplacement::registerPluginReplacement): Properly create a ReplacementPlugin instance. + (WebCore::YouTubePluginReplacement::isEnabledBySettings): Added. + * Modules/plugins/YouTubePluginReplacement.h: Declare a static member function. + * html/HTMLPlugInElement.cpp: + (WebCore::HTMLPlugInElement::requestObject): Ask the ReplacementPlugin whether it's enabled, rather than assume + all plug-in replacement is guarded by a single run-time setting. + * page/Settings.cpp: Declare values for defaults for both settings. + * page/Settings.in: Declare two settings. + * testing/InternalSettings.cpp: + (WebCore::InternalSettings::Backup::Backup): Handle both settings. + (WebCore::InternalSettings::Backup::restoreTo): Ditto. + (WebCore::InternalSettings::setQuickTimePluginReplacementEnabled): Added. + (WebCore::InternalSettings::setYouTubeFlashPluginReplacementEnabled): Added. + (WebCore::InternalSettings::setPluginReplacementEnabled): Deleted. + * testing/InternalSettings.h: Duplicate and rename. + * testing/InternalSettings.idl: Ditto. + +2016-10-20 Matthew Hanson + + Merge r205214. rdar://problem/28476952 + + 2016-08-30 Ricky Mondello + + "pluginReplacementEnabled" should be a Setting, not a RuntimeEnabledFeature + https://bugs.webkit.org/show_bug.cgi?id=161416 + + + Reviewed by Simon Fraser. + + Mostly mechanical. Tested by running LayoutTests/plugins/quicktime-plugin-replacement.html and manually toggling + defaultPluginReplacementEnabled and observing a behavior change. + + * bindings/generic/RuntimeEnabledFeatures.cpp: + (WebCore::RuntimeEnabledFeatures::reset): Purged of the pluginReplacementEnabled setting. + * bindings/generic/RuntimeEnabledFeatures.h: + (WebCore::RuntimeEnabledFeatures::setPluginReplacementEnabled): Deleted. + (WebCore::RuntimeEnabledFeatures::pluginReplacementEnabled): Deleted. + * html/HTMLPlugInElement.cpp: + (WebCore::HTMLPlugInElement::requestObject): Use the setting. + * page/Settings.cpp: Supply different values for iOS and other platforms, matching the RuntimeEnabledFeature values, + enabled for iOS and disabled otherwise. + * page/Settings.in: Declare the setting. + * testing/InternalSettings.cpp: + (WebCore::InternalSettings::Backup::Backup): Use the setting. + (WebCore::InternalSettings::Backup::restoreTo): Ditto. + (WebCore::InternalSettings::setPluginReplacementEnabled): Ditto. + * testing/InternalSettings.h: Can now throw an exception, like other Settings-backed members. + * testing/InternalSettings.idl: Declare this as possibly throwing an exception. + +2016-10-20 Matthew Hanson + + Merge r205212. rdar://problem/28476952 + + 2016-08-30 Ricky Mondello + + YouTubePluginReplacementTest's URL transformation logic should have tests + https://bugs.webkit.org/show_bug.cgi?id=161406 + + + Reviewed by Eric Carlson. + + Refactor most of YouTubePluginReplacement::youTubeURL into a static method that can be used by TestWebKitAPI. + + * Modules/plugins/YouTubePluginReplacement.cpp: + (WebCore::YouTubePluginReplacement::youTubeURL): Now implemented in terms of youTubeURLFromAbsoluteURL. + (WebCore::YouTubePluginReplacement::youTubeURLFromAbsoluteURL): Absorbs most of youTubeURL. + * Modules/plugins/YouTubePluginReplacement.h: Declare a public method, for the benefit of testing. + * WebCore.xcodeproj/project.pbxproj: Make some heads private for TestWebKitAPI's benefit. + +2016-10-12 Matthew Hanson + + Merge r206975. rdar://problem/28545012 + + 2016-10-07 Ryosuke Niwa + + REGRESSION(r165103): labels list doesn't get invalidated when other lists are invalidated at document level + https://bugs.webkit.org/show_bug.cgi?id=163145 + + Reviewed by Darin Adler. + + The bug was caused by Document::invalidateNodeListAndCollectionCaches removing all node lists regardless + of whether they have been invalidated or not. + + Fixed the bug by removing only those node lists that got invalidated via LiveNodeList::invalidateCache. + + Test: fast/dom/NodeList/form-labels-length.html + + * dom/Document.cpp: + (WebCore::Document::Document): + (WebCore::Document::unregisterNodeListForInvalidation): Removed the conditional which allowed removal to + happen while m_listsInvalidatedAtDocument is empty inside invalidateNodeListAndCollectionCaches. + * dom/Document.h: + * dom/Node.cpp: + (WebCore::Document::invalidateNodeListAndCollectionCaches): Just remove the node lists being invalidated via + LiveNodeList's invalidateCache, which calls unregisterNodeListForInvalidation, instead of removing them all. + We make a copy of the list of node lists into a local vector because mutating HashMap while iterating over it + is not a safe operation. + +2016-10-12 Matthew Hanson + + Merge r205197. rdar://problem/28481424 + + 2016-08-30 Brent Fulgham + + Use of uninitialised memory in TransformationMatrx::blend4() + https://bugs.webkit.org/show_bug.cgi?id=134621 + + + Reviewed by Dean Jackson. + + Change is based on the Blink change (patch by ): + + + TransformationMatrix::blend() was attempting to blend between non-invertable + matricies. This resulted in garbage stack variables being used. + This patch ensures that blend() will fall back to a 50% step interpolation + when one of the sides are not invertable. + + Tested by new TransformationMatrix test in TestWebKitAPI. + + * platform/graphics/transforms/TransformationMatrix.cpp: + (WebCore::TransformationMatrix::blend2): Properly handle failure in the + decompose method calls. + (WebCore::TransformationMatrix::blend4): Ditto. + +2016-10-12 Matthew Hanson + + Merge r205190. rdar://problem/28545010 + + 2016-08-30 Youenn Fablet + + [Fetch API] Blob not found URL should result in a network error + https://bugs.webkit.org/show_bug.cgi?id=161381 + + Reviewed by Sam Weinig. + + Covered by rebased and updated tests. + + Raising a network error if no blob can be found from the URL. + It is no longer notified by a 404 response. + + Updated FileReaderLoader to generate the correct exception. + + Made some clean-up in the code, in particular adding an enum class for BlobResourceHandle errors. + + * fileapi/FileReaderLoader.cpp: + (WebCore::FileReaderLoader::didFail): + (WebCore::FileReaderLoader::toErrorCode): + (WebCore::FileReaderLoader::httpStatusCodeToErrorCode): + * fileapi/FileReaderLoader.h: + * platform/network/BlobResourceHandle.cpp: + (WebCore::BlobResourceHandle::loadResourceSynchronously): + (WebCore::BlobResourceHandle::doStart): + (WebCore::BlobResourceHandle::didGetSize): + (WebCore::BlobResourceHandle::readSync): + (WebCore::BlobResourceHandle::readFileSync): + (WebCore::BlobResourceHandle::readAsync): + (WebCore::BlobResourceHandle::didOpen): + (WebCore::BlobResourceHandle::didRead): + (WebCore::BlobResourceHandle::failed): + (WebCore::BlobResourceHandle::notifyResponse): + (WebCore::BlobResourceHandle::notifyResponseOnError): + (WebCore::BlobResourceHandle::notifyFail): + * platform/network/BlobResourceHandle.h: + +2016-10-12 Matthew Hanson + + Merge r204631. rdar://problem/28481427 + + 2016-08-19 Chris Dumez + + DumpRenderTree crashed in com.apple.WebCore: WebCore::DOMWindow::resetDOMWindowProperties + 607 + https://bugs.webkit.org/show_bug.cgi?id=160983 + + + Reviewed by Brent Fulgham. + + Update DOMWindow::frameDestroyed() to ref the window object as the crash + traces seem to indicate it can get destroyed during the execution of this + method. Also update the code in the ~Frame destructor to not iterate over + the list of FrameDestructionObservers because observers remove themselves + from the list when they get destroyed. + + No new tests, do not know how to reproduce. + + * page/DOMWindow.cpp: + (WebCore::DOMWindow::frameDestroyed): + * page/Frame.cpp: + (WebCore::Frame::~Frame): + +2016-10-12 Matthew Hanson + + Merge r204266. rdar://problem/28216261 + + 2016-08-08 John Wilander + + Popups opened from a sandboxed iframe should themselves be sandboxed + https://bugs.webkit.org/show_bug.cgi?id=134850 + + + Reviewed by Brent Fulgham. + + Test: http/tests/security/window-opened-from-sandboxed-iframe-should-inherit-sandbox.html + + * loader/FrameLoader.cpp: + (WebCore::FrameLoader::continueLoadAfterNewWindowPolicy): + Now copies the opener's frame loader effective sandbox flags to the + new frame loader. + +2016-10-11 Matthew Hanson + + Merge r203383. rdar://problem/28216264 + + 2016-07-18 Brent Fulgham + + Don't associate form-associated elements with forms in other trees. + https://bugs.webkit.org/show_bug.cgi?id=119451 + + + Change is based on the Blink change (patch by ): + + + Reviewed by Chris Dumez. + + Prevent elements from being associated with forms that are not part of the same home subtree. + This brings us in line with the WhatWG HTML specification as of September, 2013. + + Tests: fast/forms/image-disconnected-during-parse.html + fast/forms/input-disconnected-during-parse.html + + * dom/Element.h: + (WebCore::Node::rootElement): Added. + * html/FormAssociatedElement.cpp: + (WebCore::FormAssociatedElement::insertedInto): If the element is associated with a form that + is not part of the same tree, remove the association. + * html/HTMLImageElement.cpp: + (WebCore::HTMLImageElement::insertedInto): Ditto. + +2016-09-28 Babak Shafiei + + Merge r206518. rdar://problem/28505032 + + 2016-09-28 Jer Noble + + [MSE][Mac] In SourceBufferPrivateAVFObjC::abort(), support reseting parser to the last appended initialization segment. + https://bugs.webkit.org/show_bug.cgi?id=135164 + + Reviewed by Eric Carlson. + + Test: media/media-source/media-source-abort-resets-parser.html + + Use the -[AVStreamDataParser appendStreamData:withFlags:] to implement "resetting" the parser. In this case, + the parser isn't explicitly reset during resetParserState(), but rather a flag is set so that the next append + signals a data discontinuity, and the parser is reset at that point. + + Because a previous append operation may be in-flight during this abort(), care must be taken to invalidate any + operations which may have already started on a background thread. So SourceBufferPrivateAVFObjC will use a + separate WeakPtrFactory for its append operations, will invalidate any outstanding WeakPtrs during an abort(), + and will block until the previous append() operation completes. + + This will require the WebAVStreamDataParserListener object to occasionally have it's WeakPtr pointing back to the + SourceBufferPrivateAVFObjC to be reset after an abort(), so make that ivar an @property. Rather than passing a + RetainPtr to itself in all the callbacks it handles, the WebAVStreamDataParserListener can just pass in a copy + of its own WeakPtr (which may be invalidated during an abort()). + + Break the distinct operations of "abort()" and "resetParserState()" into their own methods in SourceBufferPrivate + and all its subclasses. + + * Modules/mediasource/SourceBuffer.cpp: + (WebCore::SourceBuffer::resetParserState): + (WebCore::SourceBuffer::abortIfUpdating): + * platform/graphics/SourceBufferPrivate.h: + * platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.h: + * platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.mm: + (-[WebAVStreamDataParserListener streamDataParser:didParseStreamDataAsAsset:]): + (-[WebAVStreamDataParserListener streamDataParser:didParseStreamDataAsAsset:withDiscontinuity:]): + (-[WebAVStreamDataParserListener streamDataParser:didFailToParseStreamDataWithError:]): + (-[WebAVStreamDataParserListener streamDataParser:didProvideMediaData:forTrackID:mediaType:flags:]): + (-[WebAVStreamDataParserListener streamDataParser:didReachEndOfTrackWithTrackID:mediaType:]): + (-[WebAVStreamDataParserListener streamDataParserWillProvideContentKeyRequestInitializationData:forTrackID:]): + (-[WebAVStreamDataParserListener streamDataParser:didProvideContentKeyRequestInitializationData:forTrackID:]): + (WebCore::SourceBufferPrivateAVFObjC::SourceBufferPrivateAVFObjC): + (WebCore::SourceBufferPrivateAVFObjC::append): + (WebCore::SourceBufferPrivateAVFObjC::abort): + (WebCore::SourceBufferPrivateAVFObjC::resetParserState): + (-[WebAVStreamDataParserListener initWithParser:parent:]): Deleted. + * platform/graphics/gstreamer/SourceBufferPrivateGStreamer.cpp: + (WebCore::SourceBufferPrivateGStreamer::resetParserState): + * platform/graphics/gstreamer/SourceBufferPrivateGStreamer.h: + * platform/mock/mediasource/MockSourceBufferPrivate.cpp: + (WebCore::MockSourceBufferPrivate::resetParserState): + * platform/mock/mediasource/MockSourceBufferPrivate.h: + * platform/spi/mac/AVFoundationSPI.h: + +2016-09-27 Babak Shafiei + + Merge r206399. rdar://problem/28457219 + + 2016-09-26 Wenson Hsieh + + Seeking video doesn't update seek position + https://bugs.webkit.org/show_bug.cgi?id=162575 + + + Reviewed by Jer Noble. + + On ToT, seeking in a video causes the playhead to stutter, and does not actually update media remote's seek + position. This is partly due to how we do not update media remote with new information when beginning to respond + to remote seek commands, so media remote continues to think that a playing video is still playing despite the + user attempting to seek through it. + + To fix this, we introduce timer-based guards around remote seek commands, such that a seek "gesture" begins when + we receive the first seek command and ends when no seek command has been received in a set amount of time (this + is 0.5 seconds, which is approximately what other clients around the platform use). + + Also, when responding to a remote seek, perform the seek with no tolerance. This prevents the playhead from + stuttering at the end of a seek from the final requested destination of the seek to the last actually seeked + time in the video. + + When beginning to seek, we must pause the media. Through existing mechanisms, this causes the media session + manager to update its Now Playing information, which informs media remote that we are no longer playing and + prevents us from stuttering. However, when ending a seek, we must also trigger an additional update to again + refresh media remote's view of the current time. This prevents a flicker when playing media after seeking. + + Unit tests to be added in a follow-up due to time constraints. + + * html/HTMLMediaElement.cpp: + (WebCore::HTMLMediaElement::HTMLMediaElement): + (WebCore::HTMLMediaElement::handleSeekToPlaybackPosition): + (WebCore::HTMLMediaElement::seekToPlaybackPositionEndedTimerFired): + (WebCore::HTMLMediaElement::didReceiveRemoteControlCommand): + * html/HTMLMediaElement.h: + * platform/audio/PlatformMediaSessionManager.h: + (WebCore::PlatformMediaSessionManager::scheduleUpdateNowPlayingInfo): + (WebCore::PlatformMediaSessionManager::sessionDidEndRemoteScrubbing): + (WebCore::PlatformMediaSessionManager::sessions): Deleted. + * platform/audio/mac/MediaSessionManagerMac.h: + * platform/audio/mac/MediaSessionManagerMac.mm: + (WebCore::PlatformMediaSessionManager::updateNowPlayingInfoIfNecessary): + (WebCore::MediaSessionManagerMac::scheduleUpdateNowPlayingInfo): + (WebCore::MediaSessionManagerMac::sessionDidEndRemoteScrubbing): + (WebCore::MediaSessionManagerMac::updateNowPlayingInfo): + +2016-09-26 Babak Shafiei + + Merge r206375. rdar://problem/28484393 + + 2016-09-26 Per Arne Vollan + + [Win][Debug] Compile fix. + https://bugs.webkit.org/show_bug.cgi?id=162550 + + Reviewed by Alex Christensen. + + Windows headers need the FragmentForwardIterator '==' operator in debug mode. + + * rendering/SimpleLineLayout.cpp: + (WebCore::SimpleLineLayout::FragmentForwardIterator::operator==): + +2016-09-23 Babak Shafiei + + Merge r203982. rdar://problem/27547583 + + 2016-08-01 Eric Carlson + + [Mac][iOS] Adopt MediaRemote "seek to playback position" + https://bugs.webkit.org/show_bug.cgi?id=160405 + + + Reviewed by Dean Jackson. + + Test: media/remote-control-command-seek.html + + * Modules/webaudio/AudioContext.h: Update for didReceiveRemoteControlCommand argument change. + + * html/HTMLMediaElement.cpp: + (WebCore::HTMLMediaElement::didReceiveRemoteControlCommand): Support SeekToPlaybackPositionCommand. + Drive by fix, support Stop command. + (WebCore::HTMLMediaElement::supportsSeeking): New. + * html/HTMLMediaElement.h: + + * platform/RemoteCommandListener.h: + (WebCore::RemoteCommandListenerClient::didReceiveRemoteControlCommand): Add command argument. + (WebCore::RemoteCommandListenerClient::supportsSeeking): New. + (WebCore::RemoteCommandListener::updateSupportedCommands): Ditto. + (WebCore::RemoteCommandListener::client): Ditto. + + * platform/audio/PlatformMediaSession.cpp: + (WebCore::PlatformMediaSession::didReceiveRemoteControlCommand): Add command argument. + (WebCore::PlatformMediaSession::supportsSeeking): New, pass through to client. + * platform/audio/PlatformMediaSession.h: + + * platform/audio/PlatformMediaSessionManager.cpp: + (WebCore::PlatformMediaSessionManager::setCurrentSession): Tell remote command listener to + update supported commands. + (WebCore::PlatformMediaSessionManager::currentSession): Make const. + (WebCore::PlatformMediaSessionManager::didReceiveRemoteControlCommand): Add command argument. + (WebCore::PlatformMediaSessionManager::supportsSeeking): New, pass through to session. + * platform/audio/PlatformMediaSessionManager.h: + + * platform/ios/RemoteCommandListenerIOS.h: + (WebCore::RemoteCommandListenerIOS::createWeakPtr): + * platform/ios/RemoteCommandListenerIOS.mm: + (WebCore::RemoteCommandListenerIOS::RemoteCommandListenerIOS): Support changePlaybackPositionCommand. + (WebCore::RemoteCommandListenerIOS::~RemoteCommandListenerIOS): Remove seekToTime target. + (WebCore::RemoteCommandListenerIOS::updateSupportedCommands): Update changePlaybackPositionCommand. + + * platform/mac/MediaRemoteSoftLink.cpp: + * platform/mac/MediaRemoteSoftLink.h: + + * platform/mac/RemoteCommandListenerMac.h: + * platform/mac/RemoteCommandListenerMac.mm: + (WebCore::RemoteCommandListenerMac::updateSupportedCommands): New, split out of constructor. + (WebCore::RemoteCommandListenerMac::RemoteCommandListenerMac): Split setup logic out into + updateSupportedCommands. Support MRMediaRemoteCommandSeekToPlaybackPosition. Don't assert when + receiving an unsupported command, it happens. Return error when a command isn't supported or + fails. + + * testing/Internals.cpp: + (WebCore::Internals::postRemoteControlCommand): Add command argument parameter. Support + seektoplaybackposition. + * testing/Internals.h: + * testing/Internals.idl: + +2016-09-22 Babak Shafiei + + Merge r206193. rdar://problem/28376161 + + 2016-09-20 Jer Noble + + Adopt MRMediaRemoteSetParentApplication. + https://bugs.webkit.org/show_bug.cgi?id=162259 + + + Reviewed by Anders Carlsson. + + Allow MediaSessionManagerMac to retrieve the correct parent application identifier + from a PlatformMediaSession so that it can pass that identifier through to MediaRemote + via MRMediaRemoteSetParentApplication. + + * Modules/webaudio/AudioContext.cpp: + (WebCore::AudioContext::sourceApplicationIdentifier): + * Modules/webaudio/AudioContext.h: + * platform/audio/PlatformMediaSession.cpp: + (WebCore::PlatformMediaSession::sourceApplicationIdentifier): + * platform/audio/PlatformMediaSession.h: + (WebCore::PlatformMediaSession::resetPlaybackSessionState): Deleted. + * platform/audio/mac/MediaSessionManagerMac.mm: + (WebCore::MediaSessionManagerMac::updateNowPlayingInfo): + * platform/mac/MediaRemoteSoftLink.cpp: + * platform/mac/MediaRemoteSoftLink.h: + + +2016-09-12 Babak Shafiei + + Merge r204943. rdar://problem/28233330 + + 2016-08-24 Ryan Haddad + + Rebaseline bindings tests after r204923. + + Unreviewed test gardening. + + * bindings/scripts/test/JS/JSTestActiveDOMObject.cpp: + (WebCore::jsTestActiveDOMObjectExcitingAttr): + (WebCore::jsTestActiveDOMObjectPrototypeFunctionExcitingFunction): + +2016-09-09 Babak Shafiei + + Merge r203381. rdar://problem/27860536 + + 2016-07-18 Anders Carlsson + + WebKit nightly fails to build on macOS Sierra + https://bugs.webkit.org/show_bug.cgi?id=159902 + rdar://problem/27365672 + + Reviewed by Tim Horton. + + * Modules/applepay/cocoa/PaymentCocoa.mm: + * Modules/applepay/cocoa/PaymentContactCocoa.mm: + * Modules/applepay/cocoa/PaymentMerchantSessionCocoa.mm: + * Modules/applepay/cocoa/PaymentMethodCocoa.mm: + Use new PassKitSPI header. + + * WebCore.xcodeproj/project.pbxproj: + Add new PassKitSPI header. + + * icu/unicode/ucurr.h: Added. + Add ucurr.h from ICU. + + * platform/spi/cocoa/PassKitSPI.h: Added. + Add new PassKitSPI header. + +2016-09-09 Babak Shafiei + + Merge r205381. rdar://problem/27806012 + + 2016-09-02 Beth Dakin + + Need to updateEditorState if an element change edit-ability without changing + selection + https://bugs.webkit.org/show_bug.cgi?id=161546 + -and corresponding- + rdar://problem/27806012 + + Reviewed by Ryosuke Niwa. + + Call into the client in case edited state needs to be updated. + * editing/FrameSelection.cpp: + (WebCore::FrameSelection::updateAppearanceAfterLayout): + * loader/EmptyClients.h: + * page/EditorClient.h: + +2016-08-31 Babak Shafiei + + Merge r205044. rdar://problem/27933564 + + 2016-08-26 Beth Dakin + + charactersAroundPosition can be wrong because it crosses editing boundaries + https://bugs.webkit.org/show_bug.cgi?id=161215 + -and corresponding- + rdar://problem/27933564 + + Reviewed by Ryosuke Niwa. + + charactersAroundPosition() should not cross editing boundaries. This patch fixes + that by making nextCharacterBoundaryInDirection() take an + EditingBoundaryCrossingRule parameter to pass onto VisiblePosition::next() and + VisiblePosition::previous(). + + * editing/VisibleUnits.cpp: + (WebCore::nextCharacterBoundaryInDirection): + (WebCore::positionOfNextBoundaryOfGranularity): + (WebCore::charactersAroundPosition): + +2016-08-30 Babak Shafiei + + Merge r203542. rdar://problem/27991570 + + 2016-07-21 John Wilander + + Block mixed content synchronous XHR + https://bugs.webkit.org/show_bug.cgi?id=105462 + + + Reviewed by Brent Fulgham. + + Test: http/tests/security/mixedContent/insecure-xhr-sync-in-main-frame.html + + * loader/DocumentThreadableLoader.cpp: + (WebCore::DocumentThreadableLoader::loadRequest): + +2016-08-23 Babak Shafiei + + Merge r204610. rdar://problem/27750446 + + 2016-08-18 Beth Dakin + + Update the accessibility titles for list insertion + https://bugs.webkit.org/show_bug.cgi?id=160972 + -and corresponding- + rdar://problem/27750446 + + Reviewed by Chris Fleizach. + + Update accessibility titles based on feedback. + * English.lproj/Localizable.strings: + * platform/LocalizedStrings.cpp: + (WebCore::insertListTypeNone): + (WebCore::insertListTypeBulleted): + (WebCore::insertListTypeBulletedAccessibilityTitle): + (WebCore::insertListTypeNumbered): + (WebCore::insertListTypeNumberedAccessibilityTitle): + (WebCore::insertListTypeNoneAccessibilityTitle): Deleted. + * platform/LocalizedStrings.h: + +2016-08-17 Babak Shafiei + + Merge r204587. rdar://problem/27807479 + + 2016-08-17 Anders Carlsson + + Add support for additional networks + https://bugs.webkit.org/show_bug.cgi?id=160951 + rdar://problem/27807479 + + Reviewed by Sam Weinig. + + * Modules/applepay/ApplePaySession.cpp: + (WebCore::createSupportedNetworks): + (WebCore::createPaymentRequest): + (WebCore::ApplePaySession::create): + * Modules/applepay/PaymentRequest.cpp: + (WebCore::isAdditionalValidSupportedNetwork): + (WebCore::PaymentRequest::isValidSupportedNetwork): + * Modules/applepay/PaymentRequest.h: + (WebCore::PaymentRequest::supportedNetworks): + (WebCore::PaymentRequest::setSupportedNetworks): + * Modules/applepay/PaymentRequestValidator.cpp: + (WebCore::PaymentRequestValidator::validateSupportedNetworks): + * Modules/applepay/PaymentRequestValidator.h: + +2016-06-17 Babak Shafiei + + Merge r202174. + + 2016-06-17 John Wilander + + Ignore case in the check for security origin inheritance + https://bugs.webkit.org/show_bug.cgi?id=158878 + + Reviewed by Alex Christensen. + + Darin Adler commented in https://bugs.webkit.org/show_bug.cgi?id=158855: + "Are these comparisons intentionally case sensitive? Shouldn’t they ignore ASCII + case? We could use equalIgnoringASCIICase and equalLettersIgnoringASCIICase for + those two lines instead of using ==. URL::parse normalizes letters in the scheme + and host by using toASCIILower, but does not normalize letters elsewhere in the + URL, such as in the "blank" or "srcdoc" in the above URLs." + + Test: http/tests/dom/window-open-about-uppercase-blank-and-access-document.html + + * platform/URL.cpp: + (WebCore::URL::shouldInheritSecurityOriginFromOwner): + +2016-06-17 Babak Shafiei + + Merge r202151. + + 2016-06-16 John Wilander + + Restrict security origin inheritance to empty, about:blank, and about:srcdoc URLs + https://bugs.webkit.org/show_bug.cgi?id=158855 + + + Reviewed by Alex Christensen. + + Tests: http/tests/dom/window-open-about-blank-and-access-document.html + http/tests/dom/window-open-about-webkit-org-and-access-document.html + + Document.cpp previously checked whether a document should inherit its owner's + security origin by checking if the URL is either empty or blank. URL.cpp in + turn only checks if the protocol is "about:" in the isBlankURL() function. + Thus all about:* URLs inherited security origin. This patch restricts + security origin inheritance to empty, about:blank, and about:srcdoc URLs. + + Quotes and links from the WHATWG spec regarding about:srcdoc: + + 7.1 Browsing contexts + A browsing context can have a creator browsing context, the browsing context + that was responsible for its creation. If a browsing context has a parent + browsing context, then that is its creator browsing context. Otherwise, if the + browsing context has an opener browsing context, then that is its creator + browsing context. Otherwise, the browsing context has no creator browsing + context. + https://html.spec.whatwg.org/multipage/browsers.html#concept-document-bc + + 7.1.1 Nested browsing contexts + Certain elements (for example, iframe elements) can instantiate further + browsing contexts. These are called nested browsing contexts. If a browsing + context P has a Document D with an element E that nests another browsing + context C inside it, then C is said to be nested through D, and E is said to + be the browsing context container of C. If the browsing context container + element E is in the Document D, then P is said to be the parent browsing + context of C and C is said to be a child browsing context of P. Otherwise, + the nested browsing context C has no parent browsing context. + https://html.spec.whatwg.org/multipage/browsers.html#nested-browsing-context + + 4.8.5 The iframe element + The iframe element represents a nested browsing context. + ... + If the srcdoc attribute is specified + Navigate the element's child browsing context to a new response whose + url list consists of about:srcdoc ... + https://html.spec.whatwg.org/multipage/embedded-content.html#attr-iframe-srcdoc + + * dom/Document.cpp: + (WebCore::Document::initSecurityContext): + Now uses the URL::shouldInheritSecurityOriginFromOwner() function instead. + (WebCore::Document::initContentSecurityPolicy): + Now uses the URL::shouldInheritSecurityOriginFromOwner() function instead. + (WebCore::shouldInheritSecurityOriginFromOwner): Deleted. + Moved to URL::shouldInheritSecurityOriginFromOwner() and restricted the check. + * platform/URL.cpp: + (WebCore::URL::shouldInheritSecurityOriginFromOwner): + * platform/URL.h: + Moved the function from Document and restricted the check to only allow + security origin inheritance for empty, about:blank, and about:srcdoc URLs. + 2016-10-26 Zalan Bujtas Ignore out-of-flow siblings when searching for a spanner candidate. @@ -848,6 +4768,40 @@ 2016-03-18 Brent Fulgham + Merge r212026. rdar://problem/30096323 + + 2017-02-09 Chris Dumez + + Crash under FormSubmission::create() + https://bugs.webkit.org/show_bug.cgi?id=167200 + + + Reviewed by Darin Adler. + + The issue is that FormSubmission::create() was iterating over + form.associatedElements() as was calling Element::appendFormData() + in the loop. HTMLObjectElement::appendFormData() was calling + pluginWidget(PluginLoadingPolicy::Load) which causes a synchronous + layout and can fire events (such as focus event) synchronously. + Firing those events synchronously allows the JS to modify the + form.associatedElements() vector we are currently iterating on. + + To avoid this issue, we now call pluginWidget(PluginLoadingPolicy::DoNotLoad) + in HTMLObjectElement::appendFormData() as we are not allowed to fire + synchronous events at this point. I also added a security assertion + in FormSubmission::create() to catch cases where we fire JS events + while iterating over the form associated elements to more easily + notice these things in the future. + + Test: fast/forms/formsubmission-appendFormData-crash.html + + * html/HTMLObjectElement.cpp: + (WebCore::HTMLObjectElement::appendFormData): + * loader/FormSubmission.cpp: + (WebCore::FormSubmission::create): + +2017-02-10 Brent Fulgham + Unreviewed build fix. Get rid of infinitely recursive 'draw' implementation. @@ -1852,7 +5806,7 @@ 2016-01-20 Timothy Hatcher - CrashTracer: com.apple.WebKit.WebContent at cpector::CSSFrontendDispatcher::mediaQueryResultChanged + 316 + CrashTracer: com.apple.WebKit.WebContent at �cpector::CSSFrontendDispatcher::mediaQueryResultChanged + 316 Reviewed by Joseph Pecoraro. @@ -2189,7 +6143,7 @@ 2016-01-08 Timothy Hatcher - REGRESSION (193350): CrashTracer: [USER] com.apple.WebKit.WebContent at c: Inspector::CSSFrontendDispatcher::styleSheetRemoved + 768 + REGRESSION (193350): CrashTracer: [USER] com.apple.WebKit.WebContent at �c: Inspector::CSSFrontendDispatcher::styleSheetRemoved + 768 Reviewed by Joseph Pecoraro. @@ -3025,7 +6979,7 @@ 2015-10-14 Zhuo Li - Augment fs recent search history with the time each entry was added, + Augment �fs recent search history with the time each entry was added, in order to allow time-based clearing of search history. https://bugs.webkit.org/show_bug.cgi?id=148388. @@ -7451,12 +11405,12 @@ Reviewed by Tim Horton. - This regression was introduced on El Capitan because AppKit sends ‘cancelto + This regression was introduced on El Capitan because AppKit sends ‘cancel��to gesture recognizer BEFORE it sends the mouseUp. So the ImmediateActionStage needs to track whether a cancel happened after updates or without any updates since they signify different things. - Donft perform default behaviors when the stage is ActionCancelledAfterUpdate. + Don�ft perform default behaviors when the stage is ActionCancelledAfterUpdate. * page/EventHandler.cpp: (WebCore::EventHandler::handleMouseReleaseEvent): diff --git a/webkit/WebCore/English.lproj/Localizable.strings b/webkit/WebCore/English.lproj/Localizable.strings index 9da106452..7e9d33362 100755 --- a/webkit/WebCore/English.lproj/Localizable.strings +++ b/webkit/WebCore/English.lproj/Localizable.strings @@ -124,6 +124,9 @@ /* Undo action name */ "Bold (Undo action name)" = "Bold"; +/* Option in segmented control for inserting a bulleted list in text editing */ +"Bulleted list" = "Bulleted list"; + /* menu item title for phone number */ "Call Using iPhone:" = "Call Using iPhone:"; @@ -367,6 +370,9 @@ /* WebKitErrorCannotUseRestrictedPort description */ "Not allowed to use restricted network port" = "Not allowed to use restricted network port"; +/* Option in segmented control for inserting a numbered list in text editing */ +"Numbered list" = "Numbered list"; + /* OK button label in PDF password failure alert */ "OK (PDF password failure alert)" = "OK"; @@ -679,6 +685,9 @@ /* Undo action name */ "Use Standard Ligatures (Undo action name)" = "Use Standard Ligatures"; +/* Validation message for form control elements with a value shorter than maximum allowed length */ +"Use no more than %d character(s)" = "Use no more than %d character(s)"; + /* Description of WebCrypto master keys in Keychain */ "Used to encrypt WebCrypto keys in persistent storage, such as IndexedDB" = "Used to encrypt WebCrypto keys in persistent storage, such as IndexedDB"; @@ -772,6 +781,9 @@ /* accessibility help text for elapsed time display */ "current movie time in seconds" = "current movie time in seconds"; +/* accessibility role description for a date and time field. */ +"date and time field" = "date and time field"; + /* role description of ARIA definition role */ "definition" = "definition"; diff --git a/webkit/WebCore/English.lproj/Localizable.stringsdict b/webkit/WebCore/English.lproj/Localizable.stringsdict new file mode 100755 index 000000000..970c1a389 --- /dev/null +++ b/webkit/WebCore/English.lproj/Localizable.stringsdict @@ -0,0 +1,22 @@ + + + + + Use no more than %d character(s) + + NSStringLocalizedFormatKey + Use no more than %#@characters@ + characters + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + one character + other + %d characters + + + + diff --git a/webkit/WebCore/Info.plist b/webkit/WebCore/Info.plist index 02b47b989..049e82932 100755 --- a/webkit/WebCore/Info.plist +++ b/webkit/WebCore/Info.plist @@ -7,7 +7,7 @@ CFBundleExecutable ${PRODUCT_NAME} CFBundleGetInfoString - ${BUNDLE_VERSION}, Copyright 2003-2016 Apple Inc.; Copyright 1997 Martin Jones <mjones@kde.org>; Copyright 1998, 1999 Torben Weis <weis@kde.org>; Copyright 1998, 1999, 2002 Waldo Bastian <bastian@kde.org>; Copyright 1998-2000 Lars Knoll <knoll@kde.org>; Copyright 1999, 2001 Antti Koivisto <koivisto@kde.org>; Copyright 1999-2001 Harri Porten <porten@kde.org>; Copyright 2000 Simon Hausmann <hausmann@kde.org>; Copyright 2000, 2001 Dirk Mueller <mueller@kde.org>; Copyright 2000, 2001 Peter Kelly <pmk@post.com>; Copyright 2000 Daniel Molkentin <molkentin@kde.org>; Copyright 2000 Stefan Schimanski <schimmi@kde.org>; Copyright 1998-2000 Netscape Communications Corporation; Copyright 1998, 1999, 2000 Thai Open Source Software Center Ltd and Clark Cooper; Copyright 2001, 2002 Expat maintainers. + ${BUNDLE_VERSION}, Copyright 2003-2017 Apple Inc.; Copyright 1997 Martin Jones <mjones@kde.org>; Copyright 1998, 1999 Torben Weis <weis@kde.org>; Copyright 1998, 1999, 2002 Waldo Bastian <bastian@kde.org>; Copyright 1998-2000 Lars Knoll <knoll@kde.org>; Copyright 1999, 2001 Antti Koivisto <koivisto@kde.org>; Copyright 1999-2001 Harri Porten <porten@kde.org>; Copyright 2000 Simon Hausmann <hausmann@kde.org>; Copyright 2000, 2001 Dirk Mueller <mueller@kde.org>; Copyright 2000, 2001 Peter Kelly <pmk@post.com>; Copyright 2000 Daniel Molkentin <molkentin@kde.org>; Copyright 2000 Stefan Schimanski <schimmi@kde.org>; Copyright 1998-2000 Netscape Communications Corporation; Copyright 1998, 1999, 2000 Thai Open Source Software Center Ltd and Clark Cooper; Copyright 2001, 2002 Expat maintainers. CFBundleIdentifier com.apple.${PRODUCT_NAME} CFBundleInfoDictionaryVersion diff --git a/webkit/WebCore/LICENSE-Chromium_Blink b/webkit/WebCore/LICENSE-Chromium_Blink new file mode 100755 index 000000000..70bcb8ad1 --- /dev/null +++ b/webkit/WebCore/LICENSE-Chromium_Blink @@ -0,0 +1,30 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// +// The Chromium Authors can be found at +// http://src.chromium.org/svn/trunk/src/AUTHORS +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/webkit/WebCore/LICENSE_FOR_ABOUT_CREDITS-Chromium_Blink b/webkit/WebCore/LICENSE_FOR_ABOUT_CREDITS-Chromium_Blink new file mode 100755 index 000000000..fc77db598 --- /dev/null +++ b/webkit/WebCore/LICENSE_FOR_ABOUT_CREDITS-Chromium_Blink @@ -0,0 +1,967 @@ +(WebKit doesn't distribute an explicit license. This LICENSE is derived from +license text in the source.) + +Copyright (c) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, +2006, 2007 Alexander Kellett, Alexey Proskuryakov, Alex Mathews, Allan +Sandfeld Jensen, Alp Toker, Anders Carlsson, Andrew Wellington, Antti +Koivisto, Apple Inc., Arthur Langereis, Baron Schwartz, Bjoern Graf, +Brent Fulgham, Cameron Zwarich, Charles Samuels, Christian Dywan, +Collabora Ltd., Cyrus Patel, Daniel Molkentin, Dave Maclachlan, David +Smith, Dawit Alemayehu, Dirk Mueller, Dirk Schulze, Don Gibson, Enrico +Ros, Eric Seidel, Frederik Holljen, Frerich Raabe, Friedmann Kleint, +George Staikos, Google Inc., Graham Dennis, Harri Porten, Henry Mason, +Hiroyuki Ikezoe, Holger Hans Peter Freyther, IBM, James G. Speth, Jan +Alonzo, Jean-Loup Gailly, John Reis, Jonas Witt, Jon Shier, Jonas +Witt, Julien Chaffraix, Justin Haygood, Kevin Ollivier, Kevin Watters, +Kimmo Kinnunen, Kouhei Sutou, Krzysztof Kowalczyk, Lars Knoll, Luca +Bruno, Maks Orlovich, Malte Starostik, Mark Adler, Martin Jones, +Marvin Decker, Matt Lilek, Michael Emmel, Mitz Pettel, mozilla.org, +Netscape Communications Corporation, Nicholas Shanks, Nikolas +Zimmermann, Nokia, Oliver Hunt, Opened Hand, Paul Johnston, Peter +Kelly, Pioneer Research Center USA, Rich Moore, Rob Buis, Robin Dunn, +Ronald Tschalär, Samuel Weinig, Simon Hausmann, Staikos Computing +Services Inc., Stefan Schimanski, Symantec Corporation, The Dojo +Foundation, The Karbon Developers, Thomas Boyer, Tim Copperfield, +Tobias Anton, Torben Weis, Trolltech, University of Cambridge, Vaclav +Slavik, Waldo Bastian, Xan Lopez, Zack Rusin + +The terms and conditions vary from file to file, but are one of: + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the + distribution. + +*OR* + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the + distribution. +3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + +OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + + GNU LIBRARY GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1991 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the library GPL. It is + numbered 2 because it goes with version 2 of the ordinary GPL.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Library General Public License, applies to some +specially designated Free Software Foundation software, and to any +other libraries whose authors decide to use it. You can use it for +your libraries, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if +you distribute copies of the library, or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link a program with the library, you must provide +complete object files to the recipients so that they can relink them +with the library, after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + Our method of protecting your rights has two steps: (1) copyright +the library, and (2) offer you this license which gives you legal +permission to copy, distribute and/or modify the library. + + Also, for each distributor's protection, we want to make certain +that everyone understands that there is no warranty for this free +library. If the library is modified by someone else and passed on, we +want its recipients to know that what they have is not the original +version, so that any problems introduced by others will not reflect on +the original authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that companies distributing free +software will individually obtain patent licenses, thus in effect +transforming the program into proprietary software. To prevent this, +we have made it clear that any patent must be licensed for everyone's +free use or not licensed at all. + + Most GNU software, including some libraries, is covered by the ordinary +GNU General Public License, which was designed for utility programs. This +license, the GNU Library General Public License, applies to certain +designated libraries. This license is quite different from the ordinary +one; be sure to read it in full, and don't assume that anything in it is +the same as in the ordinary license. + + The reason we have a separate public license for some libraries is that +they blur the distinction we usually make between modifying or adding to a +program and simply using it. Linking a program with a library, without +changing the library, is in some sense simply using the library, and is +analogous to running a utility program or application program. However, in +a textual and legal sense, the linked executable is a combined work, a +derivative of the original library, and the ordinary General Public License +treats it as such. + + Because of this blurred distinction, using the ordinary General +Public License for libraries did not effectively promote software +sharing, because most developers did not use the libraries. We +concluded that weaker conditions might promote sharing better. + + However, unrestricted linking of non-free programs would deprive the +users of those programs of all benefit from the free status of the +libraries themselves. This Library General Public License is intended to +permit developers of non-free programs to use free libraries, while +preserving your freedom as a user of such programs to change the free +libraries that are incorporated in them. (We have not seen how to achieve +this as regards changes in header files, but we have achieved it as regards +changes in the actual functions of the Library.) The hope is that this +will lead to faster development of free libraries. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, while the latter only +works together with the library. + + Note that it is possible for a library to be covered by the ordinary +General Public License rather than by this special one. + + GNU LIBRARY GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library which +contains a notice placed by the copyright holder or other authorized +party saying it may be distributed under the terms of this Library +General Public License (also called "this License"). Each licensee is +addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also compile or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + c) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + d) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the source code distributed need not include anything that is normally +distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Library General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS diff --git a/webkit/WebCore/Modules/applepay/ApplePaySession.cpp b/webkit/WebCore/Modules/applepay/ApplePaySession.cpp new file mode 100755 index 000000000..c8a682964 --- /dev/null +++ b/webkit/WebCore/Modules/applepay/ApplePaySession.cpp @@ -0,0 +1,1294 @@ +/* + * Copyright (C) 2015, 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "ApplePaySession.h" + +#if ENABLE(APPLE_PAY) + +#include "ApplePayPaymentAuthorizedEvent.h" +#include "ApplePayPaymentMethodSelectedEvent.h" +#include "ApplePayShippingContactSelectedEvent.h" +#include "ApplePayShippingMethodSelectedEvent.h" +#include "ApplePayValidateMerchantEvent.h" +#include "ArrayValue.h" +#include "DOMWindow.h" +#include "Dictionary.h" +#include "Document.h" +#include "DocumentLoader.h" +#include "EventNames.h" +#include "JSDOMPromise.h" +#include "JSMainThreadExecState.h" +#include "LinkIconCollector.h" +#include "LinkIconType.h" +#include "MainFrame.h" +#include "Page.h" +#include "PageConsoleClient.h" +#include "PaymentAuthorizationStatus.h" +#include "PaymentContact.h" +#include "PaymentCoordinator.h" +#include "PaymentMerchantSession.h" +#include "PaymentMethod.h" +#include "PaymentRequestValidator.h" +#include "ScriptController.h" +#include "SecurityOrigin.h" +#include "Settings.h" + +namespace WebCore { + +static bool parseDigit(UChar digit, bool isNegative, int64_t& amount) +{ + if (!isASCIIDigit(digit)) + return false; + + int64_t digitValue = (digit - '0'); + + const int64_t maxMultiplier = std::numeric_limits::max() / 10; + + // Check overflow. + if (amount > maxMultiplier || (amount == maxMultiplier && digitValue > (std::numeric_limits::max() % 10) + isNegative)) + return false; + + amount = amount * 10 + digitValue; + return true; +} + +// The amount follows the regular expression -?[0-9]+(\.[0-9][0-9])?. +static Optional parseAmount(const String& amountString) +{ + int64_t amount = 0; + + bool isNegative = false; + + enum class State { + Start, + Sign, + Digit, + Dot, + DotDigit, + End, + }; + + State state = State::Start; + + for (unsigned i = 0; i < amountString.length(); ++i) { + UChar c = amountString[i]; + + switch (state) { + case State::Start: + if (c == '-') { + isNegative = true; + state = State::Sign; + break; + } + + if (!parseDigit(c, isNegative, amount)) + return Nullopt; + state = State::Digit; + break; + + case State::Sign: + if (!parseDigit(c, isNegative, amount)) + return Nullopt; + state = State::Digit; + break; + + case State::Digit: + if (c == '.') { + state = State::Dot; + break; + } + + if (!parseDigit(c, isNegative, amount)) + return Nullopt; + break; + + case State::Dot: + if (!parseDigit(c, isNegative, amount)) + return Nullopt; + + state = State::DotDigit; + break; + + case State::DotDigit: + if (!parseDigit(c, isNegative, amount)) + return Nullopt; + + state = State::End; + break; + + case State::End: + return Nullopt; + } + } + + if (state != State::Digit && state != State::DotDigit && state != State::End) + return Nullopt; + + if (state == State::DotDigit) { + // There was a single digit after the decimal point. + // FIXME: Handle this overflowing. + amount *= 10; + } else if (state == State::Digit) { + // There was no decimal point. + // FIXME: Handle this overflowing. + amount *= 100; + } + + if (isNegative) + amount = -amount; + + return amount; +} + +static Optional createContactFields(DOMWindow& window, const ArrayValue& contactFieldsArray) +{ + PaymentRequest::ContactFields result; + + size_t contactFieldsCount; + if (!contactFieldsArray.length(contactFieldsCount)) + return Nullopt; + + for (size_t i = 0; i < contactFieldsCount; ++i) { + String contactField; + if (!contactFieldsArray.get(i, contactField)) + return Nullopt; + + if (contactField == "postalAddress") + result.postalAddress = true; + else if (contactField == "phone") + result.phone = true; + else if (contactField == "email") + result.email = true; + else if (contactField == "name") + result.name = true; + else { + auto message = makeString("\"" + contactField, "\" is not a valid contact field."); + window.printErrorMessage(message); + return Nullopt; + } + } + + return result; +} + +static Optional toLineItemType(const String& type) +{ + if (type == "pending") + return PaymentRequest::LineItem::Type::Pending; + if (type == "final") + return PaymentRequest::LineItem::Type::Final; + + return Nullopt; +} + +static bool isValidLineItemPropertyName(const String& propertyName) +{ + const char* validPropertyNames[] = { + "type", + "label", + "amount", + }; + + for (auto& validPropertyName : validPropertyNames) { + if (propertyName == validPropertyName) + return true; + } + + return false; +} + +static Optional createLineItem(DOMWindow& window, const Dictionary& total) +{ + Vector propertyNames; + total.getOwnPropertyNames(propertyNames); + + for (auto& propertyName : propertyNames) { + if (!isValidLineItemPropertyName(propertyName)) { + auto message = makeString("\"" + propertyName, "\" is not a valid line item property name."); + window.printErrorMessage(message); + return Nullopt; + } + } + + // Line item type defaults to Final. + PaymentRequest::LineItem result; + + if (auto typeString = total.get("type")) { + auto type = toLineItemType(*typeString); + if (!type) { + auto message = makeString("\"" + *typeString, "\" is not a valid line item type."); + window.printErrorMessage(message); + return Nullopt; + } + + result.type = *type; + } + + if (auto label = total.get("label")) + result.label = *label; + if (auto amountString = total.get("amount")) { + if (auto amount = parseAmount(*amountString)) + result.amount = *amount; + else { + auto message = makeString("\"" + *amountString, "\" is not a valid amount."); + window.printErrorMessage(message); + return Nullopt; + } + } + + return result; +} + +static Optional> createLineItems(DOMWindow& window, const ArrayValue& lineItemsArray) +{ + Vector result; + + size_t lineItemCount; + if (!lineItemsArray.length(lineItemCount)) + return Nullopt; + + for (size_t i = 0; i < lineItemCount; ++i) { + Dictionary lineItemDictionary; + if (!lineItemsArray.get(i, lineItemDictionary)) + return Nullopt; + + if (auto lineItem = createLineItem(window, lineItemDictionary)) + result.append(*lineItem); + } + + return result; +} + +static Optional createMerchantCapabilities(DOMWindow& window, const ArrayValue& merchantCapabilitiesArray) +{ + PaymentRequest::MerchantCapabilities result; + + size_t merchantCapabilitiesCount; + if (!merchantCapabilitiesArray.length(merchantCapabilitiesCount)) + return Nullopt; + + for (size_t i = 0; i < merchantCapabilitiesCount; ++i) { + String merchantCapability; + if (!merchantCapabilitiesArray.get(i, merchantCapability)) + return Nullopt; + + if (merchantCapability == "supports3DS") + result.supports3DS = true; + else if (merchantCapability == "supportsEMV") + result.supportsEMV = true; + else if (merchantCapability == "supportsCredit") + result.supportsCredit = true; + else if (merchantCapability == "supportsDebit") + result.supportsDebit = true; + else { + auto message = makeString("\"" + merchantCapability, "\" is not a valid merchant capability."); + window.printErrorMessage(message); + return Nullopt; + } + } + + return result; +} + +static Optional> createSupportedNetworks(unsigned version, DOMWindow& window, const ArrayValue& supportedNetworksArray) +{ + Vector result; + + size_t supportedNetworksCount; + if (!supportedNetworksArray.length(supportedNetworksCount)) + return Nullopt; + + for (size_t i = 0; i < supportedNetworksCount; ++i) { + String supportedNetwork; + if (!supportedNetworksArray.get(i, supportedNetwork)) + return Nullopt; + + if (!PaymentRequest::isValidSupportedNetwork(version, supportedNetwork)) { + auto message = makeString("\"" + supportedNetwork, "\" is not a valid payment network."); + window.printErrorMessage(message); + return Nullopt; + } + + result.append(WTF::move(supportedNetwork)); + } + + return result; +} + +static Optional toShippingType(const String& shippingTypeString) +{ + if (shippingTypeString == "shipping") + return PaymentRequest::ShippingType::Shipping; + if (shippingTypeString == "delivery") + return PaymentRequest::ShippingType::Delivery; + if (shippingTypeString == "storePickup") + return PaymentRequest::ShippingType::StorePickup; + if (shippingTypeString == "servicePickup") + return PaymentRequest::ShippingType::ServicePickup; + + return Nullopt; +} + +static bool isValidShippingMethodPropertyName(const String& propertyName) +{ + const char* validPropertyNames[] = { + "label", + "detail", + "amount", + "identifier", + }; + + for (auto& validPropertyName : validPropertyNames) { + if (propertyName == validPropertyName) + return true; + } + + return false; +} + +static Optional createShippingMethod(DOMWindow& window, const Dictionary& shippingMethodDictionary) +{ + Vector propertyNames; + shippingMethodDictionary.getOwnPropertyNames(propertyNames); + + for (auto& propertyName : propertyNames) { + if (!isValidShippingMethodPropertyName(propertyName)) { + auto message = makeString("\"" + propertyName, "\" is not a valid shipping method property name."); + window.printErrorMessage(message); + return Nullopt; + } + } + + PaymentRequest::ShippingMethod result; + + auto label = shippingMethodDictionary.get("label"); + if (!label) { + window.printErrorMessage("Missing shipping method label."); + return Nullopt; + } + result.label = *label; + + auto detail = shippingMethodDictionary.get("detail"); + if (!detail) { + window.printErrorMessage("Missing shipping method detail."); + return Nullopt; + } + result.detail = *detail; + + auto amountString = shippingMethodDictionary.get("amount"); + if (!amountString) { + window.printErrorMessage("Missing shipping method amount."); + return Nullopt; + } + + if (auto amount = parseAmount(*amountString)) + result.amount = *amount; + else { + auto message = makeString("\"" + *amountString, "\" is not a valid amount."); + window.printErrorMessage(message); + return Nullopt; + } + + auto identifier = shippingMethodDictionary.get("identifier"); + if (!identifier) { + window.printErrorMessage("Missing shipping method identifier."); + return Nullopt; + } + result.identifier = *identifier; + + return result; +} + +static Optional> createShippingMethods(DOMWindow& window, const ArrayValue& shippingMethodsArray) +{ + Vector result; + + size_t shippingMethodCount; + if (!shippingMethodsArray.length(shippingMethodCount)) + return Nullopt; + + for (size_t i = 0; i < shippingMethodCount; ++i) { + Dictionary shippingMethodDictionary; + if (!shippingMethodsArray.get(i, shippingMethodDictionary)) + return Nullopt; + + if (auto shippingMethod = createShippingMethod(window, shippingMethodDictionary)) + result.append(*shippingMethod); + else + return Nullopt; + } + + return result; +} + +static bool isValidPaymentRequestPropertyName(const String& propertyName) +{ + const char* validPropertyNames[] = { + "merchantCapabilities", + "supportedNetworks", + "countryCode", + "currencyCode", + "requiredBillingContactFields", + "billingContact", + "requiredShippingContactFields", + "shippingContact", + "shippingType", + "shippingMethods", + "total", + "lineItems", + "applicationData", + }; + + for (auto& validPropertyName : validPropertyNames) { + if (propertyName == validPropertyName) + return true; + } + + return false; +} + +static Optional createPaymentRequest(unsigned version, DOMWindow& window, const Dictionary& dictionary) +{ + PaymentRequest paymentRequest; + + Vector propertyNames; + dictionary.getOwnPropertyNames(propertyNames); + + for (auto& propertyName : propertyNames) { + if (propertyName == "requiredShippingAddressFields") { + window.printErrorMessage("\"requiredShippingAddressFields\" has been deprecated. Please switch to \"requiredShippingContactFields\" instead."); + return Nullopt; + } + + if (propertyName == "requiredBillingAddressFields") { + window.printErrorMessage("\"requiredBillingAddressFields\" has been deprecated. Please switch to \"requiredBillingContactFields\" instead."); + return Nullopt; + } + + if (!isValidPaymentRequestPropertyName(propertyName)) { + auto message = makeString("\"" + propertyName, "\" is not a valid payment request property name."); + window.printErrorMessage(message); + return Nullopt; + } + } + + if (auto merchantCapabilitiesArray = dictionary.get("merchantCapabilities")) { + auto merchantCapabilities = createMerchantCapabilities(window, *merchantCapabilitiesArray); + if (!merchantCapabilities) + return Nullopt; + + paymentRequest.setMerchantCapabilities(*merchantCapabilities); + } + + if (auto supportedNetworksArray = dictionary.get("supportedNetworks")) { + auto supportedNetworks = createSupportedNetworks(version, window, *supportedNetworksArray); + if (!supportedNetworks) + return Nullopt; + + paymentRequest.setSupportedNetworks(*supportedNetworks); + } + + if (auto countryCode = dictionary.get("countryCode")) + paymentRequest.setCountryCode(*countryCode); + if (auto currencyCode = dictionary.get("currencyCode")) + paymentRequest.setCurrencyCode(*currencyCode); + + if (auto requiredBillingContactFieldsArray = dictionary.get("requiredBillingContactFields")) { + auto requiredBillingContactFields = createContactFields(window, *requiredBillingContactFieldsArray); + if (!requiredBillingContactFields) + return Nullopt; + + paymentRequest.setRequiredBillingContactFields(*requiredBillingContactFields); + } + + if (auto billingContactValue = dictionary.get("billingContact")) { + String errorMessage; + auto billingContact = PaymentContact::fromJS(*JSMainThreadExecState::currentState(), *billingContactValue, errorMessage); + if (!billingContact) { + window.printErrorMessage(errorMessage); + return Nullopt; + } + + paymentRequest.setBillingContact(*billingContact); + } + + if (auto requiredShippingContactFieldsArray = dictionary.get("requiredShippingContactFields")) { + auto requiredShippingContactFields = createContactFields(window, *requiredShippingContactFieldsArray); + if (!requiredShippingContactFields) + return Nullopt; + + paymentRequest.setRequiredShippingContactFields(*requiredShippingContactFields); + } + + if (auto shippingContactValue = dictionary.get("shippingContact")) { + String errorMessage; + auto shippingContact = PaymentContact::fromJS(*JSMainThreadExecState::currentState(), *shippingContactValue, errorMessage); + if (!shippingContact) { + window.printErrorMessage(errorMessage); + return Nullopt; + } + + paymentRequest.setShippingContact(*shippingContact); + } + + if (auto shippingTypeString = dictionary.get("shippingType")) { + auto shippingType = toShippingType(*shippingTypeString); + + if (!shippingType) { + auto message = makeString("\"" + *shippingTypeString, "\" is not a valid shipping type."); + window.printErrorMessage(message); + return Nullopt; + } + paymentRequest.setShippingType(*shippingType); + } + + if (auto shippingMethodsArray = dictionary.get("shippingMethods")) { + auto shippingMethods = createShippingMethods(window, *shippingMethodsArray); + if (!shippingMethods) + return Nullopt; + + paymentRequest.setShippingMethods(*shippingMethods); + } + + if (auto totalDictionary = dictionary.get("total")) { + auto total = createLineItem(window, *totalDictionary); + if (!total) + return Nullopt; + + paymentRequest.setTotal(*total); + } + + if (auto lineItemsArray = dictionary.get("lineItems")) { + if (auto lineItems = createLineItems(window, *lineItemsArray)) + paymentRequest.setLineItems(*lineItems); + } + + if (auto applicationData = dictionary.get("applicationData")) + paymentRequest.setApplicationData(*applicationData); + + return paymentRequest; +} + +static bool isSecure(DocumentLoader& documentLoader) +{ + if (!documentLoader.response().url().protocolIs("https")) + return false; + + if (!documentLoader.response().certificateInfo() || documentLoader.response().certificateInfo()->containsNonRootSHA1SignedCertificate()) + return false; + + return true; +} + +static bool canCallApplePaySessionAPIs(Document& document, String& errorMessage) +{ + if (!isSecure(*document.loader())) { + errorMessage = "Trying to call an ApplePaySession API from an insecure document."; + return false; + } + + auto& topDocument = document.topDocument(); + if (&document != &topDocument) { + auto& topOrigin = *topDocument.topOrigin(); + + if (!document.securityOrigin()->isSameSchemeHostPort(&topOrigin)) { + errorMessage = "Trying to call an ApplePaySession API from a document with an different security origin than its top-level frame."; + return false; + } + + for (auto* ancestorDocument = document.parentDocument(); ancestorDocument != &topDocument; ancestorDocument = ancestorDocument->parentDocument()) { + if (!isSecure(*ancestorDocument->loader())) { + errorMessage = "Trying to call an ApplePaySession API from a document with an insecure parent frame."; + return false; + } + + if (!ancestorDocument->securityOrigin()->isSameSchemeHostPort(&topOrigin)) { + errorMessage = "Trying to call an ApplePaySession API from a document with an different security origin than its top-level frame."; + return false; + } + } + } + + return true; +} + +RefPtr ApplePaySession::create(Document& document, unsigned version, const Dictionary& dictionary, ExceptionCode& ec) +{ + DOMWindow& window = *document.domWindow(); + + String errorMessage; + if (!canCallApplePaySessionAPIs(document, errorMessage)) { + window.printErrorMessage(errorMessage); + ec = INVALID_ACCESS_ERR; + return nullptr; + } + + if (!ScriptController::processingUserGesture()) { + window.printErrorMessage("Must create a new ApplePaySession from a user gesture handler."); + ec = INVALID_ACCESS_ERR; + return nullptr; + } + + auto& paymentCoordinator = document.frame()->mainFrame().paymentCoordinator(); + + if (!version || !paymentCoordinator.supportsVersion(version)) { + window.printErrorMessage(makeString("\"" + String::number(version), "\" is not a supported version.")); + ec = INVALID_ACCESS_ERR; + return nullptr; + } + + auto paymentRequest = createPaymentRequest(version, window, dictionary); + if (!paymentRequest) { + ec = TYPE_MISMATCH_ERR; + return nullptr; + } + + if (!PaymentRequestValidator(window).validate(*paymentRequest)) { + ec = INVALID_ACCESS_ERR; + return nullptr; + } + + return adoptRef(new ApplePaySession(document, WTF::move(*paymentRequest))); +} + +ApplePaySession::ApplePaySession(Document& document, PaymentRequest&& paymentRequest) + : ActiveDOMObject(&document) + , m_state(State::Idle) + , m_merchantValidationState(MerchantValidationState::Idle) + , m_paymentRequest(WTF::move(paymentRequest)) +{ + suspendIfNeeded(); +} + +ApplePaySession::~ApplePaySession() +{ +} + +bool ApplePaySession::supportsVersion(ScriptExecutionContext& scriptExecutionContext, unsigned version, ExceptionCode& ec) +{ + if (!version) { + ec = INVALID_ACCESS_ERR; + return false; + } + + auto& document = downcast(scriptExecutionContext); + DOMWindow& window = *document.domWindow(); + + String errorMessage; + if (!canCallApplePaySessionAPIs(document, errorMessage)) { + window.printErrorMessage(errorMessage); + ec = INVALID_ACCESS_ERR; + return false; + } + + auto& paymentCoordinator = document.frame()->mainFrame().paymentCoordinator(); + return paymentCoordinator.supportsVersion(version); +} + +static bool shouldDiscloseApplePayCapability(Document& document) +{ + auto* page = document.page(); + if (!page || page->usesEphemeralSession()) + return false; + + return document.frame()->settings().applePayCapabilityDisclosureAllowed(); +} + +bool ApplePaySession::canMakePayments(ScriptExecutionContext& scriptExecutionContext, ExceptionCode& ec) +{ + auto& document = downcast(scriptExecutionContext); + DOMWindow& window = *document.domWindow(); + + String errorMessage; + if (!canCallApplePaySessionAPIs(document, errorMessage)) { + window.printErrorMessage(errorMessage); + ec = INVALID_ACCESS_ERR; + return false; + } + + auto& paymentCoordinator = document.frame()->mainFrame().paymentCoordinator(); + return paymentCoordinator.canMakePayments(); +} + +void ApplePaySession::canMakePaymentsWithActiveCard(ScriptExecutionContext& scriptExecutionContext, const String& merchantIdentifier, DeferredWrapper&& promise, ExceptionCode& ec) +{ + auto& document = downcast(scriptExecutionContext); + DOMWindow& window = *document.domWindow(); + + String errorMessage; + if (!canCallApplePaySessionAPIs(document, errorMessage)) { + window.printErrorMessage(errorMessage); + ec = INVALID_ACCESS_ERR; + return; + } + + if (!shouldDiscloseApplePayCapability(document)) { + auto& paymentCoordinator = document.frame()->mainFrame().paymentCoordinator(); + bool canMakePayments = paymentCoordinator.canMakePayments(); + + RunLoop::main().dispatch([promise, canMakePayments]() mutable { + promise.resolve(canMakePayments); + }); + return; + } + + auto& paymentCoordinator = document.frame()->mainFrame().paymentCoordinator(); + + paymentCoordinator.canMakePaymentsWithActiveCard(merchantIdentifier, document.domain(), [promise](bool canMakePayments) mutable { + promise.resolve(canMakePayments); + }); +} + +void ApplePaySession::begin(ExceptionCode& ec) +{ + auto& document = *downcast(scriptExecutionContext()); + auto& window = *document.domWindow(); + + if (!canBegin()) { + window.printErrorMessage("Payment session is already active."); + ec = INVALID_ACCESS_ERR; + return; + } + + if (paymentCoordinator().hasActiveSession()) { + window.printErrorMessage("Page already has an active payment session."); + + ec = INVALID_ACCESS_ERR; + return; + } + + Vector linkIconURLs; + for (auto& icon : LinkIconCollector { document }.iconsOfTypes({ LinkIconType::TouchIcon, LinkIconType::TouchPrecomposedIcon })) + linkIconURLs.append(icon.url); + + if (!paymentCoordinator().beginPaymentSession(*this, document.url(), linkIconURLs, m_paymentRequest)) { + window.printErrorMessage("There is already has an active payment session."); + + ec = INVALID_ACCESS_ERR; + return; + } + + m_state = State::Active; + + setPendingActivity(this); +} + +void ApplePaySession::abort(ExceptionCode& ec) +{ + if (!canAbort()) { + ec = INVALID_ACCESS_ERR; + return; + } + + m_state = State::Aborted; + paymentCoordinator().abortPaymentSession(); + + didReachFinalState(); +} + +void ApplePaySession::completeMerchantValidation(const Dictionary& merchantSessionDictionary, ExceptionCode& ec) +{ + if (!canCompleteMerchantValidation()) { + ec = INVALID_ACCESS_ERR; + return; + } + + auto& document = *downcast(scriptExecutionContext()); + auto& window = *document.domWindow(); + + String errorMessage; + auto merchantSession = PaymentMerchantSession::fromJS(*merchantSessionDictionary.execState(), merchantSessionDictionary.initializerObject(), errorMessage); + if (!merchantSession) { + window.printErrorMessage(errorMessage); + ec = INVALID_ACCESS_ERR; + return; + } + + m_merchantValidationState = MerchantValidationState::ValidationComplete; + paymentCoordinator().completeMerchantValidation(*merchantSession); +} + + +static Optional toPaymentAuthorizationStatus(unsigned short status) +{ + switch (status) { + case ApplePaySession::STATUS_SUCCESS: + return PaymentAuthorizationStatus::Success; + + case ApplePaySession::STATUS_FAILURE: + return PaymentAuthorizationStatus::Failure; + + case ApplePaySession::STATUS_INVALID_BILLING_POSTAL_ADDRESS: + return PaymentAuthorizationStatus::InvalidBillingPostalAddress; + + case ApplePaySession::STATUS_INVALID_SHIPPING_POSTAL_ADDRESS: + return PaymentAuthorizationStatus::InvalidShippingPostalAddress; + + case ApplePaySession::STATUS_INVALID_SHIPPING_CONTACT: + return PaymentAuthorizationStatus::InvalidShippingContact; + + case ApplePaySession::STATUS_PIN_REQUIRED: + return PaymentAuthorizationStatus::PINRequired; + + case ApplePaySession::STATUS_PIN_INCORRECT: + return PaymentAuthorizationStatus::PINIncorrect; + + case ApplePaySession::STATUS_PIN_LOCKOUT: + return PaymentAuthorizationStatus::PINLockout; + + default: + return Nullopt; + } +} + +void ApplePaySession::completeShippingMethodSelection(unsigned short status, const Dictionary& newTotalDictionary, const ArrayValue& newLineItemsArray, ExceptionCode& ec) +{ + if (!canCompleteShippingMethodSelection()) { + ec = INVALID_ACCESS_ERR; + return; + } + + auto authorizationStatus = toPaymentAuthorizationStatus(status); + if (!authorizationStatus) { + ec = INVALID_ACCESS_ERR; + return; + } + + auto& window = *downcast(scriptExecutionContext())->domWindow(); + auto newTotal = createLineItem(window, newTotalDictionary); + if (!newTotal) { + ec = INVALID_ACCESS_ERR; + return; + } + + if (!PaymentRequestValidator(window).validateTotal(*newTotal)) { + ec = INVALID_ACCESS_ERR; + return; + } + + auto newLineItems = createLineItems(window, newLineItemsArray); + if (!newLineItems) { + ec = INVALID_ACCESS_ERR; + return; + } + + m_state = State::Active; + PaymentRequest::TotalAndLineItems totalAndLineItems; + totalAndLineItems.total = *newTotal; + totalAndLineItems.lineItems = *newLineItems; + paymentCoordinator().completeShippingMethodSelection(*authorizationStatus, totalAndLineItems); +} + +void ApplePaySession::completeShippingContactSelection(unsigned short status, const ArrayValue& newShippingMethodsArray, const Dictionary& newTotalDictionary, const ArrayValue& newLineItemsArray, ExceptionCode& ec) +{ + if (!canCompleteShippingContactSelection()) { + ec = INVALID_ACCESS_ERR; + return; + } + + auto authorizationStatus = toPaymentAuthorizationStatus(status); + if (!authorizationStatus) { + ec = INVALID_ACCESS_ERR; + return; + } + + auto& window = *downcast(scriptExecutionContext())->domWindow(); + + auto newShippingMethods = createShippingMethods(window, newShippingMethodsArray); + if (!newShippingMethods) { + ec = INVALID_ACCESS_ERR; + return; + } + + auto newTotal = createLineItem(window, newTotalDictionary); + if (!newTotal) { + ec = INVALID_ACCESS_ERR; + return; + } + + if (!PaymentRequestValidator(window).validateTotal(*newTotal)) { + ec = INVALID_ACCESS_ERR; + return; + } + + auto newLineItems = createLineItems(window, newLineItemsArray); + if (!newLineItems) { + ec = INVALID_ACCESS_ERR; + return; + } + + m_state = State::Active; + PaymentRequest::TotalAndLineItems totalAndLineItems; + totalAndLineItems.total = *newTotal; + totalAndLineItems.lineItems = *newLineItems; + paymentCoordinator().completeShippingContactSelection(*authorizationStatus, *newShippingMethods, totalAndLineItems); +} + +void ApplePaySession::completePaymentMethodSelection(const Dictionary& newTotalDictionary, const ArrayValue& newLineItemsArray, ExceptionCode& ec) +{ + if (!canCompletePaymentMethodSelection()) { + ec = INVALID_ACCESS_ERR; + return; + } + + auto& window = *downcast(scriptExecutionContext())->domWindow(); + auto newTotal = createLineItem(window, newTotalDictionary); + if (!newTotal) { + ec = INVALID_ACCESS_ERR; + return; + } + + if (!PaymentRequestValidator(window).validateTotal(*newTotal)) { + ec = INVALID_ACCESS_ERR; + return; + } + + auto newLineItems = createLineItems(window, newLineItemsArray); + if (!newLineItems) { + ec = INVALID_ACCESS_ERR; + return; + } + + m_state = State::Active; + PaymentRequest::TotalAndLineItems totalAndLineItems; + totalAndLineItems.total = *newTotal; + totalAndLineItems.lineItems = *newLineItems; + paymentCoordinator().completePaymentMethodSelection(totalAndLineItems); +} + +void ApplePaySession::completePayment(unsigned short status, ExceptionCode& ec) +{ + if (!canCompletePayment()) { + ec = INVALID_ACCESS_ERR; + return; + } + + auto authorizationStatus = toPaymentAuthorizationStatus(status); + if (!authorizationStatus) { + ec = INVALID_ACCESS_ERR; + return; + } + + paymentCoordinator().completePaymentSession(*authorizationStatus); + + if (!isFinalStateStatus(*authorizationStatus)) { + m_state = State::Active; + return; + } + + m_state = State::Completed; + unsetPendingActivity(this); +} + +void ApplePaySession::validateMerchant(const URL& validationURL) +{ + if (m_state == State::Aborted) { + // ApplePaySession::abort has been called. + return; + } + + ASSERT(m_merchantValidationState == MerchantValidationState::Idle); + ASSERT(m_state == State::Active); + + if (validationURL.isNull()) { + // Something went wrong when getting the validation URL. + // FIXME: Maybe we should send an error event here instead? + return; + } + + m_merchantValidationState = MerchantValidationState::ValidatingMerchant; + + RefPtr event = ApplePayValidateMerchantEvent::create(eventNames().validatemerchantEvent, validationURL); + dispatchEvent(*event); +} + +void ApplePaySession::didAuthorizePayment(const Payment& payment) +{ + ASSERT(m_state == State::Active); + + m_state = State::Authorized; + + RefPtr event = ApplePayPaymentAuthorizedEvent::create(eventNames().paymentauthorizedEvent, payment); + dispatchEvent(*event); +} + +void ApplePaySession::didSelectShippingMethod(const PaymentRequest::ShippingMethod& shippingMethod) +{ + ASSERT(m_state == State::Active); + + if (!hasEventListeners(eventNames().shippingmethodselectedEvent)) { + paymentCoordinator().completeShippingMethodSelection(PaymentAuthorizationStatus::Success, { }); + return; + } + + m_state = State::ShippingMethodSelected; + RefPtr event = ApplePayShippingMethodSelectedEvent::create(eventNames().shippingmethodselectedEvent, shippingMethod); + dispatchEvent(*event); +} + +void ApplePaySession::didSelectShippingContact(const PaymentContact& shippingContact) +{ + ASSERT(m_state == State::Active); + + if (!hasEventListeners(eventNames().shippingcontactselectedEvent)) { + paymentCoordinator().completeShippingContactSelection(PaymentAuthorizationStatus::Success, { }, { }); + return; + } + + m_state = State::ShippingContactSelected; + RefPtr event = ApplePayShippingContactSelectedEvent::create(eventNames().shippingcontactselectedEvent, shippingContact); + dispatchEvent(*event); +} + +void ApplePaySession::didSelectPaymentMethod(const PaymentMethod& paymentMethod) +{ + ASSERT(m_state == State::Active); + + if (!hasEventListeners(eventNames().paymentmethodselectedEvent)) { + paymentCoordinator().completePaymentMethodSelection({ }); + return; + } + + m_state = State::PaymentMethodSelected; + RefPtr event = ApplePayPaymentMethodSelectedEvent::create(eventNames().paymentmethodselectedEvent, paymentMethod); + dispatchEvent(*event); +} + +void ApplePaySession::didCancelPayment() +{ + ASSERT(canCancel()); + + m_state = State::Canceled; + + RefPtr event = Event::create(eventNames().cancelEvent, false, false); + dispatchEvent(*event); + + didReachFinalState(); +} + +const char* ApplePaySession::activeDOMObjectName() const +{ + return "ApplePaySession"; +} + +bool ApplePaySession::canSuspendForDocumentSuspension() const +{ + switch (m_state) { + case State::Idle: + case State::Aborted: + case State::Completed: + case State::Canceled: + return true; + + case State::Active: + case State::Authorized: + case State::ShippingMethodSelected: + case State::ShippingContactSelected: + case State::PaymentMethodSelected: + return false; + } +} + +void ApplePaySession::stop() +{ + if (!canAbort()) + return; + + m_state = State::Aborted; + paymentCoordinator().abortPaymentSession(); + + didReachFinalState(); +} + +PaymentCoordinator& ApplePaySession::paymentCoordinator() const +{ + return downcast(scriptExecutionContext())->frame()->mainFrame().paymentCoordinator(); +} + +bool ApplePaySession::canBegin() const +{ + switch (m_state) { + case State::Idle: + return true; + + case State::Active: + case State::Aborted: + case State::Authorized: + case State::Completed: + case State::Canceled: + case State::ShippingMethodSelected: + case State::ShippingContactSelected: + case State::PaymentMethodSelected: + return false; + } +} + +bool ApplePaySession::canAbort() const +{ + switch (m_state) { + case State::Idle: + case State::Aborted: + case State::Completed: + case State::Canceled: + return false; + + case State::Active: + case State::Authorized: + case State::ShippingMethodSelected: + case State::ShippingContactSelected: + case State::PaymentMethodSelected: + return true; + } +} + +bool ApplePaySession::canCancel() const +{ + switch (m_state) { + case State::Idle: + case State::Aborted: + case State::Completed: + case State::Canceled: + return false; + + case State::Active: + case State::Authorized: + case State::ShippingMethodSelected: + case State::ShippingContactSelected: + case State::PaymentMethodSelected: + return true; + } +} + +bool ApplePaySession::canCompleteMerchantValidation() const +{ + if (m_state != State::Active) + return false; + + if (m_merchantValidationState != MerchantValidationState::ValidatingMerchant) + return false; + + return true; +} + +bool ApplePaySession::canCompleteShippingMethodSelection() const +{ + switch (m_state) { + case State::Idle: + case State::Aborted: + case State::Active: + case State::Completed: + case State::Canceled: + case State::Authorized: + case State::PaymentMethodSelected: + case State::ShippingContactSelected: + return false; + + case State::ShippingMethodSelected: + return true; + } +} + +bool ApplePaySession::canCompleteShippingContactSelection() const +{ + switch (m_state) { + case State::Idle: + case State::Aborted: + case State::Active: + case State::Completed: + case State::Canceled: + case State::Authorized: + case State::PaymentMethodSelected: + case State::ShippingMethodSelected: + return false; + + case State::ShippingContactSelected: + return true; + } +} + +bool ApplePaySession::canCompletePaymentMethodSelection() const +{ + switch (m_state) { + case State::Idle: + case State::Aborted: + case State::Active: + case State::Completed: + case State::Canceled: + case State::Authorized: + case State::ShippingMethodSelected: + case State::ShippingContactSelected: + return false; + + case State::PaymentMethodSelected: + return true; + } +} + +bool ApplePaySession::canCompletePayment() const +{ + switch (m_state) { + case State::Idle: + case State::Aborted: + case State::Active: + case State::Completed: + case State::Canceled: + case State::ShippingMethodSelected: + case State::ShippingContactSelected: + case State::PaymentMethodSelected: + return false; + + case State::Authorized: + return true; + } +} + +bool ApplePaySession::isFinalState() const +{ + switch (m_state) { + case State::Idle: + case State::Active: + case State::ShippingMethodSelected: + case State::ShippingContactSelected: + case State::PaymentMethodSelected: + case State::Authorized: + return false; + + case State::Completed: + case State::Aborted: + case State::Canceled: + return true; + } +} + +void ApplePaySession::didReachFinalState() +{ + ASSERT(isFinalState()); + unsetPendingActivity(this); +} + +} + +#endif diff --git a/webkit/WebCore/Modules/applepay/PaymentRequest.cpp b/webkit/WebCore/Modules/applepay/PaymentRequest.cpp new file mode 100755 index 000000000..06e5244ae --- /dev/null +++ b/webkit/WebCore/Modules/applepay/PaymentRequest.cpp @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2015, 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "PaymentRequest.h" + +#if ENABLE(APPLE_PAY) + +#include "SoftLinking.h" + +namespace WebCore { + +PaymentRequest::PaymentRequest() +{ +} + +PaymentRequest::~PaymentRequest() +{ +} + +#if USE(APPLE_INTERNAL_SDK) && __has_include() +#include +#else +static inline bool isAdditionalValidSupportedNetwork(unsigned, const String&) +{ + return false; +} +#endif + +bool PaymentRequest::isValidSupportedNetwork(unsigned version, const String& supportedNetwork) +{ + if (supportedNetwork == "amex") + return true; + if (supportedNetwork == "chinaUnionPay") + return true; + if (supportedNetwork == "discover") + return true; + if (supportedNetwork == "interac") + return true; + if (supportedNetwork == "masterCard") + return true; + if (supportedNetwork == "privateLabel") + return true; + if (supportedNetwork == "visa") + return true; + + return isAdditionalValidSupportedNetwork(version, supportedNetwork); +} + +} + +#endif diff --git a/webkit/WebCore/Modules/applepay/PaymentRequest.h b/webkit/WebCore/Modules/applepay/PaymentRequest.h new file mode 100755 index 000000000..6af92d305 --- /dev/null +++ b/webkit/WebCore/Modules/applepay/PaymentRequest.h @@ -0,0 +1,152 @@ +/* + * Copyright (C) 2015, 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#if ENABLE(APPLE_PAY) + +#include "PaymentContact.h" +#include +#include +#include + +namespace WebCore { + +class PaymentRequest { +public: + WEBCORE_EXPORT PaymentRequest(); + WEBCORE_EXPORT ~PaymentRequest(); + + const String& countryCode() const { return m_countryCode; } + void setCountryCode(const String& countryCode) { m_countryCode = countryCode; } + + const String& currencyCode() const { return m_currencyCode; } + void setCurrencyCode(const String& currencyCode) { m_currencyCode = currencyCode; } + + struct ContactFields { + bool postalAddress { false }; + bool phone { false }; + bool email { false }; + bool name { false }; + }; + + const ContactFields& requiredBillingContactFields() const { return m_requiredBillingContactFields; } + void setRequiredBillingContactFields(const ContactFields& requiredBillingContactFields) { m_requiredBillingContactFields = requiredBillingContactFields; } + + const PaymentContact& billingContact() const { return m_billingContact; } + void setBillingContact(const PaymentContact& billingContact) { m_billingContact = billingContact; } + + const ContactFields& requiredShippingContactFields() const { return m_requiredShippingContactFields; } + void setRequiredShippingContactFields(const ContactFields& requiredShippingContactFields) { m_requiredShippingContactFields = requiredShippingContactFields; } + + const PaymentContact& shippingContact() const { return m_shippingContact; } + void setShippingContact(const PaymentContact& shippingContact) { m_shippingContact = shippingContact; } + + static bool isValidSupportedNetwork(unsigned version, const String&); + + const Vector& supportedNetworks() const { return m_supportedNetworks; } + void setSupportedNetworks(const Vector& supportedNetworks) { m_supportedNetworks = supportedNetworks; } + + struct MerchantCapabilities { + bool supports3DS { false }; + bool supportsEMV { false }; + bool supportsCredit { false }; + bool supportsDebit { false }; + }; + + const MerchantCapabilities& merchantCapabilities() const { return m_merchantCapabilities; } + void setMerchantCapabilities(const MerchantCapabilities& merchantCapabilities) { m_merchantCapabilities = merchantCapabilities; } + + struct LineItem { + enum class Type { + Pending, + Final, + } type { Type::Final }; + + // Stored as a fixed point decimal number with two decimals: + // 1.23 -> 123. + // 0.01 -> 1. + Optional amount; + String label; + }; + + enum class ShippingType { + Shipping, + Delivery, + StorePickup, + ServicePickup, + }; + ShippingType shippingType() const { return m_shippingType; } + void setShippingType(ShippingType shippingType) { m_shippingType = shippingType; } + + struct ShippingMethod { + String label; + String detail; + int64_t amount; + + String identifier; + }; + const Vector& shippingMethods() const { return m_shippingMethods; } + void setShippingMethods(const Vector& shippingMethods) { m_shippingMethods = shippingMethods; } + + const Vector& lineItems() const { return m_lineItems; } + void setLineItems(const Vector& lineItems) { m_lineItems = lineItems; } + + const LineItem& total() const { return m_total; }; + void setTotal(const LineItem& total) { m_total = total; } + + struct TotalAndLineItems { + PaymentRequest::LineItem total; + Vector lineItems; + }; + + const String& applicationData() const { return m_applicationData; } + void setApplicationData(const String& applicationData) { m_applicationData = applicationData; } + +private: + String m_countryCode; + String m_currencyCode; + + ContactFields m_requiredBillingContactFields; + PaymentContact m_billingContact; + + ContactFields m_requiredShippingContactFields; + PaymentContact m_shippingContact; + + Vector m_supportedNetworks; + MerchantCapabilities m_merchantCapabilities; + + ShippingType m_shippingType { ShippingType::Shipping }; + Vector m_shippingMethods; + + Vector m_lineItems; + LineItem m_total; + + String m_applicationData; +}; + +} + +#endif diff --git a/webkit/WebCore/Modules/applepay/PaymentRequestValidator.cpp b/webkit/WebCore/Modules/applepay/PaymentRequestValidator.cpp new file mode 100755 index 000000000..b435b6bab --- /dev/null +++ b/webkit/WebCore/Modules/applepay/PaymentRequestValidator.cpp @@ -0,0 +1,172 @@ +/* + * Copyright (C) 2015, 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "PaymentRequestValidator.h" + +#if ENABLE(APPLE_PAY) + +#include "DOMWindow.h" +#include "PageConsoleClient.h" +#include "PaymentRequest.h" +#include +#include + +namespace WebCore { + +PaymentRequestValidator::PaymentRequestValidator(DOMWindow& window) + : m_window(window) +{ +} + +PaymentRequestValidator::~PaymentRequestValidator() +{ +} + +bool PaymentRequestValidator::validate(const PaymentRequest& paymentRequest) const +{ + if (!validateCountryCode(paymentRequest.countryCode())) + return false; + if (!validateCurrencyCode(paymentRequest.currencyCode())) + return false; + if (!validateSupportedNetworks(paymentRequest.supportedNetworks())) + return false; + if (!validateMerchantCapabilities(paymentRequest.merchantCapabilities())) + return false; + if (!validateTotal(paymentRequest.total())) + return false; + if (!validateShippingMethods(paymentRequest.shippingMethods())) + return false; + return true; +} + +bool PaymentRequestValidator::validateTotal(const PaymentRequest::LineItem& total) const +{ + if (!total.label) { + m_window.printErrorMessage("Missing total label."); + return false; + } + + if (!total.amount) { + m_window.printErrorMessage("Missing total amount."); + return false; + } + + if (*total.amount <= 0) { + m_window.printErrorMessage("Total amount must be greater than zero."); + return false; + } + + if (*total.amount > 10000000000) { + m_window.printErrorMessage("Total amount is too big."); + return false; + } + + return true; +} + +bool PaymentRequestValidator::validateCountryCode(const String& countryCode) const +{ + if (!countryCode) { + m_window.printErrorMessage("Missing country code."); + return false; + } + + for (auto *countryCodePtr = uloc_getISOCountries(); *countryCodePtr; ++countryCodePtr) { + if (countryCode == *countryCodePtr) + return true; + } + + auto message = makeString("\"" + countryCode, "\" is not a valid country code."); + m_window.printErrorMessage(message); + + return false; +} + +bool PaymentRequestValidator::validateCurrencyCode(const String& currencyCode) const +{ + if (!currencyCode) { + m_window.printErrorMessage("Missing currency code."); + return false; + } + + UErrorCode errorCode = U_ZERO_ERROR; + auto currencyCodes = std::unique_ptr(ucurr_openISOCurrencies(UCURR_ALL, &errorCode), uenum_close); + + int32_t length; + while (auto *currencyCodePtr = uenum_next(currencyCodes.get(), &length, &errorCode)) { + if (currencyCodePtr == currencyCode) + return true; + } + + auto message = makeString("\"" + currencyCode, "\" is not a valid currency code."); + m_window.printErrorMessage(message); + + return false; +} + +bool PaymentRequestValidator::validateMerchantCapabilities(const PaymentRequest::MerchantCapabilities& merchantCapabilities) const +{ + if (!merchantCapabilities.supports3DS && !merchantCapabilities.supportsEMV && !merchantCapabilities.supportsCredit && !merchantCapabilities.supportsDebit) { + m_window.printErrorMessage("Missing merchant capabilities"); + return false; + } + + return true; +} + +bool PaymentRequestValidator::validateShippingMethod(const PaymentRequest::ShippingMethod& shippingMethod) const +{ + if (shippingMethod.amount < 0) { + m_window.printErrorMessage("Shipping method amount must be greater than or equal to zero."); + return false; + } + + return true; +} + +bool PaymentRequestValidator::validateSupportedNetworks(const Vector& supportedNetworks) const +{ + if (supportedNetworks.isEmpty()) { + m_window.printErrorMessage("Missing supported networks"); + return false; + } + + return true; +} + +bool PaymentRequestValidator::validateShippingMethods(const Vector& shippingMethods) const +{ + for (const auto& shippingMethod : shippingMethods) { + if (!validateShippingMethod(shippingMethod)) + return false; + } + + return true; +} + +} + +#endif diff --git a/webkit/WebCore/Modules/applepay/PaymentRequestValidator.h b/webkit/WebCore/Modules/applepay/PaymentRequestValidator.h new file mode 100755 index 000000000..d24bddb95 --- /dev/null +++ b/webkit/WebCore/Modules/applepay/PaymentRequestValidator.h @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2015, 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#if ENABLE(APPLE_PAY) + +#include "PaymentRequest.h" + +namespace WebCore { + +class DOMWindow; + +class PaymentRequestValidator { +public: + explicit PaymentRequestValidator(DOMWindow&); + ~PaymentRequestValidator(); + + bool validate(const PaymentRequest&) const; + bool validateTotal(const PaymentRequest::LineItem&) const; + +private: + bool validateCountryCode(const String&) const; + bool validateCurrencyCode(const String&) const; + bool validateMerchantCapabilities(const PaymentRequest::MerchantCapabilities&) const; + bool validateSupportedNetworks(const Vector&) const; + + bool validateShippingMethods(const Vector&) const; + bool validateShippingMethod(const PaymentRequest::ShippingMethod&) const; + + DOMWindow& m_window; +}; + +} + +#endif diff --git a/webkit/WebCore/Modules/gamepad/GamepadManager.cpp b/webkit/WebCore/Modules/gamepad/GamepadManager.cpp index 900fb46e7..047f85f4a 100755 --- a/webkit/WebCore/Modules/gamepad/GamepadManager.cpp +++ b/webkit/WebCore/Modules/gamepad/GamepadManager.cpp @@ -121,8 +121,11 @@ void GamepadManager::platformGamepadDisconnected(PlatformGamepad& platformGamepa } } -void GamepadManager::platformGamepadInputActivity() +void GamepadManager::platformGamepadInputActivity(bool shouldMakeGamepadVisible) { + if (!shouldMakeGamepadVisible) + return; + if (m_gamepadBlindNavigators.isEmpty() && m_gamepadBlindDOMWindows.isEmpty()) return; diff --git a/webkit/WebCore/Modules/gamepad/GamepadManager.h b/webkit/WebCore/Modules/gamepad/GamepadManager.h index b1bc10612..957bc06ad 100755 --- a/webkit/WebCore/Modules/gamepad/GamepadManager.h +++ b/webkit/WebCore/Modules/gamepad/GamepadManager.h @@ -51,7 +51,7 @@ class GamepadManager : public GamepadProviderClient { virtual void platformGamepadConnected(PlatformGamepad&) override final; virtual void platformGamepadDisconnected(PlatformGamepad&) override final; - virtual void platformGamepadInputActivity() override final; + virtual void platformGamepadInputActivity(bool shouldMakeGamepadVisible) final; void registerNavigator(NavigatorGamepad*); void unregisterNavigator(NavigatorGamepad*); diff --git a/webkit/WebCore/Modules/mediasource/SourceBuffer.cpp b/webkit/WebCore/Modules/mediasource/SourceBuffer.cpp index c801cfe41..aa3423274 100755 --- a/webkit/WebCore/Modules/mediasource/SourceBuffer.cpp +++ b/webkit/WebCore/Modules/mediasource/SourceBuffer.cpp @@ -357,7 +357,7 @@ void SourceBuffer::resetParserState() // 7. Set append state to WAITING_FOR_SEGMENT. m_appendState = WaitingForSegment; - m_private->abort(); + m_private->resetParserState(); } void SourceBuffer::abort(ExceptionCode& ec) @@ -455,6 +455,7 @@ void SourceBuffer::abortIfUpdating() // 3.1. Abort the buffer append and stream append loop algorithms if they are running. m_appendBufferTimer.stop(); m_pendingAppendData.clear(); + m_private->abort(); m_removeTimer.stop(); m_pendingRemoveStart = MediaTime::invalidTime(); @@ -1657,8 +1658,12 @@ void SourceBuffer::sourceBufferPrivateDidReceiveSample(SourceBufferPrivate*, Pas // 1.5 Let track buffer equal the track buffer that the coded frame will be added to. AtomicString trackID = sample->trackID(); auto it = m_trackBufferMap.find(trackID); - if (it == m_trackBufferMap.end()) - it = m_trackBufferMap.add(trackID, TrackBuffer()).iterator; + if (it == m_trackBufferMap.end()) { + // The client managed to append a sample with a trackID not present in the initialization + // segment. This would be a good place to post an message to the developer console. + didDropSample(); + return; + } TrackBuffer& trackBuffer = it->value; // 1.6 ↳ If last decode timestamp for track buffer is set and decode timestamp is less than last diff --git a/webkit/WebCore/Modules/plugins/PluginReplacement.h b/webkit/WebCore/Modules/plugins/PluginReplacement.h index de784340f..0d880dffc 100755 --- a/webkit/WebCore/Modules/plugins/PluginReplacement.h +++ b/webkit/WebCore/Modules/plugins/PluginReplacement.h @@ -40,6 +40,7 @@ class HTMLPlugInElement; class RenderElement; class RenderStyle; class RenderTreePosition; +class Settings; class ShadowRoot; class URL; @@ -61,14 +62,16 @@ typedef PassRefPtr (*CreatePluginReplacement)(HTMLPlugInEleme typedef bool (*PluginReplacementSupportsType)(const String&); typedef bool (*PluginReplacementSupportsFileExtension)(const String&); typedef bool (*PluginReplacementSupportsURL)(const URL&); - +typedef bool (*PluginReplacementEnabledForSettings)(const Settings*); + class ReplacementPlugin { public: - ReplacementPlugin(CreatePluginReplacement constructor, PluginReplacementSupportsType supportsType, PluginReplacementSupportsFileExtension supportsFileExtension, PluginReplacementSupportsURL supportsURL) + ReplacementPlugin(CreatePluginReplacement constructor, PluginReplacementSupportsType supportsType, PluginReplacementSupportsFileExtension supportsFileExtension, PluginReplacementSupportsURL supportsURL, PluginReplacementEnabledForSettings isEnabledBySettings) : m_constructor(constructor) , m_supportsType(supportsType) , m_supportsFileExtension(supportsFileExtension) , m_supportsURL(supportsURL) + , m_isEnabledBySettings(isEnabledBySettings) { } @@ -77,6 +80,7 @@ class ReplacementPlugin { , m_supportsType(other.m_supportsType) , m_supportsFileExtension(other.m_supportsFileExtension) , m_supportsURL(other.m_supportsURL) + , m_isEnabledBySettings(other.m_isEnabledBySettings) { } @@ -84,12 +88,14 @@ class ReplacementPlugin { bool supportsType(const String& mimeType) const { return m_supportsType(mimeType); } bool supportsFileExtension(const String& extension) const { return m_supportsFileExtension(extension); } bool supportsURL(const URL& url) const { return m_supportsURL(url); } - + bool isEnabledBySettings(const Settings* settings) const { return m_isEnabledBySettings(settings); }; + private: CreatePluginReplacement m_constructor; PluginReplacementSupportsType m_supportsType; PluginReplacementSupportsFileExtension m_supportsFileExtension; PluginReplacementSupportsURL m_supportsURL; + PluginReplacementEnabledForSettings m_isEnabledBySettings; }; typedef void (*PluginReplacementRegistrar)(const ReplacementPlugin&); diff --git a/webkit/WebCore/Modules/plugins/QuickTimePluginReplacement.h b/webkit/WebCore/Modules/plugins/QuickTimePluginReplacement.h index 9a972aaff..077ae9640 100755 --- a/webkit/WebCore/Modules/plugins/QuickTimePluginReplacement.h +++ b/webkit/WebCore/Modules/plugins/QuickTimePluginReplacement.h @@ -46,6 +46,7 @@ class QuickTimePluginReplacement : public PluginReplacement { static bool supportsMimeType(const String&); static bool supportsFileExtension(const String&); static bool supportsURL(const URL&) { return true; } + static bool isEnabledBySettings(const Settings*); static PassRefPtr create(HTMLPlugInElement&, const Vector& paramNames, const Vector& paramValues); ~QuickTimePluginReplacement(); diff --git a/webkit/WebCore/Modules/plugins/QuickTimePluginReplacement.mm b/webkit/WebCore/Modules/plugins/QuickTimePluginReplacement.mm index f2aaee63c..3a8c44971 100755 --- a/webkit/WebCore/Modules/plugins/QuickTimePluginReplacement.mm +++ b/webkit/WebCore/Modules/plugins/QuickTimePluginReplacement.mm @@ -42,6 +42,7 @@ #import "RenderElement.h" #import "ScriptController.h" #import "ScriptSourceCode.h" +#import "Settings.h" #import "UserAgentScripts.h" #import #import @@ -72,7 +73,7 @@ static String quickTimePluginReplacementScript() void QuickTimePluginReplacement::registerPluginReplacement(PluginReplacementRegistrar registrar) { - registrar(ReplacementPlugin(create, supportsMimeType, supportsFileExtension, supportsURL)); + registrar(ReplacementPlugin(create, supportsMimeType, supportsFileExtension, supportsURL, isEnabledBySettings)); } PassRefPtr QuickTimePluginReplacement::create(HTMLPlugInElement& plugin, const Vector& paramNames, const Vector& paramValues) @@ -114,6 +115,11 @@ static String quickTimePluginReplacementScript() return extensionHash.contains(extension); } +bool QuickTimePluginReplacement::isEnabledBySettings(const Settings* settings) +{ + return settings->quickTimePluginReplacementEnabled(); +} + QuickTimePluginReplacement::QuickTimePluginReplacement(HTMLPlugInElement& plugin, const Vector& paramNames, const Vector& paramValues) :PluginReplacement() , m_parentElement(&plugin) diff --git a/webkit/WebCore/Modules/plugins/YouTubePluginReplacement.cpp b/webkit/WebCore/Modules/plugins/YouTubePluginReplacement.cpp index 8f96c9f02..7b9165993 100755 --- a/webkit/WebCore/Modules/plugins/YouTubePluginReplacement.cpp +++ b/webkit/WebCore/Modules/plugins/YouTubePluginReplacement.cpp @@ -32,6 +32,7 @@ #include "HTMLPlugInElement.h" #include "Page.h" #include "RenderElement.h" +#include "Settings.h" #include "ShadowRoot.h" #include "YouTubeEmbedShadowElement.h" #include @@ -40,7 +41,7 @@ namespace WebCore { void YouTubePluginReplacement::registerPluginReplacement(PluginReplacementRegistrar registrar) { - registrar(ReplacementPlugin(create, supportsMimeType, supportsFileExtension, supportsURL)); + registrar(ReplacementPlugin(create, supportsMimeType, supportsFileExtension, supportsURL, isEnabledBySettings)); } PassRefPtr YouTubePluginReplacement::create(HTMLPlugInElement& plugin, const Vector& paramNames, const Vector& paramValues) @@ -200,7 +201,7 @@ static const String& valueForKey(const YouTubePluginReplacement::KeyValueMap& di return value->value; } -static URL processAndCreateYouTubeURL(const URL& url, bool& isYouTubeShortenedURL) +static URL processAndCreateYouTubeURL(const URL& url, bool& isYouTubeShortenedURL, String& outPathAfterFirstAmpersand) { if (!url.protocolIs("http") && !url.protocolIs("https")) return URL(); @@ -268,16 +269,22 @@ static URL processAndCreateYouTubeURL(const URL& url, bool& isYouTubeShortenedUR } } } else if (hasCaseInsensitivePrefix(path, "/v/") || hasCaseInsensitivePrefix(path, "/e/")) { - String videoID = url.lastPathComponent(); - - // These URLs are funny - they don't have a ? for the first query parameter. - // Strip all characters after and including '&' to remove extraneous parameters after the video ID. - size_t ampersand = videoID.find('&'); - if (ampersand != notFound) - videoID = videoID.substring(0, ampersand); - - if (!videoID.isEmpty()) + String lastPathComponent = url.lastPathComponent(); + String videoID; + String pathAfterFirstAmpersand; + + size_t ampersandLocation = lastPathComponent.find('&'); + if (ampersandLocation != notFound) { + // Some URLs we care about use & in place of ? for the first query parameter. + videoID = lastPathComponent.substring(0, ampersandLocation); + pathAfterFirstAmpersand = lastPathComponent.substring(ampersandLocation + 1, lastPathComponent.length() - ampersandLocation); + } else + videoID = lastPathComponent; + + if (!videoID.isEmpty()) { + outPathAfterFirstAmpersand = pathAfterFirstAmpersand; return createYouTubeURL(videoID, emptyString()); + } } return URL(); @@ -286,9 +293,14 @@ static URL processAndCreateYouTubeURL(const URL& url, bool& isYouTubeShortenedUR String YouTubePluginReplacement::youTubeURL(const String& srcString) { URL srcURL = m_parentElement->document().completeURL(stripLeadingAndTrailingHTMLSpaces(srcString)); + return youTubeURLFromAbsoluteURL(srcURL, srcString); +} +String YouTubePluginReplacement::youTubeURLFromAbsoluteURL(const URL& srcURL, const String& srcString) +{ bool isYouTubeShortenedURL = false; - URL youTubeURL = processAndCreateYouTubeURL(srcURL, isYouTubeShortenedURL); + String possibleMalformedQuery; + URL youTubeURL = processAndCreateYouTubeURL(srcURL, isYouTubeShortenedURL, possibleMalformedQuery); if (srcURL.isEmpty() || youTubeURL.isEmpty()) return srcString; @@ -313,17 +325,11 @@ String YouTubePluginReplacement::youTubeURL(const String& srcString) const String& srcURLPrefix = srcString.substring(0, locationOfPathBeforeVideoID); String query = srcURL.query(); + // If the URL has no query, use the possibly malformed query we found. + if (query.isEmpty()) + query = possibleMalformedQuery; - // By default, the iframe will display information like the video title and uploader on top of the video. Don't display - // them if the embeding html doesn't specify it. - if (!query.isEmpty() && !query.contains("showinfo")) - query.append("&showinfo=0"); - else - query = "showinfo=0"; - - // Append the query string if it is valid. Some sites apparently forget to add "?" for the query string, in that case, - // we will discard the parameters in the url. - // See: + // Append the query string if it is valid. StringBuilder finalURL; if (isYouTubeShortenedURL) finalURL.appendLiteral("http://www.youtube.com"); @@ -342,5 +348,10 @@ bool YouTubePluginReplacement::supportsURL(const URL& url) { return isYouTubeURL(url); } + +bool YouTubePluginReplacement::isEnabledBySettings(const Settings* settings) +{ + return settings->youTubeFlashPluginReplacementEnabled(); +} } diff --git a/webkit/WebCore/Modules/plugins/YouTubePluginReplacement.h b/webkit/WebCore/Modules/plugins/YouTubePluginReplacement.h index ad9f03927..d0ec67a09 100755 --- a/webkit/WebCore/Modules/plugins/YouTubePluginReplacement.h +++ b/webkit/WebCore/Modules/plugins/YouTubePluginReplacement.h @@ -46,12 +46,15 @@ class YouTubePluginReplacement : public PluginReplacement { typedef HashMap KeyValueMap; + WEBCORE_EXPORT static String youTubeURLFromAbsoluteURL(const URL& srcURL, const String& srcString); + private: YouTubePluginReplacement(HTMLPlugInElement&, const Vector& paramNames, const Vector& paramValues); static bool supportsMimeType(const String&); static bool supportsFileExtension(const String&); static bool supportsURL(const URL&); + static bool isEnabledBySettings(const Settings*); static PassRefPtr create(HTMLPlugInElement&, const Vector& paramNames, const Vector& paramValues); diff --git a/webkit/WebCore/Modules/webaudio/AudioBuffer.cpp b/webkit/WebCore/Modules/webaudio/AudioBuffer.cpp index 8cb8a71d9..f5350dd91 100755 --- a/webkit/WebCore/Modules/webaudio/AudioBuffer.cpp +++ b/webkit/WebCore/Modules/webaudio/AudioBuffer.cpp @@ -69,6 +69,11 @@ AudioBuffer::AudioBuffer(unsigned numberOfChannels, size_t numberOfFrames, float for (unsigned i = 0; i < numberOfChannels; ++i) { RefPtr channelDataArray = Float32Array::create(m_length); + if (!channelDataArray) { + invalidate(); + break; + } + channelDataArray->setNeuterable(false); m_channels.append(channelDataArray); } @@ -84,12 +89,23 @@ AudioBuffer::AudioBuffer(AudioBus* bus) m_channels.reserveCapacity(numberOfChannels); for (unsigned i = 0; i < numberOfChannels; ++i) { RefPtr channelDataArray = Float32Array::create(m_length); + if (!channelDataArray) { + invalidate(); + break; + } + channelDataArray->setNeuterable(false); channelDataArray->setRange(bus->channel(i)->data(), m_length, 0); m_channels.append(channelDataArray); } } +void AudioBuffer::invalidate() +{ + releaseMemory(); + m_length = 0; +} + void AudioBuffer::releaseMemory() { m_channels.clear(); diff --git a/webkit/WebCore/Modules/webaudio/AudioBuffer.h b/webkit/WebCore/Modules/webaudio/AudioBuffer.h index e73bceade..a6441b9e7 100755 --- a/webkit/WebCore/Modules/webaudio/AudioBuffer.h +++ b/webkit/WebCore/Modules/webaudio/AudioBuffer.h @@ -74,6 +74,8 @@ class AudioBuffer : public RefCounted { AudioBuffer(unsigned numberOfChannels, size_t numberOfFrames, float sampleRate); explicit AudioBuffer(AudioBus*); + void invalidate(); + double m_gain; // scalar gain float m_sampleRate; size_t m_length; diff --git a/webkit/WebCore/Modules/webaudio/AudioBufferSourceNode.cpp b/webkit/WebCore/Modules/webaudio/AudioBufferSourceNode.cpp index 2f97f4f41..7a3c6f050 100755 --- a/webkit/WebCore/Modules/webaudio/AudioBufferSourceNode.cpp +++ b/webkit/WebCore/Modules/webaudio/AudioBufferSourceNode.cpp @@ -178,7 +178,9 @@ bool AudioBufferSourceNode::renderFromBuffer(AudioBus* bus, unsigned destination unsigned busNumberOfChannels = bus->numberOfChannels(); bool channelCountGood = numberOfChannels && numberOfChannels == busNumberOfChannels; +#if !PLATFORM(WKC) ASSERT(channelCountGood); +#endif if (!channelCountGood) return false; diff --git a/webkit/WebCore/Modules/webaudio/AudioContext.cpp b/webkit/WebCore/Modules/webaudio/AudioContext.cpp index f9513e22b..e11d643a4 100755 --- a/webkit/WebCore/Modules/webaudio/AudioContext.cpp +++ b/webkit/WebCore/Modules/webaudio/AudioContext.cpp @@ -47,11 +47,13 @@ #include "EventNames.h" #include "ExceptionCode.h" #include "FFTFrame.h" +#include "Frame.h" #include "GainNode.h" #include "GenericEventQueue.h" #include "HRTFDatabaseLoader.h" #include "HRTFPanner.h" #include "JSDOMPromise.h" +#include "NetworkingContext.h" #include "OfflineAudioCompletionEvent.h" #include "OfflineAudioDestinationNode.h" #include "OscillatorNode.h" @@ -372,10 +374,18 @@ void AudioContext::stop() // FIXME: see if there's a more direct way to handle this issue. // FIXME: This sounds very wrong. The whole idea of stop() is that it stops everything, and if we // schedule some observable work for later, the work likely happens at an inappropriate time. +#if !PLATFORM(WKC) callOnMainThread([this] { uninitialize(); clear(); }); +#else + std::function p(std::allocator_arg, WTF::voidFuncAllocator(), [this] { + uninitialize(); + clear(); + }); + callOnMainThread(p); +#endif } bool AudioContext::canSuspendForPageCache() const @@ -400,6 +410,16 @@ const Document* AudioContext::hostingDocument() const return downcast(m_scriptExecutionContext); } +String AudioContext::sourceApplicationIdentifier() const +{ + Document* document = this->document(); + if (Frame* frame = document ? document->frame() : nullptr) { + if (NetworkingContext* networkingContext = frame->loader().networkingContext()) + return networkingContext->sourceApplicationIdentifier(); + } + return emptyString(); +} + PassRefPtr AudioContext::createBuffer(unsigned numberOfChannels, size_t numberOfFrames, float sampleRate, ExceptionCode& ec) { RefPtr audioBuffer = AudioBuffer::create(numberOfChannels, numberOfFrames, sampleRate); @@ -892,9 +912,16 @@ void AudioContext::scheduleNodeDeletion() m_isDeletionScheduled = true; RefPtr strongThis(this); +#if !PLATFORM(WKC) callOnMainThread([strongThis] { strongThis->deleteMarkedNodes(); }); +#else + std::function p(std::allocator_arg, WTF::voidFuncAllocator(), [strongThis] { + strongThis->deleteMarkedNodes(); + }); + callOnMainThread(p); +#endif } } @@ -1097,10 +1124,18 @@ void AudioContext::isPlayingAudioDidChange() // Make sure to call Document::updateIsPlayingMedia() on the main thread, since // we could be on the audio I/O thread here and the call into WebCore could block. RefPtr strongThis(this); +#if !PLATFORM(WKC) callOnMainThread([strongThis] { if (strongThis->document()) strongThis->document()->updateIsPlayingMedia(); }); +#else + std::function p(std::allocator_arg, WTF::voidFuncAllocator(), [strongThis] { + if (strongThis->document()) + strongThis->document()->updateIsPlayingMedia(); + }); + callOnMainThread(p); +#endif } void AudioContext::fireCompletionEvent() diff --git a/webkit/WebCore/Modules/webaudio/AudioContext.h b/webkit/WebCore/Modules/webaudio/AudioContext.h index ab97ce15b..77ed3981a 100755 --- a/webkit/WebCore/Modules/webaudio/AudioContext.h +++ b/webkit/WebCore/Modules/webaudio/AudioContext.h @@ -328,8 +328,10 @@ class AudioContext : public ActiveDOMObject, public ThreadSafeRefCounted>& worlds) static_cast(JSDOMWindow::commonVM().clientData)->getAllWorlds(worlds); } -void ScriptController::clearWindowShell(DOMWindow* newDOMWindow, bool goingIntoPageCache) +void ScriptController::clearWindowShellsNotMatchingDOMWindow(DOMWindow* newDOMWindow, bool goingIntoPageCache) { if (m_windowShells.isEmpty()) return; @@ -205,42 +205,47 @@ void ScriptController::clearWindowShell(DOMWindow* newDOMWindow, bool goingIntoP JSLockHolder lock(JSDOMWindowBase::commonVM()); Vector> windowShells = this->windowShells(); - for (size_t i = 0; i < windowShells.size(); ++i) { - JSDOMWindowShell* windowShell = windowShells[i].get(); - + for (auto& windowShell : windowShells) { if (&windowShell->window()->impl() == newDOMWindow) continue; // Clear the debugger and console from the current window before setting the new window. - attachDebugger(windowShell, nullptr); + attachDebugger(windowShell.get(), nullptr); windowShell->window()->setConsoleClient(nullptr); + windowShell->window()->willRemoveFromWindowShell(); + } - // FIXME: We should clear console profiles for each frame as soon as the frame is destroyed. - // Instead of clearing all of them when the main frame is destroyed. - if (m_frame.isMainFrame()) { - if (Page* page = m_frame.page()) - page->console().clearProfiles(); - } + // It's likely that resetting our windows created a lot of garbage, unless + // it went in a back/forward cache. + if (!goingIntoPageCache) + collectGarbageAfterWindowShellDestruction(); +} - windowShell->window()->willRemoveFromWindowShell(); +void ScriptController::setDOMWindowForWindowShell(DOMWindow* newDOMWindow) +{ + if (m_windowShells.isEmpty()) + return; + + JSLockHolder lock(JSDOMWindowBase::commonVM()); + + Vector> windowShells = this->windowShells(); + for (auto& windowShell : windowShells) { + if (&windowShell->window()->impl() == newDOMWindow) + continue; + windowShell->setWindow(newDOMWindow); - + // An m_cacheableBindingRootObject persists between page navigations // so needs to know about the new JSDOMWindow. if (m_cacheableBindingRootObject) m_cacheableBindingRootObject->updateGlobalObject(windowShell->window()); - + if (Page* page = m_frame.page()) { - attachDebugger(windowShell, page->debugger()); + attachDebugger(windowShell.get(), page->debugger()); windowShell->window()->setProfileGroup(page->group().identifier()); windowShell->window()->setConsoleClient(&page->console()); } } - - // It's likely that resetting our windows created a lot of garbage, unless - // it went in a back/forward cache. - if (!goingIntoPageCache) - collectGarbageAfterWindowShellDestruction(); } JSDOMWindowShell* ScriptController::initScript(DOMWrapperWorld& world) diff --git a/webkit/WebCore/bindings/js/ScriptController.h b/webkit/WebCore/bindings/js/ScriptController.h index ba699aece..76ad5c88e 100755 --- a/webkit/WebCore/bindings/js/ScriptController.h +++ b/webkit/WebCore/bindings/js/ScriptController.h @@ -1,7 +1,7 @@ /* * Copyright (C) 1999 Harri Porten (porten@kde.org) * Copyright (C) 2001 Peter Kelly (pmk@post.com) - * Copyright (C) 2008 Apple Inc. All rights reserved. + * Copyright (C) 2008, 2016 Apple Inc. All rights reserved. * Copyright (C) 2008 Eric Seidel * * This library is free software; you can redistribute it and/or @@ -135,7 +135,8 @@ class ScriptController { const String* sourceURL() const { return m_sourceURL; } // 0 if we are not evaluating any script - void clearWindowShell(DOMWindow* newDOMWindow, bool goingIntoPageCache); + void clearWindowShellsNotMatchingDOMWindow(DOMWindow* newDOMWindow, bool goingIntoPageCache); + void setDOMWindowForWindowShell(DOMWindow* newDOMWindow); void updateDocument(); void namedItemAdded(HTMLDocument*, const AtomicString&) { } diff --git a/webkit/WebCore/bindings/js/SerializedScriptValue.cpp b/webkit/WebCore/bindings/js/SerializedScriptValue.cpp index 7b6f1ab54..52f0d9e84 100755 --- a/webkit/WebCore/bindings/js/SerializedScriptValue.cpp +++ b/webkit/WebCore/bindings/js/SerializedScriptValue.cpp @@ -2250,7 +2250,7 @@ class CloneDeserializer : CloneBase { uint32_t length; if (!read(length)) return JSValue(); - if (m_end < ((uint8_t*)0) + length || m_ptr > m_end - length) { + if (static_cast(m_end - m_ptr) < length) { fail(); return JSValue(); } diff --git a/webkit/WebCore/bindings/scripts/test/JS/JSTestActiveDOMObject.cpp b/webkit/WebCore/bindings/scripts/test/JS/JSTestActiveDOMObject.cpp index 35e8ad369..5a9b29f59 100755 --- a/webkit/WebCore/bindings/scripts/test/JS/JSTestActiveDOMObject.cpp +++ b/webkit/WebCore/bindings/scripts/test/JS/JSTestActiveDOMObject.cpp @@ -179,7 +179,7 @@ EncodedJSValue jsTestActiveDOMObjectExcitingAttr(ExecState* exec, JSObject* slot UNUSED_PARAM(slotBase); UNUSED_PARAM(thisValue); auto* castedThis = jsCast(slotBase); - if (!BindingSecurity::shouldAllowAccessToDOMWindow(exec, castedThis->impl())) + if (!shouldAllowAccessToFrame(state, castedThis->wrapped().frame())) return JSValue::encode(jsUndefined()); auto& impl = castedThis->impl(); JSValue result = jsNumber(impl.excitingAttr()); @@ -209,7 +209,7 @@ EncodedJSValue JSC_HOST_CALL jsTestActiveDOMObjectPrototypeFunctionExcitingFunct if (UNLIKELY(!castedThis)) return throwThisTypeError(*exec, "TestActiveDOMObject", "excitingFunction"); ASSERT_GC_OBJECT_INHERITS(castedThis, JSTestActiveDOMObject::info()); - if (!BindingSecurity::shouldAllowAccessToDOMWindow(exec, castedThis->impl())) + if (!shouldAllowAccessToFrame(state, castedThis->wrapped().frame())) return JSValue::encode(jsUndefined()); auto& impl = castedThis->impl(); if (UNLIKELY(exec->argumentCount() < 1)) diff --git a/webkit/WebCore/contentextensions/ContentExtensionParser.cpp b/webkit/WebCore/contentextensions/ContentExtensionParser.cpp index d882574ed..e396aa372 100755 --- a/webkit/WebCore/contentextensions/ContentExtensionParser.cpp +++ b/webkit/WebCore/contentextensions/ContentExtensionParser.cpp @@ -177,8 +177,9 @@ static std::error_code loadTrigger(ExecState& exec, JSObject& ruleObject, Trigge return { }; } -static bool isValidSelector(const String& selector) +bool isValidCSSSelector(const String& selector) { + AtomicString::init(); CSSParserContext context(CSSQuirksMode); CSSParser parser(context); CSSSelectorList selectorList; @@ -211,7 +212,7 @@ static std::error_code loadAction(ExecState& exec, const JSObject& ruleObject, A return ContentExtensionError::JSONInvalidCSSDisplayNoneActionType; String s = selector.toWTFString(&exec); - if (!isValidSelector(s)) { + if (!isValidCSSSelector(selectorString)) { // Skip rules with invalid selectors to be backwards-compatible. validSelector = false; return { }; diff --git a/webkit/WebCore/contentextensions/ContentExtensionParser.h b/webkit/WebCore/contentextensions/ContentExtensionParser.h index 1f35b6b41..b7fd4b7af 100755 --- a/webkit/WebCore/contentextensions/ContentExtensionParser.h +++ b/webkit/WebCore/contentextensions/ContentExtensionParser.h @@ -39,6 +39,7 @@ namespace ContentExtensions { class ContentExtensionRule; std::error_code parseRuleList(const String& rules, Vector&); +WEBCORE_EXPORT bool isValidCSSSelector(const String&); } // namespace ContentExtensions } // namespace WebCore diff --git a/webkit/WebCore/css/CSSParser.cpp b/webkit/WebCore/css/CSSParser.cpp index c7036dacc..c917ff790 100755 --- a/webkit/WebCore/css/CSSParser.cpp +++ b/webkit/WebCore/css/CSSParser.cpp @@ -691,6 +691,8 @@ static CSSParser::ParseResult parseSimpleLengthValue(MutableStyleProperties* dec static inline bool isValidKeywordPropertyAndValue(CSSPropertyID propertyId, int valueID, const CSSParserContext& parserContext, StyleSheetContents* styleSheetContents) { + UNUSED_PARAM(parserContext); // Make sure parserContext is used. + if (!valueID) return false; @@ -1025,12 +1027,6 @@ static inline bool isValidKeywordPropertyAndValue(CSSPropertyID propertyId, int if (valueID == CSSValueDisc || valueID == CSSValueCircle || valueID == CSSValueSquare || valueID == CSSValueNone) return true; break; -#if ENABLE(IOS_TEXT_AUTOSIZING) - case CSSPropertyWebkitTextSizeAdjust: - if (valueID == CSSValueAuto || valueID == CSSValueNone) - return true; - break; -#endif case CSSPropertyTransformStyle: case CSSPropertyWebkitTransformStyle: if (valueID == CSSValueFlat || valueID == CSSValuePreserve3d) @@ -2920,6 +2916,15 @@ bool CSSParser::parseValue(CSSPropertyID propId, bool important) break; #if ENABLE(IOS_TEXT_AUTOSIZING) case CSSPropertyWebkitTextSizeAdjust: + // FIXME: Support toggling the validation of this property via a runtime setting that is independent of + // whether isTextAutosizingEnabled() is true. We want to enable this property on iOS, when simulating + // a iOS device in Safari's responsive design mode and when optionally enabled in DRT/WTR. Otherwise, + // this property should be disabled by default. +#if !PLATFORM(IOS) + if (!isTextAutosizingEnabled()) + return false; +#endif + if (id == CSSValueAuto || id == CSSValueNone) validPrimitive = true; else { diff --git a/webkit/WebCore/dom/ContainerNode.cpp b/webkit/WebCore/dom/ContainerNode.cpp index 31de5fe2c..efc946a6c 100755 --- a/webkit/WebCore/dom/ContainerNode.cpp +++ b/webkit/WebCore/dom/ContainerNode.cpp @@ -622,20 +622,29 @@ void ContainerNode::removeBetween(Node* previousChild, Node* nextChild, Node& ol void ContainerNode::parserRemoveChild(Node& oldChild) { - ASSERT(oldChild.parentNode() == this); - ASSERT(!oldChild.isDocumentFragment()); + disconnectSubframesIfNeeded(*this, DescendantsOnly); + if (oldChild.parentNode() != this) + return; - Node* prev = oldChild.previousSibling(); - Node* next = oldChild.nextSibling(); + { + NoEventDispatchAssertion assertNoEventDispatch; - oldChild.updateAncestorConnectedSubframeCountForRemoval(); + document().nodeChildrenWillBeRemoved(*this); - ChildListMutationScope(*this).willRemoveChild(oldChild); - oldChild.notifyMutationObserversNodeWillDetach(); + ASSERT(oldChild.parentNode() == this); + ASSERT(!oldChild.isDocumentFragment()); - removeBetween(prev, next, oldChild); + Node* prev = oldChild.previousSibling(); + Node* next = oldChild.nextSibling(); - notifyChildRemoved(oldChild, prev, next, ChildChangeSourceParser); + ChildListMutationScope(*this).willRemoveChild(oldChild); + oldChild.notifyMutationObserversNodeWillDetach(); + + removeBetween(prev, next, oldChild); + + notifyChildRemoved(oldChild, prev, next, ChildChangeSourceParser); + } + document().notifyRemovePendingSheetIfNeeded(); } // this differs from other remove functions because it forcibly removes all the children, @@ -746,11 +755,12 @@ void ContainerNode::parserAppendChild(PassRefPtr newChild) ASSERT(!hasTagName(HTMLNames::templateTag)); #endif - if (&document() != &newChild->document()) - document().adoptNode(newChild.get(), ASSERT_NO_EXCEPTION); - { NoEventDispatchAssertion assertNoEventDispatch; + + if (&document() != &newChild->document()) + document().adoptNode(newChild.get(), ASSERT_NO_EXCEPTION); + // FIXME: This method should take a PassRefPtr. appendChildToContainer(newChild.get(), *this); treeScope().adoptIfNeeded(newChild.get()); diff --git a/webkit/WebCore/dom/ContainerNodeAlgorithms.cpp b/webkit/WebCore/dom/ContainerNodeAlgorithms.cpp index 503de3e41..f8de54822 100755 --- a/webkit/WebCore/dom/ContainerNodeAlgorithms.cpp +++ b/webkit/WebCore/dom/ContainerNodeAlgorithms.cpp @@ -163,9 +163,12 @@ void disconnectSubframes(ContainerNode& root, SubframeDisconnectPolicy policy) collectFrameOwners(frameOwners, root); + if (auto* shadowRoot = root.shadowRoot()) + collectFrameOwners(frameOwners, *shadowRoot); + // Must disable frame loading in the subtree so an unload handler cannot // insert more frames and create loaded frames in detached subtrees. - SubframeLoadingDisabler disabler(root); + SubframeLoadingDisabler disabler(&root); bool isFirst = true; for (auto& owner : frameOwners) { diff --git a/webkit/WebCore/dom/Document.cpp b/webkit/WebCore/dom/Document.cpp index fef11d66d..100c458d7 100755 --- a/webkit/WebCore/dom/Document.cpp +++ b/webkit/WebCore/dom/Document.cpp @@ -155,6 +155,7 @@ #include "TextResourceDecoder.h" #include "TransformSource.h" #include "TreeWalker.h" +#include "ValidationMessageClient.h" #include "VisitedLinkState.h" #include "XMLDocumentParser.h" #include "XMLNSNames.h" @@ -324,19 +325,6 @@ static inline bool isValidNamePart(UChar32 c) return true; } -static bool shouldInheritSecurityOriginFromOwner(const URL& url) -{ - // http://www.whatwg.org/specs/web-apps/current-work/#origin-0 - // - // If a Document has the address "about:blank" - // The origin of the Document is the origin it was assigned when its browsing context was created. - // - // Note: We generalize this to all "blank" URLs and invalid URLs because we - // treat all of these URLs as about:blank. - // - return url.isEmpty() || url.isBlankURL(); -} - static Widget* widgetForElement(Element* focusedElement) { if (!focusedElement) @@ -480,9 +468,6 @@ Document::Document(Frame* frame, const URL& url, unsigned documentClasses, unsig , m_xmlStandalone(StandaloneUnspecified) , m_hasXMLDeclaration(false) , m_designMode(inherit) -#if !ASSERT_DISABLED - , m_inInvalidateNodeListAndCollectionCaches(false) -#endif #if ENABLE(DASHBOARD_SUPPORT) , m_hasAnnotatedRegions(false) , m_annotatedRegionsDirty(false) @@ -1223,7 +1208,7 @@ void Document::setVisualUpdatesAllowed(bool visualUpdatesAllowed) if (frame()->isMainFrame()) { frameView->addPaintPendingMilestones(DidFirstPaintAfterSuppressedIncrementalRendering); if (page->requestedLayoutMilestones() & DidFirstLayoutAfterSuppressedIncrementalRendering) - frame()->loader().didLayout(DidFirstLayoutAfterSuppressedIncrementalRendering); + frame()->loader().didReachLayoutMilestone(DidFirstLayoutAfterSuppressedIncrementalRendering); } } @@ -1734,6 +1719,8 @@ void Document::scheduleForcedStyleRecalc() void Document::scheduleStyleRecalc() { + ASSERT(!m_renderView || !m_renderView->inHitTesting()); + if (m_styleRecalcTimer.isActive() || inPageCache()) return; @@ -2221,8 +2208,8 @@ void Document::destroyRenderTree() documentWillBecomeInactive(); - if (FrameView* frameView = view()) - frameView->detachCustomScrollbars(); + if (auto* frameView = view()) + frameView->willDestroyRenderTree(); #if ENABLE(FULLSCREEN_API) if (m_fullScreenRenderer) @@ -2247,6 +2234,9 @@ void Document::destroyRenderTree() // Do this before the arena is cleared, which is needed to deref the RenderStyle on TextAutoSizingKey. m_textAutoSizedNodes.clear(); #endif + + if (auto* frameView = view()) + frameView->didDestroyRenderTree(); } void Document::prepareForDestruction() @@ -2281,6 +2271,11 @@ void Document::prepareForDestruction() page()->pointerLockController().documentDetached(this); #endif + if (auto* page = this->page()) { + if (auto* validationMessageClient = page->validationMessageClient()) + validationMessageClient->documentDetached(*this); + } + InspectorInstrumentation::documentDetached(*this); stopActiveDOMObjects(); @@ -2323,11 +2318,17 @@ void Document::removeAllEventListeners() if (m_domWindow) m_domWindow->removeAllEventListeners(); + #if ENABLE(IOS_TOUCH_EVENTS) clearTouchEventListeners(); #endif for (Node* node = firstChild(); node; node = NodeTraversal::next(*node)) node->removeAllEventListeners(); + +#if ENABLE(TOUCH_EVENTS) + m_touchEventTargets = nullptr; +#endif + m_wheelEventTargets = nullptr; } void Document::platformSuspendOrStopActiveDOMObjects() @@ -2621,18 +2622,18 @@ void Document::implicitClose() ImageLoader::dispatchPendingErrorEvents(); HTMLLinkElement::dispatchPendingLoadEvents(); HTMLStyleElement::dispatchPendingLoadEvents(); - } - // To align the HTML load event and the SVGLoad event for the outermost element, fire it from - // here, instead of doing it from SVGElement::finishedParsingChildren (if externalResourcesRequired="false", - // which is the default, for ='true' its fired at a later time, once all external resources finished loading). - if (svgExtensions()) - accessSVGExtensions().dispatchSVGLoadEventToOutermostSVGElements(); + // To align the HTML load event and the SVGLoad event for the outermost element, fire it from + // here, instead of doing it from SVGElement::finishedParsingChildren (if externalResourcesRequired="false", + // which is the default, for ='true' its fired at a later time, once all external resources finished loading). + if (svgExtensions()) + accessSVGExtensions().dispatchSVGLoadEventToOutermostSVGElements(); + } dispatchWindowLoadEvent(); - enqueuePageshowEvent(PageshowEventNotPersisted); + dispatchPageshowEvent(PageshowEventNotPersisted); if (m_pendingStateObject) - enqueuePopstateEvent(m_pendingStateObject.release()); + dispatchPopstateEvent(WTF::move(m_pendingStateObject)); if (f) f->loader().handledOnloadEvents(); @@ -3855,9 +3856,7 @@ void Document::unregisterNodeListForInvalidation(LiveNodeList& list) return; list.setRegisteredForInvalidationAtDocument(false); - ASSERT(m_inInvalidateNodeListAndCollectionCaches - ? m_listsInvalidatedAtDocument.isEmpty() - : m_listsInvalidatedAtDocument.contains(&list)); + ASSERT(m_listsInvalidatedAtDocument.contains(&list)); m_listsInvalidatedAtDocument.remove(&list); } @@ -5019,7 +5018,7 @@ void Document::initSecurityContext() setBaseURLOverride(parentDocument->baseURL()); } - if (!shouldInheritSecurityOriginFromOwner(m_url)) + if (!m_url.shouldInheritSecurityOriginFromOwner()) return; // If we do not obtain a meaningful origin from the URL, then we try to @@ -5052,7 +5051,7 @@ void Document::initSecurityContext() void Document::initContentSecurityPolicy() { - if (!m_frame->tree().parent() || (!shouldInheritSecurityOriginFromOwner(m_url) && !isPluginDocument())) + if (!m_frame->tree().parent() || (!m_url.shouldInheritSecurityOriginFromOwner() && !isPluginDocument())) return; contentSecurityPolicy()->copyStateFrom(m_frame->tree().parent()->document()->contentSecurityPolicy()); @@ -5084,7 +5083,7 @@ void Document::statePopped(PassRefPtr stateObject) // Per step 11 of section 6.5.9 (history traversal) of the HTML5 spec, we // defer firing of popstate until we're in the complete state. if (m_readyState == Complete) - enqueuePopstateEvent(stateObject); + dispatchPopstateEvent(stateObject); else m_pendingStateObject = stateObject; } @@ -5393,7 +5392,7 @@ void Document::displayBufferModifiedByEncodingInternal(CharacterType* buffer, un template void Document::displayBufferModifiedByEncodingInternal(LChar*, unsigned) const; template void Document::displayBufferModifiedByEncodingInternal(UChar*, unsigned) const; -void Document::enqueuePageshowEvent(PageshowEventPersistence persisted) +void Document::dispatchPageshowEvent(PageshowEventPersistence persisted) { // FIXME: https://bugs.webkit.org/show_bug.cgi?id=36334 Pageshow event needs to fire asynchronously. dispatchWindowEvent(PageTransitionEvent::create(eventNames().pageshowEvent, persisted), this); @@ -5404,7 +5403,7 @@ void Document::enqueueHashchangeEvent(const String& oldURL, const String& newURL enqueueWindowEvent(HashChangeEvent::create(oldURL, newURL)); } -void Document::enqueuePopstateEvent(PassRefPtr stateObject) +void Document::dispatchPopstateEvent(RefPtr&& stateObject) { dispatchWindowEvent(PopStateEvent::create(stateObject, m_domWindow ? m_domWindow->history() : nullptr)); } diff --git a/webkit/WebCore/dom/Document.h b/webkit/WebCore/dom/Document.h index 954ecac87..ca2ff64c5 100755 --- a/webkit/WebCore/dom/Document.h +++ b/webkit/WebCore/dom/Document.h @@ -1083,9 +1083,9 @@ class Document : public ContainerNode, public TreeScope, public ScriptExecutionC void enqueueWindowEvent(PassRefPtr); void enqueueDocumentEvent(PassRefPtr); void enqueueOverflowEvent(PassRefPtr); - void enqueuePageshowEvent(PageshowEventPersistence); + void dispatchPageshowEvent(PageshowEventPersistence); void enqueueHashchangeEvent(const String& oldURL, const String& newURL); - void enqueuePopstateEvent(PassRefPtr stateObject); + void dispatchPopstateEvent(RefPtr&& stateObject); virtual DocumentEventQueue& eventQueue() const override final { return m_eventQueue; } WEBCORE_EXPORT void addMediaCanStartListener(MediaCanStartListener*); @@ -1171,12 +1171,6 @@ class Document : public ContainerNode, public TreeScope, public ScriptExecutionC double lastHandledUserGestureTimestamp() const { return m_lastHandledUserGestureTimestamp; } void updateLastHandledUserGestureTimestamp(); -#if ENABLE(TOUCH_EVENTS) - bool hasTouchEventHandlers() const { return (m_touchEventTargets.get()) ? m_touchEventTargets->size() : false; } -#else - bool hasTouchEventHandlers() const { return false; } -#endif - // Used for testing. Count handlers in the main document, and one per frame which contains handlers. WEBCORE_EXPORT unsigned wheelEventHandlerCount() const; WEBCORE_EXPORT unsigned touchEventHandlerCount() const; @@ -1184,6 +1178,14 @@ class Document : public ContainerNode, public TreeScope, public ScriptExecutionC WEBCORE_EXPORT void startTrackingStyleRecalcs(); WEBCORE_EXPORT unsigned styleRecalcCount() const; +#if ENABLE(TOUCH_EVENTS) + bool hasTouchEventHandlers() const { return (m_touchEventTargets.get()) ? m_touchEventTargets->size() : false; } + bool touchEventTargetsContain(Node& node) const { return m_touchEventTargets ? m_touchEventTargets->contains(&node) : false; } +#else + bool hasTouchEventHandlers() const { return false; } + bool touchEventTargetsContain(Node&) const { return false; } +#endif + void didAddTouchEventHandler(Node&); void didRemoveTouchEventHandler(Node&, EventHandlerRemoval = EventHandlerRemoval::One); @@ -1545,10 +1547,6 @@ class Document : public ContainerNode, public TreeScope, public ScriptExecutionC HashSet m_listsInvalidatedAtDocument; HashSet m_collectionsInvalidatedAtDocument; -#if !ASSERT_DISABLED - bool m_inInvalidateNodeListAndCollectionCaches; -#endif - unsigned m_nodeListAndCollectionCounts[numNodeListInvalidationTypes]; RefPtr m_xpathEvaluator; diff --git a/webkit/WebCore/dom/Element.cpp b/webkit/WebCore/dom/Element.cpp index 0878800a3..63068d08a 100755 --- a/webkit/WebCore/dom/Element.cpp +++ b/webkit/WebCore/dom/Element.cpp @@ -1875,6 +1875,19 @@ const Vector>& Element::attrNodeList() return *attrNodeListForElement(*this); } +void Element::attachAttributeNodeIfNeeded(Attr& attrNode) +{ + ASSERT(!attrNode.ownerElement() || attrNode.ownerElement() == this); + if (attrNode.ownerElement() == this) + return; + + NoEventDispatchAssertion assertNoEventDispatch; + + attrNode.attachToElement(this); + treeScope().adoptIfNeeded(&attrNode); + ensureAttrNodeListForElement(*this).append(&attrNode); +} + RefPtr Element::setAttributeNode(Attr* attrNode, ExceptionCode& ec) { if (!attrNode) { @@ -1893,33 +1906,39 @@ RefPtr Element::setAttributeNode(Attr* attrNode, ExceptionCode& ec) return nullptr; } + { + NoEventDispatchAssertion assertNoEventDispatch; synchronizeAllAttributes(); + } + UniqueElementData& elementData = ensureUniqueElementData(); unsigned existingAttributeIndex = elementData.findAttributeIndexByName(attrNode->qualifiedName().localName(), shouldIgnoreAttributeCase(*this)); - if (existingAttributeIndex != ElementData::attributeNotFound) { + + // Attr::value() will return its 'm_standaloneValue' member any time its Element is set to nullptr. We need to cache this value + // before making changes to attrNode's Element connections. + auto attrNodeValue = attrNode->value(); + + if (existingAttributeIndex == ElementData::attributeNotFound) { + attachAttributeNodeIfNeeded(*attrNode); + setAttributeInternal(elementData.findAttributeIndexByName(attrNode->qualifiedName()), attrNode->qualifiedName(), attrNodeValue, NotInSynchronizationOfLazyAttribute); + } else { const Attribute& attribute = attributeAt(existingAttributeIndex); if (oldAttrNode) detachAttrNodeFromElementWithValue(oldAttrNode.get(), attribute.value()); else oldAttrNode = Attr::create(document(), attrNode->qualifiedName(), attribute.value()); + attachAttributeNodeIfNeeded(*attrNode); + if (attribute.name().matches(attrNode->qualifiedName())) - setAttributeInternal(existingAttributeIndex, attrNode->qualifiedName(), attrNode->value(), NotInSynchronizationOfLazyAttribute); + setAttributeInternal(existingAttributeIndex, attrNode->qualifiedName(), attrNodeValue, NotInSynchronizationOfLazyAttribute); else { removeAttributeInternal(existingAttributeIndex, NotInSynchronizationOfLazyAttribute); - unsigned existingAttributeIndexForFullQualifiedName = elementData.findAttributeIndexByName(attrNode->qualifiedName()); - setAttributeInternal(existingAttributeIndexForFullQualifiedName, attrNode->qualifiedName(), attrNode->value(), NotInSynchronizationOfLazyAttribute); + setAttributeInternal(ensureUniqueElementData().findAttributeIndexByName(attrNode->qualifiedName()), attrNode->qualifiedName(), attrNodeValue, NotInSynchronizationOfLazyAttribute); } - } else { - unsigned existingAttributeIndexForFullQualifiedName = elementData.findAttributeIndexByName(attrNode->qualifiedName()); - setAttributeInternal(existingAttributeIndexForFullQualifiedName, attrNode->qualifiedName(), attrNode->value(), NotInSynchronizationOfLazyAttribute); - } - if (attrNode->ownerElement() != this) { - attrNode->attachToElement(this); - treeScope().adoptIfNeeded(attrNode); - ensureAttrNodeListForElement(*this).append(attrNode); } + return oldAttrNode; } @@ -1941,22 +1960,29 @@ RefPtr Element::setAttributeNodeNS(Attr* attrNode, ExceptionCode& ec) return 0; } + unsigned index = 0; + + // Attr::value() will return its 'm_standaloneValue' member any time its Element is set to nullptr. We need to cache this value + // before making changes to attrNode's Element connections. + auto attrNodeValue = attrNode->value(); + + { + NoEventDispatchAssertion assertNoEventDispatch; synchronizeAllAttributes(); UniqueElementData& elementData = ensureUniqueElementData(); - unsigned index = elementData.findAttributeIndexByName(attrNode->qualifiedName()); + index = elementData.findAttributeIndexByName(attrNode->qualifiedName()); + if (index != ElementData::attributeNotFound) { if (oldAttrNode) detachAttrNodeFromElementWithValue(oldAttrNode.get(), elementData.attributeAt(index).value()); else oldAttrNode = Attr::create(document(), attrNode->qualifiedName(), elementData.attributeAt(index).value()); } + } - setAttributeInternal(index, attrNode->qualifiedName(), attrNode->value(), NotInSynchronizationOfLazyAttribute); - - attrNode->attachToElement(this); - treeScope().adoptIfNeeded(attrNode); - ensureAttrNodeListForElement(*this).append(attrNode); + attachAttributeNodeIfNeeded(*attrNode); + setAttributeInternal(index, attrNode->qualifiedName(), attrNodeValue, NotInSynchronizationOfLazyAttribute); return oldAttrNode.release(); } diff --git a/webkit/WebCore/dom/Element.h b/webkit/WebCore/dom/Element.h index 1a3961522..e971d4581 100755 --- a/webkit/WebCore/dom/Element.h +++ b/webkit/WebCore/dom/Element.h @@ -3,7 +3,7 @@ * (C) 1999 Antti Koivisto (koivisto@kde.org) * (C) 2001 Peter Kelly (pmk@post.com) * (C) 2001 Dirk Mueller (mueller@kde.org) - * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2003-2017 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -139,6 +139,8 @@ class Element : public ContainerNode { // to the render layer and merge bindingsOffsetParent and offsetParent. Element* bindingsOffsetParent(); + const Element* rootElement() const; + Element* offsetParent(); double clientLeft(); double clientTop(); @@ -396,6 +398,8 @@ class Element : public ContainerNode { virtual bool isInRange() const { return false; } virtual bool isOutOfRange() const { return false; } virtual bool isFrameElementBase() const { return false; } + virtual bool isUploadButton() const { return false; } + virtual bool isSliderContainerElement() const { return false; } virtual bool canContainRangeEndPoint() const override; @@ -594,6 +598,8 @@ class Element : public ContainerNode { // Anyone thinking of using this should call document instead of ownerDocument. void ownerDocument() const = delete; + + void attachAttributeNodeIfNeeded(Attr&); QualifiedName m_tagName; RefPtr m_elementData; @@ -615,6 +621,17 @@ inline Element* Node::parentElement() const return is(parent) ? downcast(parent) : nullptr; } +inline const Element* Element::rootElement() const +{ + if (inDocument()) + return document().documentElement(); + + const Element* highest = this; + while (highest->parentElement()) + highest = highest->parentElement(); + return highest; +} + inline bool Element::fastHasAttribute(const QualifiedName& name) const { ASSERT(fastAttributeLookupAllowed(name)); diff --git a/webkit/WebCore/dom/Event.cpp b/webkit/WebCore/dom/Event.cpp index 1d0fe6135..11dd4bd63 100755 --- a/webkit/WebCore/dom/Event.cpp +++ b/webkit/WebCore/dom/Event.cpp @@ -198,6 +198,11 @@ void Event::setTarget(PassRefPtr target) receivedTarget(); } +void Event::setCurrentTarget(EventTarget* currentTarget) +{ + m_currentTarget = currentTarget; +} + void Event::receivedTarget() { } diff --git a/webkit/WebCore/dom/Event.h b/webkit/WebCore/dom/Event.h index ffb0fa520..b07a0aa05 100755 --- a/webkit/WebCore/dom/Event.h +++ b/webkit/WebCore/dom/Event.h @@ -111,8 +111,8 @@ class Event : public ScriptWrappable, public RefCounted { EventTarget* target() const { return m_target.get(); } void setTarget(PassRefPtr); - EventTarget* currentTarget() const { return m_currentTarget; } - void setCurrentTarget(EventTarget* currentTarget) { m_currentTarget = currentTarget; } + EventTarget* currentTarget() const { return m_currentTarget.get(); } + void setCurrentTarget(EventTarget*); unsigned short eventPhase() const { return m_eventPhase; } void setEventPhase(unsigned short eventPhase) { m_eventPhase = eventPhase; } @@ -203,7 +203,7 @@ class Event : public ScriptWrappable, public RefCounted { bool m_cancelBubble; unsigned short m_eventPhase; - EventTarget* m_currentTarget; + RefPtr m_currentTarget; RefPtr m_target; DOMTimeStamp m_createTime; diff --git a/webkit/WebCore/dom/Node.cpp b/webkit/WebCore/dom/Node.cpp index fb8cbb494..bc9157bbf 100755 --- a/webkit/WebCore/dom/Node.cpp +++ b/webkit/WebCore/dom/Node.cpp @@ -341,6 +341,14 @@ Node::~Node() willBeDeletedFrom(document()); document().decrementReferencingNodeCount(); + +#if ENABLE(TOUCH_EVENTS) && PLATFORM(IOS) && (!ASSERT_DISABLED || ENABLE(SECURITY_ASSERTIONS)) + for (auto* document : Document::allDocuments()) { + ASSERT_WITH_SECURITY_IMPLICATION(!document->touchEventListenersContain(*this)); + ASSERT_WITH_SECURITY_IMPLICATION(!document->touchEventHandlersContain(*this)); + ASSERT_WITH_SECURITY_IMPLICATION(!document->touchEventTargetsContain(*this)); + } +#endif } void Node::willBeDeletedFrom(Document& document) @@ -780,19 +788,15 @@ bool Document::shouldInvalidateNodeListAndCollectionCaches(const QualifiedName* void Document::invalidateNodeListAndCollectionCaches(const QualifiedName* attrName) { -#if !ASSERT_DISABLED - m_inInvalidateNodeListAndCollectionCaches = true; -#endif - HashSet lists = WTF::move(m_listsInvalidatedAtDocument); - m_listsInvalidatedAtDocument.clear(); + Vector lists; + copyToVector(m_listsInvalidatedAtDocument, lists); for (auto* list : lists) list->invalidateCacheForAttribute(attrName); - HashSet collections = WTF::move(m_collectionsInvalidatedAtDocument); + + Vector collections; + copyToVector(m_collectionsInvalidatedAtDocument, collections); for (auto* collection : collections) collection->invalidateCache(attrName); -#if !ASSERT_DISABLED - m_inInvalidateNodeListAndCollectionCaches = false; -#endif } void Node::invalidateNodeListAndCollectionCachesInAncestors(const QualifiedName* attrName, Element* attributeOwnerElement) @@ -1844,7 +1848,7 @@ static inline bool tryAddEventListener(Node* targetNode, const AtomicString& eve #endif // PLATFORM(IOS) #if ENABLE(IOS_GESTURE_EVENTS) && ENABLE(TOUCH_EVENTS) - if (eventType == eventNames().gesturestartEvent || eventType == eventNames().gesturechangeEvent || eventType == eventNames().gestureendEvent) + if (eventNames().isGestureEventType(eventType)) targetNode->document().addTouchEventListener(targetNode); #endif @@ -1885,7 +1889,7 @@ static inline bool tryRemoveEventListener(Node* targetNode, const AtomicString& #endif // PLATFORM(IOS) #if ENABLE(IOS_GESTURE_EVENTS) && ENABLE(TOUCH_EVENTS) - if (eventType == eventNames().gesturestartEvent || eventType == eventNames().gesturechangeEvent || eventType == eventNames().gestureendEvent) + if (eventNames().isGestureEventType(eventType)) targetNode->document().removeTouchEventListener(targetNode); #endif diff --git a/webkit/WebCore/dom/ScriptExecutionContext.h b/webkit/WebCore/dom/ScriptExecutionContext.h index 5b46da15f..fcd27c76e 100755 --- a/webkit/WebCore/dom/ScriptExecutionContext.h +++ b/webkit/WebCore/dom/ScriptExecutionContext.h @@ -129,7 +129,11 @@ class ScriptExecutionContext : public SecurityContext, public Supplementable #endif Task(T task) +#if !PLATFORM(WKC) : m_task(WTF::move(task)) +#else + : m_task(std::allocator_arg, m_allocator, WTF::move(task)) +#endif , m_isCleanupTask(false) { } diff --git a/webkit/WebCore/editing/AlternativeTextController.cpp b/webkit/WebCore/editing/AlternativeTextController.cpp index 275e430eb..0576b12bd 100755 --- a/webkit/WebCore/editing/AlternativeTextController.cpp +++ b/webkit/WebCore/editing/AlternativeTextController.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2006-2008, 2016 Apple Inc. All rights reserved. * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) * * Redistribution and use in source and binary forms, with or without @@ -317,6 +317,8 @@ void AlternativeTextController::respondToUnappliedSpellCorrection(const VisibleS { if (AlternativeTextClient* client = alternativeTextClient()) client->recordAutocorrectionResponse(AutocorrectionReverted, corrected, correction); + + Ref

  • A display symbol, for a specific locale + *
  • The number of fraction digits to display + *
  • A rounding increment + *
+ * + * The DecimalFormat class uses these data to display + * currencies. + * @author Alan Liu + * @since ICU 2.2 + */ + +/** + * Finds a currency code for the given locale. + * @param locale the locale for which to retrieve a currency code. + * Currency can be specified by the "currency" keyword + * in which case it overrides the default currency code + * @param buff fill in buffer. Can be NULL for preflighting. + * @param buffCapacity capacity of the fill in buffer. Can be 0 for + * preflighting. If it is non-zero, the buff parameter + * must not be NULL. + * @param ec error code + * @return length of the currency string. It should always be 3. If 0, + * currency couldn't be found or the input values are + * invalid. + * @stable ICU 2.8 + */ +U_STABLE int32_t U_EXPORT2 +ucurr_forLocale(const char* locale, + UChar* buff, + int32_t buffCapacity, + UErrorCode* ec); + +/** + * Selector constants for ucurr_getName(). + * + * @see ucurr_getName + * @stable ICU 2.6 + */ +typedef enum UCurrNameStyle { + /** + * Selector for ucurr_getName indicating a symbolic name for a + * currency, such as "$" for USD. + * @stable ICU 2.6 + */ + UCURR_SYMBOL_NAME, + + /** + * Selector for ucurr_getName indicating the long name for a + * currency, such as "US Dollar" for USD. + * @stable ICU 2.6 + */ + UCURR_LONG_NAME +} UCurrNameStyle; + +#if !UCONFIG_NO_SERVICE +/** + * @stable ICU 2.6 + */ +typedef const void* UCurrRegistryKey; + +/** + * Register an (existing) ISO 4217 currency code for the given locale. + * Only the country code and the two variants EURO and PRE_EURO are + * recognized. + * @param isoCode the three-letter ISO 4217 currency code + * @param locale the locale for which to register this currency code + * @param status the in/out status code + * @return a registry key that can be used to unregister this currency code, or NULL + * if there was an error. + * @stable ICU 2.6 + */ +U_STABLE UCurrRegistryKey U_EXPORT2 +ucurr_register(const UChar* isoCode, + const char* locale, + UErrorCode* status); +/** + * Unregister the previously-registered currency definitions using the + * URegistryKey returned from ucurr_register. Key becomes invalid after + * a successful call and should not be used again. Any currency + * that might have been hidden by the original ucurr_register call is + * restored. + * @param key the registry key returned by a previous call to ucurr_register + * @param status the in/out status code, no special meanings are assigned + * @return TRUE if the currency for this key was successfully unregistered + * @stable ICU 2.6 + */ +U_STABLE UBool U_EXPORT2 +ucurr_unregister(UCurrRegistryKey key, UErrorCode* status); +#endif /* UCONFIG_NO_SERVICE */ + +/** + * Returns the display name for the given currency in the + * given locale. For example, the display name for the USD + * currency object in the en_US locale is "$". + * @param currency null-terminated 3-letter ISO 4217 code + * @param locale locale in which to display currency + * @param nameStyle selector for which kind of name to return + * @param isChoiceFormat fill-in set to TRUE if the returned value + * is a ChoiceFormat pattern; otherwise it is a static string + * @param len fill-in parameter to receive length of result + * @param ec error code + * @return pointer to display string of 'len' UChars. If the resource + * data contains no entry for 'currency', then 'currency' itself is + * returned. If *isChoiceFormat is TRUE, then the result is a + * ChoiceFormat pattern. Otherwise it is a static string. + * @stable ICU 2.6 + */ +U_STABLE const UChar* U_EXPORT2 +ucurr_getName(const UChar* currency, + const char* locale, + UCurrNameStyle nameStyle, + UBool* isChoiceFormat, + int32_t* len, + UErrorCode* ec); + +/** + * Returns the plural name for the given currency in the + * given locale. For example, the plural name for the USD + * currency object in the en_US locale is "US dollar" or "US dollars". + * @param currency null-terminated 3-letter ISO 4217 code + * @param locale locale in which to display currency + * @param isChoiceFormat fill-in set to TRUE if the returned value + * is a ChoiceFormat pattern; otherwise it is a static string + * @param pluralCount plural count + * @param len fill-in parameter to receive length of result + * @param ec error code + * @return pointer to display string of 'len' UChars. If the resource + * data contains no entry for 'currency', then 'currency' itself is + * returned. + * @stable ICU 4.2 + */ +U_STABLE const UChar* U_EXPORT2 +ucurr_getPluralName(const UChar* currency, + const char* locale, + UBool* isChoiceFormat, + const char* pluralCount, + int32_t* len, + UErrorCode* ec); + +/** + * Returns the number of the number of fraction digits that should + * be displayed for the given currency. + * @param currency null-terminated 3-letter ISO 4217 code + * @param ec input-output error code + * @return a non-negative number of fraction digits to be + * displayed, or 0 if there is an error + * @stable ICU 3.0 + */ +U_STABLE int32_t U_EXPORT2 +ucurr_getDefaultFractionDigits(const UChar* currency, + UErrorCode* ec); + +/** + * Returns the rounding increment for the given currency, or 0.0 if no + * rounding is done by the currency. + * @param currency null-terminated 3-letter ISO 4217 code + * @param ec input-output error code + * @return the non-negative rounding increment, or 0.0 if none, + * or 0.0 if there is an error + * @stable ICU 3.0 + */ +U_STABLE double U_EXPORT2 +ucurr_getRoundingIncrement(const UChar* currency, + UErrorCode* ec); + +/** + * Selector constants for ucurr_openCurrencies(). + * + * @see ucurr_openCurrencies + * @stable ICU 3.2 + */ +typedef enum UCurrCurrencyType { + /** + * Select all ISO-4217 currency codes. + * @stable ICU 3.2 + */ + UCURR_ALL = INT32_MAX, + /** + * Select only ISO-4217 commonly used currency codes. + * These currencies can be found in common use, and they usually have + * bank notes or coins associated with the currency code. + * This does not include fund codes, precious metals and other + * various ISO-4217 codes limited to special financial products. + * @stable ICU 3.2 + */ + UCURR_COMMON = 1, + /** + * Select ISO-4217 uncommon currency codes. + * These codes respresent fund codes, precious metals and other + * various ISO-4217 codes limited to special financial products. + * A fund code is a monetary resource associated with a currency. + * @stable ICU 3.2 + */ + UCURR_UNCOMMON = 2, + /** + * Select only deprecated ISO-4217 codes. + * These codes are no longer in general public use. + * @stable ICU 3.2 + */ + UCURR_DEPRECATED = 4, + /** + * Select only non-deprecated ISO-4217 codes. + * These codes are in general public use. + * @stable ICU 3.2 + */ + UCURR_NON_DEPRECATED = 8 +} UCurrCurrencyType; + +/** + * Provides a UEnumeration object for listing ISO-4217 codes. + * @param currType You can use one of several UCurrCurrencyType values for this + * variable. You can also | (or) them together to get a specific list of + * currencies. Most people will want to use the (UCURR_CURRENCY|UCURR_NON_DEPRECATED) value to + * get a list of current currencies. + * @param pErrorCode Error code + * @stable ICU 3.2 + */ +U_STABLE UEnumeration * U_EXPORT2 +ucurr_openISOCurrencies(uint32_t currType, UErrorCode *pErrorCode); + +/** + * Queries if the given ISO 4217 3-letter code is available on the specified date range. + * + * Note: For checking availability of a currency on a specific date, specify the date on both 'from' and 'to' + * + * When 'from' is U_DATE_MIN and 'to' is U_DATE_MAX, this method checks if the specified currency is available any time. + * If 'from' and 'to' are same UDate value, this method checks if the specified currency is available on that date. + * + * @param isoCode + * The ISO 4217 3-letter code. + * + * @param from + * The lower bound of the date range, inclusive. When 'from' is U_DATE_MIN, check the availability + * of the currency any date before 'to' + * + * @param to + * The upper bound of the date range, inclusive. When 'to' is U_DATE_MAX, check the availability of + * the currency any date after 'from' + * + * @param errorCode + * ICU error code + * + * @return TRUE if the given ISO 4217 3-letter code is supported on the specified date range. + * + * @stable ICU 4.8 + */ +U_STABLE UBool U_EXPORT2 +ucurr_isAvailable(const UChar* isoCode, + UDate from, + UDate to, + UErrorCode* errorCode); + +/** + * Finds the number of valid currency codes for the + * given locale and date. + * @param locale the locale for which to retrieve the + * currency count. + * @param date the date for which to retrieve the + * currency count for the given locale. + * @param ec error code + * @return the number of currency codes for the + * given locale and date. If 0, currency + * codes couldn't be found for the input + * values are invalid. + * @stable ICU 4.0 + */ +U_STABLE int32_t U_EXPORT2 +ucurr_countCurrencies(const char* locale, + UDate date, + UErrorCode* ec); + +/** + * Finds a currency code for the given locale and date + * @param locale the locale for which to retrieve a currency code. + * Currency can be specified by the "currency" keyword + * in which case it overrides the default currency code + * @param date the date for which to retrieve a currency code for + * the given locale. + * @param index the index within the available list of currency codes + * for the given locale on the given date. + * @param buff fill in buffer. Can be NULL for preflighting. + * @param buffCapacity capacity of the fill in buffer. Can be 0 for + * preflighting. If it is non-zero, the buff parameter + * must not be NULL. + * @param ec error code + * @return length of the currency string. It should always be 3. + * If 0, currency couldn't be found or the input values are + * invalid. + * @stable ICU 4.0 + */ +U_STABLE int32_t U_EXPORT2 +ucurr_forLocaleAndDate(const char* locale, + UDate date, + int32_t index, + UChar* buff, + int32_t buffCapacity, + UErrorCode* ec); + +/** + * Given a key and a locale, returns an array of string values in a preferred + * order that would make a difference. These are all and only those values where + * the open (creation) of the service with the locale formed from the input locale + * plus input keyword and that value has different behavior than creation with the + * input locale alone. + * @param key one of the keys supported by this service. For now, only + * "currency" is supported. + * @param locale the locale + * @param commonlyUsed if set to true it will return only commonly used values + * with the given locale in preferred order. Otherwise, + * it will return all the available values for the locale. + * @param status error status + * @return a string enumeration over keyword values for the given key and the locale. + * @stable ICU 4.2 + */ +U_STABLE UEnumeration* U_EXPORT2 +ucurr_getKeywordValuesForLocale(const char* key, + const char* locale, + UBool commonlyUsed, + UErrorCode* status); + +/** + * Returns the ISO 4217 numeric code for the currency. + *

Note: If the ISO 4217 numeric code is not assigned for the currency or + * the currency is unknown, this function returns 0. + * + * @param currency null-terminated 3-letter ISO 4217 code + * @return The ISO 4217 numeric code of the currency + * @stable ICU 49 + */ +U_STABLE int32_t U_EXPORT2 +ucurr_getNumericCode(const UChar* currency); + +#endif /* #if !UCONFIG_NO_FORMATTING */ + +#endif diff --git a/webkit/WebCore/loader/CrossOriginAccessControl.cpp b/webkit/WebCore/loader/CrossOriginAccessControl.cpp index 70cca1798..a8dcdc466 100755 --- a/webkit/WebCore/loader/CrossOriginAccessControl.cpp +++ b/webkit/WebCore/loader/CrossOriginAccessControl.cpp @@ -125,6 +125,8 @@ void updateRequestForAccessControl(ResourceRequest& request, SecurityOrigin* sec ResourceRequest createAccessControlPreflightRequest(const ResourceRequest& request, SecurityOrigin* securityOrigin) { ResourceRequest preflightRequest(request.url()); + static const double platformDefaultTimeout = 0; + preflightRequest.setTimeoutInterval(platformDefaultTimeout); updateRequestForAccessControl(preflightRequest, securityOrigin, DoNotAllowStoredCredentials); preflightRequest.setHTTPMethod("OPTIONS"); preflightRequest.setHTTPHeaderField(HTTPHeaderName::AccessControlRequestMethod, request.httpMethod()); diff --git a/webkit/WebCore/loader/DocumentLoader.cpp b/webkit/WebCore/loader/DocumentLoader.cpp index 9d9ffc96e..9ef8b6e99 100755 --- a/webkit/WebCore/loader/DocumentLoader.cpp +++ b/webkit/WebCore/loader/DocumentLoader.cpp @@ -331,19 +331,20 @@ void DocumentLoader::stopLoading() m_isStopping = true; - FrameLoader* frameLoader = DocumentLoader::frameLoader(); - - if (isLoadingMainResource()) { - // Stop the main resource loader and let it send the cancelled message. - cancelMainResourceLoad(frameLoader->cancelledError(m_request)); - } else if (!m_subresourceLoaders.isEmpty() || !m_plugInStreamLoaders.isEmpty()) { - // The main resource loader already finished loading. Set the cancelled error on the - // document and let the subresourceLoaders and pluginLoaders send individual cancelled messages below. - setMainDocumentError(frameLoader->cancelledError(m_request)); - } else { - // If there are no resource loaders, we need to manufacture a cancelled message. - // (A back/forward navigation has no resource loaders because its resources are cached.) - mainReceivedError(frameLoader->cancelledError(m_request)); + // The frame may have been detached from this document by the onunload handler + if (auto* frameLoader = DocumentLoader::frameLoader()) { + if (isLoadingMainResource()) { + // Stop the main resource loader and let it send the cancelled message. + cancelMainResourceLoad(frameLoader->cancelledError(m_request)); + } else if (!m_subresourceLoaders.isEmpty() || !m_plugInStreamLoaders.isEmpty()) { + // The main resource loader already finished loading. Set the cancelled error on the + // document and let the subresourceLoaders and pluginLoaders send individual cancelled messages below. + setMainDocumentError(frameLoader->cancelledError(m_request)); + } else { + // If there are no resource loaders, we need to manufacture a cancelled message. + // (A back/forward navigation has no resource loaders because its resources are cached.) + mainReceivedError(frameLoader->cancelledError(m_request)); + } } // We always need to explicitly cancel the Document's parser when stopping the load. diff --git a/webkit/WebCore/loader/DocumentThreadableLoader.cpp b/webkit/WebCore/loader/DocumentThreadableLoader.cpp index b0e5898bb..1d84e4de2 100755 --- a/webkit/WebCore/loader/DocumentThreadableLoader.cpp +++ b/webkit/WebCore/loader/DocumentThreadableLoader.cpp @@ -76,6 +76,8 @@ DocumentThreadableLoader::DocumentThreadableLoader(Document& document, Threadabl , m_simpleRequest(true) , m_async(blockingBehavior == LoadAsynchronously) { + relaxAdoptionRequirement(); + // Setting an outgoing referer is only supported in the async code path. ASSERT(m_async || request.httpReferrer().isEmpty()); @@ -345,6 +347,8 @@ void DocumentThreadableLoader::preflightFailure(unsigned long identifier, const void DocumentThreadableLoader::loadRequest(const ResourceRequest& request, SecurityCheckPolicy securityCheck) { + Ref protectedThis(*this); + // Any credential should have been removed from the cross-site requests. const URL& requestURL = request.url(); m_options.setSecurityCheck(securityCheck); @@ -367,6 +371,11 @@ void DocumentThreadableLoader::loadRequest(const ResourceRequest& request, Secur newRequest.setInitiator(m_options.initiator); #endif ASSERT(!m_resource); + if (m_resource) { + CachedResourceHandle resource = std::exchange(m_resource, nullptr); + resource->removeClient(this); + } + m_resource = m_document.cachedResourceLoader().requestRawResource(newRequest); if (m_resource) m_resource->addClient(this); @@ -379,8 +388,12 @@ void DocumentThreadableLoader::loadRequest(const ResourceRequest& request, Secur ResourceError error; ResourceResponse response; unsigned long identifier = std::numeric_limits::max(); - if (m_document.frame()) - identifier = m_document.frame()->loader().loadResourceSynchronously(request, m_options.allowCredentials(), m_options.clientCredentialPolicy(), error, response, data); + if (m_document.frame()) { + auto& frameLoader = m_document.frame()->loader(); + if (!frameLoader.mixedContentChecker().canRunInsecureContent(m_document.securityOrigin(), requestURL)) + return; + identifier = frameLoader.loadResourceSynchronously(request, m_options.allowCredentials(), m_options.clientCredentialPolicy(), error, response, data); + } if (!error.isNull() && response.httpStatusCode() <= 0) { if (requestURL.isLocalFile()) { diff --git a/webkit/WebCore/loader/DocumentWriter.cpp b/webkit/WebCore/loader/DocumentWriter.cpp index a1c377f8e..3a6720dd7 100755 --- a/webkit/WebCore/loader/DocumentWriter.cpp +++ b/webkit/WebCore/loader/DocumentWriter.cpp @@ -71,6 +71,12 @@ DocumentWriter::DocumentWriter(Frame* frame) void DocumentWriter::replaceDocument(const String& source, Document* ownerDocument) { m_frame->loader().stopAllLoaders(); + + // If we are in the midst of changing the frame's document, don't execute script + // that modifes the document further: + if (m_frame->documentIsBeingReplaced()) + return; + begin(m_frame->document()->url(), true, ownerDocument); if (!source.isNull()) { diff --git a/webkit/WebCore/loader/EmptyClients.h b/webkit/WebCore/loader/EmptyClients.h index 9c2e9e269..dc817b474 100755 --- a/webkit/WebCore/loader/EmptyClients.h +++ b/webkit/WebCore/loader/EmptyClients.h @@ -294,7 +294,7 @@ class EmptyFrameLoaderClient : public FrameLoaderClient { virtual void dispatchDidFailLoad(const ResourceError&) override { } virtual void dispatchDidFinishDocumentLoad() override { } virtual void dispatchDidFinishLoad() override { } - virtual void dispatchDidLayout(LayoutMilestones) override { } + void dispatchDidReachLayoutMilestone(LayoutMilestones) override { } virtual Frame* dispatchCreatePage(const NavigationAction&) override { return 0; } virtual void dispatchShow() override { } @@ -386,7 +386,7 @@ class EmptyFrameLoaderClient : public FrameLoaderClient { virtual String overrideMediaType() const override { return String(); } #if ENABLE(NETSCAPE_PLUGIN_API) - virtual void redirectDataToPlugin(Widget*) override { } + void redirectDataToPlugin(Widget*) override { } #endif virtual void dispatchDidClearWindowObjectInWorld(DOMWrapperWorld&) override { } @@ -458,6 +458,7 @@ class EmptyEditorClient : public EditorClient { virtual void respondToChangedContents() override { } virtual void respondToChangedSelection(Frame*) override { } virtual void didChangeSelectionAndUpdateLayout() override { } + void updateEditorStateAfterLayoutIfEditabilityChanged() override { } virtual void discardedComposition(Frame*) override { } virtual void didEndEditing() override { } virtual void willWriteSelectionToPasteboard(Range*) override { } diff --git a/webkit/WebCore/loader/FormSubmission.cpp b/webkit/WebCore/loader/FormSubmission.cpp index 056804bed..02d6d30da 100755 --- a/webkit/WebCore/loader/FormSubmission.cpp +++ b/webkit/WebCore/loader/FormSubmission.cpp @@ -205,19 +205,23 @@ Ref FormSubmission::create(HTMLFormElement* form, const Attribut Vector> formValues; bool containsPasswordData = false; - for (unsigned i = 0; i < form->associatedElements().size(); ++i) { - FormAssociatedElement& control = *form->associatedElements()[i]; - HTMLElement& element = control.asHTMLElement(); - if (!element.isDisabledFormControl()) - control.appendFormData(*domFormData, isMultiPartForm); - if (is(element)) { - HTMLInputElement& input = downcast(element); - if (input.isTextField()) { - formValues.append(std::pair(input.name().string(), input.value())); - input.addSearchResult(); + { + NoEventDispatchAssertion noEventDispatchAssertion; + + for (auto& control : form->associatedElements()) { + auto& element = control->asHTMLElement(); + if (!element.isDisabledFormControl()) + control->appendFormData(*domFormData, isMultiPartForm); + if (is(element)) { + auto& input = downcast(element); + if (input.isTextField()) { + // formValues.append({ input.name().string(), input.value() }); + formValues.append(std::pair(input.name().string(), input.value())); + input.addSearchResult(); + } + if (input.isPasswordField() && !input.value().isEmpty()) + containsPasswordData = true; } - if (input.isPasswordField() && !input.value().isEmpty()) - containsPasswordData = true; } } diff --git a/webkit/WebCore/loader/FrameLoader.cpp b/webkit/WebCore/loader/FrameLoader.cpp index f19c399e9..126e8146d 100755 --- a/webkit/WebCore/loader/FrameLoader.cpp +++ b/webkit/WebCore/loader/FrameLoader.cpp @@ -594,7 +594,7 @@ void FrameLoader::clear(Document* newDocument, bool clearWindowProperties, bool if (clearWindowProperties) { InspectorInstrumentation::frameWindowDiscarded(&m_frame, m_frame.document()->domWindow()); m_frame.document()->domWindow()->resetUnlessSuspendedForPageCache(); - m_frame.script().clearWindowShell(newDocument->domWindow(), m_frame.document()->inPageCache()); + m_frame.script().clearWindowShellsNotMatchingDOMWindow(newDocument->domWindow(), m_frame.document()->inPageCache()); } m_frame.selection().prepareForDestruction(); @@ -608,6 +608,9 @@ void FrameLoader::clear(Document* newDocument, bool clearWindowProperties, bool subframeLoader().clear(); + if (clearWindowProperties) + m_frame.script().setDOMWindowForWindowShell(newDocument->domWindow()); + if (clearScriptObjects) m_frame.script().clearScriptObjects(); @@ -1175,6 +1178,11 @@ static ShouldOpenExternalURLsPolicy shouldOpenExternalURLsPolicyToApply(Frame& s return propagatedPolicy; } +bool FrameLoader::isNavigationAllowed() const +{ + return m_pageDismissalEventBeingDispatched == PageDismissalType::None && NavigationDisablerForBeforeUnload::isNavigationAllowed(); +} + void FrameLoader::loadURL(const FrameLoadRequest& frameLoadRequest, const String& referrer, FrameLoadType newLoadType, Event* event, PassRefPtr prpFormState) { if (m_inStopAllLoaders) @@ -1215,7 +1223,7 @@ void FrameLoader::loadURL(const FrameLoadRequest& frameLoadRequest, const String return; } - if (m_pageDismissalEventBeingDispatched != PageDismissalType::None) + if (!isNavigationAllowed()) return; #if PLATFORM(WKC) @@ -1428,7 +1436,7 @@ void FrameLoader::loadWithDocumentLoader(DocumentLoader* loader, FrameLoadType t ASSERT(m_frame.view()); - if (m_pageDismissalEventBeingDispatched != PageDismissalType::None) + if (!isNavigationAllowed()) return; if (m_frame.document()) @@ -1627,7 +1635,7 @@ void FrameLoader::reload(bool endToEndReload) void FrameLoader::stopAllLoaders(ClearProvisionalItemPolicy clearProvisionalItemPolicy) { ASSERT(!m_frame.document() || !m_frame.document()->inPageCache()); - if (m_pageDismissalEventBeingDispatched != PageDismissalType::None) + if (!isNavigationAllowed()) return; // If this method is called from within this method, infinite recursion can occur (3442218). Avoid this. @@ -1844,12 +1852,13 @@ void FrameLoader::commitProvisionalLoad() // commit to happen before any changes to viewport arguments and dealing with this there is difficult. m_frame.page()->chrome().setDispatchViewportDataDidChangeSuppressed(true); #endif - prepareForCachedPageRestore(); + willRestoreFromCachedPage(); // FIXME: This API should be turned around so that we ground CachedPage into the Page. cachedPage->restore(*m_frame.page()); dispatchDidCommitLoad(); + #if PLATFORM(IOS) m_frame.page()->chrome().setDispatchViewportDataDidChangeSuppressed(false); m_frame.page()->chrome().dispatchViewportPropertiesDidChange(m_frame.page()->viewportArguments()); @@ -1930,20 +1939,20 @@ void FrameLoader::transitionToCommitted(CachedPage* cachedPage) if (pdl != m_provisionalDocumentLoader) return; - // Nothing else can interupt this commit - set the Provisional->Committed transition in stone if (m_documentLoader) m_documentLoader->stopLoadingSubresources(); if (m_documentLoader) m_documentLoader->stopLoadingPlugIns(); + // Setting our document loader invokes the unload event handler of our child frames. + // Script can do anything. If the script initiates a new load, we need to abandon the + // current load or the two will stomp each other. setDocumentLoader(m_provisionalDocumentLoader.get()); - setProvisionalDocumentLoader(0); - - if (pdl != m_documentLoader) { - ASSERT(m_state == FrameStateComplete); + if (pdl != m_provisionalDocumentLoader) return; - } + setProvisionalDocumentLoader(0); + // Nothing else can interupt this commit - set the Provisional->Committed transition in stone setState(FrameStateCommittedPage); #if ENABLE(TOUCH_EVENTS) && !PLATFORM(IOS) @@ -2072,7 +2081,7 @@ void FrameLoader::closeOldDataSources() m_client.setMainFrameDocumentReady(false); // stop giving out the actual DOMDocument to observers } -void FrameLoader::prepareForCachedPageRestore() +void FrameLoader::willRestoreFromCachedPage() { ASSERT(!m_frame.tree().parent()); ASSERT(m_frame.page()); @@ -2412,11 +2421,11 @@ void FrameLoader::setOriginalURLForDownloadRequest(ResourceRequest& request) } } -void FrameLoader::didLayout(LayoutMilestones milestones) +void FrameLoader::didReachLayoutMilestone(LayoutMilestones milestones) { ASSERT(m_frame.isMainFrame()); - m_client.dispatchDidLayout(milestones); + m_client.dispatchDidReachLayoutMilestone(milestones); } void FrameLoader::didFirstLayout() @@ -2451,6 +2460,11 @@ void FrameLoader::frameLoadCompleted() void FrameLoader::detachChildren() { + // Any subframe inserted by unload event handlers executed in the loop below will not get unloaded + // because we create a copy of the subframes list before looping. Therefore, it would be unsafe to + // allow loading of subframes at this point. + SubframeLoadingDisabler subframeLoadingDisabler(m_frame.document()); + Vector, 16> childrenToDetach; childrenToDetach.reserveInitialCapacity(m_frame.tree().childCount()); for (Frame* child = m_frame.tree().lastChild(); child; child = child->tree().previousSibling()) @@ -3106,6 +3120,8 @@ void FrameLoader::continueLoadAfterNewWindowPolicy(const ResourceRequest& reques if (!mainFrame) return; + mainFrame->loader().forceSandboxFlags(frame->loader().effectiveSandboxFlags()); + if (frameName != "_blank") mainFrame->tree().setName(frameName); diff --git a/webkit/WebCore/loader/FrameLoader.h b/webkit/WebCore/loader/FrameLoader.h index 2f36a6404..f420634dd 100755 --- a/webkit/WebCore/loader/FrameLoader.h +++ b/webkit/WebCore/loader/FrameLoader.h @@ -190,7 +190,7 @@ class FrameLoader { CachePolicy subresourceCachePolicy() const; - void didLayout(LayoutMilestones); + void didReachLayoutMilestone(LayoutMilestones); void didFirstLayout(); void loadedResourceFromMemoryCache(CachedResource*, ResourceRequest& newRequest); @@ -229,7 +229,7 @@ class FrameLoader { bool checkIfFormActionAllowedByCSP(const URL&) const; - Frame* opener(); + WEBCORE_EXPORT Frame* opener(); WEBCORE_EXPORT void setOpener(Frame*); void resetMultipleFormSubmissionProtection(); @@ -340,7 +340,7 @@ class FrameLoader { void setState(FrameState); void closeOldDataSources(); - void prepareForCachedPageRestore(); + void willRestoreFromCachedPage(); bool shouldReloadToHandleUnreachableURL(DocumentLoader*); @@ -382,6 +382,8 @@ class FrameLoader { void applyShouldOpenExternalURLsPolicyToNewDocumentLoader(DocumentLoader&, ShouldOpenExternalURLsPolicy propagatedPolicy); + bool isNavigationAllowed() const; + Frame& m_frame; FrameLoaderClient& m_client; diff --git a/webkit/WebCore/loader/FrameLoaderClient.h b/webkit/WebCore/loader/FrameLoaderClient.h index db44fd5ef..13e24aa62 100755 --- a/webkit/WebCore/loader/FrameLoaderClient.h +++ b/webkit/WebCore/loader/FrameLoaderClient.h @@ -174,7 +174,7 @@ namespace WebCore { virtual void dispatchDidFinishLoad() = 0; virtual void dispatchDidLayout() { } - virtual void dispatchDidLayout(LayoutMilestones) { } + virtual void dispatchDidReachLayoutMilestone(LayoutMilestones) { } virtual Frame* dispatchCreatePage(const NavigationAction&) = 0; virtual void dispatchShow() = 0; diff --git a/webkit/WebCore/loader/FrameLoaderStateMachine.h b/webkit/WebCore/loader/FrameLoaderStateMachine.h index 8c2fe642b..658e2df11 100755 --- a/webkit/WebCore/loader/FrameLoaderStateMachine.h +++ b/webkit/WebCore/loader/FrameLoaderStateMachine.h @@ -57,7 +57,7 @@ class FrameLoaderStateMachine { WEBCORE_EXPORT bool committingFirstRealLoad() const; bool committedFirstRealDocumentLoad() const; bool creatingInitialEmptyDocument() const; - bool isDisplayingInitialEmptyDocument() const; + WEBCORE_EXPORT bool isDisplayingInitialEmptyDocument() const; WEBCORE_EXPORT bool firstLayoutDone() const; void advanceTo(State); diff --git a/webkit/WebCore/loader/ResourceLoader.h b/webkit/WebCore/loader/ResourceLoader.h index 8efad1178..e9d776cbb 100755 --- a/webkit/WebCore/loader/ResourceLoader.h +++ b/webkit/WebCore/loader/ResourceLoader.h @@ -149,6 +149,8 @@ class ResourceLoader : public RefCounted, protected ResourceHand void unschedule(WTF::SchedulePair&); #endif + const Frame* frame() const { return m_frame.get(); } + protected: ResourceLoader(Frame*, ResourceLoaderOptions); diff --git a/webkit/WebCore/loader/SubframeLoader.cpp b/webkit/WebCore/loader/SubframeLoader.cpp index 996da0012..af4e7ddae 100755 --- a/webkit/WebCore/loader/SubframeLoader.cpp +++ b/webkit/WebCore/loader/SubframeLoader.cpp @@ -88,7 +88,7 @@ bool SubframeLoader::requestFrame(HTMLFrameOwnerElement& ownerElement, const Str if (!frame) return false; - if (!scriptURL.isEmpty()) + if (!scriptURL.isEmpty() && ownerElement.isURLAllowed(scriptURL)) frame->script().executeIfJavaScriptURL(scriptURL); return true; diff --git a/webkit/WebCore/loader/SubresourceLoader.cpp b/webkit/WebCore/loader/SubresourceLoader.cpp index 640947b64..ff3a7d998 100755 --- a/webkit/WebCore/loader/SubresourceLoader.cpp +++ b/webkit/WebCore/loader/SubresourceLoader.cpp @@ -192,6 +192,10 @@ void SubresourceLoader::willSendRequestInternal(ResourceRequest& newRequest, con return; ResourceLoader::willSendRequestInternal(newRequest, redirectResponse); + + if (reachedTerminalState()) + return; + if (newRequest.isNull()) cancel(); } diff --git a/webkit/WebCore/loader/cache/CachedImage.cpp b/webkit/WebCore/loader/cache/CachedImage.cpp index a3b0dbfb9..5742a561e 100755 --- a/webkit/WebCore/loader/cache/CachedImage.cpp +++ b/webkit/WebCore/loader/cache/CachedImage.cpp @@ -484,7 +484,7 @@ void CachedImage::decodedSizeChanged(const Image* image, int delta) if (!image || image != m_image) return; - setDecodedSize(decodedSize() + delta); + setDecodedSize(static_cast(decodedSize() + delta)); } void CachedImage::didDraw(const Image* image) diff --git a/webkit/WebCore/loader/cache/CachedResourceLoader.cpp b/webkit/WebCore/loader/cache/CachedResourceLoader.cpp index c9d44100a..e63ee0724 100755 --- a/webkit/WebCore/loader/cache/CachedResourceLoader.cpp +++ b/webkit/WebCore/loader/cache/CachedResourceLoader.cpp @@ -916,8 +916,14 @@ void CachedResourceLoader::loadDone(CachedResource* resource, bool shouldPerform if (resource->type() == CachedResource::MainResource) initiatorDocument = document()->parentDocument(); ASSERT(initiatorDocument); +#if PLATFORM(WKC) + if (initiatorDocument) { +#endif const InitiatorInfo& info = initiatorIt->value; initiatorDocument->domWindow()->performance()->addResourceTiming(info.name, initiatorDocument, resource->resourceRequest(), resource->response(), info.startTime, resource->loadFinishTime()); +#if PLATFORM(WKC) + } +#endif m_initiatorMap.remove(initiatorIt); } } diff --git a/webkit/WebCore/page/ContextMenuController.cpp b/webkit/WebCore/page/ContextMenuController.cpp index 4cfa5f7d3..5a81ff018 100755 --- a/webkit/WebCore/page/ContextMenuController.cpp +++ b/webkit/WebCore/page/ContextMenuController.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. + * Copyright (C) 2006-2007, 2016 Apple Inc. All rights reserved. * Copyright (C) 2010 Igalia S.L * * Redistribution and use in source and binary forms, with or without @@ -236,6 +236,8 @@ void ContextMenuController::contextMenuItemSelected(ContextMenuItem* item) if (!frame) return; + Ref protector(*frame); + switch (item->action()) { case ContextMenuItemTagOpenLinkInNewWindow: openNewWindow(m_context.hitTestResult().absoluteLinkURL(), frame, ShouldOpenExternalURLsPolicy::ShouldAllowExternalSchemes); diff --git a/webkit/WebCore/page/DOMSelection.cpp b/webkit/WebCore/page/DOMSelection.cpp index 7bcf7521b..0104171ea 100755 --- a/webkit/WebCore/page/DOMSelection.cpp +++ b/webkit/WebCore/page/DOMSelection.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2007, 2009, 2016 Apple Inc. All rights reserved. * Copyright (C) 2012 Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -204,6 +204,7 @@ void DOMSelection::collapse(Node* node, int offset, ExceptionCode& ec) return; // FIXME: Eliminate legacy editing positions + Ref protector(*m_frame); m_frame->selection().moveTo(createLegacyEditingPosition(node, offset), DOWNSTREAM); } @@ -219,6 +220,7 @@ void DOMSelection::collapseToEnd(ExceptionCode& ec) return; } + Ref protector(*m_frame); m_frame->selection().moveTo(selection.end(), DOWNSTREAM); } @@ -234,6 +236,7 @@ void DOMSelection::collapseToStart(ExceptionCode& ec) return; } + Ref protector(*m_frame); m_frame->selection().moveTo(selection.start(), DOWNSTREAM); } @@ -258,6 +261,7 @@ void DOMSelection::setBaseAndExtent(Node* baseNode, int baseOffset, Node* extent return; // FIXME: Eliminate legacy editing positions + Ref protector(*m_frame); m_frame->selection().moveTo(createLegacyEditingPosition(baseNode, baseOffset), createLegacyEditingPosition(extentNode, extentOffset), DOWNSTREAM); } @@ -274,6 +278,7 @@ void DOMSelection::setPosition(Node* node, int offset, ExceptionCode& ec) return; // FIXME: Eliminate legacy editing positions + Ref protector(*m_frame); m_frame->selection().moveTo(createLegacyEditingPosition(node, offset), DOWNSTREAM); } @@ -324,6 +329,7 @@ void DOMSelection::modify(const String& alterString, const String& directionStri else return; + Ref protector(*m_frame); m_frame->selection().modify(alter, direction, granularity); } @@ -346,6 +352,7 @@ void DOMSelection::extend(Node* node, int offset, ExceptionCode& ec) return; // FIXME: Eliminate legacy editing positions + Ref protector(*m_frame); m_frame->selection().setExtent(createLegacyEditingPosition(node, offset), DOWNSTREAM); } @@ -385,6 +392,8 @@ void DOMSelection::addRange(Range* r) if (!r) return; + Ref protector(*m_frame); + FrameSelection& selection = m_frame->selection(); if (selection.isNone()) { @@ -433,9 +442,10 @@ void DOMSelection::deleteFromDocument() selection.modify(FrameSelection::AlterationExtend, DirectionBackward, CharacterGranularity); RefPtr selectedRange = selection.selection().toNormalizedRange(); - if (!selectedRange) + if (!selectedRange || selectedRange->shadowRoot()) return; + Ref protector(*m_frame); selectedRange->deleteContents(ASSERT_NO_EXCEPTION); setBaseAndExtent(selectedRange->startContainer(ASSERT_NO_EXCEPTION), selectedRange->startOffset(), selectedRange->startContainer(), selectedRange->startOffset(), ASSERT_NO_EXCEPTION); diff --git a/webkit/WebCore/page/DOMWindow.cpp b/webkit/WebCore/page/DOMWindow.cpp index f497195a1..63ded323d 100755 --- a/webkit/WebCore/page/DOMWindow.cpp +++ b/webkit/WebCore/page/DOMWindow.cpp @@ -488,6 +488,8 @@ Page* DOMWindow::page() void DOMWindow::frameDestroyed() { + Ref protectedThis(*this); + willDestroyDocumentInFrame(); FrameDestructionObserver::frameDestroyed(); resetDOMWindowProperties(); @@ -1770,11 +1772,11 @@ bool DOMWindow::addEventListener(const AtomicString& eventType, PassRefPtr 0); - --m_touchEventListenerCount; + ASSERT(m_touchAndGestureEventListenerCount > 0); + --m_touchAndGestureEventListenerCount; } #endif #if ENABLE(IOS_GESTURE_EVENTS) else if (eventNames().isGestureEventType(eventType)) { - ASSERT(m_touchEventListenerCount > 0); - --m_touchEventListenerCount; + ASSERT(m_touchAndGestureEventListenerCount > 0); + --m_touchAndGestureEventListenerCount; } #endif #if ENABLE(GAMEPAD) @@ -1967,7 +1969,7 @@ void DOMWindow::removeAllEventListeners() #endif #if ENABLE(IOS_TOUCH_EVENTS) || ENABLE(IOS_GESTURE_EVENTS) - m_touchEventListenerCount = 0; + m_touchAndGestureEventListenerCount = 0; #endif #if ENABLE(TOUCH_EVENTS) @@ -2193,9 +2195,9 @@ PassRefPtr DOMWindow::open(const String& urlString, const AtomicStrin #endif if (!firstWindow.allowPopUp()) { - // Because FrameTree::find() returns true for empty strings, we must check for empty frame names. + // Because FrameTree::findFrameForNavigation() returns true for empty strings, we must check for empty frame names. // Otherwise, illegitimate window.open() calls with no name will pass right through the popup blocker. - if (frameName.isEmpty() || !m_frame->tree().find(frameName)) + if (frameName.isEmpty() || !m_frame->loader().findFrameForNavigation(frameName, activeDocument)) return nullptr; } diff --git a/webkit/WebCore/page/DOMWindow.h b/webkit/WebCore/page/DOMWindow.h index 03a9d6b3f..037ec27c0 100755 --- a/webkit/WebCore/page/DOMWindow.h +++ b/webkit/WebCore/page/DOMWindow.h @@ -319,7 +319,7 @@ namespace WebCore { void resetAllGeolocationPermission(); #if ENABLE(IOS_TOUCH_EVENTS) || ENABLE(IOS_GESTURE_EVENTS) - bool hasTouchEventListeners() const { return m_touchEventListenerCount > 0; } + bool hasTouchOrGestureEventListeners() const { return m_touchAndGestureEventListenerCount > 0; } #endif #if ENABLE(USER_MESSAGE_HANDLERS) @@ -399,7 +399,7 @@ namespace WebCore { #endif #if ENABLE(IOS_TOUCH_EVENTS) || ENABLE(IOS_GESTURE_EVENTS) - unsigned m_touchEventListenerCount; + unsigned m_touchAndGestureEventListenerCount { 0 }; #endif #if ENABLE(GAMEPAD) diff --git a/webkit/WebCore/page/DiagnosticLoggingKeys.cpp b/webkit/WebCore/page/DiagnosticLoggingKeys.cpp index bfc93d44c..fdbe49157 100755 --- a/webkit/WebCore/page/DiagnosticLoggingKeys.cpp +++ b/webkit/WebCore/page/DiagnosticLoggingKeys.cpp @@ -123,6 +123,11 @@ String DiagnosticLoggingKeys::networkKey() return ASCIILiteral("network"); } +String DiagnosticLoggingKeys::networkProcessCrashedKey() +{ + return ASCIILiteral("networkProcessCrashed"); +} + String DiagnosticLoggingKeys::neverSeenBeforeKey() { return ASCIILiteral("neverSeenBefore"); @@ -223,6 +228,16 @@ String DiagnosticLoggingKeys::inMemoryCacheKey() return ASCIILiteral("inMemoryCache"); } +String DiagnosticLoggingKeys::internalErrorKey() +{ + return ASCIILiteral("internalError"); +} + +String DiagnosticLoggingKeys::invalidSessionIDKey() +{ + return ASCIILiteral("invalidSessionID"); +} + String DiagnosticLoggingKeys::isAttachmentKey() { return ASCIILiteral("isAttachment"); @@ -268,6 +283,11 @@ String DiagnosticLoggingKeys::cannotSuspendActiveDOMObjectsKey() return ASCIILiteral("cannotSuspendActiveDOMObjects"); } +String DiagnosticLoggingKeys::createSharedBufferFailedKey() +{ + return ASCIILiteral("createSharedBufferFailed"); +} + String DiagnosticLoggingKeys::deltaKey() { return ASCIILiteral("delta"); @@ -403,6 +423,11 @@ String DiagnosticLoggingKeys::svgDocumentKey() return ASCIILiteral("svgDocument"); } +String DiagnosticLoggingKeys::synchronousMessageFailedKey() +{ + return ASCIILiteral("synchronousMessageFailed"); +} + String DiagnosticLoggingKeys::uncacheableStatusCodeKey() { return ASCIILiteral("uncacheableStatusCode"); diff --git a/webkit/WebCore/page/DiagnosticLoggingKeys.h b/webkit/WebCore/page/DiagnosticLoggingKeys.h index 133391235..f13b193b6 100755 --- a/webkit/WebCore/page/DiagnosticLoggingKeys.h +++ b/webkit/WebCore/page/DiagnosticLoggingKeys.h @@ -38,6 +38,7 @@ class DiagnosticLoggingKeys { WEBCORE_EXPORT static String cacheControlNoStoreKey(); static String cachedResourceRevalidationKey(); static String cannotSuspendActiveDOMObjectsKey(); + WEBCORE_EXPORT static String createSharedBufferFailedKey(); WEBCORE_EXPORT static String deltaKey(); static String deniedByClientKey(); static String deviceMotionKey(); @@ -53,6 +54,8 @@ class DiagnosticLoggingKeys { static String httpsNoStoreKey(); static String imageKey(); static String inMemoryCacheKey(); + WEBCORE_EXPORT static String internalErrorKey(); + WEBCORE_EXPORT static String invalidSessionIDKey(); WEBCORE_EXPORT static String isAttachmentKey(); WEBCORE_EXPORT static String isConditionalRequestKey(); static String isErrorPageKey(); @@ -71,6 +74,7 @@ class DiagnosticLoggingKeys { WEBCORE_EXPORT static String needsRevalidationKey(); WEBCORE_EXPORT static String networkCacheKey(); static String networkKey(); + WEBCORE_EXPORT static String networkProcessCrashedKey(); WEBCORE_EXPORT static String neverSeenBeforeKey(); static String noCacheKey(); static String noCurrentHistoryItemKey(); @@ -112,6 +116,7 @@ class DiagnosticLoggingKeys { WEBCORE_EXPORT static String streamingMedia(); static String styleSheetKey(); static String svgDocumentKey(); + WEBCORE_EXPORT static String synchronousMessageFailedKey(); WEBCORE_EXPORT static String uncacheableStatusCodeKey(); WEBCORE_EXPORT static String unlikelyToReuseKey(); WEBCORE_EXPORT static String unsupportedHTTPMethodKey(); diff --git a/webkit/WebCore/page/DragController.cpp b/webkit/WebCore/page/DragController.cpp index 68edabde1..241376302 100755 --- a/webkit/WebCore/page/DragController.cpp +++ b/webkit/WebCore/page/DragController.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007, 2009, 2010, 2013, 2015 Apple Inc. All rights reserved. + * Copyright (C) 2007, 2009-2010, 2013, 2015-2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -430,6 +430,7 @@ DragOperation DragController::operationForLoad(DragData& dragData) static bool setSelectionToDragCaret(Frame* frame, VisibleSelection& dragCaret, RefPtr& range, const IntPoint& point) { + Ref protector(*frame); frame->selection().setSelection(dragCaret); if (frame->selection().selection().isNone()) { dragCaret = frame->visiblePositionForPoint(point); @@ -750,6 +751,7 @@ bool DragController::startDrag(Frame& src, const DragState& state, DragOperation if (!src.view() || !src.contentRenderer() || !state.source) return false; + Ref protector(src); HitTestResult hitTestResult = src.eventHandler().hitTestResultAtPoint(dragOrigin, HitTestRequest::ReadOnly | HitTestRequest::Active); // FIXME(136836): Investigate whether all elements should use the containsIncludingShadowDOM() path here. diff --git a/webkit/WebCore/page/EditorClient.h b/webkit/WebCore/page/EditorClient.h index 3c53a5380..2ff0151b6 100755 --- a/webkit/WebCore/page/EditorClient.h +++ b/webkit/WebCore/page/EditorClient.h @@ -95,6 +95,7 @@ class EditorClient { virtual void respondToChangedContents() = 0; virtual void respondToChangedSelection(Frame*) = 0; virtual void didChangeSelectionAndUpdateLayout() = 0; + virtual void updateEditorStateAfterLayoutIfEditabilityChanged() = 0; virtual void didEndEditing() = 0; virtual void willWriteSelectionToPasteboard(Range*) = 0; virtual void didWriteSelectionToPasteboard() = 0; diff --git a/webkit/WebCore/page/EventHandler.cpp b/webkit/WebCore/page/EventHandler.cpp index 68fc35a08..110d6517a 100755 --- a/webkit/WebCore/page/EventHandler.cpp +++ b/webkit/WebCore/page/EventHandler.cpp @@ -91,6 +91,7 @@ #include "TextIterator.h" #include "UserGestureIndicator.h" #include "UserTypingGestureIndicator.h" +#include "ValidationMessageClient.h" #include "VisibleUnits.h" #include "WheelEvent.h" #include "WindowsKeyboardCodes.h" @@ -1148,6 +1149,10 @@ HitTestResult EventHandler::hitTestResultAtPoint(const LayoutPoint& point, HitTe } } + // We should always start hit testing a clean tree. + if (auto* frameView = m_frame.view()) + frameView->updateLayoutAndStyleIfNeededRecursive(); + HitTestResult result(point, padding.height(), padding.width(), padding.height(), padding.width()); RenderView* renderView = m_frame.contentRenderer(); @@ -1663,6 +1668,13 @@ bool EventHandler::handleMousePressEvent(const PlatformMouseEvent& platformMouse return true; } +#if ENABLE(POINTER_LOCK) + if (m_frame.page()->pointerLockController().isLocked()) { + m_frame.page()->pointerLockController().dispatchLockedMouseEvent(platformMouseEvent, eventNames().mousedownEvent); + return true; + } +#endif + if (m_frame.mainFrame().pageOverlayController().handleMouseEvent(platformMouseEvent)) return true; @@ -1811,6 +1823,13 @@ bool EventHandler::handleMouseDoubleClickEvent(const PlatformMouseEvent& platfor UserGestureIndicator gestureIndicator(DefinitelyProcessingUserGesture, m_frame.document()); +#if ENABLE(POINTER_LOCK) + if (m_frame.page()->pointerLockController().isLocked()) { + m_frame.page()->pointerLockController().dispatchLockedMouseEvent(platformMouseEvent, eventNames().mouseupEvent); + return true; + } +#endif + // We get this instead of a second mouse-up m_mousePressed = false; setLastKnownMousePosition(platformMouseEvent); @@ -1903,7 +1922,14 @@ bool EventHandler::handleMouseMoveEvent(const PlatformMouseEvent& platformMouseE return true; RefPtr protector(m_frame.view()); - + +#if ENABLE(POINTER_LOCK) + if (m_frame.page()->pointerLockController().isLocked()) { + m_frame.page()->pointerLockController().dispatchLockedMouseEvent(platformMouseEvent, eventNames().mousemoveEvent); + return true; + } +#endif + setLastKnownMousePosition(platformMouseEvent); if (m_hoverTimer.isActive()) @@ -2039,6 +2065,13 @@ bool EventHandler::handleMouseReleaseEvent(const PlatformMouseEvent& platformMou m_frame.selection().setCaretBlinkingSuspended(false); +#if ENABLE(POINTER_LOCK) + if (m_frame.page()->pointerLockController().isLocked()) { + m_frame.page()->pointerLockController().dispatchLockedMouseEvent(platformMouseEvent, eventNames().mouseupEvent); + return true; + } +#endif + if (m_frame.mainFrame().pageOverlayController().handleMouseEvent(platformMouseEvent)) return true; @@ -2116,6 +2149,17 @@ bool EventHandler::handleMouseForceEvent(const PlatformMouseEvent& event) { RefPtr protector(m_frame.view()); +#if ENABLE(POINTER_LOCK) + if (m_frame.page()->pointerLockController().isLocked()) { + m_frame.page()->pointerLockController().dispatchLockedMouseEvent(event, eventNames().webkitmouseforcechangedEvent); + if (event.type() == PlatformEvent::MouseForceDown) + m_frame.page()->pointerLockController().dispatchLockedMouseEvent(event, eventNames().webkitmouseforcedownEvent); + if (event.type() == PlatformEvent::MouseForceUp) + m_frame.page()->pointerLockController().dispatchLockedMouseEvent(event, eventNames().webkitmouseforceupEvent); + return true; + } +#endif + setLastKnownMousePosition(event); HitTestRequest::HitTestRequestType hitType = HitTestRequest::DisallowShadowContent | HitTestRequest::Active; @@ -2678,6 +2722,13 @@ bool EventHandler::handleWheelEvent(const PlatformWheelEvent& event) if (!view) return false; +#if ENABLE(POINTER_LOCK) + if (m_frame.page()->pointerLockController().isLocked()) { + m_frame.page()->pointerLockController().dispatchLockedWheelEvent(event); + return true; + } +#endif + m_isHandlingWheelEvent = true; setFrameWasScrolledByUser(); @@ -3046,6 +3097,13 @@ bool EventHandler::keyEvent(const PlatformKeyboardEvent& initialKeyEvent) { RefPtr protector(m_frame.view()); + if (initialKeyEvent.type() == PlatformEvent::KeyDown && initialKeyEvent.windowsVirtualKeyCode() == VK_ESCAPE) { + if (auto* page = m_frame.page()) { + if (auto* validationMessageClient = page->validationMessageClient()) + validationMessageClient->hideAnyValidationMessage(); + } + } + #if ENABLE(FULLSCREEN_API) if (m_frame.document()->webkitIsFullScreen() && !isKeyEventAllowedInFullScreen(initialKeyEvent)) return false; diff --git a/webkit/WebCore/page/FocusController.cpp b/webkit/WebCore/page/FocusController.cpp index b330d12ef..e906868ec 100755 --- a/webkit/WebCore/page/FocusController.cpp +++ b/webkit/WebCore/page/FocusController.cpp @@ -51,9 +51,11 @@ #include "HitTestResult.h" #include "KeyboardEvent.h" #include "MainFrame.h" +#include "MouseEventWithHitTestResults.h" #include "NodeRenderingTraversal.h" #include "Page.h" #include "Range.h" +#include "RenderView.h" #include "RenderWidget.h" #include "ScrollAnimator.h" #include "Settings.h" @@ -67,7 +69,7 @@ #if PLATFORM(WKC) #include "ElementIterator.h" -#include "HTMLLabelElement.h" +#include "HTMLFormElement.h" #endif namespace WebCore { @@ -725,6 +727,45 @@ void FocusController::setIsVisibleAndActiveInternal(bool contentIsVisible) } #if PLATFORM(WKC) +static Element* hitTestAtPoint(Frame* mainFrame, IntPoint hitPoint) +{ + Node* hitNode = 0; + Frame* frame = mainFrame; + while (frame) { + RenderView* renderView = frame->contentRenderer(); + if (!renderView) + break; + + if (frame->view()) + hitPoint = frame->view()->windowToContents(hitPoint); + + HitTestRequest request(WebCore::HitTestRequest::ReadOnly | WebCore::HitTestRequest::Active | HitTestRequest::IgnoreClipping | HitTestRequest::DisallowShadowContent); + HitTestResult result(hitPoint); + + renderView->hitTest(request, result); + result.setToNonShadowAncestor(); // if disallowsShadowContent + hitNode = result.innerNode(); + + MouseEventWithHitTestResults hr(PlatformMouseEvent(), result); + frame = EventHandler::subframeForHitTestResult(hr); + } + + if (hitNode) { + if (hitNode->isTextNode()) + hitNode = hitNode->parentElement(); + else if (is(*hitNode)) { + HTMLAreaElement& area = downcast(*hitNode); + HTMLImageElement* image = area.imageElement(); + if (!image || !image->renderer()) + return 0; + hitNode = image; + } + if (hitNode->isElementNode()) + return downcast(hitNode); + } + return 0; +} + static bool isFocusControlBannedElement(const FocusCandidate& candidate) { Document& document = candidate.visibleNode->document(); @@ -754,20 +795,13 @@ static bool isFocusControlBannedElement(const FocusCandidate& candidate) if (candidateRect.isEmpty()) continue; - IntRect rect(candidateRect.x(), candidateRect.y(), candidateRect.width(), candidateRect.height()); + IntRect rect = roundedIntRect(candidateRect); rect = mainView->contentsToWindow(rect); rect.intersect(frameRect); if (rect.isEmpty()) continue; - candidateRect = mainView->windowToContents(rect); - HitTestResult result = mainFrame.eventHandler().hitTestResultAtPoint(candidateRect.center(), HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::IgnoreClipping | HitTestRequest::DisallowShadowContent); - - Node* hitNode = result.innerNode(); - - if (hitNode && hitNode->isTextNode()) - hitNode = hitNode->parentElement(); - + Node* hitNode = hitTestAtPoint(&mainFrame, rect.center()); if (!hitNode) continue; @@ -775,10 +809,12 @@ static bool isFocusControlBannedElement(const FocusCandidate& candidate) if (document != hitNode->document()) continue; - // If the hit test result node is a label and belongs to the same form as the candidate element, then allows to be focused. - if (is(*hitNode) && candidateElement.isFormControlElement()) - if (downcast(*hitNode).form() == downcast(candidateElement).form()) + // If the hit test result node belongs to the same form as the candidate element, then allows to be focused. + if (candidateElement.isFormControlElement()) { + HTMLFormElement* form = downcast(candidateElement).form(); + if (form && form->contains(hitNode)) return false; + } // hit test result node is not in other node. if (candidateElement.contains(hitNode)) @@ -1162,28 +1198,67 @@ double FocusController::timeSinceFocusWasSet() const } #if PLATFORM(WKC) -static bool isNodeInSpecificRect(Node* node, const LayoutRect* specificRect) +bool FocusController::isClickableElement(Element* element) { - if (!specificRect || specificRect->isEmpty()) - return !hasOffscreenRect(node); + if (!element) + return false; + if (!element->parentElement()) + return false; + if (element->isFrameOwnerElement()) + return false; + if (!isInsideFocusableFrame(element)) + return false; + if (is(element)) + return false; + + if (is(element) && element->willRespondToMouseClickEvents()) + return true; + if (is(element)) { + HTMLAreaElement* area = downcast(element); + HTMLImageElement* image = area->imageElement(); + if (!image || !image->renderer() || image->renderer()->style().visibility() != VISIBLE) + return false; + + if (area->isLink()) + return true; + } else if (!element->renderer()) + return false; + if (element->isKeyboardFocusable(nullptr)) + return true; + if (element->hasEventListeners(eventNames().clickEvent)) + return true; + return false; +} + +static LayoutRect getRectFromNode(Node* node) +{ + LayoutRect rect; FrameView* frameView = node->document().view(); if (!frameView) - return false; + return rect; - LayoutRect rect; if (node->hasTagName(HTMLNames::areaTag)) { HTMLAreaElement* area = static_cast(node); HTMLImageElement* image = area->imageElement(); if (!image || !image->renderer()) - return false; + return rect; rect = rectToAbsoluteCoordinates(area->document().frame(), area->computeRect(image->renderer())); } else { RenderObject* render = node->renderer(); if (!render) - return false; + return rect; rect = nodeRectInAbsoluteCoordinates(node, true /* ignore border */); } + return rect; +} + +static bool isNodeInSpecificRect(Node* node, const LayoutRect* specificRect) +{ + if (!specificRect || specificRect->isEmpty()) + return !hasOffscreenRect(node); + + LayoutRect rect = getRectFromNode(node); if (rect.isEmpty()) return false; @@ -1245,6 +1320,9 @@ void FocusController::findFocusableNodeInDirection(Node* container, Node* starti if (!element->isKeyboardFocusable(event) && !element->isFrameOwnerElement() && !canScrollInDirection(element, direction)) continue; + if (!isInsideFocusableFrame(element)) + continue; + FocusCandidate candidate = FocusCandidate(element, direction); if (candidate.isNull()) continue; @@ -1291,7 +1369,7 @@ findFirstFocusableElement(Frame& frame, const LayoutRect* scope) if (child) element = child; } - if (element->isFocusable() && !element->isFrameOwnerElement()) + if (element->isFocusable() && !element->isFrameOwnerElement() && isInsideFocusableFrame(element)) break; } @@ -1363,10 +1441,10 @@ Element* FocusController::findNextFocusableElement(const FocusDirection& directi } LayoutRect startingRect; - if (!hasOffscreenRect(static_cast(base))) { - startingRect = nodeRectInAbsoluteCoordinates(base, true /* ignore border */); - } else if (base->hasTagName(areaTag)) { + if (base->hasTagName(areaTag)) { startingRect = virtualRectForAreaElementAndDirection(downcast(base), direction); + } else { + startingRect = nodeRectInAbsoluteCoordinates(base, true /* ignore border */); } FocusCandidate focusCandidate; @@ -1607,5 +1685,127 @@ FocusController::findNearestFocusableElementFromPoint(const IntPoint& point, con return nearest; } +Element* +FocusController::findNearestClickableElementFromPoint(const Element* start, const LayoutPoint& point, const LayoutRect& scope) +{ + if (!start) + return 0; + + Element* nearest = 0; + int nearDist = INT_MAX; + + Element* element = ElementTraversal::firstChild(*start); + for (; element; element = ElementTraversal::nextSibling(*element)) { + Element* e = element; + + // get child element preferentially + if (e->firstElementChild()) { + Element* child = findNearestClickableElementFromPoint(e, point, scope); + if (child) + e = child; + } + + if (!isNodeInSpecificRect(e, &scope)) { + continue; + } + + if (e->isFrameOwnerElement()) { + HTMLFrameOwnerElement* owner = downcast(e); + if (owner->contentFrame()) { + ContainerNode* container = owner->contentFrame()->document(); + e = findNearestClickableElementFromPoint(ElementTraversal::firstWithin(*container), point, scope); + if (!e) + continue; + } + } else if (isScrollableContainerNode(e) && !e->renderer()->isTextArea()) { + Element* child = ElementTraversal::firstChild(*e); + if (child) + e = child; + } + + FocusCandidate candidate = FocusCandidate(e, FocusDirectionDown); + if (candidate.isNull()) + continue; + if (candidate.isOffscreen) + continue; + if (isFocusControlBannedElement(candidate)) + continue; + + if (!isClickableElement(e)) + continue; + + int dist = distanceBetweenElementAndPoint(e, point); + ASSERT(dist >= 0); + if (dist == 0) { + nearest = e; + break; + } else if (dist == INT_MAX) + continue; + + if (dist < nearDist) { + nearest = e; + nearDist = dist; + } else if (dist == nearDist) { + LayoutRect rect = getRectFromNode(nearest); + if (rect.isEmpty()) + continue; + + rect.intersect(getRectFromNode(e)); + if (rect.isEmpty()) + continue; + + IntRect windowRect = e->document().view()->contentsToWindow(IntRect(rect)); + Element* hitElement = hitTestAtPoint(&e->document().page()->mainFrame(), windowRect.center()); + if (hitElement && isClickableElement(hitElement)) { + nearest = hitElement; + nearDist = distanceBetweenElementAndPoint(hitElement, point); + ASSERT(nearDist >= 0); + if (nearDist == 0) + break; + } + } + } + + return nearest; +} + +Element* +FocusController::findNearestClickableElementFromPoint(const IntPoint& point, const IntRect* scope) +{ + Frame& fr = m_page.mainFrame(); + + Element* element = hitTestAtPoint(&fr, point); + if (element && isClickableElement(element)) { + return element; + } + + LayoutRect scopeRect(0,0,0,0); + Document* doc = fr.document(); + FrameView* frameView = fr.view(); + if (!frameView) + return 0; + + RefPtr protector(frameView); + + LayoutPoint contentsPoint = frameView->windowToContents(point); + if (scope && !scope->isEmpty()) { + LayoutRect lr = frameView->windowToContents(*scope); + scopeRect = lr; + } + + Element* root = ElementTraversal::firstWithin(*fr.document()); + Element* e = findNearestClickableElementFromPoint(root, contentsPoint, scopeRect); + + if (is(e)) { + HTMLAreaElement* area = downcast(e); + HTMLImageElement* image = area->imageElement(); + if (!image || !image->renderer()) + return 0; + e = image; + } + + return e; +} + #endif // PLATFORM(WKC) } // namespace WebCore diff --git a/webkit/WebCore/page/FocusController.h b/webkit/WebCore/page/FocusController.h index ba42a3e7b..32af5ff40 100755 --- a/webkit/WebCore/page/FocusController.h +++ b/webkit/WebCore/page/FocusController.h @@ -96,14 +96,19 @@ class FocusController { double timeSinceFocusWasSet() const; #if PLATFORM(WKC) + bool isClickableElement(Element* element); bool setFocusedNode(Node *node); Element* findNextFocusableElement(const FocusDirection& direction, const IntRect* scope = 0, Element* base = 0); Element* findNearestFocusableElementFromPoint(const IntPoint& point, const IntRect* scope = 0); + // get child element preferentially + Element* findNearestClickableElementFromPoint(const IntPoint& point, const IntRect* scope = 0); #endif private: #if PLATFORM(WKC) void findFocusableNodeInDirection(Node* container, Node* startingElement, const LayoutRect& startingRect, FocusDirection direction, KeyboardEvent* event, FocusCandidate& closest, const LayoutRect* scope); + // get child element preferentially + Element* findNearestClickableElementFromPoint(const Element* start, const LayoutPoint& point, const LayoutRect& scope); #endif void setActiveInternal(bool); void setFocusedInternal(bool); diff --git a/webkit/WebCore/page/Frame.cpp b/webkit/WebCore/page/Frame.cpp index db670110b..87aefe7af 100755 --- a/webkit/WebCore/page/Frame.cpp +++ b/webkit/WebCore/page/Frame.cpp @@ -225,8 +225,8 @@ Frame::~Frame() disconnectOwnerElement(); - for (auto& observer : m_destructionObservers) - observer->frameDestroyed(); + while (auto* destructionObserver = m_destructionObservers.takeAny()) + destructionObserver->frameDestroyed(); if (!isMainFrame()) m_mainFrame.selfOnlyDeref(); @@ -273,6 +273,11 @@ void Frame::setDocument(RefPtr&& newDocument) { ASSERT(!newDocument || newDocument->frame() == this); + if (m_documentIsBeingReplaced) + return; + + m_documentIsBeingReplaced = true; + if (m_doc && !m_doc->inPageCache()) m_doc->prepareForDestruction(); @@ -286,6 +291,8 @@ void Frame::setDocument(RefPtr&& newDocument) newDocument->didBecomeCurrentDocumentInFrame(); InspectorInstrumentation::frameDocumentUpdated(this); + + m_documentIsBeingReplaced = false; } #if ENABLE(ORIENTATION_EVENTS) @@ -609,6 +616,8 @@ int Frame::checkOverflowScroll(OverflowScrollAction action) } } + Ref protectedThis(*this); + if (action == PerformOverflowScroll && (deltaX || deltaY)) { layer->scrollToOffset(IntSize(layer->scrollXOffset() + deltaX, layer->scrollYOffset() + deltaY)); diff --git a/webkit/WebCore/page/Frame.h b/webkit/WebCore/page/Frame.h index 671236fbc..a4cd5e4b5 100755 --- a/webkit/WebCore/page/Frame.h +++ b/webkit/WebCore/page/Frame.h @@ -158,6 +158,8 @@ namespace WebCore { WEBCORE_EXPORT RenderView* contentRenderer() const; // Root of the render tree for the document contained in this frame. WEBCORE_EXPORT RenderWidget* ownerRenderer() const; // Renderer for the element that contains this frame. + bool documentIsBeingReplaced() const { return m_documentIsBeingReplaced; } + // ======== All public functions below this point are candidates to move out of Frame into another class. ======== void injectUserScripts(UserScriptInjectionTime); @@ -315,6 +317,7 @@ namespace WebCore { float m_textZoomFactor; int m_activeDOMObjectsAndAnimationsSuspendedCount; + bool m_documentIsBeingReplaced { false }; }; inline void Frame::init() diff --git a/webkit/WebCore/page/FrameTree.cpp b/webkit/WebCore/page/FrameTree.cpp index e7953fdec..f4e33799c 100755 --- a/webkit/WebCore/page/FrameTree.cpp +++ b/webkit/WebCore/page/FrameTree.cpp @@ -446,6 +446,25 @@ Frame* FrameTree::traversePreviousWithWrap(bool wrap) const return nullptr; } +Frame* FrameTree::traverseNextInPostOrderWithWrap(bool wrap) const +{ + if (m_nextSibling) + return m_nextSibling->tree().deepFirstChild(); + if (m_parent) + return m_parent; + if (wrap) + return deepFirstChild(); + return nullptr; +} + +Frame* FrameTree::deepFirstChild() const +{ + Frame* result = &m_thisFrame; + while (auto* next = result->tree().firstChild()) + result = next; + return result; +} + Frame* FrameTree::deepLastChild() const { Frame* result = &m_thisFrame; diff --git a/webkit/WebCore/page/FrameTree.h b/webkit/WebCore/page/FrameTree.h index 5b2a587d0..887617973 100755 --- a/webkit/WebCore/page/FrameTree.h +++ b/webkit/WebCore/page/FrameTree.h @@ -71,6 +71,9 @@ namespace WebCore { WEBCORE_EXPORT void appendChild(PassRefPtr); bool transferChild(PassRefPtr); + + Frame* traverseNextInPostOrderWithWrap(bool) const; + void detachFromParent() { m_parent = nullptr; } void removeChild(Frame*); @@ -88,6 +91,7 @@ namespace WebCore { unsigned scopedChildCount() const; private: + Frame* deepFirstChild() const; Frame* deepLastChild() const; void actuallyAppendChild(PassRefPtr); diff --git a/webkit/WebCore/page/FrameView.cpp b/webkit/WebCore/page/FrameView.cpp index c1bf682b1..99cf9577e 100755 --- a/webkit/WebCore/page/FrameView.cpp +++ b/webkit/WebCore/page/FrameView.cpp @@ -581,6 +581,27 @@ PassRefPtr FrameView::createScrollbar(ScrollbarOrientation orientatio return ScrollView::createScrollbar(orientation); } +void FrameView::willDestroyRenderTree() +{ + detachCustomScrollbars(); + m_layoutRoot = nullptr; +} + +void FrameView::didDestroyRenderTree() +{ + ASSERT(!m_layoutRoot); + ASSERT(m_widgetsInRenderTree.isEmpty()); + + // If the render tree is destroyed below FrameView::updateEmbeddedObjects(), there will still be a null sentinel in the set. + // Everything else should have removed itself as the tree was felled. + ASSERT(!m_embeddedObjectsToUpdate || m_embeddedObjectsToUpdate->isEmpty() || (m_embeddedObjectsToUpdate->size() == 1 && m_embeddedObjectsToUpdate->first() == nullptr)); + + ASSERT(!m_viewportConstrainedObjects || m_viewportConstrainedObjects->isEmpty()); + ASSERT(!m_slowRepaintObjects || m_slowRepaintObjects->isEmpty()); + + ASSERT(!frame().animation().hasAnimations()); +} + void FrameView::setContentsSize(const IntSize& size) { if (size == contentsSize()) @@ -1458,7 +1479,7 @@ void FrameView::layout(bool allowSubtree) #endif #if ENABLE(IOS_TOUCH_EVENTS) - document.dirtyTouchEventRects(); + document.setTouchEventRegionsNeedUpdate(); #endif updateCanBlitOnScrollRecursively(); @@ -2726,8 +2747,10 @@ void FrameView::setNeedsLayout() return; } - if (RenderView* renderView = this->renderView()) + if (auto* renderView = this->renderView()) { + ASSERT(!renderView->inHitTesting()); renderView->setNeedsLayout(); + } } void FrameView::unscheduleRelayout() @@ -4747,7 +4770,7 @@ void FrameView::fireLayoutRelatedMilestonesIfNeeded() } if (milestonesAchieved && frame().isMainFrame()) - frame().loader().didLayout(milestonesAchieved); + frame().loader().didReachLayoutMilestone(milestonesAchieved); } void FrameView::firePaintRelatedMilestonesIfNeeded() @@ -4772,7 +4795,7 @@ void FrameView::firePaintRelatedMilestonesIfNeeded() m_milestonesPendingPaint = 0; if (milestonesAchieved) - page->mainFrame().loader().didLayout(milestonesAchieved); + page->mainFrame().loader().didReachLayoutMilestone(milestonesAchieved); } void FrameView::setVisualUpdatesAllowedByClient(bool visualUpdatesAllowed) diff --git a/webkit/WebCore/page/FrameView.h b/webkit/WebCore/page/FrameView.h index 72c960eb7..20b3587ee 100755 --- a/webkit/WebCore/page/FrameView.h +++ b/webkit/WebCore/page/FrameView.h @@ -560,6 +560,9 @@ class FrameView final : public ScrollView { void show() override; + void willDestroyRenderTree(); + void didDestroyRenderTree(); + protected: virtual bool scrollContentsFastPath(const IntSize& scrollDelta, const IntRect& rectToScroll, const IntRect& clipRect) override; virtual void scrollContentsSlowPath(const IntRect& updateRect) override; diff --git a/webkit/WebCore/page/LayoutMilestones.h b/webkit/WebCore/page/LayoutMilestones.h index b125bc4ea..72a589e07 100755 --- a/webkit/WebCore/page/LayoutMilestones.h +++ b/webkit/WebCore/page/LayoutMilestones.h @@ -32,13 +32,13 @@ namespace WebCore { // We should either re-name them to something more generic, or split them into // two enums -- one for painting and one for layout. enum LayoutMilestoneFlag { - DidFirstLayout = 1 << 0, - DidFirstVisuallyNonEmptyLayout = 1 << 1, - DidHitRelevantRepaintedObjectsAreaThreshold = 1 << 2, - DidFirstFlushForHeaderLayer = 1 << 3, - DidFirstLayoutAfterSuppressedIncrementalRendering = 1 << 4, - DidFirstPaintAfterSuppressedIncrementalRendering = 1 << 5, - ReachedSessionRestorationRenderTreeSizeThreshold = 1 << 6 // FIXME: only implemented by WK2 currently. + DidFirstLayout = 1 << 0, + DidFirstVisuallyNonEmptyLayout = 1 << 1, + DidHitRelevantRepaintedObjectsAreaThreshold = 1 << 2, + DidFirstFlushForHeaderLayer = 1 << 3, + DidFirstLayoutAfterSuppressedIncrementalRendering = 1 << 4, + DidFirstPaintAfterSuppressedIncrementalRendering = 1 << 5, + ReachedSessionRestorationRenderTreeSizeThreshold = 1 << 6 // FIXME: only implemented by WK2 currently. }; typedef unsigned LayoutMilestones; diff --git a/webkit/WebCore/page/Page.cpp b/webkit/WebCore/page/Page.cpp index d4b38a612..1e126be50 100755 --- a/webkit/WebCore/page/Page.cpp +++ b/webkit/WebCore/page/Page.cpp @@ -275,6 +275,7 @@ Page::~Page() m_scrollingCoordinator->pageDestroyed(); backForward().close(); + PageCache::singleton().removeAllItemsForPage(*this); #ifndef NDEBUG pageCounter.decrement(); @@ -1514,7 +1515,7 @@ void Page::addRelevantRepaintedObject(RenderObject* object, const LayoutRect& ob m_isCountingRelevantRepaintedObjects = false; resetRelevantPaintedObjectCounter(); if (Frame* frame = &mainFrame()) - frame->loader().didLayout(DidHitRelevantRepaintedObjectsAreaThreshold); + frame->loader().didReachLayoutMilestone(DidHitRelevantRepaintedObjectsAreaThreshold); } } diff --git a/webkit/WebCore/page/Performance.cpp b/webkit/WebCore/page/Performance.cpp index bb2932cb4..424bf2414 100755 --- a/webkit/WebCore/page/Performance.cpp +++ b/webkit/WebCore/page/Performance.cpp @@ -231,7 +231,7 @@ void Performance::webkitClearMeasures(const String& measureName) double Performance::now() const { double nowSeconds = monotonicallyIncreasingTime() - m_referenceTime; - const double resolutionSeconds = 0.000005; + const double resolutionSeconds = 0.0001; return 1000.0 * floor(nowSeconds / resolutionSeconds) * resolutionSeconds; } diff --git a/webkit/WebCore/page/PointerLockController.cpp b/webkit/WebCore/page/PointerLockController.cpp index cbb341cad..d1d4415d5 100755 --- a/webkit/WebCore/page/PointerLockController.cpp +++ b/webkit/WebCore/page/PointerLockController.cpp @@ -95,6 +95,11 @@ void PointerLockController::documentDetached(Document* document) } } +bool PointerLockController::isLocked() const +{ + return m_element && !m_lockPending; +} + bool PointerLockController::lockPending() const { return m_lockPending; @@ -136,6 +141,14 @@ void PointerLockController::dispatchLockedMouseEvent(const PlatformMouseEvent& e m_element->dispatchMouseEvent(event, eventNames().clickEvent, event.clickCount()); } +void PointerLockController::dispatchLockedWheelEvent(const PlatformWheelEvent& event) +{ + if (!m_element || !m_element->document().frame()) + return; + + m_element->dispatchWheelEvent(event); +} + void PointerLockController::clearElement() { m_lockPending = false; diff --git a/webkit/WebCore/page/PointerLockController.h b/webkit/WebCore/page/PointerLockController.h index 762851b0f..939baed90 100755 --- a/webkit/WebCore/page/PointerLockController.h +++ b/webkit/WebCore/page/PointerLockController.h @@ -36,6 +36,7 @@ class Element; class Document; class Page; class PlatformMouseEvent; +class PlatformWheelEvent; class VoidCallback; class PointerLockController { @@ -47,6 +48,7 @@ class PointerLockController { void requestPointerUnlock(); void elementRemoved(Element*); void documentDetached(Document*); + bool isLocked() const; bool lockPending() const; Element* element() const; @@ -54,6 +56,7 @@ class PointerLockController { void didNotAcquirePointerLock(); void didLosePointerLock(); void dispatchLockedMouseEvent(const PlatformMouseEvent&, const AtomicString& eventType); + void dispatchLockedWheelEvent(const PlatformWheelEvent&); private: void clearElement(); diff --git a/webkit/WebCore/page/Settings.cpp b/webkit/WebCore/page/Settings.cpp index b1ec887b2..267dc5c01 100755 --- a/webkit/WebCore/page/Settings.cpp +++ b/webkit/WebCore/page/Settings.cpp @@ -127,6 +127,12 @@ static EditingBehaviorType editingBehaviorTypeForPlatform() ; } +#if PLATFORM(COCOA) +static const bool defaultYouTubeFlashPluginReplacementEnabled = true; +#else +static const bool defaultYouTubeFlashPluginReplacementEnabled = false; +#endif + #if PLATFORM(IOS) static const bool defaultFixedPositionCreatesStackingContext = true; static const bool defaultFixedBackgroundsPaintRelativeToDocument = true; @@ -138,6 +144,7 @@ static const bool defaultShouldRespectImageOrientation = true; static const bool defaultImageSubsamplingEnabled = true; static const bool defaultScrollingTreeIncludesFrames = true; static const bool defaultMediaControlsScaleWithPageZoom = true; +static const bool defaultQuickTimePluginReplacementEnabled = true; #else static const bool defaultFixedPositionCreatesStackingContext = false; static const bool defaultFixedBackgroundsPaintRelativeToDocument = false; @@ -149,6 +156,7 @@ static const bool defaultShouldRespectImageOrientation = false; static const bool defaultImageSubsamplingEnabled = false; static const bool defaultScrollingTreeIncludesFrames = false; static const bool defaultMediaControlsScaleWithPageZoom = true; +static const bool defaultQuickTimePluginReplacementEnabled = false; #endif static const bool defaultAllowsPictureInPictureMediaPlayback = true; diff --git a/webkit/WebCore/page/Settings.in b/webkit/WebCore/page/Settings.in index 722ac845f..e4f56144f 100755 --- a/webkit/WebCore/page/Settings.in +++ b/webkit/WebCore/page/Settings.in @@ -104,6 +104,7 @@ webGLEnabled initial=false webGLErrorsToConsoleEnabled initial=true openGLMultisamplingEnabled initial=true forceSoftwareWebGLRendering initial=false +preferLowPowerWebGLRendering initial=true accelerated2dCanvasEnabled initial=false antialiased2dCanvasEnabled initial=true loadDeferringEnabled initial=true @@ -248,3 +249,6 @@ httpEquivEnabled initial=true # enforces all frame sandbox flags (see enum SandboxFlag in SecurityContext.h), and also disables # processing and subframe loading. contentDispositionAttachmentSandboxEnabled initial=false + +quickTimePluginReplacementEnabled initial=defaultQuickTimePluginReplacementEnabled +youTubeFlashPluginReplacementEnabled initial=defaultYouTubeFlashPluginReplacementEnabled diff --git a/webkit/WebCore/page/SpatialNavigation.cpp b/webkit/WebCore/page/SpatialNavigation.cpp index 971edb3fb..761164af8 100755 --- a/webkit/WebCore/page/SpatialNavigation.cpp +++ b/webkit/WebCore/page/SpatialNavigation.cpp @@ -100,6 +100,22 @@ static inline bool isDiagonalDirection(FocusDirection direction) return false; } } + +bool isInsideFocusableFrame(Element* element) +{ + FrameView* view = element->document().frame()->view(); + + bool isFocusable = true; + for (; view; view = downcast(view->parent())) { + Element* owner = view->frame().ownerElement(); + if (owner && !owner->isFocusable()) { + isFocusable = false; + break; + } + } + + return isFocusable; +} #endif FocusCandidate::FocusCandidate(Node* node, FocusDirection direction) @@ -136,7 +152,19 @@ FocusCandidate::FocusCandidate(Node* node, FocusDirection direction) } focusableNode = node; +#if PLATFORM(WKC) + FrameView* frameView = node->document().view(); + if (frameView) { + if (frameView->parent()) { + frameView = frameView->frame().tree().top().view(); + } + IntRect r(rect.x(), rect.y(), rect.width(), rect.height()); + frameView->contentsToWindow(r); + isOffscreen = !frameView->visibleContentRect().intersects(r); + } +#else isOffscreen = hasOffscreenRect(visibleNode); +#endif isOffscreenAfterScrolling = hasOffscreenRect(visibleNode, direction); #if PLATFORM(WKC) if (visibleNode->hasTagName(HTMLNames::aTag) && visibleNode->firstChild()) { diff --git a/webkit/WebCore/page/SpatialNavigation.h b/webkit/WebCore/page/SpatialNavigation.h index c5aca450d..e6fc86cc2 100755 --- a/webkit/WebCore/page/SpatialNavigation.h +++ b/webkit/WebCore/page/SpatialNavigation.h @@ -1,7 +1,7 @@ /* * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies) * Copyright (C) 2009 Antonio Gomes - * Copyright (C) 2012-2016 ACCESS CO., LTD. All rights reserved. + * Copyright (C) 2012-2017 ACCESS CO., LTD. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -178,6 +178,7 @@ LayoutRect rectToAbsoluteCoordinates(Frame* initialFrame, const LayoutRect& init void SpatialNavigation_SetEffectiveAngleForHorizontalNavigation(unsigned int angle); void SpatialNavigation_SetEffectiveAngleForVerticalNavigation(unsigned int angle); void SpatialNavigation_SetEffectiveAngleForDiagonalNavigation(unsigned int minAngle, unsigned int maxAngle); +bool isInsideFocusableFrame(Element* element); #endif } // namspace WebCore diff --git a/webkit/WebCore/page/TextIndicator.cpp b/webkit/WebCore/page/TextIndicator.cpp index 848869b77..cd0b106e0 100755 --- a/webkit/WebCore/page/TextIndicator.cpp +++ b/webkit/WebCore/page/TextIndicator.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010, 2015 Apple Inc. All rights reserved. + * Copyright (C) 2010, 2015-2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -55,6 +55,8 @@ RefPtr TextIndicator::createWithRange(const Range& range, TextInd if (!frame) return nullptr; + Ref protector(*frame); + #if PLATFORM(IOS) frame->editor().setIgnoreCompositionSelectionChange(true); frame->selection().setUpdateAppearanceEnabled(true); diff --git a/webkit/WebCore/page/ValidationMessageClient.h b/webkit/WebCore/page/ValidationMessageClient.h index 3beaca09f..21f2bdc0b 100755 --- a/webkit/WebCore/page/ValidationMessageClient.h +++ b/webkit/WebCore/page/ValidationMessageClient.h @@ -30,6 +30,7 @@ namespace WebCore { +class Document; class Element; class ValidationMessageClient { @@ -45,9 +46,14 @@ class ValidationMessageClient { // anchor is already visible. virtual void hideValidationMessage(const Element& anchor) = 0; + // Hide any validation message currently displayed. + virtual void hideAnyValidationMessage() = 0; + // Returns true if the validation message for the specified anchor element // is visible. virtual bool isValidationMessageVisible(const Element& anchor) = 0; + + virtual void documentDetached(Document&) = 0; }; } diff --git a/webkit/WebCore/page/animation/AnimationController.cpp b/webkit/WebCore/page/animation/AnimationController.cpp index d1cb7d4bb..8b353e560 100755 --- a/webkit/WebCore/page/animation/AnimationController.cpp +++ b/webkit/WebCore/page/animation/AnimationController.cpp @@ -773,4 +773,9 @@ void AnimationController::scrollWasUpdated() } #endif +bool AnimationController::hasAnimations() const +{ + return m_data->hasAnimations(); +} + } // namespace WebCore diff --git a/webkit/WebCore/page/animation/AnimationController.h b/webkit/WebCore/page/animation/AnimationController.h index d9ece8214..c4d85e4dd 100755 --- a/webkit/WebCore/page/animation/AnimationController.h +++ b/webkit/WebCore/page/animation/AnimationController.h @@ -94,6 +94,8 @@ class AnimationController { void scrollWasUpdated(); #endif + bool hasAnimations() const; + private: const std::unique_ptr m_data; }; diff --git a/webkit/WebCore/page/animation/CSSPropertyAnimation.cpp b/webkit/WebCore/page/animation/CSSPropertyAnimation.cpp index 5e247a854..fcf05ec97 100755 --- a/webkit/WebCore/page/animation/CSSPropertyAnimation.cpp +++ b/webkit/WebCore/page/animation/CSSPropertyAnimation.cpp @@ -292,6 +292,8 @@ static inline PassRefPtr crossfadeBlend(const AnimationBase*, StyleC return fromStyleImage; if (progress == 1) return toStyleImage; + if (!fromStyleImage->cachedImage() || !toStyleImage->cachedImage()) + return toStyleImage; auto fromImageValue = CSSImageValue::create(fromStyleImage->cachedImage()->url(), fromStyleImage); auto toImageValue = CSSImageValue::create(toStyleImage->cachedImage()->url(), toStyleImage); diff --git a/webkit/WebCore/page/scrolling/ScrollingStateTree.cpp b/webkit/WebCore/page/scrolling/ScrollingStateTree.cpp index 8c52c8b7e..980f1415c 100755 --- a/webkit/WebCore/page/scrolling/ScrollingStateTree.cpp +++ b/webkit/WebCore/page/scrolling/ScrollingStateTree.cpp @@ -79,21 +79,31 @@ PassRefPtr ScrollingStateTree::createNode(ScrollingNodeType return nullptr; } +bool ScrollingStateTree::nodeTypeAndParentMatch(ScrollingStateNode& node, ScrollingNodeType nodeType, ScrollingNodeID parentID) const +{ + if (node.nodeType() != nodeType) + return false; + + ScrollingStateNode* parent = stateNodeForID(parentID); + if (!parent) + return true; + + return node.parent() == parent; +} + ScrollingNodeID ScrollingStateTree::attachNode(ScrollingNodeType nodeType, ScrollingNodeID newNodeID, ScrollingNodeID parentID) { ASSERT(newNodeID); - if (ScrollingStateNode* node = stateNodeForID(newNodeID)) { - if (!parentID) - return newNodeID; - - ScrollingStateNode* parent = stateNodeForID(parentID); - if (!parent) - return newNodeID; - if (node->parent() == parent) + if (ScrollingStateNode* node = stateNodeForID(newNodeID)) { + if (nodeTypeAndParentMatch(*node, nodeType, parentID)) return newNodeID; + + // If the type has changed, we need to destroy and recreate the node with a new ID. + if (nodeType != node->nodeType()) + newNodeID = m_scrollingCoordinator->uniqueScrollLayerID(); - // The node is being re-parented. To do that, we'll remove it, and then re-create a new node. + // The node is being re-parented. To do that, we'll remove it, and then create a new node. removeNodeAndAllDescendants(node, SubframeNodeRemoval::Orphan); } @@ -232,7 +242,7 @@ void ScrollingStateTree::setRemovedNodes(HashSet nodes) m_nodesRemovedSinceLastCommit = WTF::move(nodes); } -ScrollingStateNode* ScrollingStateTree::stateNodeForID(ScrollingNodeID scrollLayerID) +ScrollingStateNode* ScrollingStateTree::stateNodeForID(ScrollingNodeID scrollLayerID) const { if (!scrollLayerID) return 0; diff --git a/webkit/WebCore/page/scrolling/ScrollingStateTree.h b/webkit/WebCore/page/scrolling/ScrollingStateTree.h index ee7d69276..3f8bf70f0 100755 --- a/webkit/WebCore/page/scrolling/ScrollingStateTree.h +++ b/webkit/WebCore/page/scrolling/ScrollingStateTree.h @@ -47,7 +47,7 @@ class ScrollingStateTree { WEBCORE_EXPORT ~ScrollingStateTree(); ScrollingStateFrameScrollingNode* rootStateNode() const { return m_rootStateNode.get(); } - WEBCORE_EXPORT ScrollingStateNode* stateNodeForID(ScrollingNodeID); + WEBCORE_EXPORT ScrollingStateNode* stateNodeForID(ScrollingNodeID) const; WEBCORE_EXPORT ScrollingNodeID attachNode(ScrollingNodeType, ScrollingNodeID, ScrollingNodeID parentID); void detachNode(ScrollingNodeID); @@ -78,7 +78,9 @@ class ScrollingStateTree { void addNode(ScrollingStateNode*); PassRefPtr createNode(ScrollingNodeType, ScrollingNodeID); - + + bool nodeTypeAndParentMatch(ScrollingStateNode&, ScrollingNodeType, ScrollingNodeID parentID) const; + enum class SubframeNodeRemoval { Delete, Orphan diff --git a/webkit/WebCore/platform/DragData.h b/webkit/WebCore/platform/DragData.h index fff11085d..056c0ff13 100755 --- a/webkit/WebCore/platform/DragData.h +++ b/webkit/WebCore/platform/DragData.h @@ -107,6 +107,8 @@ class DragData { bool containsFiles() const; unsigned numberOfFiles() const; int modifierKeyState() const; + void setFileNames(Vector& fileNames) { m_fileNames = WTF::move(fileNames); } + const Vector& fileNames() const { return m_fileNames; } #if PLATFORM(MAC) const String& pasteboardName() const { return m_pasteboardName; } #endif @@ -133,6 +135,7 @@ class DragData { DragDataRef m_platformDragData; DragOperation m_draggingSourceOperationMask; DragApplicationFlags m_applicationFlags; + Vector m_fileNames; #if PLATFORM(MAC) String m_pasteboardName; #endif diff --git a/webkit/WebCore/platform/GamepadProvider.cpp b/webkit/WebCore/platform/GamepadProvider.cpp index 2f339df3a..59805b25d 100755 --- a/webkit/WebCore/platform/GamepadProvider.cpp +++ b/webkit/WebCore/platform/GamepadProvider.cpp @@ -27,6 +27,7 @@ #if ENABLE(GAMEPAD) +#include "GamepadProviderClient.h" #include namespace WebCore { @@ -77,6 +78,14 @@ const Vector& GamepadProvider::platformGamepads() #endif } +void GamepadProvider::dispatchPlatformGamepadInputActivity() +{ + for (auto& client : m_clients) + client->platformGamepadInputActivity(m_shouldMakeGamepadsVisible); + + m_shouldMakeGamepadsVisible = false; +} + } // namespace WebCore #endif // ENABLE(GAMEPAD) diff --git a/webkit/WebCore/platform/GamepadProvider.h b/webkit/WebCore/platform/GamepadProvider.h index aa31cf89b..cf91d25d3 100755 --- a/webkit/WebCore/platform/GamepadProvider.h +++ b/webkit/WebCore/platform/GamepadProvider.h @@ -28,6 +28,7 @@ #if ENABLE(GAMEPAD) +#include #include namespace WebCore { @@ -35,7 +36,7 @@ namespace WebCore { class GamepadProviderClient; class PlatformGamepad; -class GamepadProvider { +class WEBCORE_EXPORT GamepadProvider { #if PLATFORM(WKC) WTF_MAKE_FAST_ALLOCATED; #endif @@ -48,6 +49,14 @@ class GamepadProvider { virtual void startMonitoringGamepads(GamepadProviderClient*); virtual void stopMonitoringGamepads(GamepadProviderClient*); virtual const Vector& platformGamepads(); + +protected: + void dispatchPlatformGamepadInputActivity(); + void setShouldMakeGamepadsVisibile() { m_shouldMakeGamepadsVisible = true; } + HashSet m_clients; + +private: + bool m_shouldMakeGamepadsVisible { false }; }; } // namespace WebCore diff --git a/webkit/WebCore/platform/GamepadProviderClient.h b/webkit/WebCore/platform/GamepadProviderClient.h index cc9692875..819cb4cfd 100755 --- a/webkit/WebCore/platform/GamepadProviderClient.h +++ b/webkit/WebCore/platform/GamepadProviderClient.h @@ -38,7 +38,7 @@ class GamepadProviderClient { virtual void platformGamepadConnected(PlatformGamepad&) = 0; virtual void platformGamepadDisconnected(PlatformGamepad&) = 0; - virtual void platformGamepadInputActivity() = 0; + virtual void platformGamepadInputActivity(bool shouldMakeGamepadVisible) = 0; }; } // namespace WebCore diff --git a/webkit/WebCore/platform/LocalizedStrings.cpp b/webkit/WebCore/platform/LocalizedStrings.cpp index 78cbab19c..084972c7e 100755 --- a/webkit/WebCore/platform/LocalizedStrings.cpp +++ b/webkit/WebCore/platform/LocalizedStrings.cpp @@ -1036,11 +1036,15 @@ String validationMessagePatternMismatchText() return WEB_UI_STRING("pattern mismatch", "Validation message for input form controls requiring a constrained value according to pattern"); } +#if !PLATFORM(COCOA) + String validationMessageTooLongText(int, int) { return WEB_UI_STRING("too long", "Validation message for form control elements with a value longer than maximum allowed length"); } +#endif + String validationMessageRangeUnderflowText(const String&) { return WEB_UI_STRING("range underflow", "Validation message for input form controls with value lower than allowed minimum"); diff --git a/webkit/WebCore/platform/LocalizedStrings.h b/webkit/WebCore/platform/LocalizedStrings.h index e7ace9003..3bfb8a645 100755 --- a/webkit/WebCore/platform/LocalizedStrings.h +++ b/webkit/WebCore/platform/LocalizedStrings.h @@ -276,6 +276,11 @@ namespace WebCore { WEBCORE_EXPORT String localizedString(const char* key); +#ifdef __OBJC__ +#define WEB_UI_NSSTRING(string, description) WebCore::localizedNSString(string) + WEBCORE_EXPORT NSString *localizedNSString(NSString *key) NS_FORMAT_ARGUMENT(1); +#endif + } // namespace WebCore #endif // LocalizedStrings_h diff --git a/webkit/WebCore/platform/MIMETypeRegistry.cpp b/webkit/WebCore/platform/MIMETypeRegistry.cpp index e61819250..f4442c012 100755 --- a/webkit/WebCore/platform/MIMETypeRegistry.cpp +++ b/webkit/WebCore/platform/MIMETypeRegistry.cpp @@ -499,7 +499,11 @@ String MIMETypeRegistry::getMIMETypeForPath(const String& path) size_t pos = path.reverseFind('.'); if (pos != notFound) { String extension = path.substring(pos + 1); +#if PLATFORM(WKC) + String result = getMediaMIMETypeForExtension(extension); +#else String result = getMIMETypeForExtension(extension); +#endif if (result.length()) return result; } diff --git a/webkit/WebCore/platform/RemoteCommandListener.h b/webkit/WebCore/platform/RemoteCommandListener.h index 5536791f2..1d68933c6 100755 --- a/webkit/WebCore/platform/RemoteCommandListener.h +++ b/webkit/WebCore/platform/RemoteCommandListener.h @@ -34,7 +34,8 @@ class RemoteCommandListenerClient { WTF_MAKE_FAST_ALLOCATED; public: virtual ~RemoteCommandListenerClient() { } - virtual void didReceiveRemoteControlCommand(PlatformMediaSession::RemoteControlCommandType) = 0; + virtual void didReceiveRemoteControlCommand(PlatformMediaSession::RemoteControlCommandType, const PlatformMediaSession::RemoteCommandArgument*) = 0; + virtual bool supportsSeeking() const = 0; }; class RemoteCommandListener { @@ -46,6 +47,10 @@ class RemoteCommandListener { RemoteCommandListener(RemoteCommandListenerClient& client) : m_client(client) { } virtual ~RemoteCommandListener() { } + virtual void updateSupportedCommands() { } + + RemoteCommandListenerClient& client() const { return m_client; } + protected: RemoteCommandListenerClient& m_client; }; diff --git a/webkit/WebCore/platform/URL.cpp b/webkit/WebCore/platform/URL.cpp index 3c1861278..d7ce94442 100755 --- a/webkit/WebCore/platform/URL.cpp +++ b/webkit/WebCore/platform/URL.cpp @@ -1997,6 +1997,13 @@ bool URL::isBlankURL() const return protocolIs("about"); } +bool URL::shouldInheritSecurityOriginFromOwner() const +{ + return isEmpty() + || equalIgnoringASCIICase(m_string, blankURL().string()) + || equalIgnoringASCIICase(m_string, "about:srcdoc"); +} + bool isDefaultPortForProtocol(unsigned short port, const String& protocol) { if (protocol.isEmpty()) diff --git a/webkit/WebCore/platform/URL.h b/webkit/WebCore/platform/URL.h index 4cd31861d..d53c9d094 100755 --- a/webkit/WebCore/platform/URL.h +++ b/webkit/WebCore/platform/URL.h @@ -136,6 +136,7 @@ class URL { bool protocolIsInHTTPFamily() const; WEBCORE_EXPORT bool isLocalFile() const; bool isBlankURL() const; + bool shouldInheritSecurityOriginFromOwner() const; WEBCORE_EXPORT bool setProtocol(const String&); void setHost(const String&); diff --git a/webkit/WebCore/platform/audio/PlatformMediaSession.cpp b/webkit/WebCore/platform/audio/PlatformMediaSession.cpp index d980f4d57..cf07c5ed3 100755 --- a/webkit/WebCore/platform/audio/PlatformMediaSession.cpp +++ b/webkit/WebCore/platform/audio/PlatformMediaSession.cpp @@ -213,9 +213,14 @@ bool PlatformMediaSession::canReceiveRemoteControlCommands() const return m_client.canReceiveRemoteControlCommands(); } -void PlatformMediaSession::didReceiveRemoteControlCommand(RemoteControlCommandType command) +void PlatformMediaSession::didReceiveRemoteControlCommand(RemoteControlCommandType command, const PlatformMediaSession::RemoteCommandArgument* argument) { - m_client.didReceiveRemoteControlCommand(command); + m_client.didReceiveRemoteControlCommand(command, argument); +} + +bool PlatformMediaSession::supportsSeeking() const +{ + return m_client.supportsSeeking(); } void PlatformMediaSession::visibilityChanged() @@ -250,6 +255,11 @@ void PlatformMediaSession::updateClientDataBuffering() m_client.setShouldBufferData(PlatformMediaSessionManager::sharedManager().sessionCanLoadMedia(*this)); } +String PlatformMediaSession::sourceApplicationIdentifier() const +{ + return m_client.sourceApplicationIdentifier(); +} + bool PlatformMediaSession::isHidden() const { return m_client.elementIsHidden(); diff --git a/webkit/WebCore/platform/audio/PlatformMediaSession.h b/webkit/WebCore/platform/audio/PlatformMediaSession.h index 805531d8c..2ecdcd1e2 100755 --- a/webkit/WebCore/platform/audio/PlatformMediaSession.h +++ b/webkit/WebCore/platform/audio/PlatformMediaSession.h @@ -104,6 +104,10 @@ class PlatformMediaSession double duration() const; double currentTime() const; + typedef union { + double asDouble; + } RemoteCommandArgument; + enum RemoteControlCommandType { NoCommand, PlayCommand, @@ -114,9 +118,11 @@ class PlatformMediaSession EndSeekingBackwardCommand, BeginSeekingForwardCommand, EndSeekingForwardCommand, + SeekToPlaybackPositionCommand, }; bool canReceiveRemoteControlCommands() const; - void didReceiveRemoteControlCommand(RemoteControlCommandType); + void didReceiveRemoteControlCommand(RemoteControlCommandType, const RemoteCommandArgument* argument = nullptr); + bool supportsSeeking() const; enum DisplayType { Normal, @@ -141,6 +147,8 @@ class PlatformMediaSession virtual bool requiresPlaybackTargetRouteMonitoring() const { return false; } #endif + String sourceApplicationIdentifier() const; + protected: PlatformMediaSessionClient& client() const { return m_client; } @@ -175,7 +183,8 @@ class PlatformMediaSessionClient { virtual double mediaSessionCurrentTime() const; virtual bool canReceiveRemoteControlCommands() const = 0; - virtual void didReceiveRemoteControlCommand(PlatformMediaSession::RemoteControlCommandType) = 0; + virtual void didReceiveRemoteControlCommand(PlatformMediaSession::RemoteControlCommandType, const PlatformMediaSession::RemoteCommandArgument*) = 0; + virtual bool supportsSeeking() const = 0; virtual void setShouldBufferData(bool) { } virtual bool elementIsHidden() const { return false; } @@ -189,6 +198,7 @@ class PlatformMediaSessionClient { virtual void setShouldPlayToPlaybackTarget(bool) { } virtual const Document* hostingDocument() const = 0; + virtual String sourceApplicationIdentifier() const = 0; protected: virtual ~PlatformMediaSessionClient() { } diff --git a/webkit/WebCore/platform/audio/PlatformMediaSessionManager.cpp b/webkit/WebCore/platform/audio/PlatformMediaSessionManager.cpp index 35971d526..a27a059f6 100755 --- a/webkit/WebCore/platform/audio/PlatformMediaSessionManager.cpp +++ b/webkit/WebCore/platform/audio/PlatformMediaSessionManager.cpp @@ -247,11 +247,13 @@ void PlatformMediaSessionManager::setCurrentSession(PlatformMediaSession& sessio m_sessions.remove(index); m_sessions.insert(0, &session); + if (m_remoteCommandListener) + m_remoteCommandListener->updateSupportedCommands(); LOG(Media, "PlatformMediaSessionManager::setCurrentSession - session moved from index %zu to 0", index); } -PlatformMediaSession* PlatformMediaSessionManager::currentSession() +PlatformMediaSession* PlatformMediaSessionManager::currentSession() const { if (!m_sessions.size()) return nullptr; @@ -313,12 +315,20 @@ void PlatformMediaSessionManager::updateSessionState() } #endif -void PlatformMediaSessionManager::didReceiveRemoteControlCommand(PlatformMediaSession::RemoteControlCommandType command) +void PlatformMediaSessionManager::didReceiveRemoteControlCommand(PlatformMediaSession::RemoteControlCommandType command, const PlatformMediaSession::RemoteCommandArgument* argument) { PlatformMediaSession* activeSession = currentSession(); if (!activeSession || !activeSession->canReceiveRemoteControlCommands()) return; - activeSession->didReceiveRemoteControlCommand(command); + activeSession->didReceiveRemoteControlCommand(command, argument); +} + +bool PlatformMediaSessionManager::supportsSeeking() const +{ + PlatformMediaSession* activeSession = currentSession(); + if (!activeSession) + return false; + return activeSession->supportsSeeking(); } void PlatformMediaSessionManager::systemWillSleep() diff --git a/webkit/WebCore/platform/audio/PlatformMediaSessionManager.h b/webkit/WebCore/platform/audio/PlatformMediaSessionManager.h index 199624973..c19cbf6a9 100755 --- a/webkit/WebCore/platform/audio/PlatformMediaSessionManager.h +++ b/webkit/WebCore/platform/audio/PlatformMediaSessionManager.h @@ -47,10 +47,15 @@ class PlatformMediaSessionManager : private RemoteCommandListenerClient, private WEBCORE_EXPORT static PlatformMediaSessionManager& sharedManager(); virtual ~PlatformMediaSessionManager() { } + virtual void scheduleUpdateNowPlayingInfo() { } bool has(PlatformMediaSession::MediaType) const; int count(PlatformMediaSession::MediaType) const; bool activeAudioSessionRequired() const; + WEBCORE_EXPORT virtual String lastUpdatedNowPlayingTitle() const { return emptyString(); } + WEBCORE_EXPORT virtual double lastUpdatedNowPlayingDuration() const { return NAN; } + WEBCORE_EXPORT virtual double lastUpdatedNowPlayingElapsedTime() const { return NAN; } + WEBCORE_EXPORT void beginInterruption(PlatformMediaSession::InterruptionType); WEBCORE_EXPORT void endInterruption(PlatformMediaSession::EndInterruptionFlags); @@ -84,6 +89,7 @@ class PlatformMediaSessionManager : private RemoteCommandListenerClient, private bool sessionRestrictsInlineVideoPlayback(const PlatformMediaSession&) const; virtual bool sessionCanLoadMedia(const PlatformMediaSession&) const; + virtual void sessionDidEndRemoteScrubbing(const PlatformMediaSession&) { }; #if PLATFORM(IOS) virtual void configureWireLessTargetMonitoring() { } @@ -91,7 +97,7 @@ class PlatformMediaSessionManager : private RemoteCommandListenerClient, private #endif void setCurrentSession(PlatformMediaSession&); - PlatformMediaSession* currentSession(); + PlatformMediaSession* currentSession() const; protected: friend class PlatformMediaSession; @@ -108,7 +114,8 @@ class PlatformMediaSessionManager : private RemoteCommandListenerClient, private void updateSessionState(); // RemoteCommandListenerClient - WEBCORE_EXPORT virtual void didReceiveRemoteControlCommand(PlatformMediaSession::RemoteControlCommandType) override; + WEBCORE_EXPORT void didReceiveRemoteControlCommand(PlatformMediaSession::RemoteControlCommandType, const PlatformMediaSession::RemoteCommandArgument*) override; + WEBCORE_EXPORT bool supportsSeeking() const override; // AudioHardwareListenerClient virtual void audioHardwareDidBecomeActive() override { } diff --git a/webkit/WebCore/platform/cocoa/LocalizedStringsCocoa.mm b/webkit/WebCore/platform/cocoa/LocalizedStringsCocoa.mm index ad33430a8..fb596f236 100755 --- a/webkit/WebCore/platform/cocoa/LocalizedStringsCocoa.mm +++ b/webkit/WebCore/platform/cocoa/LocalizedStringsCocoa.mm @@ -26,7 +26,6 @@ #include "config.h" #include "LocalizedStrings.h" -#include #include #include #include @@ -34,26 +33,27 @@ namespace WebCore { -String localizedString(const char* key) +NSString *localizedNSString(NSString *key) { - static CFBundleRef bundle = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.WebCore")); - #if !PLATFORM(IOS) // Can be called on a dispatch queue when initializing strings on iOS. // See LoadWebLocalizedStrings and . ASSERT(isMainThread()); #endif + static NSBundle *bundle = [NSBundle bundleWithIdentifier:@"com.apple.WebCore"]; + return [bundle localizedStringForKey:key value:@"localized string not found" table:nullptr]; +} + +String localizedString(const char* key) +{ RetainPtr keyString = adoptCF(CFStringCreateWithCStringNoCopy(0, key, kCFStringEncodingUTF8, kCFAllocatorNull)); - CFStringRef notFound = CFSTR("localized string not found"); - RetainPtr result; - if (bundle) { - result = adoptCF(CFBundleCopyLocalizedString(bundle, keyString.get(), notFound, 0)); - ASSERT_WITH_MESSAGE(result.get() != notFound, "could not find localizable string %s in bundle", key); - } else - result = notFound; - - return String(result.get()); + return localizedNSString((NSString *)keyString.get()); +} + +String validationMessageTooLongText(int, int maxLength) +{ + return [NSString localizedStringWithFormat:WEB_UI_NSSTRING(@"Use no more than %d character(s)", @"Validation message for form control elements with a value shorter than maximum allowed length"), maxLength]; } } // namespace WebCore diff --git a/webkit/WebCore/platform/graphics/ANGLEWebKitBridge.cpp b/webkit/WebCore/platform/graphics/ANGLEWebKitBridge.cpp index d769d0101..d21c88a77 100755 --- a/webkit/WebCore/platform/graphics/ANGLEWebKitBridge.cpp +++ b/webkit/WebCore/platform/graphics/ANGLEWebKitBridge.cpp @@ -242,13 +242,21 @@ bool ANGLEWebKitBridge::compileShaderSource(const char* shaderSource, ANGLEShade bool validateSuccess = ShCompile(compiler, shaderSourceStrings, 1, SH_OBJECT_CODE | SH_VARIABLES | extraCompileOptions); if (!validateSuccess) { +#if !PLATFORM(WKC) const std::string& log = ShGetInfoLog(compiler); +#else + const wkc_angle_string& log = ShGetInfoLog(compiler); +#endif if (log.length()) shaderValidationLog = log.c_str(); return false; } +#if !PLATFORM(WKC) const std::string& objectCode = ShGetObjectCode(compiler); +#else + const wkc_angle_string& objectCode = ShGetObjectCode(compiler); +#endif if (objectCode.length()) translatedShaderSource = objectCode.c_str(); diff --git a/webkit/WebCore/platform/graphics/ANGLEWebKitBridge.h b/webkit/WebCore/platform/graphics/ANGLEWebKitBridge.h index 8c52e8242..4654446b4 100755 --- a/webkit/WebCore/platform/graphics/ANGLEWebKitBridge.h +++ b/webkit/WebCore/platform/graphics/ANGLEWebKitBridge.h @@ -46,6 +46,9 @@ #if !PLATFORM(GTK) && !PLATFORM(EFL) && !PLATFORM(WIN) && !PLATFORM(WKC) && !defined(BUILDING_WITH_CMAKE) #include "ANGLE/ShaderLang.h" #elif (PLATFORM(WIN) || PLATFORM(WKC)) && !defined(BUILDING_WITH_CMAKE) +#if PLATFORM(WKC) +#define __WKC__ +#endif #include "GLSLANG/ShaderLang.h" #else #include diff --git a/webkit/WebCore/platform/graphics/BitmapImage.cpp b/webkit/WebCore/platform/graphics/BitmapImage.cpp index 3758a5f26..b445aa70d 100755 --- a/webkit/WebCore/platform/graphics/BitmapImage.cpp +++ b/webkit/WebCore/platform/graphics/BitmapImage.cpp @@ -506,6 +506,21 @@ PassNativeImagePtr BitmapImage::nativeImageForCurrentFrame() return frameAtIndex(currentFrame()); } +#if USE(CG) +Vector BitmapImage::framesNativeImages() +{ + Vector images; + size_t count = frameCount(); + + for (size_t i = 0; i < count; ++i) { + if (auto image = frameImageAtIndex(i)) + images.append(image); + } + + return images; +} +#endif + bool BitmapImage::frameHasAlphaAtIndex(size_t index) { if (!ensureFrameIsCached(index, CacheMetadataOnly)) diff --git a/webkit/WebCore/platform/graphics/BitmapImage.h b/webkit/WebCore/platform/graphics/BitmapImage.h index fda5855e6..097b01c67 100755 --- a/webkit/WebCore/platform/graphics/BitmapImage.h +++ b/webkit/WebCore/platform/graphics/BitmapImage.h @@ -152,11 +152,12 @@ class BitmapImage final : public Image { // Accessors for native image formats. #if USE(APPKIT) - virtual NSImage* getNSImage() override; + NSImage *nsImage() override; + RetainPtr snapshotNSImage() override; #endif #if PLATFORM(COCOA) - virtual CFDataRef getTIFFRepresentation() override; + CFDataRef tiffRepresentation() override; #endif #if USE(CG) @@ -180,6 +181,9 @@ class BitmapImage final : public Image { virtual PassNativeImagePtr nativeImageForCurrentFrame() override; virtual ImageOrientation orientationForCurrentFrame() override { return frameOrientationAtIndex(currentFrame()); } +#if USE(CG) + Vector framesNativeImages() override; +#endif virtual bool currentFrameKnownToBeOpaque() override; @@ -299,6 +303,10 @@ class BitmapImage final : public Image { void syncFrameData(size_t index); #endif +#if PLATFORM(COCOA) + RetainPtr tiffRepresentation(const Vector&); +#endif + private: virtual bool decodedDataIsPurgeable() const override; void clearTimer(); @@ -323,10 +331,10 @@ class BitmapImage final : public Image { double m_desiredFrameStartTime; // The system time at which we hope to see the next call to startAnimation(). #if USE(APPKIT) - mutable RetainPtr m_nsImage; // A cached NSImage of frame 0. Only built lazily if someone actually queries for one. + mutable RetainPtr m_nsImage; // A cached NSImage of all the frames. Only built lazily if someone actually queries for one. #endif #if USE(CG) - mutable RetainPtr m_tiffRep; // Cached TIFF rep for frame 0. Only built lazily if someone queries for one. + mutable RetainPtr m_tiffRep; // Cached TIFF rep for all the frames. Only built lazily if someone queries for one. #endif Color m_solidColor; // If we're a 1x1 solid color, this is the color to use to fill. diff --git a/webkit/WebCore/platform/graphics/GlyphBuffer.h b/webkit/WebCore/platform/graphics/GlyphBuffer.h index c910e3e36..d1502775e 100755 --- a/webkit/WebCore/platform/graphics/GlyphBuffer.h +++ b/webkit/WebCore/platform/graphics/GlyphBuffer.h @@ -103,9 +103,6 @@ class GlyphBuffer { void setInitialAdvance(GlyphBufferAdvance initialAdvance) { m_initialAdvance = initialAdvance; } const GlyphBufferAdvance& initialAdvance() const { return m_initialAdvance; } - - void setLeadingExpansion(float leadingExpansion) { m_leadingExpansion = leadingExpansion; } - float leadingExpansion() const { return m_leadingExpansion; } Glyph glyphAt(int index) const { @@ -250,7 +247,6 @@ class GlyphBuffer { #if PLATFORM(WIN) Vector m_offsets; #endif - float m_leadingExpansion; }; } diff --git a/webkit/WebCore/platform/graphics/GraphicsContext3D.h b/webkit/WebCore/platform/graphics/GraphicsContext3D.h index 222abd263..67d78ed83 100755 --- a/webkit/WebCore/platform/graphics/GraphicsContext3D.h +++ b/webkit/WebCore/platform/graphics/GraphicsContext3D.h @@ -721,32 +721,19 @@ class GraphicsContext3D : public RefCounted { // Context creation attributes. struct Attributes { - Attributes() - : alpha(true) - , depth(true) - , stencil(false) - , antialias(true) - , premultipliedAlpha(true) - , preserveDrawingBuffer(false) - , noExtensions(false) - , shareResources(true) - , preferDiscreteGPU(false) - , forceSoftwareRenderer(false) - , devicePixelRatio(1) - { - } - - bool alpha; - bool depth; - bool stencil; - bool antialias; - bool premultipliedAlpha; - bool preserveDrawingBuffer; - bool noExtensions; - bool shareResources; - bool preferDiscreteGPU; - bool forceSoftwareRenderer; - float devicePixelRatio; + bool alpha { true }; + bool depth { true }; + bool stencil { false }; + bool antialias { true }; + bool premultipliedAlpha { true }; + bool preserveDrawingBuffer { false }; + bool noExtensions { false }; + bool shareResources { true }; + bool preferLowPowerToHighPerformance { false }; + bool forceSoftwareRenderer { false }; + bool failIfMajorPerformanceCaveat { false }; + bool useGLES3 { false }; + float devicePixelRatio { 1 }; }; enum RenderStyle { @@ -1471,6 +1458,8 @@ class GraphicsContext3D : public RefCounted { std::unique_ptr m_private; WebGLRenderingContextBase* m_webglContext; + + bool m_isForWebGL2 { false }; }; } // namespace WebCore diff --git a/webkit/WebCore/platform/graphics/Image.h b/webkit/WebCore/platform/graphics/Image.h index e3845df12..e831c46c7 100755 --- a/webkit/WebCore/platform/graphics/Image.h +++ b/webkit/WebCore/platform/graphics/Image.h @@ -135,15 +135,17 @@ class Image : public RefCounted { virtual PassNativeImagePtr nativeImageForCurrentFrame() { return 0; } virtual ImageOrientation orientationForCurrentFrame() { return ImageOrientation(); } + virtual Vector framesNativeImages() { return { }; } // Accessors for native image formats. #if USE(APPKIT) - virtual NSImage* getNSImage() { return 0; } + virtual NSImage *nsImage() { return nullptr; } + virtual RetainPtr snapshotNSImage() { return nullptr; } #endif #if PLATFORM(COCOA) - virtual CFDataRef getTIFFRepresentation() { return 0; } + virtual CFDataRef tiffRepresentation() { return nullptr; } #endif #if USE(CG) diff --git a/webkit/WebCore/platform/graphics/MediaPlayer.cpp b/webkit/WebCore/platform/graphics/MediaPlayer.cpp index 2659dd973..2b29b4567 100755 --- a/webkit/WebCore/platform/graphics/MediaPlayer.cpp +++ b/webkit/WebCore/platform/graphics/MediaPlayer.cpp @@ -1445,6 +1445,17 @@ bool MediaPlayer::getRawCookies(const URL& url, Vector& cookies) const } #endif +void MediaPlayer::setShouldDisableSleep(bool flag) +{ + if (m_private) + m_private->setShouldDisableSleep(flag); +} + +bool MediaPlayer::shouldDisableSleep() const +{ + return m_client.mediaPlayerShouldDisableSleep(); +} + } #endif diff --git a/webkit/WebCore/platform/graphics/MediaPlayer.h b/webkit/WebCore/platform/graphics/MediaPlayer.h index 4ad242c59..e6fbce3cf 100755 --- a/webkit/WebCore/platform/graphics/MediaPlayer.h +++ b/webkit/WebCore/platform/graphics/MediaPlayer.h @@ -290,6 +290,8 @@ class MediaPlayerClient { virtual double mediaPlayerRequestedPlaybackRate() const { return 0; } virtual MediaPlayerEnums::VideoFullscreenMode mediaPlayerFullscreenMode() const { return MediaPlayerEnums::VideoFullscreenModeNone; } virtual Vector mediaPlayerPreferredAudioCharacteristics() const { return Vector(); } + + virtual bool mediaPlayerShouldDisableSleep() const { return false; } }; class MediaPlayerSupportsTypeClient { @@ -628,6 +630,9 @@ class MediaPlayer : public MediaPlayerEnums { String sourceApplicationIdentifier() const; Vector preferredAudioCharacteristics() const; + void setShouldDisableSleep(bool); + bool shouldDisableSleep() const; + private: const MediaPlayerFactory* nextBestMediaEngine(const MediaPlayerFactory*) const; void loadWithNextMediaEngine(const MediaPlayerFactory*); diff --git a/webkit/WebCore/platform/graphics/MediaPlayerPrivate.h b/webkit/WebCore/platform/graphics/MediaPlayerPrivate.h index 7351ec99b..2737aa797 100755 --- a/webkit/WebCore/platform/graphics/MediaPlayerPrivate.h +++ b/webkit/WebCore/platform/graphics/MediaPlayerPrivate.h @@ -281,6 +281,8 @@ class MediaPlayerPrivateInterface { #if ENABLE(AVF_CAPTIONS) virtual void notifyTrackModeChanged() { } #endif + + virtual void setShouldDisableSleep(bool) { } }; } diff --git a/webkit/WebCore/platform/graphics/SourceBufferPrivate.h b/webkit/WebCore/platform/graphics/SourceBufferPrivate.h index df977b1e2..d7044bc08 100755 --- a/webkit/WebCore/platform/graphics/SourceBufferPrivate.h +++ b/webkit/WebCore/platform/graphics/SourceBufferPrivate.h @@ -57,6 +57,7 @@ class SourceBufferPrivate : public RefCounted { virtual void append(const unsigned char* data, unsigned length) = 0; virtual void abort() = 0; + virtual void resetParserState() = 0; #if PLATFORM(WKC) virtual bool setTimestampOffset(double) = 0; virtual bool removedFromMediaSource() = 0; diff --git a/webkit/WebCore/platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.h b/webkit/WebCore/platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.h index f948c8667..592344bc6 100755 --- a/webkit/WebCore/platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.h +++ b/webkit/WebCore/platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.h @@ -29,6 +29,7 @@ #if ENABLE(MEDIA_SOURCE) && USE(AVFOUNDATION) #include "SourceBufferPrivate.h" +#include #include #include #include @@ -115,6 +116,7 @@ class SourceBufferPrivateAVFObjC final : public SourceBufferPrivate { virtual void setClient(SourceBufferPrivateClient*) override; virtual void append(const unsigned char* data, unsigned length) override; virtual void abort() override; + void resetParserState() override; virtual void removedFromMediaSource() override; virtual MediaPlayer::ReadyState readyState() const override; virtual void setReadyState(MediaPlayer::ReadyState) override; @@ -139,6 +141,7 @@ class SourceBufferPrivateAVFObjC final : public SourceBufferPrivate { Vector m_errorClients; WeakPtrFactory m_weakFactory; + WeakPtrFactory m_appendWeakFactory; RetainPtr m_parser; RetainPtr m_asset; @@ -147,6 +150,7 @@ class SourceBufferPrivateAVFObjC final : public SourceBufferPrivate { RetainPtr m_delegate; RetainPtr m_errorListener; OSObjectPtr m_hasSessionSemaphore; + OSObjectPtr m_isAppendingGroup; MediaSourcePrivateAVFObjC* m_mediaSource; SourceBufferPrivateClient* m_client; @@ -154,6 +158,7 @@ class SourceBufferPrivateAVFObjC final : public SourceBufferPrivate { FloatSize m_cachedSize; bool m_parsingSucceeded; + bool m_parserStateWasReset { false }; int m_enabledVideoTrackID; int m_protectedTrackID; }; diff --git a/webkit/WebCore/platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.mm b/webkit/WebCore/platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.mm index 71a7f49f6..ec52e932f 100755 --- a/webkit/WebCore/platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.mm +++ b/webkit/WebCore/platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.mm @@ -143,6 +143,7 @@ @interface WebAVStreamDataParserListener : NSObject { WeakPtr _parent; AVStreamDataParser* _parser; } +@property (assign) WeakPtr parent; - (id)initWithParser:(AVStreamDataParser*)parser parent:(WeakPtr)parent; @end @@ -160,6 +161,8 @@ - (id)initWithParser:(AVStreamDataParser*)parser parent:(WeakPtr strongSelf = self; RetainPtr strongAsset = asset; - callOnMainThread([strongSelf, strongAsset] { - if (strongSelf->_parent) - strongSelf->_parent->didParseStreamDataAsAsset(strongAsset.get()); + callOnMainThread([parent = _parent, protectedAsset = WTFMove(protectedAsset)] { + if (parent) + parent->didParseStreamDataAsAsset(protectedAsset.get()); }); } @@ -194,12 +196,11 @@ - (void)streamDataParser:(AVStreamDataParser *)streamDataParser didParseStreamDa UNUSED_PARAM(streamDataParser); #endif ASSERT(streamDataParser == _parser); - RetainPtr strongSelf = self; RetainPtr strongAsset = asset; - callOnMainThread([strongSelf, strongAsset] { - if (strongSelf->_parent) - strongSelf->_parent->didParseStreamDataAsAsset(strongAsset.get()); + callOnMainThread([parent = _parent, protectedAsset = WTFMove(protectedAsset)] { + if (parent) + parent->didParseStreamDataAsAsset(protectedAsset.get()); }); } @@ -209,12 +210,11 @@ - (void)streamDataParser:(AVStreamDataParser *)streamDataParser didFailToParseSt UNUSED_PARAM(streamDataParser); #endif ASSERT(streamDataParser == _parser); - RetainPtr strongSelf = self; RetainPtr strongError = error; - callOnMainThread([strongSelf, strongError] { - if (strongSelf->_parent) - strongSelf->_parent->didFailToParseStreamDataWithError(strongError.get()); + callOnMainThread([parent = _parent, protectedError = WTFMove(protectedError)] { + if (parent) + parent->didFailToParseStreamDataWithError(protectedError.get()); }); } @@ -224,13 +224,12 @@ - (void)streamDataParser:(AVStreamDataParser *)streamDataParser didProvideMediaD UNUSED_PARAM(streamDataParser); #endif ASSERT(streamDataParser == _parser); - RetainPtr strongSelf = self; RetainPtr strongSample = sample; String mediaType = nsMediaType; - callOnMainThread([strongSelf, strongSample, trackID, mediaType, flags] { - if (strongSelf->_parent) - strongSelf->_parent->didProvideMediaDataForTrackID(trackID, strongSample.get(), mediaType, flags); + callOnMainThread([parent = _parent, protectedSample = WTFMove(protectedSample), trackID, mediaType, flags] { + if (parent) + parent->didProvideMediaDataForTrackID(trackID, protectedSample.get(), mediaType, flags); }); } @@ -240,12 +239,11 @@ - (void)streamDataParser:(AVStreamDataParser *)streamDataParser didReachEndOfTra UNUSED_PARAM(streamDataParser); #endif ASSERT(streamDataParser == _parser); - RetainPtr strongSelf = self; String mediaType = nsMediaType; - callOnMainThread([strongSelf, trackID, mediaType] { - if (strongSelf->_parent) - strongSelf->_parent->didReachEndOfTrackWithTrackID(trackID, mediaType); + callOnMainThread([parent = _parent, trackID, mediaType] { + if (parent) + parent->didReachEndOfTrackWithTrackID(trackID, mediaType); }); } @@ -258,10 +256,9 @@ - (void)streamDataParserWillProvideContentKeyRequestInitializationData:(AVStream // We must call synchronously to the main thread, as the AVStreamSession must be associated // with the streamDataParser before the delegate method returns. - RetainPtr strongSelf = self; - dispatch_sync(dispatch_get_main_queue(), [strongSelf, trackID]() { - if (strongSelf->_parent) - strongSelf->_parent->willProvideContentKeyRequestInitializationDataForTrackID(trackID); + dispatch_sync(dispatch_get_main_queue(), [parent = _parent, trackID]() { + if (parent) + parent->willProvideContentKeyRequestInitializationDataForTrackID(trackID); }); } @@ -271,13 +268,12 @@ - (void)streamDataParser:(AVStreamDataParser *)streamDataParser didProvideConten UNUSED_PARAM(streamDataParser); #endif ASSERT(streamDataParser == _parser); - RetainPtr strongSelf = self; RetainPtr strongData = initData; OSObjectPtr hasSessionSemaphore = adoptOSObject(dispatch_semaphore_create(0)); - callOnMainThread([strongSelf, strongData, trackID, hasSessionSemaphore] { - if (strongSelf->_parent) - strongSelf->_parent->didProvideContentKeyRequestInitializationDataForTrackID(strongData.get(), trackID, hasSessionSemaphore); + callOnMainThread([parent = _parent, protectedInitData = RetainPtr(initData), trackID, hasSessionSemaphore] { + if (parent) + parent->didProvideContentKeyRequestInitializationDataForTrackID(protectedInitData.get(), trackID, hasSessionSemaphore); }); dispatch_semaphore_wait(hasSessionSemaphore.get(), DISPATCH_TIME_FOREVER); } @@ -572,9 +568,11 @@ static bool CMSampleBufferIsRandomAccess(CMSampleBufferRef sample) SourceBufferPrivateAVFObjC::SourceBufferPrivateAVFObjC(MediaSourcePrivateAVFObjC* parent) : m_weakFactory(this) + , m_appendWeakFactory(this) , m_parser(adoptNS([allocAVStreamDataParserInstance() init])) , m_delegate(adoptNS([[WebAVStreamDataParserListener alloc] initWithParser:m_parser.get() parent:createWeakPtr()])) , m_errorListener(adoptNS([[WebAVSampleBufferErrorListener alloc] initWithParent:this])) + , m_isAppendingGroup(adoptOSObject(dispatch_group_create())) , m_mediaSource(parent) , m_client(0) , m_parsingSucceeded(true) @@ -753,21 +751,26 @@ static dispatch_queue_t globalDataParserQueue() LOG(MediaSource, "SourceBufferPrivateAVFObjC::append(%p) - data:%p, length:%d", this, data, length); RetainPtr nsData = adoptNS([[NSData alloc] initWithBytes:data length:length]); - WeakPtr weakThis = createWeakPtr(); + WeakPtr weakThis = m_appendWeakFactory.createWeakPtr(); RetainPtr parser = m_parser; RetainPtr delegate = m_delegate; m_parsingSucceeded = true; + dispatch_group_enter(m_isAppendingGroup.get()); - dispatch_async(globalDataParserQueue(), [nsData, weakThis, parser, delegate] { - - [parser appendStreamData:nsData.get()]; + dispatch_async(globalDataParserQueue(), [nsData, weakThis, parser, delegate, isAppendingGroup = m_isAppendingGroup, parserStateWasReset = m_parserStateWasReset] { + if (parserStateWasReset) + [parser appendStreamData:nsData.get() withFlags:AVStreamDataParserStreamDataDiscontinuity]; + else + [parser appendStreamData:nsData.get()]; callOnMainThread([weakThis] { if (weakThis) weakThis->appendCompleted(); }); + dispatch_group_leave(isAppendingGroup.get()); }); + m_parserStateWasReset = false; } void SourceBufferPrivateAVFObjC::appendCompleted() @@ -781,12 +784,19 @@ static dispatch_queue_t globalDataParserQueue() void SourceBufferPrivateAVFObjC::abort() { - // The parser does not have a mechanism for resetting to a clean state, so destroy and re-create it. - // FIXME(135164): Support resetting parser to the last appended initialization segment. - destroyParser(); + // The parsing queue may be blocked waiting for the main thread to provide it a AVStreamSession. We + // were asked to abort, and that cancels all outstanding append operations. Without cancelling this + // semaphore, the m_isAppendingGroup wait operation will deadlock. + if (m_hasSessionSemaphore) + dispatch_semaphore_signal(m_hasSessionSemaphore.get()); + dispatch_group_wait(m_isAppendingGroup.get(), DISPATCH_TIME_FOREVER); + m_appendWeakFactory.revokeAll(); + m_delegate.get().parent = m_appendWeakFactory.createWeakPtr(); +} - m_parser = adoptNS([allocAVStreamDataParserInstance() init]); - m_delegate = adoptNS([[WebAVStreamDataParserListener alloc] initWithParser:m_parser.get() parent:createWeakPtr()]); +void SourceBufferPrivateAVFObjC::resetParserState() +{ + m_parserStateWasReset = true; } void SourceBufferPrivateAVFObjC::destroyParser() diff --git a/webkit/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp b/webkit/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp index d532714cc..b9c27d255 100755 --- a/webkit/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp +++ b/webkit/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp @@ -1287,32 +1287,16 @@ void GraphicsLayerCA::setVisibleAndCoverageRects(const VisibleAndCoverageRects& if (intersectsCoverageRect != m_intersectsCoverageRect) { m_uncommittedChanges |= CoverageRectChanged; m_intersectsCoverageRect = intersectsCoverageRect; - - if (GraphicsLayerCA* maskLayer = downcast(m_maskLayer)) { - maskLayer->m_uncommittedChanges |= CoverageRectChanged; - maskLayer->m_intersectsCoverageRect = intersectsCoverageRect; - } } if (visibleRectChanged) { m_uncommittedChanges |= CoverageRectChanged; m_visibleRect = rects.visibleRect; - - if (GraphicsLayerCA* maskLayer = downcast(m_maskLayer)) { - // FIXME: this assumes that the mask layer has the same geometry as this layer (which is currently always true). - maskLayer->m_uncommittedChanges |= CoverageRectChanged; - maskLayer->m_visibleRect = rects.visibleRect; - } } if (coverageRectChanged) { m_uncommittedChanges |= CoverageRectChanged; m_coverageRect = rects.coverageRect; - - if (GraphicsLayerCA* maskLayer = downcast(m_maskLayer)) { - maskLayer->m_uncommittedChanges |= CoverageRectChanged; - maskLayer->m_coverageRect = rects.coverageRect; - } } } @@ -1378,8 +1362,10 @@ void GraphicsLayerCA::recursiveCommitChanges(const CommitState& commitState, con childCommitState.ancestorIsViewportConstrained |= m_isViewportConstrained; - if (GraphicsLayerCA* maskLayer = downcast(m_maskLayer)) + if (GraphicsLayerCA* maskLayer = downcast(m_maskLayer)) { + maskLayer->setVisibleAndCoverageRects(rects, m_isViewportConstrained || commitState.ancestorIsViewportConstrained); maskLayer->commitLayerChangesBeforeSublayers(childCommitState, pageScaleFactor, baseRelativePosition); + } const Vector& childLayers = children(); size_t numChildren = childLayers.size(); @@ -2385,13 +2371,20 @@ void GraphicsLayerCA::updateMasksToBoundsRect() void GraphicsLayerCA::updateMaskLayer() { PlatformCALayer* maskCALayer = m_maskLayer ? downcast(*m_maskLayer).primaryLayer() : nullptr; - m_layer->setMask(maskCALayer); + + LayerMap* layerCloneMap; + if (m_structuralLayer) { + m_structuralLayer->setMask(maskCALayer); + layerCloneMap = m_structuralLayerClones.get(); + } else { + m_layer->setMask(maskCALayer); + layerCloneMap = m_layerClones.get(); + } LayerMap* maskLayerCloneMap = m_maskLayer ? downcast(*m_maskLayer).primaryLayerClones() : nullptr; - - if (LayerMap* layerCloneMap = m_layerClones.get()) { + if (layerCloneMap) { for (auto& clone : *layerCloneMap) { - PlatformCALayer* maskClone = maskLayerCloneMap ? maskLayerCloneMap->get(clone.key) : nullptr; + PlatformCALayer* maskClzone = maskLayerCloneMap ? maskLayerCloneMap->get(clone.key) : nullptr; clone.value->setMask(maskClone); } } diff --git a/webkit/WebCore/platform/graphics/ca/GraphicsLayerCA.h b/webkit/WebCore/platform/graphics/ca/GraphicsLayerCA.h index 1c83e06ae..8a6093439 100755 --- a/webkit/WebCore/platform/graphics/ca/GraphicsLayerCA.h +++ b/webkit/WebCore/platform/graphics/ca/GraphicsLayerCA.h @@ -573,7 +573,13 @@ class GraphicsLayerCA : public GraphicsLayer, public PlatformCALayerClient { FloatSize m_pixelAlignmentOffset; +#if PLATFORM(WIN) + // FIXME: when initializing m_uncommittedChanges to a non-zero value, nothing is painted on Windows, see https://bugs.webkit.org/show_bug.cgi?id=168666. LayerChangeFlags m_uncommittedChanges { 0 }; +#else + LayerChangeFlags m_uncommittedChanges { CoverageRectChanged }; +#endif + bool m_isCommittingChanges { false }; }; diff --git a/webkit/WebCore/platform/graphics/ca/TileGrid.cpp b/webkit/WebCore/platform/graphics/ca/TileGrid.cpp index 567b1a5a0..3ff3c7339 100755 --- a/webkit/WebCore/platform/graphics/ca/TileGrid.cpp +++ b/webkit/WebCore/platform/graphics/ca/TileGrid.cpp @@ -39,6 +39,25 @@ namespace WebCore { +#if !LOG_DISABLED +static String validationPolicyAsString(TileGrid::TileValidationPolicy validationPolicy) +{ + StringBuilder builder; + builder.appendLiteral("["); + if (validationPolicy & TileGrid::PruneSecondaryTiles) + builder.appendLiteral("prune secondary"); + + if (validationPolicy & TileGrid::UnparentAllTiles) { + if (builder.isEmpty()) + builder.appendLiteral(", "); + builder.appendLiteral("unparent all"); + } + builder.appendLiteral("]"); + + return builder.toString(); +} +#endif + TileGrid::TileGrid(TileController& controller) : m_controller(controller) , m_containerLayer(*controller.rootLayer().createCompatibleLayer(PlatformCALayer::LayerTypeLayer, nullptr)) @@ -72,8 +91,7 @@ void TileGrid::setScale(float scale) transform.scale(1 / m_scale); m_containerLayer->setTransform(transform); - // FIXME: we may revalidateTiles twice in this commit. - revalidateTiles(PruneSecondaryTiles); + m_controller.setNeedsRevalidateTiles(); for (auto& tile : m_tiles.values()) tile.layer->setContentsScale(m_controller.deviceScaleFactor()); @@ -205,6 +223,8 @@ bool TileGrid::tilesWouldChangeForCoverageRect(const FloatRect& coverageRect) co bool TileGrid::prepopulateRect(const FloatRect& rect) { + LOG_WITH_STREAM(Tiling, stream << "TileGrid " << this << " prepopulateRect: " << rect); + IntRect enclosingCoverageRect = enclosingIntRect(rect); if (m_primaryTileCoverageRect.contains(enclosingCoverageRect)) return false; @@ -306,8 +326,7 @@ void TileGrid::revalidateTiles(TileValidationPolicy validationPolicy) FloatRect coverageRect = m_controller.coverageRect(); IntRect bounds = m_controller.bounds(); - if (coverageRect.isEmpty() || bounds.isEmpty()) - return; + LOG_WITH_STREAM(Tiling, stream << "TileGrid " << this << " (controller " << &m_controller << ") revalidateTiles: bounds " << bounds << " coverageRect" << coverageRect << " validation: " << validationPolicyAsString(validationPolicy)); FloatRect scaledRect(coverageRect); scaledRect.scale(m_scale); @@ -373,19 +392,9 @@ void TileGrid::revalidateTiles(TileValidationPolicy validationPolicy) removeTilesInCohort(currCohort); } - // Ensure primary tile coverage tiles. - m_primaryTileCoverageRect = ensureTilesForRect(coverageRect, CoverageType::PrimaryTiles); - if (validationPolicy & PruneSecondaryTiles) { removeAllSecondaryTiles(); m_cohortList.clear(); - } else { - for (auto& secondaryCoverageRect : m_secondaryTileCoverageRects) { - FloatRect secondaryRectInLayerCoordinates(secondaryCoverageRect); - secondaryRectInLayerCoordinates.scale(1 / m_scale); - ensureTilesForRect(secondaryRectInLayerCoordinates, CoverageType::SecondaryTiles); - } - m_secondaryTileCoverageRects.clear(); } if (m_controller.unparentsOffscreenTiles() && (validationPolicy & UnparentAllTiles)) { @@ -432,6 +441,19 @@ void TileGrid::revalidateTiles(TileValidationPolicy validationPolicy) removeTiles(tilesToRemove); } + // Ensure primary tile coverage tiles. + m_primaryTileCoverageRect = ensureTilesForRect(coverageRect, CoverageType::PrimaryTiles); + + // Ensure secondary tiles (requested via prepopulateRect). + if (!(validationPolicy & PruneSecondaryTiles)) { + for (auto& secondaryCoverageRect : m_secondaryTileCoverageRects) { + FloatRect secondaryRectInLayerCoordinates(secondaryCoverageRect); + secondaryRectInLayerCoordinates.scale(1 / m_scale); + ensureTilesForRect(secondaryRectInLayerCoordinates, CoverageType::SecondaryTiles); + } + m_secondaryTileCoverageRects.clear(); + } + m_controller.didRevalidateTiles(); } @@ -498,6 +520,8 @@ IntRect TileGrid::ensureTilesForRect(const FloatRect& rect, CoverageType newTile if (m_controller.unparentsOffscreenTiles() && !m_controller.isInWindow()) return IntRect(); + LOG_WITH_STREAM(Tiling, stream << "TileGrid " << this << " ensureTilesForRect: " << rect); + FloatRect scaledRect(rect); scaledRect.scale(m_scale); IntRect rectInTileCoords(enclosingIntRect(scaledRect)); diff --git a/webkit/WebCore/platform/graphics/cairo/PlatformContextCairo.cpp b/webkit/WebCore/platform/graphics/cairo/PlatformContextCairo.cpp index e1447c7b8..2897e6ce8 100755 --- a/webkit/WebCore/platform/graphics/cairo/PlatformContextCairo.cpp +++ b/webkit/WebCore/platform/graphics/cairo/PlatformContextCairo.cpp @@ -147,9 +147,11 @@ void PlatformContextCairo::pushImageMask(cairo_surface_t* surface, const FloatRe cairo_push_group(m_cr.get()); cairo_set_operator(m_cr.get(), CAIRO_OPERATOR_SOURCE); +#if !PLATFORM(WKC) // The code below results in incorrect compositing with the surface. cairo_set_source_surface(m_cr.get(), currentTarget, 0, 0); cairo_rectangle(m_cr.get(), rect.x(), rect.y(), rect.width(), rect.height()); cairo_fill(m_cr.get()); +#endif } static void drawPatternToCairoContext(cairo_t* cr, cairo_pattern_t* pattern, const FloatRect& destRect, float alpha) diff --git a/webkit/WebCore/platform/graphics/filters/FEColorMatrix.cpp b/webkit/WebCore/platform/graphics/filters/FEColorMatrix.cpp index 363bb38ff..152822647 100755 --- a/webkit/WebCore/platform/graphics/filters/FEColorMatrix.cpp +++ b/webkit/WebCore/platform/graphics/filters/FEColorMatrix.cpp @@ -151,21 +151,22 @@ void FEColorMatrix::platformApplySoftware() IntRect imageRect(IntPoint(), resultImage->logicalSize()); RefPtr pixelArray = resultImage->getUnmultipliedImageData(imageRect); + Vector values = normalizedFloats(m_values); switch (m_type) { case FECOLORMATRIX_TYPE_UNKNOWN: break; case FECOLORMATRIX_TYPE_MATRIX: - effectType(pixelArray.get(), m_values); + effectType(pixelArray.get(), values); break; case FECOLORMATRIX_TYPE_SATURATE: - effectType(pixelArray.get(), m_values); + effectType(pixelArray.get(), values); break; case FECOLORMATRIX_TYPE_HUEROTATE: - effectType(pixelArray.get(), m_values); + effectType(pixelArray.get(), values); break; case FECOLORMATRIX_TYPE_LUMINANCETOALPHA: - effectType(pixelArray.get(), m_values); + effectType(pixelArray.get(), values); setIsAlphaImage(true); break; } diff --git a/webkit/WebCore/platform/graphics/filters/FEConvolveMatrix.cpp b/webkit/WebCore/platform/graphics/filters/FEConvolveMatrix.cpp index dc7f9aa7a..873d1c001 100755 --- a/webkit/WebCore/platform/graphics/filters/FEConvolveMatrix.cpp +++ b/webkit/WebCore/platform/graphics/filters/FEConvolveMatrix.cpp @@ -266,7 +266,7 @@ ALWAYS_INLINE void FEConvolveMatrix::fastSetInteriorPixels(PaintingData& paintin for (int y = yEnd + 1; y > yStart; --y) { for (int x = clipRight + 1; x > 0; --x) { - int kernelValue = m_kernelMatrix.size() - 1; + int kernelValue = paintingData.kernelMatrix.size() - 1; int kernelPixel = startKernelPixel; int width = m_kernelSize.width(); @@ -277,11 +277,11 @@ ALWAYS_INLINE void FEConvolveMatrix::fastSetInteriorPixels(PaintingData& paintin totals[3] = 0; while (kernelValue >= 0) { - totals[0] += m_kernelMatrix[kernelValue] * static_cast(paintingData.srcPixelArray->item(kernelPixel++)); - totals[1] += m_kernelMatrix[kernelValue] * static_cast(paintingData.srcPixelArray->item(kernelPixel++)); - totals[2] += m_kernelMatrix[kernelValue] * static_cast(paintingData.srcPixelArray->item(kernelPixel++)); + totals[0] += paintingData.kernelMatrix[kernelValue] * static_cast(paintingData.srcPixelArray->item(kernelPixel++)); + totals[1] += paintingData.kernelMatrix[kernelValue] * static_cast(paintingData.srcPixelArray->item(kernelPixel++)); + totals[2] += paintingData.kernelMatrix[kernelValue] * static_cast(paintingData.srcPixelArray->item(kernelPixel++)); if (!preserveAlphaValues) - totals[3] += m_kernelMatrix[kernelValue] * static_cast(paintingData.srcPixelArray->item(kernelPixel)); + totals[3] += paintingData.kernelMatrix[kernelValue] * static_cast(paintingData.srcPixelArray->item(kernelPixel)); ++kernelPixel; --kernelValue; if (!--width) { @@ -346,7 +346,7 @@ void FEConvolveMatrix::fastSetOuterPixels(PaintingData& paintingData, int x1, in for (int y = height; y > 0; --y) { for (int x = width; x > 0; --x) { - int kernelValue = m_kernelMatrix.size() - 1; + int kernelValue = paintingData.kernelMatrix.size() - 1; int kernelPixelX = startKernelPixelX; int kernelPixelY = startKernelPixelY; int width = m_kernelSize.width(); @@ -360,12 +360,12 @@ void FEConvolveMatrix::fastSetOuterPixels(PaintingData& paintingData, int x1, in while (kernelValue >= 0) { int pixelIndex = getPixelValue(paintingData, kernelPixelX, kernelPixelY); if (pixelIndex >= 0) { - totals[0] += m_kernelMatrix[kernelValue] * static_cast(paintingData.srcPixelArray->item(pixelIndex)); - totals[1] += m_kernelMatrix[kernelValue] * static_cast(paintingData.srcPixelArray->item(pixelIndex + 1)); - totals[2] += m_kernelMatrix[kernelValue] * static_cast(paintingData.srcPixelArray->item(pixelIndex + 2)); + totals[0] += paintingData.kernelMatrix[kernelValue] * static_cast(paintingData.srcPixelArray->item(pixelIndex)); + totals[1] += paintingData.kernelMatrix[kernelValue] * static_cast(paintingData.srcPixelArray->item(pixelIndex + 1)); + totals[2] += paintingData.kernelMatrix[kernelValue] * static_cast(paintingData.srcPixelArray->item(pixelIndex + 2)); } if (!preserveAlphaValues && pixelIndex >= 0) - totals[3] += m_kernelMatrix[kernelValue] * static_cast(paintingData.srcPixelArray->item(pixelIndex + 3)); + totals[3] += paintingData.kernelMatrix[kernelValue] * static_cast(paintingData.srcPixelArray->item(pixelIndex + 3)); ++kernelPixelX; --kernelValue; if (!--width) { @@ -440,6 +440,7 @@ void FEConvolveMatrix::platformApplySoftware() paintingData.width = paintSize.width(); paintingData.height = paintSize.height(); paintingData.bias = m_bias * 255; + paintingData.kernelMatrix = normalizedFloats(m_kernelMatrix); // Drawing fully covered pixels int clipRight = paintSize.width() - m_kernelSize.width(); diff --git a/webkit/WebCore/platform/graphics/filters/FEConvolveMatrix.h b/webkit/WebCore/platform/graphics/filters/FEConvolveMatrix.h index dcc9a6e02..5cc82d064 100755 --- a/webkit/WebCore/platform/graphics/filters/FEConvolveMatrix.h +++ b/webkit/WebCore/platform/graphics/filters/FEConvolveMatrix.h @@ -83,6 +83,7 @@ class FEConvolveMatrix : public FilterEffect { int width; int height; float bias; + Vector kernelMatrix; }; FEConvolveMatrix(Filter&, const IntSize&, float, float, diff --git a/webkit/WebCore/platform/graphics/filters/FilterEffect.h b/webkit/WebCore/platform/graphics/filters/FilterEffect.h index 4eedc9d6a..223dce695 100755 --- a/webkit/WebCore/platform/graphics/filters/FilterEffect.h +++ b/webkit/WebCore/platform/graphics/filters/FilterEffect.h @@ -29,6 +29,7 @@ #include #include +#include #include #include #include @@ -178,6 +179,14 @@ class FilterEffect : public RefCounted { void forceValidPreMultipliedPixels(); void clipAbsolutePaintRect(); + + static Vector normalizedFloats(const Vector& values) + { + Vector normalizedValues(values.size()); + for (size_t i = 0; i < values.size(); ++i) + normalizedValues[i] = normalizedFloat(values[i]); + return normalizedValues; + } private: std::unique_ptr m_imageBufferResult; diff --git a/webkit/WebCore/platform/graphics/gstreamer/SourceBufferPrivateGStreamer.cpp b/webkit/WebCore/platform/graphics/gstreamer/SourceBufferPrivateGStreamer.cpp index 02628cf4b..b662c22d2 100755 --- a/webkit/WebCore/platform/graphics/gstreamer/SourceBufferPrivateGStreamer.cpp +++ b/webkit/WebCore/platform/graphics/gstreamer/SourceBufferPrivateGStreamer.cpp @@ -70,6 +70,11 @@ void SourceBufferPrivateGStreamer::abort() notImplemented(); } +void SourceBufferPrivateGStreamer::resetParserState() +{ + notImplemented(); +} + void SourceBufferPrivateGStreamer::removedFromMediaSource() { m_client->removedFromMediaSource(this); diff --git a/webkit/WebCore/platform/graphics/gstreamer/SourceBufferPrivateGStreamer.h b/webkit/WebCore/platform/graphics/gstreamer/SourceBufferPrivateGStreamer.h index 095a0e236..f7651ed33 100755 --- a/webkit/WebCore/platform/graphics/gstreamer/SourceBufferPrivateGStreamer.h +++ b/webkit/WebCore/platform/graphics/gstreamer/SourceBufferPrivateGStreamer.h @@ -50,6 +50,7 @@ class SourceBufferPrivateGStreamer final : public SourceBufferPrivate { virtual void append(const unsigned char* data, unsigned length); virtual void abort(); + virtual void resetParserState(); virtual void removedFromMediaSource(); virtual MediaPlayer::ReadyState readyState() const; diff --git a/webkit/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm b/webkit/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm index 544ebf68b..55cd0d2f8 100755 --- a/webkit/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm +++ b/webkit/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm @@ -82,7 +82,7 @@ }; #if !PLATFORM(IOS) -static void setPixelFormat(Vector& attribs, int colorBits, int depthBits, bool accelerated, bool supersample, bool closest, bool antialias) +static void setPixelFormat(Vector& attribs, int colorBits, int depthBits, bool accelerated, bool supersample, bool closest, bool antialias, bool allowOffline, bool useGLES3) { attribs.clear(); @@ -111,6 +111,13 @@ static void setPixelFormat(Vector& attribs, int colorBi attribs.append(kCGLPFASamples); attribs.append(static_cast(4)); } + + if (useGLES3) { + // FIXME: Instead of backing a WebGL2 GraphicsContext3D with a OpenGL 3.2 context, we should instead back it with ANGLE. + // Use an OpenGL 3.2 context for now until the ANGLE backend is ready. + attribs.append(kCGLPFAOpenGLProfile); + attribs.append(static_cast(kCGLOGLPVersion_3_2_Core)); + } attribs.append(static_cast(0)); } @@ -182,19 +189,19 @@ static void setPixelFormat(Vector& attribs, int colorBi bool useMultisampling = m_attrs.antialias; - setPixelFormat(attribs, 32, 32, !attrs.forceSoftwareRenderer, true, false, useMultisampling); + setPixelFormat(attribs, 32, 32, !attrs.forceSoftwareRenderer, true, false, useMultisampling, attrs.preferLowPowerToHighPerformance, attrs.useGLES3); CGLChoosePixelFormat(attribs.data(), &pixelFormatObj, &numPixelFormats); if (numPixelFormats == 0) { - setPixelFormat(attribs, 32, 32, !attrs.forceSoftwareRenderer, false, false, useMultisampling); + setPixelFormat(attribs, 32, 32, !attrs.forceSoftwareRenderer, false, false, useMultisampling, attrs.preferLowPowerToHighPerformance, attrs.useGLES3); CGLChoosePixelFormat(attribs.data(), &pixelFormatObj, &numPixelFormats); if (numPixelFormats == 0) { - setPixelFormat(attribs, 32, 16, !attrs.forceSoftwareRenderer, false, false, useMultisampling); + setPixelFormat(attribs, 32, 16, !attrs.forceSoftwareRenderer, false, false, useMultisampling, attrs.preferLowPowerToHighPerformance, attrs.useGLES3); CGLChoosePixelFormat(attribs.data(), &pixelFormatObj, &numPixelFormats); if (!attrs.forceSoftwareRenderer && numPixelFormats == 0) { - setPixelFormat(attribs, 32, 16, false, false, true, false); + setPixelFormat(attribs, 32, 16, false, false, true, false, false, attrs.useGLES3); CGLChoosePixelFormat(attribs.data(), &pixelFormatObj, &numPixelFormats); useMultisampling = false; } @@ -222,6 +229,8 @@ static void setPixelFormat(Vector& attribs, int colorBi return; } + m_isForWebGL2 = attrs.useGLES3; + // Set the current context to the one given to us. CGLSetCurrentContext(m_contextObj); @@ -251,16 +260,16 @@ static void setPixelFormat(Vector& attribs, int colorBi // create a texture to render into ::glGenTextures(1, &m_texture); ::glBindTexture(GL_TEXTURE_2D, m_texture); - ::glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - ::glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - ::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); - ::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); + ::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + ::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + ::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + ::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); ::glGenTextures(1, &m_compositorTexture); ::glBindTexture(GL_TEXTURE_2D, m_compositorTexture); - ::glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - ::glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - ::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); - ::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); + ::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + ::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + ::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + ::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); ::glBindTexture(GL_TEXTURE_2D, 0); #endif @@ -306,7 +315,8 @@ static void setPixelFormat(Vector& attribs, int colorBi #if !PLATFORM(IOS) ::glEnable(GL_VERTEX_PROGRAM_POINT_SIZE); - ::glEnable(GL_POINT_SPRITE); + if (!isGLES2Compliant()) + ::glEnable(GL_POINT_SPRITE); #endif ::glClearColor(0, 0, 0, 0); @@ -413,7 +423,7 @@ static void setPixelFormat(Vector& attribs, int colorBi bool GraphicsContext3D::isGLES2Compliant() const { - return false; + return m_isForWebGL2; } void GraphicsContext3D::setContextLostCallback(std::unique_ptr) diff --git a/webkit/WebCore/platform/graphics/opengl/Extensions3DOpenGL.cpp b/webkit/WebCore/platform/graphics/opengl/Extensions3DOpenGL.cpp index e754e9813..9872b55e8 100755 --- a/webkit/WebCore/platform/graphics/opengl/Extensions3DOpenGL.cpp +++ b/webkit/WebCore/platform/graphics/opengl/Extensions3DOpenGL.cpp @@ -46,8 +46,8 @@ namespace WebCore { -Extensions3DOpenGL::Extensions3DOpenGL(GraphicsContext3D* context) - : Extensions3DOpenGLCommon(context) +Extensions3DOpenGL::Extensions3DOpenGL(GraphicsContext3D* context, bool useIndexedGetString) + : Extensions3DOpenGLCommon(context, useIndexedGetString) { } @@ -299,6 +299,7 @@ void Extensions3DOpenGL::vertexAttribDivisor(GC3Duint index, GC3Duint divisor) String Extensions3DOpenGL::getExtensions() { + ASSERT(!m_useIndexedGetString); return String(reinterpret_cast(::glGetString(GL_EXTENSIONS))); } diff --git a/webkit/WebCore/platform/graphics/opengl/Extensions3DOpenGL.h b/webkit/WebCore/platform/graphics/opengl/Extensions3DOpenGL.h index 873c18597..7d7221ad2 100755 --- a/webkit/WebCore/platform/graphics/opengl/Extensions3DOpenGL.h +++ b/webkit/WebCore/platform/graphics/opengl/Extensions3DOpenGL.h @@ -23,8 +23,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef Extensions3DOpenGL_h -#define Extensions3DOpenGL_h +#pragma once #include "Extensions3DOpenGLCommon.h" @@ -38,7 +37,7 @@ class Extensions3DOpenGL : public Extensions3DOpenGLCommon { WTF_MAKE_FAST_ALLOCATED; public: // This class only needs to be instantiated by GraphicsContext3D implementations. - explicit Extensions3DOpenGL(GraphicsContext3D*); + explicit Extensions3DOpenGL(GraphicsContext3D*, bool useIndexedGetString); virtual ~Extensions3DOpenGL(); // Extensions3D methods. @@ -61,12 +60,11 @@ class Extensions3DOpenGL : public Extensions3DOpenGLCommon { protected: virtual bool supportsExtension(const WTF::String&); virtual String getExtensions(); -#if (PLATFORM(GTK) || PLATFORM(EFL) || PLATFORM(WIN) || PLATFORM(IOS)) + private: +#if (PLATFORM(GTK) || PLATFORM(EFL) || PLATFORM(WIN) || PLATFORM(IOS)) bool isVertexArrayObjectSupported(); #endif }; } // namespace WebCore - -#endif // Extensions3DOpenGL_h diff --git a/webkit/WebCore/platform/graphics/opengl/Extensions3DOpenGLCommon.cpp b/webkit/WebCore/platform/graphics/opengl/Extensions3DOpenGLCommon.cpp index cef2e1c8e..87ad7d39a 100755 --- a/webkit/WebCore/platform/graphics/opengl/Extensions3DOpenGLCommon.cpp +++ b/webkit/WebCore/platform/graphics/opengl/Extensions3DOpenGLCommon.cpp @@ -34,13 +34,17 @@ #if PLATFORM(IOS) #include +#include #else #if USE(OPENGL_ES_2) #include "OpenGLESShims.h" #include #include #elif PLATFORM(MAC) +#define GL_DO_NOT_WARN_IF_MULTI_GL_VERSION_HEADERS_INCLUDED #include +#include +#undef GL_DO_NOT_WARN_IF_MULTI_GL_VERSION_HEADERS_INCLUDED #elif PLATFORM(GTK) || PLATFORM(EFL) || PLATFORM(WIN) #include "OpenGLShims.h" #endif @@ -51,7 +55,7 @@ namespace WebCore { -Extensions3DOpenGLCommon::Extensions3DOpenGLCommon(GraphicsContext3D* context) +Extensions3DOpenGLCommon::Extensions3DOpenGLCommon(GraphicsContext3D* context, bool useIndexedGetString) : m_initializedAvailableExtensions(false) , m_context(context) , m_isNVIDIA(false) @@ -61,6 +65,7 @@ Extensions3DOpenGLCommon::Extensions3DOpenGLCommon(GraphicsContext3D* context) , m_maySupportMultisampling(true) , m_requiresBuiltInFunctionEmulation(false) , m_requiresRestrictedMaximumTextureSize(false) + , m_useIndexedGetString(useIndexedGetString) { m_vendor = String(reinterpret_cast(::glGetString(GL_VENDOR))); m_renderer = String(reinterpret_cast(::glGetString(GL_RENDERER))); @@ -210,11 +215,21 @@ String Extensions3DOpenGLCommon::getTranslatedShaderSourceANGLE(Platform3DObject void Extensions3DOpenGLCommon::initializeAvailableExtensions() { - String extensionsString = getExtensions(); - Vector availableExtensions; - extensionsString.split(' ', availableExtensions); - for (size_t i = 0; i < availableExtensions.size(); ++i) - m_availableExtensions.add(availableExtensions[i]); +#if PLATFORM(MAC) + if (m_useIndexedGetString) { + GLint numExtensions = 0; + ::glGetIntegerv(GL_NUM_EXTENSIONS, &numExtensions); + for (GLint i = 0; i < numExtensions; ++i) + m_availableExtensions.add(glGetStringi(GL_EXTENSIONS, i)); + } else +#endif + { + String extensionsString = getExtensions(); + Vector availableExtensions; + extensionsString.split(' ', availableExtensions); + for (size_t i = 0; i < availableExtensions.size(); ++i) + m_availableExtensions.add(availableExtensions[i]); + } m_initializedAvailableExtensions = true; } diff --git a/webkit/WebCore/platform/graphics/opengl/Extensions3DOpenGLCommon.h b/webkit/WebCore/platform/graphics/opengl/Extensions3DOpenGLCommon.h index 5047a80f6..b73e979b7 100755 --- a/webkit/WebCore/platform/graphics/opengl/Extensions3DOpenGLCommon.h +++ b/webkit/WebCore/platform/graphics/opengl/Extensions3DOpenGLCommon.h @@ -24,8 +24,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef Extensions3DOpenGLCommon_h -#define Extensions3DOpenGLCommon_h +#pragma once #include "Extensions3D.h" @@ -71,7 +70,7 @@ class Extensions3DOpenGLCommon : public Extensions3D { protected: friend class Extensions3DOpenGLES; - Extensions3DOpenGLCommon(GraphicsContext3D*); + Extensions3DOpenGLCommon(GraphicsContext3D*, bool useIndexedGetString); virtual bool supportsExtension(const String&) = 0; virtual String getExtensions() = 0; @@ -91,10 +90,10 @@ class Extensions3DOpenGLCommon : public Extensions3D { bool m_requiresBuiltInFunctionEmulation; bool m_requiresRestrictedMaximumTextureSize; + bool m_useIndexedGetString { false }; + String m_vendor; String m_renderer; }; } // namespace WebCore - -#endif // Extensions3DOpenGLCommon_h diff --git a/webkit/WebCore/platform/graphics/opengl/Extensions3DOpenGLES.cpp b/webkit/WebCore/platform/graphics/opengl/Extensions3DOpenGLES.cpp index 5f945501e..a79544371 100755 --- a/webkit/WebCore/platform/graphics/opengl/Extensions3DOpenGLES.cpp +++ b/webkit/WebCore/platform/graphics/opengl/Extensions3DOpenGLES.cpp @@ -38,8 +38,8 @@ namespace WebCore { -Extensions3DOpenGLES::Extensions3DOpenGLES(GraphicsContext3D* context) - : Extensions3DOpenGLCommon(context) +Extensions3DOpenGLES::Extensions3DOpenGLES(GraphicsContext3D* context, bool useIndexedGetString) + : Extensions3DOpenGLCommon(context, useIndexedGetString) , m_contextResetStatus(GL_NO_ERROR) , m_supportsOESvertexArrayObject(false) , m_supportsIMGMultisampledRenderToTexture(false) diff --git a/webkit/WebCore/platform/graphics/opengl/Extensions3DOpenGLES.h b/webkit/WebCore/platform/graphics/opengl/Extensions3DOpenGLES.h index 97c431cf9..f8a0f12c8 100755 --- a/webkit/WebCore/platform/graphics/opengl/Extensions3DOpenGLES.h +++ b/webkit/WebCore/platform/graphics/opengl/Extensions3DOpenGLES.h @@ -24,8 +24,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef Extensions3DOpenGLES_h -#define Extensions3DOpenGLES_h +#pragma once #include "Extensions3DOpenGLCommon.h" @@ -64,7 +63,7 @@ namespace WebCore { class Extensions3DOpenGLES : public Extensions3DOpenGLCommon { public: // This class only needs to be instantiated by GraphicsContext3D implementations. - explicit Extensions3DOpenGLES(GraphicsContext3D*); + explicit Extensions3DOpenGLES(GraphicsContext3D*, bool useIndexedGetString); virtual ~Extensions3DOpenGLES(); virtual void framebufferTexture2DMultisampleIMG(unsigned long target, unsigned long attachment, unsigned long textarget, unsigned int texture, int level, unsigned long samples); @@ -126,5 +125,3 @@ class Extensions3DOpenGLES : public Extensions3DOpenGLCommon { } // namespace WebCore #endif // USE(OPENGL_ES_2) - -#endif // Extensions3DOpenGLES_h diff --git a/webkit/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGL.cpp b/webkit/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGL.cpp index 05b9c95d2..07b4ff23e 100755 --- a/webkit/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGL.cpp +++ b/webkit/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGL.cpp @@ -54,7 +54,10 @@ #define GL_RGBA32F_ARB 0x8814 #define GL_RGB32F_ARB 0x8815 #elif PLATFORM(MAC) +#define GL_DO_NOT_WARN_IF_MULTI_GL_VERSION_HEADERS_INCLUDED #include +#include +#undef GL_DO_NOT_WARN_IF_MULTI_GL_VERSION_HEADERS_INCLUDED #elif PLATFORM(GTK) || PLATFORM(EFL) || PLATFORM(WIN) #include "OpenGLShims.h" #endif @@ -265,8 +268,17 @@ void GraphicsContext3D::getIntegerv(GC3Denum pname, GC3Dint* value) *value /= 4; break; case MAX_VARYING_VECTORS: - ::glGetIntegerv(GL_MAX_VARYING_FLOATS, value); - *value /= 4; + if (isGLES2Compliant()) { + ASSERT(::glGetError() == GL_NO_ERROR); + ::glGetIntegerv(GL_MAX_VARYING_VECTORS, value); + if (::glGetError() == GL_INVALID_ENUM) { + ::glGetIntegerv(GL_MAX_VARYING_COMPONENTS, value); + *value /= 4; + } + } else { + ::glGetIntegerv(GL_MAX_VARYING_FLOATS, value); + *value /= 4; + } break; #endif case MAX_TEXTURE_SIZE: @@ -377,7 +389,7 @@ void GraphicsContext3D::clearDepth(GC3Dclampf depth) Extensions3D* GraphicsContext3D::getExtensions() { if (!m_extensions) - m_extensions = std::make_unique(this); + m_extensions = std::make_unique(this, isGLES2Compliant()); return m_extensions.get(); } diff --git a/webkit/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGLES.cpp b/webkit/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGLES.cpp index 0c9577639..9b1a30f81 100755 --- a/webkit/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGLES.cpp +++ b/webkit/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGLES.cpp @@ -238,7 +238,7 @@ void GraphicsContext3D::clearDepth(GC3Dclampf depth) Extensions3D* GraphicsContext3D::getExtensions() { if (!m_extensions) - m_extensions = std::make_unique(this); + m_extensions = std::make_unique(this, isGLES2Compliant()); return m_extensions.get(); } diff --git a/webkit/WebCore/platform/graphics/transforms/TransformationMatrix.cpp b/webkit/WebCore/platform/graphics/transforms/TransformationMatrix.cpp index 05b038870..d94fb3a07 100755 --- a/webkit/WebCore/platform/graphics/transforms/TransformationMatrix.cpp +++ b/webkit/WebCore/platform/graphics/transforms/TransformationMatrix.cpp @@ -1500,8 +1500,11 @@ void TransformationMatrix::blend2(const TransformationMatrix& from, double progr { Decomposed2Type fromDecomp; Decomposed2Type toDecomp; - from.decompose2(fromDecomp); - decompose2(toDecomp); + if (!from.decompose2(fromDecomp) || !decompose2(toDecomp)) { + if (progress < 0.5) + *this = from; + return; + } // If x-axis of one is flipped, and y-axis of the other, convert to an unflipped rotation. if ((fromDecomp.scaleX < 0 && toDecomp.scaleY < 0) || (fromDecomp.scaleY < 0 && toDecomp.scaleX < 0)) { @@ -1540,8 +1543,11 @@ void TransformationMatrix::blend4(const TransformationMatrix& from, double progr { Decomposed4Type fromDecomp; Decomposed4Type toDecomp; - from.decompose4(fromDecomp); - decompose4(toDecomp); + if (!from.decompose4(fromDecomp) || !decompose4(toDecomp)) { + if (progress < 0.5) + *this = from; + return; + } blendFloat(fromDecomp.scaleX, toDecomp.scaleX, progress); blendFloat(fromDecomp.scaleY, toDecomp.scaleY, progress); diff --git a/webkit/WebCore/platform/graphics/transforms/TransformationMatrix.h b/webkit/WebCore/platform/graphics/transforms/TransformationMatrix.h index 87253d850..c36242e8f 100755 --- a/webkit/WebCore/platform/graphics/transforms/TransformationMatrix.h +++ b/webkit/WebCore/platform/graphics/transforms/TransformationMatrix.h @@ -303,7 +303,7 @@ class TransformationMatrix { bool decompose4(Decomposed4Type&) const; void recompose4(const Decomposed4Type&); - void blend(const TransformationMatrix& from, double progress); + WEBCORE_EXPORT void blend(const TransformationMatrix& from, double progress); void blend2(const TransformationMatrix& from, double progress); void blend4(const TransformationMatrix& from, double progress); diff --git a/webkit/WebCore/platform/image-decoders/ImageDecoder.cpp b/webkit/WebCore/platform/image-decoders/ImageDecoder.cpp index 4897c7a10..0a82fd104 100755 --- a/webkit/WebCore/platform/image-decoders/ImageDecoder.cpp +++ b/webkit/WebCore/platform/image-decoders/ImageDecoder.cpp @@ -133,6 +133,10 @@ ImageFrame::ImageFrame() , m_duration(0) , m_disposalMethod(DisposeNotSpecified) , m_premultiplyAlpha(true) +#if ENABLE(WKC_BLINK_AWEBP) + , m_alphaBlendSource(BlendAtopPreviousFrame) + , m_requiredPreviousFrameIndex(-1) +#endif { } diff --git a/webkit/WebCore/platform/image-decoders/ImageDecoder.h b/webkit/WebCore/platform/image-decoders/ImageDecoder.h index eb29c0f9b..6a368e447 100755 --- a/webkit/WebCore/platform/image-decoders/ImageDecoder.h +++ b/webkit/WebCore/platform/image-decoders/ImageDecoder.h @@ -45,7 +45,8 @@ #include #include #endif -#elif PLATFORM(WKC) +#endif +#if PLATFORM(WKC) #include "ImageWKC.h" #endif @@ -69,6 +70,25 @@ namespace WebCore { DisposeOverwritePrevious // Clear frame to previous framebuffer // contents }; +#if ENABLE(WKC_BLINK_AWEBP) + // Indicates how non-opaque pixels in the current frame rectangle + // are blended with those in the previous frame. + // Notes: + // * GIF always uses 'BlendAtopPreviousFrame'. + // * WebP also uses the 'BlendAtopBgcolor' option. This is useful for + // cases where one wants to transform a few opaque pixels of the + // previous frame into non-opaque pixels in the current frame. + enum AlphaBlendSource { + // Blend non-opaque pixels atop the corresponding pixels in the + // initial buffer state (i.e. any previous frame buffer after having + // been properly disposed). + BlendAtopPreviousFrame, + + // Blend non-opaque pixels against fully transparent (i.e. simply + // overwrite the corresponding pixels). + BlendAtopBgcolor, + }; +#endif typedef unsigned PixelData; ImageFrame(); @@ -126,6 +146,10 @@ namespace WebCore { unsigned duration() const { return m_duration; } FrameDisposalMethod disposalMethod() const { return m_disposalMethod; } bool premultiplyAlpha() const { return m_premultiplyAlpha; } +#if ENABLE(WKC_BLINK_AWEBP) + AlphaBlendSource alphaBlendSource() const { return m_alphaBlendSource; } + size_t requiredPreviousFrameIndex() const { return m_requiredPreviousFrameIndex; } +#endif void setHasAlpha(bool alpha); void setColorProfile(const ColorProfile&); @@ -134,6 +158,10 @@ namespace WebCore { void setDuration(unsigned duration) { m_duration = duration; } void setDisposalMethod(FrameDisposalMethod method) { m_disposalMethod = method; } void setPremultiplyAlpha(bool premultiplyAlpha) { m_premultiplyAlpha = premultiplyAlpha; } +#if ENABLE(WKC_BLINK_AWEBP) + void setAlphaBlendSource(AlphaBlendSource alphaBlendSource) { m_alphaBlendSource = alphaBlendSource; } + void setRequiredPreviousFrameIndex(size_t previousFrameIndex) { m_requiredPreviousFrameIndex = previousFrameIndex; } +#endif #if PLATFORM(WKC) void setAllowReduceColor(bool flag); @@ -271,6 +299,16 @@ namespace WebCore { unsigned m_duration; FrameDisposalMethod m_disposalMethod; bool m_premultiplyAlpha; + +#if ENABLE(WKC_BLINK_AWEBP) + AlphaBlendSource m_alphaBlendSource; + // The frame that must be decoded before this frame can be decoded. + // -1 if this frame doesn't require any previous frame. + // This is used by ImageDecoder::clearCacheExceptFrame(), and will never + // be read for image formats that do not have multiple frames. + size_t m_requiredPreviousFrameIndex; +#endif + #if PLATFORM(WKC) ImageWKC* m_image; #endif diff --git a/webkit/WebCore/platform/image-decoders/webp/WEBPImageDecoder.cpp b/webkit/WebCore/platform/image-decoders/webp/WEBPImageDecoder.cpp index c0bcf1e2e..42359d940 100755 --- a/webkit/WebCore/platform/image-decoders/webp/WEBPImageDecoder.cpp +++ b/webkit/WebCore/platform/image-decoders/webp/WEBPImageDecoder.cpp @@ -33,11 +33,16 @@ #ifdef QCMS_WEBP_COLOR_CORRECTION #include +#endif + +#if !ENABLE(WKC_BLINK_AWEBP) +#ifdef QCMS_WEBP_COLOR_CORRECTION #include #else #undef ICCP_FLAG #define ICCP_FLAG 0 #endif +#endif // Backward emulation for earlier versions than 0.1.99. #if (WEBP_DECODER_ABI_VERSION < 0x0163) @@ -51,20 +56,166 @@ inline WEBP_CSP_MODE outputMode(bool hasAlpha) { return hasAlpha ? MODE_rgbA : M inline WEBP_CSP_MODE outputMode(bool hasAlpha) { return hasAlpha ? MODE_bgrA : MODE_BGRA; } #endif +#if ENABLE(WKC_BLINK_AWEBP) +#if CPU(BIG_ENDIAN) || CPU(MIDDLE_ENDIAN) +# define R_SHIFT 0 +# define G_SHIFT 8 +# define B_SHIFT 16 +# define A_SHIFT 24 +#else +# define A_SHIFT 24 +# define R_SHIFT 16 +# define G_SHIFT 8 +# define B_SHIFT 0 +#endif +#endif + namespace WebCore { +#if ENABLE(WKC_BLINK_AWEBP) + +static inline unsigned getAFromColor(uint32_t color) { + return (uint32_t)(color << (24 - A_SHIFT)) >> 24; +} + +static inline unsigned getRFromColor(uint32_t color) { + return (uint32_t)(color << (24 - R_SHIFT)) >> 24; +} + +static inline unsigned getGFromColor(uint32_t color) { + return (uint32_t)(color << (24 - G_SHIFT)) >> 24; +} + +static inline unsigned getBFromColor(uint32_t color) { + return (uint32_t)(color << (24 - B_SHIFT)) >> 24; +} + +static inline unsigned calcAlpha255To256(unsigned alpha) { + return alpha + 1; +} + +static inline uint32_t packARGB(unsigned a, unsigned r, unsigned g, unsigned b) { + return (a << A_SHIFT) | (r << R_SHIFT) | (g << G_SHIFT) | (b << B_SHIFT); +} + +static inline uint32_t alphaMulQ(uint32_t c, unsigned scale) { + uint32_t mask = 0xFF00FF; + + uint32_t rb = ((c & mask) * scale) >> 8; + uint32_t ag = ((c >> 8) & mask) * scale; + return (rb & mask) | (ag & ~mask); +} + +static inline uint32_t blendSrcOverDstPremultiplied(uint32_t src, uint32_t dst) { + return src + alphaMulQ(dst, calcAlpha255To256(255 - getAFromColor(src))); +} + +inline uint8_t blendChannel(uint8_t src, uint8_t srcA, uint8_t dst, uint8_t dstA, unsigned scale) +{ + unsigned blendUnscaled = src * srcA + dst * dstA; + ASSERT(blendUnscaled < (1ULL << 32) / scale); + return (blendUnscaled * scale) >> 24; +} + +inline uint32_t blendSrcOverDstNonPremultiplied(uint32_t src, uint32_t dst) +{ + uint8_t srcA = getAFromColor(src); + if (srcA == 0) + return dst; + + uint8_t dstA = getAFromColor(dst); + uint8_t dstFactorA = (dstA * calcAlpha255To256(255 - srcA)) >> 8; + ASSERT(srcA + dstFactorA < (1U << 8)); + uint8_t blendA = srcA + dstFactorA; + unsigned scale = (1UL << 24) / blendA; + + uint8_t blendR = blendChannel(getRFromColor(src), srcA, getRFromColor(dst), dstFactorA, scale); + uint8_t blendG = blendChannel(getGFromColor(src), srcA, getGFromColor(dst), dstFactorA, scale); + uint8_t blendB = blendChannel(getBFromColor(src), srcA, getBFromColor(dst), dstFactorA, scale); + + return packARGB(blendA, blendR, blendG, blendB); +} + +// Returns two point ranges ( pairs) at row 'canvasY', that belong to 'src' but not 'dst'. +// A point range is empty if the corresponding width is 0. +inline void findBlendRangeAtRow(const IntRect& src, const IntRect& dst, int canvasY, int& left1, int& width1, int& left2, int& width2) +{ + ASSERT_WITH_SECURITY_IMPLICATION(canvasY >= src.y() && canvasY < src.maxY()); + left1 = -1; + width1 = 0; + left2 = -1; + width2 = 0; + + if (canvasY < dst.y() || canvasY >= dst.maxY() || src.x() >= dst.maxX() || src.maxX() <= dst.x()) { + left1 = src.x(); + width1 = src.width(); + return; + } + + if (src.x() < dst.x()) { + left1 = src.x(); + width1 = dst.x() - src.x(); + } + + if (src.maxX() > dst.maxX()) { + left2 = dst.maxX(); + width2 = src.maxX() - dst.maxX(); + } +} + +void alphaBlendPremultiplied(ImageFrame& src, ImageFrame& dst, int canvasY, int left, int width) +{ + for (int x = 0; x < width; ++x) { + int canvasX = left + x; + ImageFrame::PixelData& pixel = *src.getAddr(canvasX, canvasY); + if (getAFromColor(pixel) != 0xff) { + ImageFrame::PixelData prevPixel = *dst.getAddr(canvasX, canvasY); + pixel = blendSrcOverDstPremultiplied(pixel, prevPixel); + } + } +} + +void alphaBlendNonPremultiplied(ImageFrame& src, ImageFrame& dst, int canvasY, int left, int width) +{ + for (int x = 0; x < width; ++x) { + int canvasX = left + x; + ImageFrame::PixelData& pixel = *src.getAddr(canvasX, canvasY); + if (getAFromColor(pixel) != 0xff) { + ImageFrame::PixelData prevPixel = *dst.getAddr(canvasX, canvasY); + pixel = blendSrcOverDstNonPremultiplied(pixel, prevPixel); + } + } +} +#endif + WEBPImageDecoder::WEBPImageDecoder(ImageSource::AlphaOption alphaOption, ImageSource::GammaAndColorProfileOption gammaAndColorProfileOption) : ImageDecoder(alphaOption, gammaAndColorProfileOption) , m_decoder(0) +#if ENABLE(WKC_BLINK_AWEBP) + , m_frameBackgroundHasAlpha(false) +#ifdef QCMS_WEBP_COLOR_CORRECTION + , m_hasColorProfile(false) +#endif + , m_demux(0) + , m_demuxState(WEBP_DEMUX_PARSING_HEADER) + , m_repetitionCount(cAnimationLoopOnce) + , m_decodedHeight(0) +#else , m_hasAlpha(false) +#endif , m_formatFlags(0) #ifdef QCMS_WEBP_COLOR_CORRECTION - , m_haveReadProfile(false) , m_transform(0) +#if !ENABLE(WKC_BLINK_AWEBP) + , m_haveReadProfile(false) , m_decodedHeight(0) #endif +#endif { +#if ENABLE(WKC_BLINK_AWEBP) + m_blendFunction = (alphaOption == ImageSource::AlphaPremultiplied) ? alphaBlendPremultiplied : alphaBlendNonPremultiplied; +#endif } WEBPImageDecoder::~WEBPImageDecoder() @@ -75,15 +226,93 @@ WEBPImageDecoder::~WEBPImageDecoder() void WEBPImageDecoder::clear() { #ifdef QCMS_WEBP_COLOR_CORRECTION - if (m_transform) - qcms_transform_release(m_transform); - m_transform = 0; + clearColorTransform(); +#endif +#if ENABLE(WKC_BLINK_AWEBP) + if (m_demux) + WebPDemuxDelete(m_demux); + m_demux = 0; + clearDecoder(); +#else + if (m_decoder) + WebPIDelete(m_decoder); + m_decoder = 0; #endif +} + +#if ENABLE(WKC_BLINK_AWEBP) +void WEBPImageDecoder::clearDecoder() +{ if (m_decoder) WebPIDelete(m_decoder); m_decoder = 0; + m_decodedHeight = 0; + m_frameBackgroundHasAlpha = false; +} + +void WEBPImageDecoder::setData(SharedBuffer* data, bool allDataReceived) +{ + if (failed()) + return; + + ImageDecoder::setData(data, allDataReceived); + updateDemuxer(); +} + +bool WEBPImageDecoder::setSize(unsigned width, unsigned height) +{ + if (ImageDecoder::isSizeAvailable() && size() == IntSize(width, height)) + return true; + + if (!ImageDecoder::setSize(width, height)) + return false; + + prepareScaleDataIfNecessary(); + return true; } +size_t WEBPImageDecoder::frameCount() +{ + const size_t oldSize = m_frameBufferCache.size(); + const size_t newSize = decodeFrameCount(); + if (oldSize != newSize) { + m_frameBufferCache.resize(newSize); + for (size_t i = oldSize; i < newSize; ++i) { + m_frameBufferCache[i].setPremultiplyAlpha(m_premultiplyAlpha); + initializeNewFrame(i); + } + } + return newSize; +} + +int WEBPImageDecoder::repetitionCount() const +{ + return failed() ? cAnimationLoopOnce : m_repetitionCount; +} + +void WEBPImageDecoder::clearFrameBufferCache(size_t clearBeforeFrame) +{ + if (m_frameBufferCache.isEmpty()) + return; + + // See GIFImageDecoder for full explanation. + clearBeforeFrame = std::min(clearBeforeFrame, m_frameBufferCache.size() - 1); + const Vector::iterator end(m_frameBufferCache.begin() + clearBeforeFrame); + + Vector::iterator i(end); + for (; (i != m_frameBufferCache.begin()) && ((i->status() == ImageFrame::FrameEmpty) || (i->disposalMethod() == ImageFrame::DisposeOverwritePrevious)); --i) { + if ((i->status() == ImageFrame::FrameComplete) && (i != end)) + i->clearPixelData(); + } + + // Now |i| holds the last frame we need to preserve; clear prior frames. + for (Vector::iterator j(m_frameBufferCache.begin()); j != i; ++j) { + ASSERT(j->status() != ImageFrame::FramePartial); + if (j->status() != ImageFrame::FrameEmpty) + j->clearPixelData(); + } +} +#else bool WEBPImageDecoder::isSizeAvailable() { if (!ImageDecoder::isSizeAvailable()) @@ -91,10 +320,15 @@ bool WEBPImageDecoder::isSizeAvailable() return ImageDecoder::isSizeAvailable(); } +#endif ImageFrame* WEBPImageDecoder::frameBufferAtIndex(size_t index) { +#if ENABLE(WKC_BLINK_AWEBP) + if (index >= frameCount()) +#else if (index) +#endif return 0; if (m_frameBufferCache.isEmpty()) { @@ -102,26 +336,42 @@ ImageFrame* WEBPImageDecoder::frameBufferAtIndex(size_t index) m_frameBufferCache[0].setPremultiplyAlpha(m_premultiplyAlpha); } +#if ENABLE(WKC_BLINK_AWEBP) + ImageFrame& frame = m_frameBufferCache[index]; + if (frame.status() != ImageFrame::FrameComplete) + decode(index); +#else ImageFrame& frame = m_frameBufferCache[0]; if (frame.status() != ImageFrame::FrameComplete) decode(false); +#endif return &frame; } #ifdef QCMS_WEBP_COLOR_CORRECTION +#if ENABLE(WKC_BLINK_AWEBP) +bool WEBPImageDecoder::createColorTransform(const char* data, size_t size) +#else void WEBPImageDecoder::createColorTransform(const char* data, size_t size) +#endif { - if (m_transform) - qcms_transform_release(m_transform); - m_transform = 0; + clearColorTransform(); qcms_profile* deviceProfile = ImageDecoder::qcmsOutputDeviceProfile(); if (!deviceProfile) +#if ENABLE(WKC_BLINK_AWEBP) + return false; +#else return; +#endif qcms_profile* inputProfile = qcms_profile_from_memory(data, size); if (!inputProfile) +#if ENABLE(WKC_BLINK_AWEBP) + return false; +#else return; +#endif // We currently only support color profiles for RGB profiled images. ASSERT(icSigRgbData == qcms_profile_get_color_space(inputProfile)); @@ -131,18 +381,31 @@ void WEBPImageDecoder::createColorTransform(const char* data, size_t size) m_transform = qcms_transform_create(inputProfile, format, deviceProfile, QCMS_DATA_RGBA_8, QCMS_INTENT_PERCEPTUAL); qcms_profile_release(inputProfile); +#if !ENABLE(WKC_BLINK_AWEBP) + return !!m_transform; +#endif } +#if ENABLE(WKC_BLINK_AWEBP) +void WEBPImageDecoder::readColorProfile() +#else void WEBPImageDecoder::readColorProfile(const uint8_t* data, size_t size) +#endif { WebPChunkIterator chunkIterator; +#if ENABLE(WKC_BLINK_AWEBP) + if (!WebPDemuxGetChunk(m_demux, "ICCP", 1, &chunkIterator)) { +#else WebPData inputData = { data, size }; WebPDemuxState state; WebPDemuxer* demuxer = WebPDemuxPartial(&inputData, &state); if (!WebPDemuxGetChunk(demuxer, "ICCP", 1, &chunkIterator)) { +#endif WebPDemuxReleaseChunkIterator(&chunkIterator); +#if !ENABLE(WKC_BLINK_AWEBP) WebPDemuxDelete(demuxer); +#endif return; } @@ -159,12 +422,19 @@ void WEBPImageDecoder::readColorProfile(const uint8_t* data, size_t size) ignoreProfile = true; if (!ignoreProfile) +#if ENABLE(WKC_BLINK_AWEBP) + m_hasColorProfile = createColorTransform(profileData, profileSize); +#else createColorTransform(profileData, profileSize); +#endif WebPDemuxReleaseChunkIterator(&chunkIterator); +#if !ENABLE(WKC_BLINK_AWEBP) WebPDemuxDelete(demuxer); +#endif } +#if !ENABLE(WKC_BLINK_AWEBP) void WEBPImageDecoder::applyColorProfile(const uint8_t* data, size_t size, ImageFrame& buffer) { int width; @@ -193,9 +463,353 @@ void WEBPImageDecoder::applyColorProfile(const uint8_t* data, size_t size, Image m_decodedHeight = decodedHeight; } +#endif + +void WEBPImageDecoder::clearColorTransform() +{ + if (m_transform) + qcms_transform_release(m_transform); + m_transform = 0; +} + +#endif // QCMS_WEBP_COLOR_CORRECTION + +#if ENABLE(WKC_BLINK_AWEBP) +size_t WEBPImageDecoder::decodeFrameCount() +{ + // If failed() true, return the existing number of frames. This way + // if we get halfway through the image before decoding fails, we won't + // suddenly start reporting that the image has zero frames. + return failed() ? m_frameBufferCache.size() : WebPDemuxGetI(m_demux, WEBP_FF_FRAME_COUNT); +} + +size_t WEBPImageDecoder::findRequiredPreviousFrame(size_t frameIndex, bool frameRectIsOpaque) +{ + ASSERT(frameIndex <= m_frameBufferCache.size()); + if (!frameIndex) { + // The first frame doesn't rely on any previous data. + return -1; + } + + const ImageFrame* currBuffer = &m_frameBufferCache[frameIndex]; + if ((frameRectIsOpaque || currBuffer->alphaBlendSource() == ImageFrame::BlendAtopBgcolor) + && currBuffer->originalFrameRect().contains(IntRect(IntPoint(), size()))) + return -1; + + // The starting state for this frame depends on the previous frame's + // disposal method. + size_t prevFrame = frameIndex - 1; + const ImageFrame* prevBuffer = &m_frameBufferCache[prevFrame]; + + switch (prevBuffer->disposalMethod()) { + case ImageFrame::DisposeNotSpecified: + case ImageFrame::DisposeKeep: + // prevFrame will be used as the starting state for this frame. + // FIXME: Be even smarter by checking the frame sizes and/or alpha-containing regions. + return prevFrame; + case ImageFrame::DisposeOverwritePrevious: + // Frames that use the DisposeOverwritePrevious method are effectively + // no-ops in terms of changing the starting state of a frame compared to + // the starting state of the previous frame, so skip over them and + // return the required previous frame of it. + return prevBuffer->requiredPreviousFrameIndex(); + case ImageFrame::DisposeOverwriteBgcolor: + // If the previous frame fills the whole image, then the current frame + // can be decoded alone. Likewise, if the previous frame could be + // decoded without reference to any prior frame, the starting state for + // this frame is a blank frame, so it can again be decoded alone. + // Otherwise, the previous frame contributes to this frame. + return (prevBuffer->originalFrameRect().contains(IntRect(IntPoint(), size())) + || (prevBuffer->requiredPreviousFrameIndex() == -1)) ? -1 : prevFrame; + default: + ASSERT_NOT_REACHED(); + return -1; + } +} + +void WEBPImageDecoder::initializeNewFrame(size_t index) +{ + if (!(m_formatFlags & ANIMATION_FLAG)) { + ASSERT(!index); + return; + } + WebPIterator animatedFrame; + WebPDemuxGetFrame(m_demux, index + 1, &animatedFrame); + ASSERT(animatedFrame.complete == 1); + ImageFrame* buffer = &m_frameBufferCache[index]; + IntRect frameRect(animatedFrame.x_offset, animatedFrame.y_offset, animatedFrame.width, animatedFrame.height); + buffer->setOriginalFrameRect(intersection(frameRect, IntRect(IntPoint(), size()))); + buffer->setDuration(animatedFrame.duration); + buffer->setDisposalMethod(animatedFrame.dispose_method == WEBP_MUX_DISPOSE_BACKGROUND ? ImageFrame::DisposeOverwriteBgcolor : ImageFrame::DisposeKeep); + buffer->setAlphaBlendSource(animatedFrame.blend_method == WEBP_MUX_BLEND ? ImageFrame::BlendAtopPreviousFrame : ImageFrame::BlendAtopBgcolor); + buffer->setRequiredPreviousFrameIndex(findRequiredPreviousFrame(index, !animatedFrame.has_alpha)); + WebPDemuxReleaseIterator(&animatedFrame); +} + +void WEBPImageDecoder::decode(size_t index) +{ + if (failed()) + return; + + Vector framesToDecode; + size_t frameToDecode = index; + do { + framesToDecode.append(frameToDecode); + frameToDecode = m_frameBufferCache[frameToDecode].requiredPreviousFrameIndex(); + } while (frameToDecode != -1 && m_frameBufferCache[frameToDecode].status() != ImageFrame::FrameComplete); + + ASSERT(m_demux); + for (auto i = framesToDecode.rbegin(); i != framesToDecode.rend(); ++i) { + if ((m_formatFlags & ANIMATION_FLAG) && !initFrameBuffer(*i)) + return; + WebPIterator webpFrame; + if (!WebPDemuxGetFrame(m_demux, *i + 1, &webpFrame)) { + setFailed(); + } else { + decodeSingleFrame(webpFrame.fragment.bytes, webpFrame.fragment.size, *i); + WebPDemuxReleaseIterator(&webpFrame); + } + if (failed()) + return; + + // We need more data to continue decoding. + if (m_frameBufferCache[*i].status() != ImageFrame::FrameComplete) + break; + } + + // It is also a fatal error if all data is received and we have decoded all + // frames available but the file is truncated. + if (index >= m_frameBufferCache.size() - 1 && isAllDataReceived() && m_demux && m_demuxState != WEBP_DEMUX_DONE) + setFailed(); +} + +bool WEBPImageDecoder::decodeSingleFrame(const uint8_t* dataBytes, size_t dataSize, size_t frameIndex) +{ + if (failed()) + return false; + + ASSERT(isSizeAvailable()); + + ASSERT(m_frameBufferCache.size() > frameIndex); + ImageFrame& buffer = m_frameBufferCache[frameIndex]; + ASSERT(buffer.status() != ImageFrame::FrameComplete); + + if (buffer.status() == ImageFrame::FrameEmpty) { + if (!buffer.setSize(size().width(), size().height())) + return setFailed(); + buffer.setStatus(ImageFrame::FramePartial); + // The buffer is transparent outside the decoded area while the image is loading. + // The correct value of 'hasAlpha' for the frame will be set when it is fully decoded. + buffer.setHasAlpha(true); + buffer.setOriginalFrameRect(IntRect(IntPoint(), size())); + } + + const IntRect& frameRect = buffer.originalFrameRect(); + if (!m_decoder) { + WEBP_CSP_MODE mode = outputMode(m_formatFlags & ALPHA_FLAG); + if (!m_premultiplyAlpha) + mode = outputMode(false); +#ifdef QCMS_WEBP_COLOR_CORRECTION + if (colorTransform()) + mode = MODE_RGBA; // Decode to RGBA for input to libqcms. +#endif + WebPInitDecBuffer(&m_decoderBuffer); + m_decoderBuffer.colorspace = mode; + m_decoderBuffer.u.RGBA.stride = size().width() * sizeof(ImageFrame::PixelData); + m_decoderBuffer.u.RGBA.size = m_decoderBuffer.u.RGBA.stride * frameRect.height(); + m_decoderBuffer.is_external_memory = 1; + m_decoder = WebPINewDecoder(&m_decoderBuffer); + if (!m_decoder) + return setFailed(); + } + + m_decoderBuffer.u.RGBA.rgba = reinterpret_cast(buffer.getAddr(frameRect.x(), frameRect.y())); + + switch (WebPIUpdate(m_decoder, dataBytes, dataSize)) { + case VP8_STATUS_OK: + applyPostProcessing(frameIndex); + buffer.setHasAlpha((m_formatFlags & ALPHA_FLAG) || m_frameBackgroundHasAlpha); + buffer.setStatus(ImageFrame::FrameComplete); + clearDecoder(); + return true; + case VP8_STATUS_SUSPENDED: + if (!isAllDataReceived() && !frameIsCompleteAtIndex(frameIndex)) { + applyPostProcessing(frameIndex); + return false; + } + // FALLTHROUGH + default: + clear(); + return setFailed(); + } +} + +bool WEBPImageDecoder::frameIsCompleteAtIndex(size_t index) const +{ + if (!m_demux || m_demuxState <= WEBP_DEMUX_PARSING_HEADER) + return false; + return (index < m_frameBufferCache.size()) && + (m_frameBufferCache[index].status() == ImageFrame::FrameComplete); +} + +bool WEBPImageDecoder::updateDemuxer() +{ + if (failed()) + return false; + + const unsigned webpHeaderSize = 30; + if (m_data->size() < webpHeaderSize) + return false; // Await VP8X header so WebPDemuxPartial succeeds. + + WebPDemuxDelete(m_demux); + WebPData inputData = { reinterpret_cast(m_data->data()), m_data->size() }; + m_demux = WebPDemuxPartial(&inputData, &m_demuxState); + if (!m_demux || (isAllDataReceived() && m_demuxState != WEBP_DEMUX_DONE)) + return setFailed(); + + ASSERT(m_demuxState > WEBP_DEMUX_PARSING_HEADER); + if (!WebPDemuxGetI(m_demux, WEBP_FF_FRAME_COUNT)) + return false; // Wait until the encoded image frame data arrives. + + if (!isSizeAvailable()) { + int width = WebPDemuxGetI(m_demux, WEBP_FF_CANVAS_WIDTH); + int height = WebPDemuxGetI(m_demux, WEBP_FF_CANVAS_HEIGHT); + if (!setSize(width, height)) + return setFailed(); + + m_formatFlags = WebPDemuxGetI(m_demux, WEBP_FF_FORMAT_FLAGS); + if (!(m_formatFlags & ANIMATION_FLAG)) { + m_repetitionCount = cAnimationNone; + } else { + // Since we have parsed at least one frame, even if partially, + // the global animation (ANIM) properties have been read since + // an ANIM chunk must precede the ANMF frame chunks. + m_repetitionCount = WebPDemuxGetI(m_demux, WEBP_FF_LOOP_COUNT); + // Repetition count is always <= 16 bits. + ASSERT(m_repetitionCount == (m_repetitionCount & 0xffff)); + // Repetition count is the number of animation cycles to show, + // where 0 means "infinite". But ImageSource::repetitionCount() + // returns -1 for "infinite", and 0 and up for "show the image + // animation one cycle more than the value". Subtract one here + // to correctly handle the finite and infinite cases. + --m_repetitionCount; + // FIXME: Implement ICC profile support for animated images. + m_formatFlags &= ~ICCP_FLAG; + } + +#ifdef QCMS_WEBP_COLOR_CORRECTION + if ((m_formatFlags & ICCP_FLAG) && !ignoresGammaAndColorProfile()) + readColorProfile(); +#endif + } + + ASSERT(isSizeAvailable()); + return true; +} +bool WEBPImageDecoder::initFrameBuffer(size_t frameIndex) +{ + ImageFrame& buffer = m_frameBufferCache[frameIndex]; + if (buffer.status() != ImageFrame::FrameEmpty) // Already initialized. + return true; + + const size_t requiredPreviousFrameIndex = buffer.requiredPreviousFrameIndex(); + if (requiredPreviousFrameIndex == -1) { + // This frame doesn't rely on any previous data. + if (!buffer.setSize(size().width(), size().height())) + return setFailed(); + m_frameBackgroundHasAlpha = !buffer.originalFrameRect().contains(IntRect(IntPoint(), size())); + } else { + const ImageFrame& prevBuffer = m_frameBufferCache[requiredPreviousFrameIndex]; + ASSERT(prevBuffer.status() == ImageFrame::FrameComplete); + + // Preserve the last frame as the starting state for this frame. + if (!buffer.copyBitmapData(prevBuffer)) + return setFailed(); + + if (prevBuffer.disposalMethod() == ImageFrame::DisposeOverwriteBgcolor) { + // We want to clear the previous frame to transparent, without + // affecting pixels in the image outside of the frame. + const IntRect& prevRect = prevBuffer.originalFrameRect(); + ASSERT(!prevRect.contains(IntRect(IntPoint(), size()))); + buffer.zeroFillFrameRect(prevRect); + } + + m_frameBackgroundHasAlpha = prevBuffer.hasAlpha() || (prevBuffer.disposalMethod() == ImageFrame::DisposeOverwriteBgcolor); + } + + buffer.setStatus(ImageFrame::FramePartial); + // The buffer is transparent outside the decoded area while the image is loading. + // The correct value of 'hasAlpha' for the frame will be set when it is fully decoded. + buffer.setHasAlpha(true); + return true; +} + +void WEBPImageDecoder::applyPostProcessing(size_t frameIndex) +{ + ImageFrame& buffer = m_frameBufferCache[frameIndex]; + int width; + int decodedHeight; + if (!WebPIDecGetRGB(m_decoder, &decodedHeight, &width, 0, 0)) + return; // See also https://bugs.webkit.org/show_bug.cgi?id=74062 + if (decodedHeight <= 0) + return; + + const IntRect& frameRect = buffer.originalFrameRect(); + ASSERT_WITH_SECURITY_IMPLICATION(width == frameRect.width()); + ASSERT_WITH_SECURITY_IMPLICATION(decodedHeight <= frameRect.height()); + const int left = frameRect.x(); + const int top = frameRect.y(); + +#ifdef QCMS_WEBP_COLOR_CORRECTION + if (qcms_transform* transform = colorTransform()) { + for (int y = m_decodedHeight; y < decodedHeight; ++y) { + const int canvasY = top + y; + uint8_t* row = reinterpret_cast(buffer.getAddr(left, canvasY)); + qcms_transform_data_type(transform, row, row, width, QCMS_OUTPUT_RGBX); + uint8_t* pixel = row; + for (int x = 0; x < width; ++x, pixel += 4) { + const int canvasX = left + x; + buffer.setRGBA(canvasX, canvasY, pixel[0], pixel[1], pixel[2], pixel[3]); + } + } + } #endif // QCMS_WEBP_COLOR_CORRECTION + // During the decoding of current frame, we may have set some pixels to be transparent (i.e. alpha < 255). + // However, the value of each of these pixels should have been determined by blending it against the value + // of that pixel in the previous frame if alpha blend source was 'BlendAtopPreviousFrame'. So, we correct these + // pixels based on disposal method of the previous frame and the previous frame buffer. + // FIXME: This could be avoided if libwebp decoder had an API that used the previous required frame + // to do the alpha-blending by itself. + if ((m_formatFlags & ANIMATION_FLAG) && frameIndex && buffer.alphaBlendSource() == ImageFrame::BlendAtopPreviousFrame && buffer.requiredPreviousFrameIndex() != -1) { + ImageFrame& prevBuffer = m_frameBufferCache[frameIndex - 1]; + ASSERT(prevBuffer.status() == ImageFrame::FrameComplete); + ImageFrame::FrameDisposalMethod prevDisposalMethod = prevBuffer.disposalMethod(); + if (prevDisposalMethod == ImageFrame::DisposeKeep) { // Blend transparent pixels with pixels in previous canvas. + for (int y = m_decodedHeight; y < decodedHeight; ++y) { + m_blendFunction(buffer, prevBuffer, top + y, left, width); + } + } else if (prevDisposalMethod == ImageFrame::DisposeOverwriteBgcolor) { + const IntRect& prevRect = prevBuffer.originalFrameRect(); + // We need to blend a transparent pixel with its value just after initFrame() call. That is: + // * Blend with fully transparent pixel if it belongs to prevRect <-- This is a no-op. + // * Blend with the pixel in the previous canvas otherwise <-- Needs alpha-blending. + for (int y = m_decodedHeight; y < decodedHeight; ++y) { + int canvasY = top + y; + int left1, width1, left2, width2; + findBlendRangeAtRow(frameRect, prevRect, canvasY, left1, width1, left2, width2); + if (width1 > 0) + m_blendFunction(buffer, prevBuffer, canvasY, left1, width1); + if (width2 > 0) + m_blendFunction(buffer, prevBuffer, canvasY, left2, width2); + } + } + } + + m_decodedHeight = decodedHeight; +} +#else bool WEBPImageDecoder::decode(bool onlySize) { if (failed()) @@ -287,6 +901,7 @@ bool WEBPImageDecoder::decode(bool onlySize) return setFailed(); } } +#endif } // namespace WebCore diff --git a/webkit/WebCore/platform/image-decoders/webp/WEBPImageDecoder.h b/webkit/WebCore/platform/image-decoders/webp/WEBPImageDecoder.h index 00bb9e436..e62e03e3f 100755 --- a/webkit/WebCore/platform/image-decoders/webp/WEBPImageDecoder.h +++ b/webkit/WebCore/platform/image-decoders/webp/WEBPImageDecoder.h @@ -34,9 +34,17 @@ #if USE(WEBP) #include "webp/decode.h" + +#if ENABLE(WKC_BLINK_AWEBP) +#include "webp/demux.h" +#if USE(QCMSLIB) +#define QCMS_WEBP_COLOR_CORRECTION +#endif +#else #if USE(QCMSLIB) && (WEBP_DECODER_ABI_VERSION > 0x200) #define QCMS_WEBP_COLOR_CORRECTION #endif +#endif namespace WebCore { @@ -46,29 +54,80 @@ class WEBPImageDecoder : public ImageDecoder { virtual ~WEBPImageDecoder(); virtual String filenameExtension() const { return "webp"; } +#if ENABLE(WKC_BLINK_AWEBP) + virtual void setData(SharedBuffer* data, bool allDataReceived); + virtual bool setSize(unsigned width, unsigned height); + virtual size_t frameCount(); + virtual int repetitionCount() const; + virtual void clearFrameBufferCache(size_t clearBeforeFrame); +#else virtual bool isSizeAvailable(); +#endif virtual ImageFrame* frameBufferAtIndex(size_t index); private: +#if ENABLE(WKC_BLINK_AWEBP) + size_t decodeFrameCount(); + size_t findRequiredPreviousFrame(size_t frameIndex, bool frameRectIsOpaque); + void initializeNewFrame(size_t index); + void decode(size_t index); + bool decodeSingleFrame(const uint8_t* dataBytes, size_t dataSize, size_t frameIndex); + bool frameIsCompleteAtIndex(size_t) const; +#else bool decode(bool onlySize); +#endif WebPIDecoder* m_decoder; +#if ENABLE(WKC_BLINK_AWEBP) + WebPDecBuffer m_decoderBuffer; + bool m_frameBackgroundHasAlpha; +#ifdef QCMS_WEBP_COLOR_CORRECTION + bool m_hasColorProfile; +#endif +#else bool m_hasAlpha; +#endif int m_formatFlags; #ifdef QCMS_WEBP_COLOR_CORRECTION qcms_transform* colorTransform() const { return m_transform; } +#if ENABLE(WKC_BLINK_AWEBP) + bool createColorTransform(const char* data, size_t); + void readColorProfile(); +#else void createColorTransform(const char* data, size_t); void readColorProfile(const uint8_t* data, size_t); void applyColorProfile(const uint8_t* data, size_t, ImageFrame&); +#endif + void clearColorTransform(); - bool m_haveReadProfile; qcms_transform* m_transform; +#if !ENABLE(WKC_BLINK_AWEBP) + bool m_haveReadProfile; int m_decodedHeight; +#endif #else +#if !ENABLE(WKC_BLINK_AWEBP) void applyColorProfile(const uint8_t*, size_t, ImageFrame&) { }; +#endif #endif void clear(); + +#if ENABLE(WKC_BLINK_AWEBP) + bool updateDemuxer(); + bool initFrameBuffer(size_t index); + void applyPostProcessing(size_t frameIndex); + + WebPDemuxer* m_demux; + WebPDemuxState m_demuxState; + int m_repetitionCount; + int m_decodedHeight; + + typedef void (*AlphaBlendFunction)(ImageFrame&, ImageFrame&, int, int, int); + AlphaBlendFunction m_blendFunction; + + void clearDecoder(); +#endif }; } // namespace WebCore diff --git a/webkit/WebCore/platform/ios/RemoteCommandListenerIOS.h b/webkit/WebCore/platform/ios/RemoteCommandListenerIOS.h index cf2e563a3..fc02ee59d 100755 --- a/webkit/WebCore/platform/ios/RemoteCommandListenerIOS.h +++ b/webkit/WebCore/platform/ios/RemoteCommandListenerIOS.h @@ -46,13 +46,15 @@ class RemoteCommandListenerIOS : public RemoteCommandListener { protected: WeakPtr createWeakPtr() { return m_weakPtrFactory.createWeakPtr(); } - + void updateSupportedCommands() override; + WeakPtrFactory m_weakPtrFactory; RetainPtr m_playTarget; RetainPtr m_pauseTarget; RetainPtr m_togglePlayPauseTarget; RetainPtr m_seekForwardTarget; RetainPtr m_seekBackwardTarget; + RetainPtr m_seekToTimeTarget; }; } diff --git a/webkit/WebCore/platform/ios/RemoteCommandListenerIOS.mm b/webkit/WebCore/platform/ios/RemoteCommandListenerIOS.mm index 7d144217d..8ea79b518 100755 --- a/webkit/WebCore/platform/ios/RemoteCommandListenerIOS.mm +++ b/webkit/WebCore/platform/ios/RemoteCommandListenerIOS.mm @@ -36,6 +36,9 @@ SOFT_LINK_FRAMEWORK(MediaPlayer) SOFT_LINK_CLASS(MediaPlayer, MPRemoteCommandCenter) SOFT_LINK_CLASS(MediaPlayer, MPSeekCommandEvent) +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 90100 +SOFT_LINK_CLASS(MediaPlayer, MPChangePlaybackPositionCommandEvent) +#endif namespace WebCore { @@ -55,7 +58,7 @@ callOnMainThread([weakThis] { if (!weakThis) return; - weakThis->m_client.didReceiveRemoteControlCommand(PlatformMediaSession::PauseCommand); + weakThis->m_client.didReceiveRemoteControlCommand(PlatformMediaSession::PauseCommand, nullptr); }); return MPRemoteCommandHandlerStatusSuccess; @@ -65,7 +68,7 @@ callOnMainThread([weakThis] { if (!weakThis) return; - weakThis->m_client.didReceiveRemoteControlCommand(PlatformMediaSession::PlayCommand); + weakThis->m_client.didReceiveRemoteControlCommand(PlatformMediaSession::PlayCommand, nullptr); }); return MPRemoteCommandHandlerStatusSuccess; @@ -75,7 +78,7 @@ callOnMainThread([weakThis] { if (!weakThis) return; - weakThis->m_client.didReceiveRemoteControlCommand(PlatformMediaSession::TogglePlayPauseCommand); + weakThis->m_client.didReceiveRemoteControlCommand(PlatformMediaSession::TogglePlayPauseCommand, nullptr); }); return MPRemoteCommandHandlerStatusSuccess; @@ -90,7 +93,7 @@ callOnMainThread([weakThis, command] { if (!weakThis) return; - weakThis->m_client.didReceiveRemoteControlCommand(command); + weakThis->m_client.didReceiveRemoteControlCommand(command, nullptr); }); return MPRemoteCommandHandlerStatusSuccess; @@ -105,11 +108,31 @@ callOnMainThread([weakThis, command] { if (!weakThis) return; - weakThis->m_client.didReceiveRemoteControlCommand(command); + weakThis->m_client.didReceiveRemoteControlCommand(command, nullptr); }); return MPRemoteCommandHandlerStatusSuccess; }]; + +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 90100 + m_seekToTimeTarget = [[center changePlaybackPositionCommand] addTargetWithHandler:^(MPRemoteCommandEvent *event) { + ASSERT([event isKindOfClass:getMPChangePlaybackPositionCommandEventClass()]); + + if (!client.supportsSeeking()) + return MPRemoteCommandHandlerStatusCommandFailed; + + MPChangePlaybackPositionCommandEvent* seekEvent = static_cast(event); + PlatformMediaSession::RemoteCommandArgument argument { [seekEvent positionTime] }; + + callOnMainThread([weakThis, argument] { + if (!weakThis) + return; + weakThis->m_client.didReceiveRemoteControlCommand(PlatformMediaSession::TogglePlayPauseCommand, &argument); + }); + + return MPRemoteCommandHandlerStatusSuccess; + }]; +#endif } RemoteCommandListenerIOS::~RemoteCommandListenerIOS() @@ -120,6 +143,16 @@ [[center togglePlayPauseCommand] removeTarget:m_togglePlayPauseTarget.get()]; [[center seekForwardCommand] removeTarget:m_seekForwardTarget.get()]; [[center seekBackwardCommand] removeTarget:m_seekBackwardTarget.get()]; +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 90100 + [[center changePlaybackPositionCommand] removeTarget:m_seekToTimeTarget.get()]; +#endif +} + +void RemoteCommandListenerIOS::updateSupportedCommands() +{ +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 90100 + [[[getMPRemoteCommandCenterClass() sharedCommandCenter] changePlaybackPositionCommand] setEnabled:!!client().supportsSeeking()]; +#endif } } diff --git a/webkit/WebCore/platform/mock/mediasource/MockSourceBufferPrivate.cpp b/webkit/WebCore/platform/mock/mediasource/MockSourceBufferPrivate.cpp index 07922f06d..1433c247e 100755 --- a/webkit/WebCore/platform/mock/mediasource/MockSourceBufferPrivate.cpp +++ b/webkit/WebCore/platform/mock/mediasource/MockSourceBufferPrivate.cpp @@ -197,6 +197,10 @@ void MockSourceBufferPrivate::abort() { } +void MockSourceBufferPrivate::resetParserState() +{ +} + #if !PLATFORM(WKC) void MockSourceBufferPrivate::removedFromMediaSource() { diff --git a/webkit/WebCore/platform/mock/mediasource/MockSourceBufferPrivate.h b/webkit/WebCore/platform/mock/mediasource/MockSourceBufferPrivate.h index 4513486f0..67949885d 100755 --- a/webkit/WebCore/platform/mock/mediasource/MockSourceBufferPrivate.h +++ b/webkit/WebCore/platform/mock/mediasource/MockSourceBufferPrivate.h @@ -65,6 +65,7 @@ class MockSourceBufferPrivate : public SourceBufferPrivate { virtual void setClient(SourceBufferPrivateClient*) override; virtual void append(const unsigned char* data, unsigned length) override; virtual void abort() override; + void resetParserState() override; #if !PLATFORM(WKC) virtual void removedFromMediaSource() override; #else diff --git a/webkit/WebCore/platform/network/BlobResourceHandle.cpp b/webkit/WebCore/platform/network/BlobResourceHandle.cpp index 104c5b071..36f8d5b40 100755 --- a/webkit/WebCore/platform/network/BlobResourceHandle.cpp +++ b/webkit/WebCore/platform/network/BlobResourceHandle.cpp @@ -55,24 +55,15 @@ static const long long positionNotSpecified = -1; static const int httpOK = 200; static const int httpPartialContent = 206; static const int httpNotAllowed = 403; -static const int httpNotFound = 404; static const int httpRequestedRangeNotSatisfiable = 416; static const int httpInternalError = 500; static const char* httpOKText = "OK"; static const char* httpPartialContentText = "Partial Content"; static const char* httpNotAllowedText = "Not Allowed"; -static const char* httpNotFoundText = "Not Found"; static const char* httpRequestedRangeNotSatisfiableText = "Requested Range Not Satisfiable"; static const char* httpInternalErrorText = "Internal Server Error"; static const char* const webKitBlobResourceDomain = "WebKitBlobResource"; -enum { - notFoundError = 1, - securityError = 2, - rangeError = 3, - notReadableError = 4, - methodNotAllowed = 5 -}; /////////////////////////////////////////////////////////////////////////////// // BlobResourceSynchronousLoader @@ -105,7 +96,7 @@ void BlobResourceSynchronousLoader::didReceiveResponse(ResourceHandle* handle, c { // We cannot handle the size that is more than maximum integer. if (response.expectedContentLength() > INT_MAX) { - m_error = ResourceError(webKitBlobResourceDomain, notReadableError, response.url(), "File is too large"); + m_error = ResourceError(webKitBlobResourceDomain, static_cast(BlobResourceHandle::Error::NotReadableError), response.url(), "File is too large"); return; } @@ -146,7 +137,7 @@ PassRefPtr BlobResourceHandle::createAsync(BlobData* blobDat void BlobResourceHandle::loadResourceSynchronously(BlobData* blobData, const ResourceRequest& request, ResourceError& error, ResourceResponse& response, Vector& data) { if (!equalIgnoringCase(request.httpMethod(), "GET")) { - error = ResourceError(webKitBlobResourceDomain, methodNotAllowed, response.url(), "Request method must be GET"); + error = ResourceError(webKitBlobResourceDomain, static_cast(Error::MethodNotAllowed), response.url(), "Request method must be GET"); return; } @@ -159,7 +150,7 @@ BlobResourceHandle::BlobResourceHandle(BlobData* blobData, const ResourceRequest : ResourceHandle(0, request, client, false, false) , m_blobData(blobData) , m_async(async) - , m_errorCode(0) + , m_errorCode(Error::NoError) , m_aborted(false) , m_rangeOffset(positionNotSpecified) , m_rangeEnd(positionNotSpecified) @@ -221,20 +212,19 @@ void BlobResourceHandle::doStart() ASSERT(isMainThread()); // Do not continue if the request is aborted or an error occurs. - if (m_aborted || m_errorCode) + if (erroredOrAborted()) return; // If the blob data is not found, fail now. if (!m_blobData) { - m_errorCode = notFoundError; - notifyResponse(); + notifyFail(Error::NotFoundError); return; } // Parse the "Range" header we care about. String range = firstRequest().httpHeaderField(HTTPHeaderName::Range); if (!range.isEmpty() && !parseRange(range, m_rangeOffset, m_rangeEnd, m_rangeSuffixLength)) { - m_errorCode = rangeError; + m_errorCode = Error::RangeError; notifyResponse(); return; } @@ -243,7 +233,7 @@ void BlobResourceHandle::doStart() getSizeForNext(); else { Ref protect(*this); // getSizeForNext calls the client - for (size_t i = 0; i < m_blobData->items().size() && !m_aborted && !m_errorCode; ++i) + for (size_t i = 0; i < m_blobData->items().size() && !erroredOrAborted(); ++i) getSizeForNext(); notifyResponse(); } @@ -289,13 +279,12 @@ void BlobResourceHandle::didGetSize(long long size) ASSERT(isMainThread()); // Do not continue if the request is aborted or an error occurs. - if (m_aborted || m_errorCode) + if (erroredOrAborted()) return; // If the size is -1, it means the file has been moved or changed. Fail now. if (size == -1) { - m_errorCode = notFoundError; - notifyResponse(); + notifyFail(Error::NotFoundError); return; } @@ -356,13 +345,13 @@ int BlobResourceHandle::readSync(char* buf, int length) int remaining = length; while (remaining) { // Do not continue if the request is aborted or an error occurs. - if (m_aborted || m_errorCode) + if (erroredOrAborted()) break; // If there is no more remaining data to read, we are done. if (!m_totalRemainingSize || m_readItemCount >= m_blobData->items().size()) break; - + const BlobDataItem& item = m_blobData->items().at(m_readItemCount); int bytesRead = 0; if (item.type == BlobDataItem::Data) @@ -379,7 +368,7 @@ int BlobResourceHandle::readSync(char* buf, int length) } int result; - if (m_aborted || m_errorCode) + if (erroredOrAborted()) result = -1; else result = length - remaining; @@ -428,7 +417,7 @@ int BlobResourceHandle::readFileSync(const BlobDataItem& item, char* buf, int le bool success = m_stream->openForRead(item.file->path(), item.offset() + m_currentItemReadSize, bytesToRead); m_currentItemReadSize = 0; if (!success) { - m_errorCode = notReadableError; + m_errorCode = Error::NotReadableError; return 0; } @@ -437,7 +426,7 @@ int BlobResourceHandle::readFileSync(const BlobDataItem& item, char* buf, int le int bytesRead = m_stream->read(buf, length); if (bytesRead < 0) { - m_errorCode = notReadableError; + m_errorCode = Error::NotReadableError; return 0; } if (!bytesRead) { @@ -456,7 +445,7 @@ void BlobResourceHandle::readAsync() ASSERT(m_async); // Do not continue if the request is aborted or an error occurs. - if (m_aborted || m_errorCode) + if (erroredOrAborted()) return; // If there is no more remaining data to read, we are done. @@ -520,7 +509,7 @@ void BlobResourceHandle::didOpen(bool success) ASSERT(m_async); if (!success) { - failed(notReadableError); + failed(Error::NotReadableError); return; } @@ -531,7 +520,7 @@ void BlobResourceHandle::didOpen(bool success) void BlobResourceHandle::didRead(int bytesRead) { if (bytesRead < 0) { - failed(notReadableError); + failed(Error::NotReadableError); return; } @@ -568,7 +557,7 @@ void BlobResourceHandle::consumeData(const char* data, int bytesRead) readAsync(); } -void BlobResourceHandle::failed(int errorCode) +void BlobResourceHandle::failed(Error errorCode) { ASSERT(m_async); Ref protect(*this); @@ -588,7 +577,7 @@ void BlobResourceHandle::notifyResponse() if (!client()) return; - if (m_errorCode) { + if (m_errorCode != Error::NoError) { Ref protect(*this); notifyResponseOnError(); notifyFinish(); @@ -619,19 +608,15 @@ void BlobResourceHandle::notifyResponseOnSuccess() void BlobResourceHandle::notifyResponseOnError() { - ASSERT(m_errorCode); + ASSERT(m_errorCode != Error::NoError); ResourceResponse response(firstRequest().url(), "text/plain", 0, String()); switch (m_errorCode) { - case rangeError: + case Error::RangeError: response.setHTTPStatusCode(httpRequestedRangeNotSatisfiable); response.setHTTPStatusText(httpRequestedRangeNotSatisfiableText); break; - case notFoundError: - response.setHTTPStatusCode(httpNotFound); - response.setHTTPStatusText(httpNotFoundText); - break; - case securityError: + case Error::SecurityError: response.setHTTPStatusCode(httpNotAllowed); response.setHTTPStatusText(httpNotAllowedText); break; @@ -655,10 +640,10 @@ void BlobResourceHandle::notifyReceiveData(const char* data, int bytesRead) client()->didReceiveBuffer(this, SharedBuffer::create(data, bytesRead), bytesRead); } -void BlobResourceHandle::notifyFail(int errorCode) +void BlobResourceHandle::notifyFail(Error errorCode) { if (client()) - client()->didFail(this, ResourceError(webKitBlobResourceDomain, errorCode, firstRequest().url(), String())); + client()->didFail(this, ResourceError(webKitBlobResourceDomain, static_cast(errorCode), firstRequest().url(), String())); } static void doNotifyFinish(void* context) diff --git a/webkit/WebCore/platform/network/BlobResourceHandle.h b/webkit/WebCore/platform/network/BlobResourceHandle.h index 676dbff98..d4c155009 100755 --- a/webkit/WebCore/platform/network/BlobResourceHandle.h +++ b/webkit/WebCore/platform/network/BlobResourceHandle.h @@ -57,6 +57,15 @@ class BlobResourceHandle final : public FileStreamClient, public ResourceHandle bool aborted() const { return m_aborted; } + enum class Error { + NoError = 0, + NotFoundError = 1, + SecurityError = 2, + RangeError = 3, + NotReadableError = 4, + MethodNotAllowed = 5 + }; + private: BlobResourceHandle(BlobData*, const ResourceRequest&, ResourceHandleClient*, bool async); virtual ~BlobResourceHandle(); @@ -74,7 +83,7 @@ class BlobResourceHandle final : public FileStreamClient, public ResourceHandle void getSizeForNext(); void seek(); void consumeData(const char* data, int bytesRead); - void failed(int errorCode); + void failed(Error); void readAsync(); void readDataAsync(const BlobDataItem&); @@ -87,16 +96,18 @@ class BlobResourceHandle final : public FileStreamClient, public ResourceHandle void notifyResponseOnSuccess(); void notifyResponseOnError(); void notifyReceiveData(const char*, int); - void notifyFail(int errorCode); + void notifyFail(Error); void notifyFinish(); + bool erroredOrAborted() const { return m_aborted || m_errorCode != Error::NoError; } + RefPtr m_blobData; bool m_async; std::unique_ptr m_asyncStream; // For asynchronous loading. std::unique_ptr m_stream; // For synchronous loading. Vector m_buffer; Vector m_itemLengthList; - int m_errorCode; + Error m_errorCode; bool m_aborted; long long m_rangeOffset; long long m_rangeEnd; diff --git a/webkit/WebCore/platform/network/ResourceRequestBase.cpp b/webkit/WebCore/platform/network/ResourceRequestBase.cpp index ded326182..22c252cac 100755 --- a/webkit/WebCore/platform/network/ResourceRequestBase.cpp +++ b/webkit/WebCore/platform/network/ResourceRequestBase.cpp @@ -39,7 +39,7 @@ ResourceRequestBase::forceTerminate() { s_defaultTimeoutInterval = INT_MAX; } -#elif !USE(SOUP) && (!PLATFORM(COCOA) || USE(CFNETWORK)) +#elif !USE(SOUP) && (!PLATFORM(MAC) || USE(CFNETWORK)) double ResourceRequestBase::s_defaultTimeoutInterval = INT_MAX; #else // Will use NSURLRequest default timeout unless set to a non-zero value with setDefaultTimeoutInterval(). diff --git a/webkit/WebCore/platform/network/ResourceResponseBase.cpp b/webkit/WebCore/platform/network/ResourceResponseBase.cpp index 5c6f8669f..887fec4fa 100755 --- a/webkit/WebCore/platform/network/ResourceResponseBase.cpp +++ b/webkit/WebCore/platform/network/ResourceResponseBase.cpp @@ -194,6 +194,19 @@ String ResourceResponseBase::suggestedFilename() const return static_cast(this)->platformSuggestedFilename(); } +String ResourceResponseBase::sanitizeSuggestedFilename(const String& suggestedFilename) +{ + if (suggestedFilename.isEmpty()) + return suggestedFilename; + + ResourceResponse response(URL(ParsedURLString, "http://example.com/"), String(), -1, String()); + response.setHTTPStatusCode(200); + String escapedSuggestedFilename = String(suggestedFilename).replace('\"', "\\\""); + String value = makeString("attachment; filename=\"", escapedSuggestedFilename, '"'); + response.setHTTPHeaderField(HTTPHeaderName::ContentDisposition, value); + return response.suggestedFilename(); +} + int ResourceResponseBase::httpStatusCode() const { lazyInit(CommonFieldsOnly); diff --git a/webkit/WebCore/platform/network/ResourceResponseBase.h b/webkit/WebCore/platform/network/ResourceResponseBase.h index 2b184026c..a2f3e0192 100755 --- a/webkit/WebCore/platform/network/ResourceResponseBase.h +++ b/webkit/WebCore/platform/network/ResourceResponseBase.h @@ -94,6 +94,7 @@ class ResourceResponseBase { WEBCORE_EXPORT bool isAttachment() const; WEBCORE_EXPORT String suggestedFilename() const; + WEBCORE_EXPORT static String sanitizeSuggestedFilename(const String&); WEBCORE_EXPORT void includeCertificateInfo() const; bool containsCertificateInfo() const { return m_includesCertificateInfo; } diff --git a/webkit/WebCore/platform/network/cf/ResourceResponse.h b/webkit/WebCore/platform/network/cf/ResourceResponse.h index acc1d4569..48300d97e 100755 --- a/webkit/WebCore/platform/network/cf/ResourceResponse.h +++ b/webkit/WebCore/platform/network/cf/ResourceResponse.h @@ -112,6 +112,10 @@ class ResourceResponse : public ResourceResponseBase { unsigned m_initLevel : 3; bool m_platformResponseIsUpToDate : 1; +#if USE(QUICK_LOOK) + bool m_isQuickLook { false }; +#endif + #if USE(CFNETWORK) mutable RetainPtr m_cfResponse; #endif diff --git a/webkit/WebCore/platform/spi/cf/CFNetworkSPI.h b/webkit/WebCore/platform/spi/cf/CFNetworkSPI.h index 8372a977b..0100259f9 100755 --- a/webkit/WebCore/platform/spi/cf/CFNetworkSPI.h +++ b/webkit/WebCore/platform/spi/cf/CFNetworkSPI.h @@ -88,8 +88,6 @@ EXTERN_C void _CFCachedURLResponseSetBecameFileBackedCallBackBlock(CFCachedURLRe #endif #endif // PLATFORM(COCOA) -EXTERN_C void CFURLConnectionInvalidateConnectionCache(); - EXTERN_C CFStringRef const kCFHTTPCookieLocalFileDomain; // FIXME: We should only forward declare this SPI when building for iOS without the Apple Internal SDK. diff --git a/webkit/WebCore/platform/spi/cocoa/PassKitSPI.h b/webkit/WebCore/platform/spi/cocoa/PassKitSPI.h new file mode 100755 index 000000000..65465452c --- /dev/null +++ b/webkit/WebCore/platform/spi/cocoa/PassKitSPI.h @@ -0,0 +1,213 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#if USE(APPLE_INTERNAL_SDK) + +#import +#import +#import + +#else + +#if PLATFORM(MAC) + +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +typedef NS_OPTIONS(NSUInteger, PKAddressField) { + PKAddressFieldNone = 0UL, + PKAddressFieldPostalAddress = 1UL << 0, + PKAddressFieldPhone = 1UL << 1, + PKAddressFieldEmail = 1UL << 2, + PKAddressFieldName = 1UL << 3, + PKAddressFieldAll = (PKAddressFieldPostalAddress|PKAddressFieldPhone|PKAddressFieldEmail|PKAddressFieldName) +}; + +typedef NS_OPTIONS(NSUInteger, PKMerchantCapability) { + PKMerchantCapability3DS = 1UL << 0, + PKMerchantCapabilityEMV = 1UL << 1, + PKMerchantCapabilityCredit = 1UL << 2, + PKMerchantCapabilityDebit = 1UL << 3 +}; + +typedef NS_ENUM(NSInteger, PKPaymentAuthorizationStatus) { + PKPaymentAuthorizationStatusSuccess, + PKPaymentAuthorizationStatusFailure, + PKPaymentAuthorizationStatusInvalidBillingPostalAddress, + PKPaymentAuthorizationStatusInvalidShippingPostalAddress, + PKPaymentAuthorizationStatusInvalidShippingContact, + PKPaymentAuthorizationStatusPINRequired, + PKPaymentAuthorizationStatusPINIncorrect, + PKPaymentAuthorizationStatusPINLockout, +}; + +typedef NS_ENUM(NSUInteger, PKPaymentMethodType) { + PKPaymentMethodTypeUnknown = 0, + PKPaymentMethodTypeDebit, + PKPaymentMethodTypeCredit, + PKPaymentMethodTypePrepaid, + PKPaymentMethodTypeStore +}; + +typedef NS_ENUM(NSUInteger, PKPaymentPassActivationState) { + PKPaymentPassActivationStateActivated, + PKPaymentPassActivationStateRequiresActivation, + PKPaymentPassActivationStateActivating, + PKPaymentPassActivationStateSuspended, + PKPaymentPassActivationStateDeactivated +}; + +typedef NS_ENUM(NSUInteger, PKPaymentSummaryItemType) { + PKPaymentSummaryItemTypeFinal, + PKPaymentSummaryItemTypePending +}; + +typedef NS_ENUM(NSUInteger, PKShippingType) { + PKShippingTypeShipping, + PKShippingTypeDelivery, + PKShippingTypeStorePickup, + PKShippingTypeServicePickup +}; + +typedef NSString * PKPaymentNetwork NS_EXTENSIBLE_STRING_ENUM; + +@protocol PKPaymentAuthorizationViewControllerDelegate; + +@interface PKObject : NSObject +@end + +@interface PKPass : PKObject +@end + +@interface PKPaymentPass : PKPass +@property (nonatomic, copy, readonly) NSString *primaryAccountIdentifier; +@property (nonatomic, copy, readonly) NSString *primaryAccountNumberSuffix; +@property (weak, readonly) NSString *deviceAccountIdentifier; +@property (weak, readonly) NSString *deviceAccountNumberSuffix; +@property (nonatomic, readonly) PKPaymentPassActivationState activationState; +@end + +@interface PKPaymentMethod : NSObject +@property (nonatomic, copy, readonly, nullable) NSString *displayName; +@property (nonatomic, copy, readonly, nullable) PKPaymentNetwork network; +@property (nonatomic, readonly) PKPaymentMethodType type; +@property (nonatomic, copy, readonly, nullable) PKPaymentPass *paymentPass; +@end + +@interface PKPaymentToken : NSObject +@property (nonatomic, strong, readonly) PKPaymentMethod *paymentMethod; +@property (nonatomic, copy, readonly) NSString *transactionIdentifier; +@property (nonatomic, copy, readonly) NSData *paymentData; +@end + +@interface PKContact : NSObject +@property (nonatomic, strong, nullable) NSPersonNameComponents *name; +@property (nonatomic, strong, nullable) CNPostalAddress *postalAddress; +@property (nonatomic, strong, nullable) NSString *emailAddress; +@property (nonatomic, strong, nullable) CNPhoneNumber *phoneNumber; +@property (nonatomic, retain, nullable) NSString *supplementarySubLocality; +@end + +@interface PKPayment : NSObject +@property (nonatomic, strong, readonly, nonnull) PKPaymentToken *token; +@property (nonatomic, strong, readonly, nullable) PKContact *billingContact; +@property (nonatomic, strong, readonly, nullable) PKContact *shippingContact; +@end + +@interface PKPaymentSummaryItem : NSObject ++ (instancetype)summaryItemWithLabel:(NSString *)label amount:(NSDecimalNumber *)amount; ++ (instancetype)summaryItemWithLabel:(NSString *)label amount:(NSDecimalNumber *)amount type:(PKPaymentSummaryItemType)type; +@property (nonatomic, copy) NSString *label; +@property (nonatomic, copy) NSDecimalNumber *amount; +@end + +@interface PKShippingMethod : PKPaymentSummaryItem +@property (nonatomic, copy, nullable) NSString *identifier; +@property (nonatomic, copy, nullable) NSString *detail; +@end + +@interface PKPaymentRequest : NSObject +@property (nonatomic, copy) NSString *countryCode; +@property (nonatomic, copy) NSArray *supportedNetworks; +@property (nonatomic, assign) PKMerchantCapability merchantCapabilities; +@property (nonatomic, copy) NSArray *paymentSummaryItems; +@property (nonatomic, copy) NSString *currencyCode; +@property (nonatomic, assign) PKAddressField requiredBillingAddressFields; +@property (nonatomic, strong, nullable) PKContact *billingContact; +@property (nonatomic, assign) PKAddressField requiredShippingAddressFields; +@property (nonatomic, strong, nullable) PKContact *shippingContact; +@property (nonatomic, copy, nullable) NSArray *shippingMethods; +@property (nonatomic, assign) PKShippingType shippingType; +@property (nonatomic, copy, nullable) NSData *applicationData; +@end + +@interface PKPaymentAuthorizationViewController : NSViewController ++ (void)requestViewControllerWithPaymentRequest:(PKPaymentRequest *)paymentRequest completion:(void(^)(PKPaymentAuthorizationViewController *viewController, NSError *error))completion; ++ (BOOL)canMakePayments; +@property (nonatomic, assign, nullable) id delegate; +@end + +@protocol PKPaymentAuthorizationViewControllerDelegate +@required +- (void)paymentAuthorizationViewController:(PKPaymentAuthorizationViewController *)controller didAuthorizePayment:(PKPayment *)payment completion:(void (^)(PKPaymentAuthorizationStatus status))completion; +- (void)paymentAuthorizationViewControllerDidFinish:(PKPaymentAuthorizationViewController *)controller; + +@optional +- (void)paymentAuthorizationViewController:(PKPaymentAuthorizationViewController *)controller didSelectShippingMethod:(PKShippingMethod *)shippingMethod completion:(void (^)(PKPaymentAuthorizationStatus status, NSArray *summaryItems))completion; +- (void)paymentAuthorizationViewController:(PKPaymentAuthorizationViewController *)controller didSelectShippingContact:(PKContact *)contact completion:(void (^)(PKPaymentAuthorizationStatus status, NSArray *shippingMethods, NSArray *summaryItems))completion; +- (void)paymentAuthorizationViewController:(PKPaymentAuthorizationViewController *)controller didSelectPaymentMethod:(PKPaymentMethod *)paymentMethod completion:(void (^)(NSArray *summaryItems))completion; +@end + +NS_ASSUME_NONNULL_END + +#endif + +NS_ASSUME_NONNULL_BEGIN + +@protocol PKPaymentAuthorizationViewControllerPrivateDelegate; + +@interface PKPaymentMerchantSession : NSObject +- (instancetype)initWithDictionary:(NSDictionary *)dictionary; +@end + +@interface PKPaymentAuthorizationViewController () ++ (void)paymentServicesMerchantURL:(void(^)(NSURL *merchantURL, NSError *error))completion; +@property (nonatomic, assign, nullable) id privateDelegate; +@end + +@protocol PKPaymentAuthorizationViewControllerPrivateDelegate +- (void)paymentAuthorizationViewController:(PKPaymentAuthorizationViewController *)controller willFinishWithError:(NSError *)error; + +@optional +- (void)paymentAuthorizationViewController:(PKPaymentAuthorizationViewController *)controller didRequestMerchantSession:(void(^)(PKPaymentMerchantSession *, NSError *))sessionBlock; +@end + +NS_ASSUME_NONNULL_END + +#endif diff --git a/webkit/WebCore/rendering/PaintPhase.h b/webkit/WebCore/rendering/PaintPhase.h index d46fc4ed4..6e8033047 100755 --- a/webkit/WebCore/rendering/PaintPhase.h +++ b/webkit/WebCore/rendering/PaintPhase.h @@ -54,15 +54,16 @@ enum PaintPhase { }; enum PaintBehaviorFlags { - PaintBehaviorNormal = 0, - PaintBehaviorSelectionOnly = 1 << 0, - PaintBehaviorForceBlackText = 1 << 1, - PaintBehaviorForceWhiteText = 1 << 2, - PaintBehaviorFlattenCompositingLayers = 1 << 3, - PaintBehaviorRenderingSVGMask = 1 << 4, - PaintBehaviorSkipRootBackground = 1 << 5, - PaintBehaviorRootBackgroundOnly = 1 << 6, - PaintBehaviorSelectionAndBackgroundsOnly = 1 << 7, + PaintBehaviorNormal = 0, + PaintBehaviorSelectionOnly = 1 << 0, + PaintBehaviorSkipSelectionHighlight = 1 << 1, + PaintBehaviorForceBlackText = 1 << 2, + PaintBehaviorForceWhiteText = 1 << 3, + PaintBehaviorFlattenCompositingLayers = 1 << 4, + PaintBehaviorRenderingSVGMask = 1 << 5, + PaintBehaviorSkipRootBackground = 1 << 6, + PaintBehaviorRootBackgroundOnly = 1 << 7, + PaintBehaviorSelectionAndBackgroundsOnly = 1 << 8, }; typedef unsigned PaintBehavior; diff --git a/webkit/WebCore/rendering/RenderBlockFlow.cpp b/webkit/WebCore/rendering/RenderBlockFlow.cpp index 337977e1d..2ce8c099d 100755 --- a/webkit/WebCore/rendering/RenderBlockFlow.cpp +++ b/webkit/WebCore/rendering/RenderBlockFlow.cpp @@ -1999,6 +1999,10 @@ void RenderBlockFlow::styleDidChange(StyleDifference diff, const RenderStyle* ol parentBlock->markAllDescendantsWithFloatsForLayout(); parentBlock->markSiblingsWithFloatsForLayout(); } + // Fresh floats need to be reparented if they actually belong to the previous anonymous block. + // It copies the logic of RenderBlock::addChildIgnoringContinuation + if (noLongerAffectsParentBlock() && style().isFloating() && previousSibling() && previousSibling()->isAnonymousBlock()) + downcast(*parent()).moveChildTo(&downcast(*previousSibling()), this); if (auto fragment = renderNamedFlowFragment()) fragment->setStyle(RenderNamedFlowFragment::createStyle(style())); @@ -3772,11 +3776,10 @@ void RenderBlockFlow::addChild(RenderObject* newChild, RenderObject* beforeChild { if (multiColumnFlowThread()) return multiColumnFlowThread()->addChild(newChild, beforeChild); - if (beforeChild) { - if (RenderFlowThread* containingFlowThread = flowThreadContainingBlock()) - beforeChild = containingFlowThread->resolveMovedChild(beforeChild); - } - RenderBlock::addChild(newChild, beforeChild); + auto* beforeChildOrPlaceholder = beforeChild; + if (auto* containingFlowThread = flowThreadContainingBlock()) + beforeChildOrPlaceholder = containingFlowThread->resolveMovedChild(beforeChild); + RenderBlock::addChild(newChild, beforeChildOrPlaceholder); } void RenderBlockFlow::removeChild(RenderObject& oldChild) diff --git a/webkit/WebCore/rendering/RenderBlockLineLayout.cpp b/webkit/WebCore/rendering/RenderBlockLineLayout.cpp index 28014d3cd..2542074fe 100755 --- a/webkit/WebCore/rendering/RenderBlockLineLayout.cpp +++ b/webkit/WebCore/rendering/RenderBlockLineLayout.cpp @@ -584,12 +584,6 @@ void RenderBlockFlow::updateRubyForJustifiedText(RenderRubyRun& rubyRun, BidiRun rubyRun.clearOverrideLogicalContentWidth(); r.box()->setExpansion(newRubyRunWidth - r.box()->logicalWidth()); - // This relayout caused the size of the RenderRubyText and the RenderRubyBase to change, dependent on the line's current expansion. Next time we relayout the - // RenderRubyRun, make sure that we relayout the RenderRubyBase and RenderRubyText as well. - rubyBase.setNeedsLayout(MarkOnlyThis); - if (RenderRubyText* rubyText = rubyRun.rubyText()) - rubyText->setNeedsLayout(MarkOnlyThis); - totalLogicalWidth += totalExpansion; expansionOpportunityCount -= totalOpportunitiesInRun; } diff --git a/webkit/WebCore/rendering/RenderBox.cpp b/webkit/WebCore/rendering/RenderBox.cpp index 8253b7a08..e5dcd802e 100755 --- a/webkit/WebCore/rendering/RenderBox.cpp +++ b/webkit/WebCore/rendering/RenderBox.cpp @@ -402,13 +402,12 @@ void RenderBox::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle if (isRootRenderer || isBodyRenderer) { // Propagate the new writing mode and direction up to the RenderView. RenderStyle& viewStyle = view().style(); - bool viewChangedWritingMode = false; bool rootStyleChanged = false; - bool viewStyleChanged = false; + bool viewDirectionOrWritingModeChanged = false; RenderObject* rootRenderer = isBodyRenderer ? document().documentElement()->renderer() : nullptr; if (viewStyle.direction() != newStyle.direction() && (isRootRenderer || !document().directionSetOnDocumentElement())) { viewStyle.setDirection(newStyle.direction()); - viewStyleChanged = true; + viewDirectionOrWritingModeChanged = true; if (isBodyRenderer) { rootRenderer->style().setDirection(newStyle.direction()); rootStyleChanged = true; @@ -418,8 +417,7 @@ void RenderBox::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle if (viewStyle.writingMode() != newStyle.writingMode() && (isRootRenderer || !document().writingModeSetOnDocumentElement())) { viewStyle.setWritingMode(newStyle.writingMode()); - viewChangedWritingMode = true; - viewStyleChanged = true; + viewDirectionOrWritingModeChanged = true; view().setHorizontalWritingMode(newStyle.isHorizontalWritingMode()); view().markAllDescendantsWithFloatsForLayout(); if (isBodyRenderer) { @@ -433,13 +431,13 @@ void RenderBox::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle view().frameView().recalculateScrollbarOverlayStyle(); const Pagination& pagination = view().frameView().pagination(); - if (viewChangedWritingMode && pagination.mode != Pagination::Unpaginated) { + if (viewDirectionOrWritingModeChanged && pagination.mode != Pagination::Unpaginated) { viewStyle.setColumnStylesFromPaginationMode(pagination.mode); if (view().multiColumnFlowThread()) view().updateColumnProgressionFromStyle(viewStyle); } - if (viewStyleChanged && view().multiColumnFlowThread()) + if (viewDirectionOrWritingModeChanged && view().multiColumnFlowThread()) view().updateStylesForColumnChildren(); if (rootStyleChanged && is(rootRenderer) && downcast(*rootRenderer).multiColumnFlowThread()) diff --git a/webkit/WebCore/rendering/RenderBoxModelObject.cpp b/webkit/WebCore/rendering/RenderBoxModelObject.cpp index 719269193..d55c32e56 100755 --- a/webkit/WebCore/rendering/RenderBoxModelObject.cpp +++ b/webkit/WebCore/rendering/RenderBoxModelObject.cpp @@ -5,7 +5,7 @@ * (C) 2005, 2006 Samuel Weinig (sam.weinig@gmail.com) * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2013 Apple Inc. All rights reserved. * Copyright (C) 2010 Google Inc. All rights reserved. - * Copyright (c) 2016 ACCESS CO., LTD. All rights reserved. + * Copyright (c) 2016-2017 ACCESS CO., LTD. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -28,6 +28,9 @@ #include "RenderBoxModelObject.h" #include "BorderEdge.h" +#if PLATFORM(WKC) +#include "CachedImage.h" +#endif #include "FloatRoundedRect.h" #include "Frame.h" #include "FrameView.h" @@ -664,6 +667,17 @@ void RenderBoxModelObject::paintFillLayerExtended(const PaintInfo& paintInfo, co StyleImage* bgImage = bgLayer->image(); bool shouldPaintBackgroundImage = bgImage && bgImage->canRender(this, style().effectiveZoom()); +#if PLATFORM(WKC) + // Try to decode bg image here if not yet done, because bg color needs to be drawn if unable to decode bg image. + if (shouldPaintBackgroundImage && (baseBgColorUsage != BaseBackgroundColorOnly)) { + CachedImage* cachedImage = bgImage->cachedImage(); + if (cachedImage) { + RefPtr image = cachedImage->image(); + if (image && image->isBitmapImage() && !image->nativeImageForCurrentFrame()) + shouldPaintBackgroundImage = false; + } + } +#endif bool forceBackgroundToWhite = false; if (document().printing()) { if (style().printColorAdjust() == PrintColorAdjustEconomy) @@ -2607,9 +2621,11 @@ void RenderBoxModelObject::moveChildrenTo(RenderBoxModelObject* toBoxModelObject // Save our next sibling as moveChildTo will clear it. RenderObject* nextSibling = child->nextSibling(); + // FIXME: This logic here fails to detect the first letter in certain cases + // and skips a valid sibling renderer (see webkit.org/b/163737). // Check to make sure we're not saving the firstLetter as the nextSibling. // When the |child| object will be moved, its firstLetter will be recreated, - // so saving it now in nextSibling would let us with a destroyed object. + // so saving it now in nextSibling would leave us with a stale object. if (is(*child) && is(nextSibling)) { RenderObject* firstLetterObj = nullptr; if (RenderBlock* block = downcast(*child).blockForAccompanyingFirstLetter()) { diff --git a/webkit/WebCore/rendering/RenderElement.cpp b/webkit/WebCore/rendering/RenderElement.cpp index 6f95f8834..e5377e51c 100755 --- a/webkit/WebCore/rendering/RenderElement.cpp +++ b/webkit/WebCore/rendering/RenderElement.cpp @@ -835,7 +835,7 @@ void RenderElement::styleWillChange(StyleDifference diff, const RenderStyle& new #endif #if PLATFORM(IOS) && ENABLE(TOUCH_EVENTS) if (visibilityChanged) - document().dirtyTouchEventRects(); + document().setTouchEventRegionsNeedUpdate(); #endif if (visibilityChanged) { if (AXObjectCache* cache = document().existingAXObjectCache()) @@ -1060,9 +1060,6 @@ void RenderElement::willBeRemovedFromTree() removeLayers(layer); } - if (m_style->hasFixedBackgroundImage() && !frame().settings().fixedBackgroundsPaintRelativeToDocument()) - view().frameView().removeSlowRepaintObject(this); - if (isOutOfFlowPositioned() && parent()->childrenInline()) parent()->dirtyLinesFromChangedChild(*this); @@ -1074,6 +1071,9 @@ void RenderElement::willBeRemovedFromTree() void RenderElement::willBeDestroyed() { + if (m_style->hasFixedBackgroundImage() && !frame().settings().fixedBackgroundsPaintRelativeToDocument()) + view().frameView().removeSlowRepaintObject(this); + animation().cancelAnimations(*this); destroyLeftoverChildren(); diff --git a/webkit/WebCore/rendering/RenderElement.h b/webkit/WebCore/rendering/RenderElement.h index d937bb231..0277594f1 100755 --- a/webkit/WebCore/rendering/RenderElement.h +++ b/webkit/WebCore/rendering/RenderElement.h @@ -259,6 +259,8 @@ class RenderElement : public RenderObject { void setRenderBlockFlowHasMarkupTruncation(bool b) { m_renderBlockFlowHasMarkupTruncation = b; } unsigned renderBlockFlowLineLayoutPath() const { return m_renderBlockFlowLineLayoutPath; } bool renderBlockFlowHasMarkupTruncation() const { return m_renderBlockFlowHasMarkupTruncation; } + + bool noLongerAffectsParentBlock() const { return s_noLongerAffectsParentBlock; } private: RenderElement(ContainerNode&, Ref&&, unsigned baseTypeFlags); diff --git a/webkit/WebCore/rendering/RenderEmbeddedObject.cpp b/webkit/WebCore/rendering/RenderEmbeddedObject.cpp index dd24c26bb..28fffee02 100755 --- a/webkit/WebCore/rendering/RenderEmbeddedObject.cpp +++ b/webkit/WebCore/rendering/RenderEmbeddedObject.cpp @@ -427,12 +427,14 @@ bool RenderEmbeddedObject::isReplacementObscured() const if (!rootRenderView) return true; - IntRect rootViewRect = view().frameView().convertToRootView(snappedIntRect(rect)); - + // We should always start hit testing a clean tree. + view().frameView().updateLayoutAndStyleIfNeededRecursive(); + HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::IgnoreClipping | HitTestRequest::DisallowShadowContent | HitTestRequest::AllowChildFrameContent); HitTestResult result; HitTestLocation location; + IntRect rootViewRect = view().frameView().convertToRootView(snappedIntRect(rect)); LayoutUnit x = rootViewRect.x(); LayoutUnit y = rootViewRect.y(); LayoutUnit width = rootViewRect.width(); diff --git a/webkit/WebCore/rendering/RenderInline.cpp b/webkit/WebCore/rendering/RenderInline.cpp index 6b0755e8b..5b86acb59 100755 --- a/webkit/WebCore/rendering/RenderInline.cpp +++ b/webkit/WebCore/rendering/RenderInline.cpp @@ -261,9 +261,12 @@ LayoutRect RenderInline::localCaretRect(InlineBox* inlineBox, int, LayoutUnit* e void RenderInline::addChild(RenderObject* newChild, RenderObject* beforeChild) { + auto* beforeChildOrPlaceholder = beforeChild; + if (auto* flowThread = flowThreadContainingBlock()) + beforeChildOrPlaceholder = flowThread->resolveMovedChild(beforeChild); if (continuation()) - return addChildToContinuation(newChild, beforeChild); - return addChildIgnoringContinuation(newChild, beforeChild); + return addChildToContinuation(newChild, beforeChildOrPlaceholder); + return addChildIgnoringContinuation(newChild, beforeChildOrPlaceholder); } static RenderBoxModelObject* nextContinuation(RenderObject* renderer) diff --git a/webkit/WebCore/rendering/RenderLayer.cpp b/webkit/WebCore/rendering/RenderLayer.cpp index 4ced18d70..7e9efd097 100755 --- a/webkit/WebCore/rendering/RenderLayer.cpp +++ b/webkit/WebCore/rendering/RenderLayer.cpp @@ -2469,7 +2469,7 @@ void RenderLayer::scrollTo(int x, int y) } #if PLATFORM(IOS) && ENABLE(TOUCH_EVENTS) - renderer().document().dirtyTouchEventRects(); + renderer().document().setTouchEventRegionsNeedUpdate(); #endif DebugPageOverlays::didLayout(renderer().frame()); } @@ -6877,7 +6877,7 @@ void RenderLayer::styleChanged(StyleDifference diff, const RenderStyle* oldStyle #if PLATFORM(IOS) && ENABLE(TOUCH_EVENTS) if (diff == StyleDifferenceRecompositeLayer || diff >= StyleDifferenceLayoutPositionedMovementOnly) - renderer().document().dirtyTouchEventRects(); + renderer().document().setTouchEventRegionsNeedUpdate(); #else UNUSED_PARAM(diff); #endif diff --git a/webkit/WebCore/rendering/RenderLayerBacking.cpp b/webkit/WebCore/rendering/RenderLayerBacking.cpp index 72231edd2..dfd50a6ac 100755 --- a/webkit/WebCore/rendering/RenderLayerBacking.cpp +++ b/webkit/WebCore/rendering/RenderLayerBacking.cpp @@ -2163,6 +2163,10 @@ GraphicsLayer* RenderLayerBacking::childForSuperlayers() const bool RenderLayerBacking::paintsIntoWindow() const { +#if USE(COORDINATED_GRAPHICS_THREADED) + return false; +#endif + if (m_usingTiledCacheLayer) return false; diff --git a/webkit/WebCore/rendering/RenderLayerCompositor.cpp b/webkit/WebCore/rendering/RenderLayerCompositor.cpp index 98b0dd730..2ca587c0a 100755 --- a/webkit/WebCore/rendering/RenderLayerCompositor.cpp +++ b/webkit/WebCore/rendering/RenderLayerCompositor.cpp @@ -1,6 +1,6 @@ /* * Copyright (C) 2009, 2010 Apple Inc. All rights reserved. - * Copyright (c) 2013 ACCESS CO., LTD. All rights reserved. + * Copyright (c) 2013-2017 ACCESS CO., LTD. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -298,7 +298,6 @@ RenderLayerCompositor::RenderLayerCompositor(RenderView& renderView) , m_layerFlushThrottlingEnabled(false) , m_layerFlushThrottlingTemporarilyDisabledForInteraction(false) , m_hasPendingLayerFlush(false) - , m_paintRelatedMilestonesTimer(*this, &RenderLayerCompositor::paintRelatedMilestonesTimerFired) { } @@ -589,8 +588,8 @@ void RenderLayerCompositor::didPaintBacking(RenderLayerBacking*) { FrameView& frameView = m_renderView.frameView(); frameView.setLastPaintTime(monotonicallyIncreasingTime()); - if (frameView.milestonesPendingPaint() && !m_paintRelatedMilestonesTimer.isActive()) - m_paintRelatedMilestonesTimer.startOneShot(0); + if (frameView.milestonesPendingPaint()) + frameView.firePaintRelatedMilestonesIfNeeded(); } void RenderLayerCompositor::didChangeVisibleRect() @@ -863,7 +862,7 @@ void RenderLayerCompositor::logLayerInfo(const RenderLayer& layer, int depth) absoluteBounds.move(layer.offsetFromAncestor(m_renderView.layer())); StringBuilder logString; - logString.append(String::format("%*p (%.6f,%.6f-%.6f,%.6f) %.2fKB", 12 + depth * 2, &layer, + logString.append(String::format("%*p (%.3f,%.3f-%.3f,%.3f) %.2fKB", 12 + depth * 2, &layer, absoluteBounds.x().toFloat(), absoluteBounds.y().toFloat(), absoluteBounds.maxX().toFloat(), absoluteBounds.maxY().toFloat(), backing->backingStoreMemoryEstimate() / 1024)); @@ -2316,6 +2315,7 @@ bool RenderLayerCompositor::requiresCompositingLayer(const RenderLayer& layer, R || clipsCompositingDescendants(*renderer.layer()) || requiresCompositingForAnimation(renderer) || requiresCompositingForFilters(renderer) + || requiresCompositingForWillChange(renderer) || requiresCompositingForPosition(renderer, *renderer.layer(), viewportConstrainedNotCompositedReason) || requiresCompositingForOverflowScrolling(*renderer.layer()); if (ret) @@ -2682,7 +2682,8 @@ bool RenderLayerCompositor::requiresCompositingForCanvas(RenderLayerModelObject& bool isCanvasLargeEnoughToForceCompositing = true; #else HTMLCanvasElement* canvas = downcast(renderer.element()); - bool isCanvasLargeEnoughToForceCompositing = canvas->size().area() >= canvasAreaThresholdRequiringCompositing; + auto canvasArea = canvas->size().area(); + bool isCanvasLargeEnoughToForceCompositing = !canvasArea.hasOverflowed() && canvasArea.unsafeGet() >= canvasAreaThresholdRequiringCompositing; #endif CanvasCompositingStrategy compositingStrategy = canvasCompositingStrategy(renderer); return compositingStrategy == CanvasAsLayerContents || (compositingStrategy == CanvasPaintedToLayer && isCanvasLargeEnoughToForceCompositing); @@ -4361,20 +4362,6 @@ void RenderLayerCompositor::layerFlushTimerFired() scheduleLayerFlushNow(); } -void RenderLayerCompositor::paintRelatedMilestonesTimerFired() -{ - Frame& frame = m_renderView.frameView().frame(); - Page* page = frame.page(); - if (!page) - return; - - // If the layer tree is frozen, we'll paint when it's unfrozen and schedule the timer again. - if (page->chrome().client().layerTreeStateIsFrozen()) - return; - - m_renderView.frameView().firePaintRelatedMilestonesIfNeeded(); -} - #if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR) RefPtr RenderLayerCompositor::createDisplayRefreshMonitor(PlatformDisplayID displayID) const { diff --git a/webkit/WebCore/rendering/RenderLayerCompositor.h b/webkit/WebCore/rendering/RenderLayerCompositor.h index 14f860eca..d1b070dc0 100755 --- a/webkit/WebCore/rendering/RenderLayerCompositor.h +++ b/webkit/WebCore/rendering/RenderLayerCompositor.h @@ -478,8 +478,6 @@ class RenderLayerCompositor final : public GraphicsLayerClient, public GraphicsL void startLayerFlushTimerIfNeeded(); void layerFlushTimerFired(); - void paintRelatedMilestonesTimerFired(); - #if !LOG_DISABLED const char* logReasonsForCompositing(const RenderLayer&); void logLayerInfo(const RenderLayer&, int depth); @@ -557,8 +555,6 @@ class RenderLayerCompositor final : public GraphicsLayerClient, public GraphicsL bool m_layerNeedsCompositingUpdate { false }; bool m_viewBackgroundIsTransparent { false }; - Timer m_paintRelatedMilestonesTimer; - #if !LOG_DISABLED int m_rootLayerUpdateCount { 0 }; int m_obligateCompositedLayerCount { 0 }; // count of layer that have to be composited. diff --git a/webkit/WebCore/rendering/RenderLineBoxList.cpp b/webkit/WebCore/rendering/RenderLineBoxList.cpp index bd0550531..ced9c4672 100755 --- a/webkit/WebCore/rendering/RenderLineBoxList.cpp +++ b/webkit/WebCore/rendering/RenderLineBoxList.cpp @@ -331,8 +331,8 @@ void RenderLineBoxList::dirtyLinesFromChangedChild(RenderBoxModelObject& contain return; } - // Try to figure out which line box we belong in. First try to find a previous - // line box by examining our siblings. If we didn't find a line box, then use our + // Try to figure out which line box we belong in. First try to find a previous + // line box by examining our siblings. If we didn't find a line box, then use our // parent's first line box. RootInlineBox* box = nullptr; RenderObject* current; @@ -378,11 +378,11 @@ void RenderLineBoxList::dirtyLinesFromChangedChild(RenderBoxModelObject& contain if (box) { box->markDirty(); - // dirty the adjacent lines that might be affected + // Dirty the adjacent lines that might be affected. // NOTE: we dirty the previous line because RootInlineBox objects cache // the address of the first object on the next line after a BR, which we may be - // invalidating here. For more info, see how RenderBlock::layoutInlineChildren - // calls setLineBreakInfo with the result of findNextLineBreak. findNextLineBreak, + // invalidating here. For more info, see how RenderBlock::layoutInlineChildren + // calls setLineBreakInfo with the result of findNextLineBreak. findNextLineBreak, // despite the name, actually returns the first RenderObject after the BR. // "Typing after pasting line does not appear until after window resize." if (RootInlineBox* prevBox = box->prevRootBox()) @@ -390,8 +390,18 @@ void RenderLineBoxList::dirtyLinesFromChangedChild(RenderBoxModelObject& contain // FIXME: We shouldn't need to always dirty the next line. This is only strictly // necessary some of the time, in situations involving BRs. - if (RootInlineBox* nextBox = box->nextRootBox()) + if (RootInlineBox* nextBox = box->nextRootBox()) { nextBox->markDirty(); + + // Dedicated linebox for floats may be added as the last rootbox. If this occurs with BRs inside inlines that propagte their lineboxes to + // the parent flow, we need to invalidate it explicitly. + // FIXME: We should be able to figure out the actual "changed child" even when we are calling through empty inlines recursively. + if (is(child) && !downcast(child).firstLineBoxIncludingCulling()) { + auto* lastRootBox = nextBox->blockFlow().lastRootBox(); + if (lastRootBox->isTrailingFloatsRootInlineBox() && !lastRootBox->isDirty()) + lastRootBox->markDirty(); + } + } } } diff --git a/webkit/WebCore/rendering/RenderMultiColumnFlowThread.cpp b/webkit/WebCore/rendering/RenderMultiColumnFlowThread.cpp index 078b4b53b..84c4f8625 100755 --- a/webkit/WebCore/rendering/RenderMultiColumnFlowThread.cpp +++ b/webkit/WebCore/rendering/RenderMultiColumnFlowThread.cpp @@ -217,6 +217,9 @@ void RenderMultiColumnFlowThread::willBeRemovedFromTree() RenderObject* RenderMultiColumnFlowThread::resolveMovedChild(RenderObject* child) const { + if (!child) + return nullptr; + if (child->style().columnSpan() != ColumnSpanAll || !is(*child)) { // We only need to resolve for column spanners. return child; diff --git a/webkit/WebCore/rendering/RenderObject.h b/webkit/WebCore/rendering/RenderObject.h index 5f6dcb322..a7aa0497f 100755 --- a/webkit/WebCore/rendering/RenderObject.h +++ b/webkit/WebCore/rendering/RenderObject.h @@ -336,6 +336,7 @@ class RenderObject : public CachedImageClient { virtual bool isTextControl() const { return false; } virtual bool isTextArea() const { return false; } virtual bool isTextField() const { return false; } + virtual bool isSearchField() const { return false; } virtual bool isTextControlInnerBlock() const { return false; } virtual bool isVideo() const { return false; } virtual bool isWidget() const { return false; } @@ -478,7 +479,7 @@ class RenderObject : public CachedImageClient { // RenderBlock::createAnonymousBlock(). This includes creating an anonymous // RenderBlock having a BLOCK or BOX display. Other classes such as RenderTextFragment // are not RenderBlocks and will return false. See https://bugs.webkit.org/show_bug.cgi?id=56709. - return isAnonymous() && (style().display() == BLOCK || style().display() == BOX) && style().styleType() == NOPSEUDO && isRenderBlock() && !isListMarker() && !isRenderFlowThread() && !isRenderMultiColumnSet() && !isRenderView() + return isAnonymous() && (style().display() == BLOCK || style().display() == BOX) && style().styleType() == NOPSEUDO && isRenderBlock() && !isListMarker() && !isRenderFlowThread() && !isRenderNamedFlowFragment() && !isRenderMultiColumnSet() && !isRenderView() #if ENABLE(FULLSCREEN_API) && !isRenderFullScreen() && !isRenderFullScreenPlaceholder() diff --git a/webkit/WebCore/rendering/RenderRubyRun.cpp b/webkit/WebCore/rendering/RenderRubyRun.cpp index f66d748be..3a04f8940 100755 --- a/webkit/WebCore/rendering/RenderRubyRun.cpp +++ b/webkit/WebCore/rendering/RenderRubyRun.cpp @@ -235,15 +235,26 @@ void RenderRubyRun::layout() { if (RenderRubyBase* base = rubyBase()) base->reset(); - RenderBlockFlow::layout(); - +} + +void RenderRubyRun::layoutBlock(bool relayoutChildren, LayoutUnit pageHeight) +{ + if (!relayoutChildren) { + // Since the extra relayout in RenderBlockFlow::updateRubyForJustifiedText() causes the size of the RenderRubyText/RenderRubyBase + // dependent on the line's current expansion, whenever we relayout the RenderRubyRun, we need to relayout the RenderRubyBase/RenderRubyText as well. + // FIXME: We should take the expansion opportunities into account if possible. + relayoutChildren = style().textAlign() == JUSTIFY; + } + + RenderBlockFlow::layoutBlock(relayoutChildren, pageHeight); + RenderRubyText* rt = rubyText(); if (!rt) return; rt->setLogicalLeft(0); - + // Place the RenderRubyText such that its bottom is flush with the lineTop of the first line of the RenderRubyBase. LayoutUnit lastLineRubyTextBottom = rt->logicalHeight(); LayoutUnit firstLineRubyTextTop = 0; diff --git a/webkit/WebCore/rendering/RenderRubyRun.h b/webkit/WebCore/rendering/RenderRubyRun.h index 65cf224a5..2d1f31476 100755 --- a/webkit/WebCore/rendering/RenderRubyRun.h +++ b/webkit/WebCore/rendering/RenderRubyRun.h @@ -55,6 +55,7 @@ class RenderRubyRun final : public RenderBlockFlow { virtual RenderObject* layoutSpecialExcludedChild(bool relayoutChildren) override; virtual void layout() override; + void layoutBlock(bool relayoutChildren, LayoutUnit pageHeight = 0) override; virtual bool isChildAllowed(const RenderObject&, const RenderStyle&) const override; virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0) override; diff --git a/webkit/WebCore/rendering/RenderSearchField.h b/webkit/WebCore/rendering/RenderSearchField.h index bc0ca9cae..6a1ac918c 100755 --- a/webkit/WebCore/rendering/RenderSearchField.h +++ b/webkit/WebCore/rendering/RenderSearchField.h @@ -46,6 +46,8 @@ class RenderSearchField final : public RenderTextControlSingleLine, private Popu void hidePopup(); private: + bool isSearchField() const final { return true; } + virtual void centerContainerIfNeeded(RenderBox*) const override; virtual LayoutUnit computeControlLogicalHeight(LayoutUnit lineHeight, LayoutUnit nonContentHeight) const override; virtual LayoutUnit computeLogicalHeightLimit() const override; @@ -92,6 +94,6 @@ class RenderSearchField final : public RenderTextControlSingleLine, private Popu } // namespace WebCore -SPECIALIZE_TYPE_TRAITS_RENDER_OBJECT(RenderSearchField, isTextField()) +SPECIALIZE_TYPE_TRAITS_RENDER_OBJECT(RenderSearchField, isSearchField()) #endif diff --git a/webkit/WebCore/rendering/RenderTextFragment.cpp b/webkit/WebCore/rendering/RenderTextFragment.cpp index 5d29b4457..744d47461 100755 --- a/webkit/WebCore/rendering/RenderTextFragment.cpp +++ b/webkit/WebCore/rendering/RenderTextFragment.cpp @@ -25,6 +25,7 @@ #include "RenderBlock.h" #include "RenderIterator.h" +#include "RenderMultiColumnFlowThread.h" #include "Text.h" namespace WebCore { @@ -112,6 +113,8 @@ RenderBlock* RenderTextFragment::blockForAccompanyingFirstLetter() if (!m_firstLetter) return nullptr; for (auto& block : ancestorsOfType(*m_firstLetter)) { + if (is(block)) + break; if (block.style().hasPseudoStyle(FIRST_LETTER) && block.canHaveChildren()) return █ } diff --git a/webkit/WebCore/rendering/RenderView.cpp b/webkit/WebCore/rendering/RenderView.cpp index 14808f73e..71775b0e6 100755 --- a/webkit/WebCore/rendering/RenderView.cpp +++ b/webkit/WebCore/rendering/RenderView.cpp @@ -51,6 +51,7 @@ #include "StyleInheritedData.h" #include "TransformState.h" #include +#include namespace WebCore { @@ -129,6 +130,7 @@ struct SelectionIterator { RenderView::RenderView(Document& document, Ref&& style) : RenderBlockFlow(document, WTF::move(style)) , m_frameView(*document.view()) + , m_weakFactory(this) , m_selectionUnsplitStart(nullptr) , m_selectionUnsplitEnd(nullptr) , m_selectionUnsplitStartPos(-1) @@ -144,6 +146,9 @@ RenderView::RenderView(Document& document, Ref&& style) , m_renderCounterCount(0) , m_selectionWasCaret(false) , m_hasSoftwareFilters(false) +#if !ASSERT_DISABLED + , m_inHitTesting(false) +#endif #if ENABLE(SERVICE_CONTROLS) , m_selectionRectGatherer(*this) #endif @@ -208,6 +213,10 @@ bool RenderView::hitTest(const HitTestRequest& request, HitTestResult& result) bool RenderView::hitTest(const HitTestRequest& request, const HitTestLocation& location, HitTestResult& result) { document().updateLayout(); + +#if !ASSERT_DISABLED + TemporaryChange hitTestRestorer { m_inHitTesting, true }; +#endif FrameFlatteningLayoutDisallower disallower(frameView()); @@ -1430,10 +1439,15 @@ void RenderView::resumePausedImageAnimationsIfNeeded(IntRect visibleRect) } RenderView::RepaintRegionAccumulator::RepaintRegionAccumulator(RenderView* view) - : m_rootView(view ? view->document().topDocument().renderView() : nullptr) { - if (!m_rootView) + if (!view) return; + + auto* rootRenderView = view->document().topDocument().renderView(); + if (!rootRenderView) + return; + + m_rootView = rootRenderView->createWeakPtr(); m_wasAccumulatingRepaintRegion = !!m_rootView->m_accumulatedRepaintRegion; if (!m_wasAccumulatingRepaintRegion) m_rootView->m_accumulatedRepaintRegion = std::make_unique(); diff --git a/webkit/WebCore/rendering/RenderView.h b/webkit/WebCore/rendering/RenderView.h index 30b310242..9f1969f7b 100755 --- a/webkit/WebCore/rendering/RenderView.h +++ b/webkit/WebCore/rendering/RenderView.h @@ -1,6 +1,6 @@ /* * Copyright (C) 1999 Lars Knoll (knoll@kde.org) - * Copyright (C) 2006, 2015 Apple Inc. + * Copyright (C) 2006, 2015-2016 Apple Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -235,10 +235,12 @@ class RenderView final : public RenderBlockFlow, public SelectionSubtreeRoot { ~RepaintRegionAccumulator(); private: - RenderView* m_rootView; + WeakPtr m_rootView; bool m_wasAccumulatingRepaintRegion; }; + WeakPtr createWeakPtr() { return m_weakFactory.createWeakPtr(); } + void scheduleLazyRepaint(RenderBox&); void unscheduleLazyRepaint(RenderBox&); @@ -251,6 +253,10 @@ class RenderView final : public RenderBlockFlow, public SelectionSubtreeRoot { const HashSet& boxesWithScrollSnapCoordinates() { return m_boxesWithScrollSnapCoordinates; } #endif +#if !ASSERT_DISABLED + bool inHitTesting() const { return m_inHitTesting; } +#endif + protected: virtual void mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState&, MapCoordinatesFlags, bool* wasFixed) const override; virtual const RenderObject* pushMappingToContainer(const RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap&) const override; @@ -317,6 +323,7 @@ class RenderView final : public RenderBlockFlow, public SelectionSubtreeRoot { private: FrameView& m_frameView; + WeakPtrFactory m_weakFactory; RenderObject* m_selectionUnsplitStart; RenderObject* m_selectionUnsplitEnd; int m_selectionUnsplitStartPos; @@ -366,6 +373,9 @@ class RenderView final : public RenderBlockFlow, public SelectionSubtreeRoot { bool m_selectionWasCaret; bool m_hasSoftwareFilters; +#if !ASSERT_DISABLED + bool m_inHitTesting; +#endif HashSet m_renderersWithPausedImageAnimation; Vector> m_protectedRenderWidgets; diff --git a/webkit/WebCore/rendering/RootInlineBox.h b/webkit/WebCore/rendering/RootInlineBox.h index 52a3d5125..1bceda840 100755 --- a/webkit/WebCore/rendering/RootInlineBox.h +++ b/webkit/WebCore/rendering/RootInlineBox.h @@ -190,6 +190,8 @@ class RootInlineBox : public InlineFlowBox { Node* getLogicalStartBoxWithNode(InlineBox*&) const; Node* getLogicalEndBoxWithNode(InlineBox*&) const; + virtual bool isTrailingFloatsRootInlineBox() const { return false; } + #if ENABLE(TREE_DEBUGGING) virtual const char* boxName() const override final; #endif diff --git a/webkit/WebCore/rendering/SimpleLineLayout.cpp b/webkit/WebCore/rendering/SimpleLineLayout.cpp index 7e0cb33f7..ba54bcc61 100755 --- a/webkit/WebCore/rendering/SimpleLineLayout.cpp +++ b/webkit/WebCore/rendering/SimpleLineLayout.cpp @@ -400,6 +400,7 @@ class FragmentForwardIterator : public std::iteratorrenderer(); bool paintSelectedTextOnly = paintInfo.phase == PaintPhaseSelection; + bool shouldPaintSelectionHighlight = !(paintInfo.paintBehavior & PaintBehaviorSkipSelectionHighlight); bool hasSelection = !parentRenderer.document().printing() && selectionState() != RenderObject::SelectionNone; if (!hasSelection && paintSelectedTextOnly) return; @@ -264,7 +265,7 @@ void SVGInlineTextBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffse bool hasVisibleStroke = svgStyle.hasVisibleStroke(); RenderStyle* selectionStyle = &style; - if (hasSelection) { + if (hasSelection && shouldPaintSelectionHighlight) { selectionStyle = parentRenderer.getCachedPseudoStyle(SELECTION); if (selectionStyle) { const SVGRenderStyle& svgSelectionStyle = selectionStyle->svgStyle(); diff --git a/webkit/WebCore/rendering/svg/SVGRenderingContext.cpp b/webkit/WebCore/rendering/svg/SVGRenderingContext.cpp index 212a166ec..8fb69ba1b 100755 --- a/webkit/WebCore/rendering/svg/SVGRenderingContext.cpp +++ b/webkit/WebCore/rendering/svg/SVGRenderingContext.cpp @@ -288,7 +288,9 @@ void SVGRenderingContext::renderSubtreeToImageBuffer(ImageBuffer* image, RenderE ASSERT(image); ASSERT(image->context()); - PaintInfo info(image->context(), LayoutRect::infiniteRect(), PaintPhaseForeground, PaintBehaviorNormal); + // Rendering into a buffer implies we're being used for masking, clipping, patterns or filters. In each of these + // cases we don't want to paint the selection. + PaintInfo info(image->context(), LayoutRect::infiniteRect(), PaintPhaseForeground, PaintBehaviorSkipSelectionHighlight); AffineTransform& contentTransformation = currentContentTransformation(); AffineTransform savedContentTransformation = contentTransformation; diff --git a/webkit/WebCore/rendering/svg/SVGRootInlineBox.cpp b/webkit/WebCore/rendering/svg/SVGRootInlineBox.cpp index d1a78389a..fe077d914 100755 --- a/webkit/WebCore/rendering/svg/SVGRootInlineBox.cpp +++ b/webkit/WebCore/rendering/svg/SVGRootInlineBox.cpp @@ -53,9 +53,10 @@ void SVGRootInlineBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffse bool isPrinting = renderSVGText().document().printing(); bool hasSelection = !isPrinting && selectionState() != RenderObject::SelectionNone; + bool shouldPaintSelectionHighlight = !(paintInfo.paintBehavior & PaintBehaviorSkipSelectionHighlight); PaintInfo childPaintInfo(paintInfo); - if (hasSelection) { + if (hasSelection && shouldPaintSelectionHighlight) { for (InlineBox* child = firstChild(); child; child = child->nextOnLine()) { if (is(*child)) downcast(*child).paintSelectionBackground(childPaintInfo); diff --git a/webkit/WebCore/rendering/svg/SVGTextRunRenderingContext.cpp b/webkit/WebCore/rendering/svg/SVGTextRunRenderingContext.cpp index dd3f28557..81378ea20 100755 --- a/webkit/WebCore/rendering/svg/SVGTextRunRenderingContext.cpp +++ b/webkit/WebCore/rendering/svg/SVGTextRunRenderingContext.cpp @@ -249,6 +249,13 @@ std::unique_ptr SVGTextRunRenderingContext::createGlyphTo SVGFontElement* fontElement = nullptr; SVGFontFaceElement* fontFaceElement = nullptr; +#if PLATFORM(WKC) + if (!font.isSVGFont()) { + // Guard in case Font::m_svgData is null caused by memory allocation failure. + return std::make_unique(); + } +#endif + const SVGFontData* svgFontData = svgFontAndFontFaceElementForFontData(&font, fontFaceElement, fontElement); if (!fontElement || !fontFaceElement) return std::make_unique(); diff --git a/webkit/WebCore/svg/SVGUseElement.cpp b/webkit/WebCore/svg/SVGUseElement.cpp index 5af98b013..bde3513aa 100755 --- a/webkit/WebCore/svg/SVGUseElement.cpp +++ b/webkit/WebCore/svg/SVGUseElement.cpp @@ -273,7 +273,7 @@ SVGElement* SVGUseElement::targetClone() const auto* root = userAgentShadowRoot(); if (!root) return nullptr; - return downcast(root->firstChild()); + return childrenOfType(*root).first(); } RenderPtr SVGUseElement::createElementRenderer(Ref&& style, const RenderTreePosition&) diff --git a/webkit/WebCore/testing/InternalSettings.cpp b/webkit/WebCore/testing/InternalSettings.cpp index 586117595..e0cd7588b 100755 --- a/webkit/WebCore/testing/InternalSettings.cpp +++ b/webkit/WebCore/testing/InternalSettings.cpp @@ -89,7 +89,8 @@ InternalSettings::Backup::Backup(Settings& settings) , m_originalTimeWithoutMouseMovementBeforeHidingControls(settings.timeWithoutMouseMovementBeforeHidingControls()) , m_useLegacyBackgroundSizeShorthandBehavior(settings.useLegacyBackgroundSizeShorthandBehavior()) , m_autoscrollForDragAndDropEnabled(settings.autoscrollForDragAndDropEnabled()) - , m_pluginReplacementEnabled(RuntimeEnabledFeatures::sharedFeatures().pluginReplacementEnabled()) + , m_quickTimePluginReplacementEnabled(settings.quickTimePluginReplacementEnabled()) + , m_youTubeFlashPluginReplacementEnabled(settings.youTubeFlashPluginReplacementEnabled()) , m_shouldConvertPositionStyleOnCopy(settings.shouldConvertPositionStyleOnCopy()) , m_fontFallbackPrefersPictographs(settings.fontFallbackPrefersPictographs()) , m_backgroundShouldExtendBeyondPage(settings.backgroundShouldExtendBeyondPage()) @@ -165,7 +166,8 @@ void InternalSettings::Backup::restoreTo(Settings& settings) #if ENABLE(TOUCH_EVENTS) settings.setTouchEventEmulationEnabled(m_touchEventEmulationEnabled); #endif - RuntimeEnabledFeatures::sharedFeatures().setPluginReplacementEnabled(m_pluginReplacementEnabled); + settings.setQuickTimePluginReplacementEnabled(m_quickTimePluginReplacementEnabled); + settings.setYouTubeFlashPluginReplacementEnabled(m_youTubeFlashPluginReplacementEnabled); } class InternalSettingsWrapper : public Supplement { @@ -501,9 +503,16 @@ void InternalSettings::setFontFallbackPrefersPictographs(bool preferPictographs, settings()->setFontFallbackPrefersPictographs(preferPictographs); } -void InternalSettings::setPluginReplacementEnabled(bool enabled) +void InternalSettings::setQuickTimePluginReplacementEnabled(bool enabled, ExceptionCode& ec) { - RuntimeEnabledFeatures::sharedFeatures().setPluginReplacementEnabled(enabled); + InternalSettingsGuardForSettings(); + settings()->setQuickTimePluginReplacementEnabled(enabled); +} + +void InternalSettings::setYouTubeFlashPluginReplacementEnabled(bool enabled, ExceptionCode& ec) +{ + InternalSettingsGuardForSettings(); + settings()->setYouTubeFlashPluginReplacementEnabled(enabled); } void InternalSettings::setBackgroundShouldExtendBeyondPage(bool hasExtendedBackground, ExceptionCode& ec) diff --git a/webkit/WebCore/testing/InternalSettings.h b/webkit/WebCore/testing/InternalSettings.h index 5ef861674..390ecdb88 100755 --- a/webkit/WebCore/testing/InternalSettings.h +++ b/webkit/WebCore/testing/InternalSettings.h @@ -86,7 +86,8 @@ class InternalSettings : public InternalSettingsGenerated { bool m_originalTimeWithoutMouseMovementBeforeHidingControls; bool m_useLegacyBackgroundSizeShorthandBehavior; bool m_autoscrollForDragAndDropEnabled; - bool m_pluginReplacementEnabled; + bool m_quickTimePluginReplacementEnabled; + bool m_youTubeFlashPluginReplacementEnabled; bool m_shouldConvertPositionStyleOnCopy; bool m_fontFallbackPrefersPictographs; bool m_backgroundShouldExtendBeyondPage; @@ -139,7 +140,8 @@ class InternalSettings : public InternalSettingsGenerated { void setUseLegacyBackgroundSizeShorthandBehavior(bool, ExceptionCode&); void setAutoscrollForDragAndDropEnabled(bool, ExceptionCode&); void setFontFallbackPrefersPictographs(bool, ExceptionCode&); - void setPluginReplacementEnabled(bool); + void setQuickTimePluginReplacementEnabled(bool, ExceptionCode&); + void setYouTubeFlashPluginReplacementEnabled(bool, ExceptionCode&); void setBackgroundShouldExtendBeyondPage(bool, ExceptionCode&); void setShouldConvertPositionStyleOnCopy(bool, ExceptionCode&); void setScrollingTreeIncludesFrames(bool, ExceptionCode&); diff --git a/webkit/WebCore/testing/InternalSettings.idl b/webkit/WebCore/testing/InternalSettings.idl index 309e89edf..8e7781172 100755 --- a/webkit/WebCore/testing/InternalSettings.idl +++ b/webkit/WebCore/testing/InternalSettings.idl @@ -58,7 +58,8 @@ [RaisesException] void setForcePendingWebGLPolicy(boolean forced); - void setPluginReplacementEnabled(boolean enabled); + [RaisesException] void setQuickTimePluginReplacementEnabled(boolean enabled); + [RaisesException] void setYouTubeFlashPluginReplacementEnabled(boolean enabled); // Editing, forms [RaisesException] void setEditingBehavior(DOMString behavior); diff --git a/webkit/WebCore/testing/Internals.cpp b/webkit/WebCore/testing/Internals.cpp index e1f6e05cd..12ed2fb1e 100755 --- a/webkit/WebCore/testing/Internals.cpp +++ b/webkit/WebCore/testing/Internals.cpp @@ -2725,9 +2725,15 @@ void Internals::setMediaElementRestrictions(HTMLMediaElement* element, const Str } void Internals::postRemoteControlCommand(const String& commandString, ExceptionCode& ec) +{ + postRemoteControlCommand(commandString, 0, ec); +} + +void Internals::postRemoteControlCommand(const String& commandString, float argument, ExceptionCode& ec) { PlatformMediaSession::RemoteControlCommandType command; - + PlatformMediaSession::RemoteCommandArgument parameter { argument }; + if (equalIgnoringCase(commandString, "Play")) command = PlatformMediaSession::PlayCommand; else if (equalIgnoringCase(commandString, "Pause")) @@ -2744,12 +2750,14 @@ void Internals::postRemoteControlCommand(const String& commandString, ExceptionC command = PlatformMediaSession::BeginSeekingForwardCommand; else if (equalIgnoringCase(commandString, "EndSeekingForward")) command = PlatformMediaSession::EndSeekingForwardCommand; + else if (equalLettersIgnoringASCIICase(commandString, "seektoplaybackposition")) + command = PlatformMediaSession::SeekToPlaybackPositionCommand; else { ec = INVALID_ACCESS_ERR; return; } - PlatformMediaSessionManager::sharedManager().didReceiveRemoteControlCommand(command); + PlatformMediaSessionManager::sharedManager().didReceiveRemoteControlCommand(command, ¶meter); } bool Internals::elementIsBlockingDisplaySleep(Element* element) const diff --git a/webkit/WebCore/testing/Internals.h b/webkit/WebCore/testing/Internals.h index 175edb38b..c6c7ba7b4 100755 --- a/webkit/WebCore/testing/Internals.h +++ b/webkit/WebCore/testing/Internals.h @@ -388,6 +388,7 @@ class Internals : public RefCounted void setMediaSessionRestrictions(const String& mediaType, const String& restrictions, ExceptionCode&); void setMediaElementRestrictions(HTMLMediaElement*, const String& restrictions, ExceptionCode&); void postRemoteControlCommand(const String&, ExceptionCode&); + void postRemoteControlCommand(const String&, float argument, ExceptionCode&); bool elementIsBlockingDisplaySleep(Element*) const; #endif diff --git a/webkit/WebCore/testing/Internals.idl b/webkit/WebCore/testing/Internals.idl index cf899a31f..2aa789a6a 100755 --- a/webkit/WebCore/testing/Internals.idl +++ b/webkit/WebCore/testing/Internals.idl @@ -356,7 +356,7 @@ enum ResourceLoadPriority { [Conditional=VIDEO, RaisesException] void setMediaSessionRestrictions(DOMString mediaType, DOMString restrictions); [Conditional=VIDEO, RaisesException] void setMediaElementRestrictions(HTMLMediaElement element, DOMString restrictions); [Conditional=WEB_AUDIO, RaisesException] void setAudioContextRestrictions(AudioContext context, DOMString restrictions); - [Conditional=VIDEO, RaisesException] void postRemoteControlCommand(DOMString command); + [Conditional=VIDEO, RaisesException] void postRemoteControlCommand(DOMString command, optional unrestricted float argument); [Conditional=VIDEO] void simulateSystemSleep(); [Conditional=VIDEO] void simulateSystemWake(); diff --git a/webkit/WebCore/xml/XMLErrors.cpp b/webkit/WebCore/xml/XMLErrors.cpp index 673c5fb62..106681561 100755 --- a/webkit/WebCore/xml/XMLErrors.cpp +++ b/webkit/WebCore/xml/XMLErrors.cpp @@ -138,8 +138,9 @@ void XMLErrors::insertErrorMessageBlock() rootElement->parserAppendChild(body); m_document->parserRemoveChild(*documentElement); + if (!documentElement->parentNode()) + body->parserAppendChild(documentElement); - body->parserAppendChild(documentElement); m_document->parserAppendChild(rootElement); documentElement = body.get(); diff --git a/webkit/WebCore/xml/parser/XMLDocumentParser.cpp b/webkit/WebCore/xml/parser/XMLDocumentParser.cpp index b5d90f0ec..590829dad 100755 --- a/webkit/WebCore/xml/parser/XMLDocumentParser.cpp +++ b/webkit/WebCore/xml/parser/XMLDocumentParser.cpp @@ -188,9 +188,11 @@ void XMLDocumentParser::end() if (m_parserPaused) return; - if (m_sawError) + if (m_sawError) { insertErrorMessageBlock(); - else { + if (isDetached()) // Inserting an error message may have ran arbitrary scripts. + return; + } else { exitText(); document()->styleResolverChanged(RecalcStyleImmediately); } @@ -208,6 +210,8 @@ void XMLDocumentParser::finish() // makes sense to call any methods on DocumentParser once it's been stopped. // However, FrameLoader::stop calls DocumentParser::finish unconditionally. + Ref protectedThis(*this); + if (m_parserPaused) m_finishCalled = true; else diff --git a/webkit/WebInspectorUI/ChangeLog b/webkit/WebInspectorUI/ChangeLog index d0133092b..0ecb4ab8a 100755 --- a/webkit/WebInspectorUI/ChangeLog +++ b/webkit/WebInspectorUI/ChangeLog @@ -1,3 +1,33 @@ +2017-01-12 Matthew Hanson + + Merge r210623. rdar://problem/29980631 + + 2017-01-11 Joseph Pecoraro + + Web Inspector: Add another Protocol Version + https://bugs.webkit.org/show_bug.cgi?id=166953 + + + Reviewed by Timothy Hatcher. + + * UserInterface/Protocol/Legacy/10.3/InspectorBackendCommands.js: Added. + * Versions/Inspector-iOS-10.3.json: Added. + +2016-09-09 Babak Shafiei + + Merge r205192. rdar://problem/28097740 + + 2016-08-30 Alex Christensen + + Fix WebInspectorUI in internal Windows build + https://bugs.webkit.org/show_bug.cgi?id=161221 + rdar://problem/28019023 + + Reviewed by Brent Fulgham and Joseph Pecoraro. + + * WebInspectorUI.vcxproj/WebInspectorUI.make: + * WebInspectorUI.vcxproj/WebInspectorUI.proj: + 2016-02-12 Matthew Hanson Merge r196362. rdar://problem/24611811 diff --git a/webkit/WebInspectorUI/UserInterface/Protocol/Legacy/10.3/InspectorBackendCommands.js b/webkit/WebInspectorUI/UserInterface/Protocol/Legacy/10.3/InspectorBackendCommands.js new file mode 100755 index 000000000..2780e3a10 --- /dev/null +++ b/webkit/WebInspectorUI/UserInterface/Protocol/Legacy/10.3/InspectorBackendCommands.js @@ -0,0 +1,409 @@ +/* + * Copyright (C) 2013 Google Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. + * Copyright (C) 2014 University of Washington. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +// DO NOT EDIT THIS FILE. It is automatically generated from Inspector-iOS-10.3.json +// by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py + +// ApplicationCache. +InspectorBackend.registerApplicationCacheDispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, "ApplicationCache"); +InspectorBackend.registerEvent("ApplicationCache.applicationCacheStatusUpdated", ["frameId", "manifestURL", "status"]); +InspectorBackend.registerEvent("ApplicationCache.networkStateUpdated", ["isNowOnline"]); +InspectorBackend.registerCommand("ApplicationCache.getFramesWithManifests", [], ["frameIds"]); +InspectorBackend.registerCommand("ApplicationCache.enable", [], []); +InspectorBackend.registerCommand("ApplicationCache.getManifestForFrame", [{"name": "frameId", "type": "string", "optional": false}], ["manifestURL"]); +InspectorBackend.registerCommand("ApplicationCache.getApplicationCacheForFrame", [{"name": "frameId", "type": "string", "optional": false}], ["applicationCache"]); +InspectorBackend.activateDomain("ApplicationCache", "web"); + +// CSS. +InspectorBackend.registerCSSDispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, "CSS"); +InspectorBackend.registerEnum("CSS.StyleSheetOrigin", {User: "user", UserAgent: "user-agent", Inspector: "inspector", Regular: "regular"}); +InspectorBackend.registerEnum("CSS.CSSPropertyStatus", {Active: "active", Inactive: "inactive", Disabled: "disabled", Style: "style"}); +InspectorBackend.registerEnum("CSS.CSSMediaSource", {MediaRule: "mediaRule", ImportRule: "importRule", LinkedSheet: "linkedSheet", InlineSheet: "inlineSheet"}); +InspectorBackend.registerEnum("CSS.RegionRegionOverset", {Overset: "overset", Fit: "fit", Empty: "empty"}); +InspectorBackend.registerEvent("CSS.mediaQueryResultChanged", []); +InspectorBackend.registerEvent("CSS.styleSheetChanged", ["styleSheetId"]); +InspectorBackend.registerEvent("CSS.styleSheetAdded", ["header"]); +InspectorBackend.registerEvent("CSS.styleSheetRemoved", ["styleSheetId"]); +InspectorBackend.registerEvent("CSS.namedFlowCreated", ["namedFlow"]); +InspectorBackend.registerEvent("CSS.namedFlowRemoved", ["documentNodeId", "flowName"]); +InspectorBackend.registerEvent("CSS.regionOversetChanged", ["namedFlow"]); +InspectorBackend.registerEvent("CSS.registeredNamedFlowContentElement", ["documentNodeId", "flowName", "contentNodeId", "nextContentNodeId"]); +InspectorBackend.registerEvent("CSS.unregisteredNamedFlowContentElement", ["documentNodeId", "flowName", "contentNodeId"]); +InspectorBackend.registerCommand("CSS.enable", [], []); +InspectorBackend.registerCommand("CSS.disable", [], []); +InspectorBackend.registerCommand("CSS.getMatchedStylesForNode", [{"name": "nodeId", "type": "number", "optional": false}, {"name": "includePseudo", "type": "boolean", "optional": true}, {"name": "includeInherited", "type": "boolean", "optional": true}], ["matchedCSSRules", "pseudoElements", "inherited"]); +InspectorBackend.registerCommand("CSS.getInlineStylesForNode", [{"name": "nodeId", "type": "number", "optional": false}], ["inlineStyle", "attributesStyle"]); +InspectorBackend.registerCommand("CSS.getComputedStyleForNode", [{"name": "nodeId", "type": "number", "optional": false}], ["computedStyle"]); +InspectorBackend.registerCommand("CSS.getAllStyleSheets", [], ["headers"]); +InspectorBackend.registerCommand("CSS.getStyleSheet", [{"name": "styleSheetId", "type": "string", "optional": false}], ["styleSheet"]); +InspectorBackend.registerCommand("CSS.getStyleSheetText", [{"name": "styleSheetId", "type": "string", "optional": false}], ["text"]); +InspectorBackend.registerCommand("CSS.setStyleSheetText", [{"name": "styleSheetId", "type": "string", "optional": false}, {"name": "text", "type": "string", "optional": false}], []); +InspectorBackend.registerCommand("CSS.setStyleText", [{"name": "styleId", "type": "object", "optional": false}, {"name": "text", "type": "string", "optional": false}], ["style"]); +InspectorBackend.registerCommand("CSS.setRuleSelector", [{"name": "ruleId", "type": "object", "optional": false}, {"name": "selector", "type": "string", "optional": false}], ["rule"]); +InspectorBackend.registerCommand("CSS.createStyleSheet", [{"name": "frameId", "type": "string", "optional": false}], ["styleSheetId"]); +InspectorBackend.registerCommand("CSS.addRule", [{"name": "styleSheetId", "type": "string", "optional": false}, {"name": "selector", "type": "string", "optional": false}], ["rule"]); +InspectorBackend.registerCommand("CSS.getSupportedCSSProperties", [], ["cssProperties"]); +InspectorBackend.registerCommand("CSS.getSupportedSystemFontFamilyNames", [], ["fontFamilyNames"]); +InspectorBackend.registerCommand("CSS.forcePseudoState", [{"name": "nodeId", "type": "number", "optional": false}, {"name": "forcedPseudoClasses", "type": "object", "optional": false}], []); +InspectorBackend.registerCommand("CSS.getNamedFlowCollection", [{"name": "documentNodeId", "type": "number", "optional": false}], ["namedFlows"]); +InspectorBackend.activateDomain("CSS", "web"); + +// Console. +InspectorBackend.registerConsoleDispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, "Console"); +InspectorBackend.registerEnum("Console.ConsoleMessageSource", {XML: "xml", Javascript: "javascript", Network: "network", ConsoleAPI: "console-api", Storage: "storage", Appcache: "appcache", Rendering: "rendering", CSS: "css", Security: "security", ContentBlocker: "content-blocker", Other: "other"}); +InspectorBackend.registerEnum("Console.ConsoleMessageLevel", {Log: "log", Info: "info", Warning: "warning", Error: "error", Debug: "debug"}); +InspectorBackend.registerEnum("Console.ConsoleMessageType", {Log: "log", Dir: "dir", DirXML: "dirxml", Table: "table", Trace: "trace", Clear: "clear", StartGroup: "startGroup", StartGroupCollapsed: "startGroupCollapsed", EndGroup: "endGroup", Assert: "assert", Timing: "timing", Profile: "profile", ProfileEnd: "profileEnd"}); +InspectorBackend.registerEvent("Console.messageAdded", ["message"]); +InspectorBackend.registerEvent("Console.messageRepeatCountUpdated", ["count"]); +InspectorBackend.registerEvent("Console.messagesCleared", []); +InspectorBackend.registerEvent("Console.heapSnapshot", ["timestamp", "snapshotData", "title"]); +InspectorBackend.registerCommand("Console.enable", [], []); +InspectorBackend.registerCommand("Console.disable", [], []); +InspectorBackend.registerCommand("Console.clearMessages", [], []); +InspectorBackend.registerCommand("Console.setMonitoringXHREnabled", [{"name": "enabled", "type": "boolean", "optional": false}], []); +InspectorBackend.registerCommand("Console.addInspectedNode", [{"name": "nodeId", "type": "number", "optional": false}], []); +InspectorBackend.activateDomain("Console"); + +// DOM. +InspectorBackend.registerDOMDispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, "DOM"); +InspectorBackend.registerEnum("DOM.PseudoType", {Before: "before", After: "after"}); +InspectorBackend.registerEnum("DOM.ShadowRootType", {UserAgent: "user-agent", Open: "open", Closed: "closed"}); +InspectorBackend.registerEnum("DOM.CustomElementState", {Builtin: "builtin", Custom: "custom", Waiting: "waiting", Failed: "failed"}); +InspectorBackend.registerEnum("DOM.LiveRegionRelevant", {Additions: "additions", Removals: "removals", Text: "text"}); +InspectorBackend.registerEnum("DOM.AccessibilityPropertiesChecked", {True: "true", False: "false", Mixed: "mixed"}); +InspectorBackend.registerEnum("DOM.AccessibilityPropertiesCurrent", {True: "true", False: "false", Page: "page", Step: "step", Location: "location", Date: "date", Time: "time"}); +InspectorBackend.registerEnum("DOM.AccessibilityPropertiesInvalid", {True: "true", False: "false", Grammar: "grammar", Spelling: "spelling"}); +InspectorBackend.registerEnum("DOM.AccessibilityPropertiesLiveRegionStatus", {Assertive: "assertive", Polite: "polite", Off: "off"}); +InspectorBackend.registerEvent("DOM.documentUpdated", []); +InspectorBackend.registerEvent("DOM.setChildNodes", ["parentId", "nodes"]); +InspectorBackend.registerEvent("DOM.attributeModified", ["nodeId", "name", "value"]); +InspectorBackend.registerEvent("DOM.attributeRemoved", ["nodeId", "name"]); +InspectorBackend.registerEvent("DOM.inlineStyleInvalidated", ["nodeIds"]); +InspectorBackend.registerEvent("DOM.characterDataModified", ["nodeId", "characterData"]); +InspectorBackend.registerEvent("DOM.childNodeCountUpdated", ["nodeId", "childNodeCount"]); +InspectorBackend.registerEvent("DOM.childNodeInserted", ["parentNodeId", "previousNodeId", "node"]); +InspectorBackend.registerEvent("DOM.childNodeRemoved", ["parentNodeId", "nodeId"]); +InspectorBackend.registerEvent("DOM.shadowRootPushed", ["hostId", "root"]); +InspectorBackend.registerEvent("DOM.shadowRootPopped", ["hostId", "rootId"]); +InspectorBackend.registerEvent("DOM.customElementStateChanged", ["nodeId", "customElementState"]); +InspectorBackend.registerEvent("DOM.pseudoElementAdded", ["parentId", "pseudoElement"]); +InspectorBackend.registerEvent("DOM.pseudoElementRemoved", ["parentId", "pseudoElementId"]); +InspectorBackend.registerCommand("DOM.getDocument", [], ["root"]); +InspectorBackend.registerCommand("DOM.requestChildNodes", [{"name": "nodeId", "type": "number", "optional": false}, {"name": "depth", "type": "number", "optional": true}], []); +InspectorBackend.registerCommand("DOM.querySelector", [{"name": "nodeId", "type": "number", "optional": false}, {"name": "selector", "type": "string", "optional": false}], ["nodeId"]); +InspectorBackend.registerCommand("DOM.querySelectorAll", [{"name": "nodeId", "type": "number", "optional": false}, {"name": "selector", "type": "string", "optional": false}], ["nodeIds"]); +InspectorBackend.registerCommand("DOM.setNodeName", [{"name": "nodeId", "type": "number", "optional": false}, {"name": "name", "type": "string", "optional": false}], ["nodeId"]); +InspectorBackend.registerCommand("DOM.setNodeValue", [{"name": "nodeId", "type": "number", "optional": false}, {"name": "value", "type": "string", "optional": false}], []); +InspectorBackend.registerCommand("DOM.removeNode", [{"name": "nodeId", "type": "number", "optional": false}], []); +InspectorBackend.registerCommand("DOM.setAttributeValue", [{"name": "nodeId", "type": "number", "optional": false}, {"name": "name", "type": "string", "optional": false}, {"name": "value", "type": "string", "optional": false}], []); +InspectorBackend.registerCommand("DOM.setAttributesAsText", [{"name": "nodeId", "type": "number", "optional": false}, {"name": "text", "type": "string", "optional": false}, {"name": "name", "type": "string", "optional": true}], []); +InspectorBackend.registerCommand("DOM.removeAttribute", [{"name": "nodeId", "type": "number", "optional": false}, {"name": "name", "type": "string", "optional": false}], []); +InspectorBackend.registerCommand("DOM.getEventListenersForNode", [{"name": "nodeId", "type": "number", "optional": false}, {"name": "objectGroup", "type": "string", "optional": true}], ["listeners"]); +InspectorBackend.registerCommand("DOM.getAccessibilityPropertiesForNode", [{"name": "nodeId", "type": "number", "optional": false}], ["properties"]); +InspectorBackend.registerCommand("DOM.getOuterHTML", [{"name": "nodeId", "type": "number", "optional": false}], ["outerHTML"]); +InspectorBackend.registerCommand("DOM.setOuterHTML", [{"name": "nodeId", "type": "number", "optional": false}, {"name": "outerHTML", "type": "string", "optional": false}], []); +InspectorBackend.registerCommand("DOM.performSearch", [{"name": "query", "type": "string", "optional": false}, {"name": "nodeIds", "type": "object", "optional": true}], ["searchId", "resultCount"]); +InspectorBackend.registerCommand("DOM.getSearchResults", [{"name": "searchId", "type": "string", "optional": false}, {"name": "fromIndex", "type": "number", "optional": false}, {"name": "toIndex", "type": "number", "optional": false}], ["nodeIds"]); +InspectorBackend.registerCommand("DOM.discardSearchResults", [{"name": "searchId", "type": "string", "optional": false}], []); +InspectorBackend.registerCommand("DOM.requestNode", [{"name": "objectId", "type": "string", "optional": false}], ["nodeId"]); +InspectorBackend.registerCommand("DOM.setInspectModeEnabled", [{"name": "enabled", "type": "boolean", "optional": false}, {"name": "highlightConfig", "type": "object", "optional": true}], []); +InspectorBackend.registerCommand("DOM.highlightRect", [{"name": "x", "type": "number", "optional": false}, {"name": "y", "type": "number", "optional": false}, {"name": "width", "type": "number", "optional": false}, {"name": "height", "type": "number", "optional": false}, {"name": "color", "type": "object", "optional": true}, {"name": "outlineColor", "type": "object", "optional": true}, {"name": "usePageCoordinates", "type": "boolean", "optional": true}], []); +InspectorBackend.registerCommand("DOM.highlightQuad", [{"name": "quad", "type": "object", "optional": false}, {"name": "color", "type": "object", "optional": true}, {"name": "outlineColor", "type": "object", "optional": true}, {"name": "usePageCoordinates", "type": "boolean", "optional": true}], []); +InspectorBackend.registerCommand("DOM.highlightSelector", [{"name": "highlightConfig", "type": "object", "optional": false}, {"name": "selectorString", "type": "string", "optional": false}, {"name": "frameId", "type": "string", "optional": true}], []); +InspectorBackend.registerCommand("DOM.highlightNode", [{"name": "highlightConfig", "type": "object", "optional": false}, {"name": "nodeId", "type": "number", "optional": true}, {"name": "objectId", "type": "string", "optional": true}], []); +InspectorBackend.registerCommand("DOM.hideHighlight", [], []); +InspectorBackend.registerCommand("DOM.highlightFrame", [{"name": "frameId", "type": "string", "optional": false}, {"name": "contentColor", "type": "object", "optional": true}, {"name": "contentOutlineColor", "type": "object", "optional": true}], []); +InspectorBackend.registerCommand("DOM.pushNodeByPathToFrontend", [{"name": "path", "type": "string", "optional": false}], ["nodeId"]); +InspectorBackend.registerCommand("DOM.pushNodeByBackendIdToFrontend", [{"name": "backendNodeId", "type": "number", "optional": false}], ["nodeId"]); +InspectorBackend.registerCommand("DOM.releaseBackendNodeIds", [{"name": "nodeGroup", "type": "string", "optional": false}], []); +InspectorBackend.registerCommand("DOM.resolveNode", [{"name": "nodeId", "type": "number", "optional": false}, {"name": "objectGroup", "type": "string", "optional": true}], ["object"]); +InspectorBackend.registerCommand("DOM.getAttributes", [{"name": "nodeId", "type": "number", "optional": false}], ["attributes"]); +InspectorBackend.registerCommand("DOM.moveTo", [{"name": "nodeId", "type": "number", "optional": false}, {"name": "targetNodeId", "type": "number", "optional": false}, {"name": "insertBeforeNodeId", "type": "number", "optional": true}], ["nodeId"]); +InspectorBackend.registerCommand("DOM.undo", [], []); +InspectorBackend.registerCommand("DOM.redo", [], []); +InspectorBackend.registerCommand("DOM.markUndoableState", [], []); +InspectorBackend.registerCommand("DOM.focus", [{"name": "nodeId", "type": "number", "optional": false}], []); +InspectorBackend.activateDomain("DOM", "web"); + +// DOMDebugger. +InspectorBackend.registerEnum("DOMDebugger.DOMBreakpointType", {SubtreeModified: "subtree-modified", AttributeModified: "attribute-modified", NodeRemoved: "node-removed"}); +InspectorBackend.registerCommand("DOMDebugger.setDOMBreakpoint", [{"name": "nodeId", "type": "number", "optional": false}, {"name": "type", "type": "string", "optional": false}], []); +InspectorBackend.registerCommand("DOMDebugger.removeDOMBreakpoint", [{"name": "nodeId", "type": "number", "optional": false}, {"name": "type", "type": "string", "optional": false}], []); +InspectorBackend.registerCommand("DOMDebugger.setEventListenerBreakpoint", [{"name": "eventName", "type": "string", "optional": false}], []); +InspectorBackend.registerCommand("DOMDebugger.removeEventListenerBreakpoint", [{"name": "eventName", "type": "string", "optional": false}], []); +InspectorBackend.registerCommand("DOMDebugger.setInstrumentationBreakpoint", [{"name": "eventName", "type": "string", "optional": false}], []); +InspectorBackend.registerCommand("DOMDebugger.removeInstrumentationBreakpoint", [{"name": "eventName", "type": "string", "optional": false}], []); +InspectorBackend.registerCommand("DOMDebugger.setXHRBreakpoint", [{"name": "url", "type": "string", "optional": false}], []); +InspectorBackend.registerCommand("DOMDebugger.removeXHRBreakpoint", [{"name": "url", "type": "string", "optional": false}], []); +InspectorBackend.activateDomain("DOMDebugger", "web"); + +// DOMStorage. +InspectorBackend.registerDOMStorageDispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, "DOMStorage"); +InspectorBackend.registerEvent("DOMStorage.domStorageItemsCleared", ["storageId"]); +InspectorBackend.registerEvent("DOMStorage.domStorageItemRemoved", ["storageId", "key"]); +InspectorBackend.registerEvent("DOMStorage.domStorageItemAdded", ["storageId", "key", "newValue"]); +InspectorBackend.registerEvent("DOMStorage.domStorageItemUpdated", ["storageId", "key", "oldValue", "newValue"]); +InspectorBackend.registerCommand("DOMStorage.enable", [], []); +InspectorBackend.registerCommand("DOMStorage.disable", [], []); +InspectorBackend.registerCommand("DOMStorage.getDOMStorageItems", [{"name": "storageId", "type": "object", "optional": false}], ["entries"]); +InspectorBackend.registerCommand("DOMStorage.setDOMStorageItem", [{"name": "storageId", "type": "object", "optional": false}, {"name": "key", "type": "string", "optional": false}, {"name": "value", "type": "string", "optional": false}], []); +InspectorBackend.registerCommand("DOMStorage.removeDOMStorageItem", [{"name": "storageId", "type": "object", "optional": false}, {"name": "key", "type": "string", "optional": false}], []); +InspectorBackend.activateDomain("DOMStorage", "web"); + +// Database. +InspectorBackend.registerDatabaseDispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, "Database"); +InspectorBackend.registerEvent("Database.addDatabase", ["database"]); +InspectorBackend.registerCommand("Database.enable", [], []); +InspectorBackend.registerCommand("Database.disable", [], []); +InspectorBackend.registerCommand("Database.getDatabaseTableNames", [{"name": "databaseId", "type": "string", "optional": false}], ["tableNames"]); +InspectorBackend.registerCommand("Database.executeSQL", [{"name": "databaseId", "type": "string", "optional": false}, {"name": "query", "type": "string", "optional": false}], ["columnNames", "values", "sqlError"]); +InspectorBackend.activateDomain("Database", "web"); + +// Debugger. +InspectorBackend.registerDebuggerDispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, "Debugger"); +InspectorBackend.registerEnum("Debugger.BreakpointActionType", {Log: "log", Evaluate: "evaluate", Sound: "sound", Probe: "probe"}); +InspectorBackend.registerEnum("Debugger.ScopeType", {Global: "global", With: "with", Closure: "closure", Catch: "catch", FunctionName: "functionName", GlobalLexicalEnvironment: "globalLexicalEnvironment", NestedLexical: "nestedLexical"}); +InspectorBackend.registerEvent("Debugger.globalObjectCleared", []); +InspectorBackend.registerEvent("Debugger.scriptParsed", ["scriptId", "url", "startLine", "startColumn", "endLine", "endColumn", "isContentScript", "sourceURL", "sourceMapURL", "module"]); +InspectorBackend.registerEvent("Debugger.scriptFailedToParse", ["url", "scriptSource", "startLine", "errorLine", "errorMessage"]); +InspectorBackend.registerEvent("Debugger.breakpointResolved", ["breakpointId", "location"]); +InspectorBackend.registerEnum("Debugger.PausedReason", {XHR: "XHR", DOM: "DOM", EventListener: "EventListener", Exception: "exception", Assert: "assert", CSPViolation: "CSPViolation", DebuggerStatement: "DebuggerStatement", Breakpoint: "Breakpoint", PauseOnNextStatement: "PauseOnNextStatement", Other: "other"}); +InspectorBackend.registerEvent("Debugger.paused", ["callFrames", "reason", "data", "asyncStackTrace"]); +InspectorBackend.registerEvent("Debugger.resumed", []); +InspectorBackend.registerEvent("Debugger.didSampleProbe", ["sample"]); +InspectorBackend.registerEvent("Debugger.playBreakpointActionSound", ["breakpointActionId"]); +InspectorBackend.registerCommand("Debugger.enable", [], []); +InspectorBackend.registerCommand("Debugger.disable", [], []); +InspectorBackend.registerCommand("Debugger.setAsyncStackTraceDepth", [{"name": "depth", "type": "number", "optional": false}], []); +InspectorBackend.registerCommand("Debugger.setBreakpointsActive", [{"name": "active", "type": "boolean", "optional": false}], []); +InspectorBackend.registerCommand("Debugger.setBreakpointByUrl", [{"name": "lineNumber", "type": "number", "optional": false}, {"name": "url", "type": "string", "optional": true}, {"name": "urlRegex", "type": "string", "optional": true}, {"name": "columnNumber", "type": "number", "optional": true}, {"name": "options", "type": "object", "optional": true}], ["breakpointId", "locations"]); +InspectorBackend.registerCommand("Debugger.setBreakpoint", [{"name": "location", "type": "object", "optional": false}, {"name": "options", "type": "object", "optional": true}], ["breakpointId", "actualLocation"]); +InspectorBackend.registerCommand("Debugger.removeBreakpoint", [{"name": "breakpointId", "type": "string", "optional": false}], []); +InspectorBackend.registerCommand("Debugger.continueUntilNextRunLoop", [], []); +InspectorBackend.registerCommand("Debugger.continueToLocation", [{"name": "location", "type": "object", "optional": false}], []); +InspectorBackend.registerCommand("Debugger.stepOver", [], []); +InspectorBackend.registerCommand("Debugger.stepInto", [], []); +InspectorBackend.registerCommand("Debugger.stepOut", [], []); +InspectorBackend.registerCommand("Debugger.pause", [], []); +InspectorBackend.registerCommand("Debugger.resume", [], []); +InspectorBackend.registerCommand("Debugger.searchInContent", [{"name": "scriptId", "type": "string", "optional": false}, {"name": "query", "type": "string", "optional": false}, {"name": "caseSensitive", "type": "boolean", "optional": true}, {"name": "isRegex", "type": "boolean", "optional": true}], ["result"]); +InspectorBackend.registerCommand("Debugger.getScriptSource", [{"name": "scriptId", "type": "string", "optional": false}], ["scriptSource"]); +InspectorBackend.registerCommand("Debugger.getFunctionDetails", [{"name": "functionId", "type": "string", "optional": false}], ["details"]); +InspectorBackend.registerCommand("Debugger.setPauseOnExceptions", [{"name": "state", "type": "string", "optional": false}], []); +InspectorBackend.registerCommand("Debugger.setPauseOnAssertions", [{"name": "enabled", "type": "boolean", "optional": false}], []); +InspectorBackend.registerCommand("Debugger.evaluateOnCallFrame", [{"name": "callFrameId", "type": "string", "optional": false}, {"name": "expression", "type": "string", "optional": false}, {"name": "objectGroup", "type": "string", "optional": true}, {"name": "includeCommandLineAPI", "type": "boolean", "optional": true}, {"name": "doNotPauseOnExceptionsAndMuteConsole", "type": "boolean", "optional": true}, {"name": "returnByValue", "type": "boolean", "optional": true}, {"name": "generatePreview", "type": "boolean", "optional": true}, {"name": "saveResult", "type": "boolean", "optional": true}], ["result", "wasThrown", "savedResultIndex"]); +InspectorBackend.registerCommand("Debugger.setOverlayMessage", [{"name": "message", "type": "string", "optional": true}], []); +InspectorBackend.activateDomain("Debugger"); + +// Heap. +InspectorBackend.registerHeapDispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, "Heap"); +InspectorBackend.registerEnum("Heap.GarbageCollectionType", {Full: "full", Partial: "partial"}); +InspectorBackend.registerEvent("Heap.garbageCollected", ["collection"]); +InspectorBackend.registerEvent("Heap.trackingStart", ["timestamp", "snapshotData"]); +InspectorBackend.registerEvent("Heap.trackingComplete", ["timestamp", "snapshotData"]); +InspectorBackend.registerCommand("Heap.enable", [], []); +InspectorBackend.registerCommand("Heap.disable", [], []); +InspectorBackend.registerCommand("Heap.gc", [], []); +InspectorBackend.registerCommand("Heap.snapshot", [], ["timestamp", "snapshotData"]); +InspectorBackend.registerCommand("Heap.startTracking", [], []); +InspectorBackend.registerCommand("Heap.stopTracking", [], []); +InspectorBackend.registerCommand("Heap.getPreview", [{"name": "heapObjectId", "type": "number", "optional": false}], ["string", "functionDetails", "preview"]); +InspectorBackend.registerCommand("Heap.getRemoteObject", [{"name": "heapObjectId", "type": "number", "optional": false}, {"name": "objectGroup", "type": "string", "optional": true}], ["result"]); +InspectorBackend.activateDomain("Heap"); + +// IndexedDB. +InspectorBackend.registerIndexedDBDispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, "IndexedDB"); +InspectorBackend.registerEnum("IndexedDB.KeyType", {Number: "number", String: "string", Date: "date", Array: "array"}); +InspectorBackend.registerEnum("IndexedDB.KeyPathType", {Null: "null", String: "string", Array: "array"}); +InspectorBackend.registerCommand("IndexedDB.enable", [], []); +InspectorBackend.registerCommand("IndexedDB.disable", [], []); +InspectorBackend.registerCommand("IndexedDB.requestDatabaseNames", [{"name": "securityOrigin", "type": "string", "optional": false}], ["databaseNames"]); +InspectorBackend.registerCommand("IndexedDB.requestDatabase", [{"name": "securityOrigin", "type": "string", "optional": false}, {"name": "databaseName", "type": "string", "optional": false}], ["databaseWithObjectStores"]); +InspectorBackend.registerCommand("IndexedDB.requestData", [{"name": "securityOrigin", "type": "string", "optional": false}, {"name": "databaseName", "type": "string", "optional": false}, {"name": "objectStoreName", "type": "string", "optional": false}, {"name": "indexName", "type": "string", "optional": false}, {"name": "skipCount", "type": "number", "optional": false}, {"name": "pageSize", "type": "number", "optional": false}, {"name": "keyRange", "type": "object", "optional": true}], ["objectStoreDataEntries", "hasMore"]); +InspectorBackend.registerCommand("IndexedDB.clearObjectStore", [{"name": "securityOrigin", "type": "string", "optional": false}, {"name": "databaseName", "type": "string", "optional": false}, {"name": "objectStoreName", "type": "string", "optional": false}], []); +InspectorBackend.activateDomain("IndexedDB", "web"); + +// Inspector. +InspectorBackend.registerInspectorDispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, "Inspector"); +InspectorBackend.registerEvent("Inspector.evaluateForTestInFrontend", ["script"]); +InspectorBackend.registerEvent("Inspector.inspect", ["object", "hints"]); +InspectorBackend.registerEvent("Inspector.detached", ["reason"]); +InspectorBackend.registerEvent("Inspector.activateExtraDomains", ["domains"]); +InspectorBackend.registerEvent("Inspector.targetCrashed", []); +InspectorBackend.registerCommand("Inspector.enable", [], []); +InspectorBackend.registerCommand("Inspector.disable", [], []); +InspectorBackend.registerCommand("Inspector.initialized", [], []); +InspectorBackend.activateDomain("Inspector"); + +// LayerTree. +InspectorBackend.registerLayerTreeDispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, "LayerTree"); +InspectorBackend.registerEvent("LayerTree.layerTreeDidChange", []); +InspectorBackend.registerCommand("LayerTree.enable", [], []); +InspectorBackend.registerCommand("LayerTree.disable", [], []); +InspectorBackend.registerCommand("LayerTree.layersForNode", [{"name": "nodeId", "type": "number", "optional": false}], ["layers"]); +InspectorBackend.registerCommand("LayerTree.reasonsForCompositingLayer", [{"name": "layerId", "type": "string", "optional": false}], ["compositingReasons"]); +InspectorBackend.activateDomain("LayerTree", "web"); + +// Memory. +InspectorBackend.registerMemoryDispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, "Memory"); +InspectorBackend.registerEnum("Memory.CategoryDataType", {Javascript: "javascript", JIT: "jit", Images: "images", Layers: "layers", Page: "page", Other: "other"}); +InspectorBackend.registerEnum("Memory.MemoryPressureSeverity", {Critical: "critical", NonCritical: "non-critical"}); +InspectorBackend.registerEvent("Memory.memoryPressure", ["timestamp", "severity"]); +InspectorBackend.registerEvent("Memory.trackingStart", ["timestamp"]); +InspectorBackend.registerEvent("Memory.trackingUpdate", ["event"]); +InspectorBackend.registerEvent("Memory.trackingComplete", []); +InspectorBackend.registerCommand("Memory.enable", [], []); +InspectorBackend.registerCommand("Memory.disable", [], []); +InspectorBackend.registerCommand("Memory.startTracking", [], []); +InspectorBackend.registerCommand("Memory.stopTracking", [], []); +InspectorBackend.activateDomain("Memory", "web"); + +// Network. +InspectorBackend.registerNetworkDispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, "Network"); +InspectorBackend.registerEnum("Network.InitiatorType", {Parser: "parser", Script: "script", Other: "other"}); +InspectorBackend.registerEvent("Network.requestWillBeSent", ["requestId", "frameId", "loaderId", "documentURL", "request", "timestamp", "initiator", "redirectResponse", "type", "targetId"]); +InspectorBackend.registerEvent("Network.requestServedFromCache", ["requestId"]); +InspectorBackend.registerEvent("Network.responseReceived", ["requestId", "frameId", "loaderId", "timestamp", "type", "response"]); +InspectorBackend.registerEvent("Network.dataReceived", ["requestId", "timestamp", "dataLength", "encodedDataLength"]); +InspectorBackend.registerEvent("Network.loadingFinished", ["requestId", "timestamp", "sourceMapURL"]); +InspectorBackend.registerEvent("Network.loadingFailed", ["requestId", "timestamp", "errorText", "canceled"]); +InspectorBackend.registerEvent("Network.requestServedFromMemoryCache", ["requestId", "frameId", "loaderId", "documentURL", "timestamp", "initiator", "resource"]); +InspectorBackend.registerEvent("Network.webSocketWillSendHandshakeRequest", ["requestId", "timestamp", "request"]); +InspectorBackend.registerEvent("Network.webSocketHandshakeResponseReceived", ["requestId", "timestamp", "response"]); +InspectorBackend.registerEvent("Network.webSocketCreated", ["requestId", "url"]); +InspectorBackend.registerEvent("Network.webSocketClosed", ["requestId", "timestamp"]); +InspectorBackend.registerEvent("Network.webSocketFrameReceived", ["requestId", "timestamp", "response"]); +InspectorBackend.registerEvent("Network.webSocketFrameError", ["requestId", "timestamp", "errorMessage"]); +InspectorBackend.registerEvent("Network.webSocketFrameSent", ["requestId", "timestamp", "response"]); +InspectorBackend.registerCommand("Network.enable", [], []); +InspectorBackend.registerCommand("Network.disable", [], []); +InspectorBackend.registerCommand("Network.setExtraHTTPHeaders", [{"name": "headers", "type": "object", "optional": false}], []); +InspectorBackend.registerCommand("Network.getResponseBody", [{"name": "requestId", "type": "string", "optional": false}], ["body", "base64Encoded"]); +InspectorBackend.registerCommand("Network.setCacheDisabled", [{"name": "cacheDisabled", "type": "boolean", "optional": false}], []); +InspectorBackend.registerCommand("Network.loadResource", [{"name": "frameId", "type": "string", "optional": false}, {"name": "url", "type": "string", "optional": false}], ["content", "mimeType", "status"]); +InspectorBackend.activateDomain("Network", "web"); + +// Page. +InspectorBackend.registerPageDispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, "Page"); +InspectorBackend.registerEnum("Page.ResourceType", {Document: "Document", Stylesheet: "Stylesheet", Image: "Image", Font: "Font", Script: "Script", XHR: "XHR", Fetch: "Fetch", WebSocket: "WebSocket", Other: "Other"}); +InspectorBackend.registerEnum("Page.CoordinateSystem", {Viewport: "Viewport", Page: "Page"}); +InspectorBackend.registerEvent("Page.domContentEventFired", ["timestamp"]); +InspectorBackend.registerEvent("Page.loadEventFired", ["timestamp"]); +InspectorBackend.registerEvent("Page.frameNavigated", ["frame"]); +InspectorBackend.registerEvent("Page.frameDetached", ["frameId"]); +InspectorBackend.registerEvent("Page.frameStartedLoading", ["frameId"]); +InspectorBackend.registerEvent("Page.frameStoppedLoading", ["frameId"]); +InspectorBackend.registerEvent("Page.frameScheduledNavigation", ["frameId", "delay"]); +InspectorBackend.registerEvent("Page.frameClearedScheduledNavigation", ["frameId"]); +InspectorBackend.registerCommand("Page.enable", [], []); +InspectorBackend.registerCommand("Page.disable", [], []); +InspectorBackend.registerCommand("Page.addScriptToEvaluateOnLoad", [{"name": "scriptSource", "type": "string", "optional": false}], ["identifier"]); +InspectorBackend.registerCommand("Page.removeScriptToEvaluateOnLoad", [{"name": "identifier", "type": "string", "optional": false}], []); +InspectorBackend.registerCommand("Page.reload", [{"name": "ignoreCache", "type": "boolean", "optional": true}, {"name": "scriptToEvaluateOnLoad", "type": "string", "optional": true}], []); +InspectorBackend.registerCommand("Page.navigate", [{"name": "url", "type": "string", "optional": false}], []); +InspectorBackend.registerCommand("Page.getCookies", [], ["cookies"]); +InspectorBackend.registerCommand("Page.deleteCookie", [{"name": "cookieName", "type": "string", "optional": false}, {"name": "url", "type": "string", "optional": false}], []); +InspectorBackend.registerCommand("Page.getResourceTree", [], ["frameTree"]); +InspectorBackend.registerCommand("Page.getResourceContent", [{"name": "frameId", "type": "string", "optional": false}, {"name": "url", "type": "string", "optional": false}], ["content", "base64Encoded"]); +InspectorBackend.registerCommand("Page.searchInResource", [{"name": "frameId", "type": "string", "optional": false}, {"name": "url", "type": "string", "optional": false}, {"name": "query", "type": "string", "optional": false}, {"name": "caseSensitive", "type": "boolean", "optional": true}, {"name": "isRegex", "type": "boolean", "optional": true}, {"name": "requestId", "type": "string", "optional": true}], ["result"]); +InspectorBackend.registerCommand("Page.searchInResources", [{"name": "text", "type": "string", "optional": false}, {"name": "caseSensitive", "type": "boolean", "optional": true}, {"name": "isRegex", "type": "boolean", "optional": true}], ["result"]); +InspectorBackend.registerCommand("Page.setShowPaintRects", [{"name": "result", "type": "boolean", "optional": false}], []); +InspectorBackend.registerCommand("Page.setEmulatedMedia", [{"name": "media", "type": "string", "optional": false}], []); +InspectorBackend.registerCommand("Page.getCompositingBordersVisible", [], ["result"]); +InspectorBackend.registerCommand("Page.setCompositingBordersVisible", [{"name": "visible", "type": "boolean", "optional": false}], []); +InspectorBackend.registerCommand("Page.snapshotNode", [{"name": "nodeId", "type": "number", "optional": false}], ["dataURL"]); +InspectorBackend.registerCommand("Page.snapshotRect", [{"name": "x", "type": "number", "optional": false}, {"name": "y", "type": "number", "optional": false}, {"name": "width", "type": "number", "optional": false}, {"name": "height", "type": "number", "optional": false}, {"name": "coordinateSystem", "type": "string", "optional": false}], ["dataURL"]); +InspectorBackend.registerCommand("Page.archive", [], ["data"]); +InspectorBackend.activateDomain("Page", "web"); + +// Runtime. +InspectorBackend.registerRuntimeDispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, "Runtime"); +InspectorBackend.registerEnum("Runtime.RemoteObjectType", {Object: "object", Function: "function", Undefined: "undefined", String: "string", Number: "number", Boolean: "boolean", Symbol: "symbol"}); +InspectorBackend.registerEnum("Runtime.RemoteObjectSubtype", {Array: "array", Null: "null", Node: "node", Regexp: "regexp", Date: "date", Error: "error", Map: "map", Set: "set", Weakmap: "weakmap", Weakset: "weakset", Iterator: "iterator", Class: "class", Proxy: "proxy"}); +InspectorBackend.registerEnum("Runtime.ObjectPreviewType", {Object: "object", Function: "function", Undefined: "undefined", String: "string", Number: "number", Boolean: "boolean", Symbol: "symbol"}); +InspectorBackend.registerEnum("Runtime.ObjectPreviewSubtype", {Array: "array", Null: "null", Node: "node", Regexp: "regexp", Date: "date", Error: "error", Map: "map", Set: "set", Weakmap: "weakmap", Weakset: "weakset", Iterator: "iterator", Class: "class", Proxy: "proxy"}); +InspectorBackend.registerEnum("Runtime.PropertyPreviewType", {Object: "object", Function: "function", Undefined: "undefined", String: "string", Number: "number", Boolean: "boolean", Symbol: "symbol", Accessor: "accessor"}); +InspectorBackend.registerEnum("Runtime.PropertyPreviewSubtype", {Array: "array", Null: "null", Node: "node", Regexp: "regexp", Date: "date", Error: "error", Map: "map", Set: "set", Weakmap: "weakmap", Weakset: "weakset", Iterator: "iterator", Class: "class", Proxy: "proxy"}); +InspectorBackend.registerEnum("Runtime.SyntaxErrorType", {None: "none", Irrecoverable: "irrecoverable", UnterminatedLiteral: "unterminated-literal", Recoverable: "recoverable"}); +InspectorBackend.registerEvent("Runtime.executionContextCreated", ["context"]); +InspectorBackend.registerCommand("Runtime.parse", [{"name": "source", "type": "string", "optional": false}], ["result", "message", "range"]); +InspectorBackend.registerCommand("Runtime.evaluate", [{"name": "expression", "type": "string", "optional": false}, {"name": "objectGroup", "type": "string", "optional": true}, {"name": "includeCommandLineAPI", "type": "boolean", "optional": true}, {"name": "doNotPauseOnExceptionsAndMuteConsole", "type": "boolean", "optional": true}, {"name": "contextId", "type": "number", "optional": true}, {"name": "returnByValue", "type": "boolean", "optional": true}, {"name": "generatePreview", "type": "boolean", "optional": true}, {"name": "saveResult", "type": "boolean", "optional": true}], ["result", "wasThrown", "savedResultIndex"]); +InspectorBackend.registerCommand("Runtime.callFunctionOn", [{"name": "objectId", "type": "string", "optional": false}, {"name": "functionDeclaration", "type": "string", "optional": false}, {"name": "arguments", "type": "object", "optional": true}, {"name": "doNotPauseOnExceptionsAndMuteConsole", "type": "boolean", "optional": true}, {"name": "returnByValue", "type": "boolean", "optional": true}, {"name": "generatePreview", "type": "boolean", "optional": true}], ["result", "wasThrown"]); +InspectorBackend.registerCommand("Runtime.getProperties", [{"name": "objectId", "type": "string", "optional": false}, {"name": "ownProperties", "type": "boolean", "optional": true}, {"name": "generatePreview", "type": "boolean", "optional": true}], ["result", "internalProperties"]); +InspectorBackend.registerCommand("Runtime.getDisplayableProperties", [{"name": "objectId", "type": "string", "optional": false}, {"name": "generatePreview", "type": "boolean", "optional": true}], ["properties", "internalProperties"]); +InspectorBackend.registerCommand("Runtime.getCollectionEntries", [{"name": "objectId", "type": "string", "optional": false}, {"name": "objectGroup", "type": "string", "optional": true}, {"name": "startIndex", "type": "number", "optional": true}, {"name": "numberToFetch", "type": "number", "optional": true}], ["entries"]); +InspectorBackend.registerCommand("Runtime.saveResult", [{"name": "value", "type": "object", "optional": false}, {"name": "contextId", "type": "number", "optional": true}], ["savedResultIndex"]); +InspectorBackend.registerCommand("Runtime.releaseObject", [{"name": "objectId", "type": "string", "optional": false}], []); +InspectorBackend.registerCommand("Runtime.releaseObjectGroup", [{"name": "objectGroup", "type": "string", "optional": false}], []); +InspectorBackend.registerCommand("Runtime.enable", [], []); +InspectorBackend.registerCommand("Runtime.disable", [], []); +InspectorBackend.registerCommand("Runtime.getRuntimeTypesForVariablesAtOffsets", [{"name": "locations", "type": "object", "optional": false}], ["types"]); +InspectorBackend.registerCommand("Runtime.enableTypeProfiler", [], []); +InspectorBackend.registerCommand("Runtime.disableTypeProfiler", [], []); +InspectorBackend.registerCommand("Runtime.enableControlFlowProfiler", [], []); +InspectorBackend.registerCommand("Runtime.disableControlFlowProfiler", [], []); +InspectorBackend.registerCommand("Runtime.getBasicBlocks", [{"name": "sourceID", "type": "string", "optional": false}], ["basicBlocks"]); +InspectorBackend.activateDomain("Runtime"); + +// ScriptProfiler. +InspectorBackend.registerScriptProfilerDispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, "ScriptProfiler"); +InspectorBackend.registerEnum("ScriptProfiler.EventType", {API: "API", Microtask: "Microtask", Other: "Other"}); +InspectorBackend.registerEvent("ScriptProfiler.trackingStart", ["timestamp"]); +InspectorBackend.registerEvent("ScriptProfiler.trackingUpdate", ["event"]); +InspectorBackend.registerEvent("ScriptProfiler.trackingComplete", ["samples"]); +InspectorBackend.registerEvent("ScriptProfiler.programmaticCaptureStarted", []); +InspectorBackend.registerEvent("ScriptProfiler.programmaticCaptureStopped", []); +InspectorBackend.registerCommand("ScriptProfiler.startTracking", [{"name": "includeSamples", "type": "boolean", "optional": true}], []); +InspectorBackend.registerCommand("ScriptProfiler.stopTracking", [], []); +InspectorBackend.activateDomain("ScriptProfiler"); + +// Timeline. +InspectorBackend.registerTimelineDispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, "Timeline"); +InspectorBackend.registerEnum("Timeline.EventType", {EventDispatch: "EventDispatch", ScheduleStyleRecalculation: "ScheduleStyleRecalculation", RecalculateStyles: "RecalculateStyles", InvalidateLayout: "InvalidateLayout", Layout: "Layout", Paint: "Paint", Composite: "Composite", RenderingFrame: "RenderingFrame", TimerInstall: "TimerInstall", TimerRemove: "TimerRemove", TimerFire: "TimerFire", EvaluateScript: "EvaluateScript", TimeStamp: "TimeStamp", Time: "Time", TimeEnd: "TimeEnd", FunctionCall: "FunctionCall", ProbeSample: "ProbeSample", ConsoleProfile: "ConsoleProfile", RequestAnimationFrame: "RequestAnimationFrame", CancelAnimationFrame: "CancelAnimationFrame", FireAnimationFrame: "FireAnimationFrame"}); +InspectorBackend.registerEnum("Timeline.Instrument", {ScriptProfiler: "ScriptProfiler", Timeline: "Timeline", Memory: "Memory", Heap: "Heap"}); +InspectorBackend.registerEvent("Timeline.eventRecorded", ["record"]); +InspectorBackend.registerEvent("Timeline.recordingStarted", ["startTime"]); +InspectorBackend.registerEvent("Timeline.recordingStopped", ["endTime"]); +InspectorBackend.registerEvent("Timeline.autoCaptureStarted", []); +InspectorBackend.registerEvent("Timeline.programmaticCaptureStarted", []); +InspectorBackend.registerEvent("Timeline.programmaticCaptureStopped", []); +InspectorBackend.registerCommand("Timeline.start", [{"name": "maxCallStackDepth", "type": "number", "optional": true}], []); +InspectorBackend.registerCommand("Timeline.stop", [], []); +InspectorBackend.registerCommand("Timeline.setAutoCaptureEnabled", [{"name": "enabled", "type": "boolean", "optional": false}], []); +InspectorBackend.registerCommand("Timeline.setInstruments", [{"name": "instruments", "type": "object", "optional": false}], []); +InspectorBackend.activateDomain("Timeline", "web"); + +// Worker. +InspectorBackend.registerWorkerDispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, "Worker"); +InspectorBackend.registerEvent("Worker.workerCreated", ["workerId", "url"]); +InspectorBackend.registerEvent("Worker.workerTerminated", ["workerId"]); +InspectorBackend.registerEvent("Worker.dispatchMessageFromWorker", ["workerId", "message"]); +InspectorBackend.registerCommand("Worker.enable", [], []); +InspectorBackend.registerCommand("Worker.disable", [], []); +InspectorBackend.registerCommand("Worker.initialized", [{"name": "workerId", "type": "string", "optional": false}], []); +InspectorBackend.registerCommand("Worker.sendMessageToWorker", [{"name": "workerId", "type": "string", "optional": false}, {"name": "message", "type": "string", "optional": false}], []); +InspectorBackend.activateDomain("Worker", "web"); diff --git a/webkit/WebInspectorUI/Versions/Inspector-iOS-10.3.json b/webkit/WebInspectorUI/Versions/Inspector-iOS-10.3.json new file mode 100755 index 000000000..328edb513 --- /dev/null +++ b/webkit/WebInspectorUI/Versions/Inspector-iOS-10.3.json @@ -0,0 +1,3714 @@ +{"domains":[ +{ + "domain": "ApplicationCache", + "availability": "web", + "types": [ + { + "id": "ApplicationCacheResource", + "type": "object", + "description": "Detailed application cache resource information.", + "properties": [ + { "name": "url", "type": "string", "description": "Resource url." }, + { "name": "size", "type": "integer", "description": "Resource size." }, + { "name": "type", "type": "string", "description": "Resource type." } + ] + }, + { + "id": "ApplicationCache", + "type": "object", + "description": "Detailed application cache information.", + "properties": [ + { "name": "manifestURL", "type": "string", "description": "Manifest URL." }, + { "name": "size", "type": "number", "description": "Application cache size." }, + { "name": "creationTime", "type": "number", "description": "Application cache creation time." }, + { "name": "updateTime", "type": "number", "description": "Application cache update time." }, + { "name": "resources", "type": "array", "items": { "$ref": "ApplicationCacheResource" }, "description": "Application cache resources." } + ] + }, + { + "id": "FrameWithManifest", + "type": "object", + "description": "Frame identifier - manifest URL pair.", + "properties": [ + { "name": "frameId", "$ref": "Network.FrameId", "description": "Frame identifier." }, + { "name": "manifestURL", "type": "string", "description": "Manifest URL." }, + { "name": "status", "type": "integer", "description": "Application cache status." } + ] + } + ], + "commands": [ + { + "name": "getFramesWithManifests", + "returns": [ + { "name": "frameIds", "type": "array", "items": { "$ref": "FrameWithManifest" }, "description": "Array of frame identifiers with manifest urls for each frame containing a document associated with some application cache." } + ], + "description": "Returns array of frame identifiers with manifest urls for each frame containing a document associated with some application cache." + }, + { + "name": "enable", + "description": "Enables application cache domain notifications." + }, + { + "name": "getManifestForFrame", + "parameters": [ + { "name": "frameId", "$ref": "Network.FrameId", "description": "Identifier of the frame containing document whose manifest is retrieved." } + ], + "returns": [ + { "name": "manifestURL", "type": "string", "description": "Manifest URL for document in the given frame." } + ], + "description": "Returns manifest URL for document in the given frame." + }, + { + "name": "getApplicationCacheForFrame", + "parameters": [ + { "name": "frameId", "$ref": "Network.FrameId", "description": "Identifier of the frame containing document whose application cache is retrieved." } + ], + "returns": [ + { "name": "applicationCache", "$ref": "ApplicationCache", "description": "Relevant application cache data for the document in given frame." } + ], + "description": "Returns relevant application cache data for the document in given frame." + } + ], + "events": [ + { + "name": "applicationCacheStatusUpdated", + "parameters": [ + { "name": "frameId", "$ref": "Network.FrameId", "description": "Identifier of the frame containing document whose application cache updated status." }, + { "name": "manifestURL", "type": "string", "description": "Manifest URL." }, + { "name": "status", "type": "integer", "description": "Updated application cache status." } + ] + }, + { + "name": "networkStateUpdated", + "parameters": [ + { "name": "isNowOnline", "type": "boolean" } + ] + } + ] +} +, +{ + "domain": "CSS", + "description": "This domain exposes CSS read/write operations. All CSS objects, like stylesheets, rules, and styles, have an associated id used in subsequent operations on the related object. Each object type has a specific id structure, and those are not interchangeable between objects of different kinds. CSS objects can be loaded using the get*ForNode() calls (which accept a DOM node id). Alternatively, a client can discover all the existing stylesheets with the getAllStyleSheets() method and subsequently load the required stylesheet contents using the getStyleSheet[Text]() methods.", + "availability": "web", + "types": [ + { + "id": "StyleSheetId", + "type": "string" + }, + { + "id": "CSSStyleId", + "type": "object", + "properties": [ + { "name": "styleSheetId", "$ref": "StyleSheetId", "description": "Enclosing stylesheet identifier." }, + { "name": "ordinal", "type": "integer", "description": "The style ordinal within the stylesheet." } + ], + "description": "This object identifies a CSS style in a unique way." + }, + { + "id": "StyleSheetOrigin", + "type": "string", + "enum": ["user", "user-agent", "inspector", "regular"], + "description": "Stylesheet type: \"user\" for user stylesheets, \"user-agent\" for user-agent stylesheets, \"inspector\" for stylesheets created by the inspector (i.e. those holding the \"via inspector\" rules), \"regular\" for regular stylesheets." + }, + { + "id": "CSSRuleId", + "type": "object", + "properties": [ + { "name": "styleSheetId", "$ref": "StyleSheetId", "description": "Enclosing stylesheet identifier." }, + { "name": "ordinal", "type": "integer", "description": "The rule ordinal within the stylesheet." } + ], + "description": "This object identifies a CSS rule in a unique way." + }, + { + "id": "PseudoIdMatches", + "type": "object", + "properties": [ + { "name": "pseudoId", "type": "integer", "description": "Pseudo style identifier (see enum PseudoId in RenderStyleConstants.h)."}, + { "name": "matches", "type": "array", "items": { "$ref": "RuleMatch" }, "description": "Matches of CSS rules applicable to the pseudo style."} + ], + "description": "CSS rule collection for a single pseudo style." + }, + { + "id": "InheritedStyleEntry", + "type": "object", + "properties": [ + { "name": "inlineStyle", "$ref": "CSSStyle", "optional": true, "description": "The ancestor node's inline style, if any, in the style inheritance chain." }, + { "name": "matchedCSSRules", "type": "array", "items": { "$ref": "RuleMatch" }, "description": "Matches of CSS rules matching the ancestor node in the style inheritance chain." } + ], + "description": "CSS rule collection for a single pseudo style." + }, + { + "id": "RuleMatch", + "type": "object", + "properties": [ + { "name": "rule", "$ref": "CSSRule", "description": "CSS rule in the match." }, + { "name": "matchingSelectors", "type": "array", "items": { "type": "integer" }, "description": "Matching selector indices in the rule's selectorList selectors (0-based)." } + ], + "description": "Match data for a CSS rule." + }, + { + "id": "CSSSelector", + "type": "object", + "properties": [ + { "name": "text", "type": "string", "description": "Canonicalized selector text." }, + { "name": "specificity", "optional": true, "type": "array", "items": { "type": "integer" }, "description": "Specificity (a, b, c) tuple. Included if the selector is sent in response to CSS.getMatchedStylesForNode which provides a context element." }, + { "name": "dynamic", "optional": true, "type": "boolean", "description": "Whether or not the specificity can be dynamic. Included if the selector is sent in response to CSS.getMatchedStylesForNode which provides a context element." } + ], + "description": "CSS selector." + }, + { + "id": "SelectorList", + "type": "object", + "properties": [ + { "name": "selectors", "type": "array", "items": { "$ref": "CSSSelector" }, "description": "Selectors in the list." }, + { "name": "text", "type": "string", "description": "Rule selector text." }, + { "name": "range", "$ref": "SourceRange", "optional": true, "description": "Rule selector range in the underlying resource (if available)." } + ], + "description": "Selector list data." + }, + { + "id": "CSSStyleAttribute", + "type": "object", + "properties": [ + { "name": "name", "type": "string", "description": "DOM attribute name (e.g. \"width\")."}, + { "name": "style", "$ref": "CSSStyle", "description": "CSS style generated by the respective DOM attribute."} + ], + "description": "CSS style information for a DOM style attribute." + }, + { + "id": "CSSStyleSheetHeader", + "type": "object", + "properties": [ + { "name": "styleSheetId", "$ref": "StyleSheetId", "description": "The stylesheet identifier."}, + { "name": "frameId", "$ref": "Network.FrameId", "description": "Owner frame identifier."}, + { "name": "sourceURL", "type": "string", "description": "Stylesheet resource URL."}, + { "name": "origin", "$ref": "StyleSheetOrigin", "description": "Stylesheet origin."}, + { "name": "title", "type": "string", "description": "Stylesheet title."}, + { "name": "disabled", "type": "boolean", "description": "Denotes whether the stylesheet is disabled."}, + { "name": "isInline", "type": "boolean", "description": "Whether this stylesheet is a