diff options
-rw-r--r-- | chrome/app/theme/chromium/login_background.png | bin | 0 -> 4531 bytes | |||
-rw-r--r-- | chrome/app/theme/chromium/login_panel.png | bin | 0 -> 5366 bytes | |||
-rw-r--r-- | chrome/app/theme/chromium/login_splash.png | bin | 0 -> 3829 bytes | |||
-rw-r--r-- | chrome/app/theme/theme_resources.grd | 2 | ||||
-rw-r--r-- | chrome/browser/browser_main.cc | 8 | ||||
-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 | ||||
-rw-r--r-- | chrome/browser/views/browser_dialogs.h | 5 | ||||
-rwxr-xr-x | chrome/chrome_browser.gypi | 4 | ||||
-rw-r--r-- | chrome/common/chrome_switches.cc | 3 | ||||
-rw-r--r-- | chrome/common/chrome_switches.h | 1 |
15 files changed, 387 insertions, 16 deletions
diff --git a/chrome/app/theme/chromium/login_background.png b/chrome/app/theme/chromium/login_background.png Binary files differnew file mode 100644 index 0000000..bad7114 --- /dev/null +++ b/chrome/app/theme/chromium/login_background.png diff --git a/chrome/app/theme/chromium/login_panel.png b/chrome/app/theme/chromium/login_panel.png Binary files differnew file mode 100644 index 0000000..ff7da57 --- /dev/null +++ b/chrome/app/theme/chromium/login_panel.png diff --git a/chrome/app/theme/chromium/login_splash.png b/chrome/app/theme/chromium/login_splash.png Binary files differnew file mode 100644 index 0000000..4f110bb --- /dev/null +++ b/chrome/app/theme/chromium/login_splash.png diff --git a/chrome/app/theme/theme_resources.grd b/chrome/app/theme/theme_resources.grd index 74dee3f..737f2cc 100644 --- a/chrome/app/theme/theme_resources.grd +++ b/chrome/app/theme/theme_resources.grd @@ -331,6 +331,8 @@ <include name="IDR_ABOUT_BACKGROUND" file="chromium/about_background.png" type="BINDATA" /> <include name="IDR_ABOUT_BACKGROUND_RTL" file="chromium/about_background_rtl.png" type="BINDATA" /> <include name="IDR_ABOUT_BACKGROUND_COLOR" file="chromium/about_background_color.png" type="BINDATA" /> + <include name="IDR_LOGIN_BACKGROUND" file="chromium/login_background.png" type="BINDATA" /> + <include name="IDR_LOGIN_PANEL" file="chromium/login_panel.png" type="BINDATA" /> <include name="IDR_PRODUCT_LOGO" file="chromium/product_logo.png" type="BINDATA" /> <include name="IDR_PRODUCT_LOGO_WHITE" file="chromium/product_logo_white.png" type="BINDATA" /> <include name="IDR_PRODUCT_LOGO_16" file="chromium/product_logo_16.png" type="BINDATA" /> diff --git a/chrome/browser/browser_main.cc b/chrome/browser/browser_main.cc index 766fb91..a8b1613 100644 --- a/chrome/browser/browser_main.cc +++ b/chrome/browser/browser_main.cc @@ -127,6 +127,7 @@ #include "chrome/browser/chromeos/cros_library.h" #include "chrome/browser/chromeos/external_cookie_handler.h" #include "chrome/browser/chromeos/external_metrics.h" +#include "chrome/browser/views/browser_dialogs.h" #endif namespace { @@ -569,6 +570,12 @@ int BrowserMain(const MainFunctionParams& parameters) { } #endif // !defined(OS_MACOSX) +#if defined(OS_CHROMEOS) + if (parsed_command_line.HasSwitch(switches::kLoginManager)) { + browser::ShowLoginManager(); + } +#endif // OS_CHROMEOS + #if defined(OS_LINUX) gtk_util::SetDefaultWindowIcon(); #endif @@ -694,6 +701,7 @@ int BrowserMain(const MainFunctionParams& parameters) { // Try to create/load the profile. ProfileManager* profile_manager = browser_process->profile_manager(); Profile* profile = profile_manager->GetDefaultProfile(user_data_dir); + #if defined(OS_WIN) if (!profile) { // Ideally, we should be able to run w/o access to disk. For now, we 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); diff --git a/chrome/browser/views/browser_dialogs.h b/chrome/browser/views/browser_dialogs.h index cdfc36a..5814da7 100644 --- a/chrome/browser/views/browser_dialogs.h +++ b/chrome/browser/views/browser_dialogs.h @@ -87,6 +87,11 @@ void ShowNewProfileDialog(); // Shows the Task Manager. void ShowTaskManager(); +#if defined(OS_CHROMEOS) +// Shows the Login Manager. +void ShowLoginManager(); +#endif + // Shows a dialog box that allows a search engine to be edited. |template_url| // is the search engine being edited. If it is NULL, then the dialog will add a // new search engine with the data the user supplies. |delegate| is an object diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index 8a88319..3c462be 100755 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -233,6 +233,8 @@ 'browser/chromeos/external_protocol_dialog.h', 'browser/chromeos/gview_request_interceptor.cc', 'browser/chromeos/gview_request_interceptor.h', + 'browser/chromeos/login_manager_view.cc', + 'browser/chromeos/login_manager_view.h', 'browser/chromeos/main_menu.cc', 'browser/chromeos/main_menu.h', 'browser/chromeos/mount_library.cc', @@ -2283,6 +2285,8 @@ 'dependencies': [ '../third_party/protobuf2/protobuf.gyp:protobuf_lite', '../third_party/protobuf2/protobuf.gyp:protoc#host', + '../third_party/chromeos_login_manager/chromeos_login_manager/chromeos_login_manager.gyp:session', + '../third_party/chromeos_login_manager/chromeos_login_manager/chromeos_login_manager.gyp:emit-login-prompt-ready', '../third_party/cros/cros_api.gyp:cros_api', ], 'actions': [ diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc index 3160bd8..ac6d558 100644 --- a/chrome/common/chrome_switches.cc +++ b/chrome/common/chrome_switches.cc @@ -665,6 +665,9 @@ const char kCookiePipe[] = "cookie-pipe"; // Document Viewer. const char kEnableGView[] = "enable-gview"; +// Enable experimental Chrome-as-a-login-manager behavior. +const char kLoginManager[] = "login-manager"; + // Attempts to load libcros and validate it, then exits. A nonzero return code // means the library could not be loaded correctly. const char kTestLoadLibcros[] = "test-load-libcros"; diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h index 5d97788..07ae41a 100644 --- a/chrome/common/chrome_switches.h +++ b/chrome/common/chrome_switches.h @@ -188,6 +188,7 @@ extern const char kZygoteProcess[]; #if defined(OS_CHROMEOS) extern const char kCookiePipe[]; extern const char kEnableGView[]; +extern const char kLoginManager[]; extern const char kTestLoadLibcros[]; extern const char kProfile[]; #endif |