summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authorasargent@chromium.org <asargent@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-10-11 19:38:24 +0000
committerasargent@chromium.org <asargent@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-10-11 19:38:24 +0000
commitd6885592f0a7ab6b969adf0bb2da2bf9a3a5e98d (patch)
tree4b062f492a1142e14a098264dbe286d6aecebf30 /chrome
parent0948989a3cfd8cab9e48108beb33f0b84d593eed (diff)
downloadchromium_src-d6885592f0a7ab6b969adf0bb2da2bf9a3a5e98d.zip
chromium_src-d6885592f0a7ab6b969adf0bb2da2bf9a3a5e98d.tar.gz
chromium_src-d6885592f0a7ab6b969adf0bb2da2bf9a3a5e98d.tar.bz2
Add a promptBrowserLogin method to webstorePrivate extension API
Also change 'getSyncLogin' to 'getBrowserLogin', and add notion of the login token to it (although this isn't actually sent yet). BUG=58033 TEST=Should be covered by browser tests. Review URL: http://codereview.chromium.org/3641001 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@62172 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r--chrome/browser/extensions/extension_function_dispatcher.cc3
-rw-r--r--chrome/browser/extensions/extension_webstore_private_api.cc76
-rw-r--r--chrome/browser/extensions/extension_webstore_private_api.h39
-rw-r--r--chrome/browser/extensions/extension_webstore_private_browsertest.cc109
-rw-r--r--chrome/browser/sync/profile_sync_service.h4
-rw-r--r--chrome/chrome_browser.gypi1
-rw-r--r--chrome/chrome_tests.gypi2
-rw-r--r--chrome/common/extensions/api/extension_api.json31
-rw-r--r--chrome/test/data/extensions/webstore_private/browser_login/no_preferred.html7
-rw-r--r--chrome/test/data/extensions/webstore_private/browser_login/preferred.html9
10 files changed, 268 insertions, 13 deletions
diff --git a/chrome/browser/extensions/extension_function_dispatcher.cc b/chrome/browser/extensions/extension_function_dispatcher.cc
index b8643fb..c908c09 100644
--- a/chrome/browser/extensions/extension_function_dispatcher.cc
+++ b/chrome/browser/extensions/extension_function_dispatcher.cc
@@ -278,10 +278,11 @@ void FactoryRegistry::ResetFunctions() {
RegisterFunction<UninstallFunction>();
// WebstorePrivate.
- RegisterFunction<GetSyncLoginFunction>();
+ RegisterFunction<GetBrowserLoginFunction>();
RegisterFunction<GetStoreLoginFunction>();
RegisterFunction<InstallFunction>();
RegisterFunction<SetStoreLoginFunction>();
+ RegisterFunction<PromptBrowserLoginFunction>();
}
void FactoryRegistry::GetAllNames(std::vector<std::string>* names) {
diff --git a/chrome/browser/extensions/extension_webstore_private_api.cc b/chrome/browser/extensions/extension_webstore_private_api.cc
index f18c2d5..8f1a33b 100644
--- a/chrome/browser/extensions/extension_webstore_private_api.cc
+++ b/chrome/browser/extensions/extension_webstore_private_api.cc
@@ -18,6 +18,9 @@
namespace {
const char* install_base_url = extension_urls::kGalleryUpdateHttpsUrl;
+const char kAlreadyLoggedInError[] = "User already logged in";
+const char kLoginKey[] = "login";
+ProfileSyncService* test_sync_service = NULL;
bool IsWebStoreURL(Profile* profile, const GURL& url) {
ExtensionsService* service = profile->GetExtensionsService();
@@ -26,7 +29,7 @@ bool IsWebStoreURL(Profile* profile, const GURL& url) {
return (service->GetExtensionByWebExtent(url) == store);
}
-}
+} // namespace
// static
void InstallFunction::SetTestingInstallBaseUrl(
@@ -67,12 +70,15 @@ bool InstallFunction::RunImpl() {
return true;
}
-bool GetSyncLoginFunction::RunImpl() {
+bool GetBrowserLoginFunction::RunImpl() {
if (!IsWebStoreURL(profile_, source_url()))
return false;
ProfileSyncService* sync_service = profile_->GetProfileSyncService();
string16 username = sync_service->GetAuthenticatedUsername();
- result_.reset(Value::CreateStringValue(username));
+ ListValue* list = new ListValue();
+ // TODO(asargent) - send the browser login token here too if available.
+ list->Append(Value::CreateStringValue(username));
+ result_.reset(list);
return true;
}
@@ -100,3 +106,67 @@ bool SetStoreLoginFunction::RunImpl() {
prefs->SetWebStoreLogin(login);
return true;
}
+
+// static
+void PromptBrowserLoginFunction::SetTestingProfileSyncService(
+ ProfileSyncService* service) {
+ test_sync_service = service;
+}
+
+ProfileSyncService* PromptBrowserLoginFunction::profile_sync_service() {
+ if (test_sync_service)
+ return test_sync_service;
+ else
+ return profile_->GetProfileSyncService();
+}
+
+PromptBrowserLoginFunction::~PromptBrowserLoginFunction() {
+ if (observing_sync_state_)
+ profile_sync_service()->RemoveObserver(this);
+}
+
+bool PromptBrowserLoginFunction::RunImpl() {
+ if (!IsWebStoreURL(profile_, source_url()))
+ return false;
+
+ std::string preferred_email;
+ ProfileSyncService* sync_service = profile_sync_service();
+ if (args_->GetSize() > 0) {
+ EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &preferred_email));
+ if (!sync_service->GetAuthenticatedUsername().empty()) {
+ error_ = kAlreadyLoggedInError;
+ return false;
+ }
+ }
+
+ // We return the result asynchronously, so we addref to keep ourself alive.
+ // Matched with a Release in OnStateChanged().
+ AddRef();
+
+ observing_sync_state_ = true;
+ sync_service->AddObserver(this);
+ // TODO(mirandac/estade) - make use of |preferred_email| to pre-populate the
+ // browser login dialog if it was set to non-empty above.
+ sync_service->ShowLoginDialog(NULL);
+
+ // The response will be sent asynchronously in OnStateChanged().
+ return true;
+}
+
+void PromptBrowserLoginFunction::OnStateChanged() {
+ ProfileSyncService* sync_service = profile_sync_service();
+ // If the setup is finished, we'll report back what happened.
+ if (!sync_service->SetupInProgress()) {
+ DictionaryValue* dictionary = new DictionaryValue();
+
+ // TODO(asargent) - send the browser login token here too if available.
+ string16 username = sync_service->GetAuthenticatedUsername();
+ dictionary->SetString(kLoginKey, username);
+
+ result_.reset(dictionary);
+ SendResponse(true);
+
+ // Matches the AddRef in RunImpl().
+ Release();
+ }
+}
diff --git a/chrome/browser/extensions/extension_webstore_private_api.h b/chrome/browser/extensions/extension_webstore_private_api.h
index 0ba27ac..4da35cf 100644
--- a/chrome/browser/extensions/extension_webstore_private_api.h
+++ b/chrome/browser/extensions/extension_webstore_private_api.h
@@ -2,11 +2,14 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CHROME_BROWSER_EXTENSIONS_EXTENSION_WEBSTORE_PRIVATE_API_H__
-#define CHROME_BROWSER_EXTENSIONS_EXTENSION_WEBSTORE_PRIVATE_API_H__
+#ifndef CHROME_BROWSER_EXTENSIONS_EXTENSION_WEBSTORE_PRIVATE_API_H_
+#define CHROME_BROWSER_EXTENSIONS_EXTENSION_WEBSTORE_PRIVATE_API_H_
#pragma once
#include "chrome/browser/extensions/extension_function.h"
+#include "chrome/browser/sync/profile_sync_service_observer.h"
+
+class ProfileSyncService;
class InstallFunction : public SyncExtensionFunction {
public:
@@ -18,9 +21,9 @@ class InstallFunction : public SyncExtensionFunction {
DECLARE_EXTENSION_FUNCTION_NAME("webstorePrivate.install");
};
-class GetSyncLoginFunction : public SyncExtensionFunction {
+class GetBrowserLoginFunction : public SyncExtensionFunction {
virtual bool RunImpl();
- DECLARE_EXTENSION_FUNCTION_NAME("webstorePrivate.getSyncLogin");
+ DECLARE_EXTENSION_FUNCTION_NAME("webstorePrivate.getBrowserLogin");
};
class GetStoreLoginFunction : public SyncExtensionFunction {
@@ -33,4 +36,30 @@ class SetStoreLoginFunction : public SyncExtensionFunction {
DECLARE_EXTENSION_FUNCTION_NAME("webstorePrivate.setStoreLogin");
};
-#endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_WEBSTORE_PRIVATE_API_H__
+class PromptBrowserLoginFunction : public AsyncExtensionFunction,
+ public ProfileSyncServiceObserver {
+ public:
+ // Allows you to set the ProfileSyncService the function will use for
+ // testing purposes.
+ static void SetTestingProfileSyncService(ProfileSyncService* service);
+
+ // Implements ProfileSyncServiceObserver interface.
+ virtual void OnStateChanged();
+
+ protected:
+ virtual ~PromptBrowserLoginFunction();
+ virtual bool RunImpl();
+
+ // Returns either the actual ProfileSyncService or the test service if one
+ // was set.
+ ProfileSyncService* profile_sync_service();
+
+ DECLARE_EXTENSION_FUNCTION_NAME("webstorePrivate.promptBrowserLogin");
+
+ private:
+ // This indicates whether we're currently registered as an observer of the
+ // ProfileSyncService, and need to unregister ourselves at destruction.
+ bool observing_sync_state_;
+};
+
+#endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_WEBSTORE_PRIVATE_API_H_
diff --git a/chrome/browser/extensions/extension_webstore_private_browsertest.cc b/chrome/browser/extensions/extension_webstore_private_browsertest.cc
new file mode 100644
index 0000000..a0e03b4
--- /dev/null
+++ b/chrome/browser/extensions/extension_webstore_private_browsertest.cc
@@ -0,0 +1,109 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/string_number_conversions.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/extensions/extension_browsertest.h"
+#include "chrome/browser/extensions/extension_test_message_listener.h"
+#include "chrome/browser/extensions/extension_webstore_private_api.h"
+#include "chrome/browser/sync/profile_sync_service.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/url_constants.h"
+#include "chrome/test/ui_test_utils.h"
+#include "googleurl/src/gurl.h"
+#include "net/base/mock_host_resolver.h"
+
+using chrome::kHttpScheme;
+using chrome::kStandardSchemeSeparator;
+
+namespace {
+
+const char kTestUrlHostname[] = "www.example.com";
+
+} // namespace
+
+// A fake version of ProfileSyncService used for testing.
+class FakeProfileSyncService : public ProfileSyncService {
+ public:
+ // The |username_after_login| parameter determines what this fake
+ // ProfileSyncService will set the username to when ShowLoginDialog is called.
+ explicit FakeProfileSyncService(const std::string& username_after_login) :
+ username_after_login_(username_after_login), observer_(NULL) {}
+ virtual ~FakeProfileSyncService() {
+ EXPECT_TRUE(observer_ == NULL);
+ }
+
+ // Overrides of virtual methods in ProfileSyncService.
+ virtual string16 GetAuthenticatedUsername() const { return username_; }
+ virtual void ShowLoginDialog(gfx::NativeWindow) {
+ EXPECT_TRUE(observer_ != NULL);
+ username_ = ASCIIToUTF16(username_after_login_);
+ observer_->OnStateChanged();
+ }
+ virtual bool SetupInProgress() const {
+ return false;
+ }
+ virtual void AddObserver(ProfileSyncServiceObserver* observer) {
+ EXPECT_TRUE(observer_ == NULL);
+ observer_ = observer;
+ }
+ virtual void RemoveObserver(ProfileSyncServiceObserver* observer) {
+ EXPECT_TRUE(observer == observer_);
+ observer_ = NULL;
+ }
+
+ private:
+ std::string username_after_login_;
+ string16 username_;
+ ProfileSyncServiceObserver* observer_;
+};
+
+class ExtensionWebstorePrivateBrowserTest : public ExtensionBrowserTest {
+ public:
+ ExtensionWebstorePrivateBrowserTest() {
+ test_url_base_ = std::string() + kHttpScheme + kStandardSchemeSeparator +
+ kTestUrlHostname;
+ }
+
+ void SetUpCommandLine(CommandLine* command_line) {
+ ExtensionBrowserTest::SetUpCommandLine(command_line);
+ command_line->AppendSwitchASCII(switches::kAppsGalleryURL, test_url_base_);
+ }
+
+ // This generates a regular test server url pointing to a test file at
+ // |relative_path|, but replaces the hostname with kTestUrlHostname so that
+ // we get the webstore private APIs injected (this happens because of the
+ // command line switch we added in SetupCommandLine).
+ GURL GetUrl(const std::string& relative_path) {
+ GURL base_url = test_server()->GetURL(
+ "files/extensions/webstore_private/" + relative_path);
+ GURL::Replacements replacements;
+ std::string replacement_host = std::string(kTestUrlHostname);
+ replacements.SetHostStr(replacement_host);
+ return base_url.ReplaceComponents(replacements);
+ }
+
+ void RunLoginTest(const std::string& relative_path,
+ const std::string& login_result) {
+ FakeProfileSyncService sync_service(login_result);
+ PromptBrowserLoginFunction::SetTestingProfileSyncService(&sync_service);
+ ExtensionTestMessageListener listener("success", false);
+ GURL url = GetUrl(relative_path);
+ ui_test_utils::NavigateToURL(browser(), url);
+ EXPECT_TRUE(listener.WaitUntilSatisfied());
+ PromptBrowserLoginFunction::SetTestingProfileSyncService(NULL);
+ }
+
+ protected:
+ std::string test_url_base_;
+};
+
+IN_PROC_BROWSER_TEST_F(ExtensionWebstorePrivateBrowserTest, BrowserLogin) {
+ host_resolver()->AddRule(kTestUrlHostname, "127.0.0.1");
+ ASSERT_TRUE(test_server()->Start());
+
+ RunLoginTest("browser_login/no_preferred.html", "");
+ RunLoginTest("browser_login/preferred.html", "foo@bar.com");
+}
+
diff --git a/chrome/browser/sync/profile_sync_service.h b/chrome/browser/sync/profile_sync_service.h
index e68f554..5a889f1 100644
--- a/chrome/browser/sync/profile_sync_service.h
+++ b/chrome/browser/sync/profile_sync_service.h
@@ -214,11 +214,11 @@ class ProfileSyncService : public browser_sync::SyncFrontend,
// progress, the sync system is already authenticated, or some error
// occurred preventing the action. We make it the duty of ProfileSyncService
// to open the dialog to easily ensure only one is ever showing.
- bool SetupInProgress() const;
+ virtual bool SetupInProgress() const;
bool WizardIsVisible() const {
return wizard_.IsVisible();
}
- void ShowLoginDialog(gfx::NativeWindow parent_window);
+ virtual void ShowLoginDialog(gfx::NativeWindow parent_window);
void ShowChooseDataTypes(gfx::NativeWindow parent_window);
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index 603f6ec..55ba15f 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -2750,6 +2750,7 @@
'browser/sync/profile_sync_factory_impl.h',
'browser/sync/profile_sync_service.cc',
'browser/sync/profile_sync_service.h',
+ 'browser/sync/profile_sync_service_observer.h',
'browser/sync/signin_manager.cc',
'browser/sync/signin_manager.h',
'browser/sync/sync_constants.cc',
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi
index 12ee7834..51598a3 100644
--- a/chrome/chrome_tests.gypi
+++ b/chrome/chrome_tests.gypi
@@ -1963,6 +1963,7 @@
'browser/extensions/extension_webnavigation_apitest.cc',
'browser/extensions/extension_webrequest_apitest.cc',
'browser/extensions/extension_websocket_apitest.cc',
+ 'browser/extensions/extension_webstore_private_browsertest.cc',
'browser/extensions/fragment_navigation_apitest.cc',
'browser/extensions/isolated_world_apitest.cc',
'browser/extensions/notifications_apitest.cc',
@@ -2095,6 +2096,7 @@
['OS=="linux"', {
'dependencies': [
'../build/linux/system.gyp:gtk',
+ '../build/linux/system.gyp:nss',
'../tools/xdisplaycheck/xdisplaycheck.gyp:xdisplaycheck',
],
}],
diff --git a/chrome/common/extensions/api/extension_api.json b/chrome/common/extensions/api/extension_api.json
index 860f94d..34ab416 100644
--- a/chrome/common/extensions/api/extension_api.json
+++ b/chrome/common/extensions/api/extension_api.json
@@ -4119,7 +4119,7 @@
]
},
{
- "name": "getSyncLogin",
+ "name": "getBrowserLogin",
"description": "Returns the logged-in sync user login if there is one, or the empty string otherwise.",
"parameters": [
{
@@ -4127,7 +4127,8 @@
"type": "function",
"optional": "false",
"parameters": [
- { "name": "login", "type": "string" }
+ { "name": "login", "type": "string" },
+ { "name": "token", "type": "string", "optional": true }
]
}
]
@@ -4153,6 +4154,32 @@
{ "name": "login", "type": "string" },
{ "name": "callback", "type": "function", "optional": "true" }
]
+ },
+ {
+ "name": "promptBrowserLogin",
+ "description": "Causes the browser to bring up the browser login UI.",
+ "parameters": [
+ {
+ "name": "preferred_email",
+ "type": "string",
+ "description": "The email address to use to pre-populate the login dialog (can be an empty string)."
+ },
+ {
+ "name": "callback",
+ "type": "function",
+ "optional": "true",
+ "parameters": [
+ {
+ "name": "info",
+ "type": "object",
+ "properties": {
+ "login": { "type": "string", "optional": true },
+ "token": { "type": "string", "optional": true }
+ }
+ }
+ ]
+ }
+ ]
}
]
}
diff --git a/chrome/test/data/extensions/webstore_private/browser_login/no_preferred.html b/chrome/test/data/extensions/webstore_private/browser_login/no_preferred.html
new file mode 100644
index 0000000..b2391e8
--- /dev/null
+++ b/chrome/test/data/extensions/webstore_private/browser_login/no_preferred.html
@@ -0,0 +1,7 @@
+<script>
+chrome.webstorePrivate.promptBrowserLogin("", function(result) {
+ if (result.login == "") {
+ chrome.test.sendMessage("success");
+ }
+});
+</script>
diff --git a/chrome/test/data/extensions/webstore_private/browser_login/preferred.html b/chrome/test/data/extensions/webstore_private/browser_login/preferred.html
new file mode 100644
index 0000000..ffbe66e
--- /dev/null
+++ b/chrome/test/data/extensions/webstore_private/browser_login/preferred.html
@@ -0,0 +1,9 @@
+<script>
+chrome.webstorePrivate.promptBrowserLogin("foo@bar.com",
+ function(result) {
+ if (result.login == "foo@bar.com") {
+ chrome.test.sendMessage("success");
+ }
+});
+</script>
+