Get the Browser Page Title & URL for Safari, Chrome, or FireFox

Chris,

OK, so do I have this right?

  • KM7 is working properly with Chrome for US/English localization
  • This issue is with the German localization.

Hey Michael (JMichaelTX),

Not true.

Chrome works just fine when it is not frontmost.

HOWEVER there is a pitfall — if Chrome has been hidden it loses its concept of front-window and returns the first window in the window-index-order.

Safari has the same problem.

-Chris

Hey Michael,

@snapitup hasn't gotten back to me yet, so I don't know. I think so, but we need to verify.

-Chris

In my macro, the one I was referring to, it tests for the frontmost app, and if it is Safari or FF, for example, it doesn't even use the Chrome tokens. :smile:

Hey Michael,

I see. It wasn't evident to me that you were referring back to the original macro and not the troubleshooting sub-thread. My bad.   :confounded:

-Chris

Chris, n.p. I wasn’t very clear.

It has nothing to do with version 7. Keyboard Maestro gets the Chrome title/URL using AppleScript, specifically:

tell application "Google Chrome"
  if it is running then
    tell window 1
      set r to execute active tab javascript "document.title"
      if r is missing value then
        set r to ""
      end if
    end tell
  else
    set r to "Not Running"
  end if
end tell
r

The AppleScript in turn is executed via osascript.

For reasons unknown to me, this AppleScript interaction with Google Chrome fails for some people some of the time. This knocks out the Google Chrome actions as well as the Google Chrome text tokens.

Its particularly odd in that it does not seem to stop other AppleScript access to Google Chrome.

However, since I have never been able to duplicate it, and since it tends to be transient, its very hard to even figure out what is failing.

Thanks for the clarification, Peter.

Sorry for the delay... I'm not sure if this is correct: The name is "Google Chrome", displayed in KM:

Is that what you mean?

Perhaps web-page dependent ? A particular context in which I do find it reproducible is when Chrome’s front window is displaying Google’s search page.

In this context:

Safari evaluates document.title → “Google”, but
Chrome evaluates document.title → “”

With both browsers displaying the Google search page, the code below, evaluating document.title first in Safari and then in Chrome, reproducibly returns:

["Google", ""]

Test code (JavaScript for Applications):

// With front page of both browsers at the Google search page,
// Safari returns "Google", but Chrome returns only an empty string.

function run() {
  return ["Safari", "Chrome"].map(
    function (strBrowser) {
      return evalJSinBrowser(
        
        // Function to be evaluated in Browser
        function () {
          return document.title;
        },
        
        [], strBrowser
      );
    }
  );
}

// Evaluate code for a function application to a named browser (Chrome | Safari)
// fn --> [arg] --> strBrowserName --> a
function evalJSinBrowser(fnMain, lstArgs, strBrowser) {

  var strDefault = "Safari",
    blnSafari = ((
      strBrowser = ((strBrowser || '').indexOf(strDefault) === 0) ?
      strDefault : "Google Chrome"
    ) === strDefault),
    appBrowser = Application(strBrowser),
    lstWins = appBrowser.windows(),
    lngWins = lstWins.length,

    // an open window (new if none exists)
    oWin = lngWins ? lstWins[0] : blnSafari ?
    appBrowser.Document().make() && appBrowser.windows[0] :
    appBrowser.Window().make(),

    // code of an fnMain().apply(null, lstArgs) function application
    strJS = [
      '(',
      fnMain.toString(),
      ').apply(null, ',
      JSON.stringify(lstArgs),
      ');'
    ].join('');

  return (
    blnSafari ?
    appBrowser.doJavaScript(
      strJS, {
        "in": oWin.tabs[0]
      }
    ) :
    oWin.activeTab.execute({
      "javascript": strJS
    })
  );
}

Hi Michael (TX), the Chrome Page is the frontmost app/screen, when i execute the macro.

Looking a little deeper, I notice that if I request a Google search page through the Home icon of Chrome, it serves a page which does in fact lack an /html/head/title element (contrary, I think, to W3C guidelines : -)

(If, however, I request the Google search page with an explicit URL, rather than Chrome's home button, Google serves me a slightly different page - one in which the text of /html/head/title is "Google".

So in the earlier test, the different results from Safari and Chrome reflected a quirk of Google's servers, rather than a divergence of the Safari and Chrome evaluation engines …

Perhaps that is what people have been encountering ?

UPDATE

If we look at a page from the New York Times, its outer level has a value for /html/head/title

(see the last line here)

but embedded lower down in the same page is another document in which the title is an empty string:

It occurs to me that Chrome and Safari may handle these cases differently.

If embedded documents with empty titles are the issue, then there are various ways of evaluating an XPath to the first non-empty instance of /html/head/title

Aternative routes to title of page in Chrome.kmmacros (4.6 KB)

(function () {
	var nodeTitle = document.evaluate(
		'//html/head/title[string-length(text()) > 0]',
		document,
		null, 0, 0
	).iterateNext();
	
	return nodeTitle ? nodeTitle.textContent : '';
})()

Or compressed a bit into a token:

%ChromeJavaScript%(function(){var a=document.evaluate("//html/head/title[string-length(text()) > 0]",document,null,0,0).iterateNext();return a?a.textContent:""})()%

and for the case of the URL, perhaps worth trying a .js token like:

%ChromeJavaScript%document.URL%

Rob, these look handy. Thanks.

Do you think your method of getting Chome page title & URL is more bullet-proof than the native KM method (which uses AppleScript under the hood)?

I did think so for a moment

(when I noticed cases of empty title tags)

but since then I’ve found that trying to get any of these actions to talk to Chrome in a newly restarted session, before Chrome has been run, can create a glitch, at least on my system.

( Cleared by closing and restarting KM, I think )

Perhaps there’s a condition in which a Chrome helper process is not ready for the conversation ? Not sure …

UPDATE

More specifically …

If I just log out and log back in, and then run these actions without launching Chrome, the response is as expected: they return the string ‘Not Running’.

If, however, I restart the machine, and then run one of these actions without launching Chrome:

  1. No string at all is returned.
  2. Still no string if I run them again after launching Chrome and opening a web page.
  3. Normal functioning is restored if I close and reopen KM. (but not if I simply close and reopen Chrome)

Seems like the issue is avoided by ensuring that Chrome is running before executing these actions, which is easy enough to do with either putting the macro in the proper Group, or specifically testing for it in a KM If/Then action.

1 Like

@JMichaelTX
Hi and good day JMichael, Did you maybe update the KM Macro BRW SUB Get Page Title & URL from Safari… ?
It is no longer at the Dropbox link.
/
with best regards,
Omar KN
Stockholm, Sweden

Omar, my apologies for not responding to this much sooner. I missed your post and just discovered it. I have updated the macro and attached it to this thread, so it should be available for download now. Just go to my original post at the top.

Hi and good day Michael,

I have updated the macro and attached it to this thread, so it should be available for download now. Just go to my original post at the top.

Phantastic!

As it is a sub macro I added a simple if/else action: Set Clipboard to Styled Text, which works,
but the action Apply Style to Clipboard (System Clipboard) is not swallowed, whereever I set it! see red frame.

More fun with Style ...

Why wouldn't it work, any idea?

/
with best regards,
Omar K N
Stockholm, Sweden

Omar, this should work. I use it in a lot of my macros.
When I have a problem like this, I copy the Action with the issue, and paste it into a new TEST macro for testing, so I can isolate the Action. You might try that.

If you can't get it to work, then it is best if you can attach your macro to your post here, so we can test.