flypig.co.uk

List items

Items from the current list are shown below.

Blog

23 Dec 2023 : Day 116 #
Yesterday we were looking at the window creation code and I made some changes to "surface" (as they say) the hidden flag of a window. The idea is to set the flag on the window generated as a result of the page being cloned during printing so that the front-end can filter the window out from the user interface.

Here's the new "Hidden" role from the tab model that I've added and which I'm hoping to use for the filtering, taken from the declarativetabmodel.h file:
    enum TabRoles {
        ThumbPathRole = Qt::UserRole + 1,
        TitleRole,
        UrlRole,
        ActiveRole,
        TabIdRole,
        DesktopModeRole,
        HiddenRole,
    };
Although in theory the pieces are in place to implement the filtering I don't want to do that just yet. I want to do something easier to check whether it's working as expected. I've already made quite a number of changes and experience tells me that periodically checking my work is a sensible thing to do. I'm not always where I think I am.

So rather than the filtering I want to add some kind of indicator to the tab view that shows whether a page is supposed to be hidden or not. I'm thinking maybe a colour change or something like that.

I've found a nice place to put this indicator in the TabItem.qml component of the sailfish-browser user interface code. There's some QML code there to set the background colour depending on the ambience:
    color: Theme.colorScheme === Theme.LightOnDark ? "black" : "white"
I'm going to embellish this a little — I can do it directly on the device — like this:
    color: hidden ? "red" : Theme.colorScheme === Theme.LightOnDark ? "black" : "white"
This is about as simple as a change gets. When I apply the change, run the browser and open the tab view I get the following error:
[W] unknown:60 - file:///usr/share/sailfish-browser/pages/components/TabItem.qml:60:
    ReferenceError: hidden is not defined
That's okay though: I've not yet installed my updated packages where the hidden role is defined, so the error is expected. Now to install the packages to see whether that changes. I have to update three sets of packages (xulrunner, qtmozembed and sailfish-browser) simultaneously to make it work.

All of the packages installed fine. The browser runs. Opening the tab window now no longer generates any errors. But things haven't quite gone to plan because now all of the tabs have turned red. Hrmf. I guess I need to check my logic.
 
Two screenshots of the tab view in the browser; on the left all of the titles of the tabs have dark backgrounds; on the right the backgrounds are all red

After checking with the debugger, all of the tabs have their hidden flag set to false. Odd. Annoyingly though, the debugger also tells me that when the print page is created its hidden state is also set to false. So that's now two errors to fix. Well, I've found the first error in my logic, caused by a hack added on top of a hack:
    color: hidden ? "red" : 
        Theme.colorScheme === Theme.LightOnDark ? "red" : "white"
It's annoyingly obvious now I see it. The second colour should be "black" not "red", like this:
    color: hidden ? "red" : 
        Theme.colorScheme === Theme.LightOnDark ? "black" : "white"
Having fixed this now all the tabs are the correct colour again. Apart from the printing page which should be red but now isn't. For some reason the information isn't being "surfaced" as it should be.

I've picked a point suitably high up the stack — on EmbedLiteViewChild::InitGeckoWindow() — to attach a breakpoint and set the print running. Hopefully this will give us an idea about where the chain is being broken.
(gdb) b EmbedLiteViewChild::InitGeckoWindow
Breakpoint 1 at 0x7fbcb195a4: file mobile/sailfishos/embedshared/
    EmbedLiteViewChild.cpp, line 179.
(gdb) c
Continuing.
[...]

Thread 8 "GeckoWorkerThre" hit Breakpoint 1, mozilla::embedlite::
    EmbedLiteViewChild::InitGeckoWindow (this=0x7e37699810, parentId=1, 
    parentBrowsingContext=0x7f88b7a680, isPrivateWindow=false,
    isDesktopMode=false, isHidden=false)
    at mobile/sailfishos/embedshared/EmbedLiteViewChild.cpp:179
179     {
(gdb) bt
#0  mozilla::embedlite::EmbedLiteViewChild::InitGeckoWindow (this=0x7e37699810,
    parentId=1, parentBrowsingContext=0x7f88b7a680, isPrivateWindow=false, 
    isDesktopMode=false, isHidden=false)
    at mobile/sailfishos/embedshared/EmbedLiteViewChild.cpp:179
#1  0x0000007fbcb0ae48 in mozilla::detail::RunnableMethodArguments<unsigned int
    const, mozilla::dom::BrowsingContext*, bool const, bool const, bool 
    const>::applyImpl<mozilla::embedlite::EmbedLiteViewChild, void 
    (mozilla::embedlite::EmbedLiteViewChild::*)(unsigned int,
    mozilla::dom::BrowsingContext*, bool, bool, bool),
    StoreCopyPassByConstLRef>unsigned int const>,
    StoreRefPtrPassByPtr<mozilla::dom::BrowsingContext>,
    StoreCopyPassByConstLRef<bool const>, StoreCopyPassByConstLRef<bool const>>,
    StoreCopyPassByConstLRef<bool const>, 0ul, 1ul, 2ul, 3ul, 4ul>
    (args=..., m=<optimized out>, o=<optimized out>)
    at ${PROJECT}/obj-build-mer-qt-xr/dist/include/mozilla/RefPtr.h:280
#2  mozilla::detail::RunnableMethodArguments<unsigned int const,
    mozilla::dom::BrowsingContext*, bool const, bool const,
    bool const>::apply<mozilla::embedlite::EmbedLiteViewChild, void
    (mozilla::embedlite::EmbedLiteViewChild::*)(unsigned int,
    mozilla::dom::BrowsingContext*, bool, bool, bool)> (
    m=<optimized out>, o=<optimized out>, this=<optimized out>)
    at xpcom/threads/nsThreadUtils.h:1154
#3  mozilla::detail::RunnableMethodImpl<mozilla::embedlite::EmbedLiteViewChild*,
    void (mozilla::embedlite::EmbedLiteViewChild::*)(unsigned int,
    mozilla::dom::BrowsingContext*, bool, bool, bool), true,
    (mozilla::RunnableKind)0, unsigned int const, mozilla::dom::BrowsingContext*,
    bool const, bool const, bool const>::Run (this=<optimized out>)
    at xpcom/threads/nsThreadUtils.h:1201
#4  0x0000007fb9c8b99c in mozilla::RunnableTask::Run (this=0x7ed8004590)
[...]
Oh, that backtrace quickly degenerates because EmbedLiteViewChild::InitGeckoWindow() is being called as a posted runnable task. I'll need to pick somewhere lower down. It's being run from the EmbedLiteViewChild::EmbedLiteViewChild() constructor, so let's try that instead.

The debugger is running incredibly slowly today for some reason. But eventually it gets there.
(gdb) delete break
Delete all breakpoints? (y or n) y
(gdb) b EmbedLiteViewChild::EmbedLiteViewChild
Breakpoint 2 at 0x7fbcb143f0: file mobile/sailfishos/embedshared/
    EmbedLiteViewChild.cpp, line 71.
(gdb) c
Continuing.

Thread 8 "GeckoWorkerThre" hit Breakpoint 1, mozilla::embedlite::
    EmbedLiteViewChild::EmbedLiteViewChild (this=0x7e30cc9000,
    aWindowId=@0x7f9f3cfc3c: 1, aId=@0x7f9f3cfc40: 2,
    aParentId=@0x7f9f3cfc44: 1, parentBrowsingContext=0x7f88bd2f40,
    isPrivateWindow=@0x7f9f3cfc2e: false,
    isDesktopMode=@0x7f9f3cfc2f: false, isHidden=@0x7f9f3cfc30: false)
    at mobile/sailfishos/embedshared/EmbedLiteViewChild.cpp:71
71      EmbedLiteViewChild::EmbedLiteViewChild(const uint32_t &aWindowId,
(gdb) bt
#0  mozilla::embedlite::EmbedLiteViewChild::EmbedLiteViewChild
    (this=0x7e30cc9000, aWindowId=@0x7f9f3cfc3c: 1, aId=@0x7f9f3cfc40: 2, 
    aParentId=@0x7f9f3cfc44: 1, parentBrowsingContext=0x7f88bd2f40,
    isPrivateWindow=@0x7f9f3cfc2e: false, isDesktopMode=@0x7f9f3cfc2f: false, 
    isHidden=@0x7f9f3cfc30: false)
    at mobile/sailfishos/embedshared/EmbedLiteViewChild.cpp:71
#1  0x0000007fbcb23aa4 in mozilla::embedlite::EmbedLiteViewThreadChild::
    EmbedLiteViewThreadChild (this=0x7e30cc9000, windowId=<optimized out>, 
    id=<optimized out>, parentId=<optimized out>,
    parentBrowsingContext=<optimized out>, isPrivateWindow=<optimized out>,
    isDesktopMode=<optimized out>, isHidden=<optimized out>)
    at mobile/sailfishos/embedthread/EmbedLiteViewThreadChild.cpp:15
#2  0x0000007fbcb2a69c in mozilla::embedlite::EmbedLiteAppThreadChild::
    AllocPEmbedLiteViewChild (this=0x7f889f48e0, windowId=@0x7f9f3cfc3c: 1, 
    id=@0x7f9f3cfc40: 2, parentId=@0x7f9f3cfc44: 1,
    parentBrowsingContext=<optimized out>, isPrivateWindow=@0x7f9f3cfc2e: false, 
    isDesktopMode=@0x7f9f3cfc2f: false, isHidden=@0x7f9f3cfc30: false)
    at ${PROJECT}/obj-build-mer-qt-xr/dist/include/mozilla/cxxalloc.h:33
#3  0x0000007fba17f48c in mozilla::embedlite::PEmbedLiteAppChild::
    OnMessageReceived (this=0x7f889f48e0, msg__=...) at PEmbedLiteAppChild.cpp:529
#4  0x0000007fba06b85c in mozilla::ipc::MessageChannel::DispatchAsyncMessage
    (this=this@entry=0x7f889f49a8, aProxy=aProxy@entry=0x7ebc001cb0, aMsg=...)
    at ${PROJECT}/obj-build-mer-qt-xr/dist/include/mozilla/ipc/ProtocolUtils.h:675
[...]
#49 0x0000007fbd165538 in js::jit::MaybeEnterJit (cx=0x7f88234ba0, state=...)
    at js/src/jit/Jit.cpp:207
#50 0x0000007f8830d951 in ?? ()
Backtrace stopped: Cannot access memory at address 0xfa512247ea
(gdb) 
That gets us a little further, but not massively so. Let's go back a bit further again.
(gdb) delete break
Delete all breakpoints? (y or n) y
(gdb) b PEmbedLiteAppParent::SendPEmbedLiteViewConstructor
Breakpoint 2 at 0x7fba19099c: PEmbedLiteAppParent::SendPEmbedLiteViewConstructor.
    (2 locations)
(gdb) c
Continuing.

Thread 1 "sailfish-browse" hit Breakpoint 2, mozilla::embedlite::
    PEmbedLiteAppParent::SendPEmbedLiteViewConstructor
    (this=this@entry=0x7f88a64fc0, windowId=@0x7fffffe414: 1,
    id=@0x7fbfb29440: 3, parentId=@0x7fffffe40c: 1,
    parentBrowsingContext=@0x7fffffe400: 547754946368, 
    isPrivateWindow=@0x7fffffe40b: false, isDesktopMode=@0x7fffffe40a: false,
    isHidden=@0x7fffffe409: false) at PEmbedLiteAppParent.cpp:168
168     PEmbedLiteAppParent.cpp: No such file or directory.
(gdb) bt
#0  mozilla::embedlite::PEmbedLiteAppParent::SendPEmbedLiteViewConstructor
    (this=this@entry=0x7f88a64fc0, windowId=@0x7fffffe414: 1,
    id=@0x7fbfb29440: 3, parentId=@0x7fffffe40c: 1,
    parentBrowsingContext=@0x7fffffe400: 547754946368,
    isPrivateWindow=@0x7fffffe40b: false, isDesktopMode=@0x7fffffe40a: false,
    isHidden=@0x7fffffe409: false) at PEmbedLiteAppParent.cpp:168
#1  0x0000007fbcb18850 in mozilla::embedlite::EmbedLiteApp::CreateView
    (this=0x5555859800, aWindow=0x5555c67e80, aParent=<optimized out>, 
    aParentBrowsingContext=<optimized out>, aIsPrivateWindow=<optimized out>,
    isDesktopMode=<optimized out>, isHidden=<optimized out>)
    at mobile/sailfishos/EmbedLiteApp.cpp:478
#2  0x0000007fbfb8693c in QMozViewPrivate::createView (this=0x555569b070)
    at qmozview_p.cpp:862
#3  QMozViewPrivate::createView (this=0x555569b070) at qmozview_p.cpp:848
#4  0x00000055555d10ec in WebPageFactory::createWebPage (this=0x55559bc500,
    webContainer=0x55559bc110, initialTab=...)
    at ../factories/webpagefactory.cpp:44
#5  0x00000055555acf68 in WebPages::page (this=0x55559bc650, tab=...)
    at include/c++/8.3.0/bits/atomic_base.h:390
#6  0x000000555559148c in DeclarativeWebContainer::activatePage
    (this=this@entry=0x55559bc110, tab=..., force=force@entry=false)
    at include/c++/8.3.0/bits/atomic_base.h:390
#7  0x000000555559160c in DeclarativeWebContainer::onNewTabRequested
    (this=0x55559bc110, tab=...) at ../core/declarativewebcontainer.cpp:1047
#8  0x0000007fb7ec4204 in QMetaObject::activate(QObject*, int, int, void**) ()
    from /usr/lib64/libQt5Core.so.5
#9  0x00000055555f6d80 in DeclarativeTabModel::newTabRequested
    (this=this@entry=0x55559d6130, _t1=...) at moc_declarativetabmodel.cpp:366
#10 0x00000055555c3d28 in DeclarativeTabModel::newTab (this=0x55559d6130,
    url=..., parentId=1, browsingContext=547754946368, hidden=<optimized out>)
    at ../history/declarativetabmodel.cpp:230
#11 0x00000055555d0e78 in DeclarativeWebPageCreator::createView
    (this=0x55559c50f0, parentId=<optimized out>,
    parentBrowsingContext=<optimized out>, hidden=<optimized out>)
    at /usr/include/qt5/QtCore/qarraydata.h:240
#12 0x0000007fbfb71ef0 in QMozContextPrivate::CreateNewWindowRequested
    (this=<optimized out>, chromeFlags=<optimized out>, hidden=<optimized out>, 
    aParentView=0x5555bf74e0, parentBrowsingContext=@0x7fffffe938: 547754946368)
    at qmozcontext.cpp:218
#13 0x0000007fbcb10eec in mozilla::embedlite::EmbedLiteApp::CreateWindowRequested
    (this=0x5555859800, chromeFlags=@0x7fffffe928: 4094,
    hidden=@0x7fffffe922: true, parentId=@0x7fffffe924: 1,
    parentBrowsingContext=@0x7fffffe938: 547754946368)
    at mobile/sailfishos/EmbedLiteApp.cpp:543
#14 0x0000007fbcb1ea68 in mozilla::embedlite::EmbedLiteAppThreadParent::
    RecvCreateWindow (this=<optimized out>, parentId=<optimized out>, 
    parentBrowsingContext=<optimized out>, chromeFlags=<optimized out>,
    hidden=<optimized out>, createdID=0x7fffffe92c, cancel=0x7fffffe923)
    at mobile/sailfishos/embedthread/EmbedLiteAppThreadParent.cpp:70
#15 0x0000007fba183aa0 in mozilla::embedlite::PEmbedLiteAppParent::
    OnMessageReceived (this=0x7f88a64fc0, msg__=..., reply__=@0x7fffffea38: 0x0)
    at PEmbedLiteAppParent.cpp:924
#16 0x0000007fba06b618 in mozilla::ipc::MessageChannel::DispatchSyncMessage
    (this=this@entry=0x7f88a65088, aProxy=aProxy@entry=0x7fa0010590, aMsg=..., 
    aReply=@0x7fffffea38: 0x0)
    at ${PROJECT}/obj-build-mer-qt-xr/dist/include/mozilla/ipc/ProtocolUtils.h:675
[...]
#36 0x000000555557b360 in main (argc=<optimized out>, argv=<optimized out>)
    at main.cpp:201
(gdb) 
Frustratingly a lot of the values we'd like to investigate have been optimised out, making them hard to access. However, what we can see is that for the call to EmbedLiteApp::CreateWindowRequested() the value of hidden is set to true:
#13 0x0000007fbcb10eec in mozilla::embedlite::EmbedLiteApp::CreateWindowRequested
    (this=0x5555859800, chromeFlags=@0x7fffffe928: 4094,
    hidden=@0x7fffffe922: true, parentId=@0x7fffffe924: 1,
    parentBrowsingContext=@0x7fffffe938: 547754946368)
That's at stack frame 13. The next time we see it in non-optimised form is at stack frame 0 where it's set to false (albeit with a slightly different name):
#0  mozilla::embedlite::PEmbedLiteAppParent::SendPEmbedLiteViewConstructor
    (this=this@entry=0x7f88a64fc0, windowId=@0x7fffffe414: 1,
    id=@0x7fbfb29440: 3, parentId=@0x7fffffe40c: 1,
    parentBrowsingContext=@0x7fffffe400: 547754946368,
    isPrivateWindow=@0x7fffffe40b: false, isDesktopMode=@0x7fffffe40a: false,
    isHidden=@0x7fffffe409: false) at PEmbedLiteAppParent.cpp:168
Somewhere between these two frames the value is getting lost. The debugger isn't being very helpful in identifying exactly where, so I'll need to read through the code manually.

Luckily it doesn't take long to find out... it's in stack frame 12 where we have this:
uint32_t QMozContextPrivate::CreateNewWindowRequested(const uint32_t &chromeFlags,
    const bool &hidden, EmbedLiteView *aParentView,
    const uintptr_t &parentBrowsingContext)
{
    Q_UNUSED(chromeFlags)

    uint32_t parentId = aParentView ? aParentView->GetUniqueID() : 0;
    qCDebug(lcEmbedLiteExt) << "QtMozEmbedContext new Window requested: parent:"
        << (void *)aParentView << parentId;
    uint32_t viewId = QMozContext::instance()->createView(parentId,
        parentBrowsingContext);
    return viewId;
}
As we can see, the value of hidden just isn't being used at all in this method. I must have missed it when I made all my changes earlier. It slipped past because I gave it a default value in the header, so it compiled even though I forgot to pass it on:
    quint32 createView(const quint32 &parentId = 0,
        const uintptr_t &parentBrowsingContext = 0, const bool hidden = false);
Luckily qtmozembed is one of the quicker browser packages to compile, so it should be possible to fix, build and test the changes pretty swiftly.
 
A screenshot of the tab view in the browser; most of the tabs have a dark background but the one at the bottom is blank and coloured red

Rather excitingly all of the windows now appear with the standard colour, except for the window created during printing which is glaringly red. Just what we need!

Okay, that's it tested and working. The next step is to add the view filtering so that the red windows aren't shown in the user interface. I have a suspicion that this step is going to be harder than I think it is. But that's something to think about tomorrow.

If you'd like to read any of my other gecko diary entries, they're all available on my Gecko-dev Diary page.

Comments

Uncover Disqus comments