15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2011 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/certificate_viewer.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <windows.h>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <cryptuiapi.h>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#pragma comment(lib, "cryptui.lib")
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
12f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/message_loop/message_loop.h"
13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/cert/x509_certificate.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(USE_AURA)
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/host_desktop.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/aura/root_window.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/aura/window.h"
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ShowCertificateViewerImpl(content::WebContents* web_contents,
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               HWND parent,
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               net::X509Certificate* cert) {
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create a new cert context and store containing just the certificate
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // and its intermediate certificates.
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PCCERT_CONTEXT cert_list = cert->CreateOSCertChainForCert();
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(cert_list);
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CRYPTUI_VIEWCERTIFICATE_STRUCT view_info = { 0 };
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  view_info.dwSize = sizeof(view_info);
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We set our parent to the tab window. This makes the cert dialog created
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // in CryptUIDlgViewCertificate modal to the browser.
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  view_info.hwndParent = parent;
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  view_info.dwFlags = CRYPTUI_DISABLE_EDITPROPERTIES |
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      CRYPTUI_DISABLE_ADDTOSTORE;
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  view_info.pCertContext = cert_list;
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HCERTSTORE cert_store = cert_list->hCertStore;
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  view_info.cStores = 1;
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  view_info.rghStores = &cert_store;
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BOOL properties_changed;
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
44f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // We must allow nested tasks to dispatch so that, e.g. gpu tasks are
45f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // processed for painting. This allows a second window to continue painting
46f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // while the the certificate dialog is open.
47f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  base::MessageLoop::ScopedNestableTaskAllower allow(
48f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      base::MessageLoop::current());
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This next call blocks but keeps processing windows messages, making it
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // modal to the browser window.
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BOOL rv = ::CryptUIDlgViewCertificate(&view_info, &properties_changed);
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CertFreeCertificateContext(cert_list);
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(USE_AURA)
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ShowCertificateViewer(content::WebContents* web_contents,
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           gfx::NativeWindow parent,
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           net::X509Certificate* cert) {
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (chrome::GetHostDesktopTypeForNativeWindow(parent) !=
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      chrome::HOST_DESKTOP_TYPE_ASH) {
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ShowCertificateViewerImpl(
65f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        web_contents,
66f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        parent->GetDispatcher()->host()->GetAcceleratedWidget(), cert);
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    NOTIMPLEMENTED();
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#else
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ShowCertificateViewer(content::WebContents* web_contents,
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           gfx::NativeWindow parent,
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           net::X509Certificate* cert) {
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ShowCertificateViewerImpl(web_contents, parent, cert);
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
78