Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(788)

Side by Side Diff: chrome/browser/content_settings/host_content_settings_map.cc

Issue 7713034: HostContentSettingsMap refactoring. (Closed) Base URL: http://git.chromium.org/git/chromium.git@trunk
Patch Set: Created 9 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/content_settings/host_content_settings_map.h" 5 #include "chrome/browser/content_settings/host_content_settings_map.h"
6 6
7 #include <list> 7 #include <list>
8 8
9 #include "base/command_line.h" 9 #include "base/command_line.h"
10 #include "base/string_util.h" 10 #include "base/string_util.h"
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
66 "preference" 66 "preference"
67 }; 67 };
68 68
69 } // namespace 69 } // namespace
70 70
71 HostContentSettingsMap::HostContentSettingsMap( 71 HostContentSettingsMap::HostContentSettingsMap(
72 PrefService* prefs, 72 PrefService* prefs,
73 ExtensionService* extension_service, 73 ExtensionService* extension_service,
74 bool incognito) 74 bool incognito)
75 : prefs_(prefs), 75 : prefs_(prefs),
76 is_off_the_record_(incognito), 76 is_off_the_record_(incognito) {
77 updating_preferences_(false),
78 block_third_party_cookies_(false),
79 is_block_third_party_cookies_managed_(false) {
80 // The order in which the default content settings providers are created is 77 // The order in which the default content settings providers are created is
81 // critical, as providers that are further down in the list (i.e. added later) 78 // critical, as providers that are further down in the list (i.e. added later)
82 // override providers further up. 79 // override providers further up.
83 content_settings::PrefDefaultProvider* default_provider = 80 content_settings::PrefDefaultProvider* default_provider =
84 new content_settings::PrefDefaultProvider(prefs_, is_off_the_record_); 81 new content_settings::PrefDefaultProvider(prefs_, is_off_the_record_);
85 default_provider->AddObserver(this); 82 default_provider->AddObserver(this);
86 default_content_settings_providers_.push_back( 83 default_content_settings_providers_.push_back(
87 make_linked_ptr(default_provider)); 84 make_linked_ptr(default_provider));
88 85
89 content_settings::PolicyDefaultProvider* policy_default_provider = 86 content_settings::PolicyDefaultProvider* policy_default_provider =
90 new content_settings::PolicyDefaultProvider(prefs_); 87 new content_settings::PolicyDefaultProvider(prefs_);
91 policy_default_provider->AddObserver(this); 88 policy_default_provider->AddObserver(this);
92 default_content_settings_providers_.push_back( 89 default_content_settings_providers_.push_back(
93 make_linked_ptr(policy_default_provider)); 90 make_linked_ptr(policy_default_provider));
94 91
95 // TODO(markusheintz): Discuss whether it is sensible to move migration code
96 // to PrefContentSettingsProvider.
97 MigrateObsoleteCookiePref();
98
99 // Read misc. global settings. 92 // Read misc. global settings.
100 block_third_party_cookies_ =
101 prefs_->GetBoolean(prefs::kBlockThirdPartyCookies);
102 if (block_third_party_cookies_) {
103 UserMetrics::RecordAction(
104 UserMetricsAction("ThirdPartyCookieBlockingEnabled"));
105 } else {
106 UserMetrics::RecordAction(
107 UserMetricsAction("ThirdPartyCookieBlockingDisabled"));
108 }
109 is_block_third_party_cookies_managed_ =
110 prefs_->IsManagedPreference(prefs::kBlockThirdPartyCookies);
111 93
112 // User defined non default content settings are provided by the PrefProvider. 94 // User defined non default content settings are provided by the PrefProvider.
113 // The order in which the content settings providers are created is critical, 95 // The order in which the content settings providers are created is critical,
114 // as providers that are further up in the list (i.e. added earlier) override 96 // as providers that are further up in the list (i.e. added earlier) override
115 // providers further down. 97 // providers further down.
116 content_settings::ObservableProvider* provider = 98 content_settings::ObservableProvider* provider =
117 new content_settings::PolicyProvider(prefs_, policy_default_provider); 99 new content_settings::PolicyProvider(prefs_, policy_default_provider);
118 provider->AddObserver(this); 100 provider->AddObserver(this);
119 content_settings_providers_.push_back(make_linked_ptr(provider)); 101 content_settings_providers_.push_back(make_linked_ptr(provider));
120 102
121 if (extension_service) { 103 if (extension_service) {
122 // |extension_service| can be NULL in unit tests. 104 // |extension_service| can be NULL in unit tests.
123 provider = new content_settings::ExtensionProvider( 105 provider = new content_settings::ExtensionProvider(
124 extension_service->GetExtensionContentSettingsStore(), 106 extension_service->GetExtensionContentSettingsStore(),
125 is_off_the_record_); 107 is_off_the_record_);
126 provider->AddObserver(this); 108 provider->AddObserver(this);
127 content_settings_providers_.push_back(make_linked_ptr(provider)); 109 content_settings_providers_.push_back(make_linked_ptr(provider));
128 } 110 }
129 provider = new content_settings::PrefProvider(prefs_, is_off_the_record_); 111 provider = new content_settings::PrefProvider(prefs_, is_off_the_record_);
130 provider->AddObserver(this); 112 provider->AddObserver(this);
131 content_settings_providers_.push_back(make_linked_ptr(provider)); 113 content_settings_providers_.push_back(make_linked_ptr(provider));
132 114
133 pref_change_registrar_.Init(prefs_);
134 pref_change_registrar_.Add(prefs::kBlockThirdPartyCookies, this);
135 } 115 }
136 116
137 // static 117 // static
138 void HostContentSettingsMap::RegisterUserPrefs(PrefService* prefs) { 118 void HostContentSettingsMap::RegisterUserPrefs(PrefService* prefs) {
139 prefs->RegisterBooleanPref(prefs::kBlockThirdPartyCookies, 119 prefs->RegisterBooleanPref(prefs::kBlockThirdPartyCookies,
140 false, 120 false,
141 PrefService::SYNCABLE_PREF); 121 PrefService::SYNCABLE_PREF);
142 prefs->RegisterIntegerPref(prefs::kContentSettingsWindowLastTabIndex, 122 prefs->RegisterIntegerPref(prefs::kContentSettingsWindowLastTabIndex,
143 0, 123 0,
144 PrefService::UNSYNCABLE_PREF); 124 PrefService::UNSYNCABLE_PREF);
(...skipping 28 matching lines...) Expand all
173 return setting; 153 return setting;
174 } 154 }
175 155
176 ContentSettings HostContentSettingsMap::GetDefaultContentSettings() const { 156 ContentSettings HostContentSettingsMap::GetDefaultContentSettings() const {
177 ContentSettings output(CONTENT_SETTING_DEFAULT); 157 ContentSettings output(CONTENT_SETTING_DEFAULT);
178 for (int i = 0; i < CONTENT_SETTINGS_NUM_TYPES; ++i) 158 for (int i = 0; i < CONTENT_SETTINGS_NUM_TYPES; ++i)
179 output.settings[i] = GetDefaultContentSetting(ContentSettingsType(i)); 159 output.settings[i] = GetDefaultContentSetting(ContentSettingsType(i));
180 return output; 160 return output;
181 } 161 }
182 162
183 ContentSetting HostContentSettingsMap::GetCookieContentSetting(
184 const GURL& url,
185 const GURL& first_party_url,
186 bool setting_cookie) const {
187 if (ShouldAllowAllContent(first_party_url))
188 return CONTENT_SETTING_ALLOW;
189
190 // First get any host-specific settings.
191 ContentSetting setting = GetNonDefaultContentSetting(url,
192 first_party_url, CONTENT_SETTINGS_TYPE_COOKIES, "");
193
194 // If no explicit exception has been made and third-party cookies are blocked
195 // by default, apply that rule.
196 if (setting == CONTENT_SETTING_DEFAULT && BlockThirdPartyCookies()) {
197 bool strict = CommandLine::ForCurrentProcess()->HasSwitch(
198 switches::kBlockReadingThirdPartyCookies);
199 net::StaticCookiePolicy policy(strict ?
200 net::StaticCookiePolicy::BLOCK_ALL_THIRD_PARTY_COOKIES :
201 net::StaticCookiePolicy::BLOCK_SETTING_THIRD_PARTY_COOKIES);
202 int rv;
203 if (setting_cookie)
204 rv = policy.CanSetCookie(url, first_party_url);
205 else
206 rv = policy.CanGetCookies(url, first_party_url);
207 DCHECK_NE(net::ERR_IO_PENDING, rv);
208 if (rv != net::OK)
209 setting = CONTENT_SETTING_BLOCK;
210 }
211
212 // If no other policy has changed the setting, use the default.
213 if (setting == CONTENT_SETTING_DEFAULT)
214 setting = GetDefaultContentSetting(CONTENT_SETTINGS_TYPE_COOKIES);
215
216 return setting;
217 }
218
219 ContentSetting HostContentSettingsMap::GetContentSetting( 163 ContentSetting HostContentSettingsMap::GetContentSetting(
220 const GURL& primary_url, 164 const GURL& primary_url,
221 const GURL& secondary_url, 165 const GURL& secondary_url,
222 ContentSettingsType content_type, 166 ContentSettingsType content_type,
223 const std::string& resource_identifier) const { 167 const std::string& resource_identifier) const {
224 DCHECK_NE(CONTENT_SETTINGS_TYPE_COOKIES, content_type); 168 DCHECK_NE(CONTENT_SETTINGS_TYPE_COOKIES, content_type);
225 DCHECK_NE(content_settings::RequiresResourceIdentifier(content_type), 169 DCHECK_NE(content_settings::RequiresResourceIdentifier(content_type),
226 resource_identifier.empty()); 170 resource_identifier.empty());
227 return GetContentSettingInternal( 171 return GetContentSettingInternal(
228 primary_url, secondary_url, content_type, resource_identifier); 172 primary_url, secondary_url, content_type, resource_identifier);
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after
428 switches::kEnableClickToPlay)); 372 switches::kEnableClickToPlay));
429 case CONTENT_SETTINGS_TYPE_GEOLOCATION: 373 case CONTENT_SETTINGS_TYPE_GEOLOCATION:
430 case CONTENT_SETTINGS_TYPE_NOTIFICATIONS: 374 case CONTENT_SETTINGS_TYPE_NOTIFICATIONS:
431 case CONTENT_SETTINGS_TYPE_INTENTS: 375 case CONTENT_SETTINGS_TYPE_INTENTS:
432 return (setting == CONTENT_SETTING_ASK); 376 return (setting == CONTENT_SETTING_ASK);
433 default: 377 default:
434 return false; 378 return false;
435 } 379 }
436 } 380 }
437 381
438 void HostContentSettingsMap::SetBlockThirdPartyCookies(bool block) { 382 void HostContentSettingsMap::OnContentSettingChanged(
383 ContentSettingsPattern primary_pattern,
384 ContentSettingsPattern secondary_pattern,
385 ContentSettingsType content_type,
386 std::string resource_identifier) {
387 const ContentSettingsDetails details(primary_pattern,
388 secondary_pattern,
389 content_type,
390 resource_identifier);
391 NotificationService::current()->Notify(
392 chrome::NOTIFICATION_CONTENT_SETTINGS_CHANGED,
393 Source<HostContentSettingsMap>(this),
394 Details<const ContentSettingsDetails>(&details));
395 }
396
397 HostContentSettingsMap::~HostContentSettingsMap() {
398 DCHECK(!prefs_);
399 }
400
401 bool HostContentSettingsMap::IsDefaultContentSettingManaged(
402 ContentSettingsType content_type) const {
403 for (ConstDefaultProviderIterator provider =
404 default_content_settings_providers_.begin();
405 provider != default_content_settings_providers_.end(); ++provider) {
406 if ((*provider)->DefaultSettingIsManaged(content_type))
407 return true;
408 }
409 return false;
410 }
411
412 void HostContentSettingsMap::ShutdownOnUIThread() {
413 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
414 DCHECK(prefs_);
415 prefs_ = NULL;
416 for (ProviderIterator it = content_settings_providers_.begin();
417 it != content_settings_providers_.end();
418 ++it) {
419 (*it)->ShutdownOnUIThread();
420 }
421 for (DefaultProviderIterator it = default_content_settings_providers_.begin();
422 it != default_content_settings_providers_.end();
423 ++it) {
424 (*it)->ShutdownOnUIThread();
425 }
426 }
427
428 CookieContentSettings::CookieContentSettings(
markusheintz_ 2011/08/24 12:29:40 Please move the CookieContentSettings to a separat
marja 2011/08/25 13:56:11 Done.
429 HostContentSettingsMap* host_content_settings_map,
430 PrefService* prefs,
431 bool incognito)
432 : host_content_settings_map_(host_content_settings_map),
433 prefs_(prefs),
434 is_off_the_record_(incognito),
435 block_third_party_cookies_(false),
436 is_block_third_party_cookies_managed_(false) {
437 block_third_party_cookies_ =
438 prefs_->GetBoolean(prefs::kBlockThirdPartyCookies);
439 if (block_third_party_cookies_) {
440 UserMetrics::RecordAction(
441 UserMetricsAction("ThirdPartyCookieBlockingEnabled"));
442 } else {
443 UserMetrics::RecordAction(
444 UserMetricsAction("ThirdPartyCookieBlockingDisabled"));
445 }
446 is_block_third_party_cookies_managed_ =
447 prefs_->IsManagedPreference(prefs::kBlockThirdPartyCookies);
448
449 // TODO(markusheintz): Discuss whether it is sensible to move migration code
450 // to PrefContentSettingsProvider.
451 MigrateObsoleteCookiePref();
452
453 pref_change_registrar_.Init(prefs_);
454 pref_change_registrar_.Add(prefs::kBlockThirdPartyCookies, this);
455 }
456
457
458 ContentSetting CookieContentSettings::GetCookieContentSetting(
459 const GURL& url,
460 const GURL& first_party_url,
461 bool setting_cookie) const {
462 if (ShouldAllowAllContent(first_party_url))
463 return CONTENT_SETTING_ALLOW;
464
465 // First get any host-specific settings.
466 ContentSetting setting =
467 host_content_settings_map_->GetNonDefaultContentSetting(
468 url, first_party_url, CONTENT_SETTINGS_TYPE_COOKIES, "");
469
470 // If no explicit exception has been made and third-party cookies are blocked
471 // by default, apply that rule.
472 if (setting == CONTENT_SETTING_DEFAULT && BlockThirdPartyCookies()) {
473 bool strict = CommandLine::ForCurrentProcess()->HasSwitch(
474 switches::kBlockReadingThirdPartyCookies);
475 net::StaticCookiePolicy policy(strict ?
476 net::StaticCookiePolicy::BLOCK_ALL_THIRD_PARTY_COOKIES :
477 net::StaticCookiePolicy::BLOCK_SETTING_THIRD_PARTY_COOKIES);
478 int rv;
479 if (setting_cookie)
480 rv = policy.CanSetCookie(url, first_party_url);
481 else
482 rv = policy.CanGetCookies(url, first_party_url);
483 DCHECK_NE(net::ERR_IO_PENDING, rv);
484 if (rv != net::OK)
485 setting = CONTENT_SETTING_BLOCK;
486 }
487
488 // If no other policy has changed the setting, use the default.
489 if (setting == CONTENT_SETTING_DEFAULT) {
490 setting = host_content_settings_map_->GetDefaultContentSetting(
491 CONTENT_SETTINGS_TYPE_COOKIES);
492 }
493 return setting;
494 }
495
496 bool CookieContentSettings::Allow(const GURL& url,
497 const GURL& first_party_url,
498 bool setting_cookie) const {
499 ContentSetting setting = GetCookieContentSetting(
500 url, first_party_url, setting_cookie);
501 DCHECK((setting == CONTENT_SETTING_ALLOW) ||
502 (setting == CONTENT_SETTING_BLOCK) ||
503 (setting == CONTENT_SETTING_SESSION_ONLY));
504 return (setting == CONTENT_SETTING_ALLOW ||
505 setting == CONTENT_SETTING_SESSION_ONLY);
506 }
507
508 bool CookieContentSettings::EnforceSessionOnly(const GURL& origin) const {
509 // FIXME(marja): Add another content type here
510 ContentSetting setting = GetCookieContentSetting(origin, origin, false);
511 DCHECK((setting == CONTENT_SETTING_ALLOW) ||
512 (setting == CONTENT_SETTING_BLOCK) ||
513 (setting == CONTENT_SETTING_SESSION_ONLY));
514 return (setting == CONTENT_SETTING_SESSION_ONLY);
515 }
516
517 void CookieContentSettings::SetBlockThirdPartyCookies(bool block) {
439 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 518 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
440 DCHECK(prefs_); 519 DCHECK(prefs_);
441 520
442 // This setting may not be directly modified for OTR sessions. Instead, it 521 // This setting may not be directly modified for OTR sessions. Instead, it
443 // is synced to the main profile's setting. 522 // is synced to the main profile's setting.
444 if (is_off_the_record_) { 523 if (is_off_the_record_) {
445 NOTREACHED(); 524 NOTREACHED();
446 return; 525 return;
447 } 526 }
448 527
449 // If the preference block-third-party-cookies is managed then do not allow to 528 // If the preference block-third-party-cookies is managed then do not allow to
450 // change it. 529 // change it.
451 if (prefs_->IsManagedPreference(prefs::kBlockThirdPartyCookies)) { 530 if (prefs_->IsManagedPreference(prefs::kBlockThirdPartyCookies)) {
452 NOTREACHED(); 531 NOTREACHED();
453 return; 532 return;
454 } 533 }
455 534
456 { 535 {
457 base::AutoLock auto_lock(lock_); 536 base::AutoLock auto_lock(lock_);
458 block_third_party_cookies_ = block; 537 block_third_party_cookies_ = block;
459 } 538 }
460 539
461 prefs_->SetBoolean(prefs::kBlockThirdPartyCookies, block); 540 prefs_->SetBoolean(prefs::kBlockThirdPartyCookies, block);
462 } 541 }
463 542
464 void HostContentSettingsMap::OnContentSettingChanged( 543 void CookieContentSettings::Observe(int type,
465 ContentSettingsPattern primary_pattern, 544 const NotificationSource& source,
466 ContentSettingsPattern secondary_pattern, 545 const NotificationDetails& details) {
467 ContentSettingsType content_type,
468 std::string resource_identifier) {
469 const ContentSettingsDetails details(primary_pattern,
470 secondary_pattern,
471 content_type,
472 resource_identifier);
473 NotificationService::current()->Notify(
474 chrome::NOTIFICATION_CONTENT_SETTINGS_CHANGED,
475 Source<HostContentSettingsMap>(this),
476 Details<const ContentSettingsDetails>(&details));
477 }
478
479 void HostContentSettingsMap::Observe(int type,
480 const NotificationSource& source,
481 const NotificationDetails& details) {
482 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 546 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
483 547
484 if (type == chrome::NOTIFICATION_PREF_CHANGED) { 548 if (type == chrome::NOTIFICATION_PREF_CHANGED) {
485 DCHECK_EQ(prefs_, Source<PrefService>(source).ptr()); 549 DCHECK_EQ(prefs_, Source<PrefService>(source).ptr());
486 if (updating_preferences_)
487 return;
488 550
489 std::string* name = Details<std::string>(details).ptr(); 551 std::string* name = Details<std::string>(details).ptr();
490 if (*name == prefs::kBlockThirdPartyCookies) { 552 if (*name == prefs::kBlockThirdPartyCookies) {
491 base::AutoLock auto_lock(lock_); 553 base::AutoLock auto_lock(lock_);
492 block_third_party_cookies_ = prefs_->GetBoolean( 554 block_third_party_cookies_ = prefs_->GetBoolean(
493 prefs::kBlockThirdPartyCookies); 555 prefs::kBlockThirdPartyCookies);
494 is_block_third_party_cookies_managed_ = 556 is_block_third_party_cookies_managed_ =
495 prefs_->IsManagedPreference( 557 prefs_->IsManagedPreference(
496 prefs::kBlockThirdPartyCookies); 558 prefs::kBlockThirdPartyCookies);
497 } else { 559 } else {
498 NOTREACHED() << "Unexpected preference observed"; 560 NOTREACHED() << "Unexpected preference observed";
499 return; 561 return;
500 } 562 }
501 } else { 563 } else {
502 NOTREACHED() << "Unexpected notification"; 564 NOTREACHED() << "Unexpected notification";
503 } 565 }
504 } 566 }
505 567
506 HostContentSettingsMap::~HostContentSettingsMap() { 568 void CookieContentSettings::ShutdownOnUIThread() {
507 DCHECK(!prefs_); 569 pref_change_registrar_.RemoveAll();
508 } 570 }
509 571
510 bool HostContentSettingsMap::IsDefaultContentSettingManaged( 572 void CookieContentSettings::MigrateObsoleteCookiePref() {
511 ContentSettingsType content_type) const {
512 for (ConstDefaultProviderIterator provider =
513 default_content_settings_providers_.begin();
514 provider != default_content_settings_providers_.end(); ++provider) {
515 if ((*provider)->DefaultSettingIsManaged(content_type))
516 return true;
517 }
518 return false;
519 }
520
521 void HostContentSettingsMap::ShutdownOnUIThread() {
522 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
523 DCHECK(prefs_);
524 pref_change_registrar_.RemoveAll();
525 prefs_ = NULL;
526 for (ProviderIterator it = content_settings_providers_.begin();
527 it != content_settings_providers_.end();
528 ++it) {
529 (*it)->ShutdownOnUIThread();
530 }
531 for (DefaultProviderIterator it = default_content_settings_providers_.begin();
532 it != default_content_settings_providers_.end();
533 ++it) {
534 (*it)->ShutdownOnUIThread();
535 }
536 }
537
538 void HostContentSettingsMap::MigrateObsoleteCookiePref() {
539 if (prefs_->HasPrefPath(prefs::kCookieBehavior)) { 573 if (prefs_->HasPrefPath(prefs::kCookieBehavior)) {
540 int cookie_behavior = prefs_->GetInteger(prefs::kCookieBehavior); 574 int cookie_behavior = prefs_->GetInteger(prefs::kCookieBehavior);
541 prefs_->ClearPref(prefs::kCookieBehavior); 575 prefs_->ClearPref(prefs::kCookieBehavior);
542 if (!prefs_->HasPrefPath(prefs::kDefaultContentSettings)) { 576 if (!prefs_->HasPrefPath(prefs::kDefaultContentSettings)) {
543 SetDefaultContentSetting(CONTENT_SETTINGS_TYPE_COOKIES, 577 host_content_settings_map_->SetDefaultContentSetting(
578 CONTENT_SETTINGS_TYPE_COOKIES,
544 (cookie_behavior == net::StaticCookiePolicy::BLOCK_ALL_COOKIES) ? 579 (cookie_behavior == net::StaticCookiePolicy::BLOCK_ALL_COOKIES) ?
545 CONTENT_SETTING_BLOCK : CONTENT_SETTING_ALLOW); 580 CONTENT_SETTING_BLOCK : CONTENT_SETTING_ALLOW);
546 } 581 }
547 if (!prefs_->HasPrefPath(prefs::kBlockThirdPartyCookies)) { 582 if (!prefs_->HasPrefPath(prefs::kBlockThirdPartyCookies)) {
548 SetBlockThirdPartyCookies(cookie_behavior == 583 SetBlockThirdPartyCookies(cookie_behavior ==
549 net::StaticCookiePolicy::BLOCK_SETTING_THIRD_PARTY_COOKIES); 584 net::StaticCookiePolicy::BLOCK_SETTING_THIRD_PARTY_COOKIES);
550 } 585 }
551 } 586 }
552 } 587 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698