Bug 1648384 - Make use of Result::propagateErr. r=mhowell

Differential Revision: https://phabricator.services.mozilla.com/D81031
This commit is contained in:
Simon Giesecke 2020-06-25 16:07:28 +00:00
Родитель 88f6ea40ee
Коммит 0378cc49f9
10 изменённых файлов: 57 добавлений и 61 удалений

Просмотреть файл

@ -161,7 +161,7 @@ LauncherResult<ElevationState> GetElevationState(
LauncherResult<TOKEN_ELEVATION_TYPE> elevationType = GetElevationType(token);
if (elevationType.isErr()) {
return LAUNCHER_ERROR_FROM_RESULT(elevationType);
return elevationType.propagateErr();
}
Maybe<ElevationState> elevationState;
@ -179,7 +179,7 @@ LauncherResult<ElevationState> GetElevationState(
// themselves.
LauncherResult<bool> isHighIntegrity = IsHighIntegrity(token);
if (isHighIntegrity.isErr()) {
return LAUNCHER_ERROR_FROM_RESULT(isHighIntegrity);
return isHighIntegrity.propagateErr();
}
if (!isHighIntegrity.unwrap()) {
@ -201,7 +201,7 @@ LauncherResult<ElevationState> GetElevationState(
LauncherResult<bool> isAdminByAppCompat =
IsAdminByAppCompat(HKEY_CURRENT_USER, aExecutablePath);
if (isAdminByAppCompat.isErr()) {
return LAUNCHER_ERROR_FROM_RESULT(isAdminByAppCompat);
return isAdminByAppCompat.propagateErr();
}
if (isAdminByAppCompat.unwrap()) {
@ -210,7 +210,7 @@ LauncherResult<ElevationState> GetElevationState(
isAdminByAppCompat =
IsAdminByAppCompat(HKEY_LOCAL_MACHINE, aExecutablePath);
if (isAdminByAppCompat.isErr()) {
return LAUNCHER_ERROR_FROM_RESULT(isAdminByAppCompat);
return isAdminByAppCompat.propagateErr();
}
if (isAdminByAppCompat.unwrap()) {
@ -232,7 +232,7 @@ LauncherResult<ElevationState> GetElevationState(
if (tokenResult.isOk()) {
aOutMediumIlToken.own(tokenResult.unwrap());
} else {
return LAUNCHER_ERROR_FROM_RESULT(tokenResult);
return tokenResult.propagateErr();
}
return elevationState.value();

Просмотреть файл

@ -71,7 +71,7 @@ static inline mozilla::LauncherResult<bool> IsSameBinaryAsParentProcess(
ImageFileCompareOption aOption = ImageFileCompareOption::Default) {
mozilla::LauncherResult<DWORD> parentPid = mozilla::nt::GetParentProcessId();
if (parentPid.isErr()) {
return LAUNCHER_ERROR_FROM_RESULT(parentPid);
return parentPid.propagateErr();
}
nsAutoHandle parentProcess(::OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION,

Просмотреть файл

@ -76,7 +76,7 @@ inline LauncherVoidResult RestoreImportDirectory(
LauncherResult<nt::DataDirectoryEntry> realImportDirectory =
detail::GetImageDirectoryViaFileIo(file, importDirEntryRva);
if (realImportDirectory.isErr()) {
return LAUNCHER_ERROR_FROM_RESULT(realImportDirectory);
return realImportDirectory.propagateErr();
}
nt::DataDirectoryEntry toWrite = realImportDirectory.unwrap();

Просмотреть файл

@ -1236,7 +1236,7 @@ inline LauncherResult<void*> GetProcessPebPtr(HANDLE aProcess) {
inline LauncherResult<HMODULE> GetProcessExeModule(HANDLE aProcess) {
LauncherResult<void*> ppeb = GetProcessPebPtr(aProcess);
if (ppeb.isErr()) {
return LAUNCHER_ERROR_FROM_RESULT(ppeb);
return ppeb.propagateErr();
}
PEB peb;
@ -1288,7 +1288,7 @@ inline LauncherResult<HMODULE> GetModuleHandleFromLeafName(
const UNICODE_STRING& aTarget) {
auto maybePeb = nt::GetProcessPebPtr(kCurrentProcess);
if (maybePeb.isErr()) {
return LAUNCHER_ERROR_FROM_RESULT(maybePeb);
return maybePeb.propagateErr();
}
const PPEB peb = reinterpret_cast<PPEB>(maybePeb.unwrap());

Просмотреть файл

@ -140,7 +140,7 @@ LauncherVoidResult LauncherRegistryInfo::ReflectPrefToRegistry(
const bool aEnable) {
LauncherResult<EnabledState> curEnabledState = IsEnabled();
if (curEnabledState.isErr()) {
return LAUNCHER_ERROR_FROM_RESULT(curEnabledState);
return curEnabledState.propagateErr();
}
bool isCurrentlyEnabled =
@ -155,7 +155,7 @@ LauncherVoidResult LauncherRegistryInfo::ReflectPrefToRegistry(
LauncherResult<bool> clearedLauncherTimestamp = ClearLauncherStartTimestamp();
MOZ_ASSERT(clearedLauncherTimestamp.isOk());
if (clearedLauncherTimestamp.isErr()) {
return LAUNCHER_ERROR_FROM_RESULT(clearedLauncherTimestamp);
return clearedLauncherTimestamp.propagateErr();
}
// Allow commit when we enable the launcher, otherwise block.
@ -170,7 +170,7 @@ LauncherVoidResult LauncherRegistryInfo::ReflectPrefToRegistry(
LauncherResult<bool> clearedBrowserTimestamp = ClearBrowserStartTimestamp();
MOZ_ASSERT(clearedBrowserTimestamp.isOk());
if (clearedBrowserTimestamp.isErr()) {
return LAUNCHER_ERROR_FROM_RESULT(clearedBrowserTimestamp);
return clearedBrowserTimestamp.propagateErr();
}
return Ok();
@ -180,7 +180,7 @@ LauncherVoidResult LauncherRegistryInfo::ReflectTelemetryPrefToRegistry(
const bool aEnable) {
LauncherResult<Disposition> disposition = Open();
if (disposition.isErr()) {
return LAUNCHER_ERROR_FROM_RESULT(disposition);
return disposition.propagateErr();
}
return WriteRegistryValueData(mRegKey, ResolveTelemetryValueName(), REG_DWORD,
@ -191,17 +191,17 @@ LauncherResult<LauncherRegistryInfo::ProcessType> LauncherRegistryInfo::Check(
const ProcessType aDesiredType, const CheckOption aOption) {
LauncherResult<Disposition> disposition = Open();
if (disposition.isErr()) {
return LAUNCHER_ERROR_FROM_RESULT(disposition);
return disposition.propagateErr();
}
LauncherResult<DWORD> ourImageTimestamp = GetCurrentImageTimestamp();
if (ourImageTimestamp.isErr()) {
return LAUNCHER_ERROR_FROM_RESULT(ourImageTimestamp);
return ourImageTimestamp.propagateErr();
}
LauncherResult<Maybe<DWORD>> savedImageTimestamp = GetSavedImageTimestamp();
if (savedImageTimestamp.isErr()) {
return LAUNCHER_ERROR_FROM_RESULT(savedImageTimestamp);
return savedImageTimestamp.propagateErr();
}
// If we don't have a saved timestamp, or we do but it doesn't match with
@ -210,13 +210,13 @@ LauncherResult<LauncherRegistryInfo::ProcessType> LauncherRegistryInfo::Check(
savedImageTimestamp.inspect().value() != ourImageTimestamp.inspect()) {
LauncherVoidResult clearResult = ClearStartTimestamps();
if (clearResult.isErr()) {
return LAUNCHER_ERROR_FROM_RESULT(clearResult);
return clearResult.propagateErr();
}
LauncherVoidResult writeResult =
WriteImageTimestamp(ourImageTimestamp.inspect());
if (writeResult.isErr()) {
return LAUNCHER_ERROR_FROM_RESULT(writeResult);
return writeResult.propagateErr();
}
}
@ -240,13 +240,13 @@ LauncherResult<LauncherRegistryInfo::ProcessType> LauncherRegistryInfo::Check(
LauncherResult<Maybe<uint64_t>> lastLauncherTimestampResult =
GetLauncherStartTimestamp();
if (lastLauncherTimestampResult.isErr()) {
return LAUNCHER_ERROR_FROM_RESULT(lastLauncherTimestampResult);
return lastLauncherTimestampResult.propagateErr();
}
LauncherResult<Maybe<uint64_t>> lastBrowserTimestampResult =
GetBrowserStartTimestamp();
if (lastBrowserTimestampResult.isErr()) {
return LAUNCHER_ERROR_FROM_RESULT(lastBrowserTimestampResult);
return lastBrowserTimestampResult.propagateErr();
}
const Maybe<uint64_t>& lastLauncherTimestamp =
@ -311,7 +311,7 @@ LauncherResult<LauncherRegistryInfo::ProcessType> LauncherRegistryInfo::Check(
LauncherVoidResult LauncherRegistryInfo::DisableDueToFailure() {
LauncherResult<Disposition> disposition = Open();
if (disposition.isErr()) {
return LAUNCHER_ERROR_FROM_RESULT(disposition);
return disposition.propagateErr();
}
LauncherVoidResult result = WriteBrowserStartTimestamp(0ULL);
if (result.isOk()) {
@ -330,14 +330,14 @@ LauncherVoidResult LauncherRegistryInfo::Commit() {
LauncherResult<Disposition> disposition = Open();
if (disposition.isErr()) {
return LAUNCHER_ERROR_FROM_RESULT(disposition);
return disposition.propagateErr();
}
if (mLauncherTimestampToWrite.isSome()) {
LauncherVoidResult writeResult =
WriteLauncherStartTimestamp(mLauncherTimestampToWrite.value());
if (writeResult.isErr()) {
return LAUNCHER_ERROR_FROM_RESULT(writeResult);
return writeResult.propagateErr();
}
mLauncherTimestampToWrite = Nothing();
}
@ -346,7 +346,7 @@ LauncherVoidResult LauncherRegistryInfo::Commit() {
LauncherVoidResult writeResult =
WriteBrowserStartTimestamp(mBrowserTimestampToWrite.value());
if (writeResult.isErr()) {
return LAUNCHER_ERROR_FROM_RESULT(writeResult);
return writeResult.propagateErr();
}
mBrowserTimestampToWrite = Nothing();
}
@ -383,19 +383,19 @@ LauncherResult<LauncherRegistryInfo::EnabledState>
LauncherRegistryInfo::IsEnabled() {
LauncherResult<Disposition> disposition = Open();
if (disposition.isErr()) {
return LAUNCHER_ERROR_FROM_RESULT(disposition);
return disposition.propagateErr();
}
LauncherResult<Maybe<uint64_t>> lastLauncherTimestamp =
GetLauncherStartTimestamp();
if (lastLauncherTimestamp.isErr()) {
return LAUNCHER_ERROR_FROM_RESULT(lastLauncherTimestamp);
return lastLauncherTimestamp.propagateErr();
}
LauncherResult<Maybe<uint64_t>> lastBrowserTimestamp =
GetBrowserStartTimestamp();
if (lastBrowserTimestamp.isErr()) {
return LAUNCHER_ERROR_FROM_RESULT(lastBrowserTimestamp);
return lastBrowserTimestamp.propagateErr();
}
return GetEnabledState(lastLauncherTimestamp.inspect(),
@ -405,13 +405,13 @@ LauncherRegistryInfo::IsEnabled() {
LauncherResult<bool> LauncherRegistryInfo::IsTelemetryEnabled() {
LauncherResult<Disposition> disposition = Open();
if (disposition.isErr()) {
return LAUNCHER_ERROR_FROM_RESULT(disposition);
return disposition.propagateErr();
}
LauncherResult<Maybe<DWORD>> result = ReadRegistryValueData<DWORD>(
mRegKey, ResolveTelemetryValueName(), REG_DWORD);
if (result.isErr()) {
return LAUNCHER_ERROR_FROM_RESULT(result);
return result.propagateErr();
}
if (result.inspect().isNothing()) {
@ -496,12 +496,12 @@ LauncherVoidResult LauncherRegistryInfo::ClearStartTimestamps() {
LauncherResult<bool> clearedLauncherTimestamp = ClearLauncherStartTimestamp();
if (clearedLauncherTimestamp.isErr()) {
return LAUNCHER_ERROR_FROM_RESULT(clearedLauncherTimestamp);
return clearedLauncherTimestamp.propagateErr();
}
LauncherResult<bool> clearedBrowserTimestamp = ClearBrowserStartTimestamp();
if (clearedBrowserTimestamp.isErr()) {
return LAUNCHER_ERROR_FROM_RESULT(clearedBrowserTimestamp);
return clearedBrowserTimestamp.propagateErr();
}
// Reset both timestamps to align with registry deletion

Просмотреть файл

@ -54,7 +54,7 @@ LauncherResult<bool> IsAdminWithoutUac() {
LauncherResult<bool> containsAdminGroup =
IsMemberOfAdministrators(nsAutoHandle());
if (containsAdminGroup.isErr()) {
return LAUNCHER_ERROR_FROM_RESULT(containsAdminGroup);
return containsAdminGroup.propagateErr();
}
if (!containsAdminGroup.unwrap()) {
@ -63,7 +63,7 @@ LauncherResult<bool> IsAdminWithoutUac() {
LauncherResult<bool> isUacEnabled = IsUacEnabled();
if (isUacEnabled.isErr()) {
return LAUNCHER_ERROR_FROM_RESULT(isUacEnabled);
return isUacEnabled.propagateErr();
}
return !isUacEnabled.unwrap();

Просмотреть файл

@ -51,7 +51,7 @@ static DWORD gMyImageTimestamp;
mozilla::LauncherResult<mozilla::LauncherRegistryInfo::ProcessType> \
result = info.Check(mozilla::LauncherRegistryInfo::desired); \
if (result.isErr()) { \
return LAUNCHER_ERROR_FROM_RESULT(result); \
return result.propagateErr(); \
} \
if (result.unwrap() != mozilla::LauncherRegistryInfo::expected) { \
return LAUNCHER_ERROR_FROM_HRESULT(E_FAIL); \
@ -63,7 +63,7 @@ static DWORD gMyImageTimestamp;
mozilla::LauncherResult<mozilla::LauncherRegistryInfo::EnabledState> \
enabled = info.IsEnabled(); \
if (enabled.isErr()) { \
return LAUNCHER_ERROR_FROM_RESULT(enabled); \
return enabled.propagateErr(); \
} \
if (enabled.unwrap() != mozilla::LauncherRegistryInfo::expected) { \
return LAUNCHER_ERROR_FROM_HRESULT(E_UNEXPECTED); \
@ -74,7 +74,7 @@ static DWORD gMyImageTimestamp;
do { \
mozilla::LauncherResult<bool> enabled = info.IsTelemetryEnabled(); \
if (enabled.isErr()) { \
return LAUNCHER_ERROR_FROM_RESULT(enabled); \
return enabled.propagateErr(); \
} \
if (enabled.unwrap() != expected) { \
return LAUNCHER_ERROR_FROM_HRESULT(E_UNEXPECTED); \
@ -86,7 +86,7 @@ static DWORD gMyImageTimestamp;
mozilla::LauncherResult<mozilla::Maybe<DWORD>> result = \
ReadRegistryValueData<DWORD>(name, REG_DWORD); \
if (result.isErr()) { \
return LAUNCHER_ERROR_FROM_RESULT(result); \
return result.propagateErr(); \
} \
if (result.inspect().isNothing() || \
result.inspect().value() != expected) { \
@ -99,7 +99,7 @@ static DWORD gMyImageTimestamp;
mozilla::LauncherResult<mozilla::Maybe<uint64_t>> result = \
ReadRegistryValueData<uint64_t>(name, REG_QWORD); \
if (result.isErr()) { \
return LAUNCHER_ERROR_FROM_RESULT(result); \
return result.propagateErr(); \
} \
if (result.inspect().isNothing()) { \
return LAUNCHER_ERROR_FROM_HRESULT(E_UNEXPECTED); \
@ -111,7 +111,7 @@ static DWORD gMyImageTimestamp;
mozilla::LauncherResult<mozilla::Maybe<uint64_t>> result = \
ReadRegistryValueData<uint64_t>(name, REG_QWORD); \
if (result.isErr()) { \
return LAUNCHER_ERROR_FROM_RESULT(result); \
return result.propagateErr(); \
} \
if (result.inspect().isNothing() || \
result.inspect().value() != expected) { \
@ -124,7 +124,7 @@ static DWORD gMyImageTimestamp;
mozilla::LauncherResult<mozilla::Maybe<DWORD>> result = \
ReadRegistryValueData<DWORD>(name, REG_DWORD); \
if (result.isErr()) { \
return LAUNCHER_ERROR_FROM_RESULT(result); \
return result.propagateErr(); \
} \
if (result.inspect().isSome()) { \
return LAUNCHER_ERROR_FROM_HRESULT(E_UNEXPECTED); \
@ -136,7 +136,7 @@ static DWORD gMyImageTimestamp;
mozilla::LauncherResult<mozilla::Maybe<uint64_t>> result = \
ReadRegistryValueData<uint64_t>(name, REG_QWORD); \
if (result.isErr()) { \
return LAUNCHER_ERROR_FROM_RESULT(result); \
return result.propagateErr(); \
} \
if (result.inspect().isSome()) { \
return LAUNCHER_ERROR_FROM_HRESULT(E_UNEXPECTED); \
@ -279,12 +279,12 @@ static mozilla::LauncherVoidResult TestNormal() {
mozilla::LauncherResult<mozilla::Maybe<uint64_t>> launcherTs =
ReadRegistryValueData<uint64_t>(gLauncherValue, REG_QWORD);
if (launcherTs.isErr()) {
return LAUNCHER_ERROR_FROM_RESULT(launcherTs);
return launcherTs.propagateErr();
}
mozilla::LauncherResult<mozilla::Maybe<uint64_t>> browserTs =
ReadRegistryValueData<uint64_t>(gBrowserValue, REG_QWORD);
if (browserTs.isErr()) {
return LAUNCHER_ERROR_FROM_RESULT(browserTs);
return browserTs.propagateErr();
}
if (launcherTs.inspect().isNothing() || browserTs.inspect().isNothing() ||
browserTs.inspect().value() <= launcherTs.inspect().value()) {
@ -451,7 +451,7 @@ static mozilla::LauncherVoidResult TestDisableDueToFailure() {
// Now call DisableDueToFailure
mozilla::LauncherVoidResult lvr = info.DisableDueToFailure();
if (lvr.isErr()) {
return LAUNCHER_ERROR_FROM_RESULT(lvr);
return lvr.propagateErr();
}
// We should now be FailDisabled
@ -479,7 +479,7 @@ static mozilla::LauncherVoidResult TestPrefReflection() {
mozilla::LauncherRegistryInfo info;
mozilla::LauncherVoidResult reflectOk = info.ReflectPrefToRegistry(false);
if (reflectOk.isErr()) {
return LAUNCHER_ERROR_FROM_RESULT(reflectOk);
return reflectOk.propagateErr();
}
// Launcher timestamp should be non-existent.
@ -492,7 +492,7 @@ static mozilla::LauncherVoidResult TestPrefReflection() {
// Now test to see what happens when the pref is set to ON.
reflectOk = info.ReflectPrefToRegistry(true);
if (reflectOk.isErr()) {
return LAUNCHER_ERROR_FROM_RESULT(reflectOk);
return reflectOk.propagateErr();
}
// Launcher and browser timestamps should be non-existent.
@ -517,13 +517,13 @@ static mozilla::LauncherVoidResult TestTelemetryConfig() {
mozilla::LauncherVoidResult reflectOk =
info.ReflectTelemetryPrefToRegistry(false);
if (reflectOk.isErr()) {
return LAUNCHER_ERROR_FROM_RESULT(reflectOk);
return reflectOk.propagateErr();
}
EXPECT_TELEMETRY_IS_ENABLED(false);
reflectOk = info.ReflectTelemetryPrefToRegistry(true);
if (reflectOk.isErr()) {
return LAUNCHER_ERROR_FROM_RESULT(reflectOk);
return reflectOk.propagateErr();
}
EXPECT_TELEMETRY_IS_ENABLED(true);
@ -540,12 +540,12 @@ static mozilla::LauncherVoidResult TestCommitAbort() {
mozilla::LauncherResult<mozilla::Maybe<uint64_t>> launcherValue =
ReadRegistryValueData<uint64_t>(gLauncherValue, REG_QWORD);
if (launcherValue.isErr() || launcherValue.inspect().isNothing()) {
return LAUNCHER_ERROR_FROM_RESULT(launcherValue);
return launcherValue.propagateErr();
}
mozilla::LauncherResult<mozilla::Maybe<uint64_t>> browserValue =
ReadRegistryValueData<uint64_t>(gBrowserValue, REG_QWORD);
if (browserValue.isErr() || browserValue.inspect().isNothing()) {
return LAUNCHER_ERROR_FROM_RESULT(browserValue);
return browserValue.propagateErr();
}
uint64_t launcherTs = launcherValue.inspect().value();
uint64_t browserTs = browserValue.inspect().value();
@ -590,7 +590,7 @@ static mozilla::LauncherVoidResult TestDisableDuringLauncherLaunch() {
mozilla::LauncherResult<mozilla::Maybe<uint64_t>> launcherTs =
ReadRegistryValueData<uint64_t>(gLauncherValue, REG_QWORD);
if (launcherTs.isErr()) {
return LAUNCHER_ERROR_FROM_RESULT(launcherTs);
return launcherTs.propagateErr();
}
if (launcherTs.inspect().isNothing()) {
return LAUNCHER_ERROR_FROM_HRESULT(E_UNEXPECTED);
@ -605,7 +605,7 @@ static mozilla::LauncherVoidResult TestDisableDuringLauncherLaunch() {
mozilla::LauncherRegistryInfo info;
mozilla::LauncherVoidResult vr = info.DisableDueToFailure();
if (vr.isErr()) {
return LAUNCHER_ERROR_FROM_RESULT(vr);
return vr.propagateErr();
}
return mozilla::Ok();
}();
@ -650,7 +650,7 @@ static mozilla::LauncherVoidResult TestDisableDuringBrowserLaunch() {
mozilla::LauncherRegistryInfo info;
mozilla::LauncherVoidResult vr = info.DisableDueToFailure();
if (vr.isErr()) {
return LAUNCHER_ERROR_FROM_RESULT(vr);
return vr.propagateErr();
}
return mozilla::Ok();
}();
@ -683,7 +683,7 @@ static mozilla::LauncherVoidResult TestReEnable() {
mozilla::LauncherRegistryInfo info;
vr = info.DisableDueToFailure();
if (vr.isErr()) {
return LAUNCHER_ERROR_FROM_RESULT(vr);
return vr.propagateErr();
}
EXPECT_ENABLED_STATE_IS(EnabledState::FailDisabled);
@ -705,7 +705,7 @@ static mozilla::LauncherVoidResult TestReEnable() {
// Make ForceDisabled
vr = info.ReflectPrefToRegistry(false);
if (vr.isErr()) {
return LAUNCHER_ERROR_FROM_RESULT(vr);
return vr.propagateErr();
}
EXPECT_ENABLED_STATE_IS(EnabledState::ForceDisabled);

Просмотреть файл

@ -36,7 +36,7 @@ namespace mozilla {
inline LauncherResult<_bstr_t> UrlmonValidateUri(const wchar_t* aUri) {
LauncherResult<UniqueAbsolutePidl> pidlResult = ShellParseDisplayName(aUri);
if (pidlResult.isErr()) {
return LAUNCHER_ERROR_FROM_RESULT(pidlResult);
return pidlResult.propagateErr();
}
// The value of |flags| is the same value as used in ieframe!_EnsureIUri in

Просмотреть файл

@ -284,10 +284,6 @@ using LauncherVoidResultWithLineInfo = LauncherResultWithLineInfo<Ok>;
#endif // defined(MOZILLA_INTERNAL_API)
// This macro enables copying of a mozilla::LauncherError from a
// mozilla::LauncherResult<Foo> into a mozilla::LauncherResult<Bar>
#define LAUNCHER_ERROR_FROM_RESULT(result) ::mozilla::Err(result.inspectErr())
// How long to wait for a created process to become available for input,
// to prevent that process's windows being forced to the background.
// This is used across update, restart, and the launcher.

Просмотреть файл

@ -14,7 +14,7 @@ using namespace mozilla;
static LauncherResult<_bstr_t> ShellValidateUri(const wchar_t* aUri) {
LauncherResult<UniqueAbsolutePidl> pidlResult = ShellParseDisplayName(aUri);
if (pidlResult.isErr()) {
return LAUNCHER_ERROR_FROM_RESULT(pidlResult);
return pidlResult.propagateErr();
}
UniqueAbsolutePidl pidl = pidlResult.unwrap();