1 // Copyright 2014 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "mojo/public/cpp/bindings/lib/validation_errors.h" 6 7 #include "base/strings/stringprintf.h" 8 #include "mojo/public/cpp/bindings/message.h" 9 10 namespace mojo { 11 namespace internal { 12 namespace { 13 14 ValidationErrorObserverForTesting* g_validation_error_observer = nullptr; 15 SerializationWarningObserverForTesting* g_serialization_warning_observer = 16 nullptr; 17 bool g_suppress_logging = false; 18 19 } // namespace 20 21 const char* ValidationErrorToString(ValidationError error) { 22 switch (error) { 23 case VALIDATION_ERROR_NONE: 24 return "VALIDATION_ERROR_NONE"; 25 case VALIDATION_ERROR_MISALIGNED_OBJECT: 26 return "VALIDATION_ERROR_MISALIGNED_OBJECT"; 27 case VALIDATION_ERROR_ILLEGAL_MEMORY_RANGE: 28 return "VALIDATION_ERROR_ILLEGAL_MEMORY_RANGE"; 29 case VALIDATION_ERROR_UNEXPECTED_STRUCT_HEADER: 30 return "VALIDATION_ERROR_UNEXPECTED_STRUCT_HEADER"; 31 case VALIDATION_ERROR_UNEXPECTED_ARRAY_HEADER: 32 return "VALIDATION_ERROR_UNEXPECTED_ARRAY_HEADER"; 33 case VALIDATION_ERROR_ILLEGAL_HANDLE: 34 return "VALIDATION_ERROR_ILLEGAL_HANDLE"; 35 case VALIDATION_ERROR_UNEXPECTED_INVALID_HANDLE: 36 return "VALIDATION_ERROR_UNEXPECTED_INVALID_HANDLE"; 37 case VALIDATION_ERROR_ILLEGAL_POINTER: 38 return "VALIDATION_ERROR_ILLEGAL_POINTER"; 39 case VALIDATION_ERROR_UNEXPECTED_NULL_POINTER: 40 return "VALIDATION_ERROR_UNEXPECTED_NULL_POINTER"; 41 case VALIDATION_ERROR_ILLEGAL_INTERFACE_ID: 42 return "VALIDATION_ERROR_ILLEGAL_INTERFACE_ID"; 43 case VALIDATION_ERROR_UNEXPECTED_INVALID_INTERFACE_ID: 44 return "VALIDATION_ERROR_UNEXPECTED_INVALID_INTERFACE_ID"; 45 case VALIDATION_ERROR_MESSAGE_HEADER_INVALID_FLAGS: 46 return "VALIDATION_ERROR_MESSAGE_HEADER_INVALID_FLAGS"; 47 case VALIDATION_ERROR_MESSAGE_HEADER_MISSING_REQUEST_ID: 48 return "VALIDATION_ERROR_MESSAGE_HEADER_MISSING_REQUEST_ID"; 49 case VALIDATION_ERROR_MESSAGE_HEADER_UNKNOWN_METHOD: 50 return "VALIDATION_ERROR_MESSAGE_HEADER_UNKNOWN_METHOD"; 51 case VALIDATION_ERROR_DIFFERENT_SIZED_ARRAYS_IN_MAP: 52 return "VALIDATION_ERROR_DIFFERENT_SIZED_ARRAYS_IN_MAP"; 53 case VALIDATION_ERROR_UNKNOWN_UNION_TAG: 54 return "VALIDATION_ERROR_UNKNOWN_UNION_TAG"; 55 case VALIDATION_ERROR_UNKNOWN_ENUM_VALUE: 56 return "VALIDATION_ERROR_UNKNOWN_ENUM_VALUE"; 57 case VALIDATION_ERROR_DESERIALIZATION_FAILED: 58 return "VALIDATION_ERROR_DESERIALIZATION_FAILED"; 59 case VALIDATION_ERROR_MAX_RECURSION_DEPTH: 60 return "VALIDATION_ERROR_MAX_RECURSION_DEPTH"; 61 } 62 63 return "Unknown error"; 64 } 65 66 void ReportValidationError(ValidationContext* context, 67 ValidationError error, 68 const char* description) { 69 if (g_validation_error_observer) { 70 g_validation_error_observer->set_last_error(error); 71 return; 72 } 73 74 if (description) { 75 if (!g_suppress_logging) { 76 LOG(ERROR) << "Invalid message: " << ValidationErrorToString(error) 77 << " (" << description << ")"; 78 } 79 if (context->message()) { 80 context->message()->NotifyBadMessage( 81 base::StringPrintf("Validation failed for %s [%s (%s)]", 82 context->description().data(), 83 ValidationErrorToString(error), description)); 84 } 85 } else { 86 if (!g_suppress_logging) 87 LOG(ERROR) << "Invalid message: " << ValidationErrorToString(error); 88 if (context->message()) { 89 context->message()->NotifyBadMessage( 90 base::StringPrintf("Validation failed for %s [%s]", 91 context->description().data(), 92 ValidationErrorToString(error))); 93 } 94 } 95 } 96 97 void ReportValidationErrorForMessage( 98 mojo::Message* message, 99 ValidationError error, 100 const char* description) { 101 ValidationContext validation_context(nullptr, 0, 0, 0, message, description); 102 ReportValidationError(&validation_context, error); 103 } 104 105 ScopedSuppressValidationErrorLoggingForTests 106 ::ScopedSuppressValidationErrorLoggingForTests() 107 : was_suppressed_(g_suppress_logging) { 108 g_suppress_logging = true; 109 } 110 111 ScopedSuppressValidationErrorLoggingForTests 112 ::~ScopedSuppressValidationErrorLoggingForTests() { 113 g_suppress_logging = was_suppressed_; 114 } 115 116 ValidationErrorObserverForTesting::ValidationErrorObserverForTesting( 117 const base::Closure& callback) 118 : last_error_(VALIDATION_ERROR_NONE), callback_(callback) { 119 DCHECK(!g_validation_error_observer); 120 g_validation_error_observer = this; 121 } 122 123 ValidationErrorObserverForTesting::~ValidationErrorObserverForTesting() { 124 DCHECK(g_validation_error_observer == this); 125 g_validation_error_observer = nullptr; 126 } 127 128 bool ReportSerializationWarning(ValidationError error) { 129 if (g_serialization_warning_observer) { 130 g_serialization_warning_observer->set_last_warning(error); 131 return true; 132 } 133 134 return false; 135 } 136 137 SerializationWarningObserverForTesting::SerializationWarningObserverForTesting() 138 : last_warning_(VALIDATION_ERROR_NONE) { 139 DCHECK(!g_serialization_warning_observer); 140 g_serialization_warning_observer = this; 141 } 142 143 SerializationWarningObserverForTesting:: 144 ~SerializationWarningObserverForTesting() { 145 DCHECK(g_serialization_warning_observer == this); 146 g_serialization_warning_observer = nullptr; 147 } 148 149 } // namespace internal 150 } // namespace mojo 151