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

Unified Diff: chrome_frame/infobar_manager.cc

Issue 4766003: Preview CL for adding an Infobar facility to Google Chrome Frame.... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 10 years, 1 month 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/infobar_manager.cc
===================================================================
--- chrome_frame/infobar_manager.cc (revision 0)
+++ chrome_frame/infobar_manager.cc (revision 0)
@@ -0,0 +1,268 @@
+// 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.
+//
+// Implementation of the manager for infobar windows.
+
+#include "chrome_frame/infobar_manager.h"
+
+#include <atlbase.h>
+#include <atlapp.h> // Must be included AFTER base.
+#include <atlcrack.h>
+#include <atlmisc.h>
+#include <atlwin.h>
+
+#include "base/logging.h"
+#include "base/task_queue.h"
+//#include "ceee/common/windows_constants.h"
+#include "chrome_frame/utils.h"
+
+namespace {
+
+const wchar_t kIeTabContentParentWindowClass[] = L"Shell DocObject View";
+
+} // namespace
+
+DISABLE_RUNNABLE_METHOD_REFCOUNT(InfobarManager);
+DISABLE_RUNNABLE_METHOD_REFCOUNT(InfobarManager::DisplacedWindowManager);
+
+
+InfobarManager::InfobarHostImpl::InfobarHostImpl(InfobarManager *manager)
+ : manager_(manager) {
+}
+
+HWND InfobarManager::InfobarHostImpl::GetContainerWindow() {
+ return manager_->container_window_;
+}
+
+void InfobarManager::InfobarHostImpl::UpdateLayout() {
+ manager_->UpdateLayout();
+}
+
+// DisplacedWindowManager subclasses IE content window's container window,
+// handles WM_NCCALCSIZE to resize its client area. It also handles WM_SIZE and
+// WM_MOVE messages to make infobars consistent with IE content window's size
+// and position.
+//
+// Finally, allows delayed tasks to be scheduled on the window's event loop.
+class InfobarManager::DisplacedWindowManager
+ : public CWindowImpl<DisplacedWindowManager> {
+ public:
+ DisplacedWindowManager(InfobarManager* manager)
+ : infobar_manager_(manager) {
+ }
+
+ // Returns true if the window is successfully subclassed, in which case this
+ // instance will take responsibility for its own destruction when the window
+ // is destroyed. If this method returns false, the caller should delete the
+ // instance immediately.
+ bool Initialize(HWND displaced_hwnd) {
+ PinModule();
+ if (!SubclassWindow(displaced_hwnd)) {
+ LOG(DFATAL) << "Failed to subclass IE Renderer HWND for infobar "
+ << "installation.";
+ return false;
+ }
+ return true;
+ }
+
+ virtual ~DisplacedWindowManager() {
+ if (IsWindow())
+ UnsubclassWindow();
+ }
+
+ // Triggers a deferred re-evaluation of the dimensions of the displaced
+ // window. InfobarManager::AdjustDisplacedWindowDimensions will be called
+ // with the natural dimensions of the displaced window.
+ virtual void UpdateLayout() {
+ PushTask(
+ NewRunnableMethod(this, &DisplacedWindowManager::DoUpdateLayout));
+ }
+
+ // Schedules a deferred task on the window message loop of this instance's
+ // managed window. The task may not occur if the window is destroyed first.
+ virtual void PushTask(Task* task) {
+ task_queue_.Push(task);
+ if (IsWindow())
+ PostMessage(TM_RUN_TASK_QUEUE, 0, 0);
+ }
+
+ BEGIN_MSG_MAP_EX(DisplacedWindowManager)
+ MSG_WM_NCCALCSIZE(OnNcCalcSize)
+ MSG_WM_DESTROY(OnDestroy)
+ MESSAGE_HANDLER(TM_RUN_TASK_QUEUE, OnRunTaskQueue)
+ END_MSG_MAP()
+
+ private:
+ enum DisplacedWindowUserMessages {
+ TM_RUN_TASK_QUEUE = WM_USER + 600,
+ };
+
+ LRESULT OnRunTaskQueue(UINT message,
+ WPARAM wparam,
+ LPARAM lparam,
+ BOOL& handled) {
+ task_queue_.Run();
+ handled = TRUE;
+ return 0;
+ }
+
+ void DoUpdateLayout() {
+ // Call SetWindowPos with SWP_FRAMECHANGED for IE window, then IE
+ // window would receive WM_NCCALCSIZE to recalculate its client size.
+ if (IsWindow())
+ ::SetWindowPos(m_hWnd,
+ NULL, 0, 0, 0, 0,
+ SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER |
+ SWP_FRAMECHANGED);
+ }
+
+ // Handles WM_NCCALCSIZE message.
+ LRESULT OnNcCalcSize(BOOL calc_valid_rects, LPARAM lparam) {
+ // Adjust client area for infobar.
+ LRESULT ret = DefWindowProc(WM_NCCALCSIZE,
+ static_cast<WPARAM>(calc_valid_rects), lparam);
+ // Whether calc_valid_rects is true or false, we could treat beginning of
+ // lparam as a RECT object.
+ RECT* rect = reinterpret_cast<RECT*>(lparam);
+ if (infobar_manager_ != NULL)
+ infobar_manager_->AdjustDisplacedWindowDimensions(rect);
+
+ // If infobars reserve all the space and rect becomes empty, the container
+ // window won't receive subsequent WM_SIZE and WM_MOVE messages.
+ // In this case, we have to explicitly notify infobars to update their
+ // position.
+ //if (rect->right - rect->left <= 0 || rect->bottom - rect->top <= 0)
+ // PushTask(
+ // NewRunnableMethod(infobar_manager_,
+ // &InfobarManager::OnDisplacedWindowPositionChange));
+ return ret;
+ }
+
+ // The displaced window has been destroyed. Inform the InfobarManager, who
+ // will orphan this instance. We will delete ourselves in OnFinalMessage.
+ void OnDestroy() {
+ infobar_manager_->OnDisplacedWindowDestroyed();
+ }
+
+ void OnFinalMessage(HWND) {
+ delete this;
+ }
+
+ InfobarManager* infobar_manager_;
+ TaskQueue task_queue_;
+ DISALLOW_COPY_AND_ASSIGN(DisplacedWindowManager);
+};
+
+InfobarManager::InfobarManager(HWND tab_window)
+ : container_window_(tab_window),
+ displaced_window_manager_(NULL),
+ infobar_host_impl_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
+ for (int index = 0; index < END_OF_INFOBAR_TYPE; ++index) {
amit 2010/11/12 00:04:49 Feels like an overkill for our rudimentary infobar
erikwright (departed) 2010/11/24 06:24:56 The TOP vs BOTTOM and sliding is unnecessary, but
+ infobars_[index].reset(
+ new InfobarWindow(static_cast<InfobarType>(index),
+ &infobar_host_impl_));
+ }
+}
+
+HRESULT InfobarManager::Show(InfobarContent* content,
+ InfobarType type,
+ int max_height) {
+ if (type < FIRST_INFOBAR_TYPE || type >= END_OF_INFOBAR_TYPE ||
grt (UTC plus 2) 2010/11/10 17:59:29 This looks like programmer error. Change to DCHEC
erikwright (departed) 2010/11/24 06:24:56 Yes. A relic of the original code. Ideally, I'd li
+ infobars_[type] == NULL) {
grt (UTC plus 2) 2010/11/10 17:59:29 How about this one, programmer error or something
erikwright (departed) 2010/11/24 06:24:56 Yes. I'm updating it to only return success or fai
+ return E_INVALIDARG;
+ }
+
+ HRESULT hr = infobars_[type]->Show(content, max_height);
+ return hr;
+}
+
+bool InfobarManager::UpdateLayout() {
+ if (FindDisplacedWindow()) {
+ displaced_window_manager_->UpdateLayout();
+ return true;
+ } else {
+ return false;
+ }
+}
+
+HRESULT InfobarManager::Hide(InfobarType type) {
+ if (type < FIRST_INFOBAR_TYPE || type >= END_OF_INFOBAR_TYPE ||
+ infobars_[type] == NULL) {
+ return E_INVALIDARG;
+ }
+
+ infobars_[type]->Hide();
+ return S_OK;
+}
+
+void InfobarManager::HideAll() {
+ for (int index = 0; index < END_OF_INFOBAR_TYPE; ++index)
+ Hide(static_cast<InfobarType>(index));
+}
+
+// Callback function for EnumChildWindows. lParam should be the pointer to
+// HWND variable where the handle of the window which class is
+// kIeTabContentParentWindowClass will be written.
+static BOOL CALLBACK FindDisplacedWindowProc(HWND hwnd, LPARAM lparam) {
+ HWND* window_handle = reinterpret_cast<HWND*>(lparam);
+ if (NULL == window_handle) {
grt (UTC plus 2) 2010/11/10 17:59:29 I prefer this style of comparison. For consistenc
erikwright (departed) 2010/11/24 06:24:56 Agreed. Not the least because scoped_ptr does not
+ // It makes no sense to continue enumeration.
+ return FALSE;
+ }
+
+ // Variable to hold the class name. The size does not matter as long as it
+ // is at least can hold kIeTabContentParentWindowClass.
+ wchar_t class_name[100];
+ if (::GetClassName(hwnd, class_name, arraysize(class_name)) &&
+ lstrcmpi(kIeTabContentParentWindowClass, class_name) == 0) {
+ // We found the window. Return its handle and stop enumeration.
+ *window_handle = hwnd;
+ return FALSE;
+ }
+ return TRUE;
+}
+
+bool InfobarManager::FindDisplacedWindow() {
+ if (displaced_window_manager_ == NULL) {
+ if (::IsWindow(container_window_)) {
+ // Find the window which is the container for the HTML view (parent of
+ // the content).
+ HWND displaced_window = NULL;
+ ::EnumChildWindows(container_window_, FindDisplacedWindowProc,
+ reinterpret_cast<LPARAM>(&displaced_window));
+
+ if (displaced_window == NULL) {
+ LOG(DFATAL) << "Failed to locate IE renderer HWND to displace for "
+ << "Infobar installation.";
+ } else {
+ scoped_ptr<DisplacedWindowManager> displaced_window_manager(
+ new DisplacedWindowManager(this));
+ if (displaced_window_manager->Initialize(displaced_window)) {
+ displaced_window_manager_ = displaced_window_manager.release();
+ }
+ }
+ }
+ }
+
+ return displaced_window_manager_ != NULL;
+}
+
+void InfobarManager::AdjustDisplacedWindowDimensions(RECT* rect) {
+ if (rect == NULL)
+ return;
+
+ for (int index = 0; index < END_OF_INFOBAR_TYPE; ++index) {
+ if (infobars_[index] != NULL)
+ infobars_[index]->ReserveSpace(rect);
+ }
+}
+
+void InfobarManager::OnDisplacedWindowDestroyed() {
+ for (int index = 0; index < END_OF_INFOBAR_TYPE; ++index) {
+ if (infobars_[index] != NULL)
+ infobars_[index]->Hide();
+ }
+ // Will be deleted in its OnFinalMessage
+ displaced_window_manager_ = NULL;
+}

Powered by Google App Engine
This is Rietveld 408576698