diff options
author | bauerb@chromium.org <bauerb@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-04-18 18:18:10 +0000 |
---|---|---|
committer | bauerb@chromium.org <bauerb@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-04-18 18:18:10 +0000 |
commit | 9cc821655bc828170c9a049697d6f2ffcf5a3488 (patch) | |
tree | 3d1dfccccd7b3227ca59b677831f8a6f99c8a4e5 | |
parent | cda668384d63be9fddaebf01d82cd55105a2f8ac (diff) | |
download | chromium_src-9cc821655bc828170c9a049697d6f2ffcf5a3488.zip chromium_src-9cc821655bc828170c9a049697d6f2ffcf5a3488.tar.gz chromium_src-9cc821655bc828170c9a049697d6f2ffcf5a3488.tar.bz2 |
Wait for other browser windows to close when entering managed mode and cancel on failure.
To do this, we need to make the interface for ManagedMode::EnterManagedMode() asynchronous and change ManagedMode into a singleton.
BUG=119284
TEST=unit_tests --gtest_filter=ManagedModeTest.*
Review URL: http://codereview.chromium.org/9903018
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@132824 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/browser/extensions/extension_managed_mode_api.cc | 18 | ||||
-rw-r--r-- | chrome/browser/extensions/extension_managed_mode_api.h | 6 | ||||
-rw-r--r-- | chrome/browser/managed_mode.cc | 165 | ||||
-rw-r--r-- | chrome/browser/managed_mode.h | 62 | ||||
-rw-r--r-- | chrome/browser/managed_mode_unittest.cc | 226 | ||||
-rw-r--r-- | chrome/browser/ui/browser.cc | 5 | ||||
-rw-r--r-- | chrome/chrome_tests.gypi | 1 | ||||
-rw-r--r-- | chrome/common/chrome_notification_types.h | 8 | ||||
-rw-r--r-- | chrome/common/chrome_switches.cc | 3 | ||||
-rw-r--r-- | chrome/common/chrome_switches.h | 1 |
10 files changed, 457 insertions, 38 deletions
diff --git a/chrome/browser/extensions/extension_managed_mode_api.cc b/chrome/browser/extensions/extension_managed_mode_api.cc index 1471743..2cd834b2 100644 --- a/chrome/browser/extensions/extension_managed_mode_api.cc +++ b/chrome/browser/extensions/extension_managed_mode_api.cc @@ -8,6 +8,7 @@ #include <string> +#include "base/bind.h" #include "chrome/browser/managed_mode.h" #include "chrome/browser/extensions/extension_preference_api_constants.h" @@ -34,16 +35,15 @@ bool GetManagedModeFunction::RunImpl() { EnterManagedModeFunction::~EnterManagedModeFunction() { } bool EnterManagedModeFunction::RunImpl() { - bool confirmed = true; - if (!ManagedMode::IsInManagedMode()) { - // TODO(pamg): WIP. Show modal password dialog and save hashed password. Set - // |confirmed| to false if user cancels dialog. - - confirmed = ManagedMode::EnterManagedMode(profile()); - } + ManagedMode::EnterManagedMode( + profile(), + base::Bind(&EnterManagedModeFunction::SendResult, this)); + return true; +} +void EnterManagedModeFunction::SendResult(bool success) { scoped_ptr<DictionaryValue> result(new DictionaryValue); - result->SetBoolean(kEnterSuccessKey, confirmed); + result->SetBoolean(kEnterSuccessKey, success); result_.reset(result.release()); - return true; + SendResponse(true); } diff --git a/chrome/browser/extensions/extension_managed_mode_api.h b/chrome/browser/extensions/extension_managed_mode_api.h index 0c1ef49..07b9e25 100644 --- a/chrome/browser/extensions/extension_managed_mode_api.h +++ b/chrome/browser/extensions/extension_managed_mode_api.h @@ -18,11 +18,15 @@ class GetManagedModeFunction : public SyncExtensionFunction { DECLARE_EXTENSION_FUNCTION_NAME("experimental.managedMode.get") }; -class EnterManagedModeFunction : public SyncExtensionFunction { +class EnterManagedModeFunction : public AsyncExtensionFunction { public: virtual ~EnterManagedModeFunction(); virtual bool RunImpl() OVERRIDE; DECLARE_EXTENSION_FUNCTION_NAME("experimental.managedMode.enter") + + private: + // Called when we have either successfully entered managed mode or failed. + void SendResult(bool success); }; #endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_MANAGED_MODE_API_H_ diff --git a/chrome/browser/managed_mode.cc b/chrome/browser/managed_mode.cc index cef0d9e..15706a8 100644 --- a/chrome/browser/managed_mode.cc +++ b/chrome/browser/managed_mode.cc @@ -7,24 +7,37 @@ #include "base/command_line.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/prefs/pref_service.h" -#include "chrome/browser/profiles/profile_manager.h" -#include "chrome/browser/ui/browser_list.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/app_modal_dialogs/app_modal_dialog.h" +#include "chrome/browser/ui/app_modal_dialogs/js_modal_dialog.h" +#include "chrome/browser/ui/browser_window.h" #include "chrome/common/chrome_notification_types.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/pref_names.h" #include "content/public/browser/notification_service.h" // static +ManagedMode* ManagedMode::GetInstance() { + return Singleton<ManagedMode>::get(); +} + +// static void ManagedMode::RegisterPrefs(PrefService* prefs) { prefs->RegisterBooleanPref(prefs::kInManagedMode, false); // Set the value directly in the PrefService instead of using // CommandLinePrefStore so we can change it at runtime. - if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kManaged)) - SetInManagedMode(true); + if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kNoManaged)) + GetInstance()->SetInManagedMode(false); + else if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kManaged)) + GetInstance()->SetInManagedMode(true); } // static bool ManagedMode::IsInManagedMode() { + return GetInstance()->IsInManagedModeImpl(); +} + +bool ManagedMode::IsInManagedModeImpl() { // |g_browser_process| can be NULL during startup. if (!g_browser_process) return false; @@ -32,46 +45,154 @@ bool ManagedMode::IsInManagedMode() { } // static -bool ManagedMode::EnterManagedMode(Profile* profile) { - bool confirmed = PlatformConfirmEnter(); - if (confirmed) { - // Close all other profiles. - // TODO(bauerb): This may not close all windows, for example if there is an - // onbeforeunload handler. We should cancel entering managed mode in that - // case. - std::vector<Profile*> profiles = - g_browser_process->profile_manager()->GetLoadedProfiles(); - for (std::vector<Profile*>::iterator it = profiles.begin(); - it != profiles.end(); ++it) { - if (*it != profile) - BrowserList::CloseAllBrowsersWithProfile(*it); - } +void ManagedMode::EnterManagedMode(Profile* profile, + const EnterCallback& callback) { + GetInstance()->EnterManagedModeImpl(profile, callback); +} + +void ManagedMode::EnterManagedModeImpl(Profile* profile, + const EnterCallback& callback) { + if (IsInManagedModeImpl()) { + callback.Run(true); + return; + } + Profile* original_profile = profile->GetOriginalProfile(); + if (!callbacks_.empty()) { + // We are already in the process of entering managed mode, waiting for + // browsers to close. Don't allow entering managed mode again for a + // different profile, and queue the callback for the same profile. + if (original_profile != managed_profile_) + callback.Run(false); + else + callbacks_.push_back(callback); + return; + } + if (!PlatformConfirmEnter()) { + callback.Run(false); + return; + } + managed_profile_ = original_profile; + // Close all other profiles. + // At this point, we shouldn't be waiting for other browsers to close (yet). + DCHECK_EQ(0u, browsers_to_close_.size()); + for (BrowserList::const_iterator i = BrowserList::begin(); + i != BrowserList::end(); ++i) { + if ((*i)->profile()->GetOriginalProfile() != managed_profile_) + browsers_to_close_.insert(*i); + } + + if (browsers_to_close_.empty()) { SetInManagedMode(true); + managed_profile_ = NULL; + callback.Run(true); + return; + } + callbacks_.push_back(callback); + registrar_.Add(this, content::NOTIFICATION_APP_EXITING, + content::NotificationService::AllSources()); + registrar_.Add(this, chrome::NOTIFICATION_BROWSER_CLOSE_CANCELLED, + content::NotificationService::AllSources()); + for (std::set<const Browser*>::const_iterator i = browsers_to_close_.begin(); + i != browsers_to_close_.end(); ++i) { + (*i)->window()->Close(); } - return confirmed; } // static void ManagedMode::LeaveManagedMode() { + GetInstance()->LeaveManagedModeImpl(); +} + +void ManagedMode::LeaveManagedModeImpl() { bool confirmed = PlatformConfirmLeave(); if (confirmed) SetInManagedMode(false); } -// static +void ManagedMode::OnBrowserAdded(const Browser* browser) { + // Return early if we don't have any queued callbacks. + if (callbacks_.empty()) + return; + + if (browser->profile()->GetOriginalProfile() != managed_profile_) + FinalizeEnter(false); +} + +void ManagedMode::OnBrowserRemoved(const Browser* browser) { + // Return early if we don't have any queued callbacks. + if (callbacks_.empty()) + return; + + if (browser->profile()->GetOriginalProfile() == managed_profile_) { + // Ignore closing browser windows that are in managed mode. + return; + } + size_t count = browsers_to_close_.erase(browser); + DCHECK_EQ(1u, count); + if (browsers_to_close_.empty()) + FinalizeEnter(true); +} + +ManagedMode::ManagedMode() : managed_profile_(NULL) { + BrowserList::AddObserver(this); +} + +ManagedMode::~ManagedMode() { + BrowserList::RemoveObserver(this); + DCHECK(!managed_profile_); + DCHECK_EQ(0u, callbacks_.size()); + DCHECK_EQ(0u, browsers_to_close_.size()); +} + +void ManagedMode::Observe(int type, + const content::NotificationSource& source, + const content::NotificationDetails& details) { + // Return early if we don't have any queued callbacks. + if (callbacks_.empty()) + return; + + switch (type) { + case content::NOTIFICATION_APP_EXITING: { + FinalizeEnter(false); + return; + } + case chrome::NOTIFICATION_BROWSER_CLOSE_CANCELLED: { + Browser* browser = content::Source<Browser>(source).ptr(); + if (browsers_to_close_.find(browser) != browsers_to_close_.end()) + FinalizeEnter(false); + return; + } + default: { + NOTREACHED(); + break; + } + } +} + +void ManagedMode::FinalizeEnter(bool result) { + if (result) + SetInManagedMode(true); + for (std::vector<EnterCallback>::iterator it = callbacks_.begin(); + it != callbacks_.end(); ++it) { + it->Run(result); + } + managed_profile_ = NULL; + callbacks_.clear(); + browsers_to_close_.clear(); + registrar_.RemoveAll(); +} + bool ManagedMode::PlatformConfirmEnter() { // TODO(bauerb): Show platform-specific confirmation dialog. return true; } -// static bool ManagedMode::PlatformConfirmLeave() { // TODO(bauerb): Show platform-specific confirmation dialog. return true; } -// static void ManagedMode::SetInManagedMode(bool in_managed_mode) { g_browser_process->local_state()->SetBoolean(prefs::kInManagedMode, in_managed_mode); diff --git a/chrome/browser/managed_mode.h b/chrome/browser/managed_mode.h index 11466bf..b3edef0 100644 --- a/chrome/browser/managed_mode.h +++ b/chrome/browser/managed_mode.h @@ -5,25 +5,75 @@ #ifndef CHROME_BROWSER_MANAGED_MODE_H_ #define CHROME_BROWSER_MANAGED_MODE_H_ +#include <set> +#include <vector> + +#include "base/callback.h" +#include "base/compiler_specific.h" +#include "base/memory/scoped_ptr.h" +#include "base/memory/singleton.h" +#include "chrome/browser/ui/browser_list.h" +#include "content/public/browser/notification_observer.h" +#include "content/public/browser/notification_registrar.h" + +class Browser; +template<typename T> +struct DefaultSingletonTraits; class PrefService; class Profile; -class ManagedMode { +class ManagedMode : public BrowserList::Observer, + public content::NotificationObserver { public: + typedef base::Callback<void(bool)> EnterCallback; + static void RegisterPrefs(PrefService* prefs); static bool IsInManagedMode(); - // Returns true iff managed mode was entered sucessfully. - static bool EnterManagedMode(Profile* profile); + // Calls |callback| with the argument true iff managed mode was entered + // sucessfully. + static void EnterManagedMode(Profile* profile, const EnterCallback& callback); static void LeaveManagedMode(); + // BrowserList::Observer implementation: + virtual void OnBrowserAdded(const Browser* browser) OVERRIDE; + virtual void OnBrowserRemoved(const Browser* browser) OVERRIDE; + + // content::NotificationObserver implementation: + virtual void Observe(int type, + const content::NotificationSource& source, + const content::NotificationDetails& details) OVERRIDE; + + protected: + ManagedMode(); + virtual ~ManagedMode(); + void EnterManagedModeImpl(Profile* profile, const EnterCallback& callback); + private: + friend struct DefaultSingletonTraits<ManagedMode>; + friend class Singleton<ManagedMode>; + + static ManagedMode* GetInstance(); + + void LeaveManagedModeImpl(); + + void FinalizeEnter(bool result); + // Platform-specific methods that confirm whether we can enter or leave // managed mode. - static bool PlatformConfirmEnter(); - static bool PlatformConfirmLeave(); + virtual bool PlatformConfirmEnter(); + virtual bool PlatformConfirmLeave(); - static void SetInManagedMode(bool in_managed_mode); + virtual bool IsInManagedModeImpl(); + virtual void SetInManagedMode(bool in_managed_mode); + + content::NotificationRegistrar registrar_; + + // The managed profile. This is non-NULL only while we're entering + // managed mode. + const Profile* managed_profile_; + std::set<const Browser*> browsers_to_close_; + std::vector<EnterCallback> callbacks_; }; #endif // CHROME_BROWSER_MANAGED_MODE_H_ diff --git a/chrome/browser/managed_mode_unittest.cc b/chrome/browser/managed_mode_unittest.cc new file mode 100644 index 0000000..712dcc7 --- /dev/null +++ b/chrome/browser/managed_mode_unittest.cc @@ -0,0 +1,226 @@ +// 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/managed_mode.h" + +#include <algorithm> +#include <vector> + +#include "base/bind.h" +#include "base/bind_helpers.h" +#include "base/message_loop.h" +#include "chrome/browser/managed_mode.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/test/base/test_browser_window.h" +#include "chrome/test/base/testing_profile.h" +#include "content/test/test_browser_thread.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/gmock/include/gmock/gmock.h" + +using ::testing::StrictMock; + +namespace { + +class FakeManagedMode : public ManagedMode { + public: + FakeManagedMode() : in_managed_mode_(false), should_cancel_enter_(false) { + } + + void set_should_cancel_enter(bool should_cancel_enter) { + should_cancel_enter_ = should_cancel_enter; + } + + void EnterManagedModeForTesting(Profile* profile, + const base::Callback<void(bool)>& callback) { + EnterManagedModeImpl(profile, callback); + } + + // ManagedMode overrides: + virtual bool IsInManagedModeImpl() OVERRIDE { + return in_managed_mode_; + } + + virtual void SetInManagedMode(bool in_managed_mode) OVERRIDE { + in_managed_mode_ = in_managed_mode; + } + + virtual bool PlatformConfirmEnter() OVERRIDE { + return !should_cancel_enter_; + } + + virtual bool PlatformConfirmLeave() OVERRIDE { + return true; + } + + private: + bool in_managed_mode_; + bool should_cancel_enter_; +}; + +class MockBrowserWindow : public TestBrowserWindow { + public: + explicit MockBrowserWindow(Browser* browser) : TestBrowserWindow(browser) { + } + + MOCK_METHOD0(Close, void()); +}; + +class BrowserFixture { + public: + BrowserFixture(FakeManagedMode* managed_mode, + TestingProfile* profile) + : browser_(Browser::TYPE_TABBED, profile), + window_(&browser_), + managed_mode_(managed_mode) { + browser_.SetWindowForTesting(&window_); + } + + ~BrowserFixture() { + } + + MockBrowserWindow* window() { + return &window_; + } + + private: + Browser browser_; + StrictMock<MockBrowserWindow> window_; + FakeManagedMode* managed_mode_; +}; + +class MockCallback : public base::RefCountedThreadSafe<MockCallback> { + public: + explicit MockCallback(FakeManagedMode* managed_mode) + : managed_mode_(managed_mode) { + } + virtual ~MockCallback() {} + + void CheckManagedMode(bool success) { + EXPECT_EQ(managed_mode_->IsInManagedModeImpl(), success); + DidEnterManagedMode(success); + } + + MOCK_METHOD1(DidEnterManagedMode, void(bool)); + + private: + FakeManagedMode* managed_mode_; + + DISALLOW_COPY_AND_ASSIGN(MockCallback); +}; + +} // namespace + +class ManagedModeTest : public ::testing::Test { + public: + ManagedModeTest() : ui_thread_(content::BrowserThread::UI, &message_loop_) { + } + + scoped_refptr<MockCallback> CreateCallback() { + return new StrictMock<MockCallback>(&managed_mode_); + } + + base::Callback<void(bool)> CreateExpectedCallback(bool success) { + scoped_refptr<MockCallback> callback = CreateCallback(); + EXPECT_CALL(*callback, DidEnterManagedMode(success)); + return base::Bind(&MockCallback::CheckManagedMode, callback); + } + + protected: + MessageLoop message_loop_; + content::TestBrowserThread ui_thread_; + TestingProfile managed_mode_profile_; + TestingProfile other_profile_; + FakeManagedMode managed_mode_; +}; + +TEST_F(ManagedModeTest, SingleBrowser) { + BrowserFixture managed_mode_browser(&managed_mode_, &managed_mode_profile_); + + // If there are no browsers belonging to a different profile, entering should + // immediately succeed. + managed_mode_.EnterManagedModeForTesting(&managed_mode_profile_, + CreateExpectedCallback(true)); +} + +TEST_F(ManagedModeTest, AlreadyInManagedMode) { + BrowserFixture managed_mode_browser(&managed_mode_, &managed_mode_profile_); + BrowserFixture other_browser(&managed_mode_, &other_profile_); + + // If we're already in managed mode, entering should immediately succeed. + managed_mode_.SetInManagedMode(true); + managed_mode_.EnterManagedModeForTesting(&managed_mode_profile_, + CreateExpectedCallback(true)); +} + +TEST_F(ManagedModeTest, QueueRequests) { + BrowserFixture managed_mode_browser(&managed_mode_, &managed_mode_profile_); + + // Keep this before the other browser is constructed, so we verify its + // expectations after the browser is destroyed. + scoped_refptr<MockCallback> callback = CreateCallback(); + BrowserFixture other_browser(&managed_mode_, &other_profile_); + + EXPECT_CALL(*other_browser.window(), Close()); + managed_mode_.EnterManagedModeForTesting( + &managed_mode_profile_, + base::Bind(&MockCallback::CheckManagedMode, callback)); + managed_mode_.EnterManagedModeForTesting( + &managed_mode_profile_, + base::Bind(&MockCallback::CheckManagedMode, callback)); + // The callbacks should run as soon as |other_browser| is closed. + EXPECT_CALL(*callback, DidEnterManagedMode(true)).Times(2); +} + +TEST_F(ManagedModeTest, OpenNewBrowser) { + BrowserFixture managed_mode_browser(&managed_mode_, &managed_mode_profile_); + BrowserFixture other_browser(&managed_mode_, &other_profile_); + + scoped_refptr<MockCallback> callback = CreateCallback(); + EXPECT_CALL(*other_browser.window(), Close()); + managed_mode_.EnterManagedModeForTesting( + &managed_mode_profile_, + base::Bind(&MockCallback::CheckManagedMode, callback)); + + // Opening another browser with the managed profile should not cancel entering + // managed mode. + BrowserFixture other_managed_mode_browser(&managed_mode_, + &managed_mode_profile_); + + // Opening another browser should cancel entering managed mode. + EXPECT_CALL(*callback, DidEnterManagedMode(false)); + BrowserFixture yet_another_browser(&managed_mode_, &other_profile_); +} + +TEST_F(ManagedModeTest, DifferentProfile) { + BrowserFixture managed_mode_browser(&managed_mode_, &managed_mode_profile_); + + // Keep this before the other browser is constructed, so we verify its + // expectations after the browser is destroyed. + scoped_refptr<MockCallback> callback = CreateCallback(); + BrowserFixture other_browser(&managed_mode_, &other_profile_); + + EXPECT_CALL(*other_browser.window(), Close()); + managed_mode_.EnterManagedModeForTesting( + &managed_mode_profile_, + base::Bind(&MockCallback::CheckManagedMode, callback)); + + // Trying to enter managed mode with a different profile should fail + // immediately. + managed_mode_.EnterManagedModeForTesting(&other_profile_, + CreateExpectedCallback(false)); + + // The first request should still succeed as soon as the other browser is + // closed. + EXPECT_CALL(*callback, DidEnterManagedMode(true)); +} + +TEST_F(ManagedModeTest, Cancelled) { + BrowserFixture managed_mode_browser(&managed_mode_, &managed_mode_profile_); + BrowserFixture other_browser(&managed_mode_, &other_profile_); + + // If the user cancelled entering managed mode, it should fail immediately. + managed_mode_.set_should_cancel_enter(true); + managed_mode_.EnterManagedModeForTesting(&managed_mode_profile_, + CreateExpectedCallback(false)); +} diff --git a/chrome/browser/ui/browser.cc b/chrome/browser/ui/browser.cc index 66744f5..316e399 100644 --- a/chrome/browser/ui/browser.cc +++ b/chrome/browser/ui/browser.cc @@ -5307,6 +5307,11 @@ void Browser::CancelWindowClose() { tabs_needing_unload_fired_.clear(); is_attempting_to_close_browser_ = false; + content::NotificationService::current()->Notify( + chrome::NOTIFICATION_BROWSER_CLOSE_CANCELLED, + content::Source<Browser>(this), + content::NotificationService::NoDetails()); + // Inform TabCloseableStateWatcher that closing of window has been canceled. TabCloseableStateWatcher* watcher = g_browser_process->tab_closeable_state_watcher(); diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi index fe30e87..39aaf80 100644 --- a/chrome/chrome_tests.gypi +++ b/chrome/chrome_tests.gypi @@ -1500,6 +1500,7 @@ 'browser/internal_auth_unittest.cc', 'browser/language_usage_metrics_unittest.cc', 'browser/mac/keystone_glue_unittest.mm', + 'browser/managed_mode_unittest.cc', 'browser/media/media_internals_unittest.cc', 'browser/media_gallery/media_device_notifications_linux_unittest.cc', 'browser/media_gallery/media_gallery_database_unittest.cc', diff --git a/chrome/common/chrome_notification_types.h b/chrome/common/chrome_notification_types.h index 1e67e8b..3781814 100644 --- a/chrome/common/chrome_notification_types.h +++ b/chrome/common/chrome_notification_types.h @@ -42,6 +42,14 @@ enum NotificationType { // valid for the duration of this call. NOTIFICATION_BROWSER_CLOSED, + // This message is sent when closing a browser has been cancelled, either by + // the user cancelling a beforeunload dialog, or IsClosingPermitted() + // disallowing closing. This notification implies that no BROWSER_CLOSING or + // BROWSER_CLOSED notification will be sent. + // The source is a Source<Browser> containing the affected browser. No details + // are expected. + NOTIFICATION_BROWSER_CLOSE_CANCELLED, + // Indicates that a top window has been closed. The source is the HWND // that was closed, no details are expected. NOTIFICATION_WINDOW_CLOSED, diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc index 80e26d1..51b273b 100644 --- a/chrome/common/chrome_switches.cc +++ b/chrome/common/chrome_switches.cc @@ -854,6 +854,9 @@ const char kNoExperiments[] = "no-experiments"; // you're for some reason tempted to pass them both. const char kNoFirstRun[] = "no-first-run"; +// Starts the browser outside of managed mode. +const char kNoManaged[] = "no-managed"; + // Don't send hyperlink auditing pings const char kNoPings[] = "no-pings"; diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h index 4afed1a..abe4977 100644 --- a/chrome/common/chrome_switches.h +++ b/chrome/common/chrome_switches.h @@ -232,6 +232,7 @@ extern const char kNoDisplayingInsecureContent[]; extern const char kNoEvents[]; extern const char kNoExperiments[]; extern const char kNoFirstRun[]; +extern const char kNoManaged[]; extern const char kNoProxyServer[]; extern const char kNoPings[]; extern const char kNoProtector[]; |