diff options
author | erikkay@google.com <erikkay@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-04-17 23:09:10 +0000 |
---|---|---|
committer | erikkay@google.com <erikkay@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-04-17 23:09:10 +0000 |
commit | 73404a373b7c8ca68793d58a0750d086dc49fdda (patch) | |
tree | eb9a0569b42fd3235913754df7a2baf79abb9e4f /chrome/browser | |
parent | bc5987b6febaa0562c1f21e91197937a53116a30 (diff) | |
download | chromium_src-73404a373b7c8ca68793d58a0750d086dc49fdda.zip chromium_src-73404a373b7c8ca68793d58a0750d086dc49fdda.tar.gz chromium_src-73404a373b7c8ca68793d58a0750d086dc49fdda.tar.bz2 |
A subset of the bookmarks API- missing events- missing unit tests- missing ability to change URL
Review URL: http://codereview.chromium.org/77003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@13977 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
-rw-r--r-- | chrome/browser/browser.vcproj | 8 | ||||
-rw-r--r-- | chrome/browser/extensions/extension_bookmarks_module.cc | 325 | ||||
-rw-r--r-- | chrome/browser/extensions/extension_bookmarks_module.h | 35 | ||||
-rw-r--r-- | chrome/browser/extensions/extension_function.cc | 11 | ||||
-rw-r--r-- | chrome/browser/extensions/extension_function.h | 22 | ||||
-rw-r--r-- | chrome/browser/extensions/extension_function_dispatcher.cc | 274 | ||||
-rw-r--r-- | chrome/browser/extensions/extension_function_dispatcher.h | 8 |
7 files changed, 562 insertions, 121 deletions
diff --git a/chrome/browser/browser.vcproj b/chrome/browser/browser.vcproj index 1e84abe..cacc5a3 100644 --- a/chrome/browser/browser.vcproj +++ b/chrome/browser/browser.vcproj @@ -1902,6 +1902,14 @@ > </File> <File + RelativePath=".\extensions\extension_bookmarks_module.cc" + > + </File> + <File + RelativePath=".\extensions\extension_bookmarks_module.h" + > + </File> + <File RelativePath=".\extensions\extension_browser_event_router.cc" > </File> diff --git a/chrome/browser/extensions/extension_bookmarks_module.cc b/chrome/browser/extensions/extension_bookmarks_module.cc new file mode 100644 index 0000000..aa720ca --- /dev/null +++ b/chrome/browser/extensions/extension_bookmarks_module.cc @@ -0,0 +1,325 @@ +// Copyright (c) 2009 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/extensions/extension_bookmarks_module.h" + +#include "chrome/browser/bookmarks/bookmark_codec.h" +#include "chrome/browser/bookmarks/bookmark_model.h" +#include "chrome/browser/bookmarks/bookmark_utils.h" +#include "chrome/browser/profile.h" + +namespace { +// keys +const wchar_t* kIdKey = L"id"; +const wchar_t* kIndexKey = L"index"; +const wchar_t* kParentIdKey = L"parentId"; +const wchar_t* kUrlKey = L"url"; +const wchar_t* kTitleKey = L"title"; +const wchar_t* kChildrenIdsKey = L"childrenIds"; +const wchar_t* kChildrenKey = L"childrenIds"; +const wchar_t* kRecursiveKey = L"recursive"; + +// errors +const char* kNoNodeError = "Can't find bookmark for id."; +const char* kNoParentError = "Can't find parent bookmark for id."; +const char* kFolderNotEmptyError = + "Can't remove non-empty folder (use recursive to force)."; +const char* kInvalidIndexError = "Index out of bounds."; +const char* kInvalidUrlError = "Invalid URL."; +const char* kModifySpecialError = "Can't modify the root bookmark folders."; +}; + +// Helper functions. +class ExtensionBookmarks { + public: + // Convert |node| into a JSON value + static DictionaryValue* GetNodeDictionary(BookmarkNode* node, bool recurse) { + DictionaryValue* dict = new DictionaryValue(); + dict->SetInteger(kIdKey, node->id()); + + BookmarkNode* parent = node->GetParent(); + if (parent) + dict->SetInteger(kParentIdKey, parent->id()); + + if (!node->is_folder()) + dict->SetString(kUrlKey, node->GetURL().spec()); + + dict->SetString(kTitleKey, node->GetTitle()); + + int childCount = node->GetChildCount(); + ListValue* children = new ListValue(); + for (int i = 0; i < childCount; ++i) { + BookmarkNode* child = node->GetChild(i); + if (recurse) { + DictionaryValue* dict = GetNodeDictionary(child, true); + children->Append(dict); + } else { + Value* child_id = new FundamentalValue(child->id()); + children->Append(child_id); + } + } + if (recurse) + dict->Set(kChildrenKey, children); + else + dict->Set(kChildrenIdsKey, children); + return dict; + } + + // Add a JSON representation of |node| to the JSON |list|. + static void AddNode(BookmarkNode* node, ListValue* list, bool recurse) { + DictionaryValue* dict = GetNodeDictionary(node, recurse); + list->Append(dict); + } + + private: + ExtensionBookmarks(); +}; + +// TODO(erikkay): add a recursive version +bool GetBookmarksFunction::RunImpl() { + // TODO(erikkay): the JSON schema doesn't support the TYPE_INTEGER + // variant yet. + EXTENSION_FUNCTION_VALIDATE(args_->IsType(Value::TYPE_LIST) || + args_->IsType(Value::TYPE_INTEGER) || + args_->IsType(Value::TYPE_NULL)); + BookmarkModel* model = profile()->GetBookmarkModel(); + scoped_ptr<ListValue> json(new ListValue()); + if (args_->IsType(Value::TYPE_INTEGER)) { + int id; + EXTENSION_FUNCTION_VALIDATE(args_->GetAsInteger(&id)); + BookmarkNode* node = model->GetNodeByID(id); + if (!node) { + error_ = kNoNodeError; + return false; + } + ExtensionBookmarks::AddNode(node, json.get(), false); + } else { + ListValue* ids = NULL; + size_t count = 0; + if (args_->IsType(Value::TYPE_LIST)) { + ids = static_cast<ListValue*>(args_); + count = ids->GetSize(); + } + if (count == 0) { + // If no ids are passed in, then we default to returning the root node. + BookmarkNode* node = model->root_node(); + ExtensionBookmarks::AddNode(node, json.get(), false); + } else { + for (size_t i = 0; i < count; ++i) { + int id = 0; + EXTENSION_FUNCTION_VALIDATE(ids->GetInteger(i, &id)); + BookmarkNode* node = model->GetNodeByID(id); + if (!node) { + error_ = kNoNodeError; + return false; + } else { + ExtensionBookmarks::AddNode(node, json.get(), false); + } + } + if (error_.size() && json->GetSize() == 0) { + return false; + } + } + } + + result_.reset(json.release()); + return true; +} + +bool SearchBookmarksFunction::RunImpl() { + EXTENSION_FUNCTION_VALIDATE(args_->IsType(Value::TYPE_STRING)); + + std::wstring query; + EXTENSION_FUNCTION_VALIDATE(args_->GetAsString(&query)); + + BookmarkModel* model = profile()->GetBookmarkModel(); + ListValue* json = new ListValue(); + std::vector<BookmarkNode*> nodes; + bookmark_utils::GetBookmarksContainingText(model, query, 50, &nodes); + std::vector<BookmarkNode*>::iterator i = nodes.begin(); + for (; i != nodes.end(); ++i) { + BookmarkNode* node = *i; + ExtensionBookmarks::AddNode(node, json, false); + } + + result_.reset(json); + return true; +} + +bool RemoveBookmarkFunction::RunImpl() { + EXTENSION_FUNCTION_VALIDATE(args_->IsType(Value::TYPE_DICTIONARY)); + DictionaryValue* json = static_cast<DictionaryValue*>(args_); + + // TODO(erikkay): it would be cool to take a list here as well. + int id; + EXTENSION_FUNCTION_VALIDATE(json->GetInteger(kIdKey, &id)); + + bool recursive = false; + json->GetBoolean(kRecursiveKey, &recursive); // optional + + BookmarkModel* model = profile()->GetBookmarkModel(); + BookmarkNode* node = model->GetNodeByID(id); + if (!node) { + error_ = kNoNodeError; + return false; + } + if (node == model->root_node() || + node == model->other_node() || + node == model->GetBookmarkBarNode()) { + error_ = kModifySpecialError; + return false; + } + if (node->is_folder() && node->GetChildCount() > 0 && !recursive) { + error_ = kFolderNotEmptyError; + return false; + } + + BookmarkNode* parent = node->GetParent(); + if (!parent) { + error_ = kNoParentError; + return false; + } + int index = parent->IndexOfChild(node); + model->Remove(parent, index); + return true; +} + +bool CreateBookmarkFunction::RunImpl() { + EXTENSION_FUNCTION_VALIDATE(args_->IsType(Value::TYPE_DICTIONARY)); + DictionaryValue* json = static_cast<DictionaryValue*>(args_); + + BookmarkModel* model = profile()->GetBookmarkModel(); + int parentId; + if (!json->HasKey(kParentIdKey)) { // optional, default to "other bookmarks" + parentId = model->other_node()->id(); + } else { + EXTENSION_FUNCTION_VALIDATE(json->GetInteger(kParentIdKey, &parentId)); + } + BookmarkNode* parent = model->GetNodeByID(parentId); + if (!parent) { + error_ = kNoParentError; + return false; + } + if (parent->GetParent() == NULL) { // can't create children of the root + error_ = kNoParentError; + return false; + } + + int index; + if (!json->HasKey(kIndexKey)) { // optional (defaults to end) + index = parent->GetChildCount(); + } else { + EXTENSION_FUNCTION_VALIDATE(json->GetInteger(kIndexKey, &index)); + if (index > parent->GetChildCount() || index < 0) { + error_ = kInvalidIndexError; + return false; + } + } + + std::wstring title; + json->GetString(kTitleKey, &title); // optional + std::string url_string; + json->GetString(kUrlKey, &url_string); // optional + GURL url(url_string); + if (!url.is_empty() && !url.is_valid()) { + error_ = kInvalidUrlError; + return false; + } + + BookmarkNode* node; + if (url_string.length()) + node = model->AddURL(parent, index, title, url); + else + node = model->AddGroup(parent, index, title); + DCHECK(node); + if (!node) { + error_ = kNoNodeError; + return false; + } + + DictionaryValue* ret = ExtensionBookmarks::GetNodeDictionary(node, false); + result_.reset(ret); + + return true; +} + +bool MoveBookmarkFunction::RunImpl() { + EXTENSION_FUNCTION_VALIDATE(args_->IsType(Value::TYPE_DICTIONARY)); + DictionaryValue* json = static_cast<DictionaryValue*>(args_); + + // TODO(erikkay) it would be cool if this could be a list of ids as well + int id = 0; + EXTENSION_FUNCTION_VALIDATE(json->GetInteger(kIdKey, &id)); + + BookmarkModel* model = profile()->GetBookmarkModel(); + BookmarkNode* node = model->GetNodeByID(id); + if (!node) { + error_ = kNoNodeError; + return false; + } + if (node == model->root_node() || + node == model->other_node() || + node == model->GetBookmarkBarNode()) { + error_ = kModifySpecialError; + return false; + } + + BookmarkNode* parent; + if (!json->HasKey(kParentIdKey)) { // optional, defaults to current parent + parent = node->GetParent(); + } else { + int parentId; + EXTENSION_FUNCTION_VALIDATE(json->GetInteger(kParentIdKey, &parentId)); + parent = model->GetNodeByID(parentId); + } + if (!parent) { + error_ = kNoParentError; + // TODO(erikkay) return an error message + return false; + } + if (parent == model->root_node()) { + error_ = kModifySpecialError; + return false; + } + + int index; + if (json->HasKey(kIndexKey)) { // optional (defaults to end) + EXTENSION_FUNCTION_VALIDATE(json->GetInteger(kIndexKey, &index)); + if (index > parent->GetChildCount() || index < 0) { + error_ = kInvalidIndexError; + return false; + } + } else { + index = parent->GetChildCount(); + } + + model->Move(node, parent, index); + return true; +} + +bool SetBookmarkTitleFunction::RunImpl() { + EXTENSION_FUNCTION_VALIDATE(args_->IsType(Value::TYPE_DICTIONARY)); + DictionaryValue* json = static_cast<DictionaryValue*>(args_); + + std::wstring title; + json->GetString(kTitleKey, &title); // optional (empty is clear) + + BookmarkModel* model = profile()->GetBookmarkModel(); + int id = 0; + EXTENSION_FUNCTION_VALIDATE(json->GetInteger(kIdKey, &id)); + BookmarkNode* node = model->GetNodeByID(id); + if (!node) { + error_ = kNoNodeError; + return false; + } + if (node == model->root_node() || + node == model->other_node() || + node == model->GetBookmarkBarNode()) { + error_ = kModifySpecialError; + return false; + } + model->SetTitle(node, title); + return true; +} + diff --git a/chrome/browser/extensions/extension_bookmarks_module.h b/chrome/browser/extensions/extension_bookmarks_module.h new file mode 100644 index 0000000..b7b38d8 --- /dev/null +++ b/chrome/browser/extensions/extension_bookmarks_module.h @@ -0,0 +1,35 @@ +// Copyright (c) 2009 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_EXTENSION_BOOKMARKS_MODULE_H__ +#define CHROME_BROWSER_EXTENSIONS_EXTENSION_BOOKMARKS_MODULE_H__ + +#include "chrome/browser/extensions/extension_function.h" + +class GetBookmarksFunction : public SyncExtensionFunction { + virtual bool RunImpl(); +}; + +class SearchBookmarksFunction : public SyncExtensionFunction { + virtual bool RunImpl(); +}; + +class RemoveBookmarkFunction : public SyncExtensionFunction { + virtual bool RunImpl(); +}; + +class CreateBookmarkFunction : public SyncExtensionFunction { + virtual bool RunImpl(); +}; + +class MoveBookmarkFunction : public SyncExtensionFunction { + virtual bool RunImpl(); +}; + +class SetBookmarkTitleFunction : public SyncExtensionFunction { + virtual bool RunImpl(); +}; + +#endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_BOOKMARKS_MODULE_H__ + diff --git a/chrome/browser/extensions/extension_function.cc b/chrome/browser/extensions/extension_function.cc index 000c1d5..8de21df 100644 --- a/chrome/browser/extensions/extension_function.cc +++ b/chrome/browser/extensions/extension_function.cc @@ -4,15 +4,24 @@ #include "chrome/browser/extensions/extension_function.h" +#include "base/logging.h" #include "chrome/browser/extensions/extension_function_dispatcher.h" void ExtensionFunction::SendResponse(bool success) { - if (success) { + if (bad_message_) { + dispatcher_->HandleBadMessage(this); + } else if (success) { if (has_callback()) { dispatcher_->SendResponse(this); } } else { // TODO(aa): In case of failure, send the error message to an error // callback. + LOG(WARNING) << error_; } } + +Profile* ExtensionFunction::profile() { + return dispatcher_->profile(); +} + diff --git a/chrome/browser/extensions/extension_function.h b/chrome/browser/extensions/extension_function.h index 421df81..ed8fe9e 100644 --- a/chrome/browser/extensions/extension_function.h +++ b/chrome/browser/extensions/extension_function.h @@ -11,12 +11,21 @@ #include "base/scoped_ptr.h" class ExtensionFunctionDispatcher; +class Profile; + +#define EXTENSION_FUNCTION_VALIDATE(test) do { \ + if (!test) { \ + bad_message_ = true; \ + return false; \ + } \ + } while (0) // Base class for an extension function. // TODO(aa): This will have to become reference counted when we introduce APIs // that live beyond a single stack frame. class ExtensionFunction { public: + ExtensionFunction() : bad_message_(false) {} virtual ~ExtensionFunction() {} void set_dispatcher(ExtensionFunctionDispatcher* dispatcher) { @@ -43,6 +52,8 @@ class ExtensionFunction { protected: void SendResponse(bool success); + Profile* profile(); + // The arguments to the API. Only non-null if argument were specfied. Value* args_; @@ -54,9 +65,15 @@ class ExtensionFunction { // class before Run() returns. std::string error_; + // Any class that gets a malformed message should set this to true before + // returning. The calling renderer process will be killed. + bool bad_message_; + private: ExtensionFunctionDispatcher* dispatcher_; int callback_id_; + + DISALLOW_COPY_AND_ASSIGN(ExtensionFunction); }; @@ -69,6 +86,8 @@ class ExtensionFunction { // need to interact with things on the browser UI thread. class SyncExtensionFunction : public ExtensionFunction { public: + SyncExtensionFunction() {} + // Derived classes should implement this method to do their work and return // success/failure. virtual bool RunImpl() = 0; @@ -76,6 +95,9 @@ class SyncExtensionFunction : public ExtensionFunction { virtual void Run() { SendResponse(RunImpl()); } + + private: + DISALLOW_COPY_AND_ASSIGN(SyncExtensionFunction); }; #endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_FUNCTION_H_ diff --git a/chrome/browser/extensions/extension_function_dispatcher.cc b/chrome/browser/extensions/extension_function_dispatcher.cc index e2b05f0..195b99e 100644 --- a/chrome/browser/extensions/extension_function_dispatcher.cc +++ b/chrome/browser/extensions/extension_function_dispatcher.cc @@ -1,120 +1,154 @@ -// Copyright (c) 2009 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/extensions/extension_function_dispatcher.h" - -#include "base/json_reader.h" -#include "base/json_writer.h" -#include "base/singleton.h" -#include "base/values.h" -#include "chrome/browser/extensions/extension_function.h" -#include "chrome/browser/extensions/extension_tabs_module.h" -#include "chrome/browser/renderer_host/render_view_host.h" - -// FactoryRegistry ------------------------------------------------------------- - -namespace { - -// A pointer to a function that create an instance of an ExtensionFunction. -typedef ExtensionFunction* (*ExtensionFunctionFactory)(); - -// Contains a list of all known extension functions and allows clients to create -// instances of them. -class FactoryRegistry { - public: - static FactoryRegistry* instance(); - FactoryRegistry(); - void GetAllNames(std::vector<std::string>* names); - ExtensionFunction* NewFunction(const std::string& name); - - private: - typedef std::map<std::string, ExtensionFunctionFactory> FactoryMap; - FactoryMap factories_; -}; - -// Template for defining ExtensionFunctionFactory. -template<class T> -ExtensionFunction* NewExtensionFunction() { - return new T(); -} - -FactoryRegistry* FactoryRegistry::instance() { - return Singleton<FactoryRegistry>::get(); -} - -FactoryRegistry::FactoryRegistry() { - // Register all functions here. - factories_["GetWindows"] = &NewExtensionFunction<GetWindowsFunction>; - factories_["GetTabsForWindow"] = - &NewExtensionFunction<GetTabsForWindowFunction>; - factories_["GetTab"] = &NewExtensionFunction<GetTabFunction>; - factories_["CreateTab"] = &NewExtensionFunction<CreateTabFunction>; - factories_["UpdateTab"] = &NewExtensionFunction<UpdateTabFunction>; - factories_["MoveTab"] = &NewExtensionFunction<MoveTabFunction>; - factories_["RemoveTab"] = &NewExtensionFunction<RemoveTabFunction>; -} - -void FactoryRegistry::GetAllNames( - std::vector<std::string>* names) { - for (FactoryMap::iterator iter = factories_.begin(); iter != factories_.end(); - ++iter) { - names->push_back(iter->first); - } -} - -ExtensionFunction* FactoryRegistry::NewFunction(const std::string& name) { - FactoryMap::iterator iter = factories_.find(name); - DCHECK(iter != factories_.end()); - return iter->second(); -} - -}; - - -// ExtensionFunctionDispatcher ------------------------------------------------- - -void ExtensionFunctionDispatcher::GetAllFunctionNames( - std::vector<std::string>* names) { - FactoryRegistry::instance()->GetAllNames(names); -} - -ExtensionFunctionDispatcher::ExtensionFunctionDispatcher( - RenderViewHost* render_view_host) - : render_view_host_(render_view_host) {} - -void ExtensionFunctionDispatcher::HandleRequest(const std::string& name, - const std::string& args, - int callback_id) { - scoped_ptr<Value> value; - if (!args.empty()) { - JSONReader reader; - value.reset(reader.JsonToValue(args, false, false)); - - // Since we do the serialization in the v8 extension, we should always get - // valid JSON. - if (!value.get()) { - DCHECK(false); - return; - } - } - - // TODO(aa): This will get a bit more complicated when we support functions - // that live longer than the stack frame. - scoped_ptr<ExtensionFunction> function( - FactoryRegistry::instance()->NewFunction(name)); - function->set_dispatcher(this); - function->set_args(value.get()); - function->set_callback_id(callback_id); - function->Run(); -} - -void ExtensionFunctionDispatcher::SendResponse(ExtensionFunction* function) { - std::string json; - - // Some functions might not need to return any results. - if (function->result()) - JSONWriter::Write(function->result(), false, &json); - - render_view_host_->SendExtensionResponse(function->callback_id(), json); -} +// Copyright (c) 2009 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/extensions/extension_function_dispatcher.h"
+
+#include "base/json_reader.h"
+#include "base/json_writer.h"
+#include "base/process_util.h"
+#include "base/singleton.h"
+#include "base/values.h"
+#include "chrome/browser/extensions/extension_bookmarks_module.h"
+#include "chrome/browser/extensions/extension_function.h"
+#include "chrome/browser/extensions/extension_tabs_module.h"
+#include "chrome/browser/renderer_host/render_process_host.h"
+#include "chrome/browser/renderer_host/render_view_host.h"
+#include "chrome/common/result_codes.h"
+
+// FactoryRegistry -------------------------------------------------------------
+
+namespace {
+
+// A pointer to a function that create an instance of an ExtensionFunction.
+typedef ExtensionFunction* (*ExtensionFunctionFactory)();
+
+// Contains a list of all known extension functions and allows clients to create
+// instances of them.
+class FactoryRegistry {
+ public:
+ static FactoryRegistry* instance();
+ FactoryRegistry();
+ void GetAllNames(std::vector<std::string>* names);
+ ExtensionFunction* NewFunction(const std::string& name);
+
+ private:
+ typedef std::map<std::string, ExtensionFunctionFactory> FactoryMap;
+ FactoryMap factories_;
+};
+
+// Template for defining ExtensionFunctionFactory.
+template<class T>
+ExtensionFunction* NewExtensionFunction() {
+ return new T();
+}
+
+FactoryRegistry* FactoryRegistry::instance() {
+ return Singleton<FactoryRegistry>::get();
+}
+
+FactoryRegistry::FactoryRegistry() {
+ // Register all functions here.
+
+ // Tabs
+ factories_["GetWindows"] = &NewExtensionFunction<GetWindowsFunction>;
+ factories_["GetTabsForWindow"] =
+ &NewExtensionFunction<GetTabsForWindowFunction>;
+ factories_["GetTab"] = &NewExtensionFunction<GetTabFunction>;
+ factories_["CreateTab"] = &NewExtensionFunction<CreateTabFunction>;
+ factories_["UpdateTab"] = &NewExtensionFunction<UpdateTabFunction>;
+ factories_["MoveTab"] = &NewExtensionFunction<MoveTabFunction>;
+ factories_["RemoveTab"] = &NewExtensionFunction<RemoveTabFunction>;
+
+ // Bookmarks
+ factories_["GetBookmarks"] = &NewExtensionFunction<GetBookmarksFunction>;
+ factories_["SearchBookmarks"] =
+ &NewExtensionFunction<SearchBookmarksFunction>;
+ factories_["RemoveBookmark"] = &NewExtensionFunction<RemoveBookmarkFunction>;
+ factories_["CreateBookmark"] = &NewExtensionFunction<CreateBookmarkFunction>;
+ factories_["MoveBookmark"] = &NewExtensionFunction<MoveBookmarkFunction>;
+ factories_["SetBookmarkTitle"] =
+ &NewExtensionFunction<SetBookmarkTitleFunction>;
+}
+
+void FactoryRegistry::GetAllNames(
+ std::vector<std::string>* names) {
+ for (FactoryMap::iterator iter = factories_.begin(); iter != factories_.end();
+ ++iter) {
+ names->push_back(iter->first);
+ }
+}
+
+ExtensionFunction* FactoryRegistry::NewFunction(const std::string& name) {
+ FactoryMap::iterator iter = factories_.find(name);
+ DCHECK(iter != factories_.end());
+ return iter->second();
+}
+
+};
+
+
+// ExtensionFunctionDispatcher -------------------------------------------------
+
+void ExtensionFunctionDispatcher::GetAllFunctionNames(
+ std::vector<std::string>* names) {
+ FactoryRegistry::instance()->GetAllNames(names);
+}
+
+ExtensionFunctionDispatcher::ExtensionFunctionDispatcher(
+ RenderViewHost* render_view_host)
+ : render_view_host_(render_view_host) {}
+
+void ExtensionFunctionDispatcher::HandleRequest(const std::string& name,
+ const std::string& args,
+ int callback_id) {
+ scoped_ptr<Value> value;
+ if (!args.empty()) {
+ JSONReader reader;
+ value.reset(reader.JsonToValue(args, false, false));
+
+ // Since we do the serialization in the v8 extension, we should always get
+ // valid JSON.
+ if (!value.get()) {
+ DCHECK(false);
+ return;
+ }
+ }
+
+ // TODO(aa): This will get a bit more complicated when we support functions
+ // that live longer than the stack frame.
+ scoped_ptr<ExtensionFunction> function(
+ FactoryRegistry::instance()->NewFunction(name));
+ function->set_dispatcher(this);
+ function->set_args(value.get());
+ function->set_callback_id(callback_id);
+ function->Run();
+}
+
+void ExtensionFunctionDispatcher::SendResponse(ExtensionFunction* function) {
+ std::string json;
+
+ // Some functions might not need to return any results.
+ if (function->result())
+ JSONWriter::Write(function->result(), false, &json);
+
+ render_view_host_->SendExtensionResponse(function->callback_id(), json);
+}
+
+void ExtensionFunctionDispatcher::HandleBadMessage(ExtensionFunction* api) {
+ LOG(ERROR) << "bad extension message " << // TODO(erikkay) name?
+ " : terminating renderer.";
+ if (RenderProcessHost::run_renderer_in_process()) {
+ // In single process mode it is better if we don't suicide but just crash.
+ CHECK(false);
+ } else {
+ NOTREACHED();
+ base::KillProcess(render_view_host_->process()->process().handle(),
+ ResultCodes::KILLED_BAD_MESSAGE, false);
+ }
+}
+
+Profile* ExtensionFunctionDispatcher::profile() {
+ return render_view_host_->process()->profile();
+}
+
diff --git a/chrome/browser/extensions/extension_function_dispatcher.h b/chrome/browser/extensions/extension_function_dispatcher.h index 2b9c49e..13057d8 100644 --- a/chrome/browser/extensions/extension_function_dispatcher.h +++ b/chrome/browser/extensions/extension_function_dispatcher.h @@ -11,6 +11,7 @@ #include "base/values.h" class ExtensionFunction; +class Profile; class RenderViewHost; // ExtensionFunctionDispatcher receives requests to execute functions from @@ -30,6 +31,13 @@ class ExtensionFunctionDispatcher { // Send a response to a function. void SendResponse(ExtensionFunction* api); + // Handle a malformed message. Possibly the result of an attack, so kill + // the renderer. + void HandleBadMessage(ExtensionFunction* api); + + // The profile that this dispatcher is associated with. + Profile* profile(); + private: RenderViewHost* render_view_host_; }; |