• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "ipc/message_filter_router.h"
6 
7 #include <stddef.h>
8 #include <stdint.h>
9 
10 #include "base/macros.h"
11 #include "ipc/ipc_message_macros.h"
12 #include "ipc/ipc_message_utils.h"
13 #include "ipc/message_filter.h"
14 
15 namespace IPC {
16 
17 namespace {
18 
TryFiltersImpl(MessageFilterRouter::MessageFilters & filters,const IPC::Message & message)19 bool 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 
RemoveFilterImpl(MessageFilterRouter::MessageFilters & filters,MessageFilter * filter)29 bool 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 
ValidMessageClass(int message_class)40 bool ValidMessageClass(int message_class) {
41   return message_class >= 0 && message_class < LastIPCMsgStart;
42 }
43 
44 }  // namespace
45 
46 MessageFilterRouter::MessageFilterRouter() = default;
47 MessageFilterRouter::~MessageFilterRouter() = default;
48 
AddFilter(MessageFilter * filter)49 void MessageFilterRouter::AddFilter(MessageFilter* filter) {
50   // Determine if the filter should be applied to all messages, or only
51   // messages of a certain class.
52   std::vector<uint32_t> supported_message_classes;
53   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 
RemoveFilter(MessageFilter * filter)71 void 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 
TryFilters(const Message & message)79 bool 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 
Clear()90 void 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
97