OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/extensions/webstore_inline_installer.h" | 5 #include "chrome/browser/extensions/webstore_inline_installer.h" |
6 | 6 |
7 #include <utility> | 7 #include <utility> |
8 | 8 |
9 #include "base/json/json_writer.h" | 9 #include "base/json/json_writer.h" |
10 #include "base/strings/stringprintf.h" | 10 #include "base/strings/stringprintf.h" |
11 #include "base/values.h" | 11 #include "base/values.h" |
12 #include "chrome/browser/browser_process.h" | |
12 #include "chrome/browser/extensions/webstore_data_fetcher.h" | 13 #include "chrome/browser/extensions/webstore_data_fetcher.h" |
13 #include "chrome/browser/profiles/profile.h" | 14 #include "chrome/browser/profiles/profile.h" |
15 #include "chrome/browser/safe_browsing/safe_browsing_navigation_observer_manager .h" | |
16 #include "chrome/browser/safe_browsing/safe_browsing_service.h" | |
14 #include "chrome/browser/ui/browser_finder.h" | 17 #include "chrome/browser/ui/browser_finder.h" |
15 #include "chrome/browser/ui/exclusive_access/fullscreen_controller.h" | 18 #include "chrome/browser/ui/exclusive_access/fullscreen_controller.h" |
16 #include "content/public/browser/navigation_entry.h" | 19 #include "content/public/browser/navigation_entry.h" |
17 #include "content/public/browser/navigation_handle.h" | 20 #include "content/public/browser/navigation_handle.h" |
18 #include "content/public/browser/web_contents.h" | 21 #include "content/public/browser/web_contents.h" |
19 | 22 |
20 using content::WebContents; | 23 using content::WebContents; |
24 using safe_browsing::SafeBrowsingNavigationObserverManager; | |
25 using safe_browsing::ReferrerChain; | |
26 | |
27 namespace { | |
28 | |
29 // The number of user gestures to trace back for CWS pings. | |
30 const int kExtensionReferrerUserGestureLimit = 2; | |
31 } | |
21 | 32 |
22 namespace extensions { | 33 namespace extensions { |
23 | 34 |
24 const char kInvalidWebstoreResponseError[] = | 35 const char kInvalidWebstoreResponseError[] = |
25 "Invalid Chrome Web Store response."; | 36 "Invalid Chrome Web Store response."; |
26 const char kNoVerifiedSitesError[] = | 37 const char kNoVerifiedSitesError[] = |
27 "Inline installs can only be initiated for Chrome Web Store items that " | 38 "Inline installs can only be initiated for Chrome Web Store items that " |
28 "have one or more verified sites."; | 39 "have one or more verified sites."; |
29 const char kNotFromVerifiedSitesError[] = | 40 const char kNotFromVerifiedSitesError[] = |
30 "Installs can only be initiated by one of the Chrome Web Store item's " | 41 "Installs can only be initiated by one of the Chrome Web Store item's " |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
94 } | 105 } |
95 } | 106 } |
96 if (!requestor_is_ok) { | 107 if (!requestor_is_ok) { |
97 *error = kNotFromVerifiedSitesError; | 108 *error = kNotFromVerifiedSitesError; |
98 return false; | 109 return false; |
99 } | 110 } |
100 *error = ""; | 111 *error = ""; |
101 return true; | 112 return true; |
102 } | 113 } |
103 | 114 |
115 bool WebstoreInlineInstaller::SafeBrowsingNavigationEventsEnabled() const { | |
116 return SafeBrowsingNavigationObserverManager::IsEnabledAndReady( | |
117 Profile::FromBrowserContext(web_contents()->GetBrowserContext())); | |
Devlin
2017/04/21 17:10:33
nit: profile()
robertshield
2017/04/25 18:02:17
Done.
| |
118 } | |
119 | |
104 std::string WebstoreInlineInstaller::GetJsonPostData() { | 120 std::string WebstoreInlineInstaller::GetJsonPostData() { |
105 // web_contents() might return null during tab destruction. This object would | 121 // web_contents() might return null during tab destruction. This object would |
106 // also be destroyed shortly thereafter but check to be on the safe side. | 122 // also be destroyed shortly thereafter but check to be on the safe side. |
107 if (!web_contents()) | 123 if (!web_contents()) |
108 return std::string(); | 124 return std::string(); |
109 | 125 |
110 content::NavigationController& navigation_controller = | 126 std::unique_ptr<base::ListValue> redirect_chain = |
Devlin
2017/04/21 17:06:11
optional: auto redirect_chain = base::MakeUnique<b
robertshield
2017/04/25 18:02:17
Done.
| |
111 web_contents()->GetController(); | 127 base::MakeUnique<base::ListValue>(); |
112 content::NavigationEntry* navigation_entry = | |
113 navigation_controller.GetLastCommittedEntry(); | |
114 | 128 |
115 if (navigation_entry) { | 129 if (SafeBrowsingNavigationEventsEnabled()) { |
130 // If we have it, use the new referrer checker. | |
131 safe_browsing::SafeBrowsingService* safe_browsing_service = | |
132 g_browser_process->safe_browsing_service(); | |
133 // May be null in some tests. | |
134 if (!safe_browsing_service) | |
135 return std::string(); | |
136 | |
137 scoped_refptr<SafeBrowsingNavigationObserverManager> | |
138 navigation_observer_manager = | |
139 safe_browsing_service->navigation_observer_manager(); | |
140 // This may be null if the navigation observer manager feature is | |
141 // disabled by experiment. | |
142 if (!navigation_observer_manager) | |
143 return std::string(); | |
144 | |
145 ReferrerChain referrer_chain; | |
146 SafeBrowsingNavigationObserverManager::AttributionResult result = | |
147 navigation_observer_manager->IdentifyReferrerChainByWebContents( | |
148 web_contents(), kExtensionReferrerUserGestureLimit, | |
149 &referrer_chain); | |
150 if (result != | |
151 SafeBrowsingNavigationObserverManager::NAVIGATION_EVENT_NOT_FOUND) { | |
152 // For now the CWS post data is JSON encoded. Consider moving it to a | |
153 // proto. | |
154 for (const auto& referrer_chain_entry : referrer_chain) { | |
155 // Referrer chain entries are a list of URLs in reverse chronological | |
156 // order, so the final URL is the last thing in the list and the initial | |
157 // landing page is the first thing in the list. | |
158 // Furthermore each entry may contain a series of server redirects | |
159 // stored in the same order. | |
160 redirect_chain->AppendString(referrer_chain_entry.url()); | |
161 for (const auto& server_side_redirect : | |
162 referrer_chain_entry.server_redirect_chain()) { | |
163 redirect_chain->AppendString(server_side_redirect.url()); | |
164 } | |
165 } | |
166 } | |
167 } else { | |
168 content::NavigationController& navigation_controller = | |
169 web_contents()->GetController(); | |
170 content::NavigationEntry* navigation_entry = | |
171 navigation_controller.GetLastCommittedEntry(); | |
116 const std::vector<GURL>& redirect_urls = | 172 const std::vector<GURL>& redirect_urls = |
117 navigation_entry->GetRedirectChain(); | 173 navigation_entry->GetRedirectChain(); |
Devlin
2017/04/21 17:06:11
We used to have a check for if (navigation_entry),
robertshield
2017/04/25 18:02:17
It was, but on further inspection, it was wrong. A
| |
118 | 174 for (const GURL& url : redirect_urls) { |
119 if (!redirect_urls.empty()) { | 175 redirect_chain->AppendString(url.spec()); |
120 base::DictionaryValue dictionary; | |
121 dictionary.SetString("id", id()); | |
122 dictionary.SetString("referrer", requestor_url_.spec()); | |
123 std::unique_ptr<base::ListValue> redirect_chain = | |
124 base::MakeUnique<base::ListValue>(); | |
125 for (const GURL& url : redirect_urls) { | |
126 redirect_chain->AppendString(url.spec()); | |
127 } | |
128 dictionary.Set("redirect_chain", std::move(redirect_chain)); | |
129 | |
130 std::string json; | |
131 base::JSONWriter::Write(dictionary, &json); | |
132 return json; | |
133 } | 176 } |
134 } | 177 } |
135 | 178 |
179 if (!redirect_chain->empty()) { | |
180 base::DictionaryValue dictionary; | |
181 dictionary.SetString("id", id()); | |
182 dictionary.SetString("referrer", requestor_url_.spec()); | |
183 dictionary.Set("redirect_chain", std::move(redirect_chain)); | |
184 | |
185 std::string json; | |
186 base::JSONWriter::Write(dictionary, &json); | |
187 return json; | |
188 } | |
189 | |
136 return std::string(); | 190 return std::string(); |
137 } | 191 } |
138 | 192 |
139 bool WebstoreInlineInstaller::CheckRequestorAlive() const { | 193 bool WebstoreInlineInstaller::CheckRequestorAlive() const { |
140 // The frame or tab may have gone away - cancel installation in that case. | 194 // The frame or tab may have gone away - cancel installation in that case. |
141 return host_ != nullptr && web_contents() != nullptr && | 195 return host_ != nullptr && web_contents() != nullptr && |
142 chrome::FindBrowserWithWebContents(web_contents()) != nullptr; | 196 chrome::FindBrowserWithWebContents(web_contents()) != nullptr; |
143 } | 197 } |
144 | 198 |
145 const GURL& WebstoreInlineInstaller::GetRequestorURL() const { | 199 const GURL& WebstoreInlineInstaller::GetRequestorURL() const { |
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
288 DLOG(WARNING) << "Could not parse " << verified_site_pattern_spec << | 342 DLOG(WARNING) << "Could not parse " << verified_site_pattern_spec << |
289 " as URL pattern " << parse_result; | 343 " as URL pattern " << parse_result; |
290 return false; | 344 return false; |
291 } | 345 } |
292 verified_site_pattern.SetScheme("*"); | 346 verified_site_pattern.SetScheme("*"); |
293 | 347 |
294 return verified_site_pattern.MatchesURL(requestor_url); | 348 return verified_site_pattern.MatchesURL(requestor_url); |
295 } | 349 } |
296 | 350 |
297 } // namespace extensions | 351 } // namespace extensions |
OLD | NEW |