| Index: third_party/inspector_protocol/lib/DispatcherBase_cpp.template
 | 
| diff --git a/third_party/inspector_protocol/lib/DispatcherBase_cpp.template b/third_party/inspector_protocol/lib/DispatcherBase_cpp.template
 | 
| index c4f36a5fd31b286d8c9ad99b328b65017571efa5..b08947aba43f32c1da32a290560dcbd32471e306 100644
 | 
| --- a/third_party/inspector_protocol/lib/DispatcherBase_cpp.template
 | 
| +++ b/third_party/inspector_protocol/lib/DispatcherBase_cpp.template
 | 
| @@ -39,6 +39,16 @@ DispatchResponse DispatchResponse::InternalError()
 | 
|  }
 | 
|  
 | 
|  // static
 | 
| +DispatchResponse DispatchResponse::InvalidParams(const String& error)
 | 
| +{
 | 
| +    DispatchResponse result;
 | 
| +    result.m_status = kError;
 | 
| +    result.m_errorCode = kInvalidParams;
 | 
| +    result.m_errorMessage = error;
 | 
| +    return result;
 | 
| +}
 | 
| +
 | 
| +// static
 | 
|  DispatchResponse DispatchResponse::FallThrough()
 | 
|  {
 | 
|      DispatchResponse result;
 | 
| @@ -58,9 +68,10 @@ DispatcherBase::WeakPtr::~WeakPtr()
 | 
|          m_dispatcher->m_weakPtrs.erase(this);
 | 
|  }
 | 
|  
 | 
| -DispatcherBase::Callback::Callback(std::unique_ptr<DispatcherBase::WeakPtr> backendImpl, int callId)
 | 
| +DispatcherBase::Callback::Callback(std::unique_ptr<DispatcherBase::WeakPtr> backendImpl, int callId, int callbackId)
 | 
|      : m_backendImpl(std::move(backendImpl))
 | 
| -    , m_callId(callId) { }
 | 
| +    , m_callId(callId)
 | 
| +    , m_callbackId(callbackId) { }
 | 
|  
 | 
|  DispatcherBase::Callback::~Callback() = default;
 | 
|  
 | 
| @@ -77,18 +88,40 @@ void DispatcherBase::Callback::sendIfActive(std::unique_ptr<protocol::Dictionary
 | 
|      m_backendImpl = nullptr;
 | 
|  }
 | 
|  
 | 
| +void DispatcherBase::Callback::fallThroughIfActive()
 | 
| +{
 | 
| +    if (!m_backendImpl || !m_backendImpl->get())
 | 
| +        return;
 | 
| +    m_backendImpl->get()->markFallThrough(m_callbackId);
 | 
| +    m_backendImpl = nullptr;
 | 
| +}
 | 
| +
 | 
|  DispatcherBase::DispatcherBase(FrontendChannel* frontendChannel)
 | 
| -    : m_frontendChannel(frontendChannel) { }
 | 
| +    : m_frontendChannel(frontendChannel)
 | 
| +    , m_lastCallbackId(0)
 | 
| +    , m_lastCallbackFallThrough(false) { }
 | 
|  
 | 
|  DispatcherBase::~DispatcherBase()
 | 
|  {
 | 
|      clearFrontend();
 | 
|  }
 | 
|  
 | 
| +int DispatcherBase::nextCallbackId()
 | 
| +{
 | 
| +    m_lastCallbackFallThrough = false;
 | 
| +    return ++m_lastCallbackId;
 | 
| +}
 | 
| +
 | 
| +void DispatcherBase::markFallThrough(int callbackId)
 | 
| +{
 | 
| +    DCHECK(callbackId == m_lastCallbackId);
 | 
| +    m_lastCallbackFallThrough = true;
 | 
| +}
 | 
| +
 | 
|  // static
 | 
|  bool DispatcherBase::getCommandName(const String& message, String* result)
 | 
|  {
 | 
| -    std::unique_ptr<protocol::Value> value = parseJSON(message);
 | 
| +    std::unique_ptr<protocol::Value> value = StringUtil::parseJSON(message);
 | 
|      if (!value)
 | 
|          return false;
 | 
|  
 | 
| @@ -169,7 +202,13 @@ std::unique_ptr<DispatcherBase::WeakPtr> DispatcherBase::weakPtr()
 | 
|  }
 | 
|  
 | 
|  UberDispatcher::UberDispatcher(FrontendChannel* frontendChannel)
 | 
| -    : m_frontendChannel(frontendChannel) { }
 | 
| +    : m_frontendChannel(frontendChannel)
 | 
| +    , m_fallThroughForNotFound(false) { }
 | 
| +
 | 
| +void UberDispatcher::setFallThroughForNotFound(bool fallThroughForNotFound)
 | 
| +{
 | 
| +    m_fallThroughForNotFound = fallThroughForNotFound;
 | 
| +}
 | 
|  
 | 
|  void UberDispatcher::registerBackend(const String& name, std::unique_ptr<protocol::DispatcherBase> dispatcher)
 | 
|  {
 | 
| @@ -206,12 +245,16 @@ DispatchResponse::Status UberDispatcher::dispatch(std::unique_ptr<Value> parsedM
 | 
|  
 | 
|      size_t dotIndex = method.find(".");
 | 
|      if (dotIndex == StringUtil::kNotFound) {
 | 
| +        if (m_fallThroughForNotFound)
 | 
| +            return DispatchResponse::kFallThrough;
 | 
|          reportProtocolErrorTo(m_frontendChannel, callId, DispatchResponse::kMethodNotFound, "'" + method + "' wasn't found", nullptr);
 | 
|          return DispatchResponse::kError;
 | 
|      }
 | 
|      String domain = StringUtil::substring(method, 0, dotIndex);
 | 
|      auto it = m_dispatchers.find(domain);
 | 
|      if (it == m_dispatchers.end()) {
 | 
| +        if (m_fallThroughForNotFound)
 | 
| +            return DispatchResponse::kFallThrough;
 | 
|          reportProtocolErrorTo(m_frontendChannel, callId, DispatchResponse::kMethodNotFound, "'" + method + "' wasn't found", nullptr);
 | 
|          return DispatchResponse::kError;
 | 
|      }
 | 
| 
 |