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#ifndef EXTENSIONS_BROWSER_PROCESS_MAP_H_
6#define EXTENSIONS_BROWSER_PROCESS_MAP_H_
7
8#include <set>
9#include <string>
10
11#include "base/basictypes.h"
12#include "components/keyed_service/core/keyed_service.h"
13#include "extensions/common/features/feature.h"
14
15namespace content {
16class BrowserContext;
17}
18
19namespace extensions {
20class Extension;
21
22// Contains information about which extensions are assigned to which processes.
23//
24// The relationship between extensions and processes is complex:
25//
26// - Extensions can be either "split" mode or "spanning" mode.
27// - In spanning mode, extensions share a single process between all incognito
28//   and normal windows. This was the original mode for extensions.
29// - In split mode, extensions have separate processes in incognito windows.
30// - There are also hosted apps, which are a kind of extensions, and those
31//   usually have a process model similar to normal web sites: multiple
32//   processes per-profile.
33// - A single hosted app can have more than one SiteInstance in the same process
34//   if we're over the process limit and force them to share a process.
35//
36// In general, we seem to play with the process model of extensions a lot, so
37// it is safest to assume it is many-to-many in most places in the codebase.
38//
39// Note that because of content scripts, frames, and other edge cases in
40// Chrome's process isolation, extension code can still end up running outside
41// an assigned process.
42//
43// But we only allow high-privilege operations to be performed by an extension
44// when it is running in an assigned process.
45//
46// ===========================================================================
47// WARNINGS - PLEASE UNDERSTAND THESE BEFORE CALLING OR MODIFYING THIS CLASS
48// ===========================================================================
49//
50// 1. This class contains the processes for hosted apps as well as extensions
51//    and packaged apps. Just because a process is present here *does not* mean
52//    it is an "extension process" (e.g., for UI purposes). It may contain only
53//    hosted apps. See crbug.com/102533.
54//
55// 2. An extension can show up in multiple processes. That is why there is no
56//    GetExtensionProcess() method here. There are two cases: a) The extension
57//    is actually a hosted app, in which case this is normal, or b) there is an
58//    incognito window open and the extension is "split mode". It is *not safe*
59//    to assume that there is one process per extension. If you only care about
60//    extensions (not hosted apps), and you are on the UI thread, and you don't
61//    care about incognito version of this extension (or vice versa if you're in
62//    an incognito profile) then use
63//    extensions::ProcessManager::GetSiteInstanceForURL()->[Has|Get]Process().
64//
65// 3. The process ids contained in this class are *not limited* to the Profile
66//    you got this map from. They can also be associated with that profile's
67//    incognito/normal twin. If you care about this, use
68//    RenderProcessHost::FromID() and check the profile of the resulting object.
69//
70// TODO(aa): The above warnings suggest this class could use improvement :).
71//
72// TODO(kalman): This class is not threadsafe, but is used on both the UI and
73//               IO threads. Somebody should fix that, either make it
74//               threadsafe or enforce single thread. Investigation required.
75class ProcessMap : public KeyedService {
76 public:
77  ProcessMap();
78  virtual ~ProcessMap();
79
80  // Returns the instance for |browser_context|. An instance is shared between
81  // an incognito and a regular context.
82  static ProcessMap* Get(content::BrowserContext* browser_context);
83
84  size_t size() const { return items_.size(); }
85
86  bool Insert(const std::string& extension_id, int process_id,
87              int site_instance_id);
88
89  bool Remove(const std::string& extension_id, int process_id,
90              int site_instance_id);
91  int RemoveAllFromProcess(int process_id);
92
93  bool Contains(const std::string& extension_id, int process_id) const;
94  bool Contains(int process_id) const;
95
96  std::set<std::string> GetExtensionsInProcess(int process_id) const;
97
98  // Gets the most likely context type for the process with ID |process_id|
99  // which hosts Extension |extension|, if any (may be NULL). Context types are
100  // renderer (JavaScript) concepts but the browser can do a decent job in
101  // guessing what the process hosts.
102  //
103  // |extension| is the funky part - unfortunately we need to trust the
104  // caller of this method to be correct that indeed the context does feature
105  // an extension. This matters for iframes, where an extension could be
106  // hosted in another extension's process (privilege level needs to be
107  // downgraded) or in a web page's process (privilege level needs to be
108  // upgraded).
109  //
110  // The latter of these is slightly problematic from a security perspective;
111  // if a web page renderer gets owned it could try to pretend it's an
112  // extension and get access to some unprivileged APIs. Luckly, when OOP
113  // iframes lauch, it won't be an issue.
114  //
115  // Anyhow, the expected behaviour is:
116  //   - For hosted app processes, this will be blessed_web_page.
117  //   - For other extension processes, this will be blessed_extension.
118  //   - For WebUI processes, this will be a webui.
119  //   - For any other extension we have the choice of unblessed_extension or
120  //     content_script. Since content scripts are more common, guess that.
121  //     We *could* in theory track which web processes have extension frames
122  //     in them, and those would be unblessed_extension, but we don't at the
123  //     moment, and once OOP iframes exist then there won't even be such a
124  //     thing as an unblessed_extension context.
125  //   - For anything else, web_page.
126  Feature::Context GetMostLikelyContextType(const Extension* extension,
127                                            int process_id) const;
128
129 private:
130  struct Item;
131
132  typedef std::set<Item> ItemSet;
133  ItemSet items_;
134
135  DISALLOW_COPY_AND_ASSIGN(ProcessMap);
136};
137
138}  // namespace extensions
139
140#endif  // EXTENSIONS_BROWSER_PROCESS_MAP_H_
141