Sunday, 18 September 2011

Get Chrome active tab URL using Delphi

After developing my first Chrome extension to retrieve all URLs from Google chrome, I have been trying to reproduce the same behaviour using Delphi, but it was impossible. Chrome is still adding some new features and extending their extensions for developers. For example, others navigators such as Internet Explorer and Firefox they have a DDE extension to retrieve some of the properties but not available for Chrome.
The best way I found was using FindWindow and SendMessage windows functions to get the text from the tab and get tue URL. It's not a win solution but will help you to retrieve the URL of the active page without copy-paste action, just by switching to the next tab and retrieving data from the tool.

The basic code to achieve this is the following one:

function GetChromeActiveTabURL(Wnd: HWnd; Param: LParam): Bool; stdcall;
var
  urls: TStrings;
  hWndMainWindow, hWndTab: HWND;
  Buffer : array[0..255] of Char;
  res : boolean;
begin
  res := true;
  urls := TStrings(Param);
  SendMessage(Wnd, WM_GETTEXT, Length(Buffer), integer(@Buffer[0]));
  hWndMainWindow := FindWindow('Chrome_WidgetWin_0', Buffer);
  application.ProcessMessages;
  if hWndMainWindow <> 0 then
  begin
    hWndTab := FindWindowEx(hWndMainWindow, 0, 'Chrome_AutocompleteEditView', nil);
    if hWndTab <> 0 then
    begin
      SendMessage(hWndTab, WM_GETTEXT, Length(Buffer), integer(@Buffer));
      urls.Add(Buffer);
      res := false;
    end;
  end;
  Result := res;
end;

procedure TUrlChrome.GetUrl(Sender: TObject);
var
  Urls: TStringList;
begin
  Urls := TStringList.Create;
  try
    EnumWindows(@GetChromeActiveTabURL, LParam(Urls));
    Memo1.Lines.AddStrings(Urls);
  finally
    FreeAndNil(Urls);
  end;
end;

To get the class name window, we can use Winspector to inspect chrome and get the names for the main window and for the tabs:

Chrome_WidgetWin_0:

Chrome_AutocompleteEditView:

And you can get the tool from here: ThundaxChromeURL.


I'm not proud of this solution, but at least it will work for current versions of Chrome. I also recommend to give a go to my chrome extension (It's not been published into Chrome market, it turns out that you have to pay a $5.00 fee), that is much better than the tool as it's able to get all urls.

Related links:

7 comments:

  1. You can try MSAA. Example: http://www.transl-gunsmoker.ru/2009/08/blog-post.html

    ReplyDelete
  2. Hi Torbins,

    Thanks for your comment, but I think that's not the same. I want to automatically get the URL from the active tab and in the example given, the user needs to move the mouse to the text.
    Anyway, the best option is to use my Chrome Extension ;)

    Jordi.

    ReplyDelete
  3. If you want a "win" solution of getting stuff from Chrome to Delphi (and your cool with making extensions) you should prolly look at WebSockets....its all a little beyond me but Im sure someone with your skills would find it trivial. With a quick look around I couldnt find anything working, but thats prolly because Chrome keeps changing the specs (mainly to do with the handshake), but they havent changed it for a while now so maybe its time to have a good look at it.

    Anywayz, great blog, lots of interesting stuff.

    ReplyDelete
  4. Hi PAEz,

    Thans for your comment! I really appreciate it, and I will have a go using WebSockets. As you actually commented Google is changing specs all the time and there is a request on their forum for this topic.

    Jordi.

    ReplyDelete
  5. Good Evening, I wonder if you're the same function for Safari.
    thank you

    ReplyDelete
    Replies
    1. Sorry but only works for Chrome. I have never delved into detail with Safari but I assume it should work in a similar fashion way.

      Delete
  6. As I googled yes, but all the classes I search returned nothing, also tried using the class delphi URLMON, so you do not know which service passes, passing only Safari would be the same with other browsers (Firefox, Internet Explorer) but also did not .

    ReplyDelete