blob: a7d73c560ff8204e47ad9c7ba514ff7b19786fa2 [file] [log] [blame]
/*
* Copyright (C) 2010-2020 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 "EventSendingController.h"
#include "GCController.h"
#include "TestRunner.h"
#include "TextInputController.h"
#include <WebKit/WKBase.h>
#include <WebKit/WKBundlePage.h>
#include <WebKit/WKRetainPtr.h>
#include <sstream>
#include <wtf/Forward.h>
#include <wtf/RefPtr.h>
#include <wtf/Vector.h>
#if ENABLE(ACCESSIBILITY)
#include "AccessibilityController.h"
#endif
namespace WTR {
class InjectedBundlePage;
class InjectedBundle {
public:
static InjectedBundle& singleton();
// Initialize the InjectedBundle.
void initialize(WKBundleRef, WKTypeRef initializationUserData);
WKBundleRef bundle() const { return m_bundle.get(); }
TestRunner* testRunner() { return m_testRunner.get(); }
GCController* gcController() { return m_gcController.get(); }
EventSendingController* eventSendingController() { return m_eventSendingController.get(); }
TextInputController* textInputController() { return m_textInputController.get(); }
#if ENABLE(ACCESSIBILITY)
AccessibilityController* accessibilityController() { return m_accessibilityController.get(); }
#endif
InjectedBundlePage* page() const;
WKBundlePageRef pageRef() const;
size_t pageCount() const { return m_pages.size(); }
void dumpBackForwardListsForAllPages(StringBuilder&);
void done();
void setAudioResult(WKDataRef audioData) { m_audioResult = audioData; }
void setPixelResult(WKImageRef image) { m_pixelResult = image; m_pixelResultIsPending = false; }
void setPixelResultIsPending(bool isPending) { m_pixelResultIsPending = isPending; }
void setRepaintRects(WKArrayRef rects) { m_repaintRects = rects; }
bool isTestRunning() { return m_state == Testing; }
WKBundleFrameRef topLoadingFrame() { return m_topLoadingFrame; }
void setTopLoadingFrame(WKBundleFrameRef frame) { m_topLoadingFrame = frame; }
bool shouldDumpPixels() const { return m_dumpPixels; }
bool dumpJSConsoleLogInStdErr() const { return m_dumpJSConsoleLogInStdErr; };
enum class IsFinalTestOutput : bool { No, Yes };
void outputText(StringView, IsFinalTestOutput = IsFinalTestOutput::No);
void dumpToStdErr(const String&);
void postNewBeforeUnloadReturnValue(bool);
void postAddChromeInputField();
void postRemoveChromeInputField();
void postSetTextInChromeInputField(const String&);
void postSelectChromeInputField();
void postGetSelectedTextInChromeInputField();
void postFocusWebView();
void postSetBackingScaleFactor(double);
void postSetWindowIsKey(bool);
void postSetViewSize(double width, double height);
void postSimulateWebNotificationClick(WKDataRef notificationID);
void postSimulateWebNotificationClickForServiceWorkerNotifications();
void postSetAddsVisitedLinks(bool);
// Geolocation.
void setGeolocationPermission(bool);
void setMockGeolocationPosition(double latitude, double longitude, double accuracy, std::optional<double> altitude, std::optional<double> altitudeAccuracy, std::optional<double> heading, std::optional<double> speed, std::optional<double> floorLevel);
void setMockGeolocationPositionUnavailableError(WKStringRef errorMessage);
bool isGeolocationProviderActive() const;
// MediaStream.
void setUserMediaPermission(bool);
void resetUserMediaPermission();
void setUserMediaPersistentPermissionForOrigin(bool permission, WKStringRef origin, WKStringRef parentOrigin);
unsigned userMediaPermissionRequestCountForOrigin(WKStringRef origin, WKStringRef parentOrigin) const;
void resetUserMediaPermissionRequestCountForOrigin(WKStringRef origin, WKStringRef parentOrigin);
// Policy delegate.
void setCustomPolicyDelegate(bool enabled, bool permissive);
// Page Visibility.
void setHidden(bool);
// Cache.
void setCacheModel(int);
// Work queue.
bool shouldProcessWorkQueue() const;
void processWorkQueue();
void queueBackNavigation(unsigned howFarBackward);
void queueForwardNavigation(unsigned howFarForward);
void queueLoad(WKStringRef url, WKStringRef target, bool shouldOpenExternalURLs = false);
void queueLoadHTMLString(WKStringRef content, WKStringRef baseURL = 0, WKStringRef unreachableURL = 0);
void queueReload();
void queueLoadingScript(WKStringRef script);
void queueNonLoadingScript(WKStringRef script);
bool isAllowedHost(WKStringRef);
unsigned imageCountInGeneralPasteboard() const;
void setAllowsAnySSLCertificate(bool);
bool statisticsNotifyObserver();
void textDidChangeInTextField();
void textFieldDidBeginEditing();
void textFieldDidEndEditing();
void reportLiveDocuments(WKBundlePageRef);
void resetUserScriptInjectedCount() { m_userScriptInjectedCount = 0; }
void increaseUserScriptInjectedCount() { ++m_userScriptInjectedCount; }
size_t userScriptInjectedCount() const { return m_userScriptInjectedCount; }
void clearResourceLoadStatistics();
private:
InjectedBundle() = default;
~InjectedBundle();
static void didCreatePage(WKBundleRef, WKBundlePageRef, const void* clientInfo);
static void willDestroyPage(WKBundleRef, WKBundlePageRef, const void* clientInfo);
static void didReceiveMessage(WKBundleRef, WKStringRef messageName, WKTypeRef messageBody, const void* clientInfo);
static void didReceiveMessageToPage(WKBundleRef, WKBundlePageRef, WKStringRef messageName, WKTypeRef messageBody, const void* clientInfo);
void didCreatePage(WKBundlePageRef);
void willDestroyPage(WKBundlePageRef);
void didReceiveMessage(WKStringRef messageName, WKTypeRef messageBody);
void didReceiveMessageToPage(WKBundlePageRef, WKStringRef messageName, WKTypeRef messageBody);
void setUpInjectedBundleClients(WKBundlePageRef);
void platformInitialize(WKTypeRef initializationUserData);
enum class BegingTestingMode { New, Resume };
void beginTesting(WKDictionaryRef initialSettings, BegingTestingMode);
WKRetainPtr<WKBundleRef> m_bundle;
Vector<std::unique_ptr<InjectedBundlePage>> m_pages;
#if ENABLE(ACCESSIBILITY)
RefPtr<AccessibilityController> m_accessibilityController;
#endif
RefPtr<TestRunner> m_testRunner;
RefPtr<GCController> m_gcController;
RefPtr<EventSendingController> m_eventSendingController;
RefPtr<TextInputController> m_textInputController;
WKBundleFrameRef m_topLoadingFrame { nullptr };
enum State {
Idle,
Testing,
Stopping
};
State m_state { Idle };
bool m_dumpPixels { false };
bool m_useWorkQueue { false };
bool m_pixelResultIsPending { false };
bool m_dumpJSConsoleLogInStdErr { false };
bool m_accessibilityIsolatedTreeMode { false };
WTF::Seconds m_timeout;
WKRetainPtr<WKDataRef> m_audioResult;
WKRetainPtr<WKImageRef> m_pixelResult;
WKRetainPtr<WKArrayRef> m_repaintRects;
Vector<String> m_allowedHosts;
size_t m_userScriptInjectedCount { 0 };
};
void postMessage(const char* name);
void postMessage(const char* name, bool value);
void postMessage(const char* name, int value);
void postMessage(const char* name, unsigned value);
void postMessage(const char* name, uint64_t value);
void postMessage(const char* name, const char* value);
void postMessage(const char* name, JSStringRef value);
void postMessage(const char* name, const void* value) = delete;
void postSynchronousMessage(const char* name);
void postSynchronousMessage(const char* name, bool value);
void postSynchronousMessage(const char* name, int value);
void postSynchronousMessage(const char* name, unsigned value);
void postSynchronousMessage(const char* name, uint64_t value);
void postSynchronousMessage(const char* name, double value);
void postSynchronousMessage(const char* name, const char* value);
void postSynchronousMessage(const char* name, const void* value) = delete;
void postPageMessage(const char* name);
void postPageMessage(const char* name, bool value);
void postPageMessage(const char* name, const char* value);
void postPageMessage(const char* name, WKStringRef value);
void postPageMessage(const char* name, WKDataRef value);
void postPageMessage(const char* name, const void* value) = delete;
void postSynchronousPageMessage(const char* name);
void postSynchronousPageMessage(const char* name, bool value);
void postSynchronousPageMessage(const char* name, const char* value);
void postSynchronousPageMessage(const char* name, const void* value) = delete;
template<typename T> void postMessage(const char* name, const WKRetainPtr<T>& value)
{
WKBundlePostMessage(InjectedBundle::singleton().bundle(), toWK(name).get(), value.get());
}
template<typename T> void postSynchronousMessage(const char* name, const WKRetainPtr<T>& value)
{
ALLOW_DEPRECATED_DECLARATIONS_BEGIN
WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), toWK(name).get(), value.get(), nullptr);
ALLOW_DEPRECATED_DECLARATIONS_END
}
template<typename T> void postPageMessage(const char* name, const WKRetainPtr<T>& value)
{
if (auto page = InjectedBundle::singleton().pageRef())
WKBundlePagePostMessage(page, toWK(name).get(), value.get());
}
template<typename T> void postSynchronousPageMessage(const char* name, const WKRetainPtr<T>& value)
{
if (auto page = InjectedBundle::singleton().pageRef()) {
// EventSender needs a layout
if (!strcmp(name, "EventSender"))
WKBundlePageLayoutIfNeeded(page);
WKBundlePagePostSynchronousMessageForTesting(page, toWK(name).get(), value.get(), nullptr);
}
}
} // namespace WTR