summaryrefslogtreecommitdiffstats
path: root/chrome/browser
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser')
-rw-r--r--chrome/browser/browser_main.cc8
-rw-r--r--chrome/browser/chromeos/external_cookie_handler.cc71
-rw-r--r--chrome/browser/chromeos/external_cookie_handler.h49
-rw-r--r--chrome/browser/chromeos/external_cookie_handler_unittest.cc152
-rw-r--r--chrome/browser/chromeos/pipe_reader.cc17
-rw-r--r--chrome/browser/chromeos/pipe_reader.h50
-rw-r--r--chrome/browser/chromeos/pipe_reader_unittest.cc97
7 files changed, 444 insertions, 0 deletions
diff --git a/chrome/browser/browser_main.cc b/chrome/browser/browser_main.cc
index bb3d1c3..9b71bde 100644
--- a/chrome/browser/browser_main.cc
+++ b/chrome/browser/browser_main.cc
@@ -117,6 +117,10 @@
#include "views/focus/accelerator_handler.h"
#endif
+#if defined(OS_CHROMEOS)
+#include "chrome/browser/chromeos/external_cookie_handler.h"
+#endif
+
namespace Platform {
void WillInitializeMainMessageLoop(const MainFunctionParams& parameters);
@@ -793,6 +797,10 @@ int BrowserMain(const MainFunctionParams& parameters) {
if (parsed_command_line.HasSwitch(switches::kEnableWebResources))
profile->InitWebResources();
+#if defined(OS_CHROMEOS)
+ ExternalCookieHandler::GetCookies(parsed_command_line, profile);
+#endif
+
// Stat the directory with the inspector's files so that we can know if we
// should display the entry in the context menu or not.
browser_process->CheckForInspectorFiles();
diff --git a/chrome/browser/chromeos/external_cookie_handler.cc b/chrome/browser/chromeos/external_cookie_handler.cc
new file mode 100644
index 0000000..e578395
--- /dev/null
+++ b/chrome/browser/chromeos/external_cookie_handler.cc
@@ -0,0 +1,71 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/external_cookie_handler.h"
+
+#include "base/command_line.h"
+#include "chrome/browser/chromeos/pipe_reader.h"
+#include "chrome/browser/profile.h"
+#include "chrome/common/chrome_switches.h"
+#include "googleurl/src/gurl.h"
+#include "net/base/cookie_store.h"
+#include "net/url_request/url_request_context.h"
+
+void ExternalCookieHandler::GetCookies(const CommandLine& parsed_command_line,
+ Profile* profile) {
+ // If there are Google External SSO cookies, add them to the cookie store.
+ if (parsed_command_line.HasSwitch(switches::kCookiePipe)) {
+ std::string pipe_name =
+ WideToASCII(parsed_command_line.GetSwitchValue(switches::kCookiePipe));
+ ExternalCookieHandler cookie_handler(new PipeReader(pipe_name));
+ cookie_handler.HandleCookies(
+ profile->GetRequestContext()->cookie_store());
+ }
+}
+
+// static
+const char ExternalCookieHandler::kGoogleAccountsUrl[] =
+ "https://www.google.com/a/google.com/acs";
+
+const int kChunkSize = 256;
+
+// Reads up to a newline, or the end of the data, in increments of |chunk|
+std::string ExternalCookieHandler::ReadLine(int chunk) {
+ std::string cookie_line = reader_->Read(chunk);
+
+ // As long as it's not an empty line...
+ if (!cookie_line.empty()) {
+ // and there's no newline at the end...
+ while ('\n' != cookie_line[cookie_line.length() - 1]) {
+ // try to pull more data...
+ std::string piece = reader_->Read(chunk);
+ if (piece.empty()) // only stop if there's none left.
+ break;
+ else
+ cookie_line.append(piece); // otherwise, append and keep going.
+ }
+ }
+
+ return cookie_line;
+}
+
+bool ExternalCookieHandler::HandleCookies(net::CookieStore *cookie_store) {
+ DCHECK(cookie_store);
+ if (NULL != reader_.get()) {
+ GURL url(ExternalCookieHandler::kGoogleAccountsUrl);
+ net::CookieOptions options;
+ options.set_include_httponly();
+
+ // Each line we get is a cookie. Grab up to a newline, then put
+ // it in to the cookie jar.
+ std::string cookie_line = ReadLine(kChunkSize);
+ while (!cookie_line.empty()) {
+ if (!cookie_store->SetCookieWithOptions(url, cookie_line, options))
+ return false;
+ cookie_line = ReadLine(kChunkSize);
+ }
+ return true;
+ }
+ return false;
+}
diff --git a/chrome/browser/chromeos/external_cookie_handler.h b/chrome/browser/chromeos/external_cookie_handler.h
new file mode 100644
index 0000000..2886756
--- /dev/null
+++ b/chrome/browser/chromeos/external_cookie_handler.h
@@ -0,0 +1,49 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CHROMEOS_EXTERNAL_COOKIE_HANDLER_H_
+#define CHROME_BROWSER_CHROMEOS_EXTERNAL_COOKIE_HANDLER_H_
+
+#include <string>
+
+#include "base/scoped_ptr.h"
+#include "chrome/browser/chromeos/pipe_reader.h"
+
+// Single sign on cookies for Google can be passed in over a
+// pipe. If they've been sent, this reads them and adds them to the
+// cookie store as session cookies.
+
+class CommandLine;
+class Profile;
+namespace net {
+class CookieStore;
+}
+
+class ExternalCookieHandler {
+ public:
+ // Takes ownsership of |reader|.
+ explicit ExternalCookieHandler(PipeReader *reader) : reader_(reader) {}
+ virtual ~ExternalCookieHandler() {}
+
+ // Given a pipe to read cookies from, reads and adds them to |cookie_store|.
+ virtual bool HandleCookies(net::CookieStore *cookie_store);
+
+ // Checks |parsed_command_line| for the --cookie-pipe; if found, reads
+ // cookies from the pipe and adds them to the cookie store found in |profile|.
+ static void GetCookies(const CommandLine& parsed_command_line,
+ Profile* profile);
+
+ // The url with which we associate the read-in cookies.
+ static const char kGoogleAccountsUrl[];
+
+ private:
+ // Reads up to a newline, or the end of the data, in increments of |chunk|.
+ std::string ReadLine(int chunk);
+
+ scoped_ptr<PipeReader> reader_;
+
+ DISALLOW_COPY_AND_ASSIGN(ExternalCookieHandler);
+};
+
+#endif // CHROME_BROWSER_CHROMEOS_EXTERNAL_COOKIE_HANDLER_H_
diff --git a/chrome/browser/chromeos/external_cookie_handler_unittest.cc b/chrome/browser/chromeos/external_cookie_handler_unittest.cc
new file mode 100644
index 0000000..014f52c
--- /dev/null
+++ b/chrome/browser/chromeos/external_cookie_handler_unittest.cc
@@ -0,0 +1,152 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/external_cookie_handler.h"
+
+#include <set>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/time.h"
+#include "googleurl/src/gurl.h"
+#include "net/base/cookie_options.h"
+#include "net/base/cookie_store.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+typedef testing::Test ExternalCookieHandlerTest;
+
+static const std::string cookie1 = "coookie1\n";
+static const std::string cookie2 = "coookie2\n";
+static const std::string cookie3 = "coookie3";
+
+class MockCookieStore : public net::CookieStore {
+ public:
+ MockCookieStore() : expected_url_(ExternalCookieHandler::kGoogleAccountsUrl) {
+ cookies_.insert(cookie1);
+ cookies_.insert(cookie2);
+ cookies_.insert(cookie3);
+ }
+ virtual ~MockCookieStore() {}
+
+ virtual bool SetCookie(const GURL& url, const std::string& cookie_line) {
+ EXPECT_TRUE(false);
+ return true;
+ }
+ virtual bool SetCookieWithOptions(const GURL& url,
+ const std::string& cookie_line,
+ const net::CookieOptions& options) {
+ EXPECT_FALSE(options.exclude_httponly());
+ EXPECT_EQ(expected_url_, url);
+ std::set<std::string>::iterator it;
+ it = cookies_.find(cookie_line);
+ bool has_cookie = cookies_.end() != it;
+ if (has_cookie)
+ cookies_.erase(it);
+ return has_cookie;
+ }
+
+ virtual bool SetCookieWithCreationTime(const GURL& url,
+ const std::string& cookie_line,
+ const base::Time& creation_time) {
+ EXPECT_TRUE(false);
+ return true;
+ }
+ virtual bool SetCookieWithCreationTimeWithOptions(
+ const GURL& url,
+ const std::string& cookie_line,
+ const base::Time& creation_time,
+ const net::CookieOptions& options) {
+ EXPECT_TRUE(false);
+ return true;
+ }
+
+ virtual void SetCookies(const GURL& url,
+ const std::vector<std::string>& cookies) {
+ EXPECT_TRUE(false);
+ }
+ virtual void SetCookiesWithOptions(const GURL& url,
+ const std::vector<std::string>& cookies,
+ const net::CookieOptions& options) {
+ EXPECT_TRUE(false);
+ }
+
+ virtual std::string GetCookies(const GURL& url) {
+ EXPECT_TRUE(false);
+ return std::string();
+ }
+ virtual std::string GetCookiesWithOptions(const GURL& url,
+ const net::CookieOptions& options) {
+ EXPECT_TRUE(false);
+ return std::string();
+ }
+
+ private:
+ std::set<std::string> cookies_;
+ const GURL expected_url_;
+
+ DISALLOW_EVIL_CONSTRUCTORS(MockCookieStore);
+};
+
+
+TEST_F(ExternalCookieHandlerTest, MockCookieStoreSanityTest) {
+ GURL url(ExternalCookieHandler::kGoogleAccountsUrl);
+ MockCookieStore cookie_store;
+ net::CookieOptions options;
+ options.set_include_httponly();
+ EXPECT_TRUE(cookie_store.SetCookieWithOptions(url, cookie1, options));
+ EXPECT_TRUE(cookie_store.SetCookieWithOptions(url, cookie2, options));
+ EXPECT_TRUE(cookie_store.SetCookieWithOptions(url, cookie3, options));
+ EXPECT_FALSE(cookie_store.SetCookieWithOptions(url, cookie1, options));
+ EXPECT_FALSE(cookie_store.SetCookieWithOptions(url, cookie2, options));
+ EXPECT_FALSE(cookie_store.SetCookieWithOptions(url, cookie3, options));
+}
+
+class MockReader : public PipeReader {
+ public:
+ explicit MockReader(const std::vector<std::string>& cookies)
+ : data_(cookies) {
+ }
+
+ std::string Read(const uint32 bytes_to_read) {
+ std::string to_return;
+ if (!data_.empty()) {
+ to_return = data_.back();
+ data_.pop_back();
+ }
+ return to_return;
+ }
+ private:
+ std::vector<std::string> data_;
+};
+
+TEST_F(ExternalCookieHandlerTest, SuccessfulReadTest) {
+ GURL url(ExternalCookieHandler::kGoogleAccountsUrl);
+
+ MockCookieStore cookie_store;
+
+ std::vector<std::string> cookies;
+ cookies.push_back(cookie3);
+ cookies.push_back(cookie2);
+ cookies.push_back(cookie1);
+ MockReader *reader = new MockReader(cookies);
+
+ ExternalCookieHandler handler(reader); // takes ownership.
+ EXPECT_TRUE(handler.HandleCookies(&cookie_store));
+}
+
+TEST_F(ExternalCookieHandlerTest, SuccessfulSlowReadTest) {
+ GURL url(ExternalCookieHandler::kGoogleAccountsUrl);
+
+ MockCookieStore cookie_store;
+
+ std::vector<std::string> cookies;
+ cookies.push_back(cookie3);
+ cookies.push_back(cookie2.substr(2));
+ cookies.push_back(cookie2.substr(0, 2));
+ cookies.push_back(cookie1);
+ MockReader *reader = new MockReader(cookies);
+
+ ExternalCookieHandler handler(reader); // takes ownership.
+ EXPECT_TRUE(handler.HandleCookies(&cookie_store));
+}
diff --git a/chrome/browser/chromeos/pipe_reader.cc b/chrome/browser/chromeos/pipe_reader.cc
new file mode 100644
index 0000000..16b9f06
--- /dev/null
+++ b/chrome/browser/chromeos/pipe_reader.cc
@@ -0,0 +1,17 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/pipe_reader.h"
+
+#include "base/scoped_ptr.h"
+
+std::string PipeReader::Read(const uint32 bytes_to_read) {
+ scoped_array<char> buffer(new char[bytes_to_read]);
+ if (pipe_ || (pipe_ = fopen(pipe_name_.c_str(), "r"))) {
+ const char* to_return = fgets(buffer.get(), bytes_to_read, pipe_);
+ if (to_return)
+ return to_return; // auto-coerced to a std::string.
+ }
+ return std::string();
+}
diff --git a/chrome/browser/chromeos/pipe_reader.h b/chrome/browser/chromeos/pipe_reader.h
new file mode 100644
index 0000000..d2a3bf2
--- /dev/null
+++ b/chrome/browser/chromeos/pipe_reader.h
@@ -0,0 +1,50 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CHROMEOS_PIPE_READER_H_
+#define CHROME_BROWSER_CHROMEOS_PIPE_READER_H_
+
+#include <fcntl.h>
+#include <string>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "base/basictypes.h"
+
+// Given a named pipe, this class reads data from it and returns it as a string.
+// Currently, we are sending login cookies from the Chrome OS login manager to
+// Chrome over a named Unix pipe. We want to replace this with DBus, but
+// would like to create a DBus wrapper library to use throughout Chrome OS
+// first. This stopgap lets us get the infrastructure for passing credentials
+// to Chrome in place, which will help clean up login jankiness, and also
+// refactor our code as we await the DBus stuff.
+// TODO(cmasone): get rid of this code and replace with DBus.
+
+class PipeReader {
+ public:
+ explicit PipeReader(const std::string& pipe_name)
+ : pipe_(NULL),
+ pipe_name_(pipe_name) {
+ }
+ virtual ~PipeReader() {
+ if (pipe_)
+ fclose(pipe_);
+ }
+
+ // Reads data from the pipe up until either a '\n' or |bytes_to_read| bytes.
+ virtual std::string Read(const uint32 bytes_to_read);
+
+ protected:
+ // For testing.
+ PipeReader() : pipe_(NULL) {}
+
+ private:
+ FILE *pipe_;
+ std::string pipe_name_;
+
+ DISALLOW_COPY_AND_ASSIGN(PipeReader);
+};
+
+#endif // CHROME_BROWSER_CHROMEOS_PIPE_READER_H_
diff --git a/chrome/browser/chromeos/pipe_reader_unittest.cc b/chrome/browser/chromeos/pipe_reader_unittest.cc
new file mode 100644
index 0000000..6d674dd
--- /dev/null
+++ b/chrome/browser/chromeos/pipe_reader_unittest.cc
@@ -0,0 +1,97 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/pipe_reader.h"
+
+#include <errno.h>
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+typedef testing::Test PipeReaderTest;
+
+TEST_F(PipeReaderTest, SuccessfulReadTest) {
+ std::string pipe_name("/tmp/MYFIFO");
+ /* Create the FIFO if it does not exist */
+ umask(0);
+ mknod(pipe_name.c_str(), S_IFIFO|0666, 0);
+ const char line[] = "foo";
+
+ pid_t pID = fork();
+ if (pID == 0) {
+ int pipe = open(pipe_name.c_str(), O_WRONLY);
+ EXPECT_NE(pipe, -1) << strerror(errno);
+ write(pipe, line, strlen(line));
+ close(pipe);
+ exit(1);
+ } else {
+ PipeReader reader(pipe_name);
+ // asking for more should still just return the amount that was written.
+ EXPECT_EQ(line, reader.Read(5 * strlen(line)));
+ }
+}
+
+TEST_F(PipeReaderTest, SuccessfulMultiLineReadTest) {
+ std::string pipe_name("/tmp/TESTFIFO");
+ /* Create the FIFO if it does not exist */
+ umask(0);
+ mknod(pipe_name.c_str(), S_IFIFO|0666, 0);
+ const char foo[] = "foo";
+ const char boo[] = "boo";
+ std::string line(foo);
+ line.append("\n");
+ line.append(boo);
+ line.append("\n");
+
+ pid_t pID = fork();
+ if (pID == 0) {
+ int pipe = open(pipe_name.c_str(), O_WRONLY);
+ EXPECT_NE(pipe, -1) << strerror(errno);
+ write(pipe, line.c_str(), line.length());
+ close(pipe);
+ exit(1);
+ } else {
+ PipeReader reader(pipe_name);
+ // asking for more should still just return the amount that was written.
+ std::string my_foo = reader.Read(5 * line.length());
+ EXPECT_EQ(my_foo[my_foo.length() - 1], '\n');
+ my_foo.resize(my_foo.length() - 1);
+ EXPECT_EQ(my_foo, foo);
+
+ std::string my_boo = reader.Read(5 * line.length());
+ EXPECT_EQ(my_boo[my_boo.length() - 1], '\n');
+ my_boo.resize(my_boo.length() - 1);
+ EXPECT_EQ(my_boo, boo);
+ }
+}
+
+TEST_F(PipeReaderTest, SuccessfulMultiLineReadNoEndingNewlineTest) {
+ std::string pipe_name("/tmp/TESTFIFO");
+ /* Create the FIFO if it does not exist */
+ umask(0);
+ mknod(pipe_name.c_str(), S_IFIFO|0666, 0);
+ const char foo[] = "foo";
+ const char boo[] = "boo";
+ std::string line(foo);
+ line.append("\n");
+ line.append(boo);
+
+ pid_t pID = fork();
+ if (pID == 0) {
+ int pipe = open(pipe_name.c_str(), O_WRONLY);
+ EXPECT_NE(pipe, -1) << strerror(errno);
+ write(pipe, line.c_str(), line.length());
+ close(pipe);
+ exit(1);
+ } else {
+ PipeReader reader(pipe_name);
+ // asking for more should still just return the amount that was written.
+ std::string my_foo = reader.Read(5 * line.length());
+ EXPECT_EQ(my_foo[my_foo.length() - 1], '\n');
+ my_foo.resize(my_foo.length() - 1);
+ EXPECT_EQ(my_foo, foo);
+
+ std::string my_boo = reader.Read(5 * line.length());
+ EXPECT_EQ(my_boo, boo);
+ }
+}