Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(powerMonitor): expose interface to query system idle state #11807

Merged
merged 5 commits into from Mar 14, 2018
Merged

feat(powerMonitor): expose interface to query system idle state #11807

merged 5 commits into from Mar 14, 2018

Conversation

kwonoj
Copy link
Contributor

@kwonoj kwonoj commented Feb 1, 2018

This PR intend to expose 2 static method to powerMonitor - querySystemIdleState and querySystemIdleTime. As interface name stands for, both allows to query system's idle status.

There are handful of users need this features (including old backlog issue like #1528), and most cases user relies on native modules (https://www.npmjs.com/package/@paulcbetts/system-idle-time / https://www.npmjs.com/package/desktop-idle, etcs). This PR exposes interface to chromium's implementation removes need of custom native module.

QuerySystemIdleState(idleThreshold: number, 
                          (state: 'active' | 'idle' | 'locked' | 'unknown') => void): void

accepts non-negative number as a threshold in seconds to be considered as system idle, notify callback with current state. Callback can be resolved synchronously or either asynchronously, depends on platform support. Among state, locked state is only available if platform support to return it.

QuerySystemIdleTime((idleTime:number) => void): void

notifys callback with system idle time in seconds.

@kwonoj kwonoj requested review from a team February 1, 2018 18:52
@kwonoj
Copy link
Contributor Author

kwonoj commented Feb 1, 2018

I am cc'ing @felixrieseberg here as well for the interested party.

@felixrieseberg
Copy link
Member

Neat! I love re-using Chromium's well-crafted code. I'm not sure about BrowserWindow though - how do you feel about adding the API to shell instead?

@kwonoj
Copy link
Contributor Author

kwonoj commented Feb 1, 2018

I'm not sure about BrowserWindow though - how do you feel about adding the API to shell instead?

Good point, this is probably me not very well knowledgeable structure of electron. Let me try.

@kwonoj kwonoj changed the title feat(BrowserWindow): expose interface to query system idle state feat(shell): expose interface to query system idle state Feb 1, 2018
@kwonoj
Copy link
Contributor Author

kwonoj commented Feb 1, 2018

@felixrieseberg PR updated per suggestion, now interface is expoed via shell module.

Copy link
Member

@deepak1556 deepak1556 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure about adding it to the shell module when we have a powerMonitor module.

dict.SetMethod("querySystemIdleTime", &QuerySystemIdleTime);

#if defined(OS_MACOSX)
ui::InitIdleMonitor();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be moved to AtomBrowserMainParts::PreCreateThreads

@kwonoj
Copy link
Contributor Author

kwonoj commented Feb 1, 2018

I'm fine to pick anywhere to expose this. @deepak1556 Is suggestion moving this interface to powerMonitor or somewhere else? if it's else, where would be? and @felixrieseberg , what do you think?

@deepak1556
Copy link
Member

There isn't a strong argument for choosing between powerMonitor or shell. I will incline to what @felixrieseberg and other maintainers decides on this.

@felixrieseberg
Copy link
Member

Nah, you're right, powerMonitor is probably better.

@kwonoj kwonoj changed the title feat(shell): expose interface to query system idle state feat(powerMonitor): expose interface to query system idle state Feb 2, 2018
@kwonoj
Copy link
Contributor Author

kwonoj commented Feb 2, 2018

@deepak1556 @felixrieseberg now interface moved into powerMonitor'. it's class method, but I thought it's fine as powerMonitor binded into instance of class. Let me know if things need to be updated.

ui::CalculateIdleState(idle_threshold, callback);
} else {
isolate->ThrowException(v8::Exception::TypeError(
mate::StringToV8(isolate, "Invalid idle threshold")));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's be super nice here, "Invalid idle threshold, must be greater than or equal to 0"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sounds good, message need to be bit amended to greater than 0, having 0 as threshold will not return valid value anyway (while CalculateIdleState can accepts it)


The `powerMonitor` module has the following methods:

#### `shell.querySystemIdleState(idle_threshold, callback)`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

powerMonitor.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/idle_threshold/idleThreshold

before considered idle. State will be notified via callback represents current system
idle state. `locked` is available on supported system only.

#### `shell.querySystemIdleTime(callback)`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

powerMonitor.


#### `shell.querySystemIdleState(idle_threshold, callback)`

* `idleThreshold` Interger
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Integer


* `idleThreshold` Interger
* `callback` Function
* `active` | `idle` | `locked` | `unknown` String
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line should be

  * `idleState` String - Can be `active, `idle`, `locked` or `unknown`

* `callback` Function
* `active` | `idle` | `locked` | `unknown` String

Calculate system idle state. `idle_threshold` is the amount of time (in seconds)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/idle_threshold/idleThreshold


Calculate system idle state. `idle_threshold` is the amount of time (in seconds)
before considered idle. State will be notified via callback represents current system
idle state. `locked` is available on supported system only.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we document which systems currently support locked?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

chromium doesn't document it as well (https://cs.chromium.org/chromium/src/ui/base/idle/idle.h?q=idle&sq=package:chromium&l=17) - I'd rather in sync with chromium as it can change anytime due to platform side patch / version up, etcs.

#### `shell.querySystemIdleTime(callback)`

* `callback` Function

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be another line here

  * `idleTime` Integer - Idle time in seconds

@kwonoj
Copy link
Contributor Author

kwonoj commented Feb 2, 2018

PR updated & fixed mistakes per comment / suggestion.

Copy link
Member

@deepak1556 deepak1556 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Current specs of PowerMonitor run only on linux, we need to enable the tests for these new apis on all three platforms.

@kwonoj
Copy link
Contributor Author

kwonoj commented Feb 2, 2018

Noticed that - what's best way? Is it allowed to instantiate powermonitor without dbus mock? (New interface won't nees those mock anyway)

@deepak1556
Copy link
Member

Not having to lazily initialize the powerMonitor module should allow enabling these test cases along side the existing dbus specs for linux.

@deepak1556
Copy link
Member

Can remove the call to base::PowerMonitorDeviceSource::AllocateSystemIOPorts, its already initialized for the main process by the content layer https://cs.chromium.org/chromium/src/content/app/content_main_runner.cc?type=cs&q=AllocateSystemIOPorts&l=582

@@ -41,7 +43,7 @@ const skip = process.platform !== 'linux' || !process.env.DBUS_SYSTEM_BUS_ADDRES
before((done) => {
logindMock.on('MethodCalled', onceMethodCalled(done))
// lazy load powerMonitor after we listen to MethodCalled mock signal
powerMonitor = require('electron').remote.powerMonitor
dbusMockPowerMonitor = require('electron').remote.powerMonitor
Copy link
Member

@deepak1556 deepak1556 Feb 2, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tarruda Is it required to lazy initialize the module ? I was hoping we can just initialize the module only once for all the specs here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It has to be lazy loaded if we want to verify that electron inhibits the system suspend (it does this by calling a method via dbus).

@@ -68,10 +110,6 @@ using atom::api::PowerMonitor;

void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
v8::Local<v8::Context> context, void* priv) {
#if defined(OS_MACOSX)
base::PowerMonitorDeviceSource::AllocateSystemIOPorts();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

per comment suggestion in #11807 (comment) .

Copy link
Member

@ckerr ckerr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mostly LGTM, nice idea && thanks for the PR. 👍

A couple of questions and suggestions inline

int idle_threshold,
const ui::IdleCallback& callback);
void QuerySystemIdleTime(const ui::IdleTimeCallback& callback);

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's make these methods private since we're only using them with the bindings. Permissions can be loosened later as needed

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

makes sense, moved it.

} else {
isolate->ThrowException(v8::Exception::TypeError(
mate::StringToV8(isolate,
"Invalid idle threshold, must be greater than 0")));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know another reviewer suggested this, but are we sure that we want this?

Since we're not publishing the ui::CheckIdleStateIsLocked(), if all you want to do is check for system lock it's reasonable to pass a -1 in for idle_threshold.

If we include that method, we can avoid this wart by having a recommended way to test for lock

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm I didn't thought in that way, but also checking lock state is somewhat limited per platform support, so passing -1 doesn't guarantee you can reliable acquire intended state. I think it's rather limit api surface, and expose CheckIdleStateIsLocked separately if there's demand for it.

* `idleState` String - Can be `active`, `idle`, `locked` or `unknown`

Calculate system idle state. `idleThreshold` is the amount of time (in seconds)
before considered idle. State will be notified via callback represents current system
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's something missing between "notified via callback" and "represents current system", I think

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's wrapped line, full sentence is State will be notified via callback represents current system idle state..

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That still doesn't make any sense though. Would this be ok?

+ Calculate the system idle state. `idleThreshold` is the amount of time (in seconds)
+ before considered idle. `callback` will be called synchronously on some systems
+ and with an `idleState` argument that describes the system's state.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think so, it's probably same bucket for my English writing skill. I'll update as suggested.


Calculate system idle state. `idleThreshold` is the amount of time (in seconds)
before considered idle. State will be notified via callback represents current system
idle state. `locked` is available on supported system only.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/system/systems/

mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
.MakeDestroyable()
.SetMethod("querySystemIdleState", &PowerMonitor::QuerySystemIdleState)
.SetMethod("querySystemIdleTime", &PowerMonitor::QuerySystemIdleTime);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we name these with "query" instead of using libcc's "calculate" nomenclature?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably cause of my bad non-native-english-naming skill . 😅 open to suggestion if recommended to rename it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😄 no worries!

My suggestion would be to copy the libchromium API names, e.g. PowerMonitor::CalculateIdleState and powerMonitor.calculateIdleState.

I don't feel very strongly about this; if other reviewers prefer querySystem I will go along

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, I'll wait for few other chime in and update PR if we'd like to go for chromium api names.

@kwonoj
Copy link
Contributor Author

kwonoj commented Feb 9, 2018

I have rebased PR to master and seeing test failures on linux, peeking it some other PR sees as well (i.e https://circleci.com/gh/electron/electron/9330) not sure way to resolve it.

@codebytere
Copy link
Member

@kwonoj it appears these are building in CI under your own name and not the electron org's, so we don't have the ability to restart them; often they flake so try restarting the failures yourself and see what happens

@kwonoj
Copy link
Contributor Author

kwonoj commented Feb 9, 2018

Bit unsure why fork CI setup reports status to PR itself. I've retriggered couple of times already, but did one more time.

@kwonoj
Copy link
Contributor Author

kwonoj commented Feb 9, 2018

@codebytere stopping my circleci config makes status notification correctly goes for electron's, but doesn't seem like build failure resolves by retriggering it.

@felixrieseberg
Copy link
Member

felixrieseberg commented Feb 12, 2018

@ckerr What do you think? Anything else OJ could do here to make it mergable?

Copy link
Member

@MarshallOfSound MarshallOfSound left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Loving this 👍

Just need to rebase changes onto current master so that arm64 builds don't blow up 👍

@MarshallOfSound
Copy link
Member

MarshallOfSound commented Mar 14, 2018

To be clear for whoever merges this in the future as well, this does not get backported, new versioning scheme means that this will go out in 2.1.x or 3.0.x, we don't backport features 👍

@MarshallOfSound MarshallOfSound added the semver/minor backwards-compatible functionality label Mar 14, 2018
Copy link
Member

@ckerr ckerr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apologies for not getting back to this sooner. Yes 👍 for landing this in master.

It would also make sense in the 2.x series when we open it back up to new nonbreaking features.

@ckerr ckerr merged commit e7181eb into electron:master Mar 14, 2018
@kwonoj kwonoj deleted the feat-idle-time branch March 14, 2018 05:56
sethlu pushed a commit to sethlu/electron that referenced this pull request May 3, 2018
…tron#11807)

* feat(BrowserWindow): expose interface to query system idle state

* test(BrowserWindow): update test cases for querySystemIdle interface

* docs(BrowserWindow): add querySystemIdle interface documentation

* refactor(powerMonitor): move querySystemIdle into powerMonitor

* test(powerMonitor): split test cases for all platform
sbannigan pushed a commit to sbannigan/electron that referenced this pull request May 10, 2018
…tron#11807)

* feat(BrowserWindow): expose interface to query system idle state

* test(BrowserWindow): update test cases for querySystemIdle interface

* docs(BrowserWindow): add querySystemIdle interface documentation

* refactor(powerMonitor): move querySystemIdle into powerMonitor

* test(powerMonitor): split test cases for all platform
@sachetsharma1
Copy link

Is there any planned release for this feature?

@dchest
Copy link

dchest commented Oct 2, 2018

Looks like this feature is missing in TypeScript typings.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
semver/minor backwards-compatible functionality
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

9 participants