extension_util.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
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 "chrome/browser/extensions/extension_util.h"
6
7#include "base/command_line.h"
8#include "chrome/browser/extensions/extension_service.h"
9#include "chrome/browser/extensions/extension_sync_service.h"
10#include "chrome/browser/profiles/profile.h"
11#include "chrome/common/chrome_switches.h"
12#include "chrome/common/extensions/sync_helper.h"
13#include "content/public/browser/site_instance.h"
14#include "extensions/browser/extension_prefs.h"
15#include "extensions/browser/extension_registry.h"
16#include "extensions/browser/extension_system.h"
17#include "extensions/common/extension.h"
18#include "extensions/common/manifest.h"
19#include "extensions/common/manifest_handlers/incognito_info.h"
20
21namespace extensions {
22namespace util {
23
24bool IsIncognitoEnabled(const std::string& extension_id,
25                        content::BrowserContext* context) {
26  const Extension* extension = ExtensionRegistry::Get(context)->
27      GetExtensionById(extension_id, ExtensionRegistry::ENABLED);
28  if (extension) {
29    if (!extension->can_be_incognito_enabled())
30      return false;
31    // If this is an existing component extension we always allow it to
32    // work in incognito mode.
33    if (extension->location() == Manifest::COMPONENT)
34      return true;
35    if (extension->force_incognito_enabled())
36      return true;
37  }
38
39  return ExtensionPrefs::Get(context)->IsIncognitoEnabled(extension_id);
40}
41
42void SetIsIncognitoEnabled(const std::string& extension_id,
43                           content::BrowserContext* context,
44                           bool enabled) {
45  ExtensionService* service =
46      ExtensionSystem::Get(context)->extension_service();
47  CHECK(service);
48  const Extension* extension = service->GetInstalledExtension(extension_id);
49
50  if (extension) {
51    if (!extension->can_be_incognito_enabled())
52      return;
53
54    if (extension->location() == Manifest::COMPONENT) {
55      // This shouldn't be called for component extensions unless it is called
56      // by sync, for syncable component extensions.
57      // See http://crbug.com/112290 and associated CLs for the sordid history.
58      DCHECK(sync_helper::IsSyncable(extension));
59
60      // If we are here, make sure the we aren't trying to change the value.
61      DCHECK_EQ(enabled, IsIncognitoEnabled(extension_id, service->profile()));
62      return;
63    }
64  }
65
66  ExtensionPrefs* extension_prefs = service->extension_prefs();
67  // Broadcast unloaded and loaded events to update browser state. Only bother
68  // if the value changed and the extension is actually enabled, since there is
69  // no UI otherwise.
70  bool old_enabled = extension_prefs->IsIncognitoEnabled(extension_id);
71  if (enabled == old_enabled)
72    return;
73
74  extension_prefs->SetIsIncognitoEnabled(extension_id, enabled);
75
76  bool extension_is_enabled = service->extensions()->Contains(extension_id);
77
78  // When we reload the extension the ID may be invalidated if we've passed it
79  // by const ref everywhere. Make a copy to be safe.
80  std::string id = extension_id;
81  if (extension_is_enabled)
82    service->ReloadExtension(id);
83
84  // Reloading the extension invalidates the |extension| pointer.
85  extension = service->GetInstalledExtension(id);
86  if (extension) {
87    ExtensionSyncService::Get(service->profile())->
88        SyncExtensionChangeIfNeeded(*extension);
89  }
90}
91
92bool CanCrossIncognito(const Extension* extension,
93                       content::BrowserContext* context) {
94  // We allow the extension to see events and data from another profile iff it
95  // uses "spanning" behavior and it has incognito access. "split" mode
96  // extensions only see events for a matching profile.
97  CHECK(extension);
98  return IsIncognitoEnabled(extension->id(), context) &&
99         !IncognitoInfo::IsSplitMode(extension);
100}
101
102bool CanLoadInIncognito(const Extension* extension,
103                        content::BrowserContext* context) {
104  CHECK(extension);
105  if (extension->is_hosted_app())
106    return true;
107  // Packaged apps and regular extensions need to be enabled specifically for
108  // incognito (and split mode should be set).
109  return IncognitoInfo::IsSplitMode(extension) &&
110         IsIncognitoEnabled(extension->id(), context);
111}
112
113bool AllowFileAccess(const std::string& extension_id,
114                     content::BrowserContext* context) {
115  return CommandLine::ForCurrentProcess()->HasSwitch(
116             switches::kDisableExtensionsFileAccessCheck) ||
117         ExtensionPrefs::Get(context)->AllowFileAccess(extension_id);
118}
119
120void SetAllowFileAccess(const std::string& extension_id,
121                        content::BrowserContext* context,
122                        bool allow) {
123  ExtensionService* service =
124      ExtensionSystem::Get(context)->extension_service();
125  CHECK(service);
126
127  // Reload to update browser state. Only bother if the value changed and the
128  // extension is actually enabled, since there is no UI otherwise.
129  if (allow == AllowFileAccess(extension_id, context))
130    return;
131
132  service->extension_prefs()->SetAllowFileAccess(extension_id, allow);
133
134  bool extension_is_enabled = service->extensions()->Contains(extension_id);
135  if (extension_is_enabled)
136    service->ReloadExtension(extension_id);
137}
138
139bool IsAppLaunchable(const std::string& extension_id,
140                     content::BrowserContext* context) {
141  return !(ExtensionPrefs::Get(context)->GetDisableReasons(extension_id) &
142           Extension::DISABLE_UNSUPPORTED_REQUIREMENT);
143}
144
145bool IsAppLaunchableWithoutEnabling(const std::string& extension_id,
146                                    content::BrowserContext* context) {
147  return ExtensionRegistry::Get(context)->GetExtensionById(
148      extension_id, ExtensionRegistry::ENABLED) != NULL;
149}
150
151bool IsExtensionIdle(const std::string& extension_id,
152                     content::BrowserContext* context) {
153  ProcessManager* process_manager =
154      ExtensionSystem::Get(context)->process_manager();
155  DCHECK(process_manager);
156  ExtensionHost* host =
157      process_manager->GetBackgroundHostForExtension(extension_id);
158  if (host)
159    return false;
160
161  content::SiteInstance* site_instance = process_manager->GetSiteInstanceForURL(
162      Extension::GetBaseURLFromExtensionId(extension_id));
163  if (site_instance && site_instance->HasProcess())
164    return false;
165
166  return process_manager->GetRenderViewHostsForExtension(extension_id).empty();
167}
168
169bool IsExtensionInstalledPermanently(const std::string& extension_id,
170                                     content::BrowserContext* context) {
171  const Extension* extension = ExtensionRegistry::Get(context)->
172      GetExtensionById(extension_id, ExtensionRegistry::EVERYTHING);
173  return extension && !extension->is_ephemeral();
174}
175
176}  // namespace util
177}  // namespace extensions
178