blob: 56075d688915a7285298665162bb87f685a46951 [file] [log] [blame]
dmichael@chromium.orgc0c370e2014-04-25 09:07:30 +09001// 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 "ipc/message_filter_router.h"
6
avi42ebda42015-12-22 11:39:04 +09007#include <stddef.h>
tfarina1cbfa082015-09-05 03:47:57 +09008#include <stdint.h>
9
avi42ebda42015-12-22 11:39:04 +090010#include "base/macros.h"
dmichael@chromium.orgc0c370e2014-04-25 09:07:30 +090011#include "ipc/ipc_message_macros.h"
12#include "ipc/ipc_message_utils.h"
13#include "ipc/message_filter.h"
14
15namespace IPC {
16
17namespace {
18
19bool TryFiltersImpl(MessageFilterRouter::MessageFilters& filters,
20 const IPC::Message& message) {
21 for (size_t i = 0; i < filters.size(); ++i) {
22 if (filters[i]->OnMessageReceived(message)) {
23 return true;
24 }
25 }
26 return false;
27}
28
29bool RemoveFilterImpl(MessageFilterRouter::MessageFilters& filters,
30 MessageFilter* filter) {
31 MessageFilterRouter::MessageFilters::iterator it =
32 std::remove(filters.begin(), filters.end(), filter);
33 if (it == filters.end())
34 return false;
35
36 filters.erase(it, filters.end());
37 return true;
38}
39
40bool ValidMessageClass(int message_class) {
41 return message_class >= 0 && message_class < LastIPCMsgStart;
42}
43
44} // namespace
45
46MessageFilterRouter::MessageFilterRouter() {}
47MessageFilterRouter::~MessageFilterRouter() {}
48
49void MessageFilterRouter::AddFilter(MessageFilter* filter) {
50 // Determine if the filter should be applied to all messages, or only
51 // messages of a certain class.
tfarina1cbfa082015-09-05 03:47:57 +090052 std::vector<uint32_t> supported_message_classes;
dmichael@chromium.orgc0c370e2014-04-25 09:07:30 +090053 if (filter->GetSupportedMessageClasses(&supported_message_classes)) {
54 DCHECK(!supported_message_classes.empty());
55 for (size_t i = 0; i < supported_message_classes.size(); ++i) {
56 const int message_class = supported_message_classes[i];
57 DCHECK(ValidMessageClass(message_class));
58 // Safely ignore repeated subscriptions to a given message class for the
59 // current filter being added.
60 if (!message_class_filters_[message_class].empty() &&
61 message_class_filters_[message_class].back() == filter) {
62 continue;
63 }
64 message_class_filters_[message_class].push_back(filter);
65 }
66 } else {
67 global_filters_.push_back(filter);
68 }
69}
70
71void MessageFilterRouter::RemoveFilter(MessageFilter* filter) {
72 if (RemoveFilterImpl(global_filters_, filter))
73 return;
74
75 for (size_t i = 0; i < arraysize(message_class_filters_); ++i)
76 RemoveFilterImpl(message_class_filters_[i], filter);
77}
78
79bool MessageFilterRouter::TryFilters(const Message& message) {
80 if (TryFiltersImpl(global_filters_, message))
81 return true;
82
83 const int message_class = IPC_MESSAGE_CLASS(message);
84 if (!ValidMessageClass(message_class))
85 return false;
86
87 return TryFiltersImpl(message_class_filters_[message_class], message);
88}
89
90void MessageFilterRouter::Clear() {
91 global_filters_.clear();
92 for (size_t i = 0; i < arraysize(message_class_filters_); ++i)
93 message_class_filters_[i].clear();
94}
95
96} // namespace IPC