Skip to content
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion windows/src/desktop/kmshell/kmshell.dpr
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,8 @@ uses
Keyman.System.UpdateStateMachine in 'main\Keyman.System.UpdateStateMachine.pas',
Keyman.System.DownloadUpdate in 'main\Keyman.System.DownloadUpdate.pas',
Keyman.System.ExecutionHistory in '..\..\..\..\common\windows\delphi\general\Keyman.System.ExecutionHistory.pas',
Keyman.Configuration.UI.UfrmStartInstall in 'main\Keyman.Configuration.UI.UfrmStartInstall.pas' {frmStartInstall};
Keyman.Configuration.UI.UfrmStartInstall in 'main\Keyman.Configuration.UI.UfrmStartInstall.pas' {frmStartInstall},
UtilNetworkConnection in 'util\UtilNetworkConnection.pas';

{$R VERSION.RES}
{$R manifest.res}
Expand Down
15 changes: 5 additions & 10 deletions windows/src/desktop/kmshell/kmshell.dproj
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,7 @@
<DCCReference Include="main\Keyman.Configuration.UI.UfrmStartInstall.pas">
<Form>frmStartInstall</Form>
</DCCReference>
<DCCReference Include="util\UtilNetworkConnection.pas"/>
<None Include="Profiling\AQtimeModule1.aqt"/>
<BuildConfiguration Include="Debug">
<Key>Cfg_2</Key>
Expand Down Expand Up @@ -418,27 +419,21 @@
<Platform value="Win64">False</Platform>
</Platforms>
<Deployment Version="3">
<DeployFile LocalName="bin\Win32\Debug\kmshell.rsm" Configuration="Debug" Class="DebugSymbols">
<Platform Name="Win32">
<RemoteName>kmshell.rsm</RemoteName>
<Overwrite>true</Overwrite>
</Platform>
</DeployFile>
<DeployFile LocalName="bin\Win32\Debug\kmshell.exe" Configuration="Debug" Class="ProjectOutput">
<Platform Name="Win32">
<RemoteName>kmshell.exe</RemoteName>
<Overwrite>true</Overwrite>
</Platform>
</DeployFile>
<DeployFile LocalName="bin\Win32\Debug\kmshell.exe" Configuration="Debug" Class="ProjectOutput">
<DeployFile LocalName="Profiling\AQtimeModule1.aqt" Configuration="Debug" Class="ProjectFile">
<Platform Name="Win32">
<RemoteName>kmshell.exe</RemoteName>
<RemoteDir>.\</RemoteDir>
<Overwrite>true</Overwrite>
</Platform>
</DeployFile>
<DeployFile LocalName="Profiling\AQtimeModule1.aqt" Configuration="Debug" Class="ProjectFile">
<DeployFile LocalName="bin\Win32\Debug\kmshell.rsm" Configuration="Debug" Class="DebugSymbols">
<Platform Name="Win32">
<RemoteDir>.\</RemoteDir>
<RemoteName>kmshell.rsm</RemoteName>
<Overwrite>true</Overwrite>
</Platform>
</DeployFile>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ object frmStartInstall: TfrmStartInstall
object lblUpdateMessage: TLabel
Left = 64
Top = 89
Width = 313
Width = 303
Height = 34
Caption = 'An update to Keyman has been downloaded and is ready to install.'
Font.Charset = DEFAULT_CHARSET
Expand Down Expand Up @@ -146,6 +146,34 @@ object frmStartInstall: TfrmStartInstall
414B8B49C3A0A5C5A461D0D262FA3F82D7F60E256D51F10000000049454E44AE
426082}
end
object shpMeteredWarning: TShape
Left = 60
Top = 149
Width = 314
Height = 45
Brush.Color = 15132415
Pen.Color = clRed
Visible = False
end
object lblMeteredWarning: TLabel
Left = 64
Top = 150
Width = 303
Height = 43
AutoSize = False
Caption = 'Metered Warning'
Color = 15132415
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -13
Font.Name = 'Segoe UI'
Font.Style = []
ParentColor = False
ParentFont = False
Transparent = False
Visible = False
WordWrap = True
end
object cmdInstall: TButton
Left = 229
Top = 200
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,27 @@ interface
Winapi.Messages,
Winapi.Windows,
UfrmKeymanBase,
UserMessages, Vcl.Imaging.pngimage;
UserMessages,
UtilNetworkConnection,
Vcl.Imaging.pngimage;

type
TfrmStartInstall = class(TfrmKeymanBase)
cmdInstall: TButton;
cmdLater: TButton;
lblUpdateMessage: TLabel;
imgKeymanLogo: TImage;
shpMeteredWarning: TShape;
lblMeteredWarning: TLabel;
procedure FormCreate(Sender: TObject);
private
FRestartRequired: Boolean;
FReadyToInstall: Boolean;
public
constructor Create(AOwner: TComponent; const RestartRequired: Boolean); reintroduce;
constructor Create(
AOwner: TComponent;
const RestartRequired: Boolean;
const ReadyToInstall: Boolean = False); reintroduce;
end;

implementation
Expand All @@ -41,13 +49,19 @@ implementation

{$R *.dfm}

constructor TfrmStartInstall.Create(AOwner: TComponent; const RestartRequired: Boolean);
constructor TfrmStartInstall.Create(
AOwner: TComponent;
const RestartRequired: Boolean;
const ReadyToInstall: Boolean = False);
begin
inherited Create(AOwner);
FRestartRequired := RestartRequired;
FReadyToInstall := ReadyToInstall;
end;

procedure TfrmStartInstall.FormCreate(Sender: TObject);
var
IsMetered: Boolean;
begin
inherited;
cmdInstall.Caption := MsgFromId(S_Update_Now);
Expand All @@ -56,6 +70,12 @@ procedure TfrmStartInstall.FormCreate(Sender: TObject);
lblUpdateMessage.Caption := MsgFromId(S_Update_Restart_Req)
else
lblUpdateMessage.Caption := MsgFromId(S_Ready_To_Install);

IsMetered := UtilNetworkConnection.IsMetered;
lblMeteredWarning.Visible := IsMetered and not FReadyToInstall;
Comment thread
rc-swag marked this conversation as resolved.
Outdated
shpMeteredWarning.Visible := IsMetered and not FReadyToInstall;
if IsMetered then
lblMeteredWarning.Caption := MsgFromId(S_Metered_Warning);
end;

end.
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ interface
KeymanPaths,
Keyman.System.ExecutionHistory,
Keyman.System.UpdateCheckResponse,
utilkmshell;
utilkmshell,
UtilNetworkConnection;

type
EUpdateStateMachine = class(Exception);
Expand Down Expand Up @@ -719,7 +720,9 @@ procedure UpdateAvailableState.EnterState;
begin
// Enter UpdateAvailableState
bucStateContext.SetRegistryState(usUpdateAvailable);
if bucStateContext.FAutomaticUpdate then

if bucStateContext.FAutomaticUpdate and
not UtilNetworkConnection.IsBackgroundUpdateAllowed then
Comment thread
ermshiperete marked this conversation as resolved.
Outdated
begin
StartDownloadProcess;
end;
Expand Down Expand Up @@ -751,7 +754,8 @@ procedure UpdateAvailableState.HandleCheck;

function UpdateAvailableState.HandleKmShell;
begin
if bucStateContext.FAutomaticUpdate then
if bucStateContext.FAutomaticUpdate and
not UtilNetworkConnection.IsBackgroundUpdateAllowed then
Comment thread
ermshiperete marked this conversation as resolved.
Outdated
begin
// we will use a new kmshell process to enable
// the download as background process.
Expand All @@ -773,6 +777,8 @@ procedure UpdateAvailableState.HandleAbort;

procedure UpdateAvailableState.HandleInstallNow;
begin
// This is deliberate action therefore no
// need to check if background update is allowed.
bucStateContext.SetApplyNow(True);
// A new kmshell process will be used to download
StartDownloadProcess;
Expand Down
8 changes: 7 additions & 1 deletion windows/src/desktop/kmshell/main/UfrmMain.pas
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,7 @@ implementation
utilexecute,
utilkmshell,
utilhttp,
UtilNetworkConnection,
utiluac,
utilxml,
KeymanPaths;
Expand Down Expand Up @@ -817,10 +818,15 @@ procedure TfrmMain.Update_ApplyNow;
ShellPath : string;
FResult, InstallNow: Boolean;
frmStartInstallNow: TfrmStartInstall;
IsMetered: Boolean;
begin
InstallNow := True;
// Confirm User is ok that this will require a reset
if HasKeymanRun then
// The metered warning has been added to the update pop up. In the future
// it would be better to have this warning in a banner on the configuration
// page.
IsMetered := UtilNetworkConnection.IsMetered;
if HasKeymanRun OR IsMetered then
Comment thread
ermshiperete marked this conversation as resolved.
Outdated
begin
frmStartInstallNow := TfrmStartInstall.Create(nil, true);
Comment thread
ermshiperete marked this conversation as resolved.
Outdated
try
Expand Down
2 changes: 1 addition & 1 deletion windows/src/desktop/kmshell/main/initprog.pas
Original file line number Diff line number Diff line change
Expand Up @@ -677,7 +677,7 @@ function ShouldSendToBUpdateSM(FSilent: Boolean; BUpdateSM: TUpdateStateMachine;
(FMode in [fmStart, fmSplash, fmMain, fmAbout,
fmHelp, fmShowHelp, fmSettings, fmBoot]) then
begin
frmStartInstall := TfrmStartInstall.Create(nil, false);
frmStartInstall := TfrmStartInstall.Create(nil, false, ValidateReadyToInstall);
try
Result := frmStartInstall.ShowModal = mrOk;
finally
Expand Down
94 changes: 94 additions & 0 deletions windows/src/desktop/kmshell/util/UtilNetworkConnection.pas
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
(*
* Keyman is copyright (C) SIL Global. MIT License.
*
* Notes: Enable checking for metered connection and background data restrictions.
*)
unit UtilNetworkConnection;

interface

(**
* Checks if the current internet connection is restricted, roaming, or over its
* data limit.
* This learn microsoft article shows how to combine network costs to determine
* if the connection is metered.
* https://learn.microsoft.com/en-us/uwp/api/windows.networking.connectivity.connectionprofile?view=winrt-28000
*
* @returns True if the connection is metered, False otherwise.
*)
function IsMetered: Boolean;

(**
* Checks if background data usage is explicitly restricted by the current network profile.
*
* @returns True if background data usage is restricted, False otherwise.
*)
function IsBackgroundDataRestricted: Boolean;

(**
* Determines whether background updates are allowed.
*
* @returns True if updates can proceed, False if blocked by network constraints.
*
* Note: Currently this checks for metered connection OR background
data usage restricted. If a configuration item is added that
provides the option to download on metered connections then
this should be updated to include that logic
*)
function IsBackgroundUpdateAllowed: Boolean;

implementation

uses
System.SysUtils,
Winapi.CommonTypes,
Winapi.WinRT,
Winapi.Networking.Connectivity;

function IsMetered: Boolean;
var
Profile: IConnectionProfile;
CostLevel: IConnectionCost;
begin
Result := False;
// Get the profile currently providing internet access
Profile := TNetworkInformation.GetInternetConnectionProfile;

if Profile <> nil then
begin
CostLevel := Profile.GetConnectionCost;
Result := (CostLevel.NetworkCostType <> NetworkCostType.Unrestricted)
or CostLevel.Roaming
or CostLevel.OverDataLimit;
end;
end;

function IsBackgroundDataRestricted: Boolean;
var
Profile: IConnectionProfile;
CostLevel: IConnectionCost;
DataRestriction: IConnectionCost2;
begin
Result := False;
Profile := TNetworkInformation.GetInternetConnectionProfile;
if Profile <> nil then
begin
CostLevel := Profile.GetConnectionCost;
if (CostLevel <> nil) and Supports(CostLevel, IConnectionCost2, DataRestriction) then
begin
Result := DataRestriction.BackgroundDataUsageRestricted;
Exit;
end;
end;
end;

// Currently this checks for metered connection OR background
// data usage restricted. If a configuration item is added that
// provides the option to download on metered connections then
// this should be updated to include that logic
function IsBackgroundUpdateAllowed: Boolean;
begin
Result := IsMetered OR IsBackgroundDataRestricted;
end;
Comment thread
ermshiperete marked this conversation as resolved.

end.
7 changes: 6 additions & 1 deletion windows/src/desktop/kmshell/xml/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -608,11 +608,16 @@
<!-- Introduced: 18.0.168 -->
<string name="S_Update_Restart_Req" comment="Update tab pop up - warns user restart will require restart ">Installing the update now will require a restart of your computer before you can use Keyman again. Update now anyway?</string>

<!-- Context: Configuration Dialog - Update on boot pop up -->
<!-- Context: Configuration Dialog - Update on pop up -->
<!-- String Type: PlainText -->
<!-- Introduced: 18.0.168 -->
<string name="S_Ready_To_Install" comment="Update on boot pop up - inform user update about to install">An update to Keyman has been downloaded and is ready to install.</string>

<!-- Context: Configuration Dialog - Update on pop up -->
<!-- String Type: PlainText -->
<!-- Introduced: 19.0.146 -->
<string name="S_Metered_Warning" comment="Update warning - inform user about being on a metered connection">You\'re on a metered connection. Downloading now may incur data charges.</string>

<!-- Context: Download Keyboard Dialog -->
<!-- String Type: PlainText -->
<!-- Introduced: 7.0.230.0 -->
Expand Down