diff options
23 files changed, 988 insertions, 61 deletions
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index 35363a4..29c710b 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd @@ -4049,6 +4049,9 @@ Update checks have repeatedly failed for the extension "<ph name="EXTENSION_NAME <message name="IDS_EXTENSION_PROMPT_WARNING_PRIVACY" desc="Permission string for access to privacy settings."> Privacy-related settings </message> + <message name="IDS_EXTENSION_PROMPT_WARNING_MANAGED_MODE" desc="Permission string for access to managed mode."> + Managed mode + </message> <!-- Extension/App error messages --> <message name="IDS_EXTENSION_CANT_GET_ABSOLUTE_PATH" desc="Warning displayed in pack dialog when the absolute path to the extension directory can not be found."> diff --git a/chrome/browser/extensions/extension_function_dispatcher.cc b/chrome/browser/extensions/extension_function_dispatcher.cc index a26b2b6..881dff5 100644 --- a/chrome/browser/extensions/extension_function_dispatcher.cc +++ b/chrome/browser/extensions/extension_function_dispatcher.cc @@ -36,6 +36,7 @@ #include "chrome/browser/extensions/extension_function.h" #include "chrome/browser/extensions/extension_i18n_api.h" #include "chrome/browser/extensions/extension_idle_api.h" +#include "chrome/browser/extensions/extension_managed_mode_api.h" #include "chrome/browser/extensions/extension_management_api.h" #include "chrome/browser/extensions/extension_metrics_module.h" #include "chrome/browser/extensions/extension_module.h" @@ -348,6 +349,10 @@ void FactoryRegistry::ResetFunctions() { #endif #endif + // Managed mode. + RegisterFunction<GetManagedModeFunction>(); + RegisterFunction<EnterManagedModeFunction>(); + // Management. RegisterFunction<GetAllExtensionsFunction>(); RegisterFunction<GetExtensionByIdFunction>(); diff --git a/chrome/browser/extensions/extension_managed_mode_api.cc b/chrome/browser/extensions/extension_managed_mode_api.cc new file mode 100644 index 0000000..12da93d --- /dev/null +++ b/chrome/browser/extensions/extension_managed_mode_api.cc @@ -0,0 +1,56 @@ +// 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. + +// Implementation of the Chrome Extensions Managed Mode API. + +#include "chrome/browser/extensions/extension_managed_mode_api.h" + +#include <string> + +#include "chrome/browser/browser_process.h" +#include "chrome/browser/extensions/extension_preference_api_constants.h" +#include "chrome/browser/prefs/pref_service.h" +#include "chrome/common/pref_names.h" + +namespace { + +// Key to report whether the attempt to enter managed mode succeeded. +const char kEnterSuccessKey[] = "success"; + +} // namespace + +namespace keys = extension_preference_api_constants; + +GetManagedModeFunction::~GetManagedModeFunction() { } + +bool GetManagedModeFunction::RunImpl() { + PrefService* local_state = g_browser_process->local_state(); + bool in_managed_mode = local_state->GetBoolean(prefs::kInManagedMode); + + scoped_ptr<DictionaryValue> result(new DictionaryValue); + result->SetBoolean(keys::kValue, in_managed_mode); + result_.reset(result.release()); + return true; +} + +EnterManagedModeFunction::~EnterManagedModeFunction() { } + +bool EnterManagedModeFunction::RunImpl() { + PrefService* local_state = g_browser_process->local_state(); + bool in_managed_mode = local_state->GetBoolean(prefs::kInManagedMode); + + bool confirmed = true; + if (!in_managed_mode) { + // TODO(pamg): WIP. Show modal password dialog and save hashed password. Set + // |confirmed| to false if user cancels dialog. + + if (confirmed) + local_state->SetBoolean(prefs::kInManagedMode, true); + } + + scoped_ptr<DictionaryValue> result(new DictionaryValue); + result->SetBoolean(kEnterSuccessKey, confirmed); + result_.reset(result.release()); + return true; +} diff --git a/chrome/browser/extensions/extension_managed_mode_api.h b/chrome/browser/extensions/extension_managed_mode_api.h new file mode 100644 index 0000000..0c1ef49 --- /dev/null +++ b/chrome/browser/extensions/extension_managed_mode_api.h @@ -0,0 +1,28 @@ +// 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. + +// Defines the Chrome Extensions Managed Mode API relevant classes to realize +// the API as specified in the extension API JSON. + +#ifndef CHROME_BROWSER_EXTENSIONS_EXTENSION_MANAGED_MODE_API_H_ +#define CHROME_BROWSER_EXTENSIONS_EXTENSION_MANAGED_MODE_API_H_ +#pragma once + +#include "chrome/browser/extensions/extension_function.h" + +class GetManagedModeFunction : public SyncExtensionFunction { + public: + virtual ~GetManagedModeFunction(); + virtual bool RunImpl() OVERRIDE; + DECLARE_EXTENSION_FUNCTION_NAME("experimental.managedMode.get") +}; + +class EnterManagedModeFunction : public SyncExtensionFunction { + public: + virtual ~EnterManagedModeFunction(); + virtual bool RunImpl() OVERRIDE; + DECLARE_EXTENSION_FUNCTION_NAME("experimental.managedMode.enter") +}; + +#endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_MANAGED_MODE_API_H_ diff --git a/chrome/browser/extensions/extension_managed_mode_apitest.cc b/chrome/browser/extensions/extension_managed_mode_apitest.cc new file mode 100644 index 0000000..54970e5 --- /dev/null +++ b/chrome/browser/extensions/extension_managed_mode_apitest.cc @@ -0,0 +1,24 @@ +// 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/browser_process.h" +#include "chrome/browser/extensions/extension_apitest.h" +#include "chrome/browser/prefs/pref_service.h" +#include "chrome/common/chrome_switches.h" +#include "chrome/common/pref_names.h" + +// Tests enabling and querying managed mode. +IN_PROC_BROWSER_TEST_F(ExtensionApiTest, ManagedModeGetAndEnable) { + CommandLine::ForCurrentProcess()->AppendSwitch( + switches::kEnableExperimentalExtensionApis); + + PrefService* local_state = g_browser_process->local_state(); + ASSERT_FALSE(local_state->GetBoolean(prefs::kInManagedMode)); + + ASSERT_TRUE(RunExtensionTest("managedMode")) << message_; + const Extension* extension = GetSingleLoadedExtension(); + ASSERT_TRUE(extension); + + EXPECT_TRUE(local_state->GetBoolean(prefs::kInManagedMode)); +} diff --git a/chrome/browser/extensions/extension_preference_api.cc b/chrome/browser/extensions/extension_preference_api.cc index 7f4f4ee..585850c 100644 --- a/chrome/browser/extensions/extension_preference_api.cc +++ b/chrome/browser/extensions/extension_preference_api.cc @@ -26,6 +26,9 @@ #include "content/public/browser/notification_details.h" #include "content/public/browser/notification_source.h" +namespace keys = extension_preference_api_constants; +namespace helpers = extension_preference_helpers; + namespace { struct PrefMappingEntry { @@ -41,15 +44,6 @@ struct PrefMappingEntry { ExtensionAPIPermission::ID permission; }; -const char kNotControllable[] = "not_controllable"; -const char kControlledByOtherExtensions[] = "controlled_by_other_extensions"; -const char kControllableByThisExtension[] = "controllable_by_this_extension"; -const char kControlledByThisExtension[] = "controlled_by_this_extension"; - -const char kIncognitoSpecific[] = "incognitoSpecific"; -const char kLevelOfControl[] = "levelOfControl"; -const char kValue[] = "value"; - const char kOnPrefChangeFormat[] = "types.ChromeSetting.%s.onChange"; PrefMappingEntry kPrefMapping[] = { @@ -69,6 +63,10 @@ PrefMappingEntry kPrefMapping[] = { prefs::kInstantEnabled, ExtensionAPIPermission::kPrivacy }, + { "managedModeEnabled", + prefs::kInManagedMode, + ExtensionAPIPermission::kManagedMode + }, { "networkPredictionEnabled", prefs::kNetworkPredictionEnabled, ExtensionAPIPermission::kPrivacy @@ -148,15 +146,15 @@ const char* GetLevelOfControl( ExtensionPrefs* ep = profile->GetExtensionService()->extension_prefs(); if (!pref->IsExtensionModifiable()) - return kNotControllable; + return keys::kNotControllable; if (ep->DoesExtensionControlPref(extension_id, browser_pref, incognito)) - return kControlledByThisExtension; + return keys::kControlledByThisExtension; if (ep->CanExtensionControlPref(extension_id, browser_pref, incognito)) - return kControllableByThisExtension; + return keys::kControllableByThisExtension; - return kControlledByOtherExtensions; + return keys::kControlledByOtherExtensions; } class PrefMapping { @@ -253,9 +251,6 @@ class PrefMapping { } // namespace -namespace keys = extension_preference_api_constants; -namespace helpers = extension_preference_helpers; - ExtensionPreferenceEventRouter::ExtensionPreferenceEventRouter( Profile* profile) : profile_(profile) { registrar_.Init(profile_->GetPrefs()); @@ -301,10 +296,11 @@ void ExtensionPreferenceEventRouter::OnPrefChanged( ExtensionService* extension_service = profile_->GetExtensionService(); PrefTransformerInterface* transformer = PrefMapping::GetInstance()->FindTransformerForBrowserPref(browser_pref); - dict->Set(kValue, transformer->BrowserToExtensionPref(pref->GetValue())); + dict->Set(keys::kValue, + transformer->BrowserToExtensionPref(pref->GetValue())); if (incognito) { ExtensionPrefs* ep = extension_service->extension_prefs(); - dict->SetBoolean(kIncognitoSpecific, + dict->SetBoolean(keys::kIncognitoSpecific, ep->HasIncognitoPrefValue(browser_pref)); } @@ -321,7 +317,7 @@ void ExtensionPreferenceEventRouter::OnPrefChanged( (!incognito || extension_service->CanCrossIncognito(*it))) { std::string level_of_control = GetLevelOfControl(profile_, extension_id, browser_pref, incognito); - dict->SetString(kLevelOfControl, level_of_control); + dict->SetString(keys::kLevelOfControl, level_of_control); std::string json_args; base::JSONWriter::Write(&args, false, &json_args); @@ -339,7 +335,22 @@ void ExtensionPreferenceEventRouter::DispatchEvent( extension_id, event_name, json_args, NULL, GURL()); } -// TODO(battre): Factor out common parts once this is stable. +PreferenceFunction::~PreferenceFunction() { } + +bool PreferenceFunction::ValidateBrowserPref( + const std::string& extension_pref_key, + std::string* browser_pref_key) { + ExtensionAPIPermission::ID permission = ExtensionAPIPermission::kInvalid; + EXTENSION_FUNCTION_VALIDATE( + PrefMapping::GetInstance()->FindBrowserPrefForExtensionPref( + extension_pref_key, browser_pref_key, &permission)); + if (!GetExtension()->HasAPIPermission(permission)) { + error_ = ExtensionErrorUtils::FormatErrorMessage( + keys::kPermissionErrorMessage, extension_pref_key); + return false; + } + return true; +} GetPreferenceFunction::~GetPreferenceFunction() { } @@ -354,40 +365,42 @@ bool GetPreferenceFunction::RunImpl() { EXTENSION_FUNCTION_VALIDATE(details->GetBoolean(keys::kIncognitoKey, &incognito)); + // Check incognito access. if (incognito && !include_incognito()) { error_ = keys::kIncognitoErrorMessage; return false; } - PrefService* prefs = incognito ? profile_->GetOffTheRecordPrefs() - : profile_->GetPrefs(); + // Obtain pref. std::string browser_pref; - ExtensionAPIPermission::ID permission = ExtensionAPIPermission::kInvalid; - EXTENSION_FUNCTION_VALIDATE( - PrefMapping::GetInstance()->FindBrowserPrefForExtensionPref( - pref_key, &browser_pref, &permission)); - if (!GetExtension()->HasAPIPermission(permission)) { - error_ = ExtensionErrorUtils::FormatErrorMessage( - keys::kPermissionErrorMessage, pref_key); + if (!ValidateBrowserPref(pref_key, &browser_pref)) return false; - } - + PrefService* prefs = incognito ? profile_->GetOffTheRecordPrefs() + : profile_->GetPrefs(); const PrefService::Preference* pref = prefs->FindPreference(browser_pref.c_str()); CHECK(pref); + + scoped_ptr<DictionaryValue> result(new DictionaryValue); + + // Retrieve level of control. std::string level_of_control = GetLevelOfControl(profile_, extension_id(), browser_pref, incognito); + result->SetString(keys::kLevelOfControl, level_of_control); - scoped_ptr<DictionaryValue> result(new DictionaryValue); + // Retrieve pref value. PrefTransformerInterface* transformer = PrefMapping::GetInstance()->FindTransformerForBrowserPref(browser_pref); - result->Set(kValue, transformer->BrowserToExtensionPref(pref->GetValue())); - result->SetString(kLevelOfControl, level_of_control); + result->Set(keys::kValue, + transformer->BrowserToExtensionPref(pref->GetValue())); + + // Retrieve incognito status. if (incognito) { ExtensionPrefs* ep = profile_->GetExtensionService()->extension_prefs(); - result->SetBoolean(kIncognitoSpecific, + result->SetBoolean(keys::kIncognitoSpecific, ep->HasIncognitoPrefValue(browser_pref)); } + result_.reset(result.release()); return true; } @@ -401,7 +414,7 @@ bool SetPreferenceFunction::RunImpl() { EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(1, &details)); Value* value = NULL; - EXTENSION_FUNCTION_VALIDATE(details->Get(kValue, &value)); + EXTENSION_FUNCTION_VALIDATE(details->Get(keys::kValue, &value)); ExtensionPrefsScope scope = kExtensionPrefsScopeRegular; if (details->HasKey(keys::kScopeKey)) { @@ -412,6 +425,7 @@ bool SetPreferenceFunction::RunImpl() { EXTENSION_FUNCTION_VALIDATE(helpers::StringToScope(scope_str, &scope)); } + // Check incognito scope. bool incognito = (scope == kExtensionPrefsScopeIncognitoPersistent || scope == kExtensionPrefsScopeIncognitoSessionOnly); if (incognito) { @@ -435,20 +449,16 @@ bool SetPreferenceFunction::RunImpl() { return false; } + // Obtain pref. std::string browser_pref; - ExtensionAPIPermission::ID permission = ExtensionAPIPermission::kInvalid; - EXTENSION_FUNCTION_VALIDATE( - PrefMapping::GetInstance()->FindBrowserPrefForExtensionPref( - pref_key, &browser_pref, &permission)); - if (!GetExtension()->HasAPIPermission(permission)) { - error_ = ExtensionErrorUtils::FormatErrorMessage( - keys::kPermissionErrorMessage, pref_key); + if (!ValidateBrowserPref(pref_key, &browser_pref)) return false; - } ExtensionPrefs* prefs = profile_->GetExtensionService()->extension_prefs(); const PrefService::Preference* pref = prefs->pref_service()->FindPreference(browser_pref.c_str()); CHECK(pref); + + // Validate new value. EXTENSION_FUNCTION_VALIDATE(value->GetType() == pref->GetType()); PrefTransformerInterface* transformer = PrefMapping::GetInstance()->FindTransformerForBrowserPref(browser_pref); @@ -461,6 +471,7 @@ bool SetPreferenceFunction::RunImpl() { bad_message_ = bad_message; return false; } + prefs->SetExtensionControlledPref(extension_id(), browser_pref, scope, @@ -485,6 +496,7 @@ bool ClearPreferenceFunction::RunImpl() { EXTENSION_FUNCTION_VALIDATE(helpers::StringToScope(scope_str, &scope)); } + // Check incognito scope. bool incognito = (scope == kExtensionPrefsScopeIncognitoPersistent || scope == kExtensionPrefsScopeIncognitoSessionOnly); if (incognito) { @@ -500,15 +512,9 @@ bool ClearPreferenceFunction::RunImpl() { } std::string browser_pref; - ExtensionAPIPermission::ID permission = ExtensionAPIPermission::kInvalid; - EXTENSION_FUNCTION_VALIDATE( - PrefMapping::GetInstance()->FindBrowserPrefForExtensionPref( - pref_key, &browser_pref, &permission)); - if (!GetExtension()->HasAPIPermission(permission)) { - error_ = ExtensionErrorUtils::FormatErrorMessage( - keys::kPermissionErrorMessage, pref_key); + if (!ValidateBrowserPref(pref_key, &browser_pref)) return false; - } + ExtensionPrefs* prefs = profile_->GetExtensionService()->extension_prefs(); prefs->RemoveExtensionControlledPref(extension_id(), browser_pref, scope); return true; diff --git a/chrome/browser/extensions/extension_preference_api.h b/chrome/browser/extensions/extension_preference_api.h index e39239f..847e0f1 100644 --- a/chrome/browser/extensions/extension_preference_api.h +++ b/chrome/browser/extensions/extension_preference_api.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// 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. @@ -66,21 +66,37 @@ class PrefTransformerInterface { const base::Value* browser_pref) = 0; }; -class GetPreferenceFunction : public SyncExtensionFunction { +// A base class to provide functionality common to the other *PreferenceFunction +// classes. +class PreferenceFunction : public SyncExtensionFunction { + public: + virtual ~PreferenceFunction(); + + protected: + // Given an |extension_pref_key|, provides its |browser_pref_key| from the + // static map in extension_preference.cc. Returns true if the corresponding + // browser pref exists and the extension has the API permission needed to + // modify that pref. Sets |error_| if the extension doesn't have the needed + // permission. + bool ValidateBrowserPref(const std::string& extension_pref_key, + std::string* browser_pref_key); +}; + +class GetPreferenceFunction : public PreferenceFunction { public: virtual ~GetPreferenceFunction(); virtual bool RunImpl() OVERRIDE; DECLARE_EXTENSION_FUNCTION_NAME("types.ChromeSetting.get") }; -class SetPreferenceFunction : public SyncExtensionFunction { +class SetPreferenceFunction : public PreferenceFunction { public: virtual ~SetPreferenceFunction(); virtual bool RunImpl() OVERRIDE; DECLARE_EXTENSION_FUNCTION_NAME("types.ChromeSetting.set") }; -class ClearPreferenceFunction : public SyncExtensionFunction { +class ClearPreferenceFunction : public PreferenceFunction { public: virtual ~ClearPreferenceFunction(); virtual bool RunImpl() OVERRIDE; diff --git a/chrome/browser/extensions/extension_preference_api_constants.cc b/chrome/browser/extensions/extension_preference_api_constants.cc index 9f4d333..aaba59f 100644 --- a/chrome/browser/extensions/extension_preference_api_constants.cc +++ b/chrome/browser/extensions/extension_preference_api_constants.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// 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. @@ -10,6 +10,15 @@ const char kIncognitoKey[] = "incognito"; const char kScopeKey[] = "scope"; +const char kNotControllable[] = "not_controllable"; +const char kControlledByOtherExtensions[] = "controlled_by_other_extensions"; +const char kControllableByThisExtension[] = "controllable_by_this_extension"; +const char kControlledByThisExtension[] = "controlled_by_this_extension"; + +const char kIncognitoSpecific[] = "incognitoSpecific"; +const char kLevelOfControl[] = "levelOfControl"; +const char kValue[] = "value"; + const char kIncognitoErrorMessage[] = "You do not have permission to access incognito preferences."; diff --git a/chrome/browser/extensions/extension_preference_api_constants.h b/chrome/browser/extensions/extension_preference_api_constants.h index cc584e1..079a578 100644 --- a/chrome/browser/extensions/extension_preference_api_constants.h +++ b/chrome/browser/extensions/extension_preference_api_constants.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// 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. @@ -8,10 +8,21 @@ namespace extension_preference_api_constants { -// Keys. +// Keys for incoming arguments. extern const char kIncognitoKey[]; extern const char kScopeKey[]; +// Keys for returned parameters. +extern const char kIncognitoSpecific[]; +extern const char kLevelOfControl[]; +extern const char kValue[]; + +// Values for levelOfControl. +extern const char kNotControllable[]; +extern const char kControlledByOtherExtensions[]; +extern const char kControllableByThisExtension[]; +extern const char kControlledByThisExtension[]; + // Errors. extern const char kIncognitoErrorMessage[]; extern const char kIncognitoSessionOnlyErrorMessage[]; diff --git a/chrome/browser/profiles/profile_manager.cc b/chrome/browser/profiles/profile_manager.cc index 323aef7..b88fbc4 100644 --- a/chrome/browser/profiles/profile_manager.cc +++ b/chrome/browser/profiles/profile_manager.cc @@ -716,6 +716,7 @@ void ProfileManager::RegisterPrefs(PrefService* prefs) { prefs->RegisterStringPref(prefs::kProfileLastUsed, ""); prefs->RegisterIntegerPref(prefs::kProfilesNumCreated, 1); prefs->RegisterListPref(prefs::kProfilesLastActive); + prefs->RegisterBooleanPref(prefs::kInManagedMode, false); } size_t ProfileManager::GetNumberOfProfiles() { @@ -919,7 +920,7 @@ ProfileManagerWithoutInit::ProfileManagerWithoutInit( void ProfileManager::RegisterTestingProfile(Profile* profile, bool add_to_cache) { RegisterProfile(profile, true); - if (add_to_cache){ + if (add_to_cache) { InitProfileUserPrefs(profile); AddProfileToCache(profile); } diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index cb1656d..b422b87 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -1199,6 +1199,8 @@ 'browser/extensions/extension_install_dialog.h', 'browser/extensions/extension_install_ui.cc', 'browser/extensions/extension_install_ui.h', + 'browser/extensions/extension_managed_mode_api.cc', + 'browser/extensions/extension_managed_mode_api.h', 'browser/extensions/extension_management_api.cc', 'browser/extensions/extension_management_api.h', 'browser/extensions/extension_management_api_constants.cc', diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi index 66be9e8..21b68ca 100644 --- a/chrome/chrome_tests.gypi +++ b/chrome/chrome_tests.gypi @@ -2681,6 +2681,7 @@ 'browser/extensions/extension_javascript_url_apitest.cc', 'browser/extensions/extension_keybinding_apitest.cc', 'browser/extensions/extension_local_filesystem_apitest.cc', + 'browser/extensions/extension_managed_mode_apitest.cc', 'browser/extensions/extension_management_api_browsertest.cc', 'browser/extensions/extension_management_apitest.cc', 'browser/extensions/extension_management_browsertest.cc', diff --git a/chrome/common/common_resources.grd b/chrome/common/common_resources.grd index 8543481..253cb1a 100644 --- a/chrome/common/common_resources.grd +++ b/chrome/common/common_resources.grd @@ -33,6 +33,7 @@ <include name="IDR_EXTENSION_API_JSON_EXPERIMENTAL_INPUT_UI" file="extensions\api\experimental.input.ui.json" type="BINDATA" /> <include name="IDR_EXTENSION_API_JSON_EXPERIMENTAL_INPUT_VIRTUALKEYBOARD" file="extensions\api\experimental.input.virtualKeyboard.json" type="BINDATA" /> <include name="IDR_EXTENSION_API_JSON_EXPERIMENTAL_KEYBINDING" file="extensions\api\experimental.keybinding.json" type="BINDATA" /> + <include name="IDR_EXTENSION_API_JSON_EXPERIMENTAL_MANAGED_MODE" file="extensions\api\experimental.managedMode.json" type="BINDATA" /> <include name="IDR_EXTENSION_API_JSON_EXPERIMENTAL_PROCESSES" file="extensions\api\experimental.processes.json" type="BINDATA" /> <include name="IDR_EXTENSION_API_JSON_EXPERIMENTAL_RLZ" file="extensions\api\experimental.rlz.json" type="BINDATA" /> <include name="IDR_EXTENSION_API_JSON_EXPERIMENTAL_SERIAL" file="extensions\api\experimental.serial.json" type="BINDATA" /> diff --git a/chrome/common/extensions/api/experimental.managedMode.json b/chrome/common/extensions/api/experimental.managedMode.json new file mode 100644 index 0000000..a68468c --- /dev/null +++ b/chrome/common/extensions/api/experimental.managedMode.json @@ -0,0 +1,57 @@ +[ + { + "namespace": "experimental.managedMode", + "dependencies": ["types"], + "functions": [ + { + "name": "enter", + "type": "function", + "description": "Shows a confirmation dialog, then puts the browser into managed mode. The callback parameter will be true if managed mode was entered successfully, false if the user cancelled the confirmation. If managed mode is already on, trying to enter it again will have no effect.", + "parameters": [ + { + "type": "function", + "name": "callback", + "optional": true, + "parameters": [ + { + "name": "result", + "type": "object", + "description": "The result of the attempt to enter managed mode.", + "properties": { + "success": { + "description": "True if managed mode was entered successfully, false if the user cancelled the confirmation.", + "type": "boolean" + } + } + } + ] + } + ] + }, + { + "name": "get", + "type": "function", + "description": "Gets the value of the setting describing whether managed mode is in effect.", + "parameters": [ + { + "type": "function", + "name": "callback", + "parameters": [ + { + "name": "details", + "type": "object", + "description": "Details of the currently effective value.", + "properties": { + "value": { + "description": "The value of the setting.", + "type": "boolean" + } + } + } + ] + } + ] + } + ] + } +] diff --git a/chrome/common/extensions/api/extension_api.cc b/chrome/common/extensions/api/extension_api.cc index 14a6562..eeece57 100644 --- a/chrome/common/extensions/api/extension_api.cc +++ b/chrome/common/extensions/api/extension_api.cc @@ -118,6 +118,7 @@ ExtensionAPI::ExtensionAPI() { IDR_EXTENSION_API_JSON_EXPERIMENTAL_INPUT_UI, IDR_EXTENSION_API_JSON_EXPERIMENTAL_INPUT_VIRTUALKEYBOARD, IDR_EXTENSION_API_JSON_EXPERIMENTAL_KEYBINDING, + IDR_EXTENSION_API_JSON_EXPERIMENTAL_MANAGED_MODE, IDR_EXTENSION_API_JSON_EXPERIMENTAL_PROCESSES, IDR_EXTENSION_API_JSON_EXPERIMENTAL_RLZ, IDR_EXTENSION_API_JSON_EXPERIMENTAL_SERIAL, diff --git a/chrome/common/extensions/docs/experimental.html b/chrome/common/extensions/docs/experimental.html index 994a901..5703a4a 100644 --- a/chrome/common/extensions/docs/experimental.html +++ b/chrome/common/extensions/docs/experimental.html @@ -243,6 +243,7 @@ on the following experimental APIs: <a href="experimental.extension.html">experimental.extension</a></li><li> <a href="experimental.infobars.html">experimental.infobars</a></li><li> <a href="experimental.keybinding.html">experimental.keybinding</a></li><li> + <a href="experimental.managedMode.html">experimental.managedMode</a></li><li> <a href="experimental.speechInput.html">experimental.speechInput</a></li> </ul> <p> diff --git a/chrome/common/extensions/docs/experimental.managedMode.html b/chrome/common/extensions/docs/experimental.managedMode.html new file mode 100755 index 0000000..f2c77168 --- /dev/null +++ b/chrome/common/extensions/docs/experimental.managedMode.html @@ -0,0 +1,570 @@ +<!DOCTYPE html><!-- This page is a placeholder for generated extensions api doc. Note: + 1) The <head> information in this page is significant, should be uniform + across api docs and should be edited only with knowledge of the + templating mechanism. + 3) All <body>.innerHTML is genereated as an rendering step. If viewed in a + browser, it will be re-generated from the template, json schema and + authored overview content. + 4) The <body>.innerHTML is also generated by an offline step so that this + page may easily be indexed by search engines. +--><html xmlns="http://www.w3.org/1999/xhtml"><head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> + <link href="css/ApiRefStyles.css" rel="stylesheet" type="text/css"> + <link href="css/print.css" rel="stylesheet" type="text/css" media="print"> + <script type="text/javascript" src="../../../third_party/jstemplate/jstemplate_compiled.js"> + </script> + <script type="text/javascript" src="js/api_page_generator.js"></script> + <script type="text/javascript" src="js/bootstrap.js"></script> + <script type="text/javascript" src="js/sidebar.js"></script> + <meta name="description" content="Documentation for the chrome.experimental.managedMode module, which is part of the Google Chrome extension APIs."><title>Managed Mode API - Google Chrome Extensions - Google Code</title></head> + <body> <div id="devModeWarning" class="displayModeWarning"> + You are viewing extension docs in chrome via the 'file:' scheme: are you expecting to see local changes when you refresh? You'll need run chrome with --allow-file-access-from-files. + </div> + <div id="branchWarning" class="displayModeWarning"> + <span>WARNING: This is the <span id="branchName">BETA</span> documentation. + It may not work with the stable release of Chrome.</span> + <select id="branchChooser"> + <option>Choose a different version... + </option><option value="">Stable + </option><option value="beta">Beta + </option><option value="dev">Dev + </option><option value="trunk">Trunk + </option></select> + </div> + <div id="unofficialWarning" class="displayModeWarning"> + <span>WARNING: This is unofficial documentation. It may not work with the + current release of Chrome.</span> + <button id="goToOfficialDocs">Go to the official docs</button> + </div> + <div id="gc-container" class="labs"> + <!-- SUBTEMPLATES: DO NOT MOVE FROM THIS LOCATION --> + <!-- In particular, sub-templates that recurse, must be used by allowing + jstemplate to make a copy of the template in this section which + are not operated on by way of the jsskip="true" --> + <!-- /SUBTEMPLATES --> + <a id="top"></a> + <div id="skipto"> + <a href="#gc-pagecontent">Skip to page content</a> + <a href="#gc-toc">Skip to main navigation</a> + </div> + <!-- API HEADER --> + <table id="header" width="100%" cellspacing="0" border="0"> + <tbody><tr> + <td valign="middle"><a href="http://code.google.com/"><img src="images/code_labs_logo.gif" height="43" width="161" alt="Google Code Labs" style="border:0; margin:0;"></a></td> + <td valign="middle" width="100%" style="padding-left:0.6em;"> + <form action="http://www.google.com/cse" id="cse" style="margin-top:0.5em"> + <div id="gsc-search-box"> + <input type="hidden" name="cx" value="002967670403910741006:61_cvzfqtno"> + <input type="hidden" name="ie" value="UTF-8"> + <input type="text" name="q" value="" size="55"> + <input class="gsc-search-button" type="submit" name="sa" value="Search"> + <br> + <span class="greytext">e.g. "page action" or "tabs"</span> + </div> + </form> + <script type="text/javascript" src="https://www.google.com/jsapi"></script> + <script type="text/javascript">google.load("elements", "1", {packages: "transliteration"});</script> + <script type="text/javascript" src="https://www.google.com/coop/cse/t13n?form=cse&t13n_langs=en"></script> + <script type="text/javascript" src="https://www.google.com/coop/cse/brand?form=cse&lang=en"></script> + </td> + </tr> + </tbody></table> + <div id="codesiteContent" class=""> + <a id="gc-topnav-anchor"></a> + <div id="gc-topnav"> + <h1>Google Chrome Extensions (<a href="http://code.google.com/labs/">Labs</a>)</h1> + <ul id="home" class="gc-topnav-tabs"> + <li id="home_link"> + <a href="index.html" title="Google Chrome Extensions home page">Home</a> + </li> + <li id="docs_link"> + <a href="docs.html" title="Official Google Chrome Extensions documentation">Docs</a> + </li> + <li id="faq_link"> + <a href="faq.html" title="Answers to frequently asked questions about Google Chrome Extensions">FAQ</a> + </li> + <li id="samples_link"> + <a href="samples.html" title="Sample extensions (with source code)">Samples</a> + </li> + <li id="group_link"> + <a href="http://groups.google.com/a/chromium.org/group/chromium-extensions" title="Google Chrome Extensions developer forum">Group</a> + </li> + <li id="so_link"> + <a href="http://stackoverflow.com/questions/tagged/google-chrome-extension" title="[google-chrome-extension] tag on Stack Overflow">Questions?</a> + </li> + </ul> + </div> <!-- end gc-topnav --> + <div class="g-section g-tpl-170"> + <!-- SIDENAV --> + <div class="g-unit g-first" id="gc-toc"> + <ul> + <li><a href="getstarted.html">Getting Started</a></li> + <li><a href="overview.html">Overview</a></li> + <li><a href="whats_new.html">What's New?</a></li> + <li><h2><a href="devguide.html">Developer's Guide</a></h2> + <ul> + <li>Browser UI + <ul> + <li><a href="browserAction.html">Browser Actions</a></li> + <li><a href="contextMenus.html">Context Menus</a></li> + <li><a href="notifications.html">Desktop Notifications</a></li> + <li><a href="omnibox.html">Omnibox</a></li> + <li><a href="options.html">Options Pages</a></li> + <li><a href="override.html">Override Pages</a></li> + <li><a href="pageAction.html">Page Actions</a></li> + </ul> + </li> + <li>Browser Interaction + <ul> + <li><a href="bookmarks.html">Bookmarks</a></li> + <li><a href="cookies.html">Cookies</a></li> + <li><a href="devtools.html">Developer Tools</a></li> + <li><a href="events.html">Events</a></li> + <li><a href="history.html">History</a></li> + <li><a href="management.html">Management</a></li> + <li><a href="tabs.html">Tabs</a></li> + <li><a href="windows.html">Windows</a></li> + </ul> + </li> + <li>Implementation + <ul> + <li><a href="a11y.html">Accessibility</a></li> + <li><a href="background_pages.html">Background Pages</a></li> + <li><a href="content_scripts.html">Content Scripts</a></li> + <li><a href="xhr.html">Cross-Origin XHR</a></li> + <li><a href="i18n.html">Internationalization</a></li> + <li><a href="messaging.html">Message Passing</a></li> + <li><a href="permissions.html">Optional Permissions</a></li> + <li><a href="npapi.html">NPAPI Plugins</a></li> + </ul> + </li> + <li>Finishing + <ul> + <li><a href="hosting.html">Hosting</a></li> + <li><a href="external_extensions.html">Other Deployment Options</a></li> + </ul> + </li> + </ul> + </li> + <li><h2><a href="apps.html">Packaged Apps</a></h2></li> + <li><h2><a href="tutorials.html">Tutorials</a></h2> + <ul> + <li><a href="tut_debugging.html">Debugging</a></li> + <li><a href="tut_analytics.html">Google Analytics</a></li> + <li><a href="tut_oauth.html">OAuth</a></li> + </ul> + </li> + <li><h2>Reference</h2> + <ul> + <li>Formats + <ul> + <li><a href="manifest.html">Manifest Files</a></li> + <li><a href="match_patterns.html">Match Patterns</a></li> + </ul> + </li> + <li><a href="permission_warnings.html">Permission Warnings</a></li> + <li><a href="api_index.html">chrome.* APIs</a></li> + <li><a href="api_other.html">Other APIs</a></li> + </ul> + </li> + <li><h2><a href="samples.html">Samples</a></h2></li> + <div class="line"> </div> + <li><h2>More</h2> + <ul> + <li><a href="http://code.google.com/chrome/webstore/docs/index.html">Chrome Web Store</a></li> + <li><a href="http://code.google.com/chrome/apps/docs/developers_guide.html">Hosted Apps</a></li> + <li><a href="themes.html">Themes</a></li> + </ul> + </li> + </ul> + </div> + <script> + initToggles(); + </script> + <div class="g-unit" id="gc-pagecontent"> + <div id="pageTitle"> + <h1 class="page_title">Managed Mode API</h1> + </div> + <!-- TABLE OF CONTENTS --> + <div id="toc"> + <h2>Contents</h2> + <ol> + <li> + <a href="#manifest">Manifest</a> + <ol> + </ol> + </li><li> + <a href="#about">About Managed Mode</a> + <ol> + </ol> + </li><li> + <a href="#usage">Usage</a> + <ol> + </ol> + </li> + <li> + <a href="#apiReference">API reference: chrome.experimental.managedMode</a> + <ol> + <li> + <a href="#global-methods">Methods</a> + <ol> + <li> + <a href="#method-enter">enter</a> + </li><li> + <a href="#method-get">get</a> + </li> + </ol> + </li> + </ol> + </li> + </ol> + </div> + <!-- /TABLE OF CONTENTS --> + <!-- Standard content lead-in for experimental API pages --> + <!-- STATIC CONTENT PLACEHOLDER --> + <div id="static"><div id="pageData-name" class="pageData">Managed Mode API</div> +<!-- BEGIN AUTHORED CONTENT --> +<p id="classSummary"> + The <code>chrome.experimental.managedMode</code> module allows extensions to + request that the browser enter managed mode, as well as to query whether it + is currently in managed mode. +</p> +<p class="note"> + <b>Note: </b>Extensions cannot request that the browser leave managed mode. + This must be done by the user from within the browser itself. +</p> +<h2 id="manifest">Manifest</h2> +<p> + You must declare the "managedMode" and "experimental" permissions in your + extension's <a href="manifest.html">manifest</a> to use the API. For example: +</p> +<pre>{ + "name": "My extension", + ... + <b>"permissions": [ + "experimental", + "managedMode" + ]</b>, + ... +}</pre> +<h2 id="about">About Managed Mode</h2> +<p> + Managed mode allows one person to manage the Chrome experience for another + person by pre-configuring and then locking a managed User profile. + <span class="todo">For more information about Chrome's managed mode, see + <b>[TBD]</b>.</span> +</p> +<h2 id="usage">Usage</h2> +<p> + Querying managed mode is straightforward. Simply call <code>get()</code>, + providing a callback function to receive the result. For example: +</p> +<pre>chrome.experimental.managedMode.get(function(details) { + if (details.value) + console.log('Managed mode is on.'); + else + console.log('Managed mode is off.'); +});</pre> +<p> + Entering managed mode is a little bit more complex, because if the browser is + already in managed mode, trying to enter it again will have no effect. To + avoid confusing users, it's advisable to check whether your extension can + enter managed mode (i.e., if it is not already in effect), and visually + disable the functionality in your extension if not. You can optionally + provide a callback function to <code>enter()</code> to receive the result. + For example: +</p> +<pre>chrome.experimental.managedMode.get(function(details) { + if (details.value) { + console.log("Managed mode is already in effect."); + } else { + chrome.experimental.managedMode.enter(function(result) { + if (chrome.extension.lastError === undefined) { + if (result.success) + console.log("Hooray, it worked!"); + else + console.log("Oops, the user changed her mind."); + } else { + console.log("Aw, snap!", chrome.extension.lastError); + } + }); + } +});</pre> +<!-- END AUTHORED CONTENT --> +</div> + <!-- API PAGE --> + <div class="apiPage"> + <a name="apiReference"></a> + <h2>API reference: chrome.experimental.managedMode</h2> + <!-- PROPERTIES --> + <!-- /apiGroup --> + <!-- METHODS --> + <div id="methodsTemplate" class="apiGroup"> + <a name="global-methods"></a> + <h3>Methods</h3> + <!-- iterates over all functions --> + <div class="apiItem"> + <a name="method-enter"></a> <!-- method-anchor --> + <h4>enter</h4> + <div class="summary"> + <!-- Note: intentionally longer 80 columns --> + <span>chrome.experimental.managedMode.enter</span>(<span class="optional"><span>function</span> + <var><span>callback</span></var></span>)</div> + <div class="description"> + <p>Shows a confirmation dialog, then puts the browser into managed mode. The callback parameter will be true if managed mode was entered successfully, false if the user cancelled the confirmation. If managed mode is already on, trying to enter it again will have no effect.</p> + <!-- PARAMETERS --> + <h4>Parameters</h4> + <dl> + <div> + <div> + <dt> + <var>callback</var> + <em> + <!-- TYPE --> + <div style="display:inline"> + ( + <span class="optional">optional</span> + <span id="typeTemplate"> + <span> + <span>function</span> + </span> + </span> + ) + </div> + </em> + </dt> + <dd class="todo"> + Undocumented. + </dd> + <!-- OBJECT PROPERTIES --> + <!-- OBJECT METHODS --> + <!-- OBJECT EVENT FIELDS --> + <!-- FUNCTION PARAMETERS --> + </div> + </div> + </dl> + <!-- RETURNS --> + <dl> + </dl> + <!-- CALLBACK --> + <div> + <div> + <h4>Callback function</h4> + <p> + If you specify the <em>callback</em> parameter, it should + specify a function that looks like this: + </p> + <!-- Note: intentionally longer 80 columns --> + <pre>function(<span>object result</span>) <span class="subdued">{...}</span>;</pre> + <dl> + <div> + <div> + <dt> + <var>result</var> + <em> + <!-- TYPE --> + <div style="display:inline"> + ( + <span id="typeTemplate"> + <span> + <span>object</span> + </span> + </span> + ) + </div> + </em> + </dt> + <dd>The result of the attempt to enter managed mode.</dd> + <!-- OBJECT PROPERTIES --> + <dd> + <dl> + <div> + <div> + <dt> + <var>success</var> + <em> + <!-- TYPE --> + <div style="display:inline"> + ( + <span id="typeTemplate"> + <span> + <span>boolean</span> + </span> + </span> + ) + </div> + </em> + </dt> + <dd>True if managed mode was entered successfully, false if the user cancelled the confirmation.</dd> + <!-- OBJECT PROPERTIES --> + <!-- OBJECT METHODS --> + <!-- OBJECT EVENT FIELDS --> + <!-- FUNCTION PARAMETERS --> + </div> + </div> + </dl> + </dd> + <!-- OBJECT METHODS --> + <!-- OBJECT EVENT FIELDS --> + <!-- FUNCTION PARAMETERS --> + </div> + </div> + </dl> + </div> + </div> + <!-- MIN_VERSION --> + </div> <!-- /description --> + </div><div class="apiItem"> + <a name="method-get"></a> <!-- method-anchor --> + <h4>get</h4> + <div class="summary"> + <!-- Note: intentionally longer 80 columns --> + <span>chrome.experimental.managedMode.get</span>(<span class="null"><span>function</span> + <var><span>callback</span></var></span>)</div> + <div class="description"> + <p>Gets the value of the setting describing whether managed mode is in effect.</p> + <!-- PARAMETERS --> + <h4>Parameters</h4> + <dl> + <div> + <div> + <dt> + <var>callback</var> + <em> + <!-- TYPE --> + <div style="display:inline"> + ( + <span id="typeTemplate"> + <span> + <span>function</span> + </span> + </span> + ) + </div> + </em> + </dt> + <dd class="todo"> + Undocumented. + </dd> + <!-- OBJECT PROPERTIES --> + <!-- OBJECT METHODS --> + <!-- OBJECT EVENT FIELDS --> + <!-- FUNCTION PARAMETERS --> + </div> + </div> + </dl> + <!-- RETURNS --> + <dl> + </dl> + <!-- CALLBACK --> + <div> + <div> + <h4>Callback function</h4> + <p> + The callback <em>parameter</em> should specify a function + that looks like this: + </p> + <!-- Note: intentionally longer 80 columns --> + <pre>function(<span>object details</span>) <span class="subdued">{...}</span>;</pre> + <dl> + <div> + <div> + <dt> + <var>details</var> + <em> + <!-- TYPE --> + <div style="display:inline"> + ( + <span id="typeTemplate"> + <span> + <span>object</span> + </span> + </span> + ) + </div> + </em> + </dt> + <dd>Details of the currently effective value.</dd> + <!-- OBJECT PROPERTIES --> + <dd> + <dl> + <div> + <div> + <dt> + <var>value</var> + <em> + <!-- TYPE --> + <div style="display:inline"> + ( + <span id="typeTemplate"> + <span> + <span>boolean</span> + </span> + </span> + ) + </div> + </em> + </dt> + <dd>The value of the setting.</dd> + <!-- OBJECT PROPERTIES --> + <!-- OBJECT METHODS --> + <!-- OBJECT EVENT FIELDS --> + <!-- FUNCTION PARAMETERS --> + </div> + </div> + </dl> + </dd> + <!-- OBJECT METHODS --> + <!-- OBJECT EVENT FIELDS --> + <!-- FUNCTION PARAMETERS --> + </div> + </div> + </dl> + </div> + </div> + <!-- MIN_VERSION --> + </div> <!-- /description --> + </div> <!-- /apiItem --> + </div> <!-- /apiGroup --> + <!-- EVENTS --> + <!-- /apiGroup --> + <!-- TYPES --> + <!-- /apiGroup --> + </div> <!-- /apiPage --> + </div> <!-- /gc-pagecontent --> + </div> <!-- /g-section --> + </div> <!-- /codesiteContent --> + <div id="gc-footer" --=""> + <div class="text"> + <p> + Except as otherwise <a href="http://code.google.com/policies.html#restrictions">noted</a>, + the content of this page is licensed under the <a rel="license" href="http://creativecommons.org/licenses/by/3.0/">Creative Commons + Attribution 3.0 License</a>, and code samples are licensed under the + <a rel="license" href="http://code.google.com/google_bsd_license.html">BSD License</a>. + </p> + <p> + ©2011 Google + </p> +<!-- begin analytics --> +<script src="https://www.google-analytics.com/urchin.js" type="text/javascript"></script> +<script src="https://www.google-analytics.com/ga.js" type="text/javascript"></script> +<script type="text/javascript"> + // chrome doc tracking + try { + var engdocs = _gat._getTracker("YT-10763712-2"); + engdocs._trackPageview(); + } catch(err) {} + // code.google.com site-wide tracking + try { + _uacct="UA-18071-1"; + _uanchor=1; + _uff=0; + urchinTracker(); + } + catch(e) {/* urchinTracker not available. */} +</script> +<!-- end analytics --> + </div> + </div> <!-- /gc-footer --> + </div> <!-- /gc-container --> +</body></html> diff --git a/chrome/common/extensions/docs/js/api_page_generator.js b/chrome/common/extensions/docs/js/api_page_generator.js index 944a54b..51a11a3 100644 --- a/chrome/common/extensions/docs/js/api_page_generator.js +++ b/chrome/common/extensions/docs/js/api_page_generator.js @@ -41,6 +41,7 @@ var MODULE_SCHEMAS = [ '../api/experimental.input.ui.json', '../api/experimental.input.virtualKeyboard.json', '../api/experimental.keybinding.json', + '../api/experimental.managedMode.json', '../api/experimental.processes.json', '../api/experimental.rlz.json', '../api/experimental.serial.json', @@ -242,7 +243,7 @@ function fetchContent(url, onSuccess, onError) { window.clearTimeout(abortTimerId); onSuccess(xhr.responseText); } else { - handleError('Failure to fetch content'); + handleError('Failure to fetch content: ' + xhr.status); } } } diff --git a/chrome/common/extensions/docs/static/experimental.managedMode.html b/chrome/common/extensions/docs/static/experimental.managedMode.html new file mode 100644 index 0000000..ec186b5 --- /dev/null +++ b/chrome/common/extensions/docs/static/experimental.managedMode.html @@ -0,0 +1,81 @@ +<div id="pageData-name" class="pageData">Managed Mode API</div> + +<!-- BEGIN AUTHORED CONTENT --> +<p id="classSummary"> + The <code>chrome.experimental.managedMode</code> module allows extensions to + request that the browser enter managed mode, as well as to query whether it + is currently in managed mode. +</p> + +<p class="note"> + <b>Note: </b>Extensions cannot request that the browser leave managed mode. + This must be done by the user from within the browser itself. +</p> + +<h2 id="manifest">Manifest</h2> +<p> + You must declare the "managedMode" and "experimental" permissions in your + extension's <a href="manifest.html">manifest</a> to use the API. For example: +</p> + +<pre>{ + "name": "My extension", + ... + <b>"permissions": [ + "experimental", + "managedMode" + ]</b>, + ... +}</pre> + +<h2 id="about">About Managed Mode</h2> + +<p> + Managed mode allows one person to manage the Chrome experience for another + person by pre-configuring and then locking a managed User profile. + + <span class="todo">For more information about Chrome's managed mode, see + <b>[TBD]</b>.</span> +</p> + +<h2 id="usage">Usage</h2> + +<p> + Querying managed mode is straightforward. Simply call <code>get()</code>, + providing a callback function to receive the result. For example: +</p> + +<pre>chrome.experimental.managedMode.get(function(details) { + if (details.value) + console.log('Managed mode is on.'); + else + console.log('Managed mode is off.'); +});</pre> + +<p> + Entering managed mode is a little bit more complex, because if the browser is + already in managed mode, trying to enter it again will have no effect. To + avoid confusing users, it's advisable to check whether your extension can + enter managed mode (i.e., if it is not already in effect), and visually + disable the functionality in your extension if not. You can optionally + provide a callback function to <code>enter()</code> to receive the result. + For example: +</p> + +<pre>chrome.experimental.managedMode.get(function(details) { + if (details.value) { + console.log("Managed mode is already in effect."); + } else { + chrome.experimental.managedMode.enter(function(result) { + if (chrome.extension.lastError === undefined) { + if (result.success) + console.log("Hooray, it worked!"); + else + console.log("Oops, the user changed her mind."); + } else { + console.log("Aw, snap!", chrome.extension.lastError); + } + }); + } +});</pre> +<!-- END AUTHORED CONTENT --> diff --git a/chrome/common/extensions/extension_permission_set.cc b/chrome/common/extensions/extension_permission_set.cc index c4e4513..18e1fec 100644 --- a/chrome/common/extensions/extension_permission_set.cc +++ b/chrome/common/extensions/extension_permission_set.cc @@ -241,6 +241,9 @@ void ExtensionAPIPermission::RegisterAllPermissions( kInput, "input", 0, ExtensionPermissionMessage::kNone, kFlagImpliesFullURLAccess, kTypeDefault); info->RegisterPermission( + kManagedMode, "managedMode", IDS_EXTENSION_PROMPT_WARNING_MANAGED_MODE, + ExtensionPermissionMessage::kManagedMode, kFlagNone, kTypeDefault); + info->RegisterPermission( kManagement, "management", IDS_EXTENSION_PROMPT_WARNING_MANAGEMENT, ExtensionPermissionMessage::kManagement, kFlagNone, kTypeDefault); info->RegisterPermission( diff --git a/chrome/common/extensions/extension_permission_set.h b/chrome/common/extensions/extension_permission_set.h index 12e540d..c219698 100644 --- a/chrome/common/extensions/extension_permission_set.h +++ b/chrome/common/extensions/extension_permission_set.h @@ -51,6 +51,7 @@ class ExtensionPermissionMessage { kContentSettings, kAllPageContent, kPrivacy, + kManagedMode, kEnumBoundary }; @@ -117,6 +118,7 @@ class ExtensionAPIPermission { kInput, kInputMethodPrivate, kKeybinding, + kManagedMode, kManagement, kMediaPlayerPrivate, kMetricsPrivate, diff --git a/chrome/test/data/extensions/api_test/managedMode/manifest.json b/chrome/test/data/extensions/api_test/managedMode/manifest.json new file mode 100644 index 0000000..a61add2 --- /dev/null +++ b/chrome/test/data/extensions/api_test/managedMode/manifest.json @@ -0,0 +1,10 @@ +{ + "name" : "Managed Mode API Test Extension", + "version" : "0.1", + "manifest_version": 2, + "description" : "Managed Mode API Test Extension", + "permissions": [ "managedMode", "experimental" ], + "background": { + "scripts": ["test.js"] + } +} diff --git a/chrome/test/data/extensions/api_test/managedMode/test.js b/chrome/test/data/extensions/api_test/managedMode/test.js new file mode 100644 index 0000000..c54f58d --- /dev/null +++ b/chrome/test/data/extensions/api_test/managedMode/test.js @@ -0,0 +1,38 @@ +// 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. + +// Managed Mode API test +// Run with browser_tests --gtest_filter=ExtensionApiTest.ManagedModeApi + +var managedMode = chrome.experimental.managedMode; + +function expect(expected, message) { + return chrome.test.callbackPass(function(value) { + chrome.test.assertEq(expected, value, message); + }); +} + +chrome.test.runTests([ + function disabledByDefault() { + managedMode.get(expect({value: false}, + 'Managed mode should be disabled.')); + }, + + // This will need to be modified once entering managed mode requires user + // confirmation. + function enteringSucceeds() { + managedMode.enter(expect({success: true}, + 'Should be able to enter managed mode.')); + + managedMode.get(expect({value: true}, + 'Managed mode should be on once it has been entered.')); + }, + + function enterTwice() { + managedMode.enter(expect({success: true}, + 'Should be able to enter managed mode.')); + managedMode.enter(expect({success: true}, + 'Should be able to enter managed mode twice.')); + } +]); |