1// Copyright 2013 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 "extensions/browser/process_map.h"
6
7#include "content/public/browser/child_process_security_policy.h"
8#include "extensions/browser/extension_registry.h"
9#include "extensions/browser/process_map_factory.h"
10#include "extensions/common/extension.h"
11#include "extensions/common/features/feature.h"
12
13namespace extensions {
14
15// Item
16struct ProcessMap::Item {
17  Item() : process_id(0), site_instance_id(0) {
18  }
19
20  // Purposely implicit constructor needed on older gcc's. See:
21  // http://codereview.chromium.org/8769022/
22  explicit Item(const ProcessMap::Item& other)
23      : extension_id(other.extension_id),
24        process_id(other.process_id),
25        site_instance_id(other.site_instance_id) {
26  }
27
28  Item(const std::string& extension_id, int process_id,
29       int site_instance_id)
30      : extension_id(extension_id),
31        process_id(process_id),
32        site_instance_id(site_instance_id) {
33  }
34
35  ~Item() {
36  }
37
38  bool operator<(const ProcessMap::Item& other) const {
39    if (extension_id < other.extension_id)
40      return true;
41
42    if (extension_id == other.extension_id &&
43        process_id < other.process_id) {
44      return true;
45    }
46
47    if (extension_id == other.extension_id &&
48        process_id == other.process_id &&
49        site_instance_id < other.site_instance_id) {
50      return true;
51    }
52
53    return false;
54  }
55
56  std::string extension_id;
57  int process_id;
58  int site_instance_id;
59};
60
61
62// ProcessMap
63ProcessMap::ProcessMap() {
64}
65
66ProcessMap::~ProcessMap() {
67}
68
69// static
70ProcessMap* ProcessMap::Get(content::BrowserContext* browser_context) {
71  return ProcessMapFactory::GetForBrowserContext(browser_context);
72}
73
74bool ProcessMap::Insert(const std::string& extension_id, int process_id,
75                        int site_instance_id) {
76  return items_.insert(Item(extension_id, process_id, site_instance_id)).second;
77}
78
79bool ProcessMap::Remove(const std::string& extension_id, int process_id,
80                        int site_instance_id) {
81  return items_.erase(Item(extension_id, process_id, site_instance_id)) > 0;
82}
83
84int ProcessMap::RemoveAllFromProcess(int process_id) {
85  int result = 0;
86  for (ItemSet::iterator iter = items_.begin(); iter != items_.end(); ) {
87    if (iter->process_id == process_id) {
88      items_.erase(iter++);
89      ++result;
90    } else {
91      ++iter;
92    }
93  }
94  return result;
95}
96
97bool ProcessMap::Contains(const std::string& extension_id,
98                          int process_id) const {
99  for (ItemSet::const_iterator iter = items_.begin(); iter != items_.end();
100       ++iter) {
101    if (iter->process_id == process_id && iter->extension_id == extension_id)
102      return true;
103  }
104  return false;
105}
106
107bool ProcessMap::Contains(int process_id) const {
108  for (ItemSet::const_iterator iter = items_.begin(); iter != items_.end();
109       ++iter) {
110    if (iter->process_id == process_id)
111      return true;
112  }
113  return false;
114}
115
116std::set<std::string> ProcessMap::GetExtensionsInProcess(int process_id) const {
117  std::set<std::string> result;
118  for (ItemSet::const_iterator iter = items_.begin(); iter != items_.end();
119       ++iter) {
120    if (iter->process_id == process_id)
121      result.insert(iter->extension_id);
122  }
123  return result;
124}
125
126Feature::Context ProcessMap::GetMostLikelyContextType(
127    const Extension* extension,
128    int process_id) const {
129  // WARNING: This logic must match Dispatcher::ClassifyJavaScriptContext, as
130  // much as possible.
131
132  if (content::ChildProcessSecurityPolicy::GetInstance()->HasWebUIBindings(
133          process_id)) {
134    return Feature::WEBUI_CONTEXT;
135  }
136
137  if (!extension) {
138    return Feature::WEB_PAGE_CONTEXT;
139  }
140
141  if (!Contains(extension->id(), process_id)) {
142    // This could equally be UNBLESSED_EXTENSION_CONTEXT, but we don't record
143    // which processes have extension frames in them.
144    // TODO(kalman): Investigate this.
145    return Feature::CONTENT_SCRIPT_CONTEXT;
146  }
147
148  if (extension->is_hosted_app() &&
149      extension->location() != Manifest::COMPONENT) {
150    return Feature::BLESSED_WEB_PAGE_CONTEXT;
151  }
152
153  return Feature::BLESSED_EXTENSION_CONTEXT;
154}
155
156}  // namespace extensions
157