# Copyright (C) 2010, 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.

messages -> WebProcess LegacyReceiver {
    InitializeWebProcess(struct WebKit::WebProcessCreationParameters processCreationParameters)

    # Create a new page.
    CreateWebPage(uint64_t newPageID, struct WebKit::WebPageCreationParameters pageCreationParameters)

    # Global preferences.
    SetCacheModel(uint32_t cacheModel)

    RegisterURLSchemeAsEmptyDocument(String scheme)
    RegisterURLSchemeAsSecure(String scheme)
    RegisterURLSchemeAsBypassingContentSecurityPolicy(String scheme)
    SetDomainRelaxationForbiddenForURLScheme(String scheme)
    RegisterURLSchemeAsLocal(String scheme)
    RegisterURLSchemeAsNoAccess(String scheme)
    RegisterURLSchemeAsDisplayIsolated(String scheme)
    RegisterURLSchemeAsCORSEnabled(String scheme)
    RegisterURLSchemeAsCachePartitioned(String scheme)
    RegisterURLSchemeAsCanDisplayOnlyIfCanRequest(String scheme)

    SetDefaultRequestTimeoutInterval(double timeoutInterval)
    SetAlwaysUsesComplexTextCodePath(bool alwaysUseComplexText)
    SetShouldUseFontSmoothing(bool useFontSmoothing)
    SetResourceLoadStatisticsEnabled(bool resourceLoadStatisticsEnabled);
    ClearResourceLoadStatistics();
    UserPreferredLanguagesChanged(Vector<String> languages)
    FullKeyboardAccessModeChanged(bool fullKeyboardAccessEnabled)

    ClearCachedCredentials()

    AddWebsiteDataStore(struct WebKit::WebsiteDataStoreParameters websiteDataStoreParameters);
    DestroySession(PAL::SessionID sessionID)

    # Plug-ins.
    DidAddPlugInAutoStartOriginHash(uint32_t hash, WallTime expirationTime, PAL::SessionID sessionID)
    ResetPlugInAutoStartOriginDefaultHashes(HashMap<uint32_t,WallTime> hashes)
    ResetPlugInAutoStartOriginHashes(HashMap<PAL::SessionID, HashMap<uint32_t,WallTime>> hashes)
    SetPluginLoadClientPolicy(uint8_t policy, String host, String bundleIdentifier, String versionString)
    ResetPluginLoadClientPolicies(HashMap<String, HashMap<String, HashMap<String, uint8_t>>> pluginLoadClientPolicies)
    ClearPluginClientPolicies()
    RefreshPlugins()

    void StartMemorySampler(WebKit::SandboxExtension::Handle sampleLogFileHandle, String sampleLogFilePath, double interval);
    void StopMemorySampler();

    SetTextCheckerState(struct WebKit::TextCheckerState textCheckerState)

    SetEnhancedAccessibility(bool flag)

    GetWebCoreStatistics(uint64_t callbackID)
    GarbageCollectJavaScriptObjects()
    SetJavaScriptGarbageCollectorTimerEnabled(bool enable)

    SetInjectedBundleParameter(String parameter, IPC::DataReference value);
    SetInjectedBundleParameters(IPC::DataReference parameters);
    HandleInjectedBundleMessage(String messageName, WebKit::UserData messageBody);

    ReleasePageCache()

    FetchWebsiteData(PAL::SessionID sessionID, OptionSet<WebKit::WebsiteDataType> websiteDataTypes) -> (struct WebKit::WebsiteData websiteData)
    DeleteWebsiteData(PAL::SessionID sessionID, OptionSet<WebKit::WebsiteDataType> websiteDataTypes, WallTime modifiedSince) -> ()
    DeleteWebsiteDataForOrigins(PAL::SessionID sessionID, OptionSet<WebKit::WebsiteDataType> websiteDataTypes, Vector<WebCore::SecurityOriginData> origins) -> ()

    SetHiddenPageDOMTimerThrottlingIncreaseLimit(int milliseconds)
    SetProcessSuppressionEnabled(bool flag)
#if PLATFORM(COCOA)
    SetQOS(int latencyQOS, int throughputQOS)
#endif

    SetMemoryCacheDisabled(bool disabled);

#if ENABLE(SERVICE_CONTROLS)
    SetEnabledServices(bool hasImageServices, bool hasSelectionServices, bool hasRichContentServices)
#endif

    EnsureAutomationSessionProxy(String sessionIdentifier)
    DestroyAutomationSessionProxy()

    ProcessWillSuspendImminently() -> (bool handled)
    PrepareToSuspend()
    CancelPrepareToSuspend()
    ProcessDidResume()

    MainThreadPing()
    BackgroundResponsivenessPing()

#if ENABLE(GAMEPAD)
    SetInitialGamepads(Vector<WebKit::GamepadData> gamepadDatas)
    GamepadConnected(WebKit::GamepadData gamepadData)
    GamepadDisconnected(unsigned index)
#endif

    SyncIPCMessageWhileWaitingForSyncReplyForTesting() -> ()

#if USE(SOUP)
    SetNetworkProxySettings(struct WebCore::SoupNetworkProxySettings settings)
#endif

#if ENABLE(SERVICE_WORKER)
    EstablishWorkerContextConnectionToStorageProcess(uint64_t pageGroupID, uint64_t pageID, struct WebKit::WebPreferencesStore store, PAL::SessionID initialSessionID)
    RegisterServiceWorkerClients()
#endif

    DidTakeAllMessagesForPort(Vector<WebCore::MessageWithMessagePorts> messages, uint64_t messageCallbackIdentifier, uint64_t messageBatchIdentifier)
    DidCheckRemotePortForActivity(uint64_t callbackIdentifier, bool hasActivity)
    CheckProcessLocalPortForActivity(struct WebCore::MessagePortIdentifier port, uint64_t callbackIdentifier)
    MessagesAvailableForPort(struct WebCore::MessagePortIdentifier port)

#if PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101400
    SetScreenProperties(HashMap<uint32_t, WebCore::ScreenProperties> screenProperties)
    ScrollerStylePreferenceChanged(bool useOvelayScrollbars)
#endif
}
