Skip to content

Ensure IAccessible2 remains available in Firefox after restarting NVDA on Windows 10 Creaters update, register ISimpleDOM proxy to allow math in Google Chrome without Firefox installed, and Allow the user to get back a virtualBuffer when restarting NVDA with a Firefox document in focus#7535

Merged
michaelDCurran merged 11 commits into
masterfrom
i7308
Sep 19, 2017

Conversation

@michaelDCurran

@michaelDCurran michaelDCurran commented Aug 29, 2017

Copy link
Copy Markdown
Member

Link to issue number:

Fixes #7269
Fixes #7308
Partial fix for #5758
Fixes #7563

Summary of the issue:

Originally some users were complaining that when they restarted NVDA while Firefox was in focus, browse mode was no longer available. Alt+tabbing away and back again would also not correct the situation.
Specifically issue #5758 covers this original case. Technically, when NVDA restarts and Firefox is already in focus, There is no focus event for Firefox and therefore NVDA's in-proces injection code is not triggered for the Firefox process. Therefore we have no binding handle for creating a virtualBuffer. However, as VirtualBuffer.prepare has already set shouldPrepare to false by the time it reaches this error, it is impossible for the virtualBuffer to ever work again, even if a binding handle does become available by shifting focus away and back again.

There was a second issue (#7269) that started appearing in Windows insider builds approaching the Windows 10 Creaters Update. In this situation, restarting NVDA and then trying to use Firefox would result in NVDA not being able to ever QueryService to IAccessibleApplication to check the Gecko version number, and therefore NVDA would never provide browse mode. Restarting NVDA would not help. All that could be done was to close and re-open Firefox. There seemed to be some kind of COM proxy stub issue where if a request was made to marshal an interface that had just been deregistered with CoRevokeClassObject, then once that interface was again successfully registered, marshalling would be for ever still broken in the server process.

Finally, issue #7308 talks about not being able to read / navigate math content in Google chrome. The main reason for this is that Google Chrome does not register ISimpleDOM interfaces which are used between chrome and NVDA to fetch the math content. What confuses the situation is that if the user did have Firefox installed, math content would work in Google chrome as the interfaces were available via Firefox's registration.

Description of how this pull request fixes the issue:

#5758 is partially fixed by simply returning early in VirtaulBuffer.prepare if there is no binding handle yet. This means that on future focus changes, the VirtaulBuffer will again try to prepare. Once there is a binding handle, this will succeeed. In short, restarting NVDA while Firefox is in focus will still result in no browse mode at first, but the user can easily shift focus away and back again to get Browse mode.

#7269 and #7308 together are fixed by a substantial re-write to NVDAHelperRemote's COM proxy registration code.
Firstly, the code has been abstracted so that it is easy to register other COM proxies other than just IAccessible2. Now both IAccessible2 and ISimpleDOM are both built, and registered in all processes we inject into if COM is initialized. The abstraction also allows us to fetch all the interfaces from the dll directly, rather than having to hardcode them.
The COM proxy dlls now contain assembly manifests which aide in us getting COM to load the class objects itself, while manging the life time of the dll, saving us from having to free it on NVDA shutdown, which in 99% of cases never worked.
And, most importantly the specific problem introduced by Windows 10 creaters update where CoRevokeClassObject would break future registration was fixed by pointing the interfaces to the standard marshaller with CoRegisterPSClsid before their class object was revoked. The standard marshaller does not support the interfaces of course, but at least they still point to a valid class object. Microsoft really needs a CoUnregisterPSClsid.

Early iterations of this PR also showed up issue #7563, which this PR now also addresses by moving all NVDA dlls into a version-specific directory to stop accidental loading or reuse of a dll from a previous version which could cause a crash.

Testing performed:

Multiple restarts of NVDA both using control+alt+n, and the NVDA+q quit dialog (choosing restart), on both Windows 10 Creaters update and Windows 7 64 bit, while Mozilla Firefox is in focus.

Known issues with pull request:

Issue #5758 is not fully fixed as the user must still alt+tab away and back again to get Browse mode in Firefox when restarting NVDA with Firefox in focus.

Change log entry:

Bug fixes:

…A on Windows 10 Creaters update. Also abstract code making it easy to register other COM proxy dlls.
…t's appModule's helperLocalBindingHandle is missing.

There may not be any binding handle yet if NVDA was started and the document in question already had focus. All though the virtualBuffer will still not yet work, at least the user can now move focus away and back again and prepare will be tried again once the binding handle is there.
@LeonarddeR

Copy link
Copy Markdown
Collaborator

I assume this doesn't contribute anything to a fix of #7311?

@michaelDCurran

michaelDCurran commented Aug 29, 2017 via email

Copy link
Copy Markdown
Member Author

Comment thread nvdaHelper/archBuild_sconscript Outdated
def clsidStringToCLSIDDefine(clsidString):
"""
Converts a CLSID string of the form "{abcdef12-abcd-abcd-abcd-abcdef123456}"
Into a c-style struct initializer for initializing a GUID (I.e. "{0xabcdef12,0xabcd,0xabcd,{0xab,0xab,0xab,0xab,0xab,0xab,0xab,0xab}}")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

If I understand this code right, I think the last part of this example result should be: {0xab, 0xcd, 0xab, 0xcd, 0xef, 0x12, 0x34, 0x56}

Comment thread nvdaHelper/ia2_sconscript Outdated

idlFile=env.Command("ia2.idl","#/miscDeps/include/ia2/ia2.idl",Copy("$TARGET","$SOURCE"))


Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

extra new line

Comment thread nvdaHelper/ia2_sconscript
LIBS=['rpcrt4','oleaut32','ole32'],
CPPDEFINES=[env['CPPDEFINES'],'WIN32','REGISTER_PROXY_DLL'],
LINKFLAGS=[env['LINKFLAGS'],'/export:DllGetClassObject,private','/export:DllCanUnloadNow,private'],
proxyClsid="{62d295fe-2062-4369-a010-4f59b5e32d5e}"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Where does this clsid come from?

/*
This file is a part of the NVDA project.
URL: http://www.nvda-project.org/
Copyright 2006-2010 NVDA contributers.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The years listed are wrong. This also doesn't match the format we have on the wiki: https://github.com/nvaccess/nvda/wiki/Copyright-headers


typedef void(RPC_ENTRY *LPFNGETPROXYDLLINFO)(ProxyFileInfo***, CLSID**);

const wchar_t* StringCLSID_StandardMarshaler=L"{00020424-0000-0000-C000-000000000046}";

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

perhaps you could add a comment to this line? Is there a reference for this value?

}
// look up the GetProxyDllInfo function on the proxy dll
LPFNGETPROXYDLLINFO Dll_GetProxyDllInfo=(LPFNGETPROXYDLLINFO)GetProcAddress(dllHandle,"GetProxyDllInfo");
if(Dll_GetProxyDllInfo==NULL) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nullptr
And there are a few more, I wont comment on all of them.

ACTCTX actCtx={0};
actCtx.cbSize=sizeof(actCtx);
actCtx.dwFlags=ACTCTX_FLAG_HMODULE_VALID|ACTCTX_FLAG_RESOURCE_NAME_VALID;
actCtx.lpResourceName=MAKEINTRESOURCE(2);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

what is 2?

reg->psClsidBackups.push_back({name,iid,clsidBackup});
LOG_DEBUG(L"Registered interface "<<name);
}
++tempInfoPtr;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Is there some docs you can point to on ProxyFileInfo? I'm a little nervous about this code. So pProxyInfo points to the start of a memory block containing ProxyFileInfo*. This memory block is null terminated. I cant find any documentation on Dll_GetProxyDllInfo How do you know the above is the case?

LOG_DEBUG(L"Unregistered interface "<<(backup.name));
}
if((res=CoRevokeClassObject((DWORD)(reg->classObjectRegistrationCookie)))!=S_OK) {
LOG_ERROR(L"Error unregistering class object from "<<(reg->dllPath)<<L", code "<<res);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

For this (and the other error case on line 156) should the function exit early, why is it ok to continue to delete reg and return true

/*
This file is a part of the NVDA project.
URL: http://www.nvda-project.org/
Copyright 2006-2010 NVDA contributers.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@LeonarddeR

Copy link
Copy Markdown
Collaborator

This seems to cause incidental errors, which I've seen in at least Thunderbird and Spotify when focussing the application

ERROR - RPC process 12692 (thunderbird.exe) (08:50:15.348):
Thread 12696, build\x86\remote\COMProxyRegistration.cpp, registerCOMProxy, 69:
GetProxyDllInfo function not found in IAccessible2Proxy.dll

ERROR - RPC process 12692 (thunderbird.exe) (08:50:15.361):
Thread 12696, build\x86\remote\ia2Support.cpp, installIA2Support, 59:
Error registering IAccessible2 proxy

@michaelDCurran

michaelDCurran commented Aug 30, 2017 via email

Copy link
Copy Markdown
Member Author

@LeonarddeR

LeonarddeR commented Aug 30, 2017 via email

Copy link
Copy Markdown
Collaborator

…XP."

We are now planning to drop support for XP/Vista in PR #7546.

This reverts commit 2aed84c.
…t Windows will always load the correct dll when hooking, rather than possibly falling back to a dll in a previous version that may currently still be loaded in a process.
@michaelDCurran

Copy link
Copy Markdown
Member Author

This PR also fixes #7563, which was uncovered by other parts of this PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

4 participants