Index: content/browser/download/quarantine_win.cc |
diff --git a/content/browser/download/quarantine_win.cc b/content/browser/download/quarantine_win.cc |
index 0d3943d3899038228f16c9f867ddd511a866603b..f45a6942404bbae64aa7af7fea3a74286842f120 100644 |
--- a/content/browser/download/quarantine_win.cc |
+++ b/content/browser/download/quarantine_win.cc |
@@ -11,6 +11,7 @@ |
#include <shellapi.h> |
#include <shlobj.h> |
#include <shobjidl.h> |
+#include <wininet.h> |
#include "base/files/file_util.h" |
#include "base/guid.h" |
@@ -171,13 +172,16 @@ QuarantineFileResult SetInternetZoneIdentifierDirectly( |
// |full_path| : is the path to the downloaded file. This should be the final |
// path of the download. Must be present. |
// |source_url|: the source URL for the download. If empty, the source will |
-// not be set. |
+// be set to 'about:internet'. |
+// |referrer_url|: the referrer URL for the download. If empty, the referrer |
+// will not be set. |
// |client_guid|: the GUID to be set in the IAttachmentExecute client slot. |
// Used to identify the app to the system AV function. |
// If GUID_NULL is passed, no client GUID is set. |
// |save_result|: Receives the result of invoking IAttachmentExecute::Save(). |
bool InvokeAttachmentServices(const base::FilePath& full_path, |
const std::string& source_url, |
+ const std::string& referrer_url, |
const GUID& client_guid, |
HRESULT* save_result) { |
base::win::ScopedComPtr<IAttachmentExecute> attachment_services; |
@@ -192,6 +196,10 @@ bool InvokeAttachmentServices(const base::FilePath& full_path, |
return false; |
} |
+ // Note that it is mandatory to check the return values from here on out. If |
+ // setting one of the parameters fails, it could leave the object in a state |
+ // where the final Save() call will also fail. |
+ |
hr = attachment_services->SetClientGuid(client_guid); |
if (FAILED(hr)) { |
RecordAttachmentServicesResult( |
@@ -206,16 +214,37 @@ bool InvokeAttachmentServices(const base::FilePath& full_path, |
return false; |
} |
- // Note: SetSource looks like it needs to be called, even if empty. |
- // Docs say it is optional, but it appears not calling it at all sets |
- // a zone that is too restrictive. |
- hr = attachment_services->SetSource(base::UTF8ToWide(source_url).c_str()); |
+ // The source URL could be empty if it was not a valid URL or was not HTTP/S. |
+ // If so, user "about:internet" as a fallback URL. The latter is known to |
+ // reliably map to the Internet zone. |
+ // |
+ // In addition, URLs that are longer than INTERNET_MAX_URL_LENGTH are also |
+ // known to cause problems for URLMon. Hence also use "about:internet" in |
+ // these cases. See http://crbug.com/601538. |
+ hr = attachment_services->SetSource( |
+ source_url.empty() || source_url.size() > INTERNET_MAX_URL_LENGTH |
+ ? L"about:internet" |
+ : base::UTF8ToWide(source_url).c_str()); |
if (FAILED(hr)) { |
RecordAttachmentServicesResult( |
AttachmentServicesResult::FAILED_TO_SET_PARAMETER); |
return false; |
} |
+ // Only set referrer if one is present and shorter than |
+ // INTERNET_MAX_URL_LENGTH. Also, the source_url is authoritative for |
+ // determining the relative danger of |full_path| so we don't consider it an |
+ // error if we have to skip the |referrer_url|. |
+ if (!referrer_url.empty() && referrer_url.size() < INTERNET_MAX_URL_LENGTH) { |
+ hr = attachment_services->SetReferrer( |
+ base::UTF8ToWide(referrer_url).c_str()); |
+ if (FAILED(hr)) { |
+ RecordAttachmentServicesResult( |
+ AttachmentServicesResult::FAILED_TO_SET_PARAMETER); |
+ return false; |
+ } |
+ } |
+ |
{ |
// This method has been known to take longer than 10 seconds in some |
// instances. |
@@ -280,8 +309,8 @@ QuarantineFileResult QuarantineFile(const base::FilePath& file, |
} |
HRESULT save_result = S_OK; |
- bool attachment_services_available = |
- InvokeAttachmentServices(file, source_url.spec(), guid, &save_result); |
+ bool attachment_services_available = InvokeAttachmentServices( |
+ file, source_url.spec(), referrer_url.spec(), guid, &save_result); |
if (!attachment_services_available) |
return SetInternetZoneIdentifierDirectly(file); |