Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(6779)

Unified Diff: chrome_frame/turndown_prompt/turndown_prompt.cc

Issue 17153006: Chrome Frame turndown prompt. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase to r208076 Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome_frame/turndown_prompt/turndown_prompt.cc
diff --git a/chrome_frame/turndown_prompt/turndown_prompt.cc b/chrome_frame/turndown_prompt/turndown_prompt.cc
new file mode 100644
index 0000000000000000000000000000000000000000..4d26a2f9bc5e32abbc16bd8e3c73ddfd05bc8dca
--- /dev/null
+++ b/chrome_frame/turndown_prompt/turndown_prompt.cc
@@ -0,0 +1,302 @@
+// Copyright 2013 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_frame/turndown_prompt/turndown_prompt.h"
+
+#include <atlbase.h>
+#include <shlguid.h>
+
+#include "base/bind.h"
+#include "base/compiler_specific.h"
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/path_service.h"
+#include "base/process_util.h"
+#include "base/win/scoped_bstr.h"
+#include "base/win/scoped_comptr.h"
+#include "base/win/win_util.h"
+#include "chrome/installer/util/browser_distribution.h"
+#include "chrome/installer/util/google_update_settings.h"
+#include "chrome/installer/util/install_util.h"
+#include "chrome/installer/util/installation_state.h"
+#include "chrome/installer/util/util_constants.h"
+#include "chrome_frame/infobars/infobar_manager.h"
+#include "chrome_frame/policy_settings.h"
+#include "chrome_frame/ready_mode/internal/ready_mode_web_browser_adapter.h"
+#include "chrome_frame/ready_mode/internal/url_launcher.h"
+#include "chrome_frame/simple_resource_loader.h"
+#include "chrome_frame/turndown_prompt/reshow_state.h"
+#include "chrome_frame/turndown_prompt/turndown_prompt_content.h"
+#include "chrome_frame/utils.h"
+#include "grit/chromium_strings.h"
+#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
+
+namespace {
+
+// Time between showings of the turndown prompt.
+const int kTurndownPromptReshowDeltaMinutes = 60 * 24 * 7;
+
+void OnUninstallClicked(UrlLauncher* url_launcher);
+
+// Manages the Turndown UI in response to browsing ChromeFrame-rendered
+// pages.
+class BrowserObserver : public ReadyModeWebBrowserAdapter::Observer {
+ public:
+ BrowserObserver(IWebBrowser2* web_browser,
+ ReadyModeWebBrowserAdapter* adapter);
+
+ // ReadyModeWebBrowserAdapter::Observer implementation
+ virtual void OnNavigateTo(const string16& url);
+ virtual void OnRenderInChromeFrame(const string16& url);
+ virtual void OnRenderInHost(const string16& url);
+
+ private:
+ // Shows the turndown prompt if it hasn't been seen since
+ // kTurndownPromptReshowDeltaMinutes.
+ void ShowPrompt();
+ void Hide();
+ // Returns a self-managed pointer that is not guaranteed to survive handling
+ // of Windows events. For safety's sake, retrieve this pointer for each use
+ // and do not store it for use outside of scope.
+ InfobarManager* GetInfobarManager();
+
+ GURL rendered_url_;
+ base::win::ScopedComPtr<IWebBrowser2> web_browser_;
+ ReadyModeWebBrowserAdapter* adapter_;
+
+ DISALLOW_COPY_AND_ASSIGN(BrowserObserver);
+};
+
+// Implements launching of a URL in an instance of IWebBrowser2.
+class UrlLauncherImpl : public UrlLauncher {
+ public:
+ explicit UrlLauncherImpl(IWebBrowser2* web_browser);
+
+ // UrlLauncher implementation
+ void LaunchUrl(const string16& url);
+
+ private:
+ base::win::ScopedComPtr<IWebBrowser2> web_browser_;
+};
+
+UrlLauncherImpl::UrlLauncherImpl(IWebBrowser2* web_browser) {
+ DCHECK(web_browser);
+ web_browser_ = web_browser;
+}
+
+void UrlLauncherImpl::LaunchUrl(const string16& url) {
+ VARIANT flags = { VT_I4 };
+ V_I4(&flags) = navOpenInNewWindow;
+ base::win::ScopedBstr location(url.c_str());
+
+ HRESULT hr = web_browser_->Navigate(location, &flags, NULL, NULL, NULL);
+ DLOG_IF(ERROR, FAILED(hr)) << "Failed to invoke Navigate on IWebBrowser2. "
+ << "Error: " << hr;
+}
+
+BrowserObserver::BrowserObserver(IWebBrowser2* web_browser,
+ ReadyModeWebBrowserAdapter* adapter)
+ : web_browser_(web_browser),
+ adapter_(adapter) {
+}
+
+void BrowserObserver::OnNavigateTo(const string16& url) {
+ if (!net::registry_controlled_domains::SameDomainOrHost(
+ GURL(url),
+ rendered_url_,
+ net::registry_controlled_domains::EXCLUDE_PRIVATE_REGISTRIES)) {
+ rendered_url_ = GURL();
+ Hide();
+ }
+}
+
+void BrowserObserver::OnRenderInChromeFrame(const string16& url) {
+ ShowPrompt();
+ rendered_url_ = GURL(url);
+}
+
+void BrowserObserver::OnRenderInHost(const string16& url) {
+ Hide();
+ rendered_url_ = GURL(url);
+}
+
+void BrowserObserver::ShowPrompt() {
+ turndown_prompt::ReshowState reshow_state(
+ base::TimeDelta::FromMinutes(kTurndownPromptReshowDeltaMinutes));
+
+ // Short-circuit if the prompt shouldn't be shown again yet.
+ if (!reshow_state.HasReshowDeltaExpired(base::Time::Now()))
+ return;
+
+ // This pointer is self-managed and not guaranteed to survive handling of
+ // Windows events. For safety's sake, retrieve this pointer for each use and
+ // do not store it for use outside of scope.
+ InfobarManager* infobar_manager = GetInfobarManager();
+
+ if (infobar_manager) {
+ // Owned by infobar_content
+ scoped_ptr<UrlLauncher> url_launcher(new UrlLauncherImpl(web_browser_));
+
+ // Owned by infobar_manager
+ scoped_ptr<InfobarContent> infobar_content(new TurndownPromptContent(
+ url_launcher.release(),
+ base::Bind(&OnUninstallClicked,
+ base::Owned(new UrlLauncherImpl(web_browser_)))));
+
+ if (infobar_manager->Show(infobar_content.release(), TOP_INFOBAR)) {
+ // Update state in the registry that the prompt was shown.
+ reshow_state.MarkShown(base::Time::Now());
+ }
+ }
+}
+
+void BrowserObserver::Hide() {
+ InfobarManager* infobar_manager = GetInfobarManager();
+ if (infobar_manager)
+ infobar_manager->HideAll();
+}
+
+InfobarManager* BrowserObserver::GetInfobarManager() {
+ HRESULT hr = NOERROR;
+
+ base::win::ScopedComPtr<IOleWindow> ole_window;
+ hr = DoQueryService(SID_SShellBrowser, web_browser_, ole_window.Receive());
+ if (FAILED(hr) || ole_window == NULL) {
+ DLOG(ERROR) << "Failed to query SID_SShellBrowser from IWebBrowser2. "
+ << "Error: " << hr;
+ return NULL;
+ }
+
+ HWND web_browser_hwnd = NULL;
+ hr = ole_window->GetWindow(&web_browser_hwnd);
+ if (FAILED(hr) || web_browser_hwnd == NULL) {
+ DLOG(ERROR) << "Failed to query HWND from IOleWindow. "
+ << "Error: " << hr;
+ return NULL;
+ }
+
+ return InfobarManager::Get(web_browser_hwnd);
+}
+
+// Returns true if the module into which this code is linked is installed at
+// system-level.
+bool IsCurrentModuleSystemLevel() {
+ base::FilePath dll_path;
+ if (PathService::Get(base::DIR_MODULE, &dll_path))
+ return !InstallUtil::IsPerUserInstall(dll_path.value().c_str());
+ return false;
+}
+
+// Attempts to create a ReadyModeWebBrowserAdapter instance.
+bool CreateWebBrowserAdapter(ReadyModeWebBrowserAdapter** adapter) {
+ *adapter = NULL;
+
+ CComObject<ReadyModeWebBrowserAdapter>* com_object;
+ HRESULT hr =
+ CComObject<ReadyModeWebBrowserAdapter>::CreateInstance(&com_object);
+
+ if (FAILED(hr)) {
+ DLOG(ERROR) << "Failed to create instance of ReadyModeWebBrowserAdapter. "
+ << "Error: " << hr;
+ return false;
+ }
+
+ com_object->AddRef();
+ *adapter = com_object;
+ return true;
+}
+
+// Attempts to install Turndown prompts in the provided web browser.
+bool InstallPrompts(IWebBrowser2* web_browser) {
+ base::win::ScopedComPtr<ReadyModeWebBrowserAdapter, NULL> adapter;
+
+ if (!CreateWebBrowserAdapter(adapter.Receive()))
+ return false;
+
+ // Pass ownership of our delegate to the BrowserObserver
+ scoped_ptr<ReadyModeWebBrowserAdapter::Observer> browser_observer(
+ new BrowserObserver(web_browser, adapter));
+
+ // Owns the BrowserObserver
+ return adapter->Initialize(web_browser, browser_observer.release());
+}
+
+// Launches the Chrome Frame uninstaller in response to user action. This
+// implementation should not be used to uninstall MSI-based versions of GCF,
+// since those must be removed by way of Windows Installer machinery.
+void LaunchChromeFrameUninstaller() {
+ BrowserDistribution* dist =
+ BrowserDistribution::GetSpecificDistribution(
+ BrowserDistribution::CHROME_FRAME);
+ const bool system_level = IsCurrentModuleSystemLevel();
+ installer::ProductState product_state;
+ if (!product_state.Initialize(system_level, dist)) {
+ DLOG(ERROR) << "Chrome frame isn't installed at "
+ << (system_level ? "system" : "user") << " level.";
+ return;
+ }
+
+ CommandLine uninstall_command(product_state.uninstall_command());
+ if (uninstall_command.GetProgram().empty()) {
+ DLOG(ERROR) << "No uninstall command found in registry.";
+ return;
+ }
+
+ // Force Uninstall silences the prompt to reboot to complete uninstall.
+ uninstall_command.AppendSwitch(installer::switches::kForceUninstall);
+ VLOG(1) << "Uninstalling Chrome Frame with command: "
+ << uninstall_command.GetCommandLineString();
+ base::LaunchProcess(uninstall_command, base::LaunchOptions(), NULL);
+}
+
+void LaunchLearnMoreURL(UrlLauncher* url_launcher) {
+ url_launcher->LaunchUrl(SimpleResourceLoader::Get(
+ IDS_CHROME_FRAME_TURNDOWN_LEARN_MORE_URL));
+}
+
+void OnUninstallClicked(UrlLauncher* url_launcher) {
+ LaunchChromeFrameUninstaller();
+ LaunchLearnMoreURL(url_launcher);
+}
+
+} // namespace
+
+namespace turndown_prompt {
+
+bool IsPromptSuppressed() {
+ // See if this is an MSI install of GCF or if updates have been disabled.
+ BrowserDistribution* dist =
+ BrowserDistribution::GetSpecificDistribution(
+ BrowserDistribution::CHROME_FRAME);
+
+ const bool system_level = IsCurrentModuleSystemLevel();
+ bool multi_install = false;
+
+ installer::ProductState product_state;
+ if (product_state.Initialize(system_level, dist)) {
+ if (product_state.is_msi())
+ return true;
+ multi_install = product_state.is_multi_install();
+ }
+
+ if (multi_install) {
+ dist =
+ BrowserDistribution::GetSpecificDistribution(
+ BrowserDistribution::CHROME_BINARIES);
+ }
+ if (GoogleUpdateSettings::GetAppUpdatePolicy(dist->GetAppGuid(), NULL) ==
+ GoogleUpdateSettings::UPDATES_DISABLED) {
+ return true;
+ }
+
+ // See if the prompt is explicitly suppressed via GP.
+ return PolicySettings::GetInstance()->suppress_turndown_prompt();
+}
+
+void Configure(IWebBrowser2* web_browser) {
+ if (!IsPromptSuppressed())
+ InstallPrompts(web_browser);
+}
+
+} // namespace turndown_prompt
« no previous file with comments | « chrome_frame/turndown_prompt/turndown_prompt.h ('k') | chrome_frame/turndown_prompt/turndown_prompt_content.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698