aboutsummaryrefslogtreecommitdiff
path: root/mojo/public/cpp/bindings/lib/validation_errors.cc
blob: 904f5e4c72a0b69cf59b02bde4c6b721877300c2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "mojo/public/cpp/bindings/lib/validation_errors.h"

#include "base/strings/stringprintf.h"
#include "mojo/public/cpp/bindings/message.h"

namespace mojo {
namespace internal {
namespace {

ValidationErrorObserverForTesting* g_validation_error_observer = nullptr;
SerializationWarningObserverForTesting* g_serialization_warning_observer =
    nullptr;
bool g_suppress_logging = false;

}  // namespace

const char* ValidationErrorToString(ValidationError error) {
  switch (error) {
    case VALIDATION_ERROR_NONE:
      return "VALIDATION_ERROR_NONE";
    case VALIDATION_ERROR_MISALIGNED_OBJECT:
      return "VALIDATION_ERROR_MISALIGNED_OBJECT";
    case VALIDATION_ERROR_ILLEGAL_MEMORY_RANGE:
      return "VALIDATION_ERROR_ILLEGAL_MEMORY_RANGE";
    case VALIDATION_ERROR_UNEXPECTED_STRUCT_HEADER:
      return "VALIDATION_ERROR_UNEXPECTED_STRUCT_HEADER";
    case VALIDATION_ERROR_UNEXPECTED_ARRAY_HEADER:
      return "VALIDATION_ERROR_UNEXPECTED_ARRAY_HEADER";
    case VALIDATION_ERROR_ILLEGAL_HANDLE:
      return "VALIDATION_ERROR_ILLEGAL_HANDLE";
    case VALIDATION_ERROR_UNEXPECTED_INVALID_HANDLE:
      return "VALIDATION_ERROR_UNEXPECTED_INVALID_HANDLE";
    case VALIDATION_ERROR_ILLEGAL_POINTER:
      return "VALIDATION_ERROR_ILLEGAL_POINTER";
    case VALIDATION_ERROR_UNEXPECTED_NULL_POINTER:
      return "VALIDATION_ERROR_UNEXPECTED_NULL_POINTER";
    case VALIDATION_ERROR_ILLEGAL_INTERFACE_ID:
      return "VALIDATION_ERROR_ILLEGAL_INTERFACE_ID";
    case VALIDATION_ERROR_UNEXPECTED_INVALID_INTERFACE_ID:
      return "VALIDATION_ERROR_UNEXPECTED_INVALID_INTERFACE_ID";
    case VALIDATION_ERROR_MESSAGE_HEADER_INVALID_FLAGS:
      return "VALIDATION_ERROR_MESSAGE_HEADER_INVALID_FLAGS";
    case VALIDATION_ERROR_MESSAGE_HEADER_MISSING_REQUEST_ID:
      return "VALIDATION_ERROR_MESSAGE_HEADER_MISSING_REQUEST_ID";
    case VALIDATION_ERROR_MESSAGE_HEADER_UNKNOWN_METHOD:
      return "VALIDATION_ERROR_MESSAGE_HEADER_UNKNOWN_METHOD";
    case VALIDATION_ERROR_DIFFERENT_SIZED_ARRAYS_IN_MAP:
      return "VALIDATION_ERROR_DIFFERENT_SIZED_ARRAYS_IN_MAP";
    case VALIDATION_ERROR_UNKNOWN_UNION_TAG:
      return "VALIDATION_ERROR_UNKNOWN_UNION_TAG";
    case VALIDATION_ERROR_UNKNOWN_ENUM_VALUE:
      return "VALIDATION_ERROR_UNKNOWN_ENUM_VALUE";
    case VALIDATION_ERROR_DESERIALIZATION_FAILED:
      return "VALIDATION_ERROR_DESERIALIZATION_FAILED";
    case VALIDATION_ERROR_MAX_RECURSION_DEPTH:
      return "VALIDATION_ERROR_MAX_RECURSION_DEPTH";
  }

  return "Unknown error";
}

void ReportValidationError(ValidationContext* context,
                           ValidationError error,
                           const char* description) {
  if (g_validation_error_observer) {
    g_validation_error_observer->set_last_error(error);
    return;
  }

  if (description) {
    if (!g_suppress_logging) {
      LOG(ERROR) << "Invalid message: " << ValidationErrorToString(error)
                 << " (" << description << ")";
    }
    if (context->message()) {
      context->message()->NotifyBadMessage(
          base::StringPrintf("Validation failed for %s [%s (%s)]",
                             context->description().data(),
                             ValidationErrorToString(error), description));
    }
  } else {
    if (!g_suppress_logging)
      LOG(ERROR) << "Invalid message: " << ValidationErrorToString(error);
    if (context->message()) {
      context->message()->NotifyBadMessage(
          base::StringPrintf("Validation failed for %s [%s]",
                             context->description().data(),
                             ValidationErrorToString(error)));
    }
  }
}

void ReportValidationErrorForMessage(
    mojo::Message* message,
    ValidationError error,
    const char* description) {
  ValidationContext validation_context(nullptr, 0, 0, 0, message, description);
  ReportValidationError(&validation_context, error);
}

ScopedSuppressValidationErrorLoggingForTests
    ::ScopedSuppressValidationErrorLoggingForTests()
    : was_suppressed_(g_suppress_logging) {
  g_suppress_logging = true;
}

ScopedSuppressValidationErrorLoggingForTests
    ::~ScopedSuppressValidationErrorLoggingForTests() {
  g_suppress_logging = was_suppressed_;
}

ValidationErrorObserverForTesting::ValidationErrorObserverForTesting(
    const base::Closure& callback)
    : last_error_(VALIDATION_ERROR_NONE), callback_(callback) {
  DCHECK(!g_validation_error_observer);
  g_validation_error_observer = this;
}

ValidationErrorObserverForTesting::~ValidationErrorObserverForTesting() {
  DCHECK(g_validation_error_observer == this);
  g_validation_error_observer = nullptr;
}

bool ReportSerializationWarning(ValidationError error) {
  if (g_serialization_warning_observer) {
    g_serialization_warning_observer->set_last_warning(error);
    return true;
  }

  return false;
}

SerializationWarningObserverForTesting::SerializationWarningObserverForTesting()
    : last_warning_(VALIDATION_ERROR_NONE) {
  DCHECK(!g_serialization_warning_observer);
  g_serialization_warning_observer = this;
}

SerializationWarningObserverForTesting::
    ~SerializationWarningObserverForTesting() {
  DCHECK(g_serialization_warning_observer == this);
  g_serialization_warning_observer = nullptr;
}

}  // namespace internal
}  // namespace mojo