summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormitchellwrosen@chromium.org <mitchellwrosen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-06-26 22:23:32 +0000
committermitchellwrosen@chromium.org <mitchellwrosen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-06-26 22:23:32 +0000
commit42c037eda3b65f09821596d2062a9f26db10a128 (patch)
tree76afa64c457346eb9402712c28702be8d1c91bcb
parentfd85fa30ce6f4a1906ed239b8f73233f1146bfc9 (diff)
downloadchromium_src-42c037eda3b65f09821596d2062a9f26db10a128.zip
chromium_src-42c037eda3b65f09821596d2062a9f26db10a128.tar.gz
chromium_src-42c037eda3b65f09821596d2062a9f26db10a128.tar.bz2
Split mode incognito extension can get misleading pref changed events from regular mode
I implemented the behavior described in comment 6 here: http://code.google.com/p/chromium/issues/detail?id=128017 BUG=128017 TEST=Manual Review URL: https://chromiumcodereview.appspot.com/10559052 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@144299 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/extensions/extension_event_router.cc3
-rw-r--r--chrome/browser/extensions/extension_pref_value_map.cc5
-rw-r--r--chrome/browser/extensions/extension_pref_value_map.h7
-rw-r--r--chrome/browser/extensions/extension_pref_value_map_unittest.cc20
-rw-r--r--chrome/browser/extensions/extension_preference_apitest.cc127
-rw-r--r--chrome/browser/extensions/extension_preference_helpers.cc34
-rw-r--r--chrome/browser/extensions/extension_prefs.cc4
-rw-r--r--chrome/browser/extensions/extension_prefs.h7
-rw-r--r--chrome/browser/prefs/pref_notifier_impl.cc3
-rw-r--r--chrome/test/data/extensions/api_test/preference/onchange/manifest.json2
-rw-r--r--chrome/test/data/extensions/api_test/preference/onchange/test.html6
-rw-r--r--chrome/test/data/extensions/api_test/preference/onchange_split/manifest.json11
-rw-r--r--chrome/test/data/extensions/api_test/preference/onchange_split/test.js191
13 files changed, 386 insertions, 34 deletions
diff --git a/chrome/browser/extensions/extension_event_router.cc b/chrome/browser/extensions/extension_event_router.cc
index 9dab54c..166d378 100644
--- a/chrome/browser/extensions/extension_event_router.cc
+++ b/chrome/browser/extensions/extension_event_router.cc
@@ -381,8 +381,9 @@ void ExtensionEventRouter::DispatchEventToListener(
const Value* event_args = NULL;
if (!CanDispatchEventToProfile(listener_profile, extension,
- event, &event_args))
+ event, &event_args)) {
return;
+ }
DispatchEvent(listener.process, listener.extension_id,
event->event_name, *event_args,
diff --git a/chrome/browser/extensions/extension_pref_value_map.cc b/chrome/browser/extensions/extension_pref_value_map.cc
index 2965471..18586e0 100644
--- a/chrome/browser/extensions/extension_pref_value_map.cc
+++ b/chrome/browser/extensions/extension_pref_value_map.cc
@@ -102,9 +102,10 @@ void ExtensionPrefValueMap::ClearAllIncognitoSessionOnlyPreferences() {
bool ExtensionPrefValueMap::DoesExtensionControlPref(
const std::string& extension_id,
const std::string& pref_key,
- bool incognito) const {
+ bool* from_incognito) const {
+ bool incognito = (from_incognito != NULL);
ExtensionEntryMap::const_iterator winner =
- GetEffectivePrefValueController(pref_key, incognito, NULL);
+ GetEffectivePrefValueController(pref_key, incognito, from_incognito);
if (winner == entries_.end())
return false;
return winner->first == extension_id;
diff --git a/chrome/browser/extensions/extension_pref_value_map.h b/chrome/browser/extensions/extension_pref_value_map.h
index 2cde315..5785bb7 100644
--- a/chrome/browser/extensions/extension_pref_value_map.h
+++ b/chrome/browser/extensions/extension_pref_value_map.h
@@ -109,13 +109,16 @@ class ExtensionPrefValueMap : public ProfileKeyedService {
// Returns true if an extension identified by |extension_id| controls the
// preference. This means this extension has set a preference value and no
- // other extension with higher precedence overrides it.
+ // other extension with higher precedence overrides it. If |from_incognito|
+ // is not NULL, looks at incognito preferences first, and |from_incognito| is
+ // set to true if the effective pref value is coming from the incognito
+ // preferences, false if it is coming from the normal ones.
// Note that the this function does does not consider the existence of
// policies. An extension is only really able to control a preference if
// PrefService::Preference::IsExtensionModifiable() returns true as well.
bool DoesExtensionControlPref(const std::string& extension_id,
const std::string& pref_key,
- bool incognito) const;
+ bool* from_incognito) const;
// Tell the store it's now fully initialized.
void NotifyInitializationCompleted();
diff --git a/chrome/browser/extensions/extension_pref_value_map_unittest.cc b/chrome/browser/extensions/extension_pref_value_map_unittest.cc
index a295c94..d457347 100644
--- a/chrome/browser/extensions/extension_pref_value_map_unittest.cc
+++ b/chrome/browser/extensions/extension_pref_value_map_unittest.cc
@@ -33,13 +33,13 @@ static base::Time CreateTime(int64 t) {
template <typename BASECLASS>
class ExtensionPrefValueMapTestBase : public BASECLASS {
public:
- const static ExtensionPrefsScope kRegular =
+ static const ExtensionPrefsScope kRegular =
kExtensionPrefsScopeRegular;
- const static ExtensionPrefsScope kRegularOnly =
+ static const ExtensionPrefsScope kRegularOnly =
kExtensionPrefsScopeRegularOnly;
- const static ExtensionPrefsScope kIncognitoPersistent =
+ static const ExtensionPrefsScope kIncognitoPersistent =
kExtensionPrefsScopeIncognitoPersistent;
- const static ExtensionPrefsScope kIncognitoSessionOnly =
+ static const ExtensionPrefsScope kIncognitoSessionOnly =
kExtensionPrefsScopeIncognitoSessionOnly;
// Returns an empty string if the key is not set.
@@ -112,18 +112,18 @@ TEST_F(ExtensionPrefValueMapTest, OverrideChecks) {
epvm_.RegisterExtension(kExt2, CreateTime(20), true);
epvm_.RegisterExtension(kExt3, CreateTime(30), true);
- EXPECT_FALSE(epvm_.DoesExtensionControlPref(kExt1, kPref1, false));
- EXPECT_FALSE(epvm_.DoesExtensionControlPref(kExt2, kPref1, false));
- EXPECT_FALSE(epvm_.DoesExtensionControlPref(kExt3, kPref1, false));
+ EXPECT_FALSE(epvm_.DoesExtensionControlPref(kExt1, kPref1, NULL));
+ EXPECT_FALSE(epvm_.DoesExtensionControlPref(kExt2, kPref1, NULL));
+ EXPECT_FALSE(epvm_.DoesExtensionControlPref(kExt3, kPref1, NULL));
EXPECT_TRUE(epvm_.CanExtensionControlPref(kExt1, kPref1, false));
EXPECT_TRUE(epvm_.CanExtensionControlPref(kExt2, kPref1, false));
EXPECT_TRUE(epvm_.CanExtensionControlPref(kExt3, kPref1, false));
epvm_.SetExtensionPref(kExt2, kPref1, kRegular, CreateVal("val1"));
- EXPECT_FALSE(epvm_.DoesExtensionControlPref(kExt1, kPref1, false));
- EXPECT_TRUE(epvm_.DoesExtensionControlPref(kExt2, kPref1, false));
- EXPECT_FALSE(epvm_.DoesExtensionControlPref(kExt3, kPref1, false));
+ EXPECT_FALSE(epvm_.DoesExtensionControlPref(kExt1, kPref1, NULL));
+ EXPECT_TRUE(epvm_.DoesExtensionControlPref(kExt2, kPref1, NULL));
+ EXPECT_FALSE(epvm_.DoesExtensionControlPref(kExt3, kPref1, NULL));
EXPECT_FALSE(epvm_.CanExtensionControlPref(kExt1, kPref1, false));
EXPECT_TRUE(epvm_.CanExtensionControlPref(kExt2, kPref1, false));
EXPECT_TRUE(epvm_.CanExtensionControlPref(kExt3, kPref1, false));
diff --git a/chrome/browser/extensions/extension_preference_apitest.cc b/chrome/browser/extensions/extension_preference_apitest.cc
index 59ffdcd..8b63e9c 100644
--- a/chrome/browser/extensions/extension_preference_apitest.cc
+++ b/chrome/browser/extensions/extension_preference_apitest.cc
@@ -4,11 +4,13 @@
#include "base/utf_string_conversions.h"
#include "chrome/browser/extensions/extension_apitest.h"
+#include "chrome/browser/extensions/extension_test_message_listener.h"
#include "chrome/browser/prefs/pref_service.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h"
+#include "chrome/test/base/ui_test_utils.h"
#include "webkit/plugins/npapi/mock_plugin_list.h"
IN_PROC_BROWSER_TEST_F(ExtensionApiTest, PreferenceApi) {
@@ -110,9 +112,128 @@ IN_PROC_BROWSER_TEST_F(ExtensionApiTest, PreferenceClear) {
}
IN_PROC_BROWSER_TEST_F(ExtensionApiTest, PreferenceOnChange) {
- PrefService* prefs = browser()->profile()->GetPrefs();
- prefs->SetBoolean(prefs::kBlockThirdPartyCookies, false);
-
EXPECT_TRUE(RunExtensionTestIncognito("preference/onchange")) <<
message_;
}
+
+IN_PROC_BROWSER_TEST_F(ExtensionApiTest, PreferenceOnChangeSplit) {
+ ResultCatcher catcher;
+ catcher.RestrictToProfile(browser()->profile());
+ ResultCatcher catcher_incognito;
+ catcher_incognito.RestrictToProfile(
+ browser()->profile()->GetOffTheRecordProfile());
+
+ // Open an incognito window.
+ ui_test_utils::OpenURLOffTheRecord(browser()->profile(),
+ GURL("chrome://newtab/"));
+
+ // changeDefault listeners.
+ ExtensionTestMessageListener listener1("changeDefault regular ready", true);
+ ExtensionTestMessageListener listener_incognito1(
+ "changeDefault incognito ready", true);
+
+ // changeIncognitoOnly listeners.
+ ExtensionTestMessageListener listener2(
+ "changeIncognitoOnly regular ready", true);
+ ExtensionTestMessageListener listener_incognito2(
+ "changeIncognitoOnly incognito ready", true);
+ ExtensionTestMessageListener listener3(
+ "changeIncognitoOnly regular listening", true);
+ ExtensionTestMessageListener listener_incognito3(
+ "changeIncognitoOnly incognito pref set", false);
+
+ // changeDefaultOnly listeners.
+ ExtensionTestMessageListener listener4(
+ "changeDefaultOnly regular ready", true);
+ ExtensionTestMessageListener listener_incognito4(
+ "changeDefaultOnly incognito ready", true);
+ ExtensionTestMessageListener listener5(
+ "changeDefaultOnly regular pref set", false);
+ ExtensionTestMessageListener listener_incognito5(
+ "changeDefaultOnly incognito listening", true);
+
+ // changeIncognitoOnlyBack listeners.
+ ExtensionTestMessageListener listener6(
+ "changeIncognitoOnlyBack regular ready", true);
+ ExtensionTestMessageListener listener_incognito6(
+ "changeIncognitoOnlyBack incognito ready", true);
+ ExtensionTestMessageListener listener7(
+ "changeIncognitoOnlyBack regular listening", true);
+ ExtensionTestMessageListener listener_incognito7(
+ "changeIncognitoOnlyBack incognito pref set", false);
+
+ // clearIncognito listeners.
+ ExtensionTestMessageListener listener8(
+ "clearIncognito regular ready", true);
+ ExtensionTestMessageListener listener_incognito8(
+ "clearIncognito incognito ready", true);
+ ExtensionTestMessageListener listener9(
+ "clearIncognito regular listening", true);
+ ExtensionTestMessageListener listener_incognito9(
+ "clearIncognito incognito pref cleared", false);
+
+ // clearDefault listeners.
+ ExtensionTestMessageListener listener10(
+ "clearDefault regular ready", true);
+ ExtensionTestMessageListener listener_incognito10(
+ "clearDefault incognito ready", true);
+
+ FilePath extension_data_dir =
+ test_data_dir_.AppendASCII("preference").AppendASCII("onchange_split");
+ ASSERT_TRUE(LoadExtensionIncognito(extension_data_dir));
+
+ // Test 1 - changeDefault
+ EXPECT_TRUE(listener1.WaitUntilSatisfied()); // Regular ready
+ EXPECT_TRUE(listener_incognito1.WaitUntilSatisfied()); // Incognito ready
+ listener1.Reply("ok");
+ listener_incognito1.Reply("ok");
+
+ // Test 2 - changeIncognitoOnly
+ EXPECT_TRUE(listener2.WaitUntilSatisfied()); // Regular ready
+ EXPECT_TRUE(listener_incognito2.WaitUntilSatisfied()); // Incognito ready
+ EXPECT_TRUE(listener3.WaitUntilSatisfied()); // Regular listening
+ listener2.Reply("ok");
+ listener_incognito2.Reply("ok");
+ // Incognito preference set -- notify the regular listener
+ EXPECT_TRUE(listener_incognito3.WaitUntilSatisfied());
+ listener3.Reply("ok");
+
+ // Test 3 - changeDefaultOnly
+ EXPECT_TRUE(listener4.WaitUntilSatisfied()); // Regular ready
+ EXPECT_TRUE(listener_incognito4.WaitUntilSatisfied()); // Incognito ready
+ EXPECT_TRUE(listener_incognito5.WaitUntilSatisfied()); // Incognito listening
+ listener4.Reply("ok");
+ listener_incognito4.Reply("ok");
+ // Regular preference set - notify the incognito listener
+ EXPECT_TRUE(listener5.WaitUntilSatisfied());
+ listener_incognito5.Reply("ok");
+
+ // Test 4 - changeIncognitoOnlyBack
+ EXPECT_TRUE(listener6.WaitUntilSatisfied()); // Regular ready
+ EXPECT_TRUE(listener_incognito6.WaitUntilSatisfied()); // Incognito ready
+ EXPECT_TRUE(listener7.WaitUntilSatisfied()); // Regular listening
+ listener6.Reply("ok");
+ listener_incognito6.Reply("ok");
+ // Incognito preference set -- notify the regular listener
+ EXPECT_TRUE(listener_incognito7.WaitUntilSatisfied());
+ listener7.Reply("ok");
+
+ // Test 5 - clearIncognito
+ EXPECT_TRUE(listener8.WaitUntilSatisfied()); // Regular ready
+ EXPECT_TRUE(listener_incognito8.WaitUntilSatisfied()); // Incognito ready
+ EXPECT_TRUE(listener9.WaitUntilSatisfied()); // Regular listening
+ listener8.Reply("ok");
+ listener_incognito8.Reply("ok");
+ // Incognito preference cleared -- notify the regular listener
+ EXPECT_TRUE(listener_incognito9.WaitUntilSatisfied());
+ listener9.Reply("ok");
+
+ // Test 6 - clearDefault
+ EXPECT_TRUE(listener10.WaitUntilSatisfied()); // Regular ready
+ EXPECT_TRUE(listener_incognito10.WaitUntilSatisfied()); // Incognito ready
+ listener10.Reply("ok");
+ listener_incognito10.Reply("ok");
+
+ EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
+ EXPECT_TRUE(catcher_incognito.GetNextResult()) << catcher.message();
+}
diff --git a/chrome/browser/extensions/extension_preference_helpers.cc b/chrome/browser/extensions/extension_preference_helpers.cc
index 44fe036..bbfbd06 100644
--- a/chrome/browser/extensions/extension_preference_helpers.cc
+++ b/chrome/browser/extensions/extension_preference_helpers.cc
@@ -51,6 +51,8 @@ const char* GetLevelOfControl(
bool incognito) {
PrefService* prefs = incognito ? profile->GetOffTheRecordPrefs()
: profile->GetPrefs();
+ bool from_incognito = false;
+ bool* from_incognito_ptr = incognito ? &from_incognito : NULL;
const PrefService::Preference* pref =
prefs->FindPreference(browser_pref.c_str());
CHECK(pref);
@@ -59,8 +61,11 @@ const char* GetLevelOfControl(
if (!pref->IsExtensionModifiable())
return kNotControllable;
- if (ep->DoesExtensionControlPref(extension_id, browser_pref, incognito))
+ if (ep->DoesExtensionControlPref(extension_id,
+ browser_pref,
+ from_incognito_ptr)) {
return kControlledByThisExtension;
+ }
if (ep->CanExtensionControlPref(extension_id, browser_pref, incognito))
return kControllableByThisExtension;
@@ -80,13 +85,15 @@ void DispatchEventToExtensions(
return;
ExtensionService* extension_service = profile->GetExtensionService();
const ExtensionSet* extensions = extension_service->extensions();
+ ExtensionPrefs* extension_prefs = extension_service->extension_prefs();
for (ExtensionSet::const_iterator it = extensions->begin();
it != extensions->end(); ++it) {
std::string extension_id = (*it)->id();
// TODO(bauerb): Only iterate over registered event listeners.
if (router->ExtensionHasEventListener(extension_id, event_name) &&
(*it)->HasAPIPermission(permission) &&
- (!incognito || extension_service->CanCrossIncognito(*it))) {
+ (!incognito || (*it)->incognito_split_mode() ||
+ extension_service->CanCrossIncognito(*it))) {
// Inject level of control key-value.
DictionaryValue* dict;
bool rv = args->GetDictionary(0, &dict);
@@ -94,11 +101,30 @@ void DispatchEventToExtensions(
std::string level_of_control =
GetLevelOfControl(profile, extension_id, browser_pref, incognito);
dict->SetString(kLevelOfControlKey, level_of_control);
-
std::string json_args;
base::JSONWriter::Write(args, &json_args);
+
+ // If the extension is in incognito split mode,
+ // a) incognito pref changes are visible only to the incognito tabs
+ // b) regular pref changes are visible only to the incognito tabs if the
+ // incognito pref has not alredy been set
+ Profile* restrict_to_profile = NULL;
+ bool from_incognito = false;
+ if ((*it)->incognito_split_mode()) {
+ if (incognito && extension_service->IsIncognitoEnabled(extension_id)) {
+ restrict_to_profile = profile->GetOffTheRecordProfile();
+ } else if (!incognito &&
+ extension_prefs->DoesExtensionControlPref(
+ extension_id,
+ browser_pref,
+ &from_incognito) &&
+ from_incognito) {
+ restrict_to_profile = profile;
+ }
+ }
+
router->DispatchEventToExtension(
- extension_id, event_name, json_args, NULL, GURL());
+ extension_id, event_name, json_args, restrict_to_profile, GURL());
}
}
}
diff --git a/chrome/browser/extensions/extension_prefs.cc b/chrome/browser/extensions/extension_prefs.cc
index 18313ee..1efc4ae 100644
--- a/chrome/browser/extensions/extension_prefs.cc
+++ b/chrome/browser/extensions/extension_prefs.cc
@@ -1811,14 +1811,14 @@ bool ExtensionPrefs::CanExtensionControlPref(const std::string& extension_id,
bool ExtensionPrefs::DoesExtensionControlPref(const std::string& extension_id,
const std::string& pref_key,
- bool incognito) {
+ bool* from_incognito) {
DCHECK(pref_service()->FindPreference(pref_key.c_str()))
<< "Extension controlled preference key " << pref_key
<< " not registered.";
return extension_pref_value_map_->DoesExtensionControlPref(extension_id,
pref_key,
- incognito);
+ from_incognito);
}
bool ExtensionPrefs::HasIncognitoPrefValue(const std::string& pref_key) {
diff --git a/chrome/browser/extensions/extension_prefs.h b/chrome/browser/extensions/extension_prefs.h
index ae7f626..429131a 100644
--- a/chrome/browser/extensions/extension_prefs.h
+++ b/chrome/browser/extensions/extension_prefs.h
@@ -382,10 +382,13 @@ class ExtensionPrefs : public extensions::ContentSettingsStore::Observer,
bool incognito);
// Returns true if extension |extension_id| currently controls the
- // preference.
+ // preference. If |from_incognito| is not NULL, looks at incognito preferences
+ // first, and |from_incognito| is set to true if the effective pref value is
+ // coming from the incognito preferences, false if it is coming from the
+ // normal ones.
bool DoesExtensionControlPref(const std::string& extension_id,
const std::string& pref_key,
- bool incognito);
+ bool* from_incognito);
// Returns true if there is an extension which controls the preference value
// for |pref_key| *and* it is specific to incognito mode.
diff --git a/chrome/browser/prefs/pref_notifier_impl.cc b/chrome/browser/prefs/pref_notifier_impl.cc
index 3c23879..a226685 100644
--- a/chrome/browser/prefs/pref_notifier_impl.cc
+++ b/chrome/browser/prefs/pref_notifier_impl.cc
@@ -1,9 +1,10 @@
-// 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.
#include "chrome/browser/prefs/pref_notifier_impl.h"
+#include "base/logging.h"
#include "base/stl_util.h"
#include "chrome/browser/prefs/pref_service.h"
#include "chrome/common/chrome_notification_types.h"
diff --git a/chrome/test/data/extensions/api_test/preference/onchange/manifest.json b/chrome/test/data/extensions/api_test/preference/onchange/manifest.json
index 7c8641fcb..ab918e8 100644
--- a/chrome/test/data/extensions/api_test/preference/onchange/manifest.json
+++ b/chrome/test/data/extensions/api_test/preference/onchange/manifest.json
@@ -5,6 +5,6 @@
"description" : "Preferences API Test Extension (Events)",
"permissions": [ "privacy" ],
"background": {
- "page": "test.html"
+ "scripts": [ "test.js" ]
}
}
diff --git a/chrome/test/data/extensions/api_test/preference/onchange/test.html b/chrome/test/data/extensions/api_test/preference/onchange/test.html
deleted file mode 100644
index 3efb342..0000000
--- a/chrome/test/data/extensions/api_test/preference/onchange/test.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<!--
- * Copyright (c) 2011 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.
--->
-<script src="test.js"></script>
diff --git a/chrome/test/data/extensions/api_test/preference/onchange_split/manifest.json b/chrome/test/data/extensions/api_test/preference/onchange_split/manifest.json
new file mode 100644
index 0000000..ee3b050
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/preference/onchange_split/manifest.json
@@ -0,0 +1,11 @@
+{
+ "name" : "Preferences API Test Extension (Events)",
+ "version" : "0.1",
+ "manifest_version": 2,
+ "description" : "Preferences API Test Extension (Events)",
+ "permissions": [ "privacy", "tabs" ],
+ "background": {
+ "scripts": [ "test.js" ]
+ },
+ "incognito": "split"
+}
diff --git a/chrome/test/data/extensions/api_test/preference/onchange_split/test.js b/chrome/test/data/extensions/api_test/preference/onchange_split/test.js
new file mode 100644
index 0000000..6067887
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/preference/onchange_split/test.js
@@ -0,0 +1,191 @@
+// 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.
+
+// Content settings API test
+// browser_tests.exe --gtest_filter=ExtensionApiTest.PreferenceOnChangeSplit
+
+var inIncognitoContext = chrome.extension.inIncognitoContext;
+var pass = chrome.test.callbackPass;
+var sendMessage = chrome.test.sendMessage;
+var allowCookies = chrome.privacy.websites.thirdPartyCookiesAllowed;
+
+// Listen until |event| has fired with all of the values in |expected|.
+function listenUntil(event, expected) {
+ var done = chrome.test.listenForever(event, function(value) {
+ for (var i = 0; i < expected.length; i++) {
+ if (chrome.test.checkDeepEq(expected[i], value)) {
+ expected.splice(i, 1);
+ if (expected.length == 0)
+ done();
+ return;
+ }
+ }
+ chrome.test.fail("Unexpected event: " + JSON.stringify(value));
+ });
+}
+
+// Fail if |event| is fired (with any values). Because listenUntil stops
+// listening when |event| has fired with all the values in |expected|, it may
+// not capture superfluous unexpected events.
+function listenAndFailWhen(event) {
+ return chrome.test.listenForever(event, function(value) {
+ chrome.test.fail("Unexpected event: " + JSON.stringify(value));
+ });
+}
+
+// Constructs messages to be sent via chrome.test.sendMessage
+function constructMessage(str, caller) {
+ caller = caller || arguments.callee.caller.name;
+ var incognitoStr = inIncognitoContext ? " incognito " : " regular ";
+ console.log(caller + incognitoStr + str);
+ return caller + incognitoStr + str;
+}
+
+chrome.test.runTests([
+ // Changing the regular settings when no incognito-specific settings are
+ // defined should fire one event in the regular window, and two in the
+ // incognito.
+ function changeDefault() {
+ var expected = [{
+ 'value': false,
+ 'levelOfControl': 'controlled_by_this_extension'
+ }];
+
+ if (inIncognitoContext) {
+ expected.push({
+ 'value': false,
+ 'incognitoSpecific': false,
+ 'levelOfControl': 'controlled_by_this_extension'
+ });
+ }
+
+ listenUntil(allowCookies.onChange, expected);
+
+ sendMessage(constructMessage("ready"), pass(function() {
+ if (!inIncognitoContext) {
+ allowCookies.set({
+ 'value': false
+ }, pass());
+ }
+ }));
+ },
+
+ // Changing incognito-specific settings should only be visible to the
+ // incognito window.
+ function changeIncognitoOnly() {
+ if (!inIncognitoContext) {
+ var done = listenAndFailWhen(allowCookies.onChange);
+ sendMessage(constructMessage("listening"), done);
+ } else {
+ listenUntil(allowCookies.onChange, [{
+ 'value': true,
+ 'incognitoSpecific': true,
+ 'levelOfControl': 'controlled_by_this_extension'
+ }]);
+ }
+
+ sendMessage(constructMessage("ready"), pass(function() {
+ if (inIncognitoContext) {
+ allowCookies.set({
+ 'value': true,
+ 'scope': 'incognito_session_only'
+ }, pass(sendMessage(constructMessage("pref set", "changeIncognitoOnly"),
+ pass())));
+ }
+ }));
+ },
+
+ // Changing the regular settings when incognito-specific settings are
+ // defined should only be visible to the regular window.
+ function changeDefaultOnly() {
+ if (!inIncognitoContext) {
+ listenUntil(allowCookies.onChange, [{
+ 'value': true,
+ 'levelOfControl': 'controlled_by_this_extension'
+ }]);
+ } else {
+ var done = listenAndFailWhen(allowCookies.onChange);
+ sendMessage(constructMessage("listening"), done);
+ }
+
+ sendMessage(constructMessage("ready"), pass(function() {
+ if (!inIncognitoContext) {
+ allowCookies.set({
+ 'value': true
+ }, pass(sendMessage(constructMessage("pref set", "changeDefaultOnly"),
+ pass())));
+ }
+ }));
+ },
+
+ // Change the incognito setting back to false so that we get an event when
+ // clearing the value. Should not be visible to regular window.
+ function changeIncognitoOnlyBack() {
+ if (!inIncognitoContext) {
+ var done = listenAndFailWhen(allowCookies.onChange);
+ sendMessage(constructMessage("listening"), done);
+ } else {
+ listenUntil(allowCookies.onChange, [{
+ 'value': false,
+ 'incognitoSpecific': true,
+ 'levelOfControl': 'controlled_by_this_extension'
+ }]);
+ }
+
+ sendMessage(constructMessage("ready"), pass(function() {
+ if (inIncognitoContext) {
+ allowCookies.set({
+ 'value': false,
+ 'scope': 'incognito_session_only'
+ }, pass(sendMessage(constructMessage("pref set",
+ "changeIncognitoOnlyBack"),
+ pass())));
+ }
+ }));
+ },
+
+ function clearIncognito() {
+ if (!inIncognitoContext) {
+ var done = listenAndFailWhen(allowCookies.onChange);
+ sendMessage(constructMessage("listening"), done);
+ } else {
+ listenUntil(allowCookies.onChange, [{
+ 'value': true,
+ 'incognitoSpecific': false,
+ 'levelOfControl': 'controlled_by_this_extension'
+ }]);
+ }
+
+ sendMessage(constructMessage("ready"), pass(function() {
+ if (inIncognitoContext) {
+ allowCookies.clear({
+ 'scope': 'incognito_session_only'
+ }, pass(sendMessage(constructMessage("pref cleared", "clearIncognito"),
+ pass())));
+ }
+ }));
+ },
+
+ function clearDefault() {
+ var expected = [{
+ 'value': true,
+ 'levelOfControl': 'controllable_by_this_extension'
+ }];
+
+ if (inIncognitoContext) {
+ expected[1] = {
+ 'value': true,
+ 'incognitoSpecific': false,
+ 'levelOfControl': 'controllable_by_this_extension'
+ };
+ }
+
+ listenUntil(allowCookies.onChange, expected);
+
+ sendMessage(constructMessage("ready"), pass(function() {
+ if (!inIncognitoContext)
+ allowCookies.clear({}, pass());
+ }));
+ }
+]);