blob: d3ecb491d102878067126a57ba535df38c10ac43 [file] [log] [blame]
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/browser_switcher/bho/bho.h"
#include <atlstr.h>
#include <initguid.h>
#include <time.h>
#include <wininet.h>
#include "chrome/browser/browser_switcher/bho/logging.h"
// Declare this GUID for Windows 8 Enhanced Protected Mode Compatibility.
// This is defined in newer SDK versions but since we need XP support we can't
// use them.
DEFINE_GUID(CATID_AppContainerCompatible,
0x59fb2056,
0xd625,
0x48d0,
0xa9,
0x44,
0x1a,
0x85,
0xb5,
0xab,
0x26,
0x40);
namespace {
const wchar_t kHttpPrefix[] = L"http://";
const wchar_t kHttpsPrefix[] = L"https://";
const wchar_t kFilePrefix[] = L"file://";
} // namespace
CBrowserSwitcherBHO::CBrowserSwitcherBHO() = default;
CBrowserSwitcherBHO::~CBrowserSwitcherBHO() = default;
// Implementation of IObjectWithSiteImpl::SetSite.
STDMETHODIMP CBrowserSwitcherBHO::SetSite(IUnknown* site) {
if (site != NULL) {
HRESULT hr = site->QueryInterface(IID_IWebBrowser2,
reinterpret_cast<void**>(&web_browser_));
if (SUCCEEDED(hr)) {
hr = DispEventAdvise(web_browser_);
advised_ = true;
}
} else { // site == NULL
if (advised_) {
DispEventUnadvise(web_browser_);
advised_ = false;
}
web_browser_.Release();
}
return IObjectWithSiteImpl<CBrowserSwitcherBHO>::SetSite(site);
}
// If enabled, monitors navigations and redirects them to Chrome if they are
// not intended to happen in IE according to the Legacy Browser Support policy.
// This only applies to top-level documents (not to frames).
void STDMETHODCALLTYPE
CBrowserSwitcherBHO::BeforeNavigate(IDispatch* disp,
VARIANT* url,
VARIANT* flags,
VARIANT* target_frame_name,
VARIANT* post_data,
VARIANT* headers,
VARIANT_BOOL* cancel) {
if (web_browser_ != NULL && disp != NULL) {
ATL::CComPtr<IUnknown> unknown1;
ATL::CComPtr<IUnknown> unknown2;
if (SUCCEEDED(web_browser_->QueryInterface(
IID_IUnknown, reinterpret_cast<void**>(&unknown1))) &&
SUCCEEDED(disp->QueryInterface(IID_IUnknown,
reinterpret_cast<void**>(&unknown2)))) {
// check if this is the outter frame.
if (unknown1 == unknown2) {
bool result =
CheckUrl((LPOLESTR)url->bstrVal, *cancel != VARIANT_FALSE);
if (result)
web_browser_->Quit();
*cancel = result ? VARIANT_TRUE : VARIANT_FALSE;
}
}
}
}
// Checks if an url should be loaded in IE or forwarded to the default browser.
bool CBrowserSwitcherBHO::CheckUrl(LPOLESTR url, bool cancel) {
// Only verify the url if it is http[s] link.
if ((!_wcsnicmp(url, kHttpPrefix, wcslen(kHttpPrefix)) ||
!_wcsnicmp(url, kHttpsPrefix, wcslen(kHttpsPrefix)) ||
!_wcsnicmp(url, kFilePrefix, wcslen(kFilePrefix))) &&
!browser_switcher_.ShouldOpenInAlternativeBrowser(url)) {
LOG(INFO) << "\tTriggering redirect" << std::endl;
if (!browser_switcher_.InvokeChrome(url)) {
LOG(ERR) << "Could not invoke alternative browser! "
<< "Will resume loading in IE!" << std::endl;
} else {
cancel = true;
}
}
return cancel;
}