15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// found in the LICENSE file.
45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "chrome/browser/extensions/extension_function_test_utils.h"
65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include <string>
85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "base/files/file_path.h"
105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "base/json/json_reader.h"
115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "base/values.h"
125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "chrome/browser/extensions/api/tabs/tabs_constants.h"
135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "chrome/browser/profiles/profile.h"
145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "chrome/browser/ui/browser.h"
155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "chrome/test/base/ui_test_utils.h"
165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "components/crx_file/id_util.h"
175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "extensions/browser/api_test_utils.h"
185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "extensions/browser/extension_function.h"
195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "extensions/browser/extension_function_dispatcher.h"
205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "extensions/common/extension.h"
215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2302772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdochusing content::WebContents;
245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)using extensions::Extension;
255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)using extensions::Manifest;
265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)namespace keys = extensions::tabs_constants;
275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
28d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)namespace {
295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)class TestFunctionDispatcherDelegate
3106f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    : public extensions::ExtensionFunctionDispatcher::Delegate {
32f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu public:
3309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)  explicit TestFunctionDispatcherDelegate(Browser* browser) :
34d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)      browser_(browser) {}
3509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)  virtual ~TestFunctionDispatcherDelegate() {}
3653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
3753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) private:
38d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)  virtual extensions::WindowController* GetExtensionWindowController()
3953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)      const OVERRIDE {
4053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    return browser_->extension_window_controller();
4153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)  }
42f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)
43f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)  virtual WebContents* GetAssociatedWebContents() const OVERRIDE {
4453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    return NULL;
4553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)  }
46d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
475d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)  Browser* browser_;
48323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)};
49a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
505d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)}  // namespace
51d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
52a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)namespace extension_function_test_utils {
535d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)
541e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)base::Value* ParseJSON(const std::string& data) {
55a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)  return base::JSONReader::Read(data);
56f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)}
575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)base::ListValue* ParseList(const std::string& data) {
595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  base::Value* result = ParseJSON(data);
60d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)  base::ListValue* list = NULL;
615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  result->GetAsList(&list);
62d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)  return list;
63aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch}
645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)base::DictionaryValue* ParseDictionary(
6610f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch    const std::string& data) {
6710f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch  base::Value* result = ParseJSON(data);
685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  base::DictionaryValue* dict = NULL;
695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  result->GetAsDictionary(&dict);
705d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)  return dict;
715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
726f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch
735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool GetBoolean(base::DictionaryValue* val, const std::string& key) {
745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  bool result = false;
755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  if (!val->GetBoolean(key, &result))
765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      ADD_FAILURE() << key << " does not exist or is not a boolean.";
775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  return result;
785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8010f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdochint GetInteger(base::DictionaryValue* val, const std::string& key) {
8110f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch  int result = 0;
82f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu  if (!val->GetInteger(key, &result))
83f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    ADD_FAILURE() << key << " does not exist or is not an integer.";
8410f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch  return result;
8510f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch}
8610f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch
8710f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdochstd::string GetString(base::DictionaryValue* val, const std::string& key) {
8810f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch  std::string result;
8910f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch  if (!val->GetString(key, &result))
9010f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch    ADD_FAILURE() << key << " does not exist or is not a string.";
9110f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch  return result;
9210f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch}
9310f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch
945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)base::DictionaryValue* ToDictionary(base::Value* val) {
9507a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch  EXPECT_TRUE(val);
9607a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch  EXPECT_EQ(base::Value::TYPE_DICTIONARY, val->GetType());
9702772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch  return static_cast<base::DictionaryValue*>(val);
9807a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch}
9907a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch
100f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)base::ListValue* ToList(base::Value* val) {
101f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)  EXPECT_TRUE(val);
102f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)  EXPECT_EQ(base::Value::TYPE_LIST, val->GetType());
103f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)  return static_cast<base::ListValue*>(val);
104f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)}
105f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)
106f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)scoped_refptr<Extension> CreateEmptyExtensionWithLocation(
10707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    Manifest::Location location) {
10807a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch  scoped_ptr<base::DictionaryValue> test_extension_value(
10907a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch      ParseDictionary("{\"name\": \"Test\", \"version\": \"1.0\"}"));
11007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch  return CreateExtension(location, test_extension_value.get(), std::string());
11107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch}
112f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)
113f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)scoped_refptr<Extension> CreateExtension(
114f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    base::DictionaryValue* test_extension_value) {
115f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)  return CreateExtension(Manifest::INTERNAL, test_extension_value,
1165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                         std::string());
1175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
11810f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch
1196f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdochscoped_refptr<Extension> CreateExtension(
12010f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch    Manifest::Location location,
12110f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch    base::DictionaryValue* test_extension_value,
12210f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch    const std::string& id_input) {
12310f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch  std::string error;
12410f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch  const base::FilePath test_extension_path;
12510f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch  std::string id;
12610f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch  if (!id_input.empty())
12710f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch    id = crx_file::id_util::GenerateId(id_input);
12810f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch  scoped_refptr<Extension> extension(Extension::Create(
12910f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch      test_extension_path,
1305d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)      location,
13110f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch      *test_extension_value,
1326f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch      Extension::NO_FLAGS,
1336f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch      id,
1346f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch      &error));
13510f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch  EXPECT_TRUE(error.empty()) << "Could not parse test extension " << error;
13610f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch  return extension;
1375d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)}
1385d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)
1395d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)bool HasPrivacySensitiveFields(base::DictionaryValue* val) {
14010f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch  std::string result;
1415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  if (val->GetString(keys::kUrlKey, &result) ||
14210f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch      val->GetString(keys::kTitleKey, &result) ||
14310f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch      val->GetString(keys::kFaviconUrlKey, &result))
14410f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch    return true;
1455d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)  return false;
14610f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch}
1475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)std::string RunFunctionAndReturnError(UIThreadExtensionFunction* function,
14909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)                                      const std::string& args,
15051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)                                      Browser* browser) {
151f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu  return RunFunctionAndReturnError(function, args, browser, NONE);
152f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu}
153d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)std::string RunFunctionAndReturnError(UIThreadExtensionFunction* function,
15409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)                                      const std::string& args,
15510f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch                                      Browser* browser,
15651b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)                                      RunFunctionFlags flags) {
15751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)  scoped_refptr<ExtensionFunction> function_owner(function);
158a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch  // Without a callback the function will not generate a result.
159a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch  function->set_has_callback(true);
160a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch  RunFunction(function, args, browser, flags);
161a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch  EXPECT_FALSE(function->GetResultList()) << "Did not expect a result";
162a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch  return function->GetError();
163d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)}
16406f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)
165d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)base::Value* RunFunctionAndReturnSingleResult(
16606f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    UIThreadExtensionFunction* function,
167d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    const std::string& args,
168d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    Browser* browser) {
16906f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)  return RunFunctionAndReturnSingleResult(function, args, browser, NONE);
170d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)}
17106f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)base::Value* RunFunctionAndReturnSingleResult(
172d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    UIThreadExtensionFunction* function,
17306f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    const std::string& args,
17406f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    Browser* browser,
17506f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    RunFunctionFlags flags) {
17606f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)  scoped_refptr<ExtensionFunction> function_owner(function);
17706f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)  // Without a callback the function will not generate a result.
17806f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)  function->set_has_callback(true);
17906f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)  RunFunction(function, args, browser, flags);
180a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch  EXPECT_TRUE(function->GetError().empty()) << "Unexpected error: "
18119cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)      << function->GetError();
1825d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)  const base::Value* single_result = NULL;
1835d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)  if (function->GetResultList() != NULL &&
1845d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)      function->GetResultList()->Get(0, &single_result)) {
1855d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    return single_result->DeepCopy();
18619cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)  }
187a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch  return NULL;
188a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch}
189a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
19010f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch// This helps us be able to wait until an UIThreadExtensionFunction calls
191f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu// SendResponse.
192f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liuclass SendResponseDelegate
1935d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    : public UIThreadExtensionFunction::DelegateForTests {
1945d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) public:
1955d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)  SendResponseDelegate() : should_post_quit_(false) {}
196a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
1975d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)  virtual ~SendResponseDelegate() {}
198a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
199a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch  void set_should_post_quit(bool should_quit) {
200a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    should_post_quit_ = should_quit;
201a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch  }
202f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu
203f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu  bool HasResponse() {
204d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    return response_.get() != NULL;
205f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)  }
206d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)
2075d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)  bool GetResponse() {
2085d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    EXPECT_TRUE(HasResponse());
2095d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    return *response_.get();
2105d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)  }
211f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)
21219cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)  virtual void OnSendResponse(UIThreadExtensionFunction* function,
21319cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)                              bool success,
21409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)                              bool bad_message) OVERRIDE {
2155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT_FALSE(bad_message);
216aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch    ASSERT_FALSE(HasResponse());
217926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    response_.reset(new bool);
21810f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch    *response_ = success;
21910f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch    if (should_post_quit_) {
220323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)      base::MessageLoopForUI::current()->Quit();
221323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    }
222323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)  }
2235d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)
2245d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) private:
2255d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)  scoped_ptr<bool> response_;
226323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)  bool should_post_quit_;
227323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)};
2285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
229aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdochbool RunFunction(UIThreadExtensionFunction* function,
23007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch                 const std::string& args,
2316f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch                 Browser* browser,
23207a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch                 RunFunctionFlags flags) {
23307a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch  scoped_ptr<base::ListValue> parsed_args(ParseList(args));
2345d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)  EXPECT_TRUE(parsed_args.get())
2355d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)      << "Could not parse extension function arguments: " << args;
2365d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)  return RunFunction(function, parsed_args.Pass(), browser, flags);
2375d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)}
2385d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)
2395d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)bool RunFunction(UIThreadExtensionFunction* function,
2405d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)                 scoped_ptr<base::ListValue> args,
2415d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)                 Browser* browser,
2425d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)                 RunFunctionFlags flags) {
2435d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)  TestFunctionDispatcherDelegate dispatcher_delegate(browser);
2445d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)  scoped_ptr<extensions::ExtensionFunctionDispatcher> dispatcher(
2455d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)      new extensions::ExtensionFunctionDispatcher(browser->profile(),
2465d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)                                                  &dispatcher_delegate));
2475d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)  // TODO(yoz): The cast is a hack; these flags should be defined in
248f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)  // only one place.  See crbug.com/394840.
249f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)  return extensions::api_test_utils::RunFunction(
250d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)      function,
25107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch      args.Pass(),
252d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)      browser->profile(),
253d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)      dispatcher.Pass(),
25407a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch      static_cast<extensions::api_test_utils::RunFunctionFlags>(flags));
25507a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch}
256f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)
257f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)} // namespace extension_function_test_utils
258d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)