Commit 2377c84b authored by harrisonsean's avatar harrisonsean Committed by Commit Bot

[iOS][Safety Check] Add timestamp support

Add support for a timestamp of when safety check last found issues.

Add support for initial unsafe states to only show if a safety check
has previously found isses.

Bug: 1078782
Change-Id: Ica710b284c066684cfad8488ada996295756ac29
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2421310
Commit-Queue: Sean Harrison <harrisonsean@chromium.org>
Reviewed-by: default avatarJavier Ernesto Flores Robles <javierrobles@chromium.org>
Reviewed-by: default avatarGauthier Ambard <gambard@chromium.org>
Cr-Commit-Position: refs/heads/master@{#810513}
parent af4400c5
......@@ -27,10 +27,14 @@ source_set("safety_check_ui") {
source_set("safety_check") {
configs += [ "//build/config/compiler:enable_arc" ]
sources = [
"safety_check_constants.h",
"safety_check_constants.mm",
"safety_check_coordinator.h",
"safety_check_coordinator.mm",
"safety_check_mediator.h",
"safety_check_mediator.mm",
"safety_check_utils.h",
"safety_check_utils.mm",
]
deps = [
":safety_check_ui",
......
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef IOS_CHROME_BROWSER_UI_SETTINGS_SAFETY_CHECK_SAFETY_CHECK_CONSTANTS_H_
#define IOS_CHROME_BROWSER_UI_SETTINGS_SAFETY_CHECK_SAFETY_CHECK_CONSTANTS_H_
#import <Foundation/Foundation.h>
// The NSUserDefaults key for the timestamp of last time safety check found an
// issue.
extern NSString* const kTimestampOfLastIssueFoundKey;
#endif // IOS_CHROME_BROWSER_UI_SETTINGS_SAFETY_CHECK_SAFETY_CHECK_CONSTANTS_H_
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import "ios/chrome/browser/ui/settings/safety_check/safety_check_constants.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
NSString* const kTimestampOfLastIssueFoundKey =
@"TimestampOfLastSafetyCheckIssueFound";
......@@ -23,6 +23,9 @@
// Initializes the check start section with |item|.
- (void)setCheckStartItem:(TableViewItem*)item;
// Initializes the footer with timestamp of last completed run.
- (void)setTimestampFooterItem:(TableViewLinkHeaderFooterItem*)item;
@end
#endif // IOS_CHROME_BROWSER_UI_SETTINGS_SAFETY_CHECK_SAFETY_CHECK_CONSUMER_H_
......@@ -8,6 +8,7 @@
#include "base/numerics/safe_conversions.h"
#include "base/strings/sys_string_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
#include "base/version.h"
#include "components/password_manager/core/browser/leak_detection_dialog_utils.h"
#include "components/password_manager/core/common/password_manager_features.h"
......@@ -25,9 +26,11 @@
#import "ios/chrome/browser/signin/authentication_service.h"
#include "ios/chrome/browser/sync/sync_setup_service.h"
#import "ios/chrome/browser/ui/settings/cells/settings_check_item.h"
#import "ios/chrome/browser/ui/settings/safety_check/safety_check_constants.h"
#import "ios/chrome/browser/ui/settings/safety_check/safety_check_consumer.h"
#import "ios/chrome/browser/ui/settings/safety_check/safety_check_navigation_commands.h"
#import "ios/chrome/browser/ui/settings/safety_check/safety_check_table_view_controller.h"
#import "ios/chrome/browser/ui/settings/safety_check/safety_check_utils.h"
#import "ios/chrome/browser/ui/settings/utils/observable_boolean.h"
#import "ios/chrome/browser/ui/settings/utils/pref_backed_boolean.h"
#import "ios/chrome/browser/ui/settings/utils/settings_utils.h"
......@@ -48,6 +51,7 @@
#import "net/base/mac/url_conversions.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/l10n/time_format.h"
#include "url/gurl.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
......@@ -71,6 +75,7 @@ typedef NS_ENUM(NSInteger, ItemType) {
HeaderItem,
// CheckStart section.
CheckStartItemType,
TimestampFooterItem,
};
// Enum with all possible states of the update check.
......@@ -192,6 +197,9 @@ typedef NS_ENUM(NSInteger, CheckStartStates) {
// Service to check if passwords are synced.
@property(nonatomic, assign) SyncSetupService* syncService;
// Whether or not a safety check just ran.
@property(nonatomic, assign) BOOL checkDidRun;
@end
@implementation SafetyCheckMediator
......@@ -243,11 +251,9 @@ typedef NS_ENUM(NSInteger, CheckStartStates) {
_updateCheckItem.infoButtonHidden = YES;
_updateCheckItem.trailingImage = nil;
// Show unsafe state if user already ran update check and the app is out of
// date.
// TODO(crbug.com/1078782): Add aditional check to make sure check has been
// run at least once.
if (!IsAppUpToDate()) {
// Show unsafe state if the app is out of date and safety check already
// found an issue.
if (!IsAppUpToDate() && PreviousSafetyCheckIssueFound()) {
_updateCheckRowState = UpdateCheckRowStateOutOfDate;
}
......@@ -266,11 +272,10 @@ typedef NS_ENUM(NSInteger, CheckStartStates) {
_passwordCheckItem.infoButtonHidden = YES;
_passwordCheckItem.trailingImage = nil;
// Show unsafe state if user already ran password check and there are
// Show unsafe state if user already ran safety check and there are
// compromised credentials.
// TODO(crbug.com/1078782): Add aditional check to make sure check has been
// run at least once.
if (!_passwordCheckManager->GetCompromisedCredentials().empty()) {
if (!_passwordCheckManager->GetCompromisedCredentials().empty() &&
PreviousSafetyCheckIssueFound()) {
_passwordCheckRowState = PasswordCheckRowStateUnSafe;
}
......@@ -400,6 +405,7 @@ typedef NS_ENUM(NSInteger, CheckStartStates) {
break;
}
case HeaderItem:
case TimestampFooterItem:
break;
}
}
......@@ -460,6 +466,7 @@ typedef NS_ENUM(NSInteger, CheckStartStates) {
return [self updateCheckErrorInfoString];
case CheckStartItemType:
case HeaderItem:
case TimestampFooterItem:
return nil;
}
}
......@@ -619,6 +626,8 @@ typedef NS_ENUM(NSInteger, CheckStartStates) {
// Stop any running checks.
self.passwordCheckManager->StopPasswordCheck();
self.checkDidRun = NO;
} else {
// Otherwise start a check.
......@@ -629,6 +638,11 @@ typedef NS_ENUM(NSInteger, CheckStartStates) {
// Change checkStartItem to cancel state.
self.checkStartState = CheckStartStateCancel;
// Hide the timestamp while running.
[self.consumer setTimestampFooterItem:nil];
self.checkDidRun = YES;
}
// Update the display.
......@@ -688,9 +702,21 @@ typedef NS_ENUM(NSInteger, CheckStartStates) {
if (self.checksRemaining) {
return;
}
// If a check has finished and issues were found, update the timestamp.
BOOL issuesFound =
(self.updateCheckRowState == UpdateCheckRowStateOutOfDate) ||
(self.passwordCheckRowState == PasswordCheckRowStateUnSafe);
if (self.checkDidRun && issuesFound) {
[self updateTimestampOfLastCheck];
self.checkDidRun = NO;
}
// If no checks are still running, reset |checkStartItem|.
self.checkStartState = CheckStartStateDefault;
[self reconfigureCheckStartSection];
// Since no checks are running, attempt to show the timestamp.
[self showTimestampIfNeeded];
return;
}
......@@ -957,4 +983,47 @@ typedef NS_ENUM(NSInteger, CheckStartStates) {
[self.consumer reconfigureCellsForItems:@[ self.checkStartItem ]];
}
// Updates the timestamp of when safety check last found an issue.
- (void)updateTimestampOfLastCheck {
NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
[defaults setDouble:base::Time::Now().ToDoubleT()
forKey:kTimestampOfLastIssueFoundKey];
}
// Shows the timestamp if a safety check has previously found issues.
- (void)showTimestampIfNeeded {
if (PreviousSafetyCheckIssueFound()) {
TableViewLinkHeaderFooterItem* footerItem =
[[TableViewLinkHeaderFooterItem alloc]
initWithType:TimestampFooterItem];
footerItem.text = [self formatElapsedTimeSinceLastCheck];
[self.consumer setTimestampFooterItem:footerItem];
} else {
// Hide the timestamp if safety check has never found issues.
[self.consumer setTimestampFooterItem:nil];
}
}
// Formats the last safety check issues found timestamp for display.
- (NSString*)formatElapsedTimeSinceLastCheck {
NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
base::Time lastCompletedCheck = base::Time::FromDoubleT(
[defaults doubleForKey:kTimestampOfLastIssueFoundKey]);
base::TimeDelta elapsedTime = base::Time::Now() - lastCompletedCheck;
base::string16 timestamp;
// If check found issues less than 1 minuete ago.
if (elapsedTime < base::TimeDelta::FromMinutes(1)) {
timestamp = l10n_util::GetStringUTF16(IDS_IOS_CHECK_FINISHED_JUST_NOW);
} else {
timestamp = ui::TimeFormat::SimpleWithMonthAndYear(
ui::TimeFormat::FORMAT_ELAPSED, ui::TimeFormat::LENGTH_LONG,
elapsedTime, true);
}
return l10n_util::GetNSStringF(
IDS_IOS_SETTINGS_SAFETY_CHECK_ISSUES_FOUND_TIME, timestamp);
}
@end
......@@ -43,6 +43,10 @@ typedef NS_ENUM(NSInteger, SectionIdentifier) {
// Current display state of the check start item.
@property(nonatomic, strong) TableViewItem* checkStartItem;
// Footer with timestamp for the safety check page.
@property(nonatomic, strong)
TableViewLinkHeaderFooterItem* safetyCheckFooterItem;
@end
@implementation SafetyCheckTableViewController
......@@ -71,6 +75,11 @@ typedef NS_ENUM(NSInteger, SectionIdentifier) {
[self reloadData];
}
- (void)setTimestampFooterItem:(TableViewLinkHeaderFooterItem*)footer {
_safetyCheckFooterItem = footer;
[self reloadData];
}
#pragma mark - ChromeTableViewController
- (void)loadModel {
......@@ -82,6 +91,7 @@ typedef NS_ENUM(NSInteger, SectionIdentifier) {
[self.tableViewModel addItem:item
toSectionWithIdentifier:SectionIdentifierCheckTypes];
}
if (self.safetyCheckHeaderItem) {
[self.tableViewModel setHeader:self.safetyCheckHeaderItem
forSectionWithIdentifier:SectionIdentifierCheckTypes];
......@@ -92,6 +102,11 @@ typedef NS_ENUM(NSInteger, SectionIdentifier) {
[self.tableViewModel addSectionWithIdentifier:SectionIdentifierCheckStart];
[self.tableViewModel addItem:self.checkStartItem
toSectionWithIdentifier:SectionIdentifierCheckStart];
if (self.safetyCheckFooterItem) {
[self.tableViewModel setFooter:self.safetyCheckFooterItem
forSectionWithIdentifier:SectionIdentifierCheckStart];
}
}
}
......
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef IOS_CHROME_BROWSER_UI_SETTINGS_SAFETY_CHECK_SAFETY_CHECK_UTILS_H_
#define IOS_CHROME_BROWSER_UI_SETTINGS_SAFETY_CHECK_SAFETY_CHECK_UTILS_H_
#import <UIKit/UIKit.h>
// Whether or not safety check previously found an issue.
bool PreviousSafetyCheckIssueFound();
#endif // IOS_CHROME_BROWSER_UI_SETTINGS_SAFETY_CHECK_SAFETY_CHECK_UTILS_H_
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import "ios/chrome/browser/ui/settings/safety_check/safety_check_utils.h"
#include "base/time/time.h"
#include "ios/chrome/browser/ui/settings/safety_check/safety_check_constants.h"
#include "ios/chrome/browser/upgrade/upgrade_utils.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
bool PreviousSafetyCheckIssueFound() {
// Verify if safety check has found issues at least once.
NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
base::Time lastCompletedCheck = base::Time::FromDoubleT(
[defaults doubleForKey:kTimestampOfLastIssueFoundKey]);
return lastCompletedCheck != base::Time();
}
......@@ -65,7 +65,9 @@
#import "ios/chrome/browser/ui/settings/language/language_settings_table_view_controller.h"
#import "ios/chrome/browser/ui/settings/password/passwords_coordinator.h"
#import "ios/chrome/browser/ui/settings/privacy/privacy_coordinator.h"
#import "ios/chrome/browser/ui/settings/safety_check/safety_check_constants.h"
#import "ios/chrome/browser/ui/settings/safety_check/safety_check_coordinator.h"
#import "ios/chrome/browser/ui/settings/safety_check/safety_check_utils.h"
#import "ios/chrome/browser/ui/settings/search_engine_table_view_controller.h"
#import "ios/chrome/browser/ui/settings/settings_table_view_controller_constants.h"
#import "ios/chrome/browser/ui/settings/sync/utils/sync_util.h"
......@@ -694,7 +696,7 @@ NSString* kDevViewSourceKey = @"DevViewSource";
_safetyCheckItem.leadingImage = safetyCheckIcon;
// Check if an issue state should be shown for updates.
if (!IsAppUpToDate()) {
if (!IsAppUpToDate() && PreviousSafetyCheckIssueFound()) {
UIImage* unSafeIconImage = [[UIImage imageNamed:@"settings_unsafe_state"]
imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
_safetyCheckItem.trailingImage = unSafeIconImage;
......@@ -1146,9 +1148,7 @@ NSString* kDevViewSourceKey = @"DevViewSource";
// Displays a red issue state on |_safetyCheckItem| if there is a reamining
// issue for any of the checks.
- (void)setSafetyCheckIssueStateUnsafe:(BOOL)isUnsafe {
// TODO(crbug.com/1078782): Add aditional check to make sure check has been
// run at least once.
if (isUnsafe) {
if (isUnsafe && PreviousSafetyCheckIssueFound()) {
UIImage* unSafeIconImage = [[UIImage imageNamed:@"settings_unsafe_state"]
imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
_safetyCheckItem.trailingImage = unSafeIconImage;
......
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