Commit 34548a8e authored by Tien Mai's avatar Tien Mai Committed by Commit Bot

[GCPW] Create bitmap version of profile picture used for reauth

- Linked agains gdi+ to use their image converting tools.
- Now when downloading the profile picture, the largest downloaded
picture will also be converted into .bmp and saved into the same
directory.
- Override the GetBitmapValue of the credential to read this bmp
file and return it.

Bug: 936847
Change-Id: Ie36b99e167c828ed7b46b88c400465f5fca44fd2
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1497192
Commit-Queue: Tien Mai <tienmai@chromium.org>
Reviewed-by: default avatarRoger Tawa <rogerta@chromium.org>
Cr-Commit-Position: refs/heads/master@{#638212}
parent f843ae38
......@@ -141,6 +141,7 @@ config("gaiacp_config") {
"advapi32.lib", # For LookupAccountSid()
"credui.lib", # For CredPackAuthenticationBufferW()
"crypt32.lib", # For CryptProtectData()
"gdiplus.lib", # To convert profile pictures to bmp.
"netapi32.lib", # For NetUserXXX()
"userenv.lib", # For GetUserProfileDirectoryW()
"winhttp.lib", # For WinHttpXXX()
......
......@@ -590,6 +590,23 @@ HRESULT CGaiaCredentialBase::GetStringValueImpl(DWORD field_id,
return hr;
}
HRESULT CGaiaCredentialBase::GetBitmapValueImpl(DWORD field_id,
HBITMAP* phbmp) {
HRESULT hr = E_INVALIDARG;
switch (field_id) {
case FID_PROVIDER_LOGO:
*phbmp = ::LoadBitmap(CURRENT_MODULE(),
MAKEINTRESOURCE(IDB_GOOGLE_LOGO_SMALL));
if (*phbmp)
hr = S_OK;
break;
default:
break;
}
return hr;
}
void CGaiaCredentialBase::ResetInternalState() {
LOGFN(INFO);
username_.Empty();
......@@ -910,19 +927,7 @@ HRESULT CGaiaCredentialBase::GetStringValue(DWORD field_id, wchar_t** value) {
}
HRESULT CGaiaCredentialBase::GetBitmapValue(DWORD field_id, HBITMAP* phbmp) {
HRESULT hr = E_INVALIDARG;
switch (field_id) {
case FID_PROVIDER_LOGO:
*phbmp = ::LoadBitmap(CURRENT_MODULE(),
MAKEINTRESOURCE(IDB_GOOGLE_LOGO_SMALL));
if (*phbmp)
hr = S_OK;
break;
default:
break;
}
return hr;
return GetBitmapValueImpl(field_id, phbmp);
}
HRESULT CGaiaCredentialBase::GetCheckboxValue(DWORD field_id,
......
......@@ -125,6 +125,10 @@ class ATL_NO_VTABLE CGaiaCredentialBase
// Gets the string value for the given credential UI field.
virtual HRESULT GetStringValueImpl(DWORD field_id, wchar_t** value);
// Can be overridden to change the icon used for anonymous tiles when they are
// shown in the selection list on the side and when they are selected.
virtual HRESULT GetBitmapValueImpl(DWORD field_id, HBITMAP* phbmp);
// Resets the state of the credential, forgetting any username or password
// that may have been set previously. Derived classes may override to
// perform more state resetting if needed, but should always call the base
......
......@@ -9,9 +9,10 @@
#include <winternl.h>
#define _NTDEF_ // Prevent redefition errors, must come after <winternl.h>
#include <ntsecapi.h> // For LsaLookupAuthenticationPackage()
#include <sddl.h> // For ConvertSidToStringSid()
#include <security.h> // For NEGOSSP_NAME_A
#include <ntsecapi.h> // For LsaLookupAuthenticationPackage()
#include <sddl.h> // For ConvertSidToStringSid()
#include <security.h> // For NEGOSSP_NAME_A
#include <shlobj.h> // For SHGetKnownFolderPath()
#include <wbemidl.h>
#include <atlbase.h>
......@@ -45,6 +46,9 @@
namespace credential_provider {
const wchar_t kDefaultProfilePictureFileExtension[] = L".jpg";
const wchar_t kCredentialLogoPictureFileExtension[] = L".bmp";
namespace {
constexpr char kSentinelFilename[] = "gcpw_startup.sentinel";
......@@ -634,6 +638,29 @@ base::string16 GetStringResource(int base_message_id) {
return localized_string;
}
HRESULT GetUserAccountPicturePath(const base::string16& sid,
base::FilePath* base_path) {
DCHECK(base_path);
base_path->clear();
LPWSTR path;
HRESULT hr = ::SHGetKnownFolderPath(FOLDERID_PublicUserTiles, 0, NULL, &path);
if (FAILED(hr)) {
LOGFN(ERROR) << "SHGetKnownFolderPath=" << putHR(hr);
return hr;
}
*base_path = base::FilePath(path).Append(sid);
::CoTaskMemFree(path);
return S_OK;
}
base::FilePath GetUserSizedAccountPictureFilePath(
const base::FilePath& account_picture_path,
int size,
const base::string16& picture_extension) {
return account_picture_path.Append(base::StringPrintf(
L"GoogleAccountPicture_%i%ls", size, picture_extension.c_str()));
}
base::string16 GetSelectedLanguage() {
return GetLanguageSelector().matched_candidate();
}
......
......@@ -54,6 +54,17 @@ constexpr int kMaxUsernameAttempts = 10;
// already exists.
constexpr int kInitialDuplicateUsernameIndex = 2;
// Default extension used as a fallback if the picture_url returned from gaia
// does not have a file extension.
extern const wchar_t kDefaultProfilePictureFileExtension[];
// Required extension for the picture that will be shown by the credential on
// the login screen. Windows only supports .bmp files for the images shown by
// credentials.
extern const wchar_t kCredentialLogoPictureFileExtension[];
constexpr int kLargestProfilePictureSize = 448;
// Because of some strange dependency problems with windows header files,
// define STATUS_SUCCESS here instead of including ntstatus.h or SubAuth.h
#define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
......@@ -200,6 +211,20 @@ void DeleteStartupSentinel();
// Gets a string resource from the DLL with the given id.
base::string16 GetStringResource(int base_message_id);
// Fills |base_path| with the path where user profile pictures are stored for
// user with |sid|. This function can fail if the known folder
// FOLDERID_PublicUserTiles cannot be found.
HRESULT GetUserAccountPicturePath(const base::string16& sid,
base::FilePath* base_path);
// Returns the full path to a user profile picture of a specific |size| and
// |picture_extension|. |account_picture_path| is path filled in by a call to
// GetUserAccountPicturePath.
base::FilePath GetUserSizedAccountPictureFilePath(
const base::FilePath& account_picture_path,
int size,
const base::string16& picture_extension);
// Gets the language selected by the base::win::i18n::LanguageSelector.
base::string16 GetSelectedLanguage();
......
......@@ -4,8 +4,12 @@
#include "chrome/credential_provider/gaiacp/reauth_credential_anonymous.h"
#include "base/files/file_util.h"
#include "chrome/credential_provider/common/gcp_strings.h"
#include "chrome/credential_provider/gaiacp/gcp_utils.h"
#include "chrome/credential_provider/gaiacp/logging.h"
#include "chrome/credential_provider/gaiacp/os_user_manager.h"
#include "chrome/credential_provider/gaiacp/reg_utils.h"
namespace credential_provider {
......@@ -37,4 +41,37 @@ HRESULT CReauthCredentialAnonymous::GetStringValueImpl(DWORD field_id,
return ::SHStrDupW(fullname.c_str(), value);
}
HRESULT CReauthCredentialAnonymous::GetBitmapValueImpl(DWORD field_id,
HBITMAP* phbmp) {
if (field_id == FID_PROVIDER_LOGO) {
base::FilePath account_picture_path;
HRESULT hr = GetUserAccountPicturePath(OLE2W(get_os_user_sid()),
&account_picture_path);
if (SUCCEEDED(hr)) {
base::FilePath target_picture_path = GetUserSizedAccountPictureFilePath(
account_picture_path, kLargestProfilePictureSize,
kCredentialLogoPictureFileExtension);
if (base::PathExists(target_picture_path)) {
*phbmp = static_cast<HBITMAP>(
::LoadImage(nullptr, target_picture_path.value().c_str(),
IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE));
if (*phbmp) {
return S_OK;
} else {
hr = HRESULT_FROM_WIN32(::GetLastError());
LOGFN(ERROR) << "Failed load image at='"
<< target_picture_path.value() << "' hr=" << putHR(hr);
}
} else {
LOGFN(ERROR) << "Required picture at='" << target_picture_path.value()
<< "' does not exist.";
}
} else {
LOGFN(ERROR) << "Failed to get account picture known folder hr="
<< putHR(hr);
}
}
return CReauthCredentialBase::GetBitmapValueImpl(field_id, phbmp);
}
} // namespace credential_provider
......@@ -39,6 +39,7 @@ class ATL_NO_VTABLE CReauthCredentialAnonymous
DECLARE_PROTECT_FINAL_CONSTRUCT()
HRESULT GetStringValueImpl(DWORD field_id, wchar_t** value) override;
HRESULT GetBitmapValueImpl(DWORD field_id, HBITMAP* phbmp) override;
};
} // namespace credential_provider
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment