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