Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / extensions / api / declarative_content / content_action.cc
1 // Copyright (c) 2012 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/api/declarative_content/content_action.h"
6
7 #include <map>
8
9 #include "base/lazy_instance.h"
10 #include "base/strings/stringprintf.h"
11 #include "base/values.h"
12 #include "chrome/browser/extensions/api/declarative_content/content_constants.h"
13 #include "chrome/browser/extensions/extension_action.h"
14 #include "chrome/browser/extensions/extension_action_manager.h"
15 #include "chrome/browser/extensions/extension_service.h"
16 #include "chrome/browser/extensions/extension_tab_util.h"
17 #include "chrome/browser/profiles/profile.h"
18 #include "content/public/browser/invalidate_type.h"
19 #include "content/public/browser/web_contents.h"
20 #include "extensions/browser/extension_system.h"
21 #include "extensions/common/extension.h"
22
23 namespace extensions {
24
25 namespace keys = declarative_content_constants;
26
27 namespace {
28 // Error messages.
29 const char kInvalidInstanceTypeError[] =
30     "An action has an invalid instanceType: %s";
31 const char kNoPageAction[] =
32     "Can't use declarativeContent.ShowPageAction without a page action";
33
34 #define INPUT_FORMAT_VALIDATE(test) do { \
35     if (!(test)) { \
36       *bad_message = true; \
37       return scoped_refptr<ContentAction>(NULL); \
38     } \
39   } while (0)
40
41 //
42 // The following are concrete actions.
43 //
44
45 // Action that instructs to show an extension's page action.
46 class ShowPageAction : public ContentAction {
47  public:
48   ShowPageAction() {}
49
50   static scoped_refptr<ContentAction> Create(const Extension* extension,
51                                              const base::DictionaryValue* dict,
52                                              std::string* error,
53                                              bool* bad_message) {
54     // We can't show a page action if the extension doesn't have one.
55     if (ActionInfo::GetPageActionInfo(extension) == NULL) {
56       *error = kNoPageAction;
57       return scoped_refptr<ContentAction>();
58     }
59     return scoped_refptr<ContentAction>(new ShowPageAction);
60   }
61
62   // Implementation of ContentAction:
63   virtual Type GetType() const OVERRIDE { return ACTION_SHOW_PAGE_ACTION; }
64   virtual void Apply(const std::string& extension_id,
65                      const base::Time& extension_install_time,
66                      ApplyInfo* apply_info) const OVERRIDE {
67     GetPageAction(apply_info->profile, extension_id)->DeclarativeShow(
68         ExtensionTabUtil::GetTabId(apply_info->tab));
69     apply_info->tab->NotifyNavigationStateChanged(
70         content::INVALIDATE_TYPE_PAGE_ACTIONS);
71   }
72   virtual void Revert(const std::string& extension_id,
73                       const base::Time& extension_install_time,
74                       ApplyInfo* apply_info) const OVERRIDE {
75     if (ExtensionAction* action =
76             GetPageAction(apply_info->profile, extension_id)) {
77       action->UndoDeclarativeShow(ExtensionTabUtil::GetTabId(apply_info->tab));
78       apply_info->tab->NotifyNavigationStateChanged(
79           content::INVALIDATE_TYPE_PAGE_ACTIONS);
80     }
81   }
82
83  private:
84   static ExtensionAction* GetPageAction(Profile* profile,
85                                         const std::string& extension_id) {
86     ExtensionService* service =
87         ExtensionSystem::Get(profile)->extension_service();
88     const Extension* extension = service->GetInstalledExtension(extension_id);
89     if (!extension)
90       return NULL;
91     return ExtensionActionManager::Get(profile)->GetPageAction(*extension);
92   }
93   virtual ~ShowPageAction() {}
94
95   DISALLOW_COPY_AND_ASSIGN(ShowPageAction);
96 };
97
98 struct ContentActionFactory {
99   // Factory methods for ContentAction instances. |extension| is the extension
100   // for which the action is being created. |dict| contains the json dictionary
101   // that describes the action. |error| is used to return error messages in case
102   // the extension passed an action that was syntactically correct but
103   // semantically incorrect. |bad_message| is set to true in case |dict| does
104   // not confirm to the validated JSON specification.
105   typedef scoped_refptr<ContentAction>(*FactoryMethod)(
106       const Extension* /* extension */,
107       const base::DictionaryValue* /* dict */,
108       std::string* /* error */,
109       bool* /* bad_message */);
110   // Maps the name of a declarativeContent action type to the factory
111   // function creating it.
112   std::map<std::string, FactoryMethod> factory_methods;
113
114   ContentActionFactory() {
115     factory_methods[keys::kShowPageAction] =
116         &ShowPageAction::Create;
117   }
118 };
119
120 base::LazyInstance<ContentActionFactory>::Leaky
121     g_content_action_factory = LAZY_INSTANCE_INITIALIZER;
122
123 }  // namespace
124
125 //
126 // ContentAction
127 //
128
129 ContentAction::ContentAction() {}
130
131 ContentAction::~ContentAction() {}
132
133 // static
134 scoped_refptr<ContentAction> ContentAction::Create(
135     const Extension* extension,
136     const base::Value& json_action,
137     std::string* error,
138     bool* bad_message) {
139   *error = "";
140   *bad_message = false;
141
142   const base::DictionaryValue* action_dict = NULL;
143   INPUT_FORMAT_VALIDATE(json_action.GetAsDictionary(&action_dict));
144
145   std::string instance_type;
146   INPUT_FORMAT_VALIDATE(
147       action_dict->GetString(keys::kInstanceType, &instance_type));
148
149   ContentActionFactory& factory = g_content_action_factory.Get();
150   std::map<std::string, ContentActionFactory::FactoryMethod>::iterator
151       factory_method_iter = factory.factory_methods.find(instance_type);
152   if (factory_method_iter != factory.factory_methods.end())
153     return (*factory_method_iter->second)(
154         extension, action_dict, error, bad_message);
155
156   *error = base::StringPrintf(kInvalidInstanceTypeError, instance_type.c_str());
157   return scoped_refptr<ContentAction>();
158 }
159
160 }  // namespace extensions