1/*
2 * Copyright (C) 2013-2017 Apple Inc. All Rights Reserved.
3 * Copyright (C) 2011 The Chromium Authors. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#pragma once
28
29#include "InspectorFrontendRouter.h"
30#include "InspectorProtocolTypes.h"
31#include <functional>
32#include <wtf/DeprecatedOptional.h>
33#include <wtf/Optional.h>
34#include <wtf/RefCounted.h>
35#include <wtf/text/WTFString.h>
36
37namespace Inspector {
38
39class BackendDispatcher;
40
41typedef String ErrorString;
42
43class JS_EXPORT_PRIVATE SupplementalBackendDispatcher : public RefCounted<SupplementalBackendDispatcher> {
44public:
45 SupplementalBackendDispatcher(BackendDispatcher&);
46 virtual ~SupplementalBackendDispatcher();
47 virtual void dispatch(long requestId, const String& method, Ref<JSON::Object>&& message) = 0;
48protected:
49 Ref<BackendDispatcher> m_backendDispatcher;
50};
51
52class JS_EXPORT_PRIVATE BackendDispatcher : public RefCounted<BackendDispatcher> {
53public:
54 static Ref<BackendDispatcher> create(Ref<FrontendRouter>&&);
55
56 class JS_EXPORT_PRIVATE CallbackBase : public RefCounted<CallbackBase> {
57 public:
58 CallbackBase(Ref<BackendDispatcher>&&, long requestId);
59
60 bool isActive() const;
61 void disable() { m_alreadySent = true; }
62
63 void sendSuccess(RefPtr<JSON::Object>&&);
64 void sendFailure(const ErrorString&);
65
66 private:
67 Ref<BackendDispatcher> m_backendDispatcher;
68 long m_requestId;
69 bool m_alreadySent { false };
70 };
71
72 bool isActive() const;
73
74 bool hasProtocolErrors() const { return m_protocolErrors.size() > 0; }
75
76 enum CommonErrorCode {
77 ParseError = 0,
78 InvalidRequest,
79 MethodNotFound,
80 InvalidParams,
81 InternalError,
82 ServerError
83 };
84
85 void registerDispatcherForDomain(const String& domain, SupplementalBackendDispatcher*);
86 void dispatch(const String& message);
87
88 // Note that 'unused' is a workaround so the compiler can pick the right sendResponse based on arity.
89 // When <http://webkit.org/b/179847> is fixed or this class is renamed for the JSON::Object case,
90 // then this alternate method with a dummy parameter can be removed in favor of the one without it.
91 void sendResponse(long requestId, RefPtr<JSON::Object>&& result, bool unused);
92 void sendResponse(long requestId, RefPtr<JSON::Object>&& result);
93 void sendPendingErrors();
94
95 void reportProtocolError(CommonErrorCode, const String& errorMessage);
96 void reportProtocolError(Optional<long> relatedRequestId, CommonErrorCode, const String& errorMessage);
97
98 template<typename T>
99 WTF_INTERNAL
100 T getPropertyValue(JSON::Object*, const String& name, bool* out_optionalValueFound, T defaultValue, std::function<bool(JSON::Value&, T&)>, const char* typeName);
101
102 int getInteger(JSON::Object*, const String& name, bool* valueFound);
103 double getDouble(JSON::Object*, const String& name, bool* valueFound);
104 String getString(JSON::Object*, const String& name, bool* valueFound);
105 bool getBoolean(JSON::Object*, const String& name, bool* valueFound);
106 RefPtr<JSON::Value> getValue(JSON::Object*, const String& name, bool* valueFound);
107 RefPtr<JSON::Object> getObject(JSON::Object*, const String& name, bool* valueFound);
108 RefPtr<JSON::Array> getArray(JSON::Object*, const String& name, bool* valueFound);
109
110private:
111 BackendDispatcher(Ref<FrontendRouter>&&);
112
113 // This is necessary for some versions of Safari. Remove it when those versions of Safari are no longer supported.
114 void reportProtocolError(WTF::DeprecatedOptional<long> relatedRequestId, CommonErrorCode, const String& errorMessage);
115
116 Ref<FrontendRouter> m_frontendRouter;
117 HashMap<String, SupplementalBackendDispatcher*> m_dispatchers;
118
119 // Protocol errors reported for the top-level request being processed.
120 // If processing a request triggers async responses, then any related errors will
121 // be attributed to the top-level request, but generate separate error messages.
122 Vector<std::tuple<CommonErrorCode, String>> m_protocolErrors;
123
124 // For synchronously handled requests, avoid plumbing requestId through every
125 // call that could potentially fail with a protocol error.
126 Optional<long> m_currentRequestId { WTF::nullopt };
127};
128
129} // namespace Inspector
130