Update extension functions to always pass a list of arguments, even when one argument was passed.

BUG=36301
TEST=Updated tests and ran all the existing tests.

Review URL: http://codereview.chromium.org/2137012

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@47972 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/chrome/browser/dom_ui/dom_ui.cc b/chrome/browser/dom_ui/dom_ui.cc
index 976c1dc..4cb12027c 100644
--- a/chrome/browser/dom_ui/dom_ui.cc
+++ b/chrome/browser/dom_ui/dom_ui.cc
@@ -37,7 +37,7 @@
 // DOMUI, public: -------------------------------------------------------------
 
 void DOMUI::ProcessDOMUIMessage(const std::string& message,
-                                const Value* content,
+                                const ListValue* content,
                                 const GURL& source_url,
                                 int request_id,
                                 bool has_callback) {
diff --git a/chrome/browser/dom_ui/dom_ui.h b/chrome/browser/dom_ui/dom_ui.h
index 7fd2e55d..838cbcf4 100644
--- a/chrome/browser/dom_ui/dom_ui.h
+++ b/chrome/browser/dom_ui/dom_ui.h
@@ -16,6 +16,7 @@
 class DictionaryValue;
 class DOMMessageHandler;
 class GURL;
+class ListValue;
 class Profile;
 class RenderViewHost;
 class Value;
@@ -41,7 +42,7 @@
 
   // Called from TabContents.
   virtual void ProcessDOMUIMessage(const std::string& message,
-                                   const Value* content,
+                                   const ListValue* content,
                                    const GURL& source_url,
                                    int request_id,
                                    bool has_callback);
diff --git a/chrome/browser/extensions/execute_code_in_tab_function.cc b/chrome/browser/extensions/execute_code_in_tab_function.cc
index fca1a17..c391db87 100644
--- a/chrome/browser/extensions/execute_code_in_tab_function.cc
+++ b/chrome/browser/extensions/execute_code_in_tab_function.cc
@@ -18,11 +18,8 @@
 namespace keys = extension_tabs_module_constants;
 
 bool ExecuteCodeInTabFunction::RunImpl() {
-  EXTENSION_FUNCTION_VALIDATE(args_->IsType(Value::TYPE_LIST));
-  const ListValue* args = args_as_list();
-
   DictionaryValue* script_info;
-  EXTENSION_FUNCTION_VALIDATE(args->GetDictionary(1, &script_info));
+  EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(1, &script_info));
   size_t number_of_value = script_info->size();
   if (number_of_value == 0) {
     error_ = keys::kNoCodeOrFileToExecuteError;
@@ -46,7 +43,7 @@
   // If |tab_id| is specified, look for it. Otherwise default to selected tab
   // in the current window.
   Value* tab_value = NULL;
-  EXTENSION_FUNCTION_VALIDATE(args->Get(0, &tab_value));
+  EXTENSION_FUNCTION_VALIDATE(args_->Get(0, &tab_value));
   if (tab_value->IsType(Value::TYPE_NULL)) {
     browser = GetCurrentBrowser();
     if (!browser) {
diff --git a/chrome/browser/extensions/extension_accessibility_api.cc b/chrome/browser/extensions/extension_accessibility_api.cc
index aebdda2..8b4630e6 100644
--- a/chrome/browser/extensions/extension_accessibility_api.cc
+++ b/chrome/browser/extensions/extension_accessibility_api.cc
@@ -182,7 +182,7 @@
 
 bool SetAccessibilityEnabledFunction::RunImpl() {
   bool enabled;
-  EXTENSION_FUNCTION_VALIDATE(args_->GetAsBoolean(&enabled));
+  EXTENSION_FUNCTION_VALIDATE(args_->GetBoolean(0, &enabled));
   ExtensionAccessibilityEventRouter::GetInstance()
       ->SetAccessibilityEnabled(enabled);
   return true;
diff --git a/chrome/browser/extensions/extension_bookmark_manager_api.cc b/chrome/browser/extensions/extension_bookmark_manager_api.cc
index 66bc9fa4..9b796d2 100644
--- a/chrome/browser/extensions/extension_bookmark_manager_api.cc
+++ b/chrome/browser/extensions/extension_bookmark_manager_api.cc
@@ -30,9 +30,9 @@
 // Returns a single bookmark node from the argument ID.
 // This returns NULL in case of failure.
 const BookmarkNode* GetNodeFromArguments(BookmarkModel* model,
-    const Value* args) {
+    const ListValue* args) {
   std::string id_string;
-  if (!args->GetAsString(&id_string))
+  if (!args->GetString(0, &id_string))
     return NULL;
   int64 id;
   if (!StringToInt64(id_string, &id))
@@ -42,8 +42,13 @@
 
 // Gets a vector of bookmark nodes from the argument list of IDs.
 // This returns false in the case of failure.
-bool GetNodesFromArguments(BookmarkModel* model, const ListValue* ids,
+bool GetNodesFromArguments(BookmarkModel* model, const ListValue* args,
     std::vector<const BookmarkNode*>* nodes) {
+
+  ListValue* ids;
+  if (!args->GetList(0, &ids))
+    return false;
+
   size_t count = ids->GetSize();
   if (count == 0)
     return false;
@@ -208,7 +213,7 @@
 bool ClipboardBookmarkManagerFunction::CopyOrCut(bool cut) {
   BookmarkModel* model = profile()->GetBookmarkModel();
   std::vector<const BookmarkNode*> nodes;
-  EXTENSION_FUNCTION_VALIDATE(GetNodesFromArguments(model, args_as_list(),
+  EXTENSION_FUNCTION_VALIDATE(GetNodesFromArguments(model, args_.get(),
                                                     &nodes));
   bookmark_utils::CopyToClipboard(model, nodes, cut);
   return true;
@@ -335,7 +340,7 @@
   BookmarkModel* model = profile()->GetBookmarkModel();
   std::vector<const BookmarkNode*> nodes;
   EXTENSION_FUNCTION_VALIDATE(
-      GetNodesFromArguments(model, args_as_list(), &nodes));
+      GetNodesFromArguments(model, args_.get(), &nodes));
 
   if (dispatcher()->render_view_host()->delegate()->GetRenderViewType() ==
       ViewType::TAB_CONTENTS) {
@@ -354,16 +359,10 @@
 bool DropBookmarkManagerFunction::RunImpl() {
   BookmarkModel* model = profile()->GetBookmarkModel();
 
-  // TODO(arv): The arguments change between a list and a value depending on the
-  // parameters. See http://crbug.com/36301
   int64 id;
   std::string id_string;
-  if (args_->IsType(Value::TYPE_STRING)) {
-    EXTENSION_FUNCTION_VALIDATE(args_->GetAsString(&id_string));
-  } else {
-    EXTENSION_FUNCTION_VALIDATE(args_->IsType(Value::TYPE_LIST));
-    EXTENSION_FUNCTION_VALIDATE(args_as_list()->GetString(0, &id_string));
-  }
+  EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &id_string));
+
   if (!StringToInt64(id_string, &id)) {
     error_ = keys::kInvalidIdError;
     return false;
@@ -376,8 +375,8 @@
   }
 
   int drop_index;
-  if (args_as_list()->GetSize() == 2)
-    EXTENSION_FUNCTION_VALIDATE(args_as_list()->GetInteger(1, &drop_index));
+  if (args_->GetSize() == 2)
+    EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(1, &drop_index));
   else
     drop_index = drop_parent->GetChildCount();
 
@@ -412,9 +411,9 @@
   const BookmarkNode* node;
   int64 id;
   std::string id_string;
-  EXTENSION_FUNCTION_VALIDATE(args_as_list()->GetString(0, &id_string));
+  EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &id_string));
   bool folders_only;
-  EXTENSION_FUNCTION_VALIDATE(args_as_list()->GetBoolean(1, &folders_only));
+  EXTENSION_FUNCTION_VALIDATE(args_->GetBoolean(1, &folders_only));
   if (id_string == "") {
     node = model->root_node();
   } else {
diff --git a/chrome/browser/extensions/extension_bookmarks_module.cc b/chrome/browser/extensions/extension_bookmarks_module.cc
index 8361b82..a07179e 100644
--- a/chrome/browser/extensions/extension_bookmarks_module.cc
+++ b/chrome/browser/extensions/extension_bookmarks_module.cc
@@ -228,8 +228,10 @@
 bool GetBookmarksFunction::RunImpl() {
   BookmarkModel* model = profile()->GetBookmarkModel();
   scoped_ptr<ListValue> json(new ListValue());
-  if (args_->IsType(Value::TYPE_LIST)) {
-    const ListValue* ids = args_as_list();
+  Value* arg0;
+  EXTENSION_FUNCTION_VALIDATE(args_->Get(0, &arg0));
+  if (arg0->IsType(Value::TYPE_LIST)) {
+    const ListValue* ids = static_cast<const ListValue*>(arg0);
     size_t count = ids->GetSize();
     EXTENSION_FUNCTION_VALIDATE(count > 0);
     for (size_t i = 0; i < count; ++i) {
@@ -249,7 +251,7 @@
   } else {
     int64 id;
     std::string id_string;
-    EXTENSION_FUNCTION_VALIDATE(args_->GetAsString(&id_string));
+    EXTENSION_FUNCTION_VALIDATE(arg0->GetAsString(&id_string));
     if (!GetBookmarkIdAsInt64(id_string, &id))
       return false;
     const BookmarkNode* node = model->GetNodeByID(id);
@@ -268,7 +270,7 @@
   BookmarkModel* model = profile()->GetBookmarkModel();
   int64 id;
   std::string id_string;
-  EXTENSION_FUNCTION_VALIDATE(args_->GetAsString(&id_string));
+  EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &id_string));
   if (!GetBookmarkIdAsInt64(id_string, &id))
     return false;
   scoped_ptr<ListValue> json(new ListValue());
@@ -288,9 +290,8 @@
 }
 
 bool GetBookmarkRecentFunction::RunImpl() {
-  EXTENSION_FUNCTION_VALIDATE(args_->IsType(Value::TYPE_INTEGER));
   int number_of_items;
-  EXTENSION_FUNCTION_VALIDATE(args_->GetAsInteger(&number_of_items));
+  EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &number_of_items));
   if (number_of_items < 1)
     return false;
 
@@ -317,10 +318,8 @@
 }
 
 bool SearchBookmarksFunction::RunImpl() {
-  EXTENSION_FUNCTION_VALIDATE(args_->IsType(Value::TYPE_STRING));
-
   std::wstring query;
-  EXTENSION_FUNCTION_VALIDATE(args_->GetAsString(&query));
+  EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &query));
 
   BookmarkModel* model = profile()->GetBookmarkModel();
   ListValue* json = new ListValue();
@@ -340,35 +339,17 @@
 }
 
 // static
-bool RemoveBookmarkFunction::ExtractIds(const Value* args,
-    std::list<int64>* ids, bool* invalid_id) {
+bool RemoveBookmarkFunction::ExtractIds(const ListValue* args,
+                                        std::list<int64>* ids,
+                                        bool* invalid_id) {
   std::string id_string;
-  if (args->IsType(Value::TYPE_STRING) &&
-      args->GetAsString(&id_string)) {
-    int64 id;
-    if (StringToInt64(id_string, &id))
-      ids->push_back(id);
-    else
-      *invalid_id = true;
-  } else {
-    if (!args->IsType(Value::TYPE_LIST))
-      return false;
-    const ListValue* ids_list = static_cast<const ListValue*>(args);
-    size_t count = ids_list->GetSize();
-    if (count <= 0)
-      return false;
-    for (size_t i = 0; i < count; ++i) {
-      if (!ids_list->GetString(i, &id_string))
-        return false;
-      int64 id;
-      if (StringToInt64(id_string, &id)) {
-        ids->push_back(id);
-      } else {
-        *invalid_id = true;
-        break;
-      }
-    }
-  }
+  if (!args->GetString(0, &id_string))
+    return false;
+  int64 id;
+  if (StringToInt64(id_string, &id))
+    ids->push_back(id);
+  else
+    *invalid_id = true;
   return true;
 }
 
@@ -395,8 +376,9 @@
 }
 
 bool CreateBookmarkFunction::RunImpl() {
-  EXTENSION_FUNCTION_VALIDATE(args_->IsType(Value::TYPE_DICTIONARY));
-  const DictionaryValue* json = args_as_dictionary();
+  DictionaryValue* json;
+  EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &json));
+  EXTENSION_FUNCTION_VALIDATE(json != NULL);
 
   BookmarkModel* model = profile()->GetBookmarkModel();
   int64 parentId;
@@ -460,7 +442,7 @@
 }
 
 // static
-bool MoveBookmarkFunction::ExtractIds(const Value* args,
+bool MoveBookmarkFunction::ExtractIds(const ListValue* args,
                                       std::list<int64>* ids,
                                       bool* invalid_id) {
   // For now, Move accepts ID parameters in the same way as an Update.
@@ -476,10 +458,9 @@
     return false;
   }
   EXTENSION_FUNCTION_VALIDATE(ids.size() == 1);
-  const ListValue* args = args_as_list();
 
   DictionaryValue* destination;
-  EXTENSION_FUNCTION_VALIDATE(args->GetDictionary(1, &destination));
+  EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(1, &destination));
 
   BookmarkModel* model = profile()->GetBookmarkModel();
   const BookmarkNode* node = model->GetNodeByID(ids.front());
@@ -540,21 +521,11 @@
 }
 
 // static
-bool UpdateBookmarkFunction::ExtractIds(const Value* args,
+bool UpdateBookmarkFunction::ExtractIds(const ListValue* args,
                                         std::list<int64>* ids,
                                         bool* invalid_id) {
-  std::string id_string;
-  if (!args->IsType(Value::TYPE_LIST))
-    return false;
-  const ListValue* args_list = static_cast<const ListValue*>(args);
-  if (!args_list->GetString(0, &id_string))
-    return false;
-  int64 id;
-  if (StringToInt64(id_string, &id))
-    ids->push_back(id);
-  else
-    *invalid_id = true;
-  return true;
+  // For now, Update accepts ID parameters in the same way as an Remove.
+  return RemoveBookmarkFunction::ExtractIds(args, ids, invalid_id);
 }
 
 bool UpdateBookmarkFunction::RunImpl() {
@@ -567,9 +538,8 @@
   }
   EXTENSION_FUNCTION_VALIDATE(ids.size() == 1);
 
-  const ListValue* args = args_as_list();
   DictionaryValue* updates;
-  EXTENSION_FUNCTION_VALIDATE(args->GetDictionary(1, &updates));
+  EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(1, &updates));
 
   std::wstring title;
   std::string url_string;
@@ -636,12 +606,12 @@
   explicit CreateBookmarkBucketMapper(Profile* profile) : profile_(profile) {}
   // TODO(tim): This should share code with CreateBookmarkFunction::RunImpl,
   // but I can't figure out a good way to do that with all the macros.
-  virtual void GetBucketsForArgs(const Value* args, BucketList* buckets) {
-    if (!args->IsType(Value::TYPE_DICTIONARY))
+  virtual void GetBucketsForArgs(const ListValue* args, BucketList* buckets) {
+    DictionaryValue* json;
+    if (!args->GetDictionary(0, &json))
       return;
 
     std::string parent_id;
-    const DictionaryValue* json = static_cast<const DictionaryValue*>(args);
     if (json->HasKey(keys::kParentIdKey)) {
       if (!json->GetString(keys::kParentIdKey, &parent_id))
         return;
@@ -671,7 +641,7 @@
 class RemoveBookmarksBucketMapper : public BookmarkBucketMapper<std::string> {
  public:
   explicit RemoveBookmarksBucketMapper(Profile* profile) : profile_(profile) {}
-  virtual void GetBucketsForArgs(const Value* args, BucketList* buckets) {
+  virtual void GetBucketsForArgs(const ListValue* args, BucketList* buckets) {
     typedef std::list<int64> IdList;
     IdList ids;
     bool invalid_id = false;
@@ -705,7 +675,7 @@
 class BookmarkIdMapper : public BookmarkBucketMapper<int64> {
  public:
   typedef std::list<int64> IdList;
-  virtual void GetBucketsForArgs(const Value* args, BucketList* buckets) {
+  virtual void GetBucketsForArgs(const ListValue* args, BucketList* buckets) {
     IdList ids;
     bool invalid_id = false;
     if (!FunctionType::ExtractIds(args, &ids, &invalid_id) || invalid_id)
diff --git a/chrome/browser/extensions/extension_bookmarks_module.h b/chrome/browser/extensions/extension_bookmarks_module.h
index cb25755..1a26b021 100644
--- a/chrome/browser/extensions/extension_bookmarks_module.h
+++ b/chrome/browser/extensions/extension_bookmarks_module.h
@@ -124,7 +124,7 @@
  public:
   // Returns true on successful parse and sets invalid_id to true if conversion
   // from id string to int64 failed.
-  static bool ExtractIds(const Value* args, std::list<int64>* ids,
+  static bool ExtractIds(const ListValue* args, std::list<int64>* ids,
                          bool* invalid_id);
   virtual bool RunImpl();
   virtual void GetQuotaLimitHeuristics(
@@ -148,7 +148,7 @@
 
 class MoveBookmarkFunction : public BookmarksFunction {
  public:
-  static bool ExtractIds(const Value* args, std::list<int64>* ids,
+  static bool ExtractIds(const ListValue* args, std::list<int64>* ids,
                          bool* invalid_id);
   virtual void GetQuotaLimitHeuristics(
       std::list<QuotaLimitHeuristic*>* heuristics) const;
@@ -159,7 +159,7 @@
 
 class UpdateBookmarkFunction : public BookmarksFunction {
  public:
-  static bool ExtractIds(const Value* args, std::list<int64>* ids,
+  static bool ExtractIds(const ListValue* args, std::list<int64>* ids,
                          bool* invalid_id);
   virtual void GetQuotaLimitHeuristics(
       std::list<QuotaLimitHeuristic*>* heuristics) const;
diff --git a/chrome/browser/extensions/extension_browser_actions_api.cc b/chrome/browser/extensions/extension_browser_actions_api.cc
index c1ffe8ecf..dfcf2ad 100644
--- a/chrome/browser/extensions/extension_browser_actions_api.cc
+++ b/chrome/browser/extensions/extension_browser_actions_api.cc
@@ -19,8 +19,8 @@
 }
 
 bool BrowserActionFunction::RunImpl() {
-  EXTENSION_FUNCTION_VALIDATE(args_->IsType(Value::TYPE_DICTIONARY));
-  details_ = args_as_dictionary();
+  EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &details_));
+  EXTENSION_FUNCTION_VALIDATE(details_ != NULL);
 
   if (details_->HasKey(L"tabId"))
     EXTENSION_FUNCTION_VALIDATE(details_->GetInteger(L"tabId", &tab_id_));
diff --git a/chrome/browser/extensions/extension_browser_actions_api.h b/chrome/browser/extensions/extension_browser_actions_api.h
index 742eecd..c958cb3 100644
--- a/chrome/browser/extensions/extension_browser_actions_api.h
+++ b/chrome/browser/extensions/extension_browser_actions_api.h
@@ -20,7 +20,7 @@
 
   // All the browser action APIs take a single argument called details that is
   // a dictionary.
-  const DictionaryValue* details_;
+  DictionaryValue* details_;
 
   // The tab id the browser action function should apply to, if any, or
   // kDefaultTabId if none was specified.
diff --git a/chrome/browser/extensions/extension_clipboard_api.cc b/chrome/browser/extensions/extension_clipboard_api.cc
index dbfe6643..22a6253 100644
--- a/chrome/browser/extensions/extension_clipboard_api.cc
+++ b/chrome/browser/extensions/extension_clipboard_api.cc
@@ -18,7 +18,7 @@
 
 bool ClipboardFunction::RunImpl() {
   int tab_id;
-  EXTENSION_FUNCTION_VALIDATE(args_->GetAsInteger(&tab_id));
+  EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &tab_id));
 
   TabContents* contents = NULL;
   if (!ExtensionTabUtil::GetTabById(tab_id, profile(), include_incognito(),
diff --git a/chrome/browser/extensions/extension_context_menu_api.cc b/chrome/browser/extensions/extension_context_menu_api.cc
index 08afa51..ab748f0 100644
--- a/chrome/browser/extensions/extension_context_menu_api.cc
+++ b/chrome/browser/extensions/extension_context_menu_api.cc
@@ -135,8 +135,8 @@
 }
 
 bool CreateContextMenuFunction::RunImpl() {
-  EXTENSION_FUNCTION_VALIDATE(args_->IsType(Value::TYPE_DICTIONARY));
-  const DictionaryValue* properties = args_as_dictionary();
+  DictionaryValue* properties;
+  EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &properties));
   EXTENSION_FUNCTION_VALIDATE(properties != NULL);
 
   std::string title;
@@ -201,10 +201,8 @@
 }
 
 bool UpdateContextMenuFunction::RunImpl() {
-  EXTENSION_FUNCTION_VALIDATE(args_->IsType(Value::TYPE_LIST));
-  const ListValue* args = args_as_list();
   int item_id = 0;
-  EXTENSION_FUNCTION_VALIDATE(args->GetInteger(0, &item_id));
+  EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &item_id));
 
   ExtensionsService* service = profile()->GetExtensionsService();
   ExtensionMenuManager* manager = service->menu_manager();
@@ -215,7 +213,7 @@
   }
 
   DictionaryValue *properties = NULL;
-  EXTENSION_FUNCTION_VALIDATE(args->GetDictionary(1, &properties));
+  EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(1, &properties));
   EXTENSION_FUNCTION_VALIDATE(properties != NULL);
 
   ExtensionMenuManager* menu_manager =
@@ -273,9 +271,8 @@
 }
 
 bool RemoveContextMenuFunction::RunImpl() {
-  EXTENSION_FUNCTION_VALIDATE(args_->IsType(Value::TYPE_INTEGER));
   int id = 0;
-  EXTENSION_FUNCTION_VALIDATE(args_->GetAsInteger(&id));
+  EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &id));
   ExtensionsService* service = profile()->GetExtensionsService();
   ExtensionMenuManager* manager = service->menu_manager();
 
diff --git a/chrome/browser/extensions/extension_cookies_api.cc b/chrome/browser/extensions/extension_cookies_api.cc
index c9c2d09a..05415cf 100644
--- a/chrome/browser/extensions/extension_cookies_api.cc
+++ b/chrome/browser/extensions/extension_cookies_api.cc
@@ -62,8 +62,8 @@
 }
 
 bool GetCookieFunction::RunImpl() {
-  EXTENSION_FUNCTION_VALIDATE(args_->IsType(Value::TYPE_DICTIONARY));
-  const DictionaryValue* details = args_as_dictionary();
+  DictionaryValue* details;
+  EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &details));
   DCHECK(details);
 
   // Read/validate input parameters.
@@ -103,8 +103,8 @@
 }
 
 bool GetAllCookiesFunction::RunImpl() {
-  EXTENSION_FUNCTION_VALIDATE(args_->IsType(Value::TYPE_DICTIONARY));
-  const DictionaryValue* details = args_as_dictionary();
+  DictionaryValue* details;
+  EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &details));
 
   // Read/validate input parameters.
   GURL url;
@@ -125,8 +125,8 @@
 }
 
 bool SetCookieFunction::RunImpl() {
-  EXTENSION_FUNCTION_VALIDATE(args_->IsType(Value::TYPE_DICTIONARY));
-  const DictionaryValue* details = args_as_dictionary();
+  DictionaryValue* details;
+  EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &details));
 
   // Read/validate input parameters.
   GURL url;
@@ -195,8 +195,8 @@
 }
 
 bool RemoveCookieFunction::RunImpl() {
-  EXTENSION_FUNCTION_VALIDATE(args_->IsType(Value::TYPE_DICTIONARY));
-  const DictionaryValue* details = args_as_dictionary();
+  DictionaryValue* details;
+  EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &details));
 
   // Read/validate input parameters.
   GURL url;
diff --git a/chrome/browser/extensions/extension_dom_ui.cc b/chrome/browser/extensions/extension_dom_ui.cc
index ddbf605..93cfa69 100644
--- a/chrome/browser/extensions/extension_dom_ui.cc
+++ b/chrome/browser/extensions/extension_dom_ui.cc
@@ -109,7 +109,7 @@
 }
 
 void ExtensionDOMUI::ProcessDOMUIMessage(const std::string& message,
-                                         const Value* content,
+                                         const ListValue* content,
                                          const GURL& source_url,
                                          int request_id,
                                          bool has_callback) {
diff --git a/chrome/browser/extensions/extension_dom_ui.h b/chrome/browser/extensions/extension_dom_ui.h
index 7f60e2f..7e66a4a8 100644
--- a/chrome/browser/extensions/extension_dom_ui.h
+++ b/chrome/browser/extensions/extension_dom_ui.h
@@ -38,7 +38,7 @@
   virtual void RenderViewCreated(RenderViewHost* render_view_host);
   virtual void RenderViewReused(RenderViewHost* render_view_host);
   virtual void ProcessDOMUIMessage(const std::string& message,
-                                   const Value* content,
+                                   const ListValue* content,
                                    const GURL& source_url,
                                    int request_id,
                                    bool has_callback);
diff --git a/chrome/browser/extensions/extension_function.cc b/chrome/browser/extensions/extension_function.cc
index 43b7033b..437867f 100644
--- a/chrome/browser/extensions/extension_function.cc
+++ b/chrome/browser/extensions/extension_function.cc
@@ -16,9 +16,9 @@
   return service->GetExtensionById(extension_id_, false);
 }
 
-void AsyncExtensionFunction::SetArgs(const Value* args) {
+void AsyncExtensionFunction::SetArgs(const ListValue* args) {
   DCHECK(!args_.get());  // Should only be called once.
-  args_.reset(args->DeepCopy());
+  args_.reset(static_cast<ListValue*>(args->DeepCopy()));
 }
 
 const std::string AsyncExtensionFunction::GetResult() {
@@ -40,8 +40,6 @@
 }
 
 bool AsyncExtensionFunction::HasOptionalArgument(size_t index) {
-  DCHECK(args_->IsType(Value::TYPE_LIST));
-  ListValue* args_list = static_cast<ListValue*>(args_.get());
   Value* value;
-  return args_list->Get(index, &value) && !value->IsType(Value::TYPE_NULL);
+  return args_->Get(index, &value) && !value->IsType(Value::TYPE_NULL);
 }
diff --git a/chrome/browser/extensions/extension_function.h b/chrome/browser/extensions/extension_function.h
index c715c28..d0e1d74b 100644
--- a/chrome/browser/extensions/extension_function.h
+++ b/chrome/browser/extensions/extension_function.h
@@ -58,7 +58,7 @@
   std::string extension_id() const { return extension_id_; }
 
   // Specifies the raw arguments to the function, as a JSON value.
-  virtual void SetArgs(const Value* args) = 0;
+  virtual void SetArgs(const ListValue* args) = 0;
 
   // Retrieves the results of the function as a JSON-encoded string (may
   // be empty).
@@ -165,7 +165,7 @@
  public:
   AsyncExtensionFunction() : args_(NULL), bad_message_(false) {}
 
-  virtual void SetArgs(const Value* args);
+  virtual void SetArgs(const ListValue* args);
   virtual const std::string GetResult();
   virtual const std::string GetError() { return error_; }
   virtual void Run() {
@@ -182,19 +182,12 @@
 
   void SendResponse(bool success);
 
-  const ListValue* args_as_list() {
-    return static_cast<ListValue*>(args_.get());
-  }
-  const DictionaryValue* args_as_dictionary() {
-    return static_cast<DictionaryValue*>(args_.get());
-  }
-
   // Return true if the argument to this function at |index| was provided and
   // is non-null.
   bool HasOptionalArgument(size_t index);
 
   // The arguments to the API. Only non-null if argument were specified.
-  scoped_ptr<Value> args_;
+  scoped_ptr<ListValue> args_;
 
   // The result of the API. This should be populated by the derived class before
   // SendResponse() is called.
diff --git a/chrome/browser/extensions/extension_function_dispatcher.cc b/chrome/browser/extensions/extension_function_dispatcher.cc
index a0b846a..40dbae56 100644
--- a/chrome/browser/extensions/extension_function_dispatcher.cc
+++ b/chrome/browser/extensions/extension_function_dispatcher.cc
@@ -378,7 +378,7 @@
 }
 
 void ExtensionFunctionDispatcher::HandleRequest(const std::string& name,
-                                                const Value* args,
+                                                const ListValue* args,
                                                 const GURL& source_url,
                                                 int request_id,
                                                 bool has_callback) {
diff --git a/chrome/browser/extensions/extension_function_dispatcher.h b/chrome/browser/extensions/extension_function_dispatcher.h
index 6ef4d17b..d9b973d4 100644
--- a/chrome/browser/extensions/extension_function_dispatcher.h
+++ b/chrome/browser/extensions/extension_function_dispatcher.h
@@ -18,11 +18,11 @@
 class ExtensionDOMUI;
 class ExtensionFunction;
 class ExtensionHost;
+class ListValue;
 class Profile;
 class RenderViewHost;
 class RenderViewHostDelegate;
 class TabContents;
-class Value;
 
 // A factory function for creating new ExtensionFunction instances.
 typedef ExtensionFunction* (*ExtensionFunctionFactory)();
@@ -95,7 +95,7 @@
   Delegate* delegate() { return delegate_; }
 
   // Handle a request to execute an extension function.
-  void HandleRequest(const std::string& name, const Value* args,
+  void HandleRequest(const std::string& name, const ListValue* args,
                      const GURL& source_url, int request_id, bool has_callback);
 
   // Send a response to a function.
diff --git a/chrome/browser/extensions/extension_history_api.cc b/chrome/browser/extensions/extension_history_api.cc
index 400c163..db4ec492 100644
--- a/chrome/browser/extensions/extension_history_api.cc
+++ b/chrome/browser/extensions/extension_history_api.cc
@@ -206,8 +206,8 @@
 }
 
 bool GetVisitsHistoryFunction::RunAsyncImpl() {
-  EXTENSION_FUNCTION_VALIDATE(args_->IsType(Value::TYPE_DICTIONARY));
-  const DictionaryValue* json = args_as_dictionary();
+  DictionaryValue* json;
+  EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &json));
 
   Value* value;
   EXTENSION_FUNCTION_VALIDATE(json->Get(keys::kUrlKey, &value));
@@ -243,8 +243,8 @@
 }
 
 bool SearchHistoryFunction::RunAsyncImpl() {
-  EXTENSION_FUNCTION_VALIDATE(args_->IsType(Value::TYPE_DICTIONARY));
-  const DictionaryValue* json = args_as_dictionary();
+  DictionaryValue* json;
+  EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &json));
 
   // Initialize the HistoryQuery
   std::wstring search_text;
@@ -293,8 +293,8 @@
 }
 
 bool AddUrlHistoryFunction::RunImpl() {
-  EXTENSION_FUNCTION_VALIDATE(args_->IsType(Value::TYPE_DICTIONARY));
-  const DictionaryValue* json = args_as_dictionary();
+  DictionaryValue* json;
+  EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &json));
 
   Value* value;
   EXTENSION_FUNCTION_VALIDATE(json->Get(keys::kUrlKey, &value));
@@ -311,8 +311,8 @@
 }
 
 bool DeleteUrlHistoryFunction::RunImpl() {
-  EXTENSION_FUNCTION_VALIDATE(args_->IsType(Value::TYPE_DICTIONARY));
-  const DictionaryValue* json = args_as_dictionary();
+  DictionaryValue* json;
+  EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &json));
 
   Value* value;
   EXTENSION_FUNCTION_VALIDATE(json->Get(keys::kUrlKey, &value));
@@ -329,8 +329,8 @@
 }
 
 bool DeleteRangeHistoryFunction::RunAsyncImpl() {
-  EXTENSION_FUNCTION_VALIDATE(args_->IsType(Value::TYPE_DICTIONARY));
-  const DictionaryValue* json = args_as_dictionary();
+  DictionaryValue* json;
+  EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &json));
 
   Value* value = NULL;
   EXTENSION_FUNCTION_VALIDATE(json->Get(keys::kStartTimeKey, &value));
diff --git a/chrome/browser/extensions/extension_host.cc b/chrome/browser/extensions/extension_host.cc
index 3a6ccc33..1ae5aca 100644
--- a/chrome/browser/extensions/extension_host.cc
+++ b/chrome/browser/extensions/extension_host.cc
@@ -539,7 +539,7 @@
 }
 
 void ExtensionHost::ProcessDOMUIMessage(const std::string& message,
-                                        const Value* content,
+                                        const ListValue* content,
                                         const GURL& source_url,
                                         int request_id,
                                         bool has_callback) {
diff --git a/chrome/browser/extensions/extension_host.h b/chrome/browser/extensions/extension_host.h
index 013cb994..83291647 100644
--- a/chrome/browser/extensions/extension_host.h
+++ b/chrome/browser/extensions/extension_host.h
@@ -130,7 +130,7 @@
 
   virtual WebPreferences GetWebkitPrefs();
   virtual void ProcessDOMUIMessage(const std::string& message,
-                                   const Value* content,
+                                   const ListValue* content,
                                    const GURL& source_url,
                                    int request_id,
                                    bool has_callback);
diff --git a/chrome/browser/extensions/extension_idle_api.cc b/chrome/browser/extensions/extension_idle_api.cc
index da1e2b1..0a6a25f 100644
--- a/chrome/browser/extensions/extension_idle_api.cc
+++ b/chrome/browser/extensions/extension_idle_api.cc
@@ -137,7 +137,7 @@
 
 bool ExtensionIdleQueryStateFunction::RunImpl() {
   int threshold;
-  EXTENSION_FUNCTION_VALIDATE(args_->GetAsInteger(&threshold));
+  EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &threshold));
   threshold = CheckThresholdBounds(threshold);
   IdleState state = ThrottledCalculateIdleState(threshold, profile());
   result_.reset(CreateIdleValue(state));
diff --git a/chrome/browser/extensions/extension_infobar_module.cc b/chrome/browser/extensions/extension_infobar_module.cc
index d8cea95..d8d4950 100644
--- a/chrome/browser/extensions/extension_infobar_module.cc
+++ b/chrome/browser/extensions/extension_infobar_module.cc
@@ -20,8 +20,8 @@
 namespace keys = extension_infobar_module_constants;
 
 bool ShowInfoBarFunction::RunImpl() {
-  EXTENSION_FUNCTION_VALIDATE(args_->IsType(Value::TYPE_DICTIONARY));
-  const DictionaryValue* args = args_as_dictionary();
+  DictionaryValue* args;
+  EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &args));
 
   std::string html_path;
   EXTENSION_FUNCTION_VALIDATE(args->GetString(keys::kHtmlPath, &html_path));
diff --git a/chrome/browser/extensions/extension_metrics_module.cc b/chrome/browser/extensions/extension_metrics_module.cc
index 30db486..380cf0af 100644
--- a/chrome/browser/extensions/extension_metrics_module.cc
+++ b/chrome/browser/extensions/extension_metrics_module.cc
@@ -29,8 +29,7 @@
 
 bool MetricsRecordUserActionFunction::RunImpl() {
   std::string name;
-  EXTENSION_FUNCTION_VALIDATE(args_->IsType(Value::TYPE_STRING));
-  EXTENSION_FUNCTION_VALIDATE(args_->GetAsString(&name));
+  EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &name));
 
   name = BuildMetricName(name, GetExtension());
   UserMetrics::RecordComputedAction(name, profile());
@@ -39,11 +38,8 @@
 
 bool MetricsHistogramHelperFunction::GetNameAndSample(std::string* name,
                                                       int* sample) {
-  EXTENSION_FUNCTION_VALIDATE(args_->IsType(Value::TYPE_LIST));
-  const ListValue* args = args_as_list();
-
-  EXTENSION_FUNCTION_VALIDATE(args->GetString(0, name));
-  EXTENSION_FUNCTION_VALIDATE(args->GetInteger(1, sample));
+  EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, name));
+  EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(1, sample));
   return true;
 }
 
@@ -74,15 +70,12 @@
 }
 
 bool MetricsRecordValueFunction::RunImpl() {
-  EXTENSION_FUNCTION_VALIDATE(args_->IsType(Value::TYPE_LIST));
-  const ListValue* args = args_as_list();
-
   int sample;
-  EXTENSION_FUNCTION_VALIDATE(args->GetInteger(1, &sample));
+  EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(1, &sample));
 
   // Get the histogram parameters from the metric type object.
   DictionaryValue* metric_type;
-  EXTENSION_FUNCTION_VALIDATE(args->GetDictionary(0, &metric_type));
+  EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &metric_type));
 
   std::string name;
   std::string type;
diff --git a/chrome/browser/extensions/extension_page_actions_module.cc b/chrome/browser/extensions/extension_page_actions_module.cc
index a169450..f91c5ef 100644
--- a/chrome/browser/extensions/extension_page_actions_module.cc
+++ b/chrome/browser/extensions/extension_page_actions_module.cc
@@ -32,13 +32,10 @@
 
 // TODO(EXTENSIONS_DEPRECATED): obsolete API.
 bool PageActionFunction::SetPageActionEnabled(bool enable) {
-  EXTENSION_FUNCTION_VALIDATE(args_->IsType(Value::TYPE_LIST));
-  const ListValue* args = args_as_list();
-
   std::string page_action_id;
-  EXTENSION_FUNCTION_VALIDATE(args->GetString(0, &page_action_id));
+  EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &page_action_id));
   DictionaryValue* action;
-  EXTENSION_FUNCTION_VALIDATE(args->GetDictionary(1, &action));
+  EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(1, &action));
 
   int tab_id;
   EXTENSION_FUNCTION_VALIDATE(action->GetInteger(keys::kTabIdKey, &tab_id));
@@ -117,7 +114,7 @@
 
 bool PageActionFunction::SetVisible(bool visible) {
   int tab_id;
-  EXTENSION_FUNCTION_VALIDATE(args_->GetAsInteger(&tab_id));
+  EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &tab_id));
   if (!InitCommon(tab_id))
     return false;
 
@@ -143,8 +140,8 @@
 }
 
 bool PageActionSetIconFunction::RunImpl() {
-  EXTENSION_FUNCTION_VALIDATE(args_->IsType(Value::TYPE_DICTIONARY));
-  const DictionaryValue* args = args_as_dictionary();
+  DictionaryValue* args;
+  EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &args));
 
   int tab_id;
   EXTENSION_FUNCTION_VALIDATE(args->GetInteger(L"tabId", &tab_id));
@@ -179,8 +176,8 @@
 }
 
 bool PageActionSetTitleFunction::RunImpl() {
-  EXTENSION_FUNCTION_VALIDATE(args_->IsType(Value::TYPE_DICTIONARY));
-  const DictionaryValue* args = args_as_dictionary();
+  DictionaryValue* args;
+  EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &args));
 
   int tab_id;
   EXTENSION_FUNCTION_VALIDATE(args->GetInteger(L"tabId", &tab_id));
@@ -196,8 +193,8 @@
 }
 
 bool PageActionSetPopupFunction::RunImpl() {
-  EXTENSION_FUNCTION_VALIDATE(args_->IsType(Value::TYPE_DICTIONARY));
-  const DictionaryValue* args = args_as_dictionary();
+  DictionaryValue* args;
+  EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &args));
 
   int tab_id;
   EXTENSION_FUNCTION_VALIDATE(args->GetInteger(L"tabId", &tab_id));
@@ -221,8 +218,8 @@
 // Not currently exposed to extensions. To re-enable, add mapping in
 // extension_function_dispatcher.
 bool PageActionSetBadgeBackgroundColorFunction::RunImpl() {
-  EXTENSION_FUNCTION_VALIDATE(args_->IsType(Value::TYPE_DICTIONARY));
-  const DictionaryValue* args = args_as_dictionary();
+  DictionaryValue* args;
+  EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &args));
 
   int tab_id;
   EXTENSION_FUNCTION_VALIDATE(args->GetInteger(L"tabId", &tab_id));
@@ -247,8 +244,8 @@
 // Not currently exposed to extensions. To re-enable, add mapping in
 // extension_function_dispatcher.
 bool PageActionSetBadgeTextColorFunction::RunImpl() {
-  EXTENSION_FUNCTION_VALIDATE(args_->IsType(Value::TYPE_DICTIONARY));
-  const DictionaryValue* args = args_as_dictionary();
+  DictionaryValue* args;
+  EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &args));
 
   int tab_id;
   EXTENSION_FUNCTION_VALIDATE(args->GetInteger(L"tabId", &tab_id));
@@ -273,8 +270,8 @@
 // Not currently exposed to extensions. To re-enable, add mapping in
 // extension_function_dispatcher.
 bool PageActionSetBadgeTextFunction::RunImpl() {
-  EXTENSION_FUNCTION_VALIDATE(args_->IsType(Value::TYPE_DICTIONARY));
-  const DictionaryValue* args = args_as_dictionary();
+  DictionaryValue* args;
+  EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &args));
 
   int tab_id;
   EXTENSION_FUNCTION_VALIDATE(args->GetInteger(L"tabId", &tab_id));
diff --git a/chrome/browser/extensions/extension_popup_api.cc b/chrome/browser/extensions/extension_popup_api.cc
index acc47e3..c648744 100644
--- a/chrome/browser/extensions/extension_popup_api.cc
+++ b/chrome/browser/extensions/extension_popup_api.cc
@@ -329,14 +329,11 @@
     return false;
   }
 
-  EXTENSION_FUNCTION_VALIDATE(args_->IsType(Value::TYPE_LIST));
-  const ListValue* args = args_as_list();
-
   std::string url_string;
-  EXTENSION_FUNCTION_VALIDATE(args->GetString(0, &url_string));
+  EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &url_string));
 
   DictionaryValue* show_details = NULL;
-  EXTENSION_FUNCTION_VALIDATE(args->GetDictionary(1, &show_details));
+  EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(1, &show_details));
 
   DictionaryValue* dom_anchor = NULL;
   EXTENSION_FUNCTION_VALIDATE(show_details->GetDictionary(kDomAnchorKey,
diff --git a/chrome/browser/extensions/extension_processes_api.cc b/chrome/browser/extensions/extension_processes_api.cc
index fda8c7f..c4895d3 100644
--- a/chrome/browser/extensions/extension_processes_api.cc
+++ b/chrome/browser/extensions/extension_processes_api.cc
@@ -20,7 +20,7 @@
 
 bool GetProcessForTabFunction::RunImpl() {
   int tab_id;
-  EXTENSION_FUNCTION_VALIDATE(args_->GetAsInteger(&tab_id));
+  EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &tab_id));
 
   TabContents* contents = NULL;
   int tab_index = -1;
diff --git a/chrome/browser/extensions/extension_tabs_module.cc b/chrome/browser/extensions/extension_tabs_module.cc
index 8de4842..047f9aa 100644
--- a/chrome/browser/extensions/extension_tabs_module.cc
+++ b/chrome/browser/extensions/extension_tabs_module.cc
@@ -220,7 +220,7 @@
 
 bool GetWindowFunction::RunImpl() {
   int window_id;
-  EXTENSION_FUNCTION_VALIDATE(args_->GetAsInteger(&window_id));
+  EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &window_id));
 
   Browser* browser = GetBrowserInProfileWithId(profile(), window_id,
                                                include_incognito(), &error_);
@@ -254,9 +254,10 @@
 
 bool GetAllWindowsFunction::RunImpl() {
   bool populate_tabs = false;
-  if (!args_->IsType(Value::TYPE_NULL)) {
-    EXTENSION_FUNCTION_VALIDATE(args_->IsType(Value::TYPE_DICTIONARY));
-    const DictionaryValue* args = args_as_dictionary();
+  if (HasOptionalArgument(0)) {
+    DictionaryValue* args;
+    EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &args));
+
     if (args->HasKey(keys::kPopulateKey)) {
       EXTENSION_FUNCTION_VALIDATE(args->GetBoolean(keys::kPopulateKey,
           &populate_tabs));
@@ -283,9 +284,10 @@
   GURL url;
 
   // Look for optional url.
-  if (!args_->IsType(Value::TYPE_NULL)) {
-    EXTENSION_FUNCTION_VALIDATE(args_->IsType(Value::TYPE_DICTIONARY));
-    const DictionaryValue *args = args_as_dictionary();
+  if (HasOptionalArgument(0)) {
+    DictionaryValue* args;
+    EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &args));
+
     std::string url_string;
     if (args->HasKey(keys::kUrlKey)) {
       EXTENSION_FUNCTION_VALIDATE(args->GetString(keys::kUrlKey,
@@ -315,8 +317,9 @@
   Profile* window_profile = profile();
   Browser::Type window_type = Browser::TYPE_NORMAL;
 
-  if (args_->IsType(Value::TYPE_DICTIONARY)) {
-    const DictionaryValue *args = args_as_dictionary();
+  if (!args_->empty()) {
+    DictionaryValue* args;
+    EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &args));
 
     // Any part of the bounds can optionally be set by the caller.
     int bounds_val;
@@ -386,12 +389,10 @@
 }
 
 bool UpdateWindowFunction::RunImpl() {
-  EXTENSION_FUNCTION_VALIDATE(args_->IsType(Value::TYPE_LIST));
-  const ListValue* args = args_as_list();
   int window_id;
-  EXTENSION_FUNCTION_VALIDATE(args->GetInteger(0, &window_id));
+  EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &window_id));
   DictionaryValue* update_props;
-  EXTENSION_FUNCTION_VALIDATE(args->GetDictionary(1, &update_props));
+  EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(1, &update_props));
 
   Browser* browser = GetBrowserInProfileWithId(profile(), window_id,
                                                include_incognito(), &error_);
@@ -438,7 +439,7 @@
 
 bool RemoveWindowFunction::RunImpl() {
   int window_id;
-  EXTENSION_FUNCTION_VALIDATE(args_->GetAsInteger(&window_id));
+  EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &window_id));
 
   Browser* browser = GetBrowserInProfileWithId(profile(), window_id,
                                                include_incognito(), &error_);
@@ -457,8 +458,8 @@
   // windowId defaults to "current" window.
   int window_id = -1;
 
-  if (!args_->IsType(Value::TYPE_NULL)) {
-    EXTENSION_FUNCTION_VALIDATE(args_->GetAsInteger(&window_id));
+  if (HasOptionalArgument(0)) {
+    EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &window_id));
     browser = GetBrowserInProfileWithId(profile(), window_id,
                                         include_incognito(), &error_);
   } else {
@@ -484,8 +485,8 @@
   Browser* browser;
   // windowId defaults to "current" window.
   int window_id = -1;
-  if (!args_->IsType(Value::TYPE_NULL)) {
-    EXTENSION_FUNCTION_VALIDATE(args_->GetAsInteger(&window_id));
+  if (HasOptionalArgument(0)) {
+    EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &window_id));
     browser = GetBrowserInProfileWithId(profile(), window_id,
                                         include_incognito(), &error_);
   } else {
@@ -502,8 +503,8 @@
 }
 
 bool CreateTabFunction::RunImpl() {
-  EXTENSION_FUNCTION_VALIDATE(args_->IsType(Value::TYPE_DICTIONARY));
-  const DictionaryValue* args = args_as_dictionary();
+  DictionaryValue* args;
+  EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &args));
 
   Browser *browser;
   // windowId defaults to "current" window.
@@ -589,7 +590,7 @@
 
 bool GetTabFunction::RunImpl() {
   int tab_id;
-  EXTENSION_FUNCTION_VALIDATE(args_->GetAsInteger(&tab_id));
+  EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &tab_id));
 
   TabStripModel* tab_strip = NULL;
   TabContents* contents = NULL;
@@ -615,11 +616,9 @@
 
 bool UpdateTabFunction::RunImpl() {
   int tab_id;
-  EXTENSION_FUNCTION_VALIDATE(args_->IsType(Value::TYPE_LIST));
-  const ListValue* args = args_as_list();
-  EXTENSION_FUNCTION_VALIDATE(args->GetInteger(0, &tab_id));
+  EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &tab_id));
   DictionaryValue* update_props;
-  EXTENSION_FUNCTION_VALIDATE(args->GetDictionary(1, &update_props));
+  EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(1, &update_props));
 
   TabStripModel* tab_strip = NULL;
   TabContents* contents = NULL;
@@ -697,11 +696,9 @@
 
 bool MoveTabFunction::RunImpl() {
   int tab_id;
-  EXTENSION_FUNCTION_VALIDATE(args_->IsType(Value::TYPE_LIST));
-  const ListValue* args = args_as_list();
-  EXTENSION_FUNCTION_VALIDATE(args->GetInteger(0, &tab_id));
+  EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &tab_id));
   DictionaryValue* update_props;
-  EXTENSION_FUNCTION_VALIDATE(args->GetDictionary(1, &update_props));
+  EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(1, &update_props));
 
   int new_index;
   EXTENSION_FUNCTION_VALIDATE(update_props->GetInteger(
@@ -772,7 +769,7 @@
 
 bool RemoveTabFunction::RunImpl() {
   int tab_id;
-  EXTENSION_FUNCTION_VALIDATE(args_->GetAsInteger(&tab_id));
+  EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &tab_id));
 
   Browser* browser = NULL;
   TabContents* contents = NULL;
@@ -801,11 +798,8 @@
   // windowId defaults to "current" window.
   int window_id = -1;
 
-  EXTENSION_FUNCTION_VALIDATE(args_->IsType(Value::TYPE_LIST));
-  const ListValue* args = args_as_list();
-
   if (HasOptionalArgument(0)) {
-    EXTENSION_FUNCTION_VALIDATE(args->GetInteger(0, &window_id));
+    EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &window_id));
     browser = GetBrowserInProfileWithId(profile(), window_id,
                                         include_incognito(), &error_);
   } else {
@@ -822,7 +816,7 @@
 
   if (HasOptionalArgument(1)) {
     DictionaryValue* options;
-    EXTENSION_FUNCTION_VALIDATE(args->GetDictionary(1, &options));
+    EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(1, &options));
 
     if (options->HasKey(keys::kFormatKey)) {
       std::string format;
@@ -967,8 +961,8 @@
 
   // If |tab_id| is specified, look for it. Otherwise default to selected tab
   // in the current window.
-  if (!args_->IsType(Value::TYPE_NULL)) {
-    EXTENSION_FUNCTION_VALIDATE(args_->GetAsInteger(&tab_id));
+  if (HasOptionalArgument(0)) {
+    EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &tab_id));
     if (!GetTabById(tab_id, profile(), include_incognito(),
                     &browser, NULL, &contents, NULL, &error_)) {
       return false;
diff --git a/chrome/browser/extensions/extension_test_api.cc b/chrome/browser/extensions/extension_test_api.cc
index 48323d4..e5ae6508 100644
--- a/chrome/browser/extensions/extension_test_api.cc
+++ b/chrome/browser/extensions/extension_test_api.cc
@@ -20,7 +20,7 @@
 
 bool ExtensionTestFailFunction::RunImpl() {
   std::string message;
-  EXTENSION_FUNCTION_VALIDATE(args_->GetAsString(&message));
+  EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &message));
   NotificationService::current()->Notify(
       NotificationType::EXTENSION_TEST_FAILED,
       Source<Profile>(dispatcher()->profile()),
@@ -30,7 +30,7 @@
 
 bool ExtensionTestLogFunction::RunImpl() {
   std::string message;
-  EXTENSION_FUNCTION_VALIDATE(args_->GetAsString(&message));
+  EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &message));
   printf("%s\n", message.c_str());
   LOG(INFO) << message;
   return true;
@@ -46,7 +46,7 @@
 
 bool ExtensionTestCreateIncognitoTabFunction::RunImpl() {
   std::string url;
-  EXTENSION_FUNCTION_VALIDATE(args_->GetAsString(&url));
+  EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &url));
   Browser::OpenURLOffTheRecord(profile(), GURL(url));
   return true;
 }
diff --git a/chrome/browser/extensions/extension_toolstrip_api.cc b/chrome/browser/extensions/extension_toolstrip_api.cc
index 3732c68..26618e0 100644
--- a/chrome/browser/extensions/extension_toolstrip_api.cc
+++ b/chrome/browser/extensions/extension_toolstrip_api.cc
@@ -77,8 +77,8 @@
     return false;
   }
 
-  EXTENSION_FUNCTION_VALIDATE(args_->IsType(Value::TYPE_DICTIONARY));
-  const DictionaryValue* args = args_as_dictionary();
+  DictionaryValue* args;
+  EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &args));
 
   int height;
   EXTENSION_FUNCTION_VALIDATE(args->GetInteger(keys::kHeightKey,
@@ -115,9 +115,9 @@
   }
 
   GURL url;
-  if (args_->GetType() != Value::TYPE_NULL) {
-    EXTENSION_FUNCTION_VALIDATE(args_->IsType(Value::TYPE_DICTIONARY));
-    const DictionaryValue* args = args_as_dictionary();
+  if (HasOptionalArgument(0)) {
+    DictionaryValue* args;
+    EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &args));
 
     if (args->HasKey(keys::kUrlKey)) {
       std::string url_string;
diff --git a/chrome/browser/extensions/extensions_quota_service.cc b/chrome/browser/extensions/extensions_quota_service.cc
index 9005d8f..de5b926 100644
--- a/chrome/browser/extensions/extensions_quota_service.cc
+++ b/chrome/browser/extensions/extensions_quota_service.cc
@@ -29,7 +29,7 @@
 }
 
 bool ExtensionsQuotaService::Assess(const std::string& extension_id,
-    ExtensionFunction* function, const Value* args,
+    ExtensionFunction* function, const ListValue* args,
     const base::TimeTicks& event_time) {
   // Lookup function list for extension.
   FunctionHeuristicsMap& functions = function_heuristics_[extension_id];
@@ -83,7 +83,7 @@
   expiration_ = start + config.refill_interval;
 }
 
-bool QuotaLimitHeuristic::ApplyToArgs(const Value* args,
+bool QuotaLimitHeuristic::ApplyToArgs(const ListValue* args,
     const base::TimeTicks& event_time) {
   BucketList buckets;
   bucket_mapper_->GetBucketsForArgs(args, &buckets);
diff --git a/chrome/browser/extensions/extensions_quota_service.h b/chrome/browser/extensions/extensions_quota_service.h
index 700f9cc..b2999abe 100644
--- a/chrome/browser/extensions/extensions_quota_service.h
+++ b/chrome/browser/extensions/extensions_quota_service.h
@@ -43,7 +43,7 @@
   // Returns true if the request is fine and can proceed, false if the request
   // should be throttled and an error returned to the extension.
   bool Assess(const std::string& extension_id, ExtensionFunction* function,
-              const Value* args, const base::TimeTicks& event_time);
+              const ListValue* args, const base::TimeTicks& event_time);
  private:
   friend class ExtensionTestQuotaResetFunction;
   typedef std::map<std::string, QuotaLimitHeuristics> FunctionHeuristicsMap;
@@ -136,7 +136,8 @@
     // occurs while parsing |args|, the function aborts - buckets may be non-
     // empty). The expectation is that invalid args and associated errors are
     // handled by the ExtensionFunction itself so we don't concern ourselves.
-    virtual void GetBucketsForArgs(const Value* args, BucketList* buckets) = 0;
+    virtual void GetBucketsForArgs(const ListValue* args,
+                                   BucketList* buckets) = 0;
   };
 
   // Ownership of |mapper| is given to the new QuotaLimitHeuristic.
@@ -148,7 +149,7 @@
   // implementation of a derived class) to perform an operation with |args|,
   // based on the history of similar operations with similar arguments (which
   // is retrieved using the BucketMapper).
-  bool ApplyToArgs(const Value* args, const base::TimeTicks& event_time);
+  bool ApplyToArgs(const ListValue* args, const base::TimeTicks& event_time);
 
  protected:
   const Config& config() { return config_; }
diff --git a/chrome/browser/extensions/extensions_quota_service_unittest.cc b/chrome/browser/extensions/extensions_quota_service_unittest.cc
index 80457eb5..72958a9 100644
--- a/chrome/browser/extensions/extensions_quota_service_unittest.cc
+++ b/chrome/browser/extensions/extensions_quota_service_unittest.cc
@@ -29,11 +29,10 @@
  public:
   Mapper() {}
   virtual ~Mapper() { STLDeleteValues(&buckets_); }
-  virtual void GetBucketsForArgs(const Value* args, BucketList* buckets) {
-    const ListValue* v = static_cast<const ListValue*>(args);
-    for (size_t i = 0; i < v->GetSize(); i++) {
+  virtual void GetBucketsForArgs(const ListValue* args, BucketList* buckets) {
+    for (size_t i = 0; i < args->GetSize(); i++) {
       int id;
-      ASSERT_TRUE(v->GetInteger(i, &id));
+      ASSERT_TRUE(args->GetInteger(i, &id));
       if (buckets_.find(id) == buckets_.end())
         buckets_[id] = new Bucket();
       buckets->push_back(buckets_[id]);
@@ -47,13 +46,13 @@
 
 class MockMapper : public QuotaLimitHeuristic::BucketMapper {
  public:
-  virtual void GetBucketsForArgs(const Value* args, BucketList* buckets) {}
+  virtual void GetBucketsForArgs(const ListValue* args, BucketList* buckets) {}
 };
 
 class MockFunction : public ExtensionFunction {
  public:
   explicit MockFunction(const std::string& name) { set_name(name); }
-  virtual void SetArgs(const Value* args) {}
+  virtual void SetArgs(const ListValue* args) {}
   virtual const std::string GetError() { return std::string(); }
   virtual const std::string GetResult() { return std::string(); }
   virtual void Run() {}
diff --git a/chrome/browser/notifications/balloon_host.cc b/chrome/browser/notifications/balloon_host.cc
index 9ac64552..3dbefdc2 100644
--- a/chrome/browser/notifications/balloon_host.cc
+++ b/chrome/browser/notifications/balloon_host.cc
@@ -72,7 +72,7 @@
 }
 
 void BalloonHost::ProcessDOMUIMessage(const std::string& message,
-                                      const Value* content,
+                                      const ListValue* content,
                                       const GURL& source_url,
                                       int request_id,
                                       bool has_callback) {
diff --git a/chrome/browser/notifications/balloon_host.h b/chrome/browser/notifications/balloon_host.h
index 4e7a77cec..06c780e1 100644
--- a/chrome/browser/notifications/balloon_host.h
+++ b/chrome/browser/notifications/balloon_host.h
@@ -74,7 +74,7 @@
     return this;
   }
   virtual void ProcessDOMUIMessage(const std::string& message,
-                                   const Value* content,
+                                   const ListValue* content,
                                    const GURL& source_url,
                                    int request_id,
                                    bool has_callback);
diff --git a/chrome/browser/renderer_host/render_view_host.cc b/chrome/browser/renderer_host/render_view_host.cc
index 1d75014..f67dafe 100644
--- a/chrome/browser/renderer_host/render_view_host.cc
+++ b/chrome/browser/renderer_host/render_view_host.cc
@@ -1241,7 +1241,7 @@
   scoped_ptr<Value> value;
   if (!content.empty()) {
     value.reset(base::JSONReader::Read(content, false));
-    if (!value.get()) {
+    if (!value.get() || !value->IsType(Value::TYPE_LIST)) {
       // The page sent us something that we didn't understand.
       // This probably indicates a programming error.
       NOTREACHED() << "Invalid JSON argument in OnMsgDOMUISend.";
@@ -1249,8 +1249,11 @@
     }
   }
 
-  delegate_->ProcessDOMUIMessage(message, value.get(), source_url,
-                                 kRequestId, kHasCallback);
+  delegate_->ProcessDOMUIMessage(message,
+                                 static_cast<const ListValue*>(value.get()),
+                                 source_url,
+                                 kRequestId,
+                                 kHasCallback);
 }
 
 void RenderViewHost::OnMsgForwardMessageToExternalHost(
@@ -1754,7 +1757,7 @@
 }
 
 void RenderViewHost::OnExtensionRequest(const std::string& name,
-                                        const ListValue& args_holder,
+                                        const ListValue& args,
                                         const GURL& source_url,
                                         int request_id,
                                         bool has_callback) {
@@ -1766,16 +1769,7 @@
     return;
   }
 
-  // The renderer sends the args in a 1-element list to make serialization
-  // easier.
-  Value* args = NULL;
-  if (!args_holder.IsType(Value::TYPE_LIST) ||
-      !static_cast<const ListValue*>(&args_holder)->Get(0, &args)) {
-    NOTREACHED();
-    return;
-  }
-
-  delegate_->ProcessDOMUIMessage(name, args, source_url, request_id,
+  delegate_->ProcessDOMUIMessage(name, &args, source_url, request_id,
       has_callback);
 }
 
diff --git a/chrome/browser/renderer_host/render_view_host_delegate.h b/chrome/browser/renderer_host/render_view_host_delegate.h
index b8ca5f0e..6fc89bf 100644
--- a/chrome/browser/renderer_host/render_view_host_delegate.h
+++ b/chrome/browser/renderer_host/render_view_host_delegate.h
@@ -26,6 +26,7 @@
 struct ContextMenuParams;
 class FilePath;
 class GURL;
+class ListValue;
 struct NativeWebKeyboardEvent;
 class NavigationEntry;
 class OSExchangeData;
@@ -38,7 +39,6 @@
 class SkBitmap;
 class TabContents;
 struct ThumbnailScore;
-class Value;
 struct ViewHostMsg_DidPrintPage_Params;
 struct ViewHostMsg_FrameNavigate_Params;
 struct ViewHostMsg_RunFileChooser_Params;
@@ -554,7 +554,7 @@
   // A message was sent from HTML-based UI.
   // By default we ignore such messages.
   virtual void ProcessDOMUIMessage(const std::string& message,
-                                   const Value* content,
+                                   const ListValue* content,
                                    const GURL& source_url,
                                    int request_id,
                                    bool has_callback) {}
diff --git a/chrome/browser/tab_contents/background_contents.cc b/chrome/browser/tab_contents/background_contents.cc
index c61802d..33822a77 100644
--- a/chrome/browser/tab_contents/background_contents.cc
+++ b/chrome/browser/tab_contents/background_contents.cc
@@ -145,7 +145,7 @@
 }
 
 void BackgroundContents::ProcessDOMUIMessage(const std::string& message,
-                                             const Value* content,
+                                             const ListValue* content,
                                              const GURL& source_url,
                                              int request_id,
                                              bool has_callback) {
diff --git a/chrome/browser/tab_contents/background_contents.h b/chrome/browser/tab_contents/background_contents.h
index 348b28a..e2542ad 100644
--- a/chrome/browser/tab_contents/background_contents.h
+++ b/chrome/browser/tab_contents/background_contents.h
@@ -51,7 +51,7 @@
                            const ViewHostMsg_FrameNavigate_Params& params);
   virtual WebPreferences GetWebkitPrefs();
   virtual void ProcessDOMUIMessage(const std::string& message,
-                                   const Value* content,
+                                   const ListValue* content,
                                    const GURL& source_url,
                                    int request_id,
                                    bool has_callback);
diff --git a/chrome/browser/tab_contents/tab_contents.cc b/chrome/browser/tab_contents/tab_contents.cc
index 52b6698..3e38fe0 100644
--- a/chrome/browser/tab_contents/tab_contents.cc
+++ b/chrome/browser/tab_contents/tab_contents.cc
@@ -2526,7 +2526,7 @@
 }
 
 void TabContents::ProcessDOMUIMessage(const std::string& message,
-                                      const Value* content,
+                                      const ListValue* content,
                                       const GURL& source_url,
                                       int request_id,
                                       bool has_callback) {
diff --git a/chrome/browser/tab_contents/tab_contents.h b/chrome/browser/tab_contents/tab_contents.h
index 93c8c71..fa4f201c 100644
--- a/chrome/browser/tab_contents/tab_contents.h
+++ b/chrome/browser/tab_contents/tab_contents.h
@@ -929,7 +929,7 @@
   virtual void DomOperationResponse(const std::string& json_string,
                                     int automation_id);
   virtual void ProcessDOMUIMessage(const std::string& message,
-                                   const Value* content,
+                                   const ListValue* content,
                                    const GURL& source_url,
                                    int request_id,
                                    bool has_callback);
diff --git a/chrome/common/render_messages_internal.h b/chrome/common/render_messages_internal.h
index d350263..2f71dc6c4 100644
--- a/chrome/common/render_messages_internal.h
+++ b/chrome/common/render_messages_internal.h
@@ -1915,7 +1915,7 @@
   // request. The browser will always respond with a ViewMsg_ExtensionResponse.
   IPC_MESSAGE_ROUTED5(ViewHostMsg_ExtensionRequest,
                       std::string /* name */,
-                      ListValue /* argument */,
+                      ListValue /* arguments */,
                       GURL /* source_url */,
                       int /* callback id */,
                       bool /* has_callback */)
diff --git a/chrome/renderer/extensions/extension_api_client_unittest.cc b/chrome/renderer/extensions/extension_api_client_unittest.cc
index 776d694..c44f9ee 100644
--- a/chrome/renderer/extensions/extension_api_client_unittest.cc
+++ b/chrome/renderer/extensions/extension_api_client_unittest.cc
@@ -72,9 +72,8 @@
     ViewHostMsg_ExtensionRequest::Read(request_msg, &params);
     ASSERT_EQ(function.c_str(), params.a) << js;
 
-    Value* args = NULL;
     ASSERT_TRUE(params.b.IsType(Value::TYPE_LIST));
-    ASSERT_TRUE(static_cast<const ListValue*>(&params.b)->Get(0, &args));
+    ListValue* args = &params.b;
 
     base::JSONReader reader;
     scoped_ptr<Value> arg1_value(reader.JsonToValue(arg1, false, false));
@@ -157,7 +156,7 @@
                "Expected 'function' but got 'integer'.");
 
   ExpectJsPass("chrome.windows.get(2, function(){})",
-               "windows.get", "2");
+               "windows.get", "[2]");
 }
 
 // This test flakily crashes (http://crbug.com/22248)
@@ -242,11 +241,11 @@
                "  height:200"
                "})",
                "windows.create",
-               "{\"url\":\"http://www.google.com/\","
+               "[{\"url\":\"http://www.google.com/\","
                "\"left\":0,"
                "\"top\":10,"
                "\"width\":100,"
-               "\"height\":200}");
+               "\"height\":200}]");
 }
 
 TEST_F(ExtensionAPIClientTest, UpdateWindow) {
@@ -291,10 +290,10 @@
                "Expected 'function' but got 'integer'.");
 
   ExpectJsPass("chrome.windows.remove(2, function(){})",
-               "windows.remove", "2");
+               "windows.remove", "[2]");
 
   ExpectJsPass("chrome.windows.remove(2)",
-               "windows.remove", "2");
+               "windows.remove", "[2]");
 }
 
 // Tab API tests
@@ -315,7 +314,7 @@
                "Expected 'function' but got 'integer'.");
 
   ExpectJsPass("chrome.tabs.get(2, function(){})",
-               "tabs.get", "2");
+               "tabs.get", "[2]");
 }
 
 TEST_F(ExtensionAPIClientTest, GetCurrentTab) {
@@ -330,7 +329,7 @@
                "Expected 'function' but got 'string'.");
 
   ExpectJsPass("chrome.tabs.getCurrent(function(){})",
-               "tabs.getCurrent", "null");
+               "tabs.getCurrent", "[]");
 }
 
 TEST_F(ExtensionAPIClientTest, DetectTabLanguage) {
@@ -346,7 +345,7 @@
                "Expected 'function' but got 'integer'.");
 
   ExpectJsPass("chrome.tabs.detectLanguage(null, function(){})",
-               "tabs.detectLanguage", "null");
+               "tabs.detectLanguage", "[null]");
 }
 
 TEST_F(ExtensionAPIClientTest, GetSelectedTab) {
@@ -365,10 +364,10 @@
                "Expected 'function' but got 'integer'.");
 
   ExpectJsPass("chrome.tabs.getSelected(2, function(){})",
-               "tabs.getSelected", "2");
+               "tabs.getSelected", "[2]");
 
   ExpectJsPass("chrome.tabs.getSelected(null, function(){})",
-               "tabs.getSelected", "null");
+               "tabs.getSelected", "[null]");
 }
 
 
@@ -388,10 +387,10 @@
                "Expected 'integer' but got 'string'.");
 
   ExpectJsPass("chrome.tabs.getAllInWindow(32, function(){})",
-               "tabs.getAllInWindow", "32");
+               "tabs.getAllInWindow", "[32]");
 
   ExpectJsPass("chrome.tabs.getAllInWindow(undefined, function(){})",
-               "tabs.getAllInWindow", "null");
+               "tabs.getAllInWindow", "[null]");
 }
 
 TEST_F(ExtensionAPIClientTest, CreateTab) {
@@ -412,10 +411,10 @@
                "  windowId:4"
                "})",
                "tabs.create",
-               "{\"url\":\"http://www.google.com/\","
+               "[{\"url\":\"http://www.google.com/\","
                "\"selected\":true,"
                "\"index\":2,"
-               "\"windowId\":4}");
+               "\"windowId\":4}]");
 }
 
 TEST_F(ExtensionAPIClientTest, UpdateTab) {
@@ -472,10 +471,10 @@
                "Expected 'function' but got 'integer'.");
 
   ExpectJsPass("chrome.tabs.remove(2, function(){})",
-               "tabs.remove", "2");
+               "tabs.remove", "[2]");
 
   ExpectJsPass("chrome.tabs.remove(2)",
-               "tabs.remove", "2");
+               "tabs.remove", "[2]");
 }
 
 TEST_F(ExtensionAPIClientTest, CaptureVisibleTab) {
@@ -556,16 +555,16 @@
   ExpectJsPass(
       "chrome.bookmarks.create({parentId:'0', title:'x'}, function(){})",
       "bookmarks.create",
-      "{\"parentId\":\"0\",\"title\":\"x\"}");
+      "[{\"parentId\":\"0\",\"title\":\"x\"}]");
 }
 
 TEST_F(ExtensionAPIClientTest, GetBookmarks) {
   ExpectJsPass("chrome.bookmarks.get('0', function(){});",
                "bookmarks.get",
-               "\"0\"");
+               "[\"0\"]");
   ExpectJsPass("chrome.bookmarks.get(['0','1','2','3'], function(){});",
                "bookmarks.get",
-               "[\"0\",\"1\",\"2\",\"3\"]");
+               "[[\"0\",\"1\",\"2\",\"3\"]]");
   ExpectJsFail("chrome.bookmarks.get(null, function(){});",
                "Uncaught Error: Parameter 0 is required.");
   // TODO(erikkay) This is succeeding, when it should fail.
@@ -580,37 +579,37 @@
 TEST_F(ExtensionAPIClientTest, GetBookmarkChildren) {
   ExpectJsPass("chrome.bookmarks.getChildren('42', function(){});",
                "bookmarks.getChildren",
-               "\"42\"");
+               "[\"42\"]");
 }
 
 TEST_F(ExtensionAPIClientTest, GetBookmarkRecent) {
   ExpectJsPass("chrome.bookmarks.getRecent(5, function(){});",
     "bookmarks.getRecent",
-    "5");
+    "[5]");
 }
 
 TEST_F(ExtensionAPIClientTest, GetBookmarkTree) {
   ExpectJsPass("chrome.bookmarks.getTree(function(){});",
                "bookmarks.getTree",
-               "null");
+               "[]");
 }
 
 TEST_F(ExtensionAPIClientTest, SearchBookmarks) {
   ExpectJsPass("chrome.bookmarks.search('hello',function(){});",
                "bookmarks.search",
-               "\"hello\"");
+               "[\"hello\"]");
 }
 
 TEST_F(ExtensionAPIClientTest, RemoveBookmark) {
   ExpectJsPass("chrome.bookmarks.remove('42');",
                "bookmarks.remove",
-               "\"42\"");
+               "[\"42\"]");
 }
 
 TEST_F(ExtensionAPIClientTest, RemoveBookmarkTree) {
   ExpectJsPass("chrome.bookmarks.removeTree('42');",
                "bookmarks.removeTree",
-               "\"42\"");
+               "[\"42\"]");
 }
 
 TEST_F(ExtensionAPIClientTest, MoveBookmark) {
@@ -649,14 +648,14 @@
 TEST_F(ExtensionAPIClientTest, ExpandToolstrip) {
   ExpectJsPass("chrome.toolstrip.expand({height:100, url:'http://foo/'})",
                "toolstrip.expand",
-               "{\"height\":100,\"url\":\"http://foo/\"}");
+               "[{\"height\":100,\"url\":\"http://foo/\"}]");
   ExpectJsPass("chrome.toolstrip.expand({height:100}, null)",
                "toolstrip.expand",
-               "{\"height\":100}");
+               "[{\"height\":100}]");
   ExpectJsPass("chrome.toolstrip.expand({height:100,url:'http://foo/'}, "
                    "function(){})",
                "toolstrip.expand",
-               "{\"height\":100,\"url\":\"http://foo/\"}");
+               "[{\"height\":100,\"url\":\"http://foo/\"}]");
 
 
   ExpectJsFail("chrome.toolstrip.expand()",
@@ -679,13 +678,13 @@
 TEST_F(ExtensionAPIClientTest, CollapseToolstrip) {
   ExpectJsPass("chrome.toolstrip.collapse({url:'http://foo/'})",
                "toolstrip.collapse",
-               "{\"url\":\"http://foo/\"}");
+               "[{\"url\":\"http://foo/\"}]");
   ExpectJsPass("chrome.toolstrip.collapse(null)",
                "toolstrip.collapse",
-               "null");
+               "[null]");
   ExpectJsPass("chrome.toolstrip.collapse({url:'http://foo/'}, function(){})",
                "toolstrip.collapse",
-               "{\"url\":\"http://foo/\"}");
+               "[{\"url\":\"http://foo/\"}]");
 
   ExpectJsFail("chrome.toolstrip.collapse(1)",
                "Uncaught Error: Invalid value for argument 0. "
@@ -711,7 +710,7 @@
                "Expected 'function' but got 'string'.");
 
   ExpectJsPass("chrome.i18n.getAcceptLanguages(function(){})",
-               "i18n.getAcceptLanguages", "null");
+               "i18n.getAcceptLanguages", "[]");
 }
 
 // TODO(cira): re-enable when we get validation going for
diff --git a/chrome/renderer/extensions/extension_process_bindings.cc b/chrome/renderer/extensions/extension_process_bindings.cc
index b9f4e29..1ba0808 100644
--- a/chrome/renderer/extensions/extension_process_bindings.cc
+++ b/chrome/renderer/extensions/extension_process_bindings.cc
@@ -409,7 +409,7 @@
   // Common code for starting an API request to the browser. |value_args|
   // contains the request's arguments.
   static v8::Handle<v8::Value> StartRequestCommon(
-      const v8::Arguments& args, Value* value_args) {
+      const v8::Arguments& args, ListValue* value_args) {
     // Get the current RenderView so that we can send a routed IPC message from
     // the correct source.
     RenderView* renderview = bindings_utils::GetRenderViewForCurrentContext();
@@ -434,18 +434,13 @@
     int request_id = args[2]->Int32Value();
     bool has_callback = args[3]->BooleanValue();
 
-    // Put the args in a 1-element list for easier serialization. Maybe all
-    // requests should have a list of args?
-    ListValue args_holder;
-    args_holder.Append(value_args);
-
     v8::Persistent<v8::Context> current_context =
         v8::Persistent<v8::Context>::New(v8::Context::GetCurrent());
     DCHECK(!current_context.IsEmpty());
     GetPendingRequestMap()[request_id].reset(new PendingRequest(
         current_context, name));
 
-    renderview->SendExtensionRequest(name, args_holder, source_url,
+    renderview->SendExtensionRequest(name, *value_args, source_url,
                                      request_id, has_callback);
 
     return v8::Undefined();
@@ -460,12 +455,12 @@
 
     // Since we do the serialization in the v8 extension, we should always get
     // valid JSON.
-    if (!value_args) {
+    if (!value_args || !value_args->IsType(Value::TYPE_LIST)) {
       NOTREACHED() << "Invalid JSON passed to StartRequest.";
       return v8::Undefined();
     }
 
-    return StartRequestCommon(args, value_args);
+    return StartRequestCommon(args, static_cast<ListValue*>(value_args));
   }
 
   // A special request for setting the extension action icon. This function
@@ -473,7 +468,9 @@
   // before sending the request to the browser.
   static v8::Handle<v8::Value> SetExtensionActionIcon(
       const v8::Arguments& args) {
-    v8::Local<v8::Object> details = args[1]->ToObject();
+    v8::Local<v8::Object> extension_args = args[1]->ToObject();
+    v8::Local<v8::Object> details =
+        extension_args->Get(v8::String::New("0"))->ToObject();
     v8::Local<v8::Object> image_data =
         details->Get(v8::String::New("imageData"))->ToObject();
     v8::Local<v8::Object> data =
@@ -516,7 +513,10 @@
                        details->Get(v8::String::New("tabId"))->Int32Value());
     }
 
-    return StartRequestCommon(args, dict);
+    ListValue* list_value = new ListValue();
+    list_value->Append(dict);
+
+    return StartRequestCommon(args, list_value);
   }
 
   static v8::Handle<v8::Value> GetRenderViewId(const v8::Arguments& args) {
diff --git a/chrome/renderer/resources/extension_process_bindings.js b/chrome/renderer/resources/extension_process_bindings.js
index c19872c..c3d6a33 100644
--- a/chrome/renderer/resources/extension_process_bindings.js
+++ b/chrome/renderer/resources/extension_process_bindings.js
@@ -159,16 +159,9 @@
       --argCount;
     }
 
-    // Calls with one argument expect singular argument. Calls with multiple
-    // expect a list.
-    if (argCount == 1) {
-      request.args = args[0];
-    }
-    if (argCount > 1) {
-      request.args = [];
-      for (var k = 0; k < argCount; k++) {
-        request.args[k] = args[k];
-      }
+    request.args = [];
+    for (var k = 0; k < argCount; k++) {
+      request.args[k] = args[k];
     }
 
     return request;