【问题标题】:Firefox Extension/Addon - Detect workspace lockedFirefox 扩展/插件 - 检测工作区锁定
【发布时间】:2014-12-09 11:19:46
【问题描述】:

我正在我的 Firefox 插件中寻找解决方案,以检测用户工作区何时被锁定/释放。在谷歌浏览器中,有一个简单的 API chrome.idle.onStateChanged.addListener,在 Firefox 中是否有类似的东西,或者是否有可能做到这一点,独立于平台? 顺便说一句,我用的是插件sdk。

我已经尝试过idle服务:

Cc["@mozilla.org/widget/idleservice;1"].getService(Ci.nsIIdleService) 

但我只是让我在进入睡眠状态时访问一些空闲超时或系统,而不仅仅是锁定工作区。

编辑:“工作区锁定”是指用户使用 ctrl + alt + delete 锁定工作区。我不知道这在 OSX 或 linux 上究竟是如何工作的。

Edit2:我目前在 Windows 8.1 中工作,但我猜 chrome.idle 处理程序可以跨平台工作。

Edit3:我目前从当前答案中得到的是 1. 不存在跨平台解决方案,无论是在 chrome 还是在 Firefox 中。 chrome.idle.onStateChanged 似乎在 windows、linux 和 osx 上的工作方式不同。只有 Windows 可以按预期处理这种“锁定”行为。我无法测试 OSX,在 ubuntu 14 上它对我不起作用。
2. 对于 firefox,有一些深入的代码可以尝试使其工作 - 请参阅本主题中 Noitidart 的回答。

Edit4:Noitidart 找到了适用于 Windows 的解决方案 - github link。

【问题讨论】:

  • 工作空间被锁定是什么意思?如果用户使用 ctrl+alt+del 锁定屏幕,就像 windows 一样?
  • 如果没有人找到解决方案,请不要犹豫,在bugzilla.mozilla.org 上提交错误,在组件toolkit 中,并将我 (:Yoric) 添加到抄送列表中。我不做任何承诺,但核心开发人员或不定期的贡献者可能有兴趣从事此工作。
  • 谢谢@Yoric 我想我会查找谷歌浏览器的源代码,比如 MXR 或 DXR 并给这个人一个 js-ctypes 解决方案,直到我们得到一个 XPCOM 解决方案。此外,如果我在 google chrome 中找到该代码,那么我可以将其发布在 bugzilla 主题中,这听起来像是一个不错的第一个错误。
  • @BrianFooLong 你知道chrome.idle 的操作系统是什么吗?你能帮我测试一下吗?看起来在mac中它只在屏幕保护程序打开时触发锁定。在 Windows 中,当屏幕锁定或屏幕保护程序运行时,它看起来工作正常。在linux中,看起来他们根本不支持它。你能验证一下吗?
  • 其实mac好像也支持screnlock。所以windows和mac都支持锁屏和屏保。 linux呢?从源代码看来,两者都不支持,但我不确定,请您验证一下。说明有关操作系统的任何内容的文档。

标签: firefox firefox-addon firefox-addon-sdk


【解决方案1】:

我不知道如何检测屏幕锁定,但有这些观察者通知:

https://developer.mozilla.org/en-US/docs/Observer_Notifications#Idle_Service

还有计算机睡眠唤醒通知。生病四处询问锁定屏幕,这是一个有趣的。

关于这个主题的一些有用的聊天,看看谷歌浏览器是如何做到的:

[12:33] 好的,伙计们对实际工作提出疑问。有谁知道如何检测屏幕是否被锁定?显然谷歌浏览器有一个方法:https://developer.chrome.com/extensions/idle#event-onStateChanged

[12:45] 有人知道谷歌浏览器代码库的 MXR 或 DXR 吗?

[12:46] mxr.mozilla.org/chromium

[12:52] Ms2ger:你能帮我看看他们是如何测试屏幕锁定的吗?我在看这里:http://mxr.mozilla.org/chromium/source/src/chrome/browser/extensions/api/idle/idle_api_unittest.cc#84

[12:56] 哦,糟糕,他们好像在投票:http://mxr.mozilla.org/chromium/source/src/chrome/browser/extensions/api/idle/idle_manager.h#118

也许他们没有投票。

看看这个:

http://mxr.mozilla.org/chromium/source/src/chrome/browser/extensions/api/idle/idle_manager.cc#246

244 void IdleManager::UpdateIdleStateCallback(int idle_time) {
245   DCHECK(thread_checker_.CalledOnValidThread());
246   bool locked = idle_time_provider_->CheckIdleStateIsLocked();
247   int listener_count = 0;

导致:http://mxr.mozilla.org/chromium/source/src/chrome/browser/idle_win.cc#52

52 bool CheckIdleStateIsLocked() {
53   return ui::IsWorkstationLocked() || IsScreensaverRunning();
54 }

因此我们可以测试屏幕保护程序是否正在运行或工作站是否锁定

导致:

  • http://mxr.mozilla.org/chromium/search?string=IsWorkstationLocked

    • 我们只看到一个实现(这很好奇,因为没有 linux 支持,但它在 chrome 文档页面上没有这样说,所以也许我找不到它)

      • 窗户

        • http://mxr.mozilla.org/chromium/source/src/ui/base/win/lock_state.cc#11

          11 bool IsWorkstationLocked() {
          12   bool is_locked = true;
          13   HDESK input_desk = ::OpenInputDesktop(0, 0, GENERIC_READ);
          14   if (input_desk) {
          15     wchar_t name[256] = {0};
          16     DWORD needed = 0;
          17     if (::GetUserObjectInformation(
          18             input_desk, UOI_NAME, name, sizeof(name), &needed)) {
          19       is_locked = lstrcmpi(name, L"default") != 0;
          20     }
          21     ::CloseDesktop(input_desk);
          22   }
          23   return is_locked;
          24 }
          
      • Mac
        • 请参阅下面的屏幕保护程序部分,屏幕锁定也是通过那里处理的
  • http://mxr.mozilla.org/chromium/search?string=IsScreensaverRunning&find=&findi=&filter=^%5B^\0%5D*%24&hitlimit=&tree=chromium

    • 我们在这个搜索结果中看到了 2 个实现,mac 和 windows >

      • windows 实现:http://mxr.mozilla.org/chromium/source/src/chrome/browser/idle_win.cc#39

        39 bool IsScreensaverRunning() {
        40   DWORD result = 0;
        41   if (::SystemParametersInfo(SPI_GETSCREENSAVERRUNNING, 0, &result, 0))
        42     return result != FALSE;
        43   return false;
        44 }
        45 
        
      • mac 实现:http://mxr.mozilla.org/chromium/source/src/chrome/browser/idle_mac.mm#28

        28 - (id)init {
        29   if ((self = [super init])) {
        30     NSDistributedNotificationCenter* distCenter =
        31           [NSDistributedNotificationCenter defaultCenter];
        32     [distCenter addObserver:self
        33                    selector:@selector(onScreenSaverStarted:)
        34                        name:@"com.apple.screensaver.didstart"
        35                      object:nil];
        36     [distCenter addObserver:self
        37                    selector:@selector(onScreenSaverStopped:)
        38                        name:@"com.apple.screensaver.didstop"
        39                      object:nil];
        40     [distCenter addObserver:self
        41                    selector:@selector(onScreenLocked:)
        42                        name:@"com.apple.screenIsLocked"
        43                      object:nil];
        44     [distCenter addObserver:self
        45                    selector:@selector(onScreenUnlocked:)
        46                        name:@"com.apple.screenIsUnlocked"
        47                      object:nil];
        48   }
        49   return self;
        50 }
        

总结一下:

[13:32] 对于 Windows,它的小菜一碟 winapi 已调用测试屏幕是否已锁定或屏幕保护程序正在运行

[13:32] 对于 Mac,他们没有屏幕锁定测试。他们只是有屏幕保护程序测试,但它是一个观察者方法

[13:32] 对于 linux,他们没有屏幕锁定或屏幕保护程序测试。真奇怪。我问他是否知道他们支持 chrome.idle 的哪个操作系统

编辑:实际上我找到了 linux 实现。从搜索结果返回:CheckIdleStateLocked:http://mxr.mozilla.org/chromium/search?string=CheckIdleStateIsLocked

  • http://mxr.mozilla.org/chromium/source/src/chrome/browser/idle_linux.cc#24

    24 bool CheckIdleStateIsLocked() {
    25   // Usually the screensaver is used to lock the screen, so we do not need to
    26   // check if the workstation is locked.
    27 #if defined(OS_CHROMEOS)
    28   return false;
    29 #elif defined(USE_OZONE)
    30   return false;
    31 #else
    32   return ScreensaverWindowFinder::ScreensaverWindowExists();
    33 #endif
    34 }
    
  • 导致询问ScreensaverWindowExists 我们如何找到这个:http://mxr.mozilla.org/chromium/source/src/chrome/browser/screensaver_window_finder_x11.cc

    15 bool ScreensaverWindowFinder::ScreensaverWindowExists() {
    16   gfx::X11ErrorTracker err_tracker;
    17   ScreensaverWindowFinder finder;
    18   ui::EnumerateTopLevelWindows(&finder);
    19   return finder.exists_ && !err_tracker.FoundNewError();
    20 }
    
  • 导致EnumerateTopLevelWindowshttp://mxr.mozilla.org/chromium/source/src/ui/base/x/x11_util.cc#1059是什么:

    1059 void EnumerateTopLevelWindows(ui::EnumerateWindowsDelegate* delegate) {
    1060   std::vector<XID> stack;
    1061   if (!ui::GetXWindowStack(ui::GetX11RootWindow(), &stack)) {
    1062     // Window Manager doesn't support _NET_CLIENT_LIST_STACKING, so fall back
    1063     // to old school enumeration of all X windows.  Some WMs parent 'top-level'
    1064     // windows in unnamed actual top-level windows (ion WM), so extend the
    1065     // search depth to all children of top-level windows.
    1066     const int kMaxSearchDepth = 1;
            1067     ui::EnumerateAllWindows(delegate, kMaxSearchDepth);
    1068     return;
    1069   }
    1070   XMenuList::GetInstance()->InsertMenuWindowXIDs(&stack);
    1071 
    1072   std::vector<XID>::iterator iter;
    1073   for (iter = stack.begin(); iter != stack.end(); iter++) {
    1074     if (delegate->ShouldStopIterating(*iter))
    1075       return;
    1076   }
    1077 }
    1078 
    
  • 我们说他们打电话给delegate-&gt;ShouldStopIterating,这与ScreensaverWindowExists在同一文件中看到:http://mxr.mozilla.org/chromium/source/src/chrome/browser/screensaver_window_finder_x11.cc

    22 bool ScreensaverWindowFinder::ShouldStopIterating(XID window) {
    23   if (!ui::IsWindowVisible(window) || !IsScreensaverWindow(window))
    24     return false;
    25   exists_ = true;
    26   return true;
    27 }
    
  • 引导询问IsWindowVisible和IsScreensaverWindow是什么

*IsScreensaverWindow,在ScreensaverWindowExists的同一文件中:http://mxr.mozilla.org/chromium/source/src/chrome/browser/screensaver_window_finder_x11.cc

    29 bool ScreensaverWindowFinder::IsScreensaverWindow(XID window) const {
    30   // It should occupy the full screen.
    31   if (!ui::IsX11WindowFullScreen(window))
    32     return false;
    33 
    34   // For xscreensaver, the window should have _SCREENSAVER_VERSION property.
    35   if (ui::PropertyExists(window, "_SCREENSAVER_VERSION"))
    36     return true;
    37 
    38   // For all others, like gnome-screensaver, the window's WM_CLASS property
    39   // should contain "screensaver".
    40   std::string value;
    41   if (!ui::GetStringProperty(window, "WM_CLASS", &value))
    42     return false;
    43 
    44   return value.find("screensaver") != std::string::npos;
    45 }
  • IsWindowVisible:http://mxr.mozilla.org/chromium/source/src/ui/base/x/x11_util.cc#546

    546 bool IsWindowVisible(XID window) {
    547   TRACE_EVENT0("ui", "IsWindowVisible");
    548 
    549   XWindowAttributes win_attributes;
    550   if (!XGetWindowAttributes(gfx::GetXDisplay(), window, &win_attributes))
    551     return false;
    552   if (win_attributes.map_state != IsViewable)
    553     return false;
    554 
    555   // Minimized windows are not visible.
    556   std::vector<XAtom> wm_states;
    557   if (GetAtomArrayProperty(window, "_NET_WM_STATE", &wm_states)) {
    558     XAtom hidden_atom = GetAtom("_NET_WM_STATE_HIDDEN");
    559     if (std::find(wm_states.begin(), wm_states.end(), hidden_atom) !=
    560             wm_states.end()) {
    561       return false;
    562     }
    563   }
    

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2011-05-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-29
相关资源
最近更新 更多