Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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/ui/webui/settings/site_settings_handler.h" | 5 #include "chrome/browser/ui/webui/settings/site_settings_handler.h" |
| 6 | 6 |
| 7 #include <memory> | 7 #include <memory> |
| 8 #include <string> | 8 #include <string> |
| 9 #include <utility> | 9 #include <utility> |
| 10 | 10 |
| 11 #include "base/bind.h" | 11 #include "base/bind.h" |
| 12 #include "base/macros.h" | 12 #include "base/macros.h" |
| 13 #include "base/values.h" | 13 #include "base/values.h" |
| 14 #include "chrome/browser/browsing_data/browsing_data_local_storage_helper.h" | 14 #include "chrome/browser/browsing_data/browsing_data_local_storage_helper.h" |
| 15 #include "chrome/browser/chrome_notification_types.h" | |
| 15 #include "chrome/browser/content_settings/host_content_settings_map_factory.h" | 16 #include "chrome/browser/content_settings/host_content_settings_map_factory.h" |
| 16 #include "chrome/browser/permissions/chooser_context_base.h" | 17 #include "chrome/browser/permissions/chooser_context_base.h" |
| 17 #include "chrome/browser/profiles/profile.h" | 18 #include "chrome/browser/profiles/profile.h" |
| 18 #include "chrome/browser/ui/webui/site_settings_helper.h" | 19 #include "chrome/browser/ui/webui/site_settings_helper.h" |
| 19 #include "chrome/common/extensions/manifest_handlers/app_launch_info.h" | 20 #include "chrome/common/extensions/manifest_handlers/app_launch_info.h" |
| 20 #include "components/content_settings/core/browser/host_content_settings_map.h" | 21 #include "components/content_settings/core/browser/host_content_settings_map.h" |
| 21 #include "components/content_settings/core/common/content_settings_types.h" | 22 #include "components/content_settings/core/common/content_settings_types.h" |
| 22 #include "content/public/browser/browser_thread.h" | 23 #include "content/public/browser/browser_thread.h" |
| 24 #include "content/public/browser/notification_service.h" | |
| 23 #include "content/public/browser/web_ui.h" | 25 #include "content/public/browser/web_ui.h" |
| 24 #include "extensions/browser/extension_registry.h" | 26 #include "extensions/browser/extension_registry.h" |
| 25 #include "extensions/common/permissions/api_permission.h" | 27 #include "extensions/common/permissions/api_permission.h" |
| 26 #include "extensions/common/permissions/permissions_data.h" | 28 #include "extensions/common/permissions/permissions_data.h" |
| 27 #include "storage/browser/quota/quota_manager.h" | 29 #include "storage/browser/quota/quota_manager.h" |
| 28 #include "storage/common/quota/quota_status_code.h" | 30 #include "storage/common/quota/quota_status_code.h" |
| 29 #include "ui/base/text/bytes_formatting.h" | 31 #include "ui/base/text/bytes_formatting.h" |
| 30 | 32 |
| 31 | |
| 32 namespace settings { | 33 namespace settings { |
| 33 | 34 |
| 34 namespace { | 35 namespace { |
| 35 | 36 |
| 36 const char kAppName[] = "appName"; | 37 const char kAppName[] = "appName"; |
| 37 const char kAppId[] = "appId"; | 38 const char kAppId[] = "appId"; |
| 38 | 39 |
| 39 // Return an appropriate API Permission ID for the given string name. | 40 // Return an appropriate API Permission ID for the given string name. |
| 40 extensions::APIPermission::APIPermission::ID APIPermissionFromGroupName( | 41 extensions::APIPermission::APIPermission::ID APIPermissionFromGroupName( |
| 41 std::string type) { | 42 std::string type) { |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 100 continue; | 101 continue; |
| 101 AddExceptionForHostedApp(launch_url.spec(), *extension->get(), exceptions); | 102 AddExceptionForHostedApp(launch_url.spec(), *extension->get(), exceptions); |
| 102 } | 103 } |
| 103 } | 104 } |
| 104 | 105 |
| 105 } // namespace | 106 } // namespace |
| 106 | 107 |
| 107 | 108 |
| 108 SiteSettingsHandler::SiteSettingsHandler(Profile* profile) | 109 SiteSettingsHandler::SiteSettingsHandler(Profile* profile) |
| 109 : profile_(profile), observer_(this) { | 110 : profile_(profile), observer_(this) { |
| 111 notification_registrar_.Add( | |
| 112 this, chrome::NOTIFICATION_PROFILE_CREATED, | |
| 113 content::NotificationService::AllSources()); | |
| 114 notification_registrar_.Add( | |
| 115 this, chrome::NOTIFICATION_PROFILE_DESTROYED, | |
| 116 content::NotificationService::AllSources()); | |
|
dschuyler
2016/09/01 23:13:49
Both of theses Add() calls should move from the ct
Finnur
2016/09/02 15:44:14
OK, fine. But I'm concerned about that because pro
| |
| 110 } | 117 } |
| 111 | 118 |
| 112 SiteSettingsHandler::~SiteSettingsHandler() { | 119 SiteSettingsHandler::~SiteSettingsHandler() { |
| 113 } | 120 } |
| 114 | 121 |
| 115 void SiteSettingsHandler::RegisterMessages() { | 122 void SiteSettingsHandler::RegisterMessages() { |
| 116 web_ui()->RegisterMessageCallback( | 123 web_ui()->RegisterMessageCallback( |
| 117 "fetchUsageTotal", | 124 "fetchUsageTotal", |
| 118 base::Bind(&SiteSettingsHandler::HandleFetchUsageTotal, | 125 base::Bind(&SiteSettingsHandler::HandleFetchUsageTotal, |
| 119 base::Unretained(this))); | 126 base::Unretained(this))); |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 146 base::Bind(&SiteSettingsHandler::HandleResetCategoryPermissionForOrigin, | 153 base::Bind(&SiteSettingsHandler::HandleResetCategoryPermissionForOrigin, |
| 147 base::Unretained(this))); | 154 base::Unretained(this))); |
| 148 web_ui()->RegisterMessageCallback( | 155 web_ui()->RegisterMessageCallback( |
| 149 "setCategoryPermissionForOrigin", | 156 "setCategoryPermissionForOrigin", |
| 150 base::Bind(&SiteSettingsHandler::HandleSetCategoryPermissionForOrigin, | 157 base::Bind(&SiteSettingsHandler::HandleSetCategoryPermissionForOrigin, |
| 151 base::Unretained(this))); | 158 base::Unretained(this))); |
| 152 web_ui()->RegisterMessageCallback( | 159 web_ui()->RegisterMessageCallback( |
| 153 "isPatternValid", | 160 "isPatternValid", |
| 154 base::Bind(&SiteSettingsHandler::HandleIsPatternValid, | 161 base::Bind(&SiteSettingsHandler::HandleIsPatternValid, |
| 155 base::Unretained(this))); | 162 base::Unretained(this))); |
| 163 web_ui()->RegisterMessageCallback( | |
| 164 "updateIncognitoStatus", | |
| 165 base::Bind(&SiteSettingsHandler::HandleUpdateIncognitoStatus, | |
| 166 base::Unretained(this))); | |
| 156 } | 167 } |
| 157 | 168 |
| 158 void SiteSettingsHandler::OnJavascriptAllowed() { | 169 void SiteSettingsHandler::OnJavascriptAllowed() { |
| 159 observer_.Add(HostContentSettingsMapFactory::GetForProfile(profile_)); | 170 observer_.Add(HostContentSettingsMapFactory::GetForProfile(profile_)); |
| 160 if (profile_->HasOffTheRecordProfile()) { | 171 if (profile_->HasOffTheRecordProfile()) { |
| 161 auto* map = HostContentSettingsMapFactory::GetForProfile( | 172 auto* map = HostContentSettingsMapFactory::GetForProfile( |
| 162 profile_->GetOffTheRecordProfile()); | 173 profile_->GetOffTheRecordProfile()); |
| 163 if (!observer_.IsObserving(map)) | 174 if (!observer_.IsObserving(map)) |
| 164 observer_.Add(map); | 175 observer_.Add(map); |
| 165 } | 176 } |
| 166 } | 177 } |
| 167 | 178 |
| 168 void SiteSettingsHandler::OnJavascriptDisallowed() { | 179 void SiteSettingsHandler::OnJavascriptDisallowed() { |
| 169 observer_.RemoveAll(); | 180 observer_.RemoveAll(); |
|
dschuyler
2016/09/01 23:13:49
After the notification_registrar_.Add() calls are
Finnur
2016/09/02 15:44:14
Yeah, I now understand the RemoveAll comment bette
| |
| 170 } | 181 } |
| 171 | 182 |
| 172 void SiteSettingsHandler::OnGetUsageInfo( | 183 void SiteSettingsHandler::OnGetUsageInfo( |
| 173 const storage::UsageInfoEntries& entries) { | 184 const storage::UsageInfoEntries& entries) { |
| 174 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 185 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| 175 | 186 |
| 176 for (const auto& entry : entries) { | 187 for (const auto& entry : entries) { |
| 177 if (entry.usage <= 0) continue; | 188 if (entry.usage <= 0) continue; |
| 178 if (entry.host == usage_host_) { | 189 if (entry.host == usage_host_) { |
| 179 CallJavascriptFunction("settings.WebsiteUsagePrivateApi.returnUsageTotal", | 190 CallJavascriptFunction("settings.WebsiteUsagePrivateApi.returnUsageTotal", |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 212 base::StringValue("contentSettingSitePermissionChanged"), | 223 base::StringValue("contentSettingSitePermissionChanged"), |
| 213 base::StringValue(site_settings::ContentSettingsTypeToGroupName( | 224 base::StringValue(site_settings::ContentSettingsTypeToGroupName( |
| 214 content_type)), | 225 content_type)), |
| 215 base::StringValue(primary_pattern.ToString()), | 226 base::StringValue(primary_pattern.ToString()), |
| 216 base::StringValue( | 227 base::StringValue( |
| 217 secondary_pattern == ContentSettingsPattern::Wildcard() ? | 228 secondary_pattern == ContentSettingsPattern::Wildcard() ? |
| 218 "" : secondary_pattern.ToString())); | 229 "" : secondary_pattern.ToString())); |
| 219 } | 230 } |
| 220 } | 231 } |
| 221 | 232 |
| 233 void SiteSettingsHandler::Observe( | |
| 234 int type, | |
| 235 const content::NotificationSource& source, | |
| 236 const content::NotificationDetails& details) { | |
| 237 switch (type) { | |
| 238 case chrome::NOTIFICATION_PROFILE_DESTROYED: { | |
| 239 Profile* profile = content::Source<Profile>(source).ptr(); | |
| 240 if (profile != profile_ && !IsOurIncognitoProfile(profile)) | |
| 241 break; | |
| 242 SendIncognitoStatus(profile, true); // Destroy -> true. | |
|
stevenjb
2016/09/01 17:07:54
was_destroyed throughout
dschuyler
2016/09/01 23:13:49
Coding style comment:
SendIncognitoStatus(profile,
Finnur
2016/09/02 15:44:14
Done.
| |
| 243 | |
| 244 HostContentSettingsMap* settings_map = | |
| 245 HostContentSettingsMapFactory::GetForProfile(profile); | |
| 246 if (profile->IsOffTheRecord() && | |
| 247 observer_.IsObserving(settings_map)) { | |
| 248 observer_.Remove(settings_map); | |
| 249 } | |
| 250 | |
| 251 break; | |
| 252 } | |
| 253 | |
| 254 case chrome::NOTIFICATION_PROFILE_CREATED: { | |
| 255 Profile* profile = content::Source<Profile>(source).ptr(); | |
| 256 if (profile != profile_ && !IsOurIncognitoProfile(profile)) | |
| 257 break; | |
| 258 SendIncognitoStatus(profile, false); // Destroy -> false. | |
| 259 | |
| 260 observer_.Add(HostContentSettingsMapFactory::GetForProfile(profile)); | |
| 261 break; | |
| 262 } | |
| 263 } | |
| 264 } | |
| 265 | |
| 222 void SiteSettingsHandler::HandleFetchUsageTotal( | 266 void SiteSettingsHandler::HandleFetchUsageTotal( |
| 223 const base::ListValue* args) { | 267 const base::ListValue* args) { |
| 224 AllowJavascript(); | 268 AllowJavascript(); |
| 225 | 269 |
| 226 CHECK_EQ(1U, args->GetSize()); | 270 CHECK_EQ(1U, args->GetSize()); |
| 227 std::string host; | 271 std::string host; |
| 228 CHECK(args->GetString(0, &host)); | 272 CHECK(args->GetString(0, &host)); |
| 229 usage_host_ = host; | 273 usage_host_ = host; |
| 230 | 274 |
| 231 scoped_refptr<StorageInfoFetcher> storage_info_fetcher | 275 scoped_refptr<StorageInfoFetcher> storage_info_fetcher |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 346 | 390 |
| 347 CHECK_EQ(2U, args->GetSize()); | 391 CHECK_EQ(2U, args->GetSize()); |
| 348 const base::Value* callback_id; | 392 const base::Value* callback_id; |
| 349 CHECK(args->Get(0, &callback_id)); | 393 CHECK(args->Get(0, &callback_id)); |
| 350 std::string type; | 394 std::string type; |
| 351 CHECK(args->GetString(1, &type)); | 395 CHECK(args->GetString(1, &type)); |
| 352 ContentSettingsType content_type = | 396 ContentSettingsType content_type = |
| 353 static_cast<ContentSettingsType>(static_cast<int>( | 397 static_cast<ContentSettingsType>(static_cast<int>( |
| 354 site_settings::ContentSettingsTypeFromGroupName(type))); | 398 site_settings::ContentSettingsTypeFromGroupName(type))); |
| 355 | 399 |
| 400 std::unique_ptr<base::ListValue> exceptions(new base::ListValue); | |
| 401 | |
| 356 HostContentSettingsMap* map = | 402 HostContentSettingsMap* map = |
| 357 HostContentSettingsMapFactory::GetForProfile(profile_); | 403 HostContentSettingsMapFactory::GetForProfile(profile_); |
| 358 std::unique_ptr<base::ListValue> exceptions(new base::ListValue); | |
| 359 | |
| 360 AddExceptionsGrantedByHostedApps(profile_, APIPermissionFromGroupName(type), | 404 AddExceptionsGrantedByHostedApps(profile_, APIPermissionFromGroupName(type), |
| 361 exceptions.get()); | 405 exceptions.get()); |
| 406 site_settings::GetExceptionsFromHostContentSettingsMap( | |
| 407 map, content_type, web_ui(), false, exceptions.get()); | |
| 362 | 408 |
| 363 site_settings::GetExceptionsFromHostContentSettingsMap( | 409 if (profile_->HasOffTheRecordProfile()) { |
| 364 map, content_type, web_ui(), exceptions.get()); | 410 Profile* incognito = profile_->GetOffTheRecordProfile(); |
| 411 map = HostContentSettingsMapFactory::GetForProfile(incognito); | |
| 412 site_settings::GetExceptionsFromHostContentSettingsMap( | |
| 413 map, content_type, web_ui(), true, exceptions.get()); | |
| 414 } | |
| 415 | |
| 365 ResolveJavascriptCallback(*callback_id, *exceptions.get()); | 416 ResolveJavascriptCallback(*callback_id, *exceptions.get()); |
| 366 } | 417 } |
| 367 | 418 |
| 368 void SiteSettingsHandler::HandleResetCategoryPermissionForOrigin( | 419 void SiteSettingsHandler::HandleResetCategoryPermissionForOrigin( |
| 369 const base::ListValue* args) { | 420 const base::ListValue* args) { |
| 370 CHECK_EQ(3U, args->GetSize()); | 421 CHECK_EQ(4U, args->GetSize()); |
| 371 std::string primary_pattern; | 422 std::string primary_pattern; |
| 372 CHECK(args->GetString(0, &primary_pattern)); | 423 CHECK(args->GetString(0, &primary_pattern)); |
| 373 std::string secondary_pattern; | 424 std::string secondary_pattern; |
| 374 CHECK(args->GetString(1, &secondary_pattern)); | 425 CHECK(args->GetString(1, &secondary_pattern)); |
| 375 std::string type; | 426 std::string type; |
| 376 CHECK(args->GetString(2, &type)); | 427 CHECK(args->GetString(2, &type)); |
| 428 bool incognito; | |
| 429 CHECK(args->GetBoolean(3, &incognito)); | |
| 377 | 430 |
| 378 ContentSettingsType content_type = | 431 ContentSettingsType content_type = |
| 379 static_cast<ContentSettingsType>(static_cast<int>( | 432 static_cast<ContentSettingsType>(static_cast<int>( |
| 380 site_settings::ContentSettingsTypeFromGroupName(type))); | 433 site_settings::ContentSettingsTypeFromGroupName(type))); |
| 381 | 434 |
| 435 Profile* profile = nullptr; | |
| 436 if (incognito) { | |
| 437 if (!profile_->HasOffTheRecordProfile()) | |
| 438 return; | |
| 439 profile = profile_->GetOffTheRecordProfile(); | |
| 440 } else { | |
| 441 profile = profile_; | |
| 442 } | |
| 443 | |
| 382 HostContentSettingsMap* map = | 444 HostContentSettingsMap* map = |
| 383 HostContentSettingsMapFactory::GetForProfile(profile_); | 445 HostContentSettingsMapFactory::GetForProfile(profile); |
| 384 map->SetContentSettingCustomScope( | 446 map->SetContentSettingCustomScope( |
| 385 ContentSettingsPattern::FromString(primary_pattern), | 447 ContentSettingsPattern::FromString(primary_pattern), |
| 386 secondary_pattern.empty() ? | 448 secondary_pattern.empty() ? |
| 387 ContentSettingsPattern::Wildcard() : | 449 ContentSettingsPattern::Wildcard() : |
| 388 ContentSettingsPattern::FromString(secondary_pattern), | 450 ContentSettingsPattern::FromString(secondary_pattern), |
| 389 content_type, "", CONTENT_SETTING_DEFAULT); | 451 content_type, "", CONTENT_SETTING_DEFAULT); |
| 390 } | 452 } |
| 391 | 453 |
| 392 void SiteSettingsHandler::HandleSetCategoryPermissionForOrigin( | 454 void SiteSettingsHandler::HandleSetCategoryPermissionForOrigin( |
| 393 const base::ListValue* args) { | 455 const base::ListValue* args) { |
| 394 CHECK_EQ(4U, args->GetSize()); | 456 CHECK_EQ(5U, args->GetSize()); |
| 395 std::string primary_pattern; | 457 std::string primary_pattern; |
| 396 CHECK(args->GetString(0, &primary_pattern)); | 458 CHECK(args->GetString(0, &primary_pattern)); |
| 397 std::string secondary_pattern; | 459 std::string secondary_pattern; |
| 398 CHECK(args->GetString(1, &secondary_pattern)); | 460 CHECK(args->GetString(1, &secondary_pattern)); |
| 399 std::string type; | 461 std::string type; |
| 400 CHECK(args->GetString(2, &type)); | 462 CHECK(args->GetString(2, &type)); |
| 401 std::string value; | 463 std::string value; |
| 402 CHECK(args->GetString(3, &value)); | 464 CHECK(args->GetString(3, &value)); |
| 465 bool incognito; | |
| 466 CHECK(args->GetBoolean(4, &incognito)); | |
| 403 | 467 |
| 404 ContentSettingsType content_type = | 468 ContentSettingsType content_type = |
| 405 static_cast<ContentSettingsType>(static_cast<int>( | 469 static_cast<ContentSettingsType>(static_cast<int>( |
| 406 site_settings::ContentSettingsTypeFromGroupName(type))); | 470 site_settings::ContentSettingsTypeFromGroupName(type))); |
| 407 ContentSetting setting; | 471 ContentSetting setting; |
| 408 CHECK(content_settings::ContentSettingFromString(value, &setting)); | 472 CHECK(content_settings::ContentSettingFromString(value, &setting)); |
| 409 | 473 |
| 474 Profile* profile = nullptr; | |
| 475 if (incognito) { | |
| 476 if (!profile_->HasOffTheRecordProfile()) | |
| 477 return; | |
| 478 profile = profile_->GetOffTheRecordProfile(); | |
| 479 } else { | |
| 480 profile = profile_; | |
| 481 } | |
| 482 | |
| 410 HostContentSettingsMap* map = | 483 HostContentSettingsMap* map = |
| 411 HostContentSettingsMapFactory::GetForProfile(profile_); | 484 HostContentSettingsMapFactory::GetForProfile(profile); |
| 412 map->SetContentSettingCustomScope( | 485 map->SetContentSettingCustomScope( |
| 413 ContentSettingsPattern::FromString(primary_pattern), | 486 ContentSettingsPattern::FromString(primary_pattern), |
| 414 secondary_pattern.empty() ? | 487 secondary_pattern.empty() ? |
| 415 ContentSettingsPattern::Wildcard() : | 488 ContentSettingsPattern::Wildcard() : |
| 416 ContentSettingsPattern::FromString(secondary_pattern), | 489 ContentSettingsPattern::FromString(secondary_pattern), |
| 417 content_type, "", setting); | 490 content_type, "", setting); |
| 418 } | 491 } |
| 419 | 492 |
| 420 void SiteSettingsHandler::HandleIsPatternValid( | 493 void SiteSettingsHandler::HandleIsPatternValid( |
| 421 const base::ListValue* args) { | 494 const base::ListValue* args) { |
| 422 CHECK_EQ(2U, args->GetSize()); | 495 CHECK_EQ(2U, args->GetSize()); |
| 423 const base::Value* callback_id; | 496 const base::Value* callback_id; |
| 424 CHECK(args->Get(0, &callback_id)); | 497 CHECK(args->Get(0, &callback_id)); |
| 425 std::string pattern_string; | 498 std::string pattern_string; |
| 426 CHECK(args->GetString(1, &pattern_string)); | 499 CHECK(args->GetString(1, &pattern_string)); |
| 427 | 500 |
| 428 ContentSettingsPattern pattern = | 501 ContentSettingsPattern pattern = |
| 429 ContentSettingsPattern::FromString(pattern_string); | 502 ContentSettingsPattern::FromString(pattern_string); |
| 430 ResolveJavascriptCallback( | 503 ResolveJavascriptCallback( |
| 431 *callback_id, base::FundamentalValue(pattern.IsValid())); | 504 *callback_id, base::FundamentalValue(pattern.IsValid())); |
| 432 } | 505 } |
| 433 | 506 |
| 507 void SiteSettingsHandler::HandleUpdateIncognitoStatus( | |
| 508 const base::ListValue* args) { | |
| 509 AllowJavascript(); | |
| 510 SendIncognitoStatus(profile_, false); // Destroy -> false. | |
|
dschuyler
2016/09/01 23:13:49
Change comment here too :)
Finnur
2016/09/02 15:44:14
Done.
| |
| 511 } | |
| 512 | |
| 513 bool SiteSettingsHandler::IsOurIncognitoProfile(Profile* profile) { | |
| 514 return profile_->HasOffTheRecordProfile() && | |
| 515 profile == profile_->GetOffTheRecordProfile(); | |
| 516 } | |
| 517 | |
| 518 void SiteSettingsHandler::SendIncognitoStatus( | |
| 519 Profile* profile, bool was_destroyed) { | |
| 520 if (!IsJavascriptAllowed()) | |
| 521 return; | |
| 522 | |
| 523 // When an incognito profile is destroyed, it sends out the destruction | |
| 524 // message before destroying, so HasOffTheRecordProfile for profile_ won't | |
| 525 // return false until after the profile actually been destroyed. | |
| 526 bool incognito_enabled = profile_->HasOffTheRecordProfile() && | |
| 527 !(was_destroyed && profile == profile_->GetOffTheRecordProfile()); | |
| 528 | |
| 529 if (profile == profile_ || IsOurIncognitoProfile(profile)) { | |
| 530 CallJavascriptFunction("cr.webUIListenerCallback", | |
| 531 base::StringValue("onIncognitoStatusChanged"), | |
| 532 base::FundamentalValue(incognito_enabled)); | |
| 533 } | |
| 534 } | |
| 535 | |
| 434 } // namespace settings | 536 } // namespace settings |
| OLD | NEW |