summaryrefslogtreecommitdiffstats
path: root/chrome_frame/ready_mode
diff options
context:
space:
mode:
authorerikwright@chromium.org <erikwright@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-12-14 20:56:01 +0000
committererikwright@chromium.org <erikwright@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-12-14 20:56:01 +0000
commit2bf5f415ac56938fa2b99417b21ce0c75476d3f4 (patch)
tree2f32792d3fe9ea6f4a5b003c073e68e8d8ab2c2a /chrome_frame/ready_mode
parent61e512816c5510a234f0e5dd21d7556f207cc4cd (diff)
downloadchromium_src-2bf5f415ac56938fa2b99417b21ce0c75476d3f4.zip
chromium_src-2bf5f415ac56938fa2b99417b21ce0c75476d3f4.tar.gz
chromium_src-2bf5f415ac56938fa2b99417b21ce0c75476d3f4.tar.bz2
Implement a ReadyPromptContent that displays a prompt to accept, temporarily decline, or permanently decline ready mode. Implement a RegistryReadyModeState that manages the state (based on user's decision) in the registry. Interfaces to integrate those with the installer.
BUG=None TEST=chrome_frame_unittests --gtest_filter='Ready*' Review URL: http://codereview.chromium.org/5747002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@69175 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome_frame/ready_mode')
-rw-r--r--chrome_frame/ready_mode/internal/installation_state.h31
-rw-r--r--chrome_frame/ready_mode/internal/ready_mode_state.h24
-rw-r--r--chrome_frame/ready_mode/internal/ready_prompt_content.cc102
-rw-r--r--chrome_frame/ready_mode/internal/ready_prompt_content.h37
-rw-r--r--chrome_frame/ready_mode/internal/ready_prompt_window.cc74
-rw-r--r--chrome_frame/ready_mode/internal/ready_prompt_window.h87
-rw-r--r--chrome_frame/ready_mode/internal/registry_ready_mode_state.cc143
-rw-r--r--chrome_frame/ready_mode/internal/registry_ready_mode_state.h73
-rw-r--r--chrome_frame/ready_mode/ready_mode_manager.cc172
-rw-r--r--chrome_frame/ready_mode/ready_mode_manager.h16
10 files changed, 759 insertions, 0 deletions
diff --git a/chrome_frame/ready_mode/internal/installation_state.h b/chrome_frame/ready_mode/internal/installation_state.h
new file mode 100644
index 0000000..52bdfcb
--- /dev/null
+++ b/chrome_frame/ready_mode/internal/installation_state.h
@@ -0,0 +1,31 @@
+// Copyright (c) 2010 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.
+
+#ifndef CHROME_FRAME_READY_MODE_INTERNAL_INSTALLATION_STATE_H_
+#define CHROME_FRAME_READY_MODE_INTERNAL_INSTALLATION_STATE_H_
+#pragma once
+
+// Provides an interface to query and manipulate the registration and
+// installation state of the product.
+class InstallationState {
+ public:
+ virtual ~InstallationState() {}
+
+ // Queries the installation state of the product (whether the product appears
+ // in "Add/Remove Programs" or its equivalent).
+ virtual bool IsProductInstalled() = 0;
+
+ // Queries the registration state of the product (whether the COM objects,
+ // BHO, etc. are registered).
+ virtual bool IsProductRegistered() = 0;
+
+ // Installs the product. Returns true iff successful.
+ virtual bool InstallProduct() = 0;
+
+ // Unregisters the product. Fails if the product is installed. Returns true
+ // iff successful.
+ virtual bool UnregisterProduct() = 0;
+}; // class InstallationState
+
+#endif // CHROME_FRAME_READY_MODE_INTERNAL_INSTALLATION_STATE_H_
diff --git a/chrome_frame/ready_mode/internal/ready_mode_state.h b/chrome_frame/ready_mode/internal/ready_mode_state.h
new file mode 100644
index 0000000..d219631
--- /dev/null
+++ b/chrome_frame/ready_mode/internal/ready_mode_state.h
@@ -0,0 +1,24 @@
+// Copyright (c) 2010 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.
+
+#ifndef CHROME_FRAME_READY_MODE_INTERNAL_READY_MODE_STATE_H_
+#define CHROME_FRAME_READY_MODE_INTERNAL_READY_MODE_STATE_H_
+#pragma once
+
+// Allows the UI element to signal the user's response to a Ready Mode prompt.
+class ReadyModeState {
+ public:
+ virtual ~ReadyModeState() {}
+
+ // Indicates that the user has temporarily declined the product.
+ virtual void TemporarilyDeclineChromeFrame() = 0;
+
+ // Indicates that the user has permanently declined the product.
+ virtual void PermanentlyDeclineChromeFrame() = 0;
+
+ // Indicates that the user has accepted the product.
+ virtual void AcceptChromeFrame() = 0;
+}; // class ReadyModeState
+
+#endif // CHROME_FRAME_READY_MODE_INTERNAL_READY_MODE_STATE_H_
diff --git a/chrome_frame/ready_mode/internal/ready_prompt_content.cc b/chrome_frame/ready_mode/internal/ready_prompt_content.cc
new file mode 100644
index 0000000..4764e63
--- /dev/null
+++ b/chrome_frame/ready_mode/internal/ready_prompt_content.cc
@@ -0,0 +1,102 @@
+// Copyright (c) 2010 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/ready_mode/internal/ready_prompt_content.h"
+
+#include <atlbase.h>
+#include <atlwin.h>
+
+#include "base/logging.h"
+#include "chrome_frame/ready_mode/internal/ready_mode_state.h"
+#include "chrome_frame/ready_mode/internal/ready_prompt_window.h"
+
+ReadyPromptContent::ReadyPromptContent(ReadyModeState* ready_mode_state)
+ : ready_mode_state_(ready_mode_state) {
+}
+
+ReadyPromptContent::~ReadyPromptContent() {
+ if (window_ != NULL && window_->IsWindow()) {
+ // The window must discard its ContentFrame pointer at this time.
+ window_->DestroyWindow();
+ window_.reset();
+ }
+}
+
+bool ReadyPromptContent::InstallInFrame(Frame* frame) {
+ DCHECK(window_ == NULL);
+ DCHECK(ready_mode_state_ != NULL);
+
+ // The window owns itself upon call to Initialize.
+ ReadyPromptWindow* new_window_ = new ReadyPromptWindow();
+ window_ = new_window_->Initialize(frame, ready_mode_state_.release());
+
+ return window_ != NULL;
+}
+
+void ReadyPromptContent::SetDimensions(const RECT& dimensions) {
+ if (window_ != NULL && window_->IsWindow()) {
+ window_->SetWindowPos(HWND_TOP, &dimensions,
+ ::IsRectEmpty(&dimensions) ? SWP_HIDEWINDOW :
+ SWP_SHOWWINDOW);
+ }
+}
+
+bool GetDialogTemplateDimensions(ReadyPromptWindow* window, RECT* dimensions) {
+ HRSRC resource = ::FindResource(_AtlBaseModule.GetResourceInstance(),
+ MAKEINTRESOURCE(ReadyPromptWindow::IDD),
+ RT_DIALOG);
+
+ HGLOBAL handle = NULL;
+ DLGTEMPLATE* dlgtemplate = NULL;
+ _DialogSplitHelper::DLGTEMPLATEEX* dlgtemplateex = NULL;
+
+ if (resource == NULL) {
+ DPLOG(ERROR) << "Failed to find resource for ReadyPromptWindow::IDD";
+ return false;
+ }
+
+ handle = ::LoadResource(_AtlBaseModule.GetResourceInstance(), resource);
+
+ if (handle == NULL) {
+ DPLOG(ERROR) << "Failed to load resource for ReadyPromptWindow::IDD";
+ return false;
+ }
+
+ dlgtemplate = reinterpret_cast<DLGTEMPLATE*>(::LockResource(handle));
+ if (dlgtemplate == NULL) {
+ DPLOG(ERROR) << "Failed to lock resource for ReadyPromptWindow::IDD";
+ return false;
+ }
+
+ if (!_DialogSplitHelper::IsDialogEx(dlgtemplate)) {
+ DLOG(ERROR) << "Resource ReadyPromptWindow::IDD is not a DLGTEMPLATEEX";
+ return false;
+ }
+
+ dlgtemplateex =
+ reinterpret_cast<_DialogSplitHelper::DLGTEMPLATEEX*>(dlgtemplate);
+
+ RECT dlgdimensions = {0, 0, dlgtemplateex->cx, dlgtemplateex->cy};
+ if (!window->MapDialogRect(&dlgdimensions)) {
+ DPLOG(ERROR) << "Failure in MapDialogRect";
+ return false;
+ }
+
+ *dimensions = dlgdimensions;
+ return true;
+}
+
+size_t ReadyPromptContent::GetDesiredSize(size_t width, size_t height) {
+ DCHECK(window_ != NULL && window_->IsWindow());
+
+ if (window_ == NULL || !window_->IsWindow()) {
+ return 0;
+ }
+ RECT dialog_dimensions = {0, 0, 0, 0};
+
+ if (GetDialogTemplateDimensions(window_.get(), &dialog_dimensions))
+ return width == 0 ? dialog_dimensions.right : dialog_dimensions.bottom;
+ else
+ return width == 0 ? 0 : 39;
+}
diff --git a/chrome_frame/ready_mode/internal/ready_prompt_content.h b/chrome_frame/ready_mode/internal/ready_prompt_content.h
new file mode 100644
index 0000000..bb8692e
--- /dev/null
+++ b/chrome_frame/ready_mode/internal/ready_prompt_content.h
@@ -0,0 +1,37 @@
+// Copyright (c) 2010 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.
+
+#ifndef CHROME_FRAME_READY_MODE_INTERNAL_READY_PROMPT_CONTENT_H_
+#define CHROME_FRAME_READY_MODE_INTERNAL_READY_PROMPT_CONTENT_H_
+#pragma once
+
+#include "base/basictypes.h"
+#include "base/scoped_ptr.h"
+#include "base/weak_ptr.h"
+#include "chrome_frame/infobars/infobar_content.h"
+
+class ReadyModeState;
+class ReadyPromptWindow;
+
+// Encapsulates the Ready Mode prompt inviting users to permanently activate
+// Chrome Frame, temporarily disable Ready Mode, or permanently disable Ready
+// Mode.
+class ReadyPromptContent : public InfobarContent {
+ public:
+ explicit ReadyPromptContent(ReadyModeState* ready_mode_state);
+ ~ReadyPromptContent();
+
+ // InfobarContent implementation
+ virtual bool InstallInFrame(Frame* frame);
+ virtual void SetDimensions(const RECT& dimensions);
+ virtual size_t GetDesiredSize(size_t width, size_t height);
+
+ private:
+ base::WeakPtr<ReadyPromptWindow> window_;
+ scoped_ptr<ReadyModeState> ready_mode_state_;
+
+ DISALLOW_COPY_AND_ASSIGN(ReadyPromptContent);
+}; // class ReadyPromptContent
+
+#endif // CHROME_FRAME_READY_MODE_INTERNAL_READY_PROMPT_CONTENT_H_
diff --git a/chrome_frame/ready_mode/internal/ready_prompt_window.cc b/chrome_frame/ready_mode/internal/ready_prompt_window.cc
new file mode 100644
index 0000000..b05fbce
--- /dev/null
+++ b/chrome_frame/ready_mode/internal/ready_prompt_window.cc
@@ -0,0 +1,74 @@
+// Copyright (c) 2010 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/ready_mode/internal/ready_prompt_window.h"
+
+#include "base/compiler_specific.h"
+#include "chrome_frame/ready_mode/internal/ready_mode_state.h"
+
+ReadyPromptWindow::ReadyPromptWindow()
+ : frame_(NULL),
+ weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
+}
+
+base::WeakPtr<ReadyPromptWindow> ReadyPromptWindow::Initialize(
+ InfobarContent::Frame* frame, ReadyModeState* ready_mode_state) {
+ DCHECK(frame != NULL);
+ DCHECK(frame_ == NULL);
+ DCHECK(ready_mode_state != NULL);
+ DCHECK(ready_mode_state_ == NULL);
+
+ frame_ = frame;
+ ready_mode_state_.reset(ready_mode_state);
+
+ DCHECK(!IsWindow());
+
+ if (Create(frame->GetFrameWindow()) == NULL) {
+ DPLOG(ERROR) << "Failed to create HWND for ReadyPromptWindow.";
+ delete this;
+ return base::WeakPtr<ReadyPromptWindow>();
+ }
+
+ return weak_ptr_factory_.GetWeakPtr();
+}
+
+void ReadyPromptWindow::OnDestroy() {
+ frame_ = NULL;
+}
+
+BOOL ReadyPromptWindow::OnInitDialog(CWindow wndFocus, LPARAM lInitParam) {
+ DlgResize_Init(false); // false => 'no gripper'
+ return TRUE;
+}
+
+LRESULT ReadyPromptWindow::OnYes(WORD /*wNotifyCode*/,
+ WORD /*wID*/,
+ HWND /*hWndCtl*/,
+ BOOL& /*bHandled*/) {
+ frame_->CloseInfobar();
+ ready_mode_state_->AcceptChromeFrame();
+ return 0;
+}
+
+LRESULT ReadyPromptWindow::OnRemindMeLater(WORD /*wNotifyCode*/,
+ WORD /*wID*/,
+ HWND /*hWndCtl*/,
+ BOOL& /*bHandled*/) {
+ frame_->CloseInfobar();
+ ready_mode_state_->TemporarilyDeclineChromeFrame();
+ return 0;
+}
+
+LRESULT ReadyPromptWindow::OnNo(WORD /*wNotifyCode*/,
+ WORD /*wID*/,
+ HWND /*hWndCtl*/,
+ BOOL& /*bHandled*/) {
+ frame_->CloseInfobar();
+ ready_mode_state_->PermanentlyDeclineChromeFrame();
+ return 0;
+}
+
+void ReadyPromptWindow::OnFinalMessage(HWND) {
+ delete this;
+}
diff --git a/chrome_frame/ready_mode/internal/ready_prompt_window.h b/chrome_frame/ready_mode/internal/ready_prompt_window.h
new file mode 100644
index 0000000..2d931a3
--- /dev/null
+++ b/chrome_frame/ready_mode/internal/ready_prompt_window.h
@@ -0,0 +1,87 @@
+// Copyright (c) 2010 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.
+
+#ifndef CHROME_FRAME_READY_MODE_INTERNAL_READY_PROMPT_WINDOW_H_
+#define CHROME_FRAME_READY_MODE_INTERNAL_READY_PROMPT_WINDOW_H_
+#pragma once
+
+#include <atlbase.h>
+#include <atlapp.h>
+#include <atlcrack.h>
+#include <atlframe.h>
+#include <atlwin.h>
+
+#include "base/weak_ptr.h"
+#include "base/scoped_ptr.h"
+#include "chrome_frame/infobars/infobar_content.h"
+#include "chrome_frame/resource.h"
+#include "grit/generated_resources.h"
+
+class ReadyModeState;
+
+// Implements a dialog with text and buttons inviting the user to permanently
+// activate the product or temporarily/permanently disable Ready Mode.
+class ReadyPromptWindow
+ : public CDialogImpl<ReadyPromptWindow, CWindow>,
+ public CDialogResize<ReadyPromptWindow> {
+ public:
+ enum { IDD = IDD_CHROME_FRAME_READY_PROMPT };
+
+ ReadyPromptWindow();
+ ~ReadyPromptWindow() {}
+
+ // Initializes the dialog for display in the provided frame. The
+ // ReadyModeState will be invoked to capture the user's response, if any.
+ //
+ // Upon success, takes ownership of itself (to be deleted upon WM_DESTROY) and
+ // returns a weak pointer to this dialog. Upon failure, returns a null weak
+ // pointer and deletes self.
+ //
+ // In either case, takes ownership of the ReadyModeState, but not the frame.
+ base::WeakPtr<ReadyPromptWindow> Initialize(InfobarContent::Frame* frame,
+ ReadyModeState* ready_mode_state);
+
+ BEGIN_MSG_MAP(InfobarWindow)
+ MSG_WM_INITDIALOG(OnInitDialog)
+ MSG_WM_DESTROY(OnDestroy)
+ COMMAND_HANDLER(IDACTIVATE, BN_CLICKED, OnYes)
+ COMMAND_HANDLER(IDLATER, BN_CLICKED, OnRemindMeLater)
+ COMMAND_HANDLER(IDNEVER, BN_CLICKED, OnNo)
+ CHAIN_MSG_MAP(CDialogResize<ReadyPromptWindow>)
+ END_MSG_MAP()
+
+ BEGIN_DLGRESIZE_MAP(InfobarWindow)
+ DLGRESIZE_CONTROL(IDACTIVATE, DLSZ_CENTER_Y | DLSZ_MOVE_X)
+ DLGRESIZE_CONTROL(IDLATER, DLSZ_CENTER_Y | DLSZ_MOVE_X)
+ DLGRESIZE_CONTROL(IDNEVER, DLSZ_CENTER_Y | DLSZ_MOVE_X)
+ DLGRESIZE_CONTROL(IDC_PROMPT_MESSAGE, DLSZ_SIZE_Y | DLSZ_SIZE_X)
+ END_DLGRESIZE_MAP()
+
+ virtual void OnFinalMessage(HWND);
+
+ private:
+ // Event handlers.
+ void OnDestroy();
+ BOOL OnInitDialog(CWindow wndFocus, LPARAM lInitParam);
+ LRESULT OnYes(WORD wNotifyCode,
+ WORD wID,
+ HWND hWndCtl,
+ BOOL& bHandled);
+ LRESULT OnRemindMeLater(WORD wNotifyCode,
+ WORD wID,
+ HWND hWndCtl,
+ BOOL& bHandled);
+ LRESULT OnNo(WORD wNotifyCode,
+ WORD wID,
+ HWND hWndCtl,
+ BOOL& bHandled);
+
+ InfobarContent::Frame* frame_; // Not owned by this instance
+ scoped_ptr<ReadyModeState> ready_mode_state_;
+
+ base::WeakPtrFactory<ReadyPromptWindow> weak_ptr_factory_;
+ DISALLOW_COPY_AND_ASSIGN(ReadyPromptWindow);
+}; // class ReadyPromptWindow
+
+#endif // CHROME_FRAME_READY_MODE_INTERNAL_READY_PROMPT_WINDOW_H_
diff --git a/chrome_frame/ready_mode/internal/registry_ready_mode_state.cc b/chrome_frame/ready_mode/internal/registry_ready_mode_state.cc
new file mode 100644
index 0000000..8561732
--- /dev/null
+++ b/chrome_frame/ready_mode/internal/registry_ready_mode_state.cc
@@ -0,0 +1,143 @@
+// Copyright (c) 2010 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/ready_mode/internal/registry_ready_mode_state.h"
+
+#include "base/time.h"
+#include "base/task.h"
+#include "base/win/registry.h"
+#include "chrome_frame/ready_mode/internal/installation_state.h"
+#include "chrome_frame/ready_mode/ready_mode_manager.h"
+
+namespace {
+
+const wchar_t kReadyModeStateValue[] = L"ReadyModeState";
+
+}; // namespace
+
+RegistryReadyModeState::RegistryReadyModeState(
+ const std::wstring& key_name, base::TimeDelta temporary_decline_duration,
+ InstallationState* installation_state, Observer* observer)
+ : key_name_(key_name),
+ temporary_decline_duration_(temporary_decline_duration),
+ installation_state_(installation_state),
+ observer_(observer) {
+}
+
+RegistryReadyModeState::~RegistryReadyModeState() {
+}
+
+base::Time RegistryReadyModeState::GetNow() {
+ return base::Time::Now();
+}
+
+ReadyModeStatus RegistryReadyModeState::GetStatus() {
+ if (installation_state_->IsProductInstalled())
+ return READY_MODE_ACCEPTED;
+
+ if (!installation_state_->IsProductRegistered())
+ return READY_MODE_PERMANENTLY_DECLINED;
+
+ bool exists = false;
+ int64 value = 0;
+
+ if (!GetValue(&value, &exists))
+ return READY_MODE_TEMPORARILY_DECLINED;
+
+ if (!exists)
+ return READY_MODE_ACTIVE;
+
+ if (value == 0)
+ return READY_MODE_PERMANENTLY_DECLINED;
+
+ base::Time when_declined(base::Time::FromInternalValue(value));
+ base::Time now(GetNow());
+
+ // If the decline duration has passed, or is further in the future than
+ // the total timeout, consider it expired.
+ bool expired = (now - when_declined) > temporary_decline_duration_ ||
+ (when_declined - now) > temporary_decline_duration_;
+
+ // To avoid a race-condition in GetValue (between ValueExists and ReadValue)
+ // we never delete the temporary decline flag.
+ if (expired)
+ return READY_MODE_ACTIVE;
+
+ return READY_MODE_TEMPORARILY_DECLINED;
+}
+
+bool RegistryReadyModeState::GetValue(int64* value, bool* exists) {
+ *exists = false;
+ *value = 0;
+
+ base::win::RegKey config_key;
+ if (!config_key.Open(HKEY_CURRENT_USER, key_name_.c_str(), KEY_QUERY_VALUE)) {
+ DLOG(ERROR) << "Failed to open registry key " << key_name_;
+ return false;
+ }
+
+ if (!config_key.ValueExists(kReadyModeStateValue))
+ return true;
+
+ int64 temp;
+ DWORD value_size = sizeof(temp);
+ DWORD type = 0;
+ if (!config_key.ReadValue(kReadyModeStateValue, &temp, &value_size, &type)) {
+ DLOG(ERROR) << "Failed to open registry key " << key_name_;
+ return false;
+ }
+
+ if (value_size != sizeof(temp) || type != REG_QWORD) {
+ DLOG(ERROR) << "Unexpected state found under registry key " << key_name_
+ << " and value " << kReadyModeStateValue;
+ config_key.DeleteValue(kReadyModeStateValue);
+ return true;
+ }
+
+ *value = temp;
+ *exists = true;
+ return true;
+}
+
+bool RegistryReadyModeState::StoreValue(int64 value) {
+ base::win::RegKey config_key;
+ if (config_key.Open(HKEY_CURRENT_USER, key_name_.c_str(), KEY_SET_VALUE) &&
+ config_key.WriteValue(kReadyModeStateValue, &value, sizeof(value),
+ REG_QWORD)) {
+ return true;
+ }
+
+ DLOG(ERROR) << "Failed to open or write to registry key " << key_name_
+ << " and value " << kReadyModeStateValue;
+
+ return false;
+}
+
+void RegistryReadyModeState::TemporarilyDeclineChromeFrame() {
+ int64 value = GetNow().ToInternalValue();
+
+ if (StoreValue(value))
+ observer_->OnStateChange();
+}
+
+void RegistryReadyModeState::PermanentlyDeclineChromeFrame() {
+ bool success = false;
+
+ // Either change, by itself, will deactivate Ready Mode, though we prefer to
+ // also unregister, in order to free up resources.
+
+ if (StoreValue(0))
+ success = true;
+
+ if (installation_state_->UnregisterProduct())
+ success = true;
+
+ if (success)
+ observer_->OnStateChange();
+}
+
+void RegistryReadyModeState::AcceptChromeFrame() {
+ if (installation_state_->InstallProduct())
+ observer_->OnStateChange();
+}
diff --git a/chrome_frame/ready_mode/internal/registry_ready_mode_state.h b/chrome_frame/ready_mode/internal/registry_ready_mode_state.h
new file mode 100644
index 0000000..54f44e3
--- /dev/null
+++ b/chrome_frame/ready_mode/internal/registry_ready_mode_state.h
@@ -0,0 +1,73 @@
+// Copyright (c) 2010 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.
+
+#ifndef CHROME_FRAME_READY_MODE_INTERNAL_REGISTRY_READY_MODE_STATE_H_
+#define CHROME_FRAME_READY_MODE_INTERNAL_REGISTRY_READY_MODE_STATE_H_
+#pragma once
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/scoped_ptr.h"
+#include "base/time.h"
+#include "chrome_frame/ready_mode/internal/ready_mode_state.h"
+
+enum ReadyModeStatus;
+
+class InstallationState;
+class Task;
+
+// Implements ReadyModeState, storing state in the Registry and delegating to an
+// instance of InstallationState to interact with the installer. Notifies a
+// single Observer when the state changes.
+class RegistryReadyModeState : public ReadyModeState {
+ public:
+ // Receives notification when the Ready Mode state changes in response to a
+ // user interaction. Does not receive notification when a temporary decline of
+ // Ready Mode expires.
+ class Observer {
+ public:
+ virtual ~Observer() {}
+ // Indicates that a state change has occurred.
+ virtual void OnStateChange() = 0;
+ }; // class Observer
+
+ // Construct an instance backed by the specified key
+ // (pre-existing under HKCU). The provided duration indicates how long, after
+ // a temporary decline, Ready Mode re-activates.
+ //
+ // Takes ownership of the Observer and InstallationState instances.
+ RegistryReadyModeState(const std::wstring& key_name,
+ base::TimeDelta temporary_decline_duration,
+ InstallationState* installation_state,
+ Observer* observer);
+ virtual ~RegistryReadyModeState();
+
+ // Returns the current Ready Mode status, as determined using our registry
+ // state and InstallationState instance.
+ ReadyModeStatus GetStatus();
+
+ // ReadyModeState implementation
+ virtual void TemporarilyDeclineChromeFrame();
+ virtual void PermanentlyDeclineChromeFrame();
+ virtual void AcceptChromeFrame();
+
+ protected:
+ // allow dependency replacement via derivation for tests
+ virtual base::Time GetNow();
+
+ private:
+ // Retrieves state from the registry. Returns true upon success.
+ bool GetValue(int64* value, bool* exists);
+ // Stores value in the registry. Returns true upon success.
+ bool StoreValue(int64 value);
+
+ base::TimeDelta temporary_decline_duration_;
+ int temporary_decline_length_seconds_;
+ std::wstring key_name_;
+ scoped_ptr<InstallationState> installation_state_;
+ scoped_ptr<Observer> observer_;
+}; // class RegistryReadyModeState
+
+#endif // CHROME_FRAME_READY_MODE_INTERNAL_REGISTRY_READY_MODE_STATE_H_
diff --git a/chrome_frame/ready_mode/ready_mode_manager.cc b/chrome_frame/ready_mode/ready_mode_manager.cc
new file mode 100644
index 0000000..c0e03fc
--- /dev/null
+++ b/chrome_frame/ready_mode/ready_mode_manager.cc
@@ -0,0 +1,172 @@
+// Copyright (c) 2010 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/ready_mode/ready_mode_manager.h"
+
+#include <exdisp.h>
+#include <atlbase.h>
+#include <shlguid.h>
+
+#include "base/compiler_specific.h"
+#include "base/logging.h"
+#include "base/scoped_ptr.h"
+#include "base/utf_string_conversions.h"
+#include "base/win/scoped_comptr.h"
+#include "net/base/registry_controlled_domain.h"
+#include "chrome_frame/infobars/infobar_manager.h"
+#include "chrome_frame/ready_mode/internal/ready_prompt_content.h"
+#include "chrome_frame/ready_mode/internal/registry_ready_mode_state.h"
+#include "chrome_frame/utils.h"
+
+namespace {
+
+const int kTemporaryDeclineDurationMinutes = 1;
+
+}; // namespace
+
+class ReadyModeManagerImpl : public ReadyModeManager {
+ public:
+ bool Initialize(IUnknown* site) {
+ DCHECK(!web_browser_);
+ DCHECK(site);
+
+ if (web_browser_ != NULL)
+ return false;
+
+ if (site != NULL)
+ web_browser_.QueryFrom(site);
+
+ return web_browser_ != NULL;
+ }
+
+ protected:
+ virtual void OnDeclineChromeFrame() {
+ VARIANT flags = { VT_I4 };
+ V_I4(&flags) = navNoHistory;
+ web_browser_->Navigate(CComBSTR(ASCIIToWide(rendered_url_.spec()).c_str()),
+ &flags, NULL, NULL, NULL);
+ }
+
+ virtual InfobarManager* GetInfobarManager() {
+ base::win::ScopedComPtr<IOleWindow> ole_window;
+ HWND web_browserhwnd = NULL;
+
+ if (web_browser_ != NULL)
+ DoQueryService(SID_SShellBrowser, web_browser_, ole_window.Receive());
+
+ if (ole_window != NULL)
+ ole_window->GetWindow(&web_browserhwnd);
+
+ if (web_browserhwnd != NULL)
+ return InfobarManager::Get(web_browserhwnd);
+
+ return NULL;
+ }
+
+ private:
+ base::win::ScopedComPtr<IWebBrowser2> web_browser_;
+};
+
+class DisableReadyModeObserver : public RegistryReadyModeState::Observer {
+ public:
+ DisableReadyModeObserver(IWebBrowser2* web_browser)
+ : web_browser_(web_browser) {
+ DCHECK(web_browser != NULL);
+ }
+ virtual void OnStateChange() {
+ VARIANT flags = { VT_I4 };
+ V_I4(&flags) = navNoHistory;
+ web_browser_->Navigate(CComBSTR(ASCIIToWide(rendered_url_.spec()).c_str()),
+ &flags, NULL, NULL, NULL);
+ }
+ private:
+ base::win::ScopedComPtr<IWebBrowser2> web_browser_;
+};
+
+class ReadyModeUIImpl : public ReadyModeWebBrowserAdapter::ReadyModeUI {
+ public:
+ virtual void ShowPrompt() {
+ InfobarManager* infobar_manager = GetInfobarManager();
+ if (infobar_manager) {
+ InstallationState* = new DummyInstallationState();
+
+ ReadyModeState* ready_mode_state = new RegistryReadyModeState(
+ kChromeFrameConfigKey,
+ base::TimeDelta::FromMinutes(kTemporaryDeclineDurationMinutes),
+ installation_state,
+ observer);
+ base::WeakPtr<ReadyModeManager> weak_ptr(weak_ptr_factory_.GetWeakPtr());
+ infobar_manager->Show(new ReadyPromptContent(NULL /* TODO(erikwright)*/), TOP_INFOBAR);
+ }
+ }
+ virtual void Hide() {
+ }
+
+ private:
+ virtual InfobarManager* GetInfobarManager() {
+ base::win::ScopedComPtr<IOleWindow> ole_window;
+ HWND web_browserhwnd = NULL;
+
+ if (web_browser_ != NULL)
+ DoQueryService(SID_SShellBrowser, web_browser_, ole_window.Receive());
+
+ if (ole_window != NULL)
+ ole_window->GetWindow(&web_browserhwnd);
+
+ if (web_browserhwnd != NULL)
+ return InfobarManager::Get(web_browserhwnd);
+
+ return NULL;
+ }
+
+ base::win::ScopedComPtr<IWebBrowser2> web_browser_;
+};
+
+void ReadyMode::Configure(ChromeFrameIntegration* integration,
+ IWebBrowser2* site) {
+
+}
+
+ReadyModeManager::ReadyModeManager()
+ : weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
+}
+
+ReadyModeManager::~ReadyModeManager() {
+}
+
+ReadyModeManager* ReadyModeManager::CreateReadyModeManager(IUnknown* site) {
+ scoped_ptr<ReadyModeManagerImpl> impl(new ReadyModeManagerImpl());
+
+ if (impl->Initialize(site))
+ return impl.release();
+
+ return NULL;
+}
+
+void ReadyModeManager::BeginNavigationTo(std::string http_method, std::wstring url) {
+ if (!net::RegistryControlledDomainService::SameDomainOrHost(GURL(url),
+ rendered_url_)) {
+ InfobarManager* infobar_manager = GetInfobarManager();
+ if (infobar_manager)
+ infobar_manager->HideAll();
+
+ rendered_url_ = GURL();
+ }
+}
+
+void ReadyModeManager::RenderingInHost(std::string http_method, std::wstring url) {
+ InfobarManager* infobar_manager = GetInfobarManager();
+ if (infobar_manager)
+ infobar_manager->HideAll();
+ rendered_url_ = GURL(url);
+}
+
+void ReadyModeManager::RenderingInChromeFrame(std::string http_method, std::wstring url) {
+ InfobarManager* infobar_manager = GetInfobarManager();
+ if (infobar_manager) {
+ base::WeakPtr<ReadyModeManager> weak_ptr(weak_ptr_factory_.GetWeakPtr());
+ infobar_manager->Show(new ReadyPromptContent(NULL /* TODO(erikwright)*/), TOP_INFOBAR);
+ }
+ rendered_url_ = GURL(url);
+}
diff --git a/chrome_frame/ready_mode/ready_mode_manager.h b/chrome_frame/ready_mode/ready_mode_manager.h
new file mode 100644
index 0000000..f496a26
--- /dev/null
+++ b/chrome_frame/ready_mode/ready_mode_manager.h
@@ -0,0 +1,16 @@
+// Copyright (c) 2010 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.
+
+#ifndef CHROME_FRAME_READY_MODE_READY_MODE_MANAGER_H_
+#define CHROME_FRAME_READY_MODE_READY_MODE_MANAGER_H_
+#pragma once
+
+enum ReadyModeStatus {
+ READY_MODE_PERMANENTLY_DECLINED,
+ READY_MODE_TEMPORARILY_DECLINED,
+ READY_MODE_ACTIVE,
+ READY_MODE_ACCEPTED
+}; // enum ReadyModeStatus
+
+#endif // CHROME_FRAME_READY_MODE_READY_MODE_MANAGER_H_