### 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.registerNetworkDispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, "Network");
InspectorBackend.registerEvent("Network.resourceLoaded", []);
InspectorBackend.registerCommand("Network.loadResource", [], []);
InspectorBackend.activateDomain("Network");
### 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> result = m_result.releaseNonNull();
            return WTFMove(*reinterpret_cast<Ref<NetworkError>*>(&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 {
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 = std::make_unique<ObjCInspectorNetworkBackendDispatcher>(handler);
    auto alternateAgent = std::make_unique<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


### 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
