summaryrefslogtreecommitdiffstats
path: root/chrome/browser/chromeos
diff options
context:
space:
mode:
authorcmasone@google.com <cmasone@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-12-09 03:14:40 +0000
committercmasone@google.com <cmasone@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-12-09 03:14:40 +0000
commitb6270acaa846c4a3b767b527354fbd875680118f (patch)
tree2b6cfc6732b10ea0400cbdb82231567a4ec53619 /chrome/browser/chromeos
parent309b764b38f67d23f8b12488e6d1f542ca19b13e (diff)
downloadchromium_src-b6270acaa846c4a3b767b527354fbd875680118f.zip
chromium_src-b6270acaa846c4a3b767b527354fbd875680118f.tar.gz
chromium_src-b6270acaa846c4a3b767b527354fbd875680118f.tar.bz2
Views-based login window for Chrome OS. Doesn't yet actually do anything
Review URL: http://codereview.chromium.org/449023 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@34134 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/chromeos')
-rw-r--r--chrome/browser/chromeos/external_cookie_handler.cc14
-rw-r--r--chrome/browser/chromeos/image_background.h39
-rw-r--r--chrome/browser/chromeos/login_manager_view.cc228
-rw-r--r--chrome/browser/chromeos/login_manager_view.h75
-rw-r--r--chrome/browser/chromeos/pipe_reader.h5
-rw-r--r--chrome/browser/chromeos/pipe_reader_unittest.cc19
6 files changed, 364 insertions, 16 deletions
diff --git a/chrome/browser/chromeos/external_cookie_handler.cc b/chrome/browser/chromeos/external_cookie_handler.cc
index a3cf9d5..525ed80 100644
--- a/chrome/browser/chromeos/external_cookie_handler.cc
+++ b/chrome/browser/chromeos/external_cookie_handler.cc
@@ -5,6 +5,7 @@
#include "chrome/browser/chromeos/external_cookie_handler.h"
#include "base/command_line.h"
+#include "base/file_util.h"
#include "chrome/browser/chromeos/pipe_reader.h"
#include "chrome/browser/net/url_request_context_getter.h"
#include "chrome/browser/profile.h"
@@ -19,11 +20,14 @@ 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 =
- parsed_command_line.GetSwitchValueASCII(switches::kCookiePipe);
- ExternalCookieHandler cookie_handler(new PipeReader(pipe_name));
- cookie_handler.HandleCookies(
- profile->GetRequestContext()->GetCookieStore());
+ FilePath cookie_pipe =
+ parsed_command_line.GetSwitchValuePath(switches::kCookiePipe);
+ if (file_util::PathExists(cookie_pipe)) {
+ ExternalCookieHandler cookie_handler(new PipeReader(cookie_pipe));
+ cookie_handler.HandleCookies(
+ profile->GetRequestContext()->GetCookieStore());
+ file_util::Delete(cookie_pipe, false);
+ }
}
}
diff --git a/chrome/browser/chromeos/image_background.h b/chrome/browser/chromeos/image_background.h
new file mode 100644
index 0000000..6dca849
--- /dev/null
+++ b/chrome/browser/chromeos/image_background.h
@@ -0,0 +1,39 @@
+// 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_IMAGE_BACKGROUND_H_
+#define CHROME_BROWSER_CHROMEOS_IMAGE_BACKGROUND_H_
+
+#include "base/basictypes.h"
+#include "views/background.h"
+#include "app/gfx/canvas.h"
+
+namespace gfx {
+class Canvas;
+}
+
+namespace views {
+
+class ImageBackground : public Background {
+ public:
+ explicit ImageBackground(GdkPixbuf* background_image)
+ : background_image_(background_image) {
+ }
+
+ virtual ~ImageBackground() {}
+
+ void Paint(gfx::Canvas* canvas, View* view) const {
+ canvas->DrawGdkPixbuf(background_image_, 0, 0);
+ }
+ private:
+ // Background image that is drawn by this background.
+ // This class does _not_ take ownership of the image.
+ GdkPixbuf* background_image_;
+ DISALLOW_COPY_AND_ASSIGN(ImageBackground);
+};
+
+} // namespace views
+
+#endif // CHROME_BROWSER_CHROMEOS_IMAGE_BACKGROUND_H_
+
diff --git a/chrome/browser/chromeos/login_manager_view.cc b/chrome/browser/chromeos/login_manager_view.cc
new file mode 100644
index 0000000..2afaaee
--- /dev/null
+++ b/chrome/browser/chromeos/login_manager_view.cc
@@ -0,0 +1,228 @@
+// 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/login_manager_view.h"
+
+#include "app/resource_bundle.h"
+#include "base/keyboard_codes.h"
+#include "base/logging.h"
+#include "base/process_util.h"
+#include "chrome/browser/chromeos/image_background.h"
+#include "chrome/common/chrome_switches.h"
+#include "grit/theme_resources.h"
+#include "views/controls/label.h"
+#include "views/focus/accelerator_handler.h"
+#include "views/grid_layout.h"
+#include "views/widget/widget.h"
+#include "views/window/window.h"
+
+using views::Background;
+using views::ColumnSet;
+using views::GridLayout;
+using views::Label;
+using views::Textfield;
+using views::View;
+using views::Widget;
+using views::Accelerator;
+
+const int kPanelY = 0;
+const int kUsernameY = 386;
+const int kPanelSpacing = 36;
+const int kTextfieldWidth = 286;
+const int kBottomPadding = 112;
+
+namespace browser {
+
+bool EmitLoginPromptReady() {
+ base::ProcessHandle handle;
+ std::vector<std::string> argv;
+ argv.push_back("/opt/google/chrome/emit-login-prompt-ready");
+ base::environment_vector no_env;
+ base::file_handle_mapping_vector no_files;
+ return base::LaunchApp(argv, no_env, no_files, false, &handle);
+}
+
+// Declared in browser_dialogs.h so that others don't need to depend on our .h.
+void ShowLoginManager() {
+ views::Window::CreateChromeWindow(NULL,
+ gfx::Rect(),
+ new LoginManagerView())->Show();
+ EmitLoginPromptReady();
+ bool old_state = MessageLoop::current()->NestableTasksAllowed();
+ MessageLoop::current()->SetNestableTasksAllowed(true);
+ MessageLoop::current()->Run();
+ MessageLoop::current()->SetNestableTasksAllowed(old_state);
+}
+} // namespace browser
+
+LoginManagerView::LoginManagerView() {
+ Init();
+}
+
+LoginManagerView::~LoginManagerView() {
+ MessageLoop::current()->Quit();
+}
+
+
+void LoginManagerView::Init() {
+ username_field_ = new views::Textfield;
+ password_field_ = new views::Textfield(views::Textfield::STYLE_PASSWORD);
+
+ // Creates the main window
+ BuildWindow();
+
+ // Controller to handle events from textfields
+ username_field_->SetController(this);
+ password_field_->SetController(this);
+}
+
+gfx::Size LoginManagerView::GetPreferredSize() {
+ return dialog_dimensions_;
+}
+
+
+void LoginManagerView::BuildWindow() {
+ ResourceBundle& rb = ResourceBundle::GetSharedInstance();
+ panel_pixbuf_ = rb.GetPixbufNamed(IDR_LOGIN_PANEL);
+ background_pixbuf_ = rb.GetPixbufNamed(IDR_LOGIN_BACKGROUND);
+
+ // --------------------- Get attributes of images -----------------------
+ dialog_dimensions_.SetSize(gdk_pixbuf_get_width(background_pixbuf_),
+ gdk_pixbuf_get_height(background_pixbuf_));
+
+ int panel_height = gdk_pixbuf_get_height(panel_pixbuf_);
+ int panel_width = gdk_pixbuf_get_width(panel_pixbuf_);
+
+ // ---------------------- Set up root View ------------------------------
+ set_background(new views::ImageBackground(background_pixbuf_));
+
+ // Set layout
+ GridLayout* layout = new GridLayout(this);
+ SetLayoutManager(layout);
+
+ ColumnSet* column_set = layout->AddColumnSet(0);
+ column_set->AddPaddingColumn(1, 0);
+ column_set->AddColumn(GridLayout::CENTER, GridLayout::FILL, 0,
+ GridLayout::FIXED, panel_width, panel_width);
+ column_set->AddPaddingColumn(1, 0);
+
+ // Row is resized with window (panel page)
+ layout->AddPaddingRow(0, kPanelY);
+
+ layout->StartRow(1, 0);
+ {
+ // Create login_prompt view
+ View* login_prompt = new View();
+ // TODO(cmasone): determine if it's more performant to do the background
+ // by creating an BackgroundPainter directly, like so:
+ // Background::CreateBackgroundPainter(true,
+ // Painter::CreateImagePainter(image, ...))
+ login_prompt->set_background(new views::ImageBackground(panel_pixbuf_));
+
+ // Set layout
+ GridLayout* prompt_layout = new GridLayout(login_prompt);
+ login_prompt->SetLayoutManager(prompt_layout);
+ ColumnSet* prompt_column_set = prompt_layout->AddColumnSet(0);
+ prompt_column_set->AddPaddingColumn(1, 0);
+ prompt_column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 0,
+ GridLayout::FIXED,
+ kTextfieldWidth, kTextfieldWidth);
+ prompt_column_set->AddPaddingColumn(1, 0);
+
+ prompt_layout->AddPaddingRow(0, kUsernameY);
+ prompt_layout->StartRow(1, 0);
+ prompt_layout->AddView(username_field_);
+ prompt_layout->AddPaddingRow(0, kPanelSpacing);
+ prompt_layout->StartRow(1, 0);
+ prompt_layout->AddView(password_field_);
+ prompt_layout->AddPaddingRow(0, kBottomPadding);
+
+ layout->AddView(login_prompt, 1, 1, GridLayout::CENTER, GridLayout::CENTER,
+ panel_width, panel_height);
+ }
+
+ layout->AddPaddingRow(1, 0);
+}
+
+views::View* LoginManagerView::GetContentsView() {
+ return this;
+}
+
+bool LoginManagerView::Authenticate(const std::string& username,
+ const std::string& password) {
+ base::ProcessHandle handle;
+ std::vector<std::string> argv;
+ // TODO(cmasone): we'll want this to be configurable.
+ argv.push_back("/opt/google/chrome/session");
+ argv.push_back(username);
+ argv.push_back(password);
+
+ base::environment_vector no_env;
+ base::file_handle_mapping_vector no_files;
+ base::LaunchApp(argv, no_env, no_files, false, &handle);
+ int child_exit_code;
+ return base::WaitForExitCode(handle, &child_exit_code) &&
+ child_exit_code == 0;
+}
+
+bool LoginManagerView::RunWindowManager(const std::string& username) {
+ base::ProcessHandle handle;
+ std::vector<std::string> argv;
+ // TODO(cmasone): we'll want this to be configurable.
+ argv.push_back("/etc/init.d/start_wm.sh");
+ base::environment_vector env;
+
+ // TODO(cmasone): This is a legacy way of communication the logged in user's
+ // email to xscreensaver. Figure out a better way.
+ env.push_back(std::pair<std::string, std::string>("CHROMEOS_USER", username));
+ base::file_handle_mapping_vector no_files;
+ return base::LaunchApp(argv, env, no_files, false, &handle);
+}
+
+void LoginManagerView::SetupSession(const std::string& username) {
+ if (window()) {
+ window()->Close();
+ }
+ if (username.find("@google.com") != std::string::npos) {
+ // This isn't thread-safe. However, the login window is specifically
+ // supposed to be run in a blocking fashion, before any other threads are
+ // created by the initial browser process.
+ CommandLine::ForCurrentProcess()->AppendSwitch(
+ switches::kAutoSSLClientAuth);
+ }
+ RunWindowManager(username);
+}
+
+bool LoginManagerView::HandleKeystroke(views::Textfield* s,
+ const views::Textfield::Keystroke& keystroke) {
+ if (keystroke.GetKeyboardCode() == base::VKEY_RETURN) {
+ // Disallow 0 size username | passwords
+ if (username_field_->text().length() == 0 ||
+ password_field_->text().length() == 0) {
+ // Return true so that processing ends
+ return true;
+ } else {
+ // Set up credentials to prepare for authentication. Also
+ // perform wstring to string conversion
+ std::string username, password;
+ username.assign(username_field_->text().begin(),
+ username_field_->text().end());
+ password.assign(password_field_->text().begin(),
+ password_field_->text().end());
+
+ if (!Authenticate(username, password)) {
+ return false;
+ }
+ // TODO(cmasone): something sensible if errors occur.
+
+ SetupSession(username);
+ // Return true so that processing ends
+ return true;
+ }
+ }
+ // Return false so that processing does not end
+ return false;
+}
+
+
diff --git a/chrome/browser/chromeos/login_manager_view.h b/chrome/browser/chromeos/login_manager_view.h
new file mode 100644
index 0000000..60d54f2
--- /dev/null
+++ b/chrome/browser/chromeos/login_manager_view.h
@@ -0,0 +1,75 @@
+// 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 <string>
+#include "views/accelerator.h"
+#include "views/controls/textfield/textfield.h"
+#include "views/view.h"
+#include "views/widget/widget_gtk.h"
+#include "views/window/dialog_delegate.h"
+
+#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_MANAGER_VIEW_H_
+#define CHROME_BROWSER_CHROMEOS_LOGIN_MANAGER_VIEW_H_
+
+class LoginManagerView : public views::View,
+ public views::WindowDelegate,
+ public views::Textfield::Controller {
+ public:
+ LoginManagerView();
+ virtual ~LoginManagerView();
+
+ // Initialize the controls on the dialog.
+ void Init();
+
+ // Overridden from views::View:
+ virtual gfx::Size GetPreferredSize();
+
+ // Overridden from views::WindowDelegate:
+ virtual views::View* GetContentsView();
+
+
+ // Overridden from views::Textfield::Controller
+ // Not thread-safe, by virtue of using SetupSession().
+ virtual bool HandleKeystroke(views::Textfield* sender,
+ const views::Textfield::Keystroke& keystroke);
+ // This method is called whenever the text in the field changes.
+ virtual void ContentsChanged(views::Textfield* sender,
+ const string16& new_contents) {}
+
+ // Creates all examples and start UI event loop.
+ private:
+ views::Textfield* username_field_;
+ views::Textfield* password_field_;
+
+ // The dialog dimensions.
+ gfx::Size dialog_dimensions_;
+
+ GdkPixbuf* background_pixbuf_;
+ GdkPixbuf* panel_pixbuf_;
+
+ // Helper functions to modularize class
+ void BuildWindow();
+
+ // Given a |username| and |password|, this method attempts to authenticate to
+ // the Google accounts servers.
+ // Returns true upon success and false on failure.
+ bool Authenticate(const std::string& username,
+ const std::string& password);
+
+ // Asynchronously launches the Chrome OS window manager.
+ bool RunWindowManager(const std::string& username);
+
+ // This is not threadsafe; as authentication is supposed to happen on the main
+ // thread before any other threads are started, so this should be ok.
+ // That said, the only reason we're not threadsafe right now is that we're
+ // munging the CommandLine::ForCurrentProcess() to enable auto-client-side-ssl
+ // for Googlers. So, if we can do that differently to make this thread-safe,
+ // that'd be A Good Thing (tm).
+ void SetupSession(const std::string& username);
+
+ DISALLOW_COPY_AND_ASSIGN(LoginManagerView);
+};
+
+#endif // CHROME_BROWSER_CHROMEOS_LOGIN_MANAGER_VIEW_H_
+
diff --git a/chrome/browser/chromeos/pipe_reader.h b/chrome/browser/chromeos/pipe_reader.h
index a2e552d..d89405d 100644
--- a/chrome/browser/chromeos/pipe_reader.h
+++ b/chrome/browser/chromeos/pipe_reader.h
@@ -14,6 +14,7 @@
#include <string>
#include "base/basictypes.h"
+#include "base/file_path.h"
namespace chromeos {
@@ -28,9 +29,9 @@ namespace chromeos {
class PipeReader {
public:
- explicit PipeReader(const std::string& pipe_name)
+ explicit PipeReader(const FilePath& pipe_name)
: pipe_(NULL),
- pipe_name_(pipe_name) {
+ pipe_name_(pipe_name.value()) {
}
virtual ~PipeReader() {
if (pipe_)
diff --git a/chrome/browser/chromeos/pipe_reader_unittest.cc b/chrome/browser/chromeos/pipe_reader_unittest.cc
index 619af7f..3b21798 100644
--- a/chrome/browser/chromeos/pipe_reader_unittest.cc
+++ b/chrome/browser/chromeos/pipe_reader_unittest.cc
@@ -6,6 +6,7 @@
#include <errno.h>
+#include "base/file_path.h"
#include "base/safe_strerror_posix.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -14,15 +15,15 @@ namespace chromeos {
typedef testing::Test PipeReaderTest;
TEST_F(PipeReaderTest, SuccessfulReadTest) {
- std::string pipe_name("/tmp/MYFIFO");
+ FilePath pipe_name("/tmp/MYFIFO");
/* Create the FIFO if it does not exist */
umask(0);
- mknod(pipe_name.c_str(), S_IFIFO|0666, 0);
+ mknod(pipe_name.value().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);
+ int pipe = open(pipe_name.value().c_str(), O_WRONLY);
EXPECT_NE(pipe, -1) << safe_strerror(errno);
write(pipe, line, strlen(line));
close(pipe);
@@ -35,10 +36,10 @@ TEST_F(PipeReaderTest, SuccessfulReadTest) {
}
TEST_F(PipeReaderTest, SuccessfulMultiLineReadTest) {
- std::string pipe_name("/tmp/TESTFIFO");
+ FilePath pipe_name("/tmp/TESTFIFO");
/* Create the FIFO if it does not exist */
umask(0);
- mknod(pipe_name.c_str(), S_IFIFO|0666, 0);
+ mknod(pipe_name.value().c_str(), S_IFIFO|0666, 0);
const char foo[] = "foo";
const char boo[] = "boo";
std::string line(foo);
@@ -48,7 +49,7 @@ TEST_F(PipeReaderTest, SuccessfulMultiLineReadTest) {
pid_t pID = fork();
if (pID == 0) {
- int pipe = open(pipe_name.c_str(), O_WRONLY);
+ int pipe = open(pipe_name.value().c_str(), O_WRONLY);
EXPECT_NE(pipe, -1) << safe_strerror(errno);
write(pipe, line.c_str(), line.length());
close(pipe);
@@ -69,10 +70,10 @@ TEST_F(PipeReaderTest, SuccessfulMultiLineReadTest) {
}
TEST_F(PipeReaderTest, SuccessfulMultiLineReadNoEndingNewlineTest) {
- std::string pipe_name("/tmp/TESTFIFO");
+ FilePath pipe_name("/tmp/TESTFIFO");
/* Create the FIFO if it does not exist */
umask(0);
- mknod(pipe_name.c_str(), S_IFIFO|0666, 0);
+ mknod(pipe_name.value().c_str(), S_IFIFO|0666, 0);
const char foo[] = "foo";
const char boo[] = "boo";
std::string line(foo);
@@ -81,7 +82,7 @@ TEST_F(PipeReaderTest, SuccessfulMultiLineReadNoEndingNewlineTest) {
pid_t pID = fork();
if (pID == 0) {
- int pipe = open(pipe_name.c_str(), O_WRONLY);
+ int pipe = open(pipe_name.value().c_str(), O_WRONLY);
EXPECT_NE(pipe, -1) << safe_strerror(errno);
write(pipe, line.c_str(), line.length());
close(pipe);