summaryrefslogtreecommitdiffstats
path: root/chrome/browser
diff options
context:
space:
mode:
authorpetewil@chromium.org <petewil@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-02-26 03:17:36 +0000
committerpetewil@chromium.org <petewil@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-02-26 03:17:36 +0000
commit23ee535fbe4ce2c4e70d5b3b460590e8cee4823a (patch)
treec68582c77c7deb6384740d2d2fd30b6f315063c6 /chrome/browser
parent580f17d6c756c68a78d379c6a2b2a11565566b24 (diff)
downloadchromium_src-23ee535fbe4ce2c4e70d5b3b460590e8cee4823a.zip
chromium_src-23ee535fbe4ce2c4e70d5b3b460590e8cee4823a.tar.gz
chromium_src-23ee535fbe4ce2c4e70d5b3b460590e8cee4823a.tar.bz2
Canary test for push messaging.
This test will run on a modified buildbot (NOT in the normal checkin flow) which our team will monitor. It will be used to detect checkins that pass our unit tests, but break our scenario. BUG=159757 Review URL: https://chromiumcodereview.appspot.com/11360142 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@184574 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
-rw-r--r--chrome/browser/extensions/api/push_messaging/push_messaging_api.cc6
-rw-r--r--chrome/browser/extensions/api/push_messaging/push_messaging_canary_test.cc184
-rw-r--r--chrome/browser/extensions/api/push_messaging/sync_setup_helper.cc92
-rw-r--r--chrome/browser/extensions/api/push_messaging/sync_setup_helper.h79
-rw-r--r--chrome/browser/sync/profile_sync_service_harness.cc44
-rw-r--r--chrome/browser/sync/profile_sync_service_harness.h9
6 files changed, 396 insertions, 18 deletions
diff --git a/chrome/browser/extensions/api/push_messaging/push_messaging_api.cc b/chrome/browser/extensions/api/push_messaging/push_messaging_api.cc
index 07ca1d3..4dcbee4 100644
--- a/chrome/browser/extensions/api/push_messaging/push_messaging_api.cc
+++ b/chrome/browser/extensions/api/push_messaging/push_messaging_api.cc
@@ -66,6 +66,11 @@ void PushMessagingEventRouter::OnMessage(const std::string& extension_id,
message.subchannel_id = subchannel;
message.payload = payload;
+ DVLOG(2) << "PushMessagingEventRouter::OnMessage"
+ << " payload = '" << payload
+ << "' subchannel = '" << subchannel
+ << "' extension = '" << extension_id << "'";
+
scoped_ptr<base::ListValue> args(glue::OnMessage::Create(message));
scoped_ptr<extensions::Event> event(new extensions::Event(
event_names::kOnPushMessage, args.Pass()));
@@ -222,6 +227,7 @@ void PushMessagingGetChannelIdFunction::OnObfuscatedGaiaIdFetchFailure(
}
ReportResult(std::string(), error_text);
+ DVLOG(1) << "GetChannelId status: '" << error_text << "'";
}
PushMessagingAPI::PushMessagingAPI(Profile* profile) : profile_(profile) {
diff --git a/chrome/browser/extensions/api/push_messaging/push_messaging_canary_test.cc b/chrome/browser/extensions/api/push_messaging/push_messaging_canary_test.cc
new file mode 100644
index 0000000..22350f2
--- /dev/null
+++ b/chrome/browser/extensions/api/push_messaging/push_messaging_canary_test.cc
@@ -0,0 +1,184 @@
+// Copyright (c) 2012 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 <string>
+
+#include "base/string16.h"
+#include "base/stringprintf.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/extensions/api/push_messaging/sync_setup_helper.h"
+#include "chrome/browser/extensions/extension_apitest.h"
+#include "chrome/browser/extensions/extension_test_message_listener.h"
+#include "chrome/browser/extensions/platform_app_launcher.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_tabstrip.h"
+#include "chrome/browser/ui/tabs/tab_strip_model.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/test/base/ui_test_utils.h"
+#include "content/public/browser/render_view_host.h"
+#include "content/public/test/browser_test_utils.h"
+#include "net/base/mock_host_resolver.h"
+
+namespace switches {
+const char kPasswordFileForTest[] = "password-file-for-test";
+const char kOverrideUserDataDir[] = "override-user-data-dir";
+}
+
+namespace extensions {
+
+// This class provides tests specific to the push messaging
+// canary test server. These tests require network access,
+// and should not be run by normal buildbots as part of the normal
+// checkin process.
+class PushMessagingCanaryTest : public ExtensionApiTest {
+ public:
+ PushMessagingCanaryTest() {
+ sync_setup_helper_.reset(new SyncSetupHelper());
+ }
+
+ ~PushMessagingCanaryTest() {
+ }
+
+ virtual void SetUp() OVERRIDE {
+ CommandLine* command_line = CommandLine::ForCurrentProcess();
+
+ if (command_line->HasSwitch(switches::kPasswordFileForTest)) {
+ base::FilePath password_file =
+ command_line->GetSwitchValuePath(switches::kPasswordFileForTest);
+ ASSERT_TRUE(sync_setup_helper_->ReadPasswordFile(password_file));
+ }
+
+ // The test framework overrides any command line user-data-dir
+ // argument with a /tmp/.org.chromium.Chromium.XXXXXX directory.
+ // That happens in the ChromeTestLauncherDelegate, and affects
+ // all unit tests (no opt out available). It intentionally erases
+ // any --user-data-dir switch if present and appends a new one.
+ // Re-override the default data dir for our test so we can persist
+ // the profile for this particular test so we can persist the max
+ // invalidation version between runs.
+ base::FilePath user_data_dir =
+ command_line->GetSwitchValuePath(switches::kUserDataDir);
+ base::FilePath override_user_data_dir =
+ command_line->GetSwitchValuePath(switches::kOverrideUserDataDir);
+
+ if (!override_user_data_dir.empty() &&
+ override_user_data_dir != user_data_dir) {
+ CommandLine::SwitchMap switches =
+ CommandLine::ForCurrentProcess()->GetSwitches();
+ command_line->AppendSwitchPath(switches::kUserDataDir,
+ base::FilePath(override_user_data_dir));
+ LOG(INFO) << "command line file override switch is "
+ << override_user_data_dir.AsUTF8Unsafe();
+ }
+
+ ExtensionApiTest::SetUp();
+ }
+
+ void InitializeSync(Profile* profile) {
+ ASSERT_TRUE(sync_setup_helper_->InitializeSync(profile));
+ }
+
+ // InProcessBrowserTest override. Destroys the sync client and sync
+ // profile created by the test. We must clean up ProfileSyncServiceHarness
+ // now before the profile is cleaned up.
+ virtual void CleanUpOnMainThread() OVERRIDE {
+ sync_setup_helper_.reset();
+ }
+
+ void StartRunningTest() {
+ // Get the credentials from the setup helper.
+ const std::string& client_id = sync_setup_helper_->client_id();
+ const std::string& client_secret = sync_setup_helper_->client_secret();
+ const std::string& refresh_token = sync_setup_helper_->refresh_token();
+
+ // Construct a JS string to pass in the parameters and start the test.
+ std::string script_string = StringPrintf(
+ "startTestWithCredentials('%s', '%s', '%s');",
+ client_id.c_str(), client_secret.c_str(), refresh_token.c_str());
+ string16 script16 = UTF8ToUTF16(script_string);
+
+ browser()->tab_strip_model()->GetActiveWebContents()->GetRenderViewHost()->
+ ExecuteJavascriptInWebFrame(string16(), script16);
+ }
+
+ protected:
+ // Override InProcessBrowserTest. Change behavior of the default host
+ // resolver to avoid DNS lookup errors, so we can make network calls.
+ virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
+ // The resolver object lifetime is managed by sync_test_setup, not here.
+ EnableDNSLookupForThisTest(
+ new net::RuleBasedHostResolverProc(host_resolver()));
+ }
+
+ virtual void TearDownInProcessBrowserTestFixture() OVERRIDE {
+ DisableDNSLookupForThisTest();
+ }
+
+
+ // Change behavior of the default host resolver to allow DNS lookup
+ // to proceed instead of being blocked by the test infrastructure.
+ void EnableDNSLookupForThisTest(
+ net::RuleBasedHostResolverProc* host_resolver) {
+ // mock_host_resolver_override_ takes ownership of the resolver.
+ scoped_refptr<net::RuleBasedHostResolverProc> resolver =
+ new net::RuleBasedHostResolverProc(host_resolver);
+ resolver->AllowDirectLookup("*.google.com");
+ // On Linux, we use Chromium's NSS implementation which uses the following
+ // hosts for certificate verification. Without these overrides, running the
+ // integration tests on Linux causes error as we make external DNS lookups.
+ resolver->AllowDirectLookup("*.thawte.com");
+ resolver->AllowDirectLookup("*.geotrust.com");
+ resolver->AllowDirectLookup("*.gstatic.com");
+ resolver->AllowDirectLookup("*.googleapis.com");
+ mock_host_resolver_override_.reset(
+ new net::ScopedDefaultHostResolverProc(resolver));
+ }
+
+ // We need to reset the DNS lookup when we finish, or the test will fail.
+ void DisableDNSLookupForThisTest() {
+ mock_host_resolver_override_.reset();
+ }
+
+ private:
+ scoped_ptr<SyncSetupHelper> sync_setup_helper_;
+
+ // This test needs to make live DNS requests for access to
+ // GAIA and sync server URLs under google.com. We use a scoped version
+ // to override the default resolver while the test is active.
+ scoped_ptr<net::ScopedDefaultHostResolverProc> mock_host_resolver_override_;
+};
+
+// Test that a push can make a round trip through the servers.
+// This test is disabled to keep it from running on trybots since
+// it requires network access, and it is not a good idea to run
+// this test as part of a checkin or nightly test.
+IN_PROC_BROWSER_TEST_F(PushMessagingCanaryTest, DISABLED_ReceivesPush) {
+ ResultCatcher catcher;
+ catcher.RestrictToProfile(browser()->profile());
+ ExtensionTestMessageListener ready("ready", true);
+
+ // Turn on sync so we can receive notifications over sync.
+ InitializeSync(browser()->profile());
+
+ const extensions::Extension* extension =
+ LoadExtension(test_data_dir_.AppendASCII("push_messaging_canary"));
+ ASSERT_TRUE(extension);
+
+ DVLOG(1) << "extension dir is " << test_data_dir_.value();
+
+ ui_test_utils::NavigateToURL(
+ browser(), extension->GetResourceURL("push_messaging_canary.html"));
+
+ EXPECT_TRUE(ready.WaitUntilSatisfied());
+
+ DVLOG(1) << "push_canary app done loading";
+
+ StartRunningTest();
+
+ EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
+
+ LOG(INFO) << "Exiting Push Messaging Canary test";
+}
+
+} // namespace extensions
diff --git a/chrome/browser/extensions/api/push_messaging/sync_setup_helper.cc b/chrome/browser/extensions/api/push_messaging/sync_setup_helper.cc
new file mode 100644
index 0000000..4ca347f
--- /dev/null
+++ b/chrome/browser/extensions/api/push_messaging/sync_setup_helper.cc
@@ -0,0 +1,92 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/extensions/api/push_messaging/sync_setup_helper.h"
+
+#include <vector>
+
+#include "base/file_util.h"
+#include "base/string_util.h"
+#include "chrome/browser/bookmarks/bookmark_model_factory.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/history/history_service_factory.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_manager.h"
+#include "chrome/browser/search_engines/template_url_service_factory.h"
+#include "chrome/browser/sync/profile_sync_service_factory.h"
+#include "chrome/browser/sync/profile_sync_service_harness.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/common/chrome_paths.h"
+#include "chrome/test/base/ui_test_utils.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace extensions {
+
+SyncSetupHelper::SyncSetupHelper() {}
+
+SyncSetupHelper::~SyncSetupHelper() {}
+
+// Initialize sync clients and profiles for the case where we already
+// have some valid sync data we wish to keep.
+bool SyncSetupHelper::InitializeSync(Profile* profile) {
+ profile_ = profile;
+ client_.reset(new ProfileSyncServiceHarness(profile_, username_, password_));
+
+ // Hook up the sync listener.
+ if (!client_->InitializeSync()) {
+ LOG(ERROR) << "InitializeSync() failed.";
+ return false;
+ }
+
+ // If the data is not already synced, setup sync.
+ if (!client_->IsDataSynced()) {
+ client_->SetupSync();
+ }
+
+ DVLOG(1) << "InitializeSync awaiting quiescence";
+
+ // Because clients may modify sync data as part of startup (for example local
+ // session-releated data is rewritten), we need to ensure all startup-based
+ // changes have propagated between the clients.
+ // This could take several seconds.
+ AwaitQuiescence();
+
+ DVLOG(1) << "InitializeSync reached quiescence";
+
+ return true;
+}
+
+// Read the sync signin credentials from a file on the machine.
+bool SyncSetupHelper::ReadPasswordFile(const base::FilePath& password_file) {
+ std::string file_contents;
+ bool success = file_util::ReadFileToString(password_file, &file_contents);
+ EXPECT_TRUE(success)
+ << "Password file \""
+ << password_file.value() << "\" does not exist.";
+ if (!success)
+ return false;
+
+ std::vector<std::string> tokens;
+ std::string delimiters = "\r\n";
+ Tokenize(file_contents, delimiters, &tokens);
+ EXPECT_EQ(5U, tokens.size()) << "Password file \""
+ << password_file.value()
+ << "\" must contain exactly five lines of text.";
+ if (5U != tokens.size())
+ return false;
+ username_ = tokens[0];
+ password_ = tokens[1];
+ client_id_ = tokens[2];
+ client_secret_ = tokens[3];
+ refresh_token_ = tokens[4];
+ return true;
+}
+
+bool SyncSetupHelper::AwaitQuiescence() {
+ std::vector<ProfileSyncServiceHarness*> clients;
+ clients.push_back(client_.get());
+ return ProfileSyncServiceHarness::AwaitQuiescence(clients);
+}
+
+} // namespace extensions
diff --git a/chrome/browser/extensions/api/push_messaging/sync_setup_helper.h b/chrome/browser/extensions/api/push_messaging/sync_setup_helper.h
new file mode 100644
index 0000000..9ea5709
--- /dev/null
+++ b/chrome/browser/extensions/api/push_messaging/sync_setup_helper.h
@@ -0,0 +1,79 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_EXTENSIONS_API_PUSH_MESSAGING_SYNC_SETUP_HELPER_H_
+#define CHROME_BROWSER_EXTENSIONS_API_PUSH_MESSAGING_SYNC_SETUP_HELPER_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "base/file_util.h"
+#include "base/memory/scoped_ptr.h"
+#include "net/base/mock_host_resolver.h"
+
+class Profile;
+class ProfileSyncServiceHarness;
+
+namespace extensions {
+
+class SyncSetupHelper {
+ public:
+ SyncSetupHelper();
+
+ ~SyncSetupHelper();
+
+ // Initialize sync clients and profiles for the case where we already
+ // have some valid sync data we wish to keep.
+ bool InitializeSync(Profile* profile);
+
+ // Helper method used to read GAIA credentials from a local password file.
+ // Note: The password file must be a plain text file with two lines.
+ // The username is on the first line and the password is on the second line.
+ bool ReadPasswordFile(const base::FilePath& passwordFile);
+
+ const std::string& client_id() const { return client_id_; }
+ const std::string& client_secret() const { return client_secret_; }
+ const std::string& refresh_token() const { return refresh_token_; }
+
+ private:
+ // Block until all sync clients have completed their mutual sync cycles.
+ // Return true if a quiescent state was successfully reached.
+ bool AwaitQuiescence();
+
+ // GAIA account used by the test case.
+ std::string username_;
+
+ // GAIA password used by the test case.
+ std::string password_;
+
+ // GAIA client id for making the API call to push messaging.
+ std::string client_id_;
+
+ // GAIA client secret for making the API call to push messaging.
+ std::string client_secret_;
+
+ // GAIA refresh token for making the API call to push messaging.
+ std::string refresh_token_;
+
+ // The sync profile used by a test. The profile is owned by the
+ // ProfileManager.
+ Profile* profile_;
+
+ // Sync client used by a test. A sync client is associated with
+ // a sync profile, and implements methods that sync the contents of the
+ // profile with the server.
+ scoped_ptr<ProfileSyncServiceHarness> client_;
+
+ // This test needs to make live DNS requests for access to
+ // GAIA and sync server URLs under google.com. We use a scoped version
+ // to override the default resolver while the test is active.
+ scoped_ptr<net::ScopedDefaultHostResolverProc> mock_host_resolver_override_;
+
+ DISALLOW_COPY_AND_ASSIGN(SyncSetupHelper);
+};
+
+} // namespace extensions
+
+#endif // CHROME_BROWSER_EXTENSIONS_API_PUSH_MESSAGING_SYNC_SETUP_HELPER_H_
diff --git a/chrome/browser/sync/profile_sync_service_harness.cc b/chrome/browser/sync/profile_sync_service_harness.cc
index 7b5d337..6e74f58 100644
--- a/chrome/browser/sync/profile_sync_service_harness.cc
+++ b/chrome/browser/sync/profile_sync_service_harness.cc
@@ -162,17 +162,8 @@ bool ProfileSyncServiceHarness::SetupSync() {
bool ProfileSyncServiceHarness::SetupSync(
syncer::ModelTypeSet synced_datatypes) {
- // Initialize the sync client's profile sync service object.
- service_ =
- ProfileSyncServiceFactory::GetInstance()->GetForProfile(profile_);
- if (service_ == NULL) {
- LOG(ERROR) << "SetupSync(): service_ is null.";
+ if (!InitializeSync())
return false;
- }
-
- // Subscribe sync client to notifications from the profile sync service.
- if (!service_->HasObserver(this))
- service_->AddObserver(this);
// Tell the sync service that setup is in progress so we don't start syncing
// until we've finished configuration.
@@ -202,6 +193,8 @@ bool ProfileSyncServiceHarness::SetupSync(
return false;
}
+ DVLOG(2) << "Done waiting for sync backend";
+
// Choose the datatypes to be synced. If all datatypes are to be synced,
// set sync_everything to true; otherwise, set it to false.
bool sync_everything =
@@ -230,8 +223,10 @@ bool ProfileSyncServiceHarness::SetupSync(
}
// Wait for initial sync cycle to be completed.
- DCHECK_EQ(wait_state_, WAITING_FOR_INITIAL_SYNC);
- if (!AwaitStatusChangeWithTimeout(kLiveSyncOperationTimeoutMs,
+ DCHECK(wait_state_ == WAITING_FOR_INITIAL_SYNC ||
+ wait_state_ == FULLY_SYNCED);
+ if (wait_state_ != FULLY_SYNCED &&
+ !AwaitStatusChangeWithTimeout(kLiveSyncOperationTimeoutMs,
"Waiting for initial sync cycle to complete.")) {
LOG(ERROR) << "Initial sync cycle did not complete after "
<< kLiveSyncOperationTimeoutMs / 1000
@@ -258,14 +253,33 @@ bool ProfileSyncServiceHarness::SetupSync(
return true;
}
+bool ProfileSyncServiceHarness::InitializeSync() {
+ // Initialize the sync client's profile sync service object.
+ service_ =
+ ProfileSyncServiceFactory::GetInstance()->GetForProfile(profile_);
+ if (service_ == NULL) {
+ LOG(ERROR) << "InitializeSync(): service_ is null.";
+ return false;
+ }
+
+ // Subscribe sync client to notifications from the profile sync service.
+ if (!service_->HasObserver(this))
+ service_->AddObserver(this);
+
+ return true;
+}
+
bool ProfileSyncServiceHarness::TryListeningToMigrationEvents() {
browser_sync::BackendMigrator* migrator =
service_->GetBackendMigratorForTest();
- if (migrator && !migrator->HasMigrationObserver(this)) {
+
+ if (!migrator)
+ return false;
+
+ if (!migrator->HasMigrationObserver(this)) {
migrator->AddMigrationObserver(this);
- return true;
}
- return false;
+ return true;
}
void ProfileSyncServiceHarness::SignalStateCompleteWithNextState(
diff --git a/chrome/browser/sync/profile_sync_service_harness.h b/chrome/browser/sync/profile_sync_service_harness.h
index 83989a3..f6b55a3 100644
--- a/chrome/browser/sync/profile_sync_service_harness.h
+++ b/chrome/browser/sync/profile_sync_service_harness.h
@@ -60,6 +60,12 @@ class ProfileSyncServiceHarness
// in |synced_datatypes|.
bool SetupSync(syncer::ModelTypeSet synced_datatypes);
+ // Prepare for setting up to sync, but without clearing the existing items.
+ bool InitializeSync();
+
+ // Returns true if the sync client has no unsynced items.
+ bool IsDataSynced();
+
// ProfileSyncServiceObserver implementation.
virtual void OnStateChanged() OVERRIDE;
@@ -294,9 +300,6 @@ class ProfileSyncServiceHarness
bool IsDataSyncedImpl(
const syncer::sessions::SyncSessionSnapshot& snapshot);
- // Returns true if the sync client has no unsynced items.
- bool IsDataSynced();
-
// Returns true if the sync client has no unsynced items and its progress
// markers are believed to be up to date.
//