Index: ipc/message_filter_router.cc |
diff --git a/ipc/message_filter_router.cc b/ipc/message_filter_router.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..766ba821b1003e37e05943d3cd4a5f969858f32d |
--- /dev/null |
+++ b/ipc/message_filter_router.cc |
@@ -0,0 +1,92 @@ |
+// Copyright (c) 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 "ipc/message_filter_router.h" |
+ |
+#include "ipc/ipc_message_macros.h" |
+#include "ipc/ipc_message_utils.h" |
+#include "ipc/message_filter.h" |
+ |
+namespace IPC { |
+ |
+namespace { |
+ |
+bool TryFiltersImpl(MessageFilterRouter::MessageFilters& filters, |
+ const IPC::Message& message) { |
+ for (size_t i = 0; i < filters.size(); ++i) { |
+ if (filters[i]->OnMessageReceived(message)) { |
+ return true; |
+ } |
+ } |
+ return false; |
+} |
+ |
+bool RemoveFilterImpl(MessageFilterRouter::MessageFilters& filters, |
+ MessageFilter* filter) { |
+ MessageFilterRouter::MessageFilters::iterator it = |
+ std::remove(filters.begin(), filters.end(), filter); |
+ if (it == filters.end()) |
+ return false; |
+ |
+ filters.erase(it, filters.end()); |
+ return true; |
+} |
+ |
+bool ValidMessageClass(int message_class) { |
+ return message_class >= 0 && message_class < LastIPCMsgStart; |
+} |
+ |
+} // namespace |
+ |
+MessageFilterRouter::MessageFilterRouter() {} |
+MessageFilterRouter::~MessageFilterRouter() {} |
+ |
+void MessageFilterRouter::AddFilter(MessageFilter* filter) { |
+ // Determine if the filter should be applied to all messages, or only |
+ // messages of a certain class. |
+ std::vector<uint32> supported_message_classes; |
+ if (filter->GetSupportedMessageClasses(&supported_message_classes)) { |
+ DCHECK(!supported_message_classes.empty()); |
+ for (size_t i = 0; i < supported_message_classes.size(); ++i) { |
+ const int message_class = supported_message_classes[i]; |
+ DCHECK(ValidMessageClass(message_class)); |
+ // Safely ignore repeated subscriptions to a given message class for the |
+ // current filter being added. |
+ if (!message_class_filters_[message_class].empty() && |
+ message_class_filters_[message_class].back() == filter) { |
+ continue; |
+ } |
+ message_class_filters_[message_class].push_back(filter); |
+ } |
+ } else { |
+ global_filters_.push_back(filter); |
+ } |
+} |
+ |
+void MessageFilterRouter::RemoveFilter(MessageFilter* filter) { |
+ if (RemoveFilterImpl(global_filters_, filter)) |
+ return; |
+ |
+ for (size_t i = 0; i < arraysize(message_class_filters_); ++i) |
+ RemoveFilterImpl(message_class_filters_[i], filter); |
+} |
+ |
+bool MessageFilterRouter::TryFilters(const Message& message) { |
+ if (TryFiltersImpl(global_filters_, message)) |
+ return true; |
+ |
+ const int message_class = IPC_MESSAGE_CLASS(message); |
+ if (!ValidMessageClass(message_class)) |
+ return false; |
+ |
+ return TryFiltersImpl(message_class_filters_[message_class], message); |
+} |
+ |
+void MessageFilterRouter::Clear() { |
+ global_filters_.clear(); |
+ for (size_t i = 0; i < arraysize(message_class_filters_); ++i) |
+ message_class_filters_[i].clear(); |
+} |
+ |
+} // namespace IPC |