diff options
author | cmasone@google.com <cmasone@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-12-09 03:14:40 +0000 |
---|---|---|
committer | cmasone@google.com <cmasone@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-12-09 03:14:40 +0000 |
commit | b6270acaa846c4a3b767b527354fbd875680118f (patch) | |
tree | 2b6cfc6732b10ea0400cbdb82231567a4ec53619 /chrome/browser/chromeos | |
parent | 309b764b38f67d23f8b12488e6d1f542ca19b13e (diff) | |
download | chromium_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.cc | 14 | ||||
-rw-r--r-- | chrome/browser/chromeos/image_background.h | 39 | ||||
-rw-r--r-- | chrome/browser/chromeos/login_manager_view.cc | 228 | ||||
-rw-r--r-- | chrome/browser/chromeos/login_manager_view.h | 75 | ||||
-rw-r--r-- | chrome/browser/chromeos/pipe_reader.h | 5 | ||||
-rw-r--r-- | chrome/browser/chromeos/pipe_reader_unittest.cc | 19 |
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); |