Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 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 | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "chrome/browser/browsing_data/clear_site_data_throttle.h" | |
| 6 | |
| 7 #include "base/bind.h" | |
| 8 #include "base/callback.h" | |
| 9 #include "base/values.h" | |
| 10 #include "chrome/browser/browsing_data/browsing_data_helper.h" | |
| 11 #include "chrome/browser/browsing_data/browsing_data_remover.h" | |
| 12 #include "chrome/browser/browsing_data/browsing_data_remover_factory.h" | |
| 13 #include "chrome/browser/browsing_data/registrable_domain_filter_builder.h" | |
| 14 #include "chrome/browser/profiles/profile.h" | |
| 15 #include "components/safe_json/safe_json_parser.h" | |
| 16 #include "content/public/browser/browser_thread.h" | |
| 17 #include "content/public/browser/web_contents.h" | |
| 18 #include "net/base/registry_controlled_domains/registry_controlled_domain.h" | |
| 19 #include "net/url_request/url_request.h" | |
| 20 #include "url/gurl.h" | |
| 21 | |
| 22 namespace { | |
| 23 | |
| 24 const char* kNameForLogging = "ClearSiteDataThrottle"; | |
| 25 | |
| 26 const char* kClearSiteDataHeader = "Clear-Site-Data"; | |
| 27 | |
| 28 const char* kTypesKey = "types"; | |
| 29 | |
| 30 } // namespace | |
| 31 | |
| 32 ClearSiteDataThrottle::ClearSiteDataThrottle(const net::URLRequest* request) | |
| 33 : request_(request) {} | |
| 34 | |
| 35 ClearSiteDataThrottle::~ClearSiteDataThrottle() {} | |
| 36 | |
| 37 void ClearSiteDataThrottle::WillProcessResponse(bool* defer) { | |
| 38 std::string header; | |
| 39 request_->GetResponseHeaderByName(kClearSiteDataHeader, &header); | |
| 40 if (header.empty()) | |
| 41 return; | |
| 42 | |
| 43 std::string domain; | |
| 44 if (request_->url().HostIsIPAddress()) { | |
| 45 domain = request_->url().host(); | |
| 46 } else { | |
| 47 domain = GetDomainAndRegistry( | |
|
Mike West
2016/05/31 05:35:51
This is going to strip `www.example.com` down to `
msramek
2016/06/01 14:20:40
Done. Sorry, forgot to add a comment about this. I
| |
| 48 request_->url(), | |
| 49 net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES); | |
| 50 } | |
| 51 | |
| 52 if (domain.empty()) | |
|
Mike West
2016/05/31 05:35:51
Another implication is that folks on an intranet w
msramek
2016/06/01 14:20:40
Yes, or even a simpler example: localhost. I think
| |
| 53 return; | |
| 54 | |
| 55 const content::ResourceRequestInfo* info = | |
| 56 content::ResourceRequestInfo::ForRequest(request_); | |
| 57 content::BrowserThread::PostTask( | |
| 58 content::BrowserThread::UI, FROM_HERE, | |
| 59 base::Bind( | |
| 60 &ClearSiteDataThrottle::ProcessResponseOnUIThread, | |
| 61 info->GetWebContentsGetterForRequest(), | |
| 62 domain, | |
| 63 header)); | |
| 64 } | |
| 65 | |
| 66 const char* ClearSiteDataThrottle::GetNameForLogging() const { | |
| 67 return kNameForLogging; | |
| 68 } | |
| 69 | |
| 70 // static | |
| 71 void ClearSiteDataThrottle::ProcessResponseOnUIThread( | |
| 72 const content::ResourceRequestInfo::WebContentsGetter& getter, | |
| 73 std::string domain, | |
| 74 std::string header) { | |
| 75 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | |
| 76 | |
| 77 content::WebContents* web_contents = getter.Run(); | |
| 78 if (!web_contents) | |
| 79 return; | |
| 80 | |
| 81 Profile* profile = | |
| 82 Profile::FromBrowserContext( | |
| 83 web_contents->GetBrowserContext())->GetOriginalProfile(); | |
| 84 | |
| 85 safe_json::SafeJsonParser::Parse( | |
|
Mike West
2016/05/31 05:35:51
Why do we need to parse JSON on the UI thread? Can
msramek
2016/06/01 14:20:41
N/A, since after moving to content/ were using the
| |
| 86 header, | |
| 87 base::Bind( | |
| 88 &ClearSiteDataThrottle::ClearData, | |
| 89 base::Unretained(profile), | |
| 90 domain), | |
| 91 base::Bind(&ClearSiteDataThrottle::OnParseError)); | |
| 92 } | |
| 93 | |
| 94 // static | |
| 95 void ClearSiteDataThrottle::ClearData( | |
| 96 Profile* profile, | |
| 97 std::string domain, | |
| 98 std::unique_ptr<base::Value> header) { | |
| 99 if (!header || !header->GetAsDictionary(nullptr)) { | |
| 100 DVLOG(1) << "Not a valid dictionary value."; | |
|
Mike West
2016/05/31 05:35:52
// TODO(you): Write a console error.
msramek
2016/06/01 14:20:40
Done. (actually implemented the console error)
| |
| 101 return; | |
| 102 } | |
| 103 | |
| 104 const base::ListValue* types; | |
| 105 if (!static_cast<base::DictionaryValue*>(header.get()) | |
| 106 ->GetListWithoutPathExpansion(kTypesKey, &types)) { | |
| 107 DVLOG(1) << "No 'types' field present."; | |
|
Mike West
2016/05/31 05:35:51
// TODO(you): Write a console error.
msramek
2016/06/01 14:20:40
Done. (actually implemented the console error)
| |
| 108 return; | |
| 109 } | |
| 110 | |
| 111 int remove_mask = 0; | |
| 112 for (const base::Value* value : *types) { | |
|
Mike West
2016/05/31 05:35:51
Nit: These are `unique_ptr` aren't they?
msramek
2016/06/01 14:20:40
types->begin() is std::vector<base::Value*>::const
msramek
2016/06/01 14:25:30
Ah. Because this is a recent change and I have an
| |
| 113 std::string type; | |
| 114 if (!value->GetAsString(&type)) { | |
| 115 DVLOG(1) << "Invalid type: " << *value; | |
|
Mike West
2016/05/31 05:35:51
// TODO(you): Write a console error.
msramek
2016/06/01 14:20:40
Done. (actually implemented the console error)
| |
| 116 continue; | |
| 117 } | |
| 118 | |
| 119 if (type == "cache") { | |
| 120 remove_mask |= BrowsingDataRemover::REMOVE_CACHE; | |
| 121 DVLOG(2) << "Clearing cache."; | |
| 122 } else if (type == "cookies") { | |
| 123 remove_mask |= BrowsingDataRemover::REMOVE_COOKIES; | |
| 124 DVLOG(2) << "Clearing cookies."; | |
| 125 } else if (type == "storage") { | |
| 126 remove_mask |= BrowsingDataRemover::REMOVE_SITE_DATA; | |
|
Mike West
2016/05/31 05:35:51
This includes cookies; it shouldn't. I think you'l
msramek
2016/06/01 14:20:40
Done. Thanks for paying attention to this :)
| |
| 127 DVLOG(2) << "Clearing storage."; | |
| 128 } | |
| 129 } | |
| 130 | |
| 131 if (!remove_mask) { | |
| 132 DVLOG(2) << "No valid types specified for clearing."; | |
|
Mike West
2016/05/31 05:35:51
// TODO(you): Write a console error.
msramek
2016/06/01 14:20:41
Done. (actually implemented the console error)
| |
| 133 return; | |
| 134 } | |
| 135 | |
| 136 BrowsingDataRemover* browsing_data_remover = | |
| 137 BrowsingDataRemoverFactory::GetForBrowserContext(profile); | |
| 138 | |
| 139 RegistrableDomainFilterBuilder filter_builder( | |
| 140 BrowsingDataFilterBuilder::WHITELIST); | |
| 141 filter_builder.AddRegisterableDomain(domain); | |
|
Mike West
2016/05/31 05:35:51
Again, we should talk about the registerable domai
msramek
2016/06/01 14:20:40
Please see my current implementation. I'm using or
| |
| 142 | |
| 143 browsing_data_remover->RemoveWithFilter( | |
|
Mike West
2016/05/31 05:35:51
This eventually hops back to the IO thread, right?
msramek
2016/06/01 14:20:40
N/A, since we're not doing any more thread hopping
| |
| 144 BrowsingDataRemover::Period(BrowsingDataRemover::TimePeriod::EVERYTHING), | |
| 145 remove_mask, | |
| 146 BrowsingDataHelper::UNPROTECTED_WEB, | |
| 147 filter_builder); | |
| 148 } | |
| 149 | |
| 150 // static | |
| 151 void ClearSiteDataThrottle::OnParseError(const std::string& error) { | |
| 152 DVLOG(1) << "The header value is not a valid JSON."; | |
| 153 DVLOG(1) << error; | |
|
Mike West
2016/05/31 05:35:52
// TODO(you): write a console error.
msramek
2016/06/01 14:20:41
Done. (actually implemented the console error)
| |
| 154 } | |
| OLD | NEW |