### Begin File: InspectorBackendCommands.js
/*
 * 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 definitions-with-mac-platform.json
// by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py

// Network
InspectorBackend.registerDomain("Network", null);
InspectorBackend.registerCommand("Network.loadResource", null, [], []);
InspectorBackend.registerEvent("Network.resourceLoaded", null, []);
InspectorBackend.registerNetworkDispatcher = InspectorBackend.registerDispatcher.bind(InspectorBackend, "Network");
InspectorBackend.activateDomain("Network", null);
### End File: InspectorBackendCommands.js

### Begin File: TestAlternateBackendDispatchers.h
/*
 * 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 definitions-with-mac-platform.json
// by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py

#pragma once

#if ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS)

#include "TestProtocolTypes.h"
#include <JavaScriptCore/InspectorBackendDispatcher.h>
#include <JavaScriptCore/InspectorFrontendRouter.h>

namespace Inspector {

class AlternateBackendDispatcher {
public:
    void setBackendDispatcher(RefPtr<BackendDispatcher>&& dispatcher) { m_backendDispatcher = WTFMove(dispatcher); }
    BackendDispatcher* backendDispatcher() const { return m_backendDispatcher.get(); }
private:
    RefPtr<BackendDispatcher> m_backendDispatcher;
};


class AlternateNetworkBackendDispatcher : public AlternateBackendDispatcher {
public:
    virtual ~AlternateNetworkBackendDispatcher() { }
    virtual void loadResource(long callId) = 0;
};

} // namespace Inspector

#endif // ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS)
### End File: TestAlternateBackendDispatchers.h

### Begin File: TestBackendDispatchers.h
/*
 * 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 definitions-with-mac-platform.json
// by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py

#pragma once

#include "TestProtocolObjects.h"
#include <JavaScriptCore/InspectorBackendDispatcher.h>
#include <wtf/text/WTFString.h>

namespace Inspector {

typedef String ErrorString;

#if ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS)
class AlternateNetworkBackendDispatcher;
#endif // ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS)

class NetworkBackendDispatcherHandler {
public:
    virtual void loadResource(ErrorString&) = 0;
protected:
    virtual ~NetworkBackendDispatcherHandler();
};

class NetworkBackendDispatcher final : public SupplementalBackendDispatcher {
public:
    static Ref<NetworkBackendDispatcher> create(BackendDispatcher&, NetworkBackendDispatcherHandler*);
    void dispatch(long requestId, const String& method, Ref<JSON::Object>&& message) override;
private:
    void loadResource(long requestId, RefPtr<JSON::Object>&& parameters);
#if ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS)
public:
    void setAlternateDispatcher(AlternateNetworkBackendDispatcher* alternateDispatcher) { m_alternateDispatcher = alternateDispatcher; }
private:
    AlternateNetworkBackendDispatcher* m_alternateDispatcher { nullptr };
#endif
private:
    NetworkBackendDispatcher(BackendDispatcher&, NetworkBackendDispatcherHandler*);
    NetworkBackendDispatcherHandler* m_agent { nullptr };
};

} // namespace Inspector
### End File: TestBackendDispatchers.h

### Begin File: TestBackendDispatchers.cpp
/*
 * 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 definitions-with-mac-platform.json
// by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py

#include "config.h"
#include "TestBackendDispatchers.h"

#include <JavaScriptCore/InspectorFrontendRouter.h>
#include <wtf/JSONValues.h>
#include <wtf/NeverDestroyed.h>
#include <wtf/text/CString.h>

#if ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS)
#include "TestAlternateBackendDispatchers.h"
#endif

namespace Inspector {

NetworkBackendDispatcherHandler::~NetworkBackendDispatcherHandler() { }

Ref<NetworkBackendDispatcher> NetworkBackendDispatcher::create(BackendDispatcher& backendDispatcher, NetworkBackendDispatcherHandler* agent)
{
    return adoptRef(*new NetworkBackendDispatcher(backendDispatcher, agent));
}

NetworkBackendDispatcher::NetworkBackendDispatcher(BackendDispatcher& backendDispatcher, NetworkBackendDispatcherHandler* agent)
    : SupplementalBackendDispatcher(backendDispatcher)
    , m_agent(agent)
{
    m_backendDispatcher->registerDispatcherForDomain("Network"_s, this);
}

void NetworkBackendDispatcher::dispatch(long requestId, const String& method, Ref<JSON::Object>&& message)
{
    Ref<NetworkBackendDispatcher> protect(*this);

    RefPtr<JSON::Object> parameters;
    message->getObject("params"_s, parameters);

    if (method == "loadResource")
        loadResource(requestId, WTFMove(parameters));
    else
        m_backendDispatcher->reportProtocolError(BackendDispatcher::MethodNotFound, "'Network." + method + "' was not found");
}

void NetworkBackendDispatcher::loadResource(long requestId, RefPtr<JSON::Object>&&)
{
#if ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS)
    if (m_alternateDispatcher) {
        m_alternateDispatcher->loadResource(requestId);
        return;
    }
#endif

    ErrorString error;
    Ref<JSON::Object> result = JSON::Object::create();
    m_agent->loadResource(error);

    if (!error.length())
        m_backendDispatcher->sendResponse(requestId, WTFMove(result), false);
    else
        m_backendDispatcher->reportProtocolError(BackendDispatcher::ServerError, WTFMove(error));
}

} // namespace Inspector

### End File: TestBackendDispatchers.cpp

### Begin File: TestFrontendDispatchers.h
/*
 * 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 definitions-with-mac-platform.json
// by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py

#pragma once

#include "TestProtocolObjects.h"
#include <wtf/JSONValues.h>
#include <wtf/text/WTFString.h>

namespace Inspector {

class FrontendRouter;

class NetworkFrontendDispatcher {
    WTF_MAKE_FAST_ALLOCATED;
public:
    NetworkFrontendDispatcher(FrontendRouter& frontendRouter) : m_frontendRouter(frontendRouter) { }
    void resourceLoaded();
private:
    FrontendRouter& m_frontendRouter;
};

} // namespace Inspector
### End File: TestFrontendDispatchers.h

### Begin File: TestFrontendDispatchers.cpp
/*
 * 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 definitions-with-mac-platform.json
// by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py

#include "config.h"
#include "TestFrontendDispatchers.h"

#include <JavaScriptCore/InspectorFrontendRouter.h>
#include <wtf/text/CString.h>

namespace Inspector {

void NetworkFrontendDispatcher::resourceLoaded()
{
    Ref<JSON::Object> jsonMessage = JSON::Object::create();
    jsonMessage->setString("method"_s, "Network.resourceLoaded"_s);

    m_frontendRouter.sendEvent(jsonMessage->toJSONString());
}

} // namespace Inspector

### End File: TestFrontendDispatchers.cpp

### Begin File: TestProtocolObjects.h
/*
 * 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 definitions-with-mac-platform.json
// by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py

#pragma once

#include <JavaScriptCore/InspectorProtocolTypes.h>
#include <wtf/Assertions.h>

namespace Inspector {



namespace Protocol {



// Forward declarations.
namespace Network {
class NetworkError;
} // Network
// End of forward declarations.




namespace Network {
class NetworkError : public JSON::ObjectBase {
public:
    enum {
        NoFieldsSet = 0,
        MessageSet = 1 << 0,
        CodeSet = 1 << 1,
        AllFieldsSet = (MessageSet | CodeSet)
    };

    template<int STATE>
    class Builder {
    private:
        RefPtr<JSON::Object> m_result;

        template<int STEP> Builder<STATE | STEP>& castState()
        {
            return *reinterpret_cast<Builder<STATE | STEP>*>(this);
        }

        Builder(Ref</*NetworkError*/JSON::Object>&& object)
            : m_result(WTFMove(object))
        {
            COMPILE_ASSERT(STATE == NoFieldsSet, builder_created_in_non_init_state);
        }
        friend class NetworkError;
    public:

        Builder<STATE | MessageSet>& setMessage(const String& value)
        {
            COMPILE_ASSERT(!(STATE & MessageSet), property_message_already_set);
            m_result->setString("message"_s, value);
            return castState<MessageSet>();
        }

        Builder<STATE | CodeSet>& setCode(int value)
        {
            COMPILE_ASSERT(!(STATE & CodeSet), property_code_already_set);
            m_result->setInteger("code"_s, value);
            return castState<CodeSet>();
        }

        Ref<NetworkError> release()
        {
            COMPILE_ASSERT(STATE == AllFieldsSet, result_is_not_ready);
            COMPILE_ASSERT(sizeof(NetworkError) == sizeof(JSON::Object), cannot_cast);

            Ref<JSON::Object> jsonResult = m_result.releaseNonNull();
            auto result = WTFMove(*reinterpret_cast<Ref<NetworkError>*>(&jsonResult));
            return result;
        }
    };

    /*
     * Synthetic constructor:
     * Ref<NetworkError> result = NetworkError::create()
     *     .setMessage(...)
     *     .setCode(...)
     *     .release();
     */
    static Builder<NoFieldsSet> create()
    {
        return Builder<NoFieldsSet>(JSON::Object::create());
    }
};

} // Network



} // namespace Protocol

} // namespace Inspector
### End File: TestProtocolObjects.h

### Begin File: TestProtocolObjects.cpp
/*
 * 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 definitions-with-mac-platform.json
// by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py

#include "config.h"
#include "TestProtocolObjects.h"

#include <wtf/Optional.h>
#include <wtf/text/CString.h>

namespace Inspector {

namespace Protocol {



} // namespace Protocol

} // namespace Inspector

### End File: TestProtocolObjects.cpp

### Begin File: TestProtocolBackendDispatchers.h
/*
 * 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 definitions-with-mac-platform.json
// by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py

#include <JavaScriptCore/InspectorAlternateBackendDispatchers.h>
#include <wtf/RetainPtr.h>

@protocol TestProtocolNetworkDomainHandler;

namespace Inspector {


class ObjCInspectorNetworkBackendDispatcher final : public AlternateNetworkBackendDispatcher {
    WTF_MAKE_FAST_ALLOCATED;
public:
    ObjCInspectorNetworkBackendDispatcher(id<TestProtocolNetworkDomainHandler> handler) { m_delegate = handler; }
    virtual void loadResource(long requestId) override;
private:
    RetainPtr<id<TestProtocolNetworkDomainHandler>> m_delegate;
};

} // namespace Inspector

### End File: TestProtocolBackendDispatchers.h

### Begin File: TestProtocolBackendDispatchers.mm
/*
 * 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 definitions-with-mac-platform.json
// by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py

#import "config.h"
#import "TestProtocolBackendDispatchers.h"

#include "TestProtocolInternal.h"
#include "TestProtocolTypeConversions.h"
#include <wtf/JSONValues.h>

namespace Inspector {

void ObjCInspectorNetworkBackendDispatcher::loadResource(long requestId)
{
    id errorCallback = ^(NSString *error) {
        backendDispatcher()->reportProtocolError(requestId, BackendDispatcher::ServerError, error);
        backendDispatcher()->sendPendingErrors();
    };

    id successCallback = ^{
        backendDispatcher()->sendResponse(requestId, JSON::Object::create(), false);
    };

    [m_delegate loadResourceWithErrorCallback:errorCallback successCallback:successCallback];
}


} // namespace Inspector

### End File: TestProtocolBackendDispatchers.mm

### Begin File: TestProtocolConfiguration.h
/*
 * 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 definitions-with-mac-platform.json
// by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py

#import <WebInspector/TestProtocol.h>

__attribute__((visibility ("default")))
@interface TestProtocolConfiguration : NSObject
@property (nonatomic, retain, setter=setNetworkHandler:) id<TestProtocolNetworkDomainHandler> networkHandler;
@property (nonatomic, readonly) TestProtocolNetworkDomainEventDispatcher *networkEventDispatcher;
@end


### End File: TestProtocolConfiguration.h

### Begin File: TestProtocolConfiguration.mm
/*
 * 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 definitions-with-mac-platform.json
// by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py

#import "TestProtocolConfiguration.h"

#import "TestProtocolInternal.h"
#import "TestProtocolBackendDispatchers.h"
#import <JavaScriptCore/AlternateDispatchableAgent.h>
#import <JavaScriptCore/AugmentableInspectorController.h>
#import <JavaScriptCore/InspectorAlternateBackendDispatchers.h>
#import <JavaScriptCore/InspectorBackendDispatchers.h>

using namespace Inspector;

@implementation TestProtocolConfiguration
{
    AugmentableInspectorController* _controller;
    id<TestProtocolNetworkDomainHandler> _networkHandler;
    TestProtocolNetworkDomainEventDispatcher *_networkEventDispatcher;
}

- (instancetype)initWithController:(AugmentableInspectorController*)controller
{
    self = [super init];
    if (!self)
        return nil;
    ASSERT(controller);
    _controller = controller;
    return self;
}

- (void)dealloc
{
    [_networkHandler release];
    [_networkEventDispatcher release];
    [super dealloc];
}

- (void)setNetworkHandler:(id<TestProtocolNetworkDomainHandler>)handler
{
    if (handler == _networkHandler)
        return;

    [_networkHandler release];
    _networkHandler = [handler retain];

    auto alternateDispatcher = makeUnique<ObjCInspectorNetworkBackendDispatcher>(handler);
    auto alternateAgent = makeUnique<AlternateDispatchableAgent<NetworkBackendDispatcher, AlternateNetworkBackendDispatcher>>("Network"_s, *_controller, WTFMove(alternateDispatcher));
    _controller->appendExtraAgent(WTFMove(alternateAgent));
}

- (id<TestProtocolNetworkDomainHandler>)networkHandler
{
    return _networkHandler;
}

- (TestProtocolNetworkDomainEventDispatcher *)networkEventDispatcher
{
    if (!_networkEventDispatcher)
        _networkEventDispatcher = [[TestProtocolNetworkDomainEventDispatcher alloc] initWithController:_controller];
    return _networkEventDispatcher;
}

@end


### End File: TestProtocolConfiguration.mm

### Begin File: TestProtocolEventDispatchers.mm
/*
 * 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 definitions-with-mac-platform.json
// by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py

#import "TestProtocolInternal.h"

#import "TestProtocolTypeConversions.h"
#import <wtf/JSONValues.h>

using namespace Inspector;

@implementation TestProtocolNetworkDomainEventDispatcher
{
    AugmentableInspectorController* _controller;
}

- (instancetype)initWithController:(AugmentableInspectorController*)controller
{
    self = [super init];
    if (!self)
        return nil;
    ASSERT(controller);
    _controller = controller;
    return self;
}

- (void)resourceLoaded
{
    const FrontendRouter& router = _controller->frontendRouter();

    Ref<JSON::Object> jsonMessage = JSON::Object::create();
    jsonMessage->setString("method"_s, "Network.resourceLoaded"_s);
    router.sendEvent(jsonMessage->toJSONString());
}

@end


### End File: TestProtocolEventDispatchers.mm

### Begin File: TestProtocol.h
/*
 * 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 definitions-with-mac-platform.json
// by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py

#import <Foundation/Foundation.h>

#import <WebInspector/RWIProtocolJSONObject.h>


@class TestProtocolNetworkError;

typedef NS_ENUM(NSInteger, TestProtocolPlatform) {
    TestProtocolPlatformAll,
    TestProtocolPlatformGeneric,
    TestProtocolPlatformIOS,
    TestProtocolPlatformMacOS,
};




__attribute__((visibility ("default")))
@interface TestProtocolNetworkError : RWIProtocolJSONObject
- (instancetype)initWithPayload:(NSDictionary<NSString *, id> *)payload;
- (instancetype)initWithProtocolObject:(RWIProtocolJSONObject *)jsonObject;
- (instancetype)initWithMessage:(NSString *)message code:(int)code;
/* required */ @property (nonatomic, copy) NSString *message;
/* required */ @property (nonatomic, assign) int code;
@end

@protocol TestProtocolNetworkDomainHandler <NSObject>
@required
- (void)loadResourceWithErrorCallback:(void(^)(NSString *error))errorCallback successCallback:(void(^)(void))successCallback;
@end

__attribute__((visibility ("default")))
@interface TestProtocolNetworkDomainEventDispatcher : NSObject
- (void)resourceLoaded;
@end


#import <WebInspector/RWIProtocolBuildCompatibilityObjects.h>

### End File: TestProtocol.h

### Begin File: TestProtocolInternal.h
/*
 * 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 definitions-with-mac-platform.json
// by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py

#import "TestProtocol.h"
#import "TestProtocolJSONObjectPrivate.h"
#import <JavaScriptCore/AugmentableInspectorController.h>
#import <wtf/JSONValues.h>

@interface TestProtocolNetworkDomainEventDispatcher (Private)
- (instancetype)initWithController:(Inspector::AugmentableInspectorController*)controller;
@end


### End File: TestProtocolInternal.h

### Begin File: TestProtocolTypeConversions.h
/*
 * 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 definitions-with-mac-platform.json
// by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py

#import "TestProtocol.h"
#import <WebInspector/RWIProtocolArrayConversions.h>

namespace Inspector {

template<typename ObjCEnumType>
Optional<ObjCEnumType> fromProtocolString(const String& value);

inline String toProtocolString(TestProtocolPlatform value)
{
    switch(value) {
    case TestProtocolPlatformAll:
        return "all"_s;
    case TestProtocolPlatformGeneric:
        return "generic"_s;
    case TestProtocolPlatformIOS:
        return "ios"_s;
    case TestProtocolPlatformMacOS:
        return "macos"_s;
    }
}

template<>
inline Optional<TestProtocolPlatform> fromProtocolString(const String& value)
{
    if (value == "all")
        return TestProtocolPlatformAll;
    if (value == "generic")
        return TestProtocolPlatformGeneric;
    if (value == "ios")
        return TestProtocolPlatformIOS;
    if (value == "macos")
        return TestProtocolPlatformMacOS;
    return WTF::nullopt;
}



} // namespace Inspector

### End File: TestProtocolTypeConversions.h

### Begin File: TestProtocolTypeConversions.mm
/*
 * 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 definitions-with-mac-platform.json
// by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py

#import "TestProtocolTypeConversions.h"

#import "TestProtocol.h"
#import "TestProtocolTypeParser.h"
#import <WebInspector/RWIProtocolJSONObjectPrivate.h>

using namespace Inspector;

@interface TestProtocolTypeConversions (NetworkDomain)

+ (void)_parseNetworkError:(TestProtocolNetworkError **)outValue fromPayload:(id)payload;

@end

@implementation TestProtocolTypeConversions (NetworkDomain)

+ (void)_parseNetworkError:(TestProtocolNetworkError **)outValue fromPayload:(id)payload
{
    THROW_EXCEPTION_FOR_BAD_TYPE(payload, [NSDictionary class]);
    *outValue = [[TestProtocolNetworkError alloc] initWithPayload:payload];
}

@end


### End File: TestProtocolTypeConversions.mm

### Begin File: TestProtocolTypes.mm
/*
 * 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 definitions-with-mac-platform.json
// by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py

#import "TestProtocolInternal.h"

#import "TestProtocolTypeConversions.h"
#import <WebInspector/RWIProtocolJSONObjectPrivate.h>
#import <wtf/Assertions.h>
#import <wtf/JSONValues.h>

using namespace Inspector;


@implementation TestProtocolNetworkError

- (instancetype)initWithPayload:(nonnull NSDictionary<NSString *, id> *)payload
{
    if (!(self = [super init]))
        return nil;

    THROW_EXCEPTION_FOR_REQUIRED_PROPERTY(payload[@"message"], @"message");
    self.message = payload[@"message"];

    THROW_EXCEPTION_FOR_REQUIRED_PROPERTY(payload[@"code"], @"code");
    self.code = [payload[@"code"] integerValue];

    return self;
}
- (instancetype)initWithProtocolObject:(RWIProtocolJSONObject *)object
{
    if (!(self = [super initWithJSONObject:[object toJSONObject].get()]))
        return nil;

    return self;
}

- (instancetype)initWithMessage:(NSString *)message code:(int)code
{
    if (!(self = [super init]))
        return nil;

    THROW_EXCEPTION_FOR_REQUIRED_PROPERTY(message, @"message");

    self.message = message;
    self.code = code;

    return self;
}

- (void)setMessage:(NSString *)message
{
    [super setString:message forKey:@"message"];
}

- (NSString *)message
{
    return [super stringForKey:@"message"];
}

- (void)setCode:(int)code
{
    [super setInteger:code forKey:@"code"];
}

- (int)code
{
    return [super integerForKey:@"code"];
}

@end


### End File: TestProtocolTypes.mm
