summaryrefslogtreecommitdiffstats
path: root/chrome/browser/extensions/component_migration_helper.h
blob: 4f4ce9eb9cd61ff5469dbc8c6241587c948914e9 (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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
// Copyright 2016 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.

#ifndef CHROME_BROWSER_EXTENSIONS_COMPONENT_MIGRATION_HELPER_H_
#define CHROME_BROWSER_EXTENSIONS_COMPONENT_MIGRATION_HELPER_H_

#include <set>
#include <string>
#include <utility>
#include <vector>

#include "base/macros.h"
#include "base/scoped_observer.h"
#include "extensions/browser/extension_registry_observer.h"

class Profile;
class PrefRegistrySimple;
class PrefService;

namespace content {
class BrowserContext;
}

namespace extensions {

class ExtensionRegistry;
class ExtensionSystem;

// For migrating existing extensions to component actions, and vice versa.  A
// previous enabled extension is used as a signal to add the corresponding
// component action to the visible area of the toolbar. This allows users who
// have already installed the extension to have their preference for a component
// action in the visible area of the toolbar respected, without enabling this
// for the entire user base.
//
// MIGRATION LOGIC
//
// When the feature is enabled (i.e. by experiment or flag), the client should
// call OnFeatureEnabled(action_id).  The extension action redesign MUST also be
// enabled.
//
//   - If the extension is enabled, it is unloaded with a reason of
//     MIGRATED_TO_COMPONENT, the component action shown, and a pref set
//     recording the migration.
//   - If pref is set the component action is shown.
//   - Otherwise, the component action is not shown.
//
// When the feature is disabled (for example, by starting with a flag off), the
// client should call OnFeatureDisabled(action_id).
//
//   - The pref is removed.
//   - If the extension action redesign is enabled, the associated component
//     action is removed.
//
// USAGE
// helper->Register("some-action-id", "some-extension-id");
// helper->Register("some-action-id", "other-extension-id");
// ...
// // When feature is enabled
// helper->OnFeatureEnabled("some-action-id");
// ...
// // When feature is disabled
// helper->OnFeatureDisabled("some-action-id");
//
// It is legal to register more than one extension per action but not vice
// versa.
class ComponentMigrationHelper : public ExtensionRegistryObserver {
 public:
  // Object that knows how to manage component actions in the toolbar model.
  class ComponentActionDelegate {
   public:
    // Adds or removes the component action labeled by |action_id| from the
    // toolbar model.  The caller will not add the same action twice.
    virtual void AddComponentAction(const std::string& action_id) = 0;
    virtual void RemoveComponentAction(const std::string& action_id) = 0;

    // Returns |true| if the toolbar model has an action for |action_id|.
    virtual bool HasComponentAction(const std::string& action_id) const = 0;
  };

  ComponentMigrationHelper(Profile* profile, ComponentActionDelegate* delegate);
  ~ComponentMigrationHelper() override;

  static void RegisterPrefs(PrefRegistrySimple* registry);

  // Registers and unregisters a component action/extension pair.  A component
  // action may have more than one associated extension id, but not vice versa.
  void Register(const std::string& component_action_id,
                const ExtensionId& extension_id);
  void Unregister(const std::string& component_action_id,
                  const ExtensionId& extension_id);

  // Call when we should potentially add the component action and unload
  // the extension.  PREREQUISITE: The extension action redesign MUST be
  // enabled.
  void OnFeatureEnabled(const std::string& component_action_id);

  // Call when we should potentially remove the component action and re-enable
  // extension loading.
  void OnFeatureDisabled(const std::string& component_action_id);

  // Call when the user manually removes the component action from the toolbar.
  void OnActionRemoved(const std::string& component_action_id);

  // extensions::ExtensionRegistryObserver:
  void OnExtensionReady(content::BrowserContext* browser_context,
                        const Extension* extension) override;

 protected:
  // Protected for unit testing.
  void SetComponentActionPref(const std::string& component_action_id,
                              bool enabled);

  // A set of component action ids whose features are currently enabled.
  // Protected for unit testing.
  std::set<std::string> enabled_actions_;

 private:
  bool IsExtensionInstalledAndEnabled(const ExtensionId& extension_id) const;
  void UnloadExtension(const ExtensionId& extension_id);
  void RemoveComponentActionPref(const std::string& component_action_id);
  std::vector<std::string> GetExtensionIdsForActionId(
      const std::string& component_action_id) const;
  std::string GetActionIdForExtensionId(const ExtensionId& extension_id) const;

  Profile* const profile_;
  ComponentActionDelegate* const delegate_;
  // The ExtensionRegistry, PrefService, and ExtensionSystem, cached for
  // convenience.
  ExtensionRegistry* const extension_registry_;
  PrefService* const pref_service_;
  ExtensionSystem* const extension_system_;

  ScopedObserver<ExtensionRegistry, ExtensionRegistryObserver>
      extension_registry_observer_;

  // A list of pairs of component action ids and extension ids.
  std::vector<std::pair<std::string, ExtensionId>> migrated_actions_;

  DISALLOW_COPY_AND_ASSIGN(ComponentMigrationHelper);
};

}  // namespace extensions

#endif  // CHROME_BROWSER_EXTENSIONS_COMPONENT_MIGRATION_HELPER_H_