WinLauncher fails to download files.
[WebKit-https.git] / Source / WebKit / win / WebView.cpp
index 55ab7d3..80946fe 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2014 Apple, Inc.  All rights reserved.
+ * Copyright (C) 2006-2015 Apple, Inc.  All rights reserved.
  * Copyright (C) 2009, 2010, 2011 Appcelerator, Inc. All rights reserved.
  * Copyright (C) 2011 Brent Fulgham. All rights reserved.
  *
 #include "WebPreferences.h"
 #include "WebScriptWorld.h"
 #include "WebStorageNamespaceProvider.h"
+#include "WebViewGroup.h"
 #include "WebVisitedLinkStore.h"
 #include "resource.h"
 #include <JavaScriptCore/APICast.h>
+#include <JavaScriptCore/Exception.h>
 #include <JavaScriptCore/InitializeThreading.h>
 #include <JavaScriptCore/JSCJSValue.h>
 #include <JavaScriptCore/JSLock.h>
 #include <WebCore/SecurityPolicy.h>
 #include <WebCore/Settings.h>
 #include <WebCore/SystemInfo.h>
+#include <WebCore/UserContentController.h>
 #include <WebCore/WindowMessageBroadcaster.h>
 #include <WebCore/WindowsTouch.h>
 #include <bindings/ScriptValue.h>
 #include <wtf/MainThread.h>
+#include <wtf/RAMSize.h>
 
 #if USE(CG)
 #include <CoreGraphics/CGContext.h>
@@ -250,6 +254,15 @@ static inline URL toURL(BSTR bstr)
     return URL(URL(), toString(bstr));
 }
 
+static String localStorageDatabasePath(WebPreferences* preferences)
+{
+    BString localStorageDatabasePath;
+    if (FAILED(preferences->localStorageDatabasePath(&localStorageDatabasePath)))
+        return String();
+
+    return toString(localStorageDatabasePath);
+}
+
 class PreferencesChangedOrRemovedObserver : public IWebNotificationObserver {
 public:
     static PreferencesChangedOrRemovedObserver* sharedInstance();
@@ -434,6 +447,9 @@ WebView::WebView()
     if (SUCCEEDED(sharedPreferences->grammarCheckingEnabled(&enabled)))
         grammarCheckingEnabled = !!enabled;
 
+    m_webViewGroup = WebViewGroup::getOrCreate(String(), localStorageDatabasePath(sharedPreferences));
+    m_webViewGroup->addWebView(this);
+
     WebViewCount++;
     gClassCount++;
     gClassNameCount().add("WebView");
@@ -455,6 +471,8 @@ WebView::~WebView()
     ASSERT(!m_layerTreeHost);
 #endif
 
+    m_webViewGroup->removeWebView(this);
+
     WebViewCount--;
     gClassCount--;
     gClassNameCount().remove("WebView");
@@ -521,9 +539,10 @@ void WebView::setCacheModel(WebCacheModel cacheModel)
     long cacheDiskCapacity = 0;
 #endif
 
+    unsigned long long memSize = ramSize() / 1024 / 1024;
+
     // As a fudge factor, use 1000 instead of 1024, in case the reported byte 
     // count doesn't align exactly to a megabyte boundary.
-    unsigned long long memSize = WebMemorySize() / 1024 / 1000;
     unsigned long long diskFreeSize = WebVolumeFreeSize(cacheDirectory) / 1024 / 1000;
 
     unsigned cacheTotalCapacity = 0;
@@ -1264,14 +1283,19 @@ void WebView::frameRect(RECT* rect)
     ::GetWindowRect(m_viewWindow, rect);
 }
 
-class WindowCloseTimer : public WebCore::SuspendableTimer {
+class WindowCloseTimer final : public WebCore::SuspendableTimer {
 public:
     static WindowCloseTimer* create(WebView*);
 
 private:
     WindowCloseTimer(ScriptExecutionContext&, WebView*);
-    virtual void contextDestroyed();
-    virtual void fired();
+
+    // ActiveDOMObject API.
+    void contextDestroyed() override;
+    const char* activeDOMObjectName() const override { return "WindowCloseTimer"; }
+
+    // SuspendableTimer API.
+    void fired() override;
 
     WebView* m_webView;
 };
@@ -2241,7 +2265,7 @@ LRESULT CALLBACK WebView::WebViewWndProc(HWND hWnd, UINT message, WPARAM wParam,
     ASSERT(webView);
 
     // Windows Media Player has a modal message loop that will deliver messages
-    // to us at inappropriate times and we will crash if we handle them when
+    // to us at inappropriate times and we will crash if we handle them when:
     // they are delivered. We repost paint messages so that we eventually get
     // a chance to paint once the modal loop has exited, but other messages
     // aren't safe to repost, so we just drop them.
@@ -2496,8 +2520,7 @@ LRESULT CALLBACK WebView::WebViewWndProc(HWND hWnd, UINT message, WPARAM wParam,
             break;
     }
 
-    if (webView->needsDisplay() && message != WM_PAINT)
-        ::UpdateWindow(hWnd);
+    webView->updateWindowIfNeeded(hWnd, message);
 
     if (!handled)
         lResult = DefWindowProc(hWnd, message, wParam, lParam);
@@ -2506,6 +2529,24 @@ LRESULT CALLBACK WebView::WebViewWndProc(HWND hWnd, UINT message, WPARAM wParam,
     return (message == WM_KEYDOWN || message == WM_SYSKEYDOWN || message == WM_KEYUP || message == WM_SYSKEYUP) ? !handled : lResult;
 }
 
+void WebView::updateWindowIfNeeded(HWND hWnd, UINT message)
+{
+    if (!needsDisplay())
+        return;
+
+    // Care should be taken when updating the window from the window procedure.
+    // Updating the window in response to e.g. WM_PARENTNOTIFY may cause reentrancy problems,
+    // because WM_PARENTNOTIFY is sent synchronously to the parent window when e.g. DestroyWindow() is called.
+
+    switch (message) {
+    case WM_PAINT:
+    case WM_PARENTNOTIFY:
+        return;
+    }
+
+    ::UpdateWindow(hWnd);
+}
+
 bool WebView::developerExtrasEnabled() const
 {
     if (m_preferences->developerExtrasDisabledByOverride())
@@ -2624,8 +2665,8 @@ bool WebView::canShowMIMEType(const String& mimeType)
         || MIMETypeRegistry::isSupportedMediaMIMEType(mimeType);
 
     if (!canShow && m_page) {
-        canShow = (m_page->pluginData().supportsMimeType(mimeType, PluginData::AllPlugins) && allowPlugins)
-            || m_page->pluginData().supportsMimeType(mimeType, PluginData::OnlyApplicationPlugins);
+        canShow = (m_page->pluginData().supportsWebVisibleMimeType(mimeType, PluginData::AllPlugins) && allowPlugins)
+            || m_page->pluginData().supportsWebVisibleMimeType(mimeType, PluginData::OnlyApplicationPlugins);
     }
 
     if (!canShow)
@@ -2697,7 +2738,7 @@ static void WebKitSetApplicationCachePathIfNecessary()
 #endif
 
     if (!path.isNull())
-        cacheStorage().setCacheDirectory(path);
+        ApplicationCacheStorage::singleton().setCacheDirectory(path);
 
     initialized = true;
 }
@@ -2730,15 +2771,6 @@ bool WebView::shouldInitializeTrackPointHack()
     return shouldCreateScrollbars;
 }
 
-static String localStorageDatabasePath(WebPreferences* preferences)
-{
-    BString localStorageDatabasePath;
-    if (FAILED(preferences->localStorageDatabasePath(&localStorageDatabasePath)))
-        return String();
-
-    return toString(localStorageDatabasePath);
-}
-
 HRESULT STDMETHODCALLTYPE WebView::initWithFrame( 
     /* [in] */ RECT frame,
     /* [in] */ BSTR frameName,
@@ -2783,17 +2815,10 @@ HRESULT STDMETHODCALLTYPE WebView::initWithFrame(
 
         WebKitInitializeWebDatabasesIfNecessary();
         WebKitSetApplicationCachePathIfNecessary();
-        Settings::setDefaultMinDOMTimerInterval(0.004);
 
         didOneTimeInitialization = true;
      }
 
-#if USE(SAFARI_THEME)
-    BOOL shouldPaintNativeControls;
-    if (SUCCEEDED(m_preferences->shouldPaintNativeControls(&shouldPaintNativeControls)))
-        Settings::setShouldPaintNativeControls(shouldPaintNativeControls);
-#endif
-
     BOOL useHighResolutionTimer;
     if (SUCCEEDED(m_preferences->shouldUseHighResolutionTimers(&useHighResolutionTimer)))
         Settings::setShouldUseHighResolutionTimers(useHighResolutionTimer);
@@ -2808,9 +2833,10 @@ HRESULT STDMETHODCALLTYPE WebView::initWithFrame(
     configuration.inspectorClient = m_inspectorClient;
     configuration.loaderClientForMainFrame = new WebFrameLoaderClient;
     configuration.databaseProvider = &WebDatabaseProvider::singleton();
-    configuration.storageNamespaceProvider = WebStorageNamespaceProvider::create(localStorageDatabasePath(m_preferences.get()));
+    configuration.storageNamespaceProvider = &m_webViewGroup->storageNamespaceProvider();
     configuration.progressTrackerClient = static_cast<WebFrameLoaderClient*>(configuration.loaderClientForMainFrame);
-    configuration.visitedLinkStore = &WebVisitedLinkStore::singleton();
+    configuration.userContentController = &m_webViewGroup->userContentController();
+    configuration.visitedLinkStore = &m_webViewGroup->visitedLinkStore();
 
     m_page = new Page(configuration);
     provideGeolocationTo(m_page, new WebGeolocationClient(this));
@@ -2848,6 +2874,8 @@ HRESULT STDMETHODCALLTYPE WebView::initWithFrame(
     notifyCenter->addObserver(this, WebPreferences::webPreferencesChangedNotification(), static_cast<IWebPreferences*>(m_preferences.get()));
     m_preferences->postPreferencesChangesNotification();
 
+    m_page->setDeviceScaleFactor(deviceScaleFactor());
+
     setSmartInsertDeleteEnabled(TRUE);
     return hr;
 }
@@ -3510,6 +3538,9 @@ HRESULT WebView::setHostWindow(/* [in] */ HWND window)
 
     windowAncestryDidChange();
 
+    if (m_page)
+        m_page->setDeviceScaleFactor(deviceScaleFactor());
+
     return S_OK;
 }
 
@@ -3677,8 +3708,17 @@ HRESULT STDMETHODCALLTYPE WebView::registerViewClass(
 HRESULT STDMETHODCALLTYPE WebView::setGroupName( 
         /* [in] */ BSTR groupName)
 {
+    if (m_webViewGroup)
+        m_webViewGroup->removeWebView(this);
+
+    m_webViewGroup = WebViewGroup::getOrCreate(groupName, localStorageDatabasePath(m_preferences.get()));
+    m_webViewGroup->addWebView(this);
+
     if (!m_page)
         return S_OK;
+
+    m_page->setUserContentController(&m_webViewGroup->userContentController());
+    m_page->setVisitedLinkStore(m_webViewGroup->visitedLinkStore());
     m_page->setGroupName(toString(groupName));
     return S_OK;
 }
@@ -3948,7 +3988,7 @@ HRESULT STDMETHODCALLTYPE WebView::canGoBack(
         /* [in] */ IUnknown* /*sender*/,
         /* [retval][out] */ BOOL* result)
 {
-    *result = !!(m_page->backForward().client()->backItem() && !m_page->defersLoading());
+    *result = !!(m_page->backForward().backItem() && !m_page->defersLoading());
     return S_OK;
 }
     
@@ -3963,7 +4003,7 @@ HRESULT STDMETHODCALLTYPE WebView::canGoForward(
         /* [in] */ IUnknown* /*sender*/,
         /* [retval][out] */ BOOL* result)
 {
-    *result = !!(m_page->backForward().client()->forwardItem() && !m_page->defersLoading());
+    *result = !!(m_page->backForward().forwardItem() && !m_page->defersLoading());
     return S_OK;
 }
     
@@ -4996,7 +5036,7 @@ HRESULT WebView::notifyPreferencesChanged(IWebNotification* notification)
     hr = prefsPrivate->databasesEnabled(&enabled);
     if (FAILED(hr))
         return hr;
-    DatabaseManager::manager().setIsAvailable(enabled);
+    DatabaseManager::singleton().setIsAvailable(enabled);
 
     hr = prefsPrivate->localStorageEnabled(&enabled);
     if (FAILED(hr))
@@ -5033,13 +5073,6 @@ HRESULT WebView::notifyPreferencesChanged(IWebNotification* notification)
         return hr;
     settings.setXSSAuditorEnabled(!!enabled);
 
-#if USE(SAFARI_THEME)
-    hr = prefsPrivate->shouldPaintNativeControls(&enabled);
-    if (FAILED(hr))
-        return hr;
-    settings.setShouldPaintNativeControls(!!enabled);
-#endif
-
     hr = prefsPrivate->shouldUseHighResolutionTimers(&enabled);
     if (FAILED(hr))
         return hr;
@@ -5115,12 +5148,12 @@ HRESULT WebView::notifyPreferencesChanged(IWebNotification* notification)
     hr = prefsPrivate->mediaPlaybackRequiresUserGesture(&enabled);
     if (FAILED(hr))
         return hr;
-    settings.setMediaPlaybackRequiresUserGesture(enabled);
+    settings.setRequiresUserGestureForMediaPlayback(enabled);
 
     hr = prefsPrivate->mediaPlaybackAllowsInline(&enabled);
     if (FAILED(hr))
         return hr;
-    settings.setMediaPlaybackAllowsInline(enabled);
+    settings.setAllowsInlineMediaPlayback(enabled);
 
     hr = prefsPrivate->shouldInvertColors(&enabled);
     if (FAILED(hr))
@@ -5238,7 +5271,23 @@ HRESULT STDMETHODCALLTYPE WebView::formDelegate(
 HRESULT STDMETHODCALLTYPE WebView::setFrameLoadDelegatePrivate( 
     /* [in] */ IWebFrameLoadDelegatePrivate* d)
 {
+    if (m_frameLoadDelegatePrivate == d)
+        return S_OK;
+
+    static BSTR webViewProgressFinishedNotificationName = SysAllocString(WebViewProgressFinishedNotification);
+
+    IWebNotificationCenter* notifyCenter = WebNotificationCenter::defaultCenterInternal();
+
+    COMPtr<IWebNotificationObserver> wasObserver(Query, m_frameLoadDelegatePrivate);
+    if (wasObserver)
+        notifyCenter->removeObserver(wasObserver.get(), webViewProgressFinishedNotificationName, nullptr);
+
     m_frameLoadDelegatePrivate = d;
+
+    COMPtr<IWebNotificationObserver> isObserver(Query, m_frameLoadDelegatePrivate);
+    if (isObserver)
+        notifyCenter->addObserver(isObserver.get(), webViewProgressFinishedNotificationName, nullptr);
+
     return S_OK;
 }
 
@@ -5481,30 +5530,30 @@ HRESULT STDMETHODCALLTYPE WebView::loadBackForwardListFromOtherView(
     // It turns out the right combination of behavior is done with the back/forward load
     // type.  (See behavior matrix at the top of WebFramePrivate.)  So we copy all the items
     // in the back forward list, and go to the current one.
-    BackForwardClient* backForwardClient = m_page->backForward().client();
-    ASSERT(!backForwardClient->currentItem()); // destination list should be empty
+    BackForwardController& backForward = m_page->backForward();
+    ASSERT(!backForward.currentItem()); // destination list should be empty
 
     COMPtr<WebView> otherWebView;
     if (FAILED(otherView->QueryInterface(&otherWebView)))
         return E_FAIL;
-    BackForwardClient* otherBackForwardClient = otherWebView->m_page->backForward().client();
-    if (!otherBackForwardClient->currentItem())
+    BackForwardController& otherBackForward = otherWebView->m_page->backForward();
+    if (!otherBackForward.currentItem())
         return S_OK; // empty back forward list, bail
     
     HistoryItem* newItemToGoTo = 0;
 
-    int lastItemIndex = otherBackForwardClient->forwardListCount();
-    for (int i = -otherBackForwardClient->backListCount(); i <= lastItemIndex; ++i) {
+    int lastItemIndex = otherBackForward.forwardCount();
+    for (int i = -otherBackForward.backCount(); i <= lastItemIndex; ++i) {
         if (!i) {
             // If this item is showing , save away its current scroll and form state,
             // since that might have changed since loading and it is normally not saved
             // until we leave that page.
             otherWebView->m_page->mainFrame().loader().history().saveDocumentAndScrollState();
         }
-        Ref<HistoryItem> newItem = otherBackForwardClient->itemAtIndex(i)->copy();
+        Ref<HistoryItem> newItem = otherBackForward.itemAtIndex(i)->copy();
         if (!i) 
             newItemToGoTo = newItem.ptr();
-        backForwardClient->addItem(WTF::move(newItem));
+        backForward.client()->addItem(WTF::move(newItem));
     }
     
     ASSERT(newItemToGoTo);
@@ -5978,6 +6027,9 @@ HRESULT STDMETHODCALLTYPE WebView::windowAncestryDidChange()
     if (m_topLevelParent)
         WindowMessageBroadcaster::addListener(m_topLevelParent, this);
 
+    if (m_page)
+        m_page->setDeviceScaleFactor(deviceScaleFactor());
+
     updateActiveState();
 
     return S_OK;
@@ -6348,14 +6400,14 @@ HRESULT WebView::setCanStartPlugins(BOOL canStartPlugins)
     return S_OK;
 }
 
-void WebView::enterVideoFullscreenForVideoElement(HTMLVideoElement* videoElement)
+void WebView::enterVideoFullscreenForVideoElement(HTMLVideoElement& videoElement)
 {
 #if ENABLE(VIDEO) && !USE(GSTREAMER) && !USE(MEDIA_FOUNDATION)
     if (m_fullScreenVideoController) {
-        if (m_fullScreenVideoController->videoElement() == videoElement) {
+        if (m_fullScreenVideoController->videoElement() == &videoElement) {
             // The backend may just warn us that the underlaying plaftormMovie()
             // has changed. Just force an update.
-            m_fullScreenVideoController->setVideoElement(videoElement);
+            m_fullScreenVideoController->setVideoElement(&videoElement);
             return; // No more to do.
         }
 
@@ -6367,12 +6419,12 @@ void WebView::enterVideoFullscreenForVideoElement(HTMLVideoElement* videoElement
     }
 
     m_fullScreenVideoController = std::make_unique<FullscreenVideoController>();
-    m_fullScreenVideoController->setVideoElement(videoElement);
+    m_fullScreenVideoController->setVideoElement(&videoElement);
     m_fullScreenVideoController->enterFullscreen();
 #endif
 }
 
-void WebView::exitVideoFullscreen()
+void WebView::exitVideoFullscreenForVideoElement(WebCore::HTMLVideoElement&)
 {
 #if ENABLE(VIDEO) && !USE(GSTREAMER) && !USE(MEDIA_FOUNDATION)
     if (!m_fullScreenVideoController)
@@ -6476,7 +6528,7 @@ HRESULT WebView::historyDelegate(IWebHistoryDelegate** historyDelegate)
 
 HRESULT WebView::addVisitedLinks(BSTR* visitedURLs, unsigned visitedURLCount)
 {
-    auto& visitedLinkStore = WebVisitedLinkStore::singleton();
+    auto& visitedLinkStore = m_webViewGroup->visitedLinkStore();
     PageGroup& group = core(this)->group();
     
     for (unsigned i = 0; i < visitedURLCount; ++i) {
@@ -6491,6 +6543,9 @@ HRESULT WebView::addVisitedLinks(BSTR* visitedURLs, unsigned visitedURLCount)
 
 void WebView::downloadURL(const URL& url)
 {
+    if (!m_downloadDelegate)
+        return;
+
     // It's the delegate's job to ref the WebDownload to keep it alive - otherwise it will be
     // destroyed when this function returns.
 #if USE(CURL)
@@ -6831,13 +6886,13 @@ HRESULT WebView::defaultMinimumTimerInterval(double* interval)
 {
     if (!interval)
         return E_POINTER;
-    *interval = Settings::defaultMinDOMTimerInterval();
+    *interval = DOMTimer::defaultMinimumInterval();
     return S_OK;
 }
 
 HRESULT WebView::setMinimumTimerInterval(double interval)
 {
-    page()->settings().setMinDOMTimerInterval(interval);
+    page()->settings().setMinimumDOMTimerInterval(interval);
     return S_OK;
 }
 
@@ -7099,3 +7154,53 @@ HRESULT WebView::scaleWebView(double scale, POINT origin)
 
     return S_OK;
 }
+
+HRESULT WebView::dispatchPendingLoadRequests()
+{
+    resourceLoadScheduler()->servePendingRequests();
+    return S_OK;
+}
+
+static float scaleFactorFromWindow(HWND window)
+{
+    HWndDC dc(window);
+    return ::GetDeviceCaps(dc, LOGPIXELSX) / 96.0f;
+}
+
+float WebView::deviceScaleFactor() const
+{
+    if (m_customDeviceScaleFactor)
+        return m_customDeviceScaleFactor;
+
+    // FIXME(146335): Should check for Windows 8.1 High DPI Features here first.
+
+    if (m_viewWindow)
+        return scaleFactorFromWindow(m_viewWindow);
+
+    if (m_hostWindow)
+        return scaleFactorFromWindow(m_hostWindow);
+
+    return scaleFactorFromWindow(0);
+}
+
+HRESULT WebView::setCustomBackingScaleFactor(double customScaleFactor)
+{
+    double oldScaleFactor = deviceScaleFactor();
+
+    m_customDeviceScaleFactor = customScaleFactor;
+
+    if (oldScaleFactor != deviceScaleFactor())
+        m_page->setDeviceScaleFactor(deviceScaleFactor());
+
+    return S_OK;
+}
+
+HRESULT WebView::backingScaleFactor(double* factor)
+{
+    if (!factor)
+        return E_POINTER;
+
+    *factor = deviceScaleFactor();
+
+    return S_OK;
+}