summaryrefslogtreecommitdiffstats
path: root/chrome/browser/browsing_instance.cc
blob: ff3346aa2dc70cd1ea364df8290478a709329a76 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
// Copyright (c) 2006-2008 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 "chrome/browser/browsing_instance.h"

#include "base/command_line.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/renderer_host/site_instance.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/url_constants.h"

/*static*/
BrowsingInstance::ProfileSiteInstanceMap
    BrowsingInstance::profile_site_instance_map_;

bool BrowsingInstance::ShouldUseProcessPerSite(const GURL& url) {
  // Returns true if we should use the process-per-site model.  This will be
  // the case if the --process-per-site switch is specified, or in
  // process-per-site-instance for particular sites (e.g., the new tab page).

  const CommandLine& command_line = *CommandLine::ForCurrentProcess();
  if (command_line.HasSwitch(switches::kProcessPerSite))
    return true;

  if (!command_line.HasSwitch(switches::kProcessPerTab)) {
    // We are not in process-per-site or process-per-tab, so we must be in the
    // default (process-per-site-instance).  Only use the process-per-site
    // logic for particular sites that we want to consolidate.
    // Note that --single-process may have been specified, but that affects the
    // process creation logic in RenderProcessHost, so we do not need to worry
    // about it here.
    if (url.SchemeIs(chrome::kChromeUIScheme) ||
        url.SchemeIs(chrome::kExtensionScheme))
      // Always consolidate instances of the new tab page (and instances of any
      // other internal resource urls), as well as extensions.
      return true;

    // TODO(creis): List any other special cases that we want to limit to a
    // single process for all instances.
  }

  // In all other cases, don't use process-per-site logic.
  return false;
}

BrowsingInstance::SiteInstanceMap* BrowsingInstance::GetSiteInstanceMap(
    Profile* profile, const GURL& url) {
  if (!ShouldUseProcessPerSite(url)) {
    // Not using process-per-site, so use a map specific to this instance.
    return &site_instance_map_;
  }

  // Otherwise, process-per-site is in use, at least for this URL.  Look up the
  // global map for this profile, creating an entry if necessary.
  ProfileId runtime_id = profile ? profile->GetRuntimeId()
                                 : Profile::InvalidProfileId;
  return &profile_site_instance_map_[runtime_id];
}

bool BrowsingInstance::HasSiteInstance(const GURL& url) {
  std::string site = SiteInstance::GetSiteForURL(url).possibly_invalid_spec();

  SiteInstanceMap* map = GetSiteInstanceMap(profile_, url);
  SiteInstanceMap::iterator i = map->find(site);
  return (i != map->end());
}

SiteInstance* BrowsingInstance::GetSiteInstanceForURL(const GURL& url) {
  std::string site = SiteInstance::GetSiteForURL(url).possibly_invalid_spec();

  SiteInstanceMap* map = GetSiteInstanceMap(profile_, url);
  SiteInstanceMap::iterator i = map->find(site);
  if (i != map->end()) {
    return i->second;
  }

  // No current SiteInstance for this site, so let's create one.
  SiteInstance* instance = new SiteInstance(this);

  // Set the site of this new SiteInstance, which will register it with us.
  instance->SetSite(url);
  return instance;
}

void BrowsingInstance::RegisterSiteInstance(SiteInstance* site_instance) {
  DCHECK(site_instance->browsing_instance() == this);
  DCHECK(site_instance->has_site());
  std::string site = site_instance->site().possibly_invalid_spec();

  // Only register if we don't have a SiteInstance for this site already.
  // It's possible to have two SiteInstances point to the same site if two
  // tabs are navigated there at the same time.  (We don't call SetSite or
  // register them until DidNavigate.)  If there is a previously existing
  // SiteInstance for this site, we just won't register the new one.
  SiteInstanceMap* map = GetSiteInstanceMap(profile_, site_instance->site());
  SiteInstanceMap::iterator i = map->find(site);
  if (i == map->end()) {
    // Not previously registered, so register it.
    (*map)[site] = site_instance;
  }
}

void BrowsingInstance::UnregisterSiteInstance(SiteInstance* site_instance) {
  DCHECK(site_instance->browsing_instance() == this);
  DCHECK(site_instance->has_site());
  std::string site = site_instance->site().possibly_invalid_spec();

  // Only unregister the SiteInstance if it is the same one that is registered
  // for the site.  (It might have been an unregistered SiteInstance.  See the
  // comments in RegisterSiteInstance.)
  SiteInstanceMap* map = GetSiteInstanceMap(profile_, site_instance->site());
  SiteInstanceMap::iterator i = map->find(site);
  if (i != map->end() && i->second == site_instance) {
    // Matches, so erase it.
    map->erase(i);
  }
}