<commit_before>// 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/browser/extensions/extension_install_ui.h"

#include <map>

#include "app/l10n_util.h"
#include "app/resource_bundle.h"
#include "base/file_util.h"
#include "base/rand_util.h"
#include "base/string_util.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/browser_list.h"
#include "chrome/browser/browser_window.h"
#include "chrome/browser/extensions/theme_installed_infobar_delegate.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#if defined(TOOLKIT_VIEWS)  // TODO(port)
#include "chrome/browser/views/extensions/extension_installed_bubble.h"
#elif defined(TOOLKIT_GTK)
#include "chrome/browser/gtk/extension_installed_bubble_gtk.h"
#endif
#include "chrome/common/extensions/extension.h"
#include "chrome/common/notification_service.h"
#include "chrome/common/platform_util.h"
#include "chrome/common/url_constants.h"
#include "grit/browser_resources.h"
#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"

#if defined(TOOLKIT_GTK)
#include "chrome/browser/extensions/gtk_theme_installed_infobar_delegate.h"
#include "chrome/browser/gtk/gtk_theme_provider.h"
#endif

#if defined(OS_MACOSX)
#include "chrome/browser/cocoa/extension_installed_bubble_bridge.h"
#endif

// static
const int ExtensionInstallUI::kTitleIds[NUM_PROMPT_TYPES] = {
  IDS_EXTENSION_INSTALL_PROMPT_TITLE,
  IDS_EXTENSION_UNINSTALL_PROMPT_TITLE
};
// static
const int ExtensionInstallUI::kHeadingIds[NUM_PROMPT_TYPES] = {
  IDS_EXTENSION_INSTALL_PROMPT_HEADING,
  IDS_EXTENSION_UNINSTALL_PROMPT_HEADING
};
// static
const int ExtensionInstallUI::kButtonIds[NUM_PROMPT_TYPES] = {
  IDS_EXTENSION_PROMPT_INSTALL_BUTTON,
  IDS_EXTENSION_PROMPT_UNINSTALL_BUTTON
};

namespace {

// We also show the severe warning if the extension has access to any file://
// URLs. They aren't *quite* as dangerous as full access to the system via
// NPAPI, but pretty dang close. Content scripts are currently the only way
// that extension can get access to file:// URLs.
static bool ExtensionHasFileAccess(Extension* extension) {
  for (UserScriptList::const_iterator script =
           extension->content_scripts().begin();
       script != extension->content_scripts().end();
       ++script) {
    for (UserScript::PatternList::const_iterator pattern =
             script->url_patterns().begin();
         pattern != script->url_patterns().end();
         ++pattern) {
      if (pattern->scheme() == chrome::kFileScheme)
        return true;
    }
  }

  return false;
}

static void GetV2Warnings(Extension* extension,
                          std::vector<string16>* warnings) {
  if (!extension->plugins().empty() || ExtensionHasFileAccess(extension)) {
    // TODO(aa): This one is a bit awkward. Should we have a separate
    // presentation for this case?
    warnings->push_back(
        l10n_util::GetStringUTF16(IDS_EXTENSION_PROMPT2_WARNING_FULL_ACCESS));
    return;
  }

  if (extension->HasAccessToAllHosts()) {
    warnings->push_back(
        l10n_util::GetStringUTF16(IDS_EXTENSION_PROMPT2_WARNING_ALL_HOSTS));
  } else {
    std::set<std::string> hosts = extension->GetEffectiveHostPermissions();
    if (hosts.size() == 1) {
      warnings->push_back(
          l10n_util::GetStringFUTF16(IDS_EXTENSION_PROMPT2_WARNING_1_HOST,
                                     UTF8ToUTF16(*hosts.begin())));
    } else if (hosts.size() == 2) {
      warnings->push_back(
          l10n_util::GetStringFUTF16(IDS_EXTENSION_PROMPT2_WARNING_2_HOSTS,
                                     UTF8ToUTF16(*hosts.begin()),
                                     UTF8ToUTF16(*(++hosts.begin()))));
    } else if (hosts.size() == 3) {
      warnings->push_back(
          l10n_util::GetStringFUTF16(IDS_EXTENSION_PROMPT2_WARNING_3_HOSTS,
                                     UTF8ToUTF16(*hosts.begin()),
                                     UTF8ToUTF16(*(++hosts.begin())),
                                     UTF8ToUTF16(*(++++hosts.begin()))));
    } else if (hosts.size() >= 4) {
      warnings->push_back(
          l10n_util::GetStringFUTF16(
              IDS_EXTENSION_PROMPT2_WARNING_4_OR_MORE_HOSTS,
              UTF8ToUTF16(*hosts.begin()),
              UTF8ToUTF16(*(++hosts.begin())),
              IntToString16(hosts.size() - 2)));
    }
  }

  if (extension->HasEffectiveBrowsingHistoryPermission()) {
    warnings->push_back(
        l10n_util::GetStringUTF16(
            IDS_EXTENSION_PROMPT2_WARNING_BROWSING_HISTORY));
  }

  // TODO(aa): Geolocation, camera/mic, what else?
}

}  // namespace

ExtensionInstallUI::ExtensionInstallUI(Profile* profile)
    : profile_(profile),
      ui_loop_(MessageLoop::current()),
      previous_use_system_theme_(false),
      extension_(NULL),
      delegate_(NULL),
      prompt_type_(NUM_PROMPT_TYPES),
      ALLOW_THIS_IN_INITIALIZER_LIST(tracker_(this)) {}

void ExtensionInstallUI::ConfirmInstall(Delegate* delegate,
                                        Extension* extension) {
  DCHECK(ui_loop_ == MessageLoop::current());
  extension_ = extension;
  delegate_ = delegate;

  // We special-case themes to not show any confirm UI. Instead they are
  // immediately installed, and then we show an infobar (see OnInstallSuccess)
  // to allow the user to revert if they don't like it.
  if (extension->IsTheme()) {
    // Remember the current theme in case the user pressed undo.
    Extension* previous_theme = profile_->GetTheme();
    if (previous_theme)
      previous_theme_id_ = previous_theme->id();

#if defined(TOOLKIT_GTK)
    // On Linux, we also need to take the user's system settings into account
    // to undo theme installation.
    previous_use_system_theme_ =
        GtkThemeProvider::GetFrom(profile_)->UseGtkTheme();
#else
    DCHECK(!previous_use_system_theme_);
#endif

    delegate->InstallUIProceed(false);
    return;
  }

  ShowConfirmation(INSTALL_PROMPT);
}

void ExtensionInstallUI::ConfirmUninstall(Delegate* delegate,
                                          Extension* extension) {
  DCHECK(ui_loop_ == MessageLoop::current());
  extension_ = extension;
  delegate_ = delegate;

  ShowConfirmation(UNINSTALL_PROMPT);
}

void ExtensionInstallUI::OnInstallSuccess(Extension* extension) {
  if (extension->IsTheme()) {
    ShowThemeInfoBar(previous_theme_id_, previous_use_system_theme_,
                     extension, profile_);
    return;
  }

  // GetLastActiveWithProfile will fail on the build bots. This needs to be
  // implemented differently if any test is created which depends on
  // ExtensionInstalledBubble showing.
  Browser* browser = BrowserList::GetLastActiveWithProfile(profile_);

#if defined(TOOLKIT_VIEWS)
  if (!browser)
    return;

  ExtensionInstalledBubble::Show(extension, browser, icon_);
#elif defined(OS_MACOSX)
  DCHECK(browser);
  // Note that browser actions don't appear in incognito mode initially,
  // so fall back to the generic case.
  if ((extension->browser_action() && !browser->profile()->IsOffTheRecord()) ||
      (extension->page_action() &&
      !extension->page_action()->default_icon_path().empty())) {
    ExtensionInstalledBubbleCocoa::ShowExtensionInstalledBubble(
        browser->window()->GetNativeHandle(),
        extension, browser, icon_);
  }  else {
    // If the extension is of type GENERIC, meaning it doesn't have a UI
    // surface to display for this window, launch infobar instead of popup
    // bubble, because we have no guaranteed wrench menu button to point to.
    ShowGenericExtensionInstalledInfoBar(extension);
  }
#elif defined(TOOLKIT_GTK)
  if (!browser)
    return;
  ExtensionInstalledBubbleGtk::Show(extension, browser, icon_);
#endif  // TOOLKIT_VIEWS
}

void ExtensionInstallUI::OnInstallFailure(const std::string& error) {
  DCHECK(ui_loop_ == MessageLoop::current());

  Browser* browser = BrowserList::GetLastActiveWithProfile(profile_);
  platform_util::SimpleErrorBox(
      browser ? browser->window()->GetNativeHandle() : NULL,
      l10n_util::GetStringUTF16(IDS_EXTENSION_INSTALL_FAILURE_TITLE),
      UTF8ToUTF16(error));
}

void ExtensionInstallUI::OnOverinstallAttempted(Extension* extension) {
  ShowThemeInfoBar(previous_theme_id_, previous_use_system_theme_,
                   extension, profile_);
}

void ExtensionInstallUI::OnImageLoaded(
    SkBitmap* image, ExtensionResource resource, int index) {
  if (image)
    icon_ = *image;
  else
    icon_ = SkBitmap();
  if (icon_.empty()) {
    icon_ = *ResourceBundle::GetSharedInstance().GetBitmapNamed(
        IDR_EXTENSION_DEFAULT_ICON);
  }

  switch (prompt_type_) {
    case INSTALL_PROMPT: {
      NotificationService* service = NotificationService::current();
      service->Notify(NotificationType::EXTENSION_WILL_SHOW_CONFIRM_DIALOG,
          Source<ExtensionInstallUI>(this),
          NotificationService::NoDetails());

      std::vector<string16> warnings;
      GetV2Warnings(extension_, &warnings);
      ShowExtensionInstallUIPrompt2Impl(
          profile_, delegate_, extension_, &icon_, warnings);
      break;
    }
    case UNINSTALL_PROMPT: {
      string16 message =
          l10n_util::GetStringUTF16(IDS_EXTENSION_UNINSTALL_CONFIRMATION);
      ShowExtensionInstallUIPromptImpl(profile_, delegate_, extension_, &icon_,
          message, UNINSTALL_PROMPT);
      break;
    }
    default:
      NOTREACHED() << "Unknown message";
      break;
  }
}

void ExtensionInstallUI::ShowThemeInfoBar(
    const std::string& previous_theme_id, bool previous_use_system_theme,
    Extension* new_theme, Profile* profile) {
  if (!new_theme->IsTheme())
    return;

  Browser* browser = BrowserList::GetLastActiveWithProfile(profile);
  if (!browser)
    return;

  TabContents* tab_contents = browser->GetSelectedTabContents();
  if (!tab_contents)
    return;

  // First find any previous theme preview infobars.
  InfoBarDelegate* old_delegate = NULL;
  for (int i = 0; i < tab_contents->infobar_delegate_count(); ++i) {
    InfoBarDelegate* delegate = tab_contents->GetInfoBarDelegateAt(i);
    if (delegate->AsThemePreviewInfobarDelegate()) {
      old_delegate = delegate;
      break;
    }
  }

  // Then either replace that old one or add a new one.
  InfoBarDelegate* new_delegate =
      GetNewThemeInstalledInfoBarDelegate(
          tab_contents, new_theme,
          previous_theme_id, previous_use_system_theme);

  if (old_delegate)
    tab_contents->ReplaceInfoBar(old_delegate, new_delegate);
  else
    tab_contents->AddInfoBar(new_delegate);
}

void ExtensionInstallUI::ShowConfirmation(PromptType prompt_type) {
  // Load the image asynchronously. For the response, check OnImageLoaded.
  prompt_type_ = prompt_type;
  ExtensionResource image =
      extension_->GetIconPath(Extension::EXTENSION_ICON_LARGE);
  tracker_.LoadImage(extension_, image,
                     gfx::Size(Extension::EXTENSION_ICON_LARGE,
                               Extension::EXTENSION_ICON_LARGE),
                     ImageLoadingTracker::DONT_CACHE);
}

#if defined(OS_MACOSX)
void ExtensionInstallUI::ShowGenericExtensionInstalledInfoBar(
    Extension* new_extension) {
  Browser* browser = BrowserList::GetLastActiveWithProfile(profile_);
  if (!browser)
    return;

  TabContents* tab_contents = browser->GetSelectedTabContents();
  if (!tab_contents)
    return;

  std::wstring msg = l10n_util::GetStringF(IDS_EXTENSION_INSTALLED_HEADING,
                                           UTF8ToWide(new_extension->name())) +
         L" " + l10n_util::GetString(IDS_EXTENSION_INSTALLED_MANAGE_INFO_MAC);
  InfoBarDelegate* delegate = new SimpleAlertInfoBarDelegate(
      tab_contents, msg, new SkBitmap(icon_), true);
  tab_contents->AddInfoBar(delegate);
}
#endif

InfoBarDelegate* ExtensionInstallUI::GetNewThemeInstalledInfoBarDelegate(
    TabContents* tab_contents, Extension* new_theme,
    const std::string& previous_theme_id, bool previous_use_system_theme) {
#if defined(TOOLKIT_GTK)
  return new GtkThemeInstalledInfoBarDelegate(tab_contents, new_theme,
      previous_theme_id, previous_use_system_theme);
#else
  return new ThemeInstalledInfoBarDelegate(tab_contents, new_theme,
      previous_theme_id);
#endif
}
<commit_msg>Auto-launch apps after installation.<commit_after>// 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/browser/extensions/extension_install_ui.h"

#include <map>

#include "app/l10n_util.h"
#include "app/resource_bundle.h"
#include "base/file_util.h"
#include "base/rand_util.h"
#include "base/string_util.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/browser_list.h"
#include "chrome/browser/browser_window.h"
#include "chrome/browser/extensions/theme_installed_infobar_delegate.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#if defined(TOOLKIT_VIEWS)  // TODO(port)
#include "chrome/browser/views/extensions/extension_installed_bubble.h"
#elif defined(TOOLKIT_GTK)
#include "chrome/browser/gtk/extension_installed_bubble_gtk.h"
#endif
#include "chrome/common/extensions/extension.h"
#include "chrome/common/notification_service.h"
#include "chrome/common/platform_util.h"
#include "chrome/common/url_constants.h"
#include "grit/browser_resources.h"
#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"

#if defined(TOOLKIT_GTK)
#include "chrome/browser/extensions/gtk_theme_installed_infobar_delegate.h"
#include "chrome/browser/gtk/gtk_theme_provider.h"
#endif

#if defined(OS_MACOSX)
#include "chrome/browser/cocoa/extension_installed_bubble_bridge.h"
#endif

// static
const int ExtensionInstallUI::kTitleIds[NUM_PROMPT_TYPES] = {
  IDS_EXTENSION_INSTALL_PROMPT_TITLE,
  IDS_EXTENSION_UNINSTALL_PROMPT_TITLE
};
// static
const int ExtensionInstallUI::kHeadingIds[NUM_PROMPT_TYPES] = {
  IDS_EXTENSION_INSTALL_PROMPT_HEADING,
  IDS_EXTENSION_UNINSTALL_PROMPT_HEADING
};
// static
const int ExtensionInstallUI::kButtonIds[NUM_PROMPT_TYPES] = {
  IDS_EXTENSION_PROMPT_INSTALL_BUTTON,
  IDS_EXTENSION_PROMPT_UNINSTALL_BUTTON
};

namespace {

// We also show the severe warning if the extension has access to any file://
// URLs. They aren't *quite* as dangerous as full access to the system via
// NPAPI, but pretty dang close. Content scripts are currently the only way
// that extension can get access to file:// URLs.
static bool ExtensionHasFileAccess(Extension* extension) {
  for (UserScriptList::const_iterator script =
           extension->content_scripts().begin();
       script != extension->content_scripts().end();
       ++script) {
    for (UserScript::PatternList::const_iterator pattern =
             script->url_patterns().begin();
         pattern != script->url_patterns().end();
         ++pattern) {
      if (pattern->scheme() == chrome::kFileScheme)
        return true;
    }
  }

  return false;
}

static void GetV2Warnings(Extension* extension,
                          std::vector<string16>* warnings) {
  if (!extension->plugins().empty() || ExtensionHasFileAccess(extension)) {
    // TODO(aa): This one is a bit awkward. Should we have a separate
    // presentation for this case?
    warnings->push_back(
        l10n_util::GetStringUTF16(IDS_EXTENSION_PROMPT2_WARNING_FULL_ACCESS));
    return;
  }

  if (extension->HasAccessToAllHosts()) {
    warnings->push_back(
        l10n_util::GetStringUTF16(IDS_EXTENSION_PROMPT2_WARNING_ALL_HOSTS));
  } else {
    std::set<std::string> hosts = extension->GetEffectiveHostPermissions();
    if (hosts.size() == 1) {
      warnings->push_back(
          l10n_util::GetStringFUTF16(IDS_EXTENSION_PROMPT2_WARNING_1_HOST,
                                     UTF8ToUTF16(*hosts.begin())));
    } else if (hosts.size() == 2) {
      warnings->push_back(
          l10n_util::GetStringFUTF16(IDS_EXTENSION_PROMPT2_WARNING_2_HOSTS,
                                     UTF8ToUTF16(*hosts.begin()),
                                     UTF8ToUTF16(*(++hosts.begin()))));
    } else if (hosts.size() == 3) {
      warnings->push_back(
          l10n_util::GetStringFUTF16(IDS_EXTENSION_PROMPT2_WARNING_3_HOSTS,
                                     UTF8ToUTF16(*hosts.begin()),
                                     UTF8ToUTF16(*(++hosts.begin())),
                                     UTF8ToUTF16(*(++++hosts.begin()))));
    } else if (hosts.size() >= 4) {
      warnings->push_back(
          l10n_util::GetStringFUTF16(
              IDS_EXTENSION_PROMPT2_WARNING_4_OR_MORE_HOSTS,
              UTF8ToUTF16(*hosts.begin()),
              UTF8ToUTF16(*(++hosts.begin())),
              IntToString16(hosts.size() - 2)));
    }
  }

  if (extension->HasEffectiveBrowsingHistoryPermission()) {
    warnings->push_back(
        l10n_util::GetStringUTF16(
            IDS_EXTENSION_PROMPT2_WARNING_BROWSING_HISTORY));
  }

  // TODO(aa): Geolocation, camera/mic, what else?
}

}  // namespace

ExtensionInstallUI::ExtensionInstallUI(Profile* profile)
    : profile_(profile),
      ui_loop_(MessageLoop::current()),
      previous_use_system_theme_(false),
      extension_(NULL),
      delegate_(NULL),
      prompt_type_(NUM_PROMPT_TYPES),
      ALLOW_THIS_IN_INITIALIZER_LIST(tracker_(this)) {}

void ExtensionInstallUI::ConfirmInstall(Delegate* delegate,
                                        Extension* extension) {
  DCHECK(ui_loop_ == MessageLoop::current());
  extension_ = extension;
  delegate_ = delegate;

  // We special-case themes to not show any confirm UI. Instead they are
  // immediately installed, and then we show an infobar (see OnInstallSuccess)
  // to allow the user to revert if they don't like it.
  if (extension->IsTheme()) {
    // Remember the current theme in case the user pressed undo.
    Extension* previous_theme = profile_->GetTheme();
    if (previous_theme)
      previous_theme_id_ = previous_theme->id();

#if defined(TOOLKIT_GTK)
    // On Linux, we also need to take the user's system settings into account
    // to undo theme installation.
    previous_use_system_theme_ =
        GtkThemeProvider::GetFrom(profile_)->UseGtkTheme();
#else
    DCHECK(!previous_use_system_theme_);
#endif

    delegate->InstallUIProceed(false);
    return;
  }

  ShowConfirmation(INSTALL_PROMPT);
}

void ExtensionInstallUI::ConfirmUninstall(Delegate* delegate,
                                          Extension* extension) {
  DCHECK(ui_loop_ == MessageLoop::current());
  extension_ = extension;
  delegate_ = delegate;

  ShowConfirmation(UNINSTALL_PROMPT);
}

void ExtensionInstallUI::OnInstallSuccess(Extension* extension) {
  if (extension->IsTheme()) {
    ShowThemeInfoBar(previous_theme_id_, previous_use_system_theme_,
                     extension, profile_);
    return;
  }

  if (extension->GetFullLaunchURL().is_valid()) {
    Browser::OpenApplicationTab(profile_, extension);
    return;
  }

  // GetLastActiveWithProfile will fail on the build bots. This needs to be
  // implemented differently if any test is created which depends on
  // ExtensionInstalledBubble showing.
  Browser* browser = BrowserList::GetLastActiveWithProfile(profile_);

#if defined(TOOLKIT_VIEWS)
  if (!browser)
    return;

  ExtensionInstalledBubble::Show(extension, browser, icon_);
#elif defined(OS_MACOSX)
  DCHECK(browser);
  // Note that browser actions don't appear in incognito mode initially,
  // so fall back to the generic case.
  if ((extension->browser_action() && !browser->profile()->IsOffTheRecord()) ||
      (extension->page_action() &&
      !extension->page_action()->default_icon_path().empty())) {
    ExtensionInstalledBubbleCocoa::ShowExtensionInstalledBubble(
        browser->window()->GetNativeHandle(),
        extension, browser, icon_);
  }  else {
    // If the extension is of type GENERIC, meaning it doesn't have a UI
    // surface to display for this window, launch infobar instead of popup
    // bubble, because we have no guaranteed wrench menu button to point to.
    ShowGenericExtensionInstalledInfoBar(extension);
  }
#elif defined(TOOLKIT_GTK)
  if (!browser)
    return;
  ExtensionInstalledBubbleGtk::Show(extension, browser, icon_);
#endif  // TOOLKIT_VIEWS
}

void ExtensionInstallUI::OnInstallFailure(const std::string& error) {
  DCHECK(ui_loop_ == MessageLoop::current());

  Browser* browser = BrowserList::GetLastActiveWithProfile(profile_);
  platform_util::SimpleErrorBox(
      browser ? browser->window()->GetNativeHandle() : NULL,
      l10n_util::GetStringUTF16(IDS_EXTENSION_INSTALL_FAILURE_TITLE),
      UTF8ToUTF16(error));
}

void ExtensionInstallUI::OnOverinstallAttempted(Extension* extension) {
  ShowThemeInfoBar(previous_theme_id_, previous_use_system_theme_,
                   extension, profile_);
}

void ExtensionInstallUI::OnImageLoaded(
    SkBitmap* image, ExtensionResource resource, int index) {
  if (image)
    icon_ = *image;
  else
    icon_ = SkBitmap();
  if (icon_.empty()) {
    icon_ = *ResourceBundle::GetSharedInstance().GetBitmapNamed(
        IDR_EXTENSION_DEFAULT_ICON);
  }

  switch (prompt_type_) {
    case INSTALL_PROMPT: {
      NotificationService* service = NotificationService::current();
      service->Notify(NotificationType::EXTENSION_WILL_SHOW_CONFIRM_DIALOG,
          Source<ExtensionInstallUI>(this),
          NotificationService::NoDetails());

      std::vector<string16> warnings;
      GetV2Warnings(extension_, &warnings);
      ShowExtensionInstallUIPrompt2Impl(
          profile_, delegate_, extension_, &icon_, warnings);
      break;
    }
    case UNINSTALL_PROMPT: {
      string16 message =
          l10n_util::GetStringUTF16(IDS_EXTENSION_UNINSTALL_CONFIRMATION);
      ShowExtensionInstallUIPromptImpl(profile_, delegate_, extension_, &icon_,
          message, UNINSTALL_PROMPT);
      break;
    }
    default:
      NOTREACHED() << "Unknown message";
      break;
  }
}

void ExtensionInstallUI::ShowThemeInfoBar(
    const std::string& previous_theme_id, bool previous_use_system_theme,
    Extension* new_theme, Profile* profile) {
  if (!new_theme->IsTheme())
    return;

  Browser* browser = BrowserList::GetLastActiveWithProfile(profile);
  if (!browser)
    return;

  TabContents* tab_contents = browser->GetSelectedTabContents();
  if (!tab_contents)
    return;

  // First find any previous theme preview infobars.
  InfoBarDelegate* old_delegate = NULL;
  for (int i = 0; i < tab_contents->infobar_delegate_count(); ++i) {
    InfoBarDelegate* delegate = tab_contents->GetInfoBarDelegateAt(i);
    if (delegate->AsThemePreviewInfobarDelegate()) {
      old_delegate = delegate;
      break;
    }
  }

  // Then either replace that old one or add a new one.
  InfoBarDelegate* new_delegate =
      GetNewThemeInstalledInfoBarDelegate(
          tab_contents, new_theme,
          previous_theme_id, previous_use_system_theme);

  if (old_delegate)
    tab_contents->ReplaceInfoBar(old_delegate, new_delegate);
  else
    tab_contents->AddInfoBar(new_delegate);
}

void ExtensionInstallUI::ShowConfirmation(PromptType prompt_type) {
  // Load the image asynchronously. For the response, check OnImageLoaded.
  prompt_type_ = prompt_type;
  ExtensionResource image =
      extension_->GetIconPath(Extension::EXTENSION_ICON_LARGE);
  tracker_.LoadImage(extension_, image,
                     gfx::Size(Extension::EXTENSION_ICON_LARGE,
                               Extension::EXTENSION_ICON_LARGE),
                     ImageLoadingTracker::DONT_CACHE);
}

#if defined(OS_MACOSX)
void ExtensionInstallUI::ShowGenericExtensionInstalledInfoBar(
    Extension* new_extension) {
  Browser* browser = BrowserList::GetLastActiveWithProfile(profile_);
  if (!browser)
    return;

  TabContents* tab_contents = browser->GetSelectedTabContents();
  if (!tab_contents)
    return;

  std::wstring msg = l10n_util::GetStringF(IDS_EXTENSION_INSTALLED_HEADING,
                                           UTF8ToWide(new_extension->name())) +
         L" " + l10n_util::GetString(IDS_EXTENSION_INSTALLED_MANAGE_INFO_MAC);
  InfoBarDelegate* delegate = new SimpleAlertInfoBarDelegate(
      tab_contents, msg, new SkBitmap(icon_), true);
  tab_contents->AddInfoBar(delegate);
}
#endif

InfoBarDelegate* ExtensionInstallUI::GetNewThemeInstalledInfoBarDelegate(
    TabContents* tab_contents, Extension* new_theme,
    const std::string& previous_theme_id, bool previous_use_system_theme) {
#if defined(TOOLKIT_GTK)
  return new GtkThemeInstalledInfoBarDelegate(tab_contents, new_theme,
      previous_theme_id, previous_use_system_theme);
#else
  return new ThemeInstalledInfoBarDelegate(tab_contents, new_theme,
      previous_theme_id);
#endif
}
<|endoftext|>


<commit_before>//..............................................................................
//
//  This file is part of the Jancy toolkit.
//
//  Jancy is distributed under the MIT license.
//  For details see accompanying license.txt file,
//  the public copy of which is also available at:
//  http://tibbo.com/downloads/archive/jancy/license.txt
//
//..............................................................................

#include "pch.h"
#include "jnc_ct_AttributeBlock.h"
#include "jnc_ct_Module.h"

namespace jnc {
namespace ct {

//..............................................................................

bool
Attribute::parseInitializer()
{
	ASSERT(!m_initializer.isEmpty());

	Unit* prevUnit = m_module->m_unitMgr.setCurrentUnit(m_parentUnit);
	bool result = m_module->m_operatorMgr.parseConstExpression(m_initializer, &m_value);
	if (!result)
		return false;

	m_module->m_unitMgr.setCurrentUnit(prevUnit);
	return true;
}

//..............................................................................

Attribute*
AttributeBlock::createAttribute(
	const sl::StringRef& name,
	sl::BoxList<Token>* initializer
	)
{
	sl::StringHashTableIterator<Attribute*> it = m_attributeMap.visit(name);
	if (it->m_value)
	{
		err::setFormatStringError("redefinition of attribute '%s'", name.sz());
		return NULL;
	}

	Attribute* attribute = AXL_MEM_NEW(Attribute);
	attribute->m_module = m_module;
	attribute->m_name = name;

	if (initializer)
		sl::takeOver(&attribute->m_initializer, initializer);

	m_attributeList.insertTail(attribute);
	m_attributeArray.append(attribute);
	it->m_value = attribute;
	return attribute;
}

bool
AttributeBlock::prepareAttributeValues()
{
	ASSERT(!(m_flags & AttributeBlockFlag_ValuesReady));

	size_t count = m_attributeArray.getCount();
	for (size_t i = 0; i < count; i++)
	{
		Attribute* attribute = m_attributeArray[i];
		if (attribute->hasInitializer())
		{
			bool result = attribute->parseInitializer();
			if (!result)
				return false;
		}
	}

	m_flags |= AttributeBlockFlag_ValuesReady;
	return true;
}

//..............................................................................

} // namespace ct
} // namespace jnc
<commit_msg>[jnc_ct] ensure layout for function attribute values<commit_after>//..............................................................................
//
//  This file is part of the Jancy toolkit.
//
//  Jancy is distributed under the MIT license.
//  For details see accompanying license.txt file,
//  the public copy of which is also available at:
//  http://tibbo.com/downloads/archive/jancy/license.txt
//
//..............................................................................

#include "pch.h"
#include "jnc_ct_AttributeBlock.h"
#include "jnc_ct_Module.h"

namespace jnc {
namespace ct {

//..............................................................................

bool
Attribute::parseInitializer()
{
	ASSERT(!m_initializer.isEmpty());

	Unit* prevUnit = m_module->m_unitMgr.setCurrentUnit(m_parentUnit);
	bool result = m_module->m_operatorMgr.parseConstExpression(m_initializer, &m_value);
	if (!result)
		return false;

	if (m_value.getValueKind() == ValueKind_Function)
	{
		result = m_value.getFunction()->getType()->getFunctionPtrType(FunctionPtrTypeKind_Thin)->ensureLayout();
		if (!result)
			return false;
	}

	m_module->m_unitMgr.setCurrentUnit(prevUnit);
	return true;
}

//..............................................................................

Attribute*
AttributeBlock::createAttribute(
	const sl::StringRef& name,
	sl::BoxList<Token>* initializer
	)
{
	sl::StringHashTableIterator<Attribute*> it = m_attributeMap.visit(name);
	if (it->m_value)
	{
		err::setFormatStringError("redefinition of attribute '%s'", name.sz());
		return NULL;
	}

	Attribute* attribute = AXL_MEM_NEW(Attribute);
	attribute->m_module = m_module;
	attribute->m_name = name;

	if (initializer)
		sl::takeOver(&attribute->m_initializer, initializer);

	m_attributeList.insertTail(attribute);
	m_attributeArray.append(attribute);
	it->m_value = attribute;
	return attribute;
}

bool
AttributeBlock::prepareAttributeValues()
{
	ASSERT(!(m_flags & AttributeBlockFlag_ValuesReady));

	size_t count = m_attributeArray.getCount();
	for (size_t i = 0; i < count; i++)
	{
		Attribute* attribute = m_attributeArray[i];
		if (attribute->hasInitializer())
		{
			bool result = attribute->parseInitializer();
			if (!result)
				return false;
		}
	}

	m_flags |= AttributeBlockFlag_ValuesReady;
	return true;
}

//..............................................................................

} // namespace ct
} // namespace jnc
<|endoftext|>


<commit_before>// Copyright (c) 2009 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/extensions/extension_install_ui.h"

#include <map>

#include "app/l10n_util.h"
#include "app/resource_bundle.h"
#include "base/file_util.h"
#include "base/rand_util.h"
#include "chrome/browser/browser_list.h"
#include "chrome/browser/browser_window.h"
#include "chrome/browser/extensions/theme_installed_infobar_delegate.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/common/extensions/extension.h"
#include "grit/browser_resources.h"
#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"

#if defined(OS_WIN)
#include "app/win_util.h"
#elif defined(OS_MACOSX)
#include "base/scoped_cftyperef.h"
#include "base/sys_string_conversions.h"
#include <CoreFoundation/CFUserNotification.h>
#elif defined(TOOLKIT_GTK)
#include "chrome/browser/extensions/gtk_theme_installed_infobar_delegate.h"
#include "chrome/browser/gtk/gtk_theme_provider.h"
#endif

namespace {

#if defined(OS_WIN) || defined(TOOLKIT_GTK)

static std::wstring GetInstallWarning(Extension* extension) {
  // If the extension has a plugin, it's easy: the plugin has the most severe
  // warning.
  if (!extension->plugins().empty())
    return l10n_util::GetString(IDS_EXTENSION_PROMPT_WARNING_NEW_FULL_ACCESS);

  // Otherwise, we go in descending order of severity: all hosts, several hosts,
  // a single host, no hosts. For each of these, we also have a variation of the
  // message for when api permissions are also requested.
  if (extension->HasAccessToAllHosts()) {
    if (extension->api_permissions().empty())
      return l10n_util::GetString(IDS_EXTENSION_PROMPT_WARNING_NEW_ALL_HOSTS);
    else
      return l10n_util::GetString(
          IDS_EXTENSION_PROMPT_WARNING_NEW_ALL_HOSTS_AND_BROWSER);
  }

  const std::set<std::string> hosts = extension->GetEffectiveHostPermissions();
  if (hosts.size() > 1) {
    if (extension->api_permissions().empty())
      return l10n_util::GetString(
          IDS_EXTENSION_PROMPT_WARNING_NEW_MULTIPLE_HOSTS);
    else
      return l10n_util::GetString(
          IDS_EXTENSION_PROMPT_WARNING_NEW_MULTIPLE_HOSTS_AND_BROWSER);
  }

  if (hosts.size() == 1) {
    if (extension->api_permissions().empty())
      return l10n_util::GetStringF(
          IDS_EXTENSION_PROMPT_WARNING_NEW_SINGLE_HOST,
          UTF8ToWide(*hosts.begin()));
    else
      return l10n_util::GetStringF(
          IDS_EXTENSION_PROMPT_WARNING_NEW_SINGLE_HOST_AND_BROWSER,
          UTF8ToWide(*hosts.begin()));
  }

  DCHECK(hosts.size() == 0);
  if (extension->api_permissions().empty())
    return L"";
  else
    return l10n_util::GetString(IDS_EXTENSION_PROMPT_WARNING_NEW_BROWSER);
}

#endif

}  // namespace

ExtensionInstallUI::ExtensionInstallUI(Profile* profile)
    : profile_(profile), ui_loop_(MessageLoop::current())
#if defined(TOOLKIT_GTK)
    ,previous_use_gtk_theme_(false)
#endif
{
}

void ExtensionInstallUI::ConfirmInstall(Delegate* delegate,
                                        Extension* extension,
                                        SkBitmap* install_icon) {
  DCHECK(ui_loop_ == MessageLoop::current());

  // We special-case themes to not show any confirm UI. Instead they are
  // immediately installed, and then we show an infobar (see OnInstallSuccess)
  // to allow the user to revert if they don't like it.
  if (extension->IsTheme()) {
    // Remember the current theme in case the user pressed undo.
    Extension* previous_theme = profile_->GetTheme();
    if (previous_theme)
      previous_theme_id_ = previous_theme->id();

#if defined(TOOLKIT_GTK)
    // On linux, we also need to take the user's system settings into account
    // to undo theme installation.
    previous_use_gtk_theme_ =
        GtkThemeProvider::GetFrom(profile_)->UseGtkTheme();
#endif

    delegate->ContinueInstall();
    return;
  }

#if defined(OS_WIN) || defined(TOOLKIT_GTK)
  if (!install_icon) {
    install_icon = ResourceBundle::GetSharedInstance().GetBitmapNamed(
        IDR_DEFAULT_EXTENSION_ICON_128);
  }

  ShowExtensionInstallPrompt(profile_, delegate, extension, install_icon,
                             GetInstallWarning(extension));

#elif defined(OS_MACOSX)
  // TODO(port): Implement nicer UI.
  // Using CoreFoundation to do this dialog is unimaginably lame but will do
  // until the UI is redone.
  scoped_cftyperef<CFStringRef> confirm_title(base::SysWideToCFStringRef(
      l10n_util::GetString(IDS_EXTENSION_PROMPT_TITLE)));

  // Build the confirmation prompt, including a heading, a random humorous
  // warning, and a severe warning.
  const string16& confirm_format(ASCIIToUTF16("$1\n\n$2\n\n$3"));
  std::vector<string16> subst;
  subst.push_back(l10n_util::GetStringFUTF16(IDS_EXTENSION_PROMPT_HEADING,
      UTF8ToUTF16(extension->name())));
  string16 warnings[] = {
    l10n_util::GetStringUTF16(IDS_EXTENSION_PROMPT_WARNING_1),
    l10n_util::GetStringUTF16(IDS_EXTENSION_PROMPT_WARNING_2),
    l10n_util::GetStringUTF16(IDS_EXTENSION_PROMPT_WARNING_3)
  };
  subst.push_back(warnings[base::RandInt(0, arraysize(warnings) - 1)]);
  subst.push_back(l10n_util::GetStringUTF16(
      IDS_EXTENSION_PROMPT_WARNING_SEVERE));
  scoped_cftyperef<CFStringRef> confirm_prompt(base::SysUTF16ToCFStringRef(
      ReplaceStringPlaceholders(confirm_format, subst, NULL)));

  scoped_cftyperef<CFStringRef> confirm_cancel(base::SysWideToCFStringRef(
      l10n_util::GetString(IDS_EXTENSION_PROMPT_CANCEL_BUTTON)));

  CFOptionFlags response;
  if (kCFUserNotificationAlternateResponse == CFUserNotificationDisplayAlert(
      0, kCFUserNotificationCautionAlertLevel,
      NULL, // TODO(port): show the install_icon instead of a default.
      NULL, NULL, // Sound URL, localization URL.
      confirm_title,
      confirm_prompt,
      NULL, // Default button.
      confirm_cancel,
      NULL, // Other button.
      &response)) {
    delegate->AbortInstall();
  } else {
    delegate->ContinueInstall();
  }
#else
  // TODO(port): Implement some UI.
  NOTREACHED();
  delegate->ContinueInstall();
#endif  // OS_*
}

void ExtensionInstallUI::OnInstallSuccess(Extension* extension) {
  ShowThemeInfoBar(extension);
}

void ExtensionInstallUI::OnInstallFailure(const std::string& error) {
  DCHECK(ui_loop_ == MessageLoop::current());

#if defined(OS_WIN)
  win_util::MessageBox(NULL, UTF8ToWide(error), L"Extension Install Error",
      MB_OK | MB_SETFOREGROUND);
#elif defined(OS_MACOSX)
  // There must be a better way to do this, for all platforms.
  scoped_cftyperef<CFStringRef> message_cf(
      base::SysUTF8ToCFStringRef(error));
  CFOptionFlags response;
  CFUserNotificationDisplayAlert(
      0, kCFUserNotificationNoteAlertLevel, NULL, NULL, NULL,
      CFSTR("Extension Install Error"), message_cf,
      NULL, NULL, NULL, &response);
#else
  GtkWidget* dialog = gtk_message_dialog_new(NULL, GTK_DIALOG_MODAL,
      GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "%s", error.c_str());
  gtk_dialog_run(GTK_DIALOG(dialog));
  gtk_widget_destroy(dialog);
#endif
}

void ExtensionInstallUI::OnOverinstallAttempted(Extension* extension) {
  ShowThemeInfoBar(extension);
}

void ExtensionInstallUI::ShowThemeInfoBar(Extension* new_theme) {
  if (!new_theme->IsTheme())
    return;

  Browser* browser = BrowserList::GetLastActiveWithProfile(profile_);
  if (!browser)
    return;

  TabContents* tab_contents = browser->GetSelectedTabContents();
  if (!tab_contents)
    return;

  // First find any previous theme preview infobars.
  InfoBarDelegate* old_delegate = NULL;
  for (int i = 0; i < tab_contents->infobar_delegate_count(); ++i) {
    InfoBarDelegate* delegate = tab_contents->GetInfoBarDelegateAt(i);
    if (delegate->AsThemePreviewInfobarDelegate()) {
      old_delegate = delegate;
      break;
    }
  }

  // Then either replace that old one or add a new one.
  InfoBarDelegate* new_delegate =
#if defined(TOOLKIT_GTK)
      new GtkThemeInstalledInfoBarDelegate(
          tab_contents,
          new_theme->name(), previous_theme_id_, previous_use_gtk_theme_);
#else
      new ThemeInstalledInfoBarDelegate(tab_contents,
                                        new_theme->name(), previous_theme_id_);
#endif

  if (old_delegate)
    tab_contents->ReplaceInfoBar(old_delegate, new_delegate);
  else
    tab_contents->AddInfoBar(new_delegate);
}
<commit_msg>Fix extension canceling; the CFUserNotification functionality gets a bit weird.<commit_after>// Copyright (c) 2009 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/extensions/extension_install_ui.h"

#include <map>

#include "app/l10n_util.h"
#include "app/resource_bundle.h"
#include "base/file_util.h"
#include "base/rand_util.h"
#include "chrome/browser/browser_list.h"
#include "chrome/browser/browser_window.h"
#include "chrome/browser/extensions/theme_installed_infobar_delegate.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/common/extensions/extension.h"
#include "grit/browser_resources.h"
#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"

#if defined(OS_WIN)
#include "app/win_util.h"
#elif defined(OS_MACOSX)
#include "base/scoped_cftyperef.h"
#include "base/sys_string_conversions.h"
#include <CoreFoundation/CFUserNotification.h>
#elif defined(TOOLKIT_GTK)
#include "chrome/browser/extensions/gtk_theme_installed_infobar_delegate.h"
#include "chrome/browser/gtk/gtk_theme_provider.h"
#endif

namespace {

#if defined(OS_WIN) || defined(TOOLKIT_GTK)

static std::wstring GetInstallWarning(Extension* extension) {
  // If the extension has a plugin, it's easy: the plugin has the most severe
  // warning.
  if (!extension->plugins().empty())
    return l10n_util::GetString(IDS_EXTENSION_PROMPT_WARNING_NEW_FULL_ACCESS);

  // Otherwise, we go in descending order of severity: all hosts, several hosts,
  // a single host, no hosts. For each of these, we also have a variation of the
  // message for when api permissions are also requested.
  if (extension->HasAccessToAllHosts()) {
    if (extension->api_permissions().empty())
      return l10n_util::GetString(IDS_EXTENSION_PROMPT_WARNING_NEW_ALL_HOSTS);
    else
      return l10n_util::GetString(
          IDS_EXTENSION_PROMPT_WARNING_NEW_ALL_HOSTS_AND_BROWSER);
  }

  const std::set<std::string> hosts = extension->GetEffectiveHostPermissions();
  if (hosts.size() > 1) {
    if (extension->api_permissions().empty())
      return l10n_util::GetString(
          IDS_EXTENSION_PROMPT_WARNING_NEW_MULTIPLE_HOSTS);
    else
      return l10n_util::GetString(
          IDS_EXTENSION_PROMPT_WARNING_NEW_MULTIPLE_HOSTS_AND_BROWSER);
  }

  if (hosts.size() == 1) {
    if (extension->api_permissions().empty())
      return l10n_util::GetStringF(
          IDS_EXTENSION_PROMPT_WARNING_NEW_SINGLE_HOST,
          UTF8ToWide(*hosts.begin()));
    else
      return l10n_util::GetStringF(
          IDS_EXTENSION_PROMPT_WARNING_NEW_SINGLE_HOST_AND_BROWSER,
          UTF8ToWide(*hosts.begin()));
  }

  DCHECK(hosts.size() == 0);
  if (extension->api_permissions().empty())
    return L"";
  else
    return l10n_util::GetString(IDS_EXTENSION_PROMPT_WARNING_NEW_BROWSER);
}

#endif

}  // namespace

ExtensionInstallUI::ExtensionInstallUI(Profile* profile)
    : profile_(profile), ui_loop_(MessageLoop::current())
#if defined(TOOLKIT_GTK)
    ,previous_use_gtk_theme_(false)
#endif
{
}

void ExtensionInstallUI::ConfirmInstall(Delegate* delegate,
                                        Extension* extension,
                                        SkBitmap* install_icon) {
  DCHECK(ui_loop_ == MessageLoop::current());

  // We special-case themes to not show any confirm UI. Instead they are
  // immediately installed, and then we show an infobar (see OnInstallSuccess)
  // to allow the user to revert if they don't like it.
  if (extension->IsTheme()) {
    // Remember the current theme in case the user pressed undo.
    Extension* previous_theme = profile_->GetTheme();
    if (previous_theme)
      previous_theme_id_ = previous_theme->id();

#if defined(TOOLKIT_GTK)
    // On linux, we also need to take the user's system settings into account
    // to undo theme installation.
    previous_use_gtk_theme_ =
        GtkThemeProvider::GetFrom(profile_)->UseGtkTheme();
#endif

    delegate->ContinueInstall();
    return;
  }

#if defined(OS_WIN) || defined(TOOLKIT_GTK)
  if (!install_icon) {
    install_icon = ResourceBundle::GetSharedInstance().GetBitmapNamed(
        IDR_DEFAULT_EXTENSION_ICON_128);
  }

  ShowExtensionInstallPrompt(profile_, delegate, extension, install_icon,
                             GetInstallWarning(extension));

#elif defined(OS_MACOSX)
  // TODO(port): Implement nicer UI.
  // Using CoreFoundation to do this dialog is unimaginably lame but will do
  // until the UI is redone.
  scoped_cftyperef<CFStringRef> confirm_title(base::SysWideToCFStringRef(
      l10n_util::GetString(IDS_EXTENSION_PROMPT_TITLE)));

  // Build the confirmation prompt, including a heading, a random humorous
  // warning, and a severe warning.
  const string16& confirm_format(ASCIIToUTF16("$1\n\n$2\n\n$3"));
  std::vector<string16> subst;
  subst.push_back(l10n_util::GetStringFUTF16(IDS_EXTENSION_PROMPT_HEADING,
      UTF8ToUTF16(extension->name())));
  string16 warnings[] = {
    l10n_util::GetStringUTF16(IDS_EXTENSION_PROMPT_WARNING_1),
    l10n_util::GetStringUTF16(IDS_EXTENSION_PROMPT_WARNING_2),
    l10n_util::GetStringUTF16(IDS_EXTENSION_PROMPT_WARNING_3)
  };
  subst.push_back(warnings[base::RandInt(0, arraysize(warnings) - 1)]);
  subst.push_back(l10n_util::GetStringUTF16(
      IDS_EXTENSION_PROMPT_WARNING_SEVERE));
  scoped_cftyperef<CFStringRef> confirm_prompt(base::SysUTF16ToCFStringRef(
      ReplaceStringPlaceholders(confirm_format, subst, NULL)));

  scoped_cftyperef<CFStringRef> confirm_cancel(base::SysWideToCFStringRef(
      l10n_util::GetString(IDS_EXTENSION_PROMPT_CANCEL_BUTTON)));

  CFOptionFlags response;
  CFUserNotificationDisplayAlert(
      0, kCFUserNotificationCautionAlertLevel,
      NULL, // TODO(port): show the install_icon instead of a default.
      NULL, NULL, // Sound URL, localization URL.
      confirm_title,
      confirm_prompt,
      NULL, // Default button.
      confirm_cancel,
      NULL, // Other button.
      &response);
  if (response == kCFUserNotificationAlternateResponse) {
    delegate->AbortInstall();
  } else {
    delegate->ContinueInstall();
  }
#else
  // TODO(port): Implement some UI.
  NOTREACHED();
  delegate->ContinueInstall();
#endif  // OS_*
}

void ExtensionInstallUI::OnInstallSuccess(Extension* extension) {
  ShowThemeInfoBar(extension);
}

void ExtensionInstallUI::OnInstallFailure(const std::string& error) {
  DCHECK(ui_loop_ == MessageLoop::current());

#if defined(OS_WIN)
  win_util::MessageBox(NULL, UTF8ToWide(error), L"Extension Install Error",
      MB_OK | MB_SETFOREGROUND);
#elif defined(OS_MACOSX)
  // There must be a better way to do this, for all platforms.
  scoped_cftyperef<CFStringRef> message_cf(
      base::SysUTF8ToCFStringRef(error));
  CFOptionFlags response;
  CFUserNotificationDisplayAlert(
      0, kCFUserNotificationNoteAlertLevel, NULL, NULL, NULL,
      CFSTR("Extension Install Error"), message_cf,
      NULL, NULL, NULL, &response);
#else
  GtkWidget* dialog = gtk_message_dialog_new(NULL, GTK_DIALOG_MODAL,
      GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "%s", error.c_str());
  gtk_dialog_run(GTK_DIALOG(dialog));
  gtk_widget_destroy(dialog);
#endif
}

void ExtensionInstallUI::OnOverinstallAttempted(Extension* extension) {
  ShowThemeInfoBar(extension);
}

void ExtensionInstallUI::ShowThemeInfoBar(Extension* new_theme) {
  if (!new_theme->IsTheme())
    return;

  Browser* browser = BrowserList::GetLastActiveWithProfile(profile_);
  if (!browser)
    return;

  TabContents* tab_contents = browser->GetSelectedTabContents();
  if (!tab_contents)
    return;

  // First find any previous theme preview infobars.
  InfoBarDelegate* old_delegate = NULL;
  for (int i = 0; i < tab_contents->infobar_delegate_count(); ++i) {
    InfoBarDelegate* delegate = tab_contents->GetInfoBarDelegateAt(i);
    if (delegate->AsThemePreviewInfobarDelegate()) {
      old_delegate = delegate;
      break;
    }
  }

  // Then either replace that old one or add a new one.
  InfoBarDelegate* new_delegate =
#if defined(TOOLKIT_GTK)
      new GtkThemeInstalledInfoBarDelegate(
          tab_contents,
          new_theme->name(), previous_theme_id_, previous_use_gtk_theme_);
#else
      new ThemeInstalledInfoBarDelegate(tab_contents,
                                        new_theme->name(), previous_theme_id_);
#endif

  if (old_delegate)
    tab_contents->ReplaceInfoBar(old_delegate, new_delegate);
  else
    tab_contents->AddInfoBar(new_delegate);
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: iconcache.cxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: obo $ $Date: 2005-04-20 11:42:13 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <msiquery.h>

#include <stdlib.h>

extern "C" UINT __stdcall RebuildShellIconCache(MSIHANDLE handle)
{
    // Rebuild icon cache on windows OS prior XP

    OSVERSIONINFO   osverinfo;

    osverinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);

    if (
        GetVersionEx( &osverinfo ) &&
        VER_PLATFORM_WIN32_NT == osverinfo.dwPlatformId &&
        (
        5 < osverinfo.dwMajorVersion ||
        5 == osverinfo.dwMajorVersion && 0 < osverinfo.dwMinorVersion
        )
        )
    {
        return ERROR_SUCCESS;
    }

    HKEY    hKey;
    DWORD   dwDispostion;
    LONG    lError = RegCreateKeyEx( HKEY_CURRENT_USER, TEXT("Control Panel\\Desktop\\WindowMetrics"), 0, NULL, REG_OPTION_VOLATILE, KEY_SET_VALUE | KEY_QUERY_VALUE, NULL, &hKey, &dwDispostion );

    if ( ERROR_SUCCESS == lError )
    {
        TCHAR   szValue[256];
        TCHAR   szTempValue[256];
        DWORD   cbValue = sizeof(szValue);
        DWORD   dwType;
        int     iSize = 0;

        lError = RegQueryValueEx( hKey, TEXT("Shell Icon Size"), 0, &dwType, (LPBYTE)szValue, &cbValue );

        if ( ERROR_SUCCESS == lError )
            iSize = atoi( szValue );

        if ( !iSize )
        {
            iSize = GetSystemMetrics( SM_CXICON );
            itoa( iSize, szValue, 10 );
            cbValue = strlen( szValue ) + 1;
            dwType = REG_SZ;
        }

        itoa( iSize + 1, szTempValue, 10 );
        lError = RegSetValueEx( hKey, TEXT("Shell Icon Size"), 0, dwType, (LPBYTE)szTempValue, strlen( szTempValue ) + 1 );

        LRESULT lResult = SendMessageTimeout(
             HWND_BROADCAST,
             WM_SETTINGCHANGE,
             SPI_SETNONCLIENTMETRICS,
             (LPARAM)TEXT("WindowMetrics"),
             SMTO_NORMAL|SMTO_ABORTIFHUNG,
             0, NULL);

        lError = RegSetValueEx( hKey, TEXT("Shell Icon Size"), 0, dwType, (LPBYTE)szValue, cbValue );

        lResult = SendMessageTimeout(
             HWND_BROADCAST,
             WM_SETTINGCHANGE,
             SPI_SETNONCLIENTMETRICS,
             (LPARAM)TEXT("WindowMetrics"),
             SMTO_NORMAL|SMTO_ABORTIFHUNG,
             0, NULL);

        lError = RegCloseKey( hKey );
    }

    return ERROR_SUCCESS;
}
<commit_msg>INTEGRATION: CWS ooo19126 (1.2.44); FILE MERGED 2005/09/05 17:36:45 rt 1.2.44.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: iconcache.cxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-07 16:39:53 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <msiquery.h>

#include <stdlib.h>

extern "C" UINT __stdcall RebuildShellIconCache(MSIHANDLE handle)
{
    // Rebuild icon cache on windows OS prior XP

    OSVERSIONINFO   osverinfo;

    osverinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);

    if (
        GetVersionEx( &osverinfo ) &&
        VER_PLATFORM_WIN32_NT == osverinfo.dwPlatformId &&
        (
        5 < osverinfo.dwMajorVersion ||
        5 == osverinfo.dwMajorVersion && 0 < osverinfo.dwMinorVersion
        )
        )
    {
        return ERROR_SUCCESS;
    }

    HKEY    hKey;
    DWORD   dwDispostion;
    LONG    lError = RegCreateKeyEx( HKEY_CURRENT_USER, TEXT("Control Panel\\Desktop\\WindowMetrics"), 0, NULL, REG_OPTION_VOLATILE, KEY_SET_VALUE | KEY_QUERY_VALUE, NULL, &hKey, &dwDispostion );

    if ( ERROR_SUCCESS == lError )
    {
        TCHAR   szValue[256];
        TCHAR   szTempValue[256];
        DWORD   cbValue = sizeof(szValue);
        DWORD   dwType;
        int     iSize = 0;

        lError = RegQueryValueEx( hKey, TEXT("Shell Icon Size"), 0, &dwType, (LPBYTE)szValue, &cbValue );

        if ( ERROR_SUCCESS == lError )
            iSize = atoi( szValue );

        if ( !iSize )
        {
            iSize = GetSystemMetrics( SM_CXICON );
            itoa( iSize, szValue, 10 );
            cbValue = strlen( szValue ) + 1;
            dwType = REG_SZ;
        }

        itoa( iSize + 1, szTempValue, 10 );
        lError = RegSetValueEx( hKey, TEXT("Shell Icon Size"), 0, dwType, (LPBYTE)szTempValue, strlen( szTempValue ) + 1 );

        LRESULT lResult = SendMessageTimeout(
             HWND_BROADCAST,
             WM_SETTINGCHANGE,
             SPI_SETNONCLIENTMETRICS,
             (LPARAM)TEXT("WindowMetrics"),
             SMTO_NORMAL|SMTO_ABORTIFHUNG,
             0, NULL);

        lError = RegSetValueEx( hKey, TEXT("Shell Icon Size"), 0, dwType, (LPBYTE)szValue, cbValue );

        lResult = SendMessageTimeout(
             HWND_BROADCAST,
             WM_SETTINGCHANGE,
             SPI_SETNONCLIENTMETRICS,
             (LPARAM)TEXT("WindowMetrics"),
             SMTO_NORMAL|SMTO_ABORTIFHUNG,
             0, NULL);

        lError = RegCloseKey( hKey );
    }

    return ERROR_SUCCESS;
}
<|endoftext|>


<commit_before>// Copyright (c) 2014 Jae-jun Kang
// See the file COPYING for license details.

#include "xpiler.hpp"

#include <boost/algorithm/string.hpp>
#include <boost/foreach.hpp>

#include "document.hpp"

#include "boost_formatter.hpp"
#include "xml_handler.hpp"

using namespace std;

namespace fs = boost::filesystem;

namespace xpiler
{
    options xpiler::opts;

    xpiler::handler_map_type xpiler::handlers_;
    xpiler::formatter_map_type xpiler::formatters_;

    xpiler::static_initializer xpiler::static_init_;

    xpiler::xpiler()
    {
        formatter_ = formatters_[opts.spec];
        formatter_->setup();
    }

    void xpiler::process(const string& path)
    {
        if (fs::is_directory(path))
        {
            process_dir(path);
        }
        else if (fs::exists(path))
        {
            process_file(path);
        }
        else
        {
            cout << path << " doesn't exist." << endl;
            error = true;
        }
    }

    void xpiler::process_dir(const fs::path& path)
    {
        cout << "Directory " << fs::canonical(path).string() << endl;

        fs::directory_iterator di(path);
        fs::directory_iterator end;
        for (; di != end; ++di)
        {
            fs::directory_entry& entry = *di;
            fs::path filename = entry.path().filename();

            fs::path pathname = path / filename;
            if (fs::is_directory(entry.status()))
            {
                if (opts.recursive)
                {
                    sub_dirs_.push_back(filename.string());
                    process_dir(pathname);
                    sub_dirs_.pop_back();
                }
            }
            else
            {
                process_file(pathname);
            }
        }
    }

    void xpiler::process_file(const fs::path& path)
    {
        fs::path filename = path.filename();
        string extension = path.extension().string();
        fs::path out_dir;
        if (opts.out_dir.empty())
        {
            out_dir = path.parent_path();
        }
        else
        {
            out_dir = opts.out_dir;
            BOOST_FOREACH(string& sub_dir, sub_dirs_)
            {
                out_dir /= sub_dir;
            }
        }

        boost::algorithm::to_lower(extension);
        handler_map_type::iterator it = handlers_.find(extension);
        if (it == handlers_.end() ||
            (!opts.forced && formatter_->is_up_to_date(path)))
        {
            return;
        }
        handler* handler = it->second;

        cout << filename.string() << endl;

        document* doc;
        if (!handler->handle(path.string(), &doc))
        {
            error = true;
        }
        if (error == true || doc == NULL)
        {
            return;
        }

        doc->basename = filename.stem().string();

        if (!out_dir.empty() && !fs::is_directory(out_dir))
        {
            fs::create_directories(out_dir);
        }

        if (!formatter_->format(doc, out_dir.string()))
        {
            error = true;
        }

        delete doc;
    }

    xpiler::static_initializer::static_initializer()
    {
        handlers_[".xml"] = new xml_handler;
        formatters_["boost"] = new boost_formatter;
    }

    xpiler::static_initializer::~static_initializer()
    {
        BOOST_FOREACH(handler_map_type::value_type& pair, handlers_)
        {
            delete pair.second;
        }
        BOOST_FOREACH(formatter_map_type::value_type& pair, formatters_)
        {
            delete pair.second;
        }
    }
}

// EOF xpiler.cpp
<commit_msg>touched xpiler<commit_after>// Copyright (c) 2014 Jae-jun Kang
// See the file COPYING for license details.

#include "xpiler.hpp"

#include <boost/algorithm/string.hpp>
#include <boost/foreach.hpp>

#include "document.hpp"

#include "boost_formatter.hpp"
#include "xml_handler.hpp"

using namespace std;

namespace fs = boost::filesystem;

namespace xpiler
{
    options xpiler::opts;

    xpiler::handler_map_type xpiler::handlers_;
    xpiler::formatter_map_type xpiler::formatters_;

    xpiler::static_initializer xpiler::static_init_;

    xpiler::xpiler()
    {
        formatter_ = formatters_[opts.spec];
        formatter_->setup();
    }

    void xpiler::process(const string& path)
    {
        if (fs::is_directory(path))
        {
            process_dir(path);
        }
        else if (fs::exists(path))
        {
            process_file(path);
        }
        else
        {
            cout << path << " doesn't exist." << endl;
            error = true;
        }
    }

    void xpiler::process_dir(const fs::path& path)
    {
        cout << "Directory " << fs::canonical(path).string() << endl;

        fs::directory_iterator di(path);
        fs::directory_iterator end;
        for (; di != end; ++di)
        {
            fs::directory_entry& entry = *di;
            fs::path filename = entry.path().filename();

            fs::path pathname = path / filename;
            if (fs::is_directory(entry.status()))
            {
                if (opts.recursive)
                {
                    sub_dirs_.push_back(filename.string());
                    process_dir(pathname);
                    sub_dirs_.pop_back();
                }
            }
            else
            {
                process_file(pathname);
            }
        }
    }

    void xpiler::process_file(const fs::path& path)
    {
        fs::path filename = path.filename();
        string extension = path.extension().string();
        fs::path out_dir;
        if (opts.out_dir.empty())
        {
            out_dir = path.parent_path();
        }
        else
        {
            out_dir = opts.out_dir;
            BOOST_FOREACH(string& sub_dir, sub_dirs_)
            {
                out_dir /= sub_dir;
            }
        }

        boost::algorithm::to_lower(extension);
        handler_map_type::iterator it = handlers_.find(extension);
        if (it == handlers_.end() ||
            (!opts.forced && formatter_->is_up_to_date(path)))
        {
            return;
        }
        handler* handler = it->second;

        document* doc;
        if (!handler->handle(path.string(), &doc))
        {
            error = true;
        }
        if (error == true || doc == NULL)
        {
            return;
        }

        cout << filename.string() << endl;

        doc->basename = filename.stem().string();

        if (!out_dir.empty() && !fs::is_directory(out_dir))
        {
            fs::create_directories(out_dir);
        }

        if (!formatter_->format(doc, out_dir.string()))
        {
            error = true;
        }

        delete doc;
    }

    xpiler::static_initializer::static_initializer()
    {
        handlers_[".xml"] = new xml_handler;
        formatters_["boost"] = new boost_formatter;
    }

    xpiler::static_initializer::~static_initializer()
    {
        BOOST_FOREACH(handler_map_type::value_type& pair, handlers_)
        {
            delete pair.second;
        }
        BOOST_FOREACH(formatter_map_type::value_type& pair, formatters_)
        {
            delete pair.second;
        }
    }
}

// EOF xpiler.cpp
<|endoftext|>


<commit_before>#include <pistache/http_headers.h>
#include <pistache/date.h>

#include "gtest/gtest.h"

#include <algorithm>
#include <chrono>
#include <iostream>

using namespace Pistache::Http;

TEST(headers_test, accept) {
    Header::Accept a1;
    a1.parse("audio/*; q=0.2");

    {
        const auto& media = a1.media();
        ASSERT_EQ(media.size(), 1U);

        const auto& mime = media[0];
        ASSERT_EQ(mime, MIME(Audio, Star));
        ASSERT_EQ(mime.q().getOrElse(Mime::Q(0)), Mime::Q(20));
    }

    Header::Accept a2;
    a2.parse("text/*, text/html, text/html;level=1, */*");

    {
        const auto& media = a2.media();
        ASSERT_EQ(media.size(), 4U);

        const auto &m1 = media[0];
        ASSERT_EQ(m1, MIME(Text, Star));
        const auto &m2 = media[1];
        ASSERT_EQ(m2, MIME(Text, Html));
        const auto& m3 = media[2];
        ASSERT_EQ(m3, MIME(Text, Html));
        auto level = m3.getParam("level");
        ASSERT_EQ(level.getOrElse(""), "1");
        const auto& m4 = media[3];
        ASSERT_EQ(m4, MIME(Star, Star));
    }

    Header::Accept a3;
    a3.parse("text/*;q=0.3, text/html;q=0.7, text/html;level=1, "
             "text/html;level=2;q=0.4, */*;q=0.5");

    {
        const auto& media = a3.media();
        ASSERT_EQ(media.size(), 5U);

        ASSERT_EQ(media[0], MIME(Text, Star));
        ASSERT_EQ(media[0].q().getOrElse(Mime::Q(0)), Mime::Q(30));

        ASSERT_EQ(media[1], MIME(Text, Html));
        ASSERT_EQ(media[2], MIME(Text, Html));
        ASSERT_EQ(media[3], MIME(Text, Html));
        ASSERT_EQ(media[4], MIME(Star, Star));
        ASSERT_EQ(media[4].q().getOrElse(Mime::Q(0)), Mime::Q::fromFloat(0.5));
    }

    Header::Accept a4;
    ASSERT_THROW(a4.parse("text/*;q=0.4, text/html;q=0.3,"), std::runtime_error);

    Header::Accept a5;
    ASSERT_THROW(a5.parse("text/*;q=0.4, text/html;q=0.3, "), std::runtime_error);
}

TEST(headers_test, allow) {
    Header::Allow a1(Method::Get);

    std::ostringstream os;
    a1.write(os);
    ASSERT_EQ(os.str(), "GET");
    os.str("");

    Header::Allow a2({ Method::Post, Method::Put });
    a2.write(os);
    ASSERT_EQ(os.str(), "POST, PUT");
    os.str("");

    Header::Allow a3;
    a3.addMethod(Method::Get);
    a3.write(os);
    ASSERT_EQ(os.str(), "GET");
    os.str("");
    a3.addMethod(Method::Options);
    a3.write(os);
    ASSERT_EQ(os.str(), "GET, OPTIONS");
    os.str("");

    Header::Allow a4(Method::Head);
    a4.addMethods({ Method::Get, Method::Options });
    a4.write(os);
    ASSERT_EQ(os.str(), "HEAD, GET, OPTIONS");
}

TEST(headers_test, cache_control) {
    auto testTrivial = [](std::string str, CacheDirective::Directive expected) {
        Header::CacheControl cc;
        cc.parse(str);

        auto directives = cc.directives();
        ASSERT_EQ(directives.size(), 1U);
        ASSERT_EQ(directives[0].directive(), expected);
    };

    auto testTimed = [](
            std::string str, CacheDirective::Directive expected, uint64_t delta) {
        Header::CacheControl cc;
        cc.parse(str);

        auto directives = cc.directives();
        ASSERT_EQ(directives.size(), 1U);

        ASSERT_EQ(directives[0].directive(), expected);
        ASSERT_EQ(directives[0].delta(), std::chrono::seconds(delta));
    };

    testTrivial("no-cache", CacheDirective::NoCache);
    testTrivial("no-store", CacheDirective::NoStore);
    testTrivial("no-transform", CacheDirective::NoTransform);
    testTrivial("only-if-cached", CacheDirective::OnlyIfCached);

    testTimed("max-age=0", CacheDirective::MaxAge, 0);
    testTimed("max-age=12", CacheDirective::MaxAge, 12);

    testTimed("max-stale=12345", CacheDirective::MaxStale, 12345);
    testTimed("min-fresh=48", CacheDirective::MinFresh, 48);

    Header::CacheControl cc1;
    cc1.parse("private, max-age=600");
    auto d1 = cc1.directives();
    ASSERT_EQ(d1.size(), 2U);
    ASSERT_EQ(d1[0].directive(), CacheDirective::Private);
    ASSERT_EQ(d1[1].directive(), CacheDirective::MaxAge);
    ASSERT_EQ(d1[1].delta(), std::chrono::seconds(600));

    Header::CacheControl cc2;
    cc2.parse("public, s-maxage=200, proxy-revalidate");
    auto d2 = cc2.directives();
    ASSERT_EQ(d2.size(), 3U);
    ASSERT_EQ(d2[0].directive(), CacheDirective::Public);
    ASSERT_EQ(d2[1].directive(), CacheDirective::SMaxAge);
    ASSERT_EQ(d2[1].delta(), std::chrono::seconds(200));
    ASSERT_EQ(d2[2].directive(), CacheDirective::ProxyRevalidate);

    Header::CacheControl cc3(CacheDirective::NoCache);
    std::ostringstream oss;
    cc3.write(oss);
    ASSERT_EQ(oss.str(), "no-cache");
    oss.str("");

    cc3.addDirective(CacheDirective::NoStore);
    cc3.write(oss);
    ASSERT_EQ(oss.str(), "no-cache, no-store");
    oss.str("");

    Header::CacheControl cc4;
    cc4.addDirectives({
            CacheDirective::Public,
            CacheDirective(CacheDirective::MaxAge, std::chrono::seconds(600))
    });
    cc4.write(oss);
    ASSERT_EQ(oss.str(), "public, max-age=600");

}

TEST(headers_test, content_length) {
    Header::ContentLength cl;

    cl.parse("3495");
    ASSERT_EQ(cl.value(), 3495U);
}

TEST(headers_test, connection) {
    Header::Connection connection;

    constexpr struct Test {
        const char *data;
        ConnectionControl expected;
    } tests[] = {
      { "close", ConnectionControl::Close },
      { "clOse", ConnectionControl::Close },
      { "Close", ConnectionControl::Close },
      { "CLOSE", ConnectionControl::Close },

      { "keep-alive", ConnectionControl::KeepAlive },
      { "Keep-Alive", ConnectionControl::KeepAlive },
      { "kEEp-alIvE", ConnectionControl::KeepAlive },
      { "KEEP-ALIVE", ConnectionControl::KeepAlive }
    };

    for (auto test: tests) {
        Header::Connection connection;
        connection.parse(test.data);

        ASSERT_EQ(connection.control(), test.expected);
    }
}

TEST(headers_test, date_test_rfc_1123) {

    using namespace std::chrono;
    FullDate::time_point expected_time_point = date::sys_days(date::year{1994}/11/6)
                                                + hours(8) + minutes(49) + seconds(37);

    /* RFC-1123 */
    Header::Date d1;
    d1.parse("Sun, 06 Nov 1994 08:49:37 GMT");
    auto dd1 = d1.fullDate().date();
    ASSERT_EQ(expected_time_point, dd1);
}

TEST(headers_test, date_test_rfc_850) {

    using namespace std::chrono;
    FullDate::time_point expected_time_point = date::sys_days(date::year{1994}/11/6)
                                                + hours(8) + minutes(49) + seconds(37);

    /* RFC-850 */
    Header::Date d2;
    d2.parse("Sunday, 06-Nov-94 08:49:37 GMT");
    auto dd2 = d2.fullDate().date();
    ASSERT_EQ(dd2, expected_time_point);
}

TEST(headers_test, date_test_asctime) {

    using namespace std::chrono;
    FullDate::time_point expected_time_point = date::sys_days(date::year{1994}/11/6)
                                                + hours(8) + minutes(49) + seconds(37);

    /* ANSI C's asctime format */
    Header::Date d3;
    d3.parse("Sun Nov  6 08:49:37 1994");
    auto dd3 = d3.fullDate().date();
    ASSERT_EQ(dd3, expected_time_point);
}

TEST(headers_test, date_test_ostream) {

    std::ostringstream os;

    Header::Date d4;
    d4.parse("Fri, 25 Jan 2019 21:04:45.000000000 UTC");
    d4.write(os);
    ASSERT_EQ("Fri, 25 Jan 2019 21:04:45.000000000 UTC", os.str());
}

TEST(headers_test, host) {
    Header::Host host;

    host.parse("www.w3.org");
    ASSERT_EQ(host.host(), "www.w3.org");
    ASSERT_EQ(host.port(), 80);

    host.parse("www.example.com:8080");
    ASSERT_EQ(host.host(), "www.example.com");
    ASSERT_EQ(host.port(), 8080);

    host.parse("localhost:8080");
    ASSERT_EQ(host.host(), "localhost");
    ASSERT_EQ(host.port(), 8080);

/* Due to an error in GLIBC these tests don't fail as expected, further research needed */
//     ASSERT_THROW( host.parse("256.256.256.256:8080");, std::invalid_argument);
//     ASSERT_THROW( host.parse("1.0.0.256:8080");, std::invalid_argument);

    host.parse("[::1]:8080");
    ASSERT_EQ(host.host(), "[::1]");
    ASSERT_EQ(host.port(), 8080);

    host.parse("[2001:0DB8:AABB:CCDD:EEFF:0011:2233:4455]:8080");
    ASSERT_EQ(host.host(), "[2001:0DB8:AABB:CCDD:EEFF:0011:2233:4455]");
    ASSERT_EQ(host.port(), 8080);

/* Due to an error in GLIBC these tests don't fail as expected, further research needed */
//     ASSERT_THROW( host.parse("[GGGG:GGGG:GGGG:GGGG:GGGG:GGGG:GGGG:GGGG]:8080");, std::invalid_argument);
//     ASSERT_THROW( host.parse("[::GGGG]:8080");, std::invalid_argument);
}

TEST(headers_test, user_agent) {
    Header::UserAgent ua;

    ua.parse("CERN-LineMode/2.15 libwww/2.17b3");
    ASSERT_EQ(ua.agent(), "CERN-LineMode/2.15 libwww/2.17b3");
}

TEST(headers_test, content_encoding) {
    Header::ContentEncoding ce;

    ce.parse("gzip");
    ASSERT_EQ(ce.encoding(), Header::Encoding::Gzip);
}

TEST(headers_test, content_type) {
    Header::ContentType ct;

    ct.parse("text/html; charset=ISO-8859-4");
    const auto& mime = ct.mime();
    ASSERT_EQ(mime, MIME(Text, Html));
    ASSERT_EQ(mime.getParam("charset").getOrElse(""), "ISO-8859-4");
}

TEST(headers_test, access_control_allow_origin_test)
{
    Header::AccessControlAllowOrigin allowOrigin;

    allowOrigin.parse("http://foo.bar");
    ASSERT_EQ(allowOrigin.uri(), "http://foo.bar");
}

TEST(headers_test, access_control_allow_headers_test)
{
    Header::AccessControlAllowHeaders allowHeaders;

    allowHeaders.parse("Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With");
    ASSERT_EQ(allowHeaders.val(), "Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With");
}

TEST(headers_test, access_control_expose_headers_test)
{
    Header::AccessControlExposeHeaders exposeHeaders;

    exposeHeaders.parse("Accept, Location");
    ASSERT_EQ(exposeHeaders.val(), "Accept, Location");
}

TEST(headers_test, access_control_allow_methods_test)
{
    Header::AccessControlAllowMethods allowMethods;

    allowMethods.parse("GET, POST, DELETE");
    ASSERT_EQ(allowMethods.val(), "GET, POST, DELETE");
}

CUSTOM_HEADER(TestHeader)

TEST(header_test, macro_for_custom_headers)
{
    TestHeader testHeader;
    ASSERT_TRUE( strcmp(TestHeader::Name,"TestHeader") == 0);

    testHeader.parse("Header Content Test");
    ASSERT_EQ(testHeader.val(), "Header Content Test");
}

TEST(headers_test, add_new_header_test)
{
    const std::string headerName = "TestHeader";

    ASSERT_FALSE(Header::Registry::instance().isRegistered(headerName));
    Header::Registry::instance().registerHeader<TestHeader>();
    ASSERT_TRUE(Header::Registry::instance().isRegistered(headerName));

    const auto& headersList = Header::Registry::instance().headersList();
    const bool isFound = std::find(headersList.begin(), headersList.end(), headerName) != headersList.end();
    ASSERT_TRUE(isFound);
}
<commit_msg>Added test cases to exceptions and some uncovered methods in headers<commit_after>#include <pistache/http_headers.h>
#include <pistache/date.h>

#include "gtest/gtest.h"

#include <algorithm>
#include <chrono>
#include <iostream>

using namespace Pistache::Http;

TEST(headers_test, accept) {
    Header::Accept a1;
    a1.parse("audio/*; q=0.2");

    {
        const auto& media = a1.media();
        ASSERT_EQ(media.size(), 1U);

        const auto& mime = media[0];
        ASSERT_EQ(mime, MIME(Audio, Star));
        ASSERT_EQ(mime.q().getOrElse(Mime::Q(0)), Mime::Q(20));
    }

    Header::Accept a2;
    a2.parse("text/*, text/html, text/html;level=1, */*");

    {
        const auto& media = a2.media();
        ASSERT_EQ(media.size(), 4U);

        const auto &m1 = media[0];
        ASSERT_EQ(m1, MIME(Text, Star));
        const auto &m2 = media[1];
        ASSERT_EQ(m2, MIME(Text, Html));
        const auto& m3 = media[2];
        ASSERT_EQ(m3, MIME(Text, Html));
        auto level = m3.getParam("level");
        ASSERT_EQ(level.getOrElse(""), "1");
        const auto& m4 = media[3];
        ASSERT_EQ(m4, MIME(Star, Star));
    }

    Header::Accept a3;
    a3.parse("text/*;q=0.3, text/html;q=0.7, text/html;level=1, "
             "text/html;level=2;q=0.4, */*;q=0.5");

    {
        const auto& media = a3.media();
        ASSERT_EQ(media.size(), 5U);

        ASSERT_EQ(media[0], MIME(Text, Star));
        ASSERT_EQ(media[0].q().getOrElse(Mime::Q(0)), Mime::Q(30));

        ASSERT_EQ(media[1], MIME(Text, Html));
        ASSERT_EQ(media[2], MIME(Text, Html));
        ASSERT_EQ(media[3], MIME(Text, Html));
        ASSERT_EQ(media[4], MIME(Star, Star));
        ASSERT_EQ(media[4].q().getOrElse(Mime::Q(0)), Mime::Q::fromFloat(0.5));
    }

    Header::Accept a4;
    ASSERT_THROW(a4.parse("text/*;q=0.4, text/html;q=0.3,"), std::runtime_error);

    Header::Accept a5;
    ASSERT_THROW(a5.parse("text/*;q=0.4, text/html;q=0.3, "), std::runtime_error);
}

TEST(headers_test, allow) {
    Header::Allow a1(Method::Get);

    std::ostringstream os;
    a1.write(os);
    ASSERT_EQ(os.str(), "GET");
    os.str("");

    Header::Allow a2({ Method::Post, Method::Put });
    a2.write(os);
    ASSERT_EQ(os.str(), "POST, PUT");
    os.str("");

    Header::Allow a3;
    a3.addMethod(Method::Get);
    a3.write(os);
    ASSERT_EQ(os.str(), "GET");
    os.str("");
    a3.addMethod(Method::Options);
    a3.write(os);
    ASSERT_EQ(os.str(), "GET, OPTIONS");
    os.str("");

    Header::Allow a4(Method::Head);
    a4.addMethods({ Method::Get, Method::Options });
    a4.write(os);
    ASSERT_EQ(os.str(), "HEAD, GET, OPTIONS");
    os.str("");

    Header::Allow a5(Method::Head);
    std::vector<Method> methods;
    methods.push_back(Method::Get);
    a5.addMethods(methods);
    a5.write(os);
    ASSERT_EQ(os.str(), "HEAD, GET");
}

TEST(headers_test, cache_control) {
    auto testTrivial = [](std::string str, CacheDirective::Directive expected) {
        Header::CacheControl cc;
        cc.parse(str);

        auto directives = cc.directives();
        ASSERT_EQ(directives.size(), 1U);
        ASSERT_EQ(directives[0].directive(), expected);
    };

    auto testTimed = [](
            std::string str, CacheDirective::Directive expected, uint64_t delta) {
        Header::CacheControl cc;
        cc.parse(str);

        auto directives = cc.directives();
        ASSERT_EQ(directives.size(), 1U);

        ASSERT_EQ(directives[0].directive(), expected);
        ASSERT_EQ(directives[0].delta(), std::chrono::seconds(delta));
    };

    testTrivial("no-cache", CacheDirective::NoCache);
    testTrivial("no-store", CacheDirective::NoStore);
    testTrivial("no-transform", CacheDirective::NoTransform);
    testTrivial("only-if-cached", CacheDirective::OnlyIfCached);

    testTimed("max-age=0", CacheDirective::MaxAge, 0);
    testTimed("max-age=12", CacheDirective::MaxAge, 12);

    testTimed("max-stale=12345", CacheDirective::MaxStale, 12345);
    testTimed("min-fresh=48", CacheDirective::MinFresh, 48);

    Header::CacheControl cc1;
    cc1.parse("private, max-age=600");
    auto d1 = cc1.directives();
    ASSERT_EQ(d1.size(), 2U);
    ASSERT_EQ(d1[0].directive(), CacheDirective::Private);
    ASSERT_EQ(d1[1].directive(), CacheDirective::MaxAge);
    ASSERT_EQ(d1[1].delta(), std::chrono::seconds(600));

    Header::CacheControl cc2;
    cc2.parse("public, s-maxage=200, proxy-revalidate");
    auto d2 = cc2.directives();
    ASSERT_EQ(d2.size(), 3U);
    ASSERT_EQ(d2[0].directive(), CacheDirective::Public);
    ASSERT_EQ(d2[1].directive(), CacheDirective::SMaxAge);
    ASSERT_EQ(d2[1].delta(), std::chrono::seconds(200));
    ASSERT_EQ(d2[2].directive(), CacheDirective::ProxyRevalidate);

    Header::CacheControl cc3(CacheDirective::NoCache);
    std::ostringstream oss;
    cc3.write(oss);
    ASSERT_EQ(oss.str(), "no-cache");
    oss.str("");

    cc3.addDirective(CacheDirective::NoStore);
    cc3.write(oss);
    ASSERT_EQ(oss.str(), "no-cache, no-store");
    oss.str("");

    Header::CacheControl cc4;
    cc4.addDirectives({
            CacheDirective::Public,
            CacheDirective(CacheDirective::MaxAge, std::chrono::seconds(600))
    });
    cc4.write(oss);
    ASSERT_EQ(oss.str(), "public, max-age=600");

}

TEST(headers_test, content_length) {
    Header::ContentLength cl;

    cl.parse("3495");
    ASSERT_EQ(cl.value(), 3495U);
}

TEST(headers_test, connection) {
    Header::Connection connection;

    constexpr struct Test {
        const char *data;
        ConnectionControl expected;
    } tests[] = {
      { "close", ConnectionControl::Close },
      { "clOse", ConnectionControl::Close },
      { "Close", ConnectionControl::Close },
      { "CLOSE", ConnectionControl::Close },

      { "keep-alive", ConnectionControl::KeepAlive },
      { "Keep-Alive", ConnectionControl::KeepAlive },
      { "kEEp-alIvE", ConnectionControl::KeepAlive },
      { "KEEP-ALIVE", ConnectionControl::KeepAlive }
    };

    for (auto test: tests) {
        Header::Connection connection;
        connection.parse(test.data);

        ASSERT_EQ(connection.control(), test.expected);
    }
}

TEST(headers_test, date_test_rfc_1123) {

    using namespace std::chrono;
    FullDate::time_point expected_time_point = date::sys_days(date::year{1994}/11/6)
                                                + hours(8) + minutes(49) + seconds(37);

    /* RFC-1123 */
    Header::Date d1;
    d1.parse("Sun, 06 Nov 1994 08:49:37 GMT");
    auto dd1 = d1.fullDate().date();
    ASSERT_EQ(expected_time_point, dd1);
}

TEST(headers_test, date_test_rfc_850) {

    using namespace std::chrono;
    FullDate::time_point expected_time_point = date::sys_days(date::year{1994}/11/6)
                                                + hours(8) + minutes(49) + seconds(37);

    /* RFC-850 */
    Header::Date d2;
    d2.parse("Sunday, 06-Nov-94 08:49:37 GMT");
    auto dd2 = d2.fullDate().date();
    ASSERT_EQ(dd2, expected_time_point);
}

TEST(headers_test, date_test_asctime) {

    using namespace std::chrono;
    FullDate::time_point expected_time_point = date::sys_days(date::year{1994}/11/6)
                                                + hours(8) + minutes(49) + seconds(37);

    /* ANSI C's asctime format */
    Header::Date d3;
    d3.parse("Sun Nov  6 08:49:37 1994");
    auto dd3 = d3.fullDate().date();
    ASSERT_EQ(dd3, expected_time_point);
}

TEST(headers_test, date_test_ostream) {

    std::ostringstream os;

    Header::Date d4;
    d4.parse("Fri, 25 Jan 2019 21:04:45.000000000 UTC");
    d4.write(os);
    ASSERT_EQ("Fri, 25 Jan 2019 21:04:45.000000000 UTC", os.str());
}

TEST(headers_test, host) {
    Header::Host host;

    host.parse("www.w3.org");
    ASSERT_EQ(host.host(), "www.w3.org");
    ASSERT_EQ(host.port(), 80);

    host.parse("www.example.com:8080");
    ASSERT_EQ(host.host(), "www.example.com");
    ASSERT_EQ(host.port(), 8080);

    host.parse("localhost:8080");
    ASSERT_EQ(host.host(), "localhost");
    ASSERT_EQ(host.port(), 8080);

/* Due to an error in GLIBC these tests don't fail as expected, further research needed */
//     ASSERT_THROW( host.parse("256.256.256.256:8080");, std::invalid_argument);
//     ASSERT_THROW( host.parse("1.0.0.256:8080");, std::invalid_argument);

    host.parse("[::1]:8080");
    ASSERT_EQ(host.host(), "[::1]");
    ASSERT_EQ(host.port(), 8080);

    host.parse("[2001:0DB8:AABB:CCDD:EEFF:0011:2233:4455]:8080");
    ASSERT_EQ(host.host(), "[2001:0DB8:AABB:CCDD:EEFF:0011:2233:4455]");
    ASSERT_EQ(host.port(), 8080);

/* Due to an error in GLIBC these tests don't fail as expected, further research needed */
//     ASSERT_THROW( host.parse("[GGGG:GGGG:GGGG:GGGG:GGGG:GGGG:GGGG:GGGG]:8080");, std::invalid_argument);
//     ASSERT_THROW( host.parse("[::GGGG]:8080");, std::invalid_argument);
}

TEST(headers_test, user_agent) {
    Header::UserAgent ua;

    ua.parse("CERN-LineMode/2.15 libwww/2.17b3");
    ASSERT_EQ(ua.agent(), "CERN-LineMode/2.15 libwww/2.17b3");
}

TEST(headers_test, content_encoding) {
    Header::ContentEncoding ce;

    ce.parse("gzip");
    ASSERT_EQ(ce.encoding(), Header::Encoding::Gzip);
}

TEST(headers_test, content_type) {
    Header::ContentType ct;

    ct.parse("text/html; charset=ISO-8859-4");
    const auto& mime = ct.mime();
    ASSERT_EQ(mime, MIME(Text, Html));
    ASSERT_EQ(mime.getParam("charset").getOrElse(""), "ISO-8859-4");
}

TEST(headers_test, access_control_allow_origin_test)
{
    Header::AccessControlAllowOrigin allowOrigin;

    allowOrigin.parse("http://foo.bar");
    ASSERT_EQ(allowOrigin.uri(), "http://foo.bar");
}

TEST(headers_test, access_control_allow_headers_test)
{
    Header::AccessControlAllowHeaders allowHeaders;

    allowHeaders.parse("Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With");
    ASSERT_EQ(allowHeaders.val(), "Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With");
}

TEST(headers_test, access_control_expose_headers_test)
{
    Header::AccessControlExposeHeaders exposeHeaders;

    exposeHeaders.parse("Accept, Location");
    ASSERT_EQ(exposeHeaders.val(), "Accept, Location");
}

TEST(headers_test, access_control_allow_methods_test)
{
    Header::AccessControlAllowMethods allowMethods;

    allowMethods.parse("GET, POST, DELETE");
    ASSERT_EQ(allowMethods.val(), "GET, POST, DELETE");
}

CUSTOM_HEADER(TestHeader)

TEST(header_test, macro_for_custom_headers)
{
    TestHeader testHeader;
    ASSERT_TRUE( strcmp(TestHeader::Name,"TestHeader") == 0);

    testHeader.parse("Header Content Test");
    ASSERT_EQ(testHeader.val(), "Header Content Test");
}

TEST(headers_test, add_new_header_test)
{
    const std::string headerName = "TestHeader";

    ASSERT_FALSE(Header::Registry::instance().isRegistered(headerName));
    Header::Registry::instance().registerHeader<TestHeader>();
    ASSERT_TRUE(Header::Registry::instance().isRegistered(headerName));

    const auto& headersList = Header::Registry::instance().headersList();
    const bool isFound = std::find(headersList.begin(), headersList.end(), headerName) != headersList.end();
    ASSERT_TRUE(isFound);
}

//throw std::runtime_error("Header already registered");
//throw std::runtime_error("Unknown header");
//throw std::runtime_error("Could not find header");
//    Collection::get(const std::string& name) const
//    Collection::get(const std::string& name)
//    Collection::getRaw(const std::string& name) const

using namespace Pistache::Http::Header;

TEST(headers_test, header_already_registered)
{
    std::string what;

    try {
        RegisterHeader(Accept);
    } catch (std::exception& e) {
        what = e.what();
    }

    ASSERT_TRUE(strcmp(what.c_str(),"Header already registered") == 0);

}

TEST(headers_test, unknown_header)
{

    std::string what;

    try {
        auto h = Pistache::Http::Header::Registry::instance().makeHeader("UnknownHeader");
    } catch (std::exception& e) {
        what = e.what();
    }

    ASSERT_TRUE(std::strcmp(what.c_str(),"Unknown header") == 0);

}<|endoftext|>


<commit_before>// RUN: %clang_cc1 -std=c++98 -fcxx-exceptions -verify %s
// RUN: %clang_cc1 -std=c++11 -fcxx-exceptions -verify %s
// RUN: %clang_cc1 -std=c++1y -fcxx-exceptions -fsized-deallocation -verify %s
// RUN: %clang_cc1 -std=c++14 -fcxx-exceptions -fsized-deallocation -verify %s
// RUN: %clang_cc1 -std=c++1z -fcxx-exceptions -fsized-deallocation -verify %s
// RUN: %clang_cc1 -std=c++1z -fcxx-exceptions -fsized-deallocation -fconcepts-ts -DCONCEPTS_TS=1 -verify %s
// RUN: %clang_cc1 -fno-rtti -verify %s -DNO_EXCEPTIONS -DNO_RTTI
// RUN: %clang_cc1 -fcoroutines-ts -DNO_EXCEPTIONS -DCOROUTINES -verify %s

// expected-no-diagnostics

// FIXME using `defined` in a macro has undefined behavior.
#if __cplusplus < 201103L
#define check(macro, cxx98, cxx11, cxx14, cxx1z) cxx98 == 0 ? defined(__cpp_##macro) : __cpp_##macro != cxx98
#elif __cplusplus < 201402L
#define check(macro, cxx98, cxx11, cxx14, cxx1z) cxx11 == 0 ? defined(__cpp_##macro) : __cpp_##macro != cxx11
#elif __cplusplus < 201406L
#define check(macro, cxx98, cxx11, cxx14, cxx1z) cxx14 == 0 ? defined(__cpp_##macro) : __cpp_##macro != cxx14
#else
#define check(macro, cxx98, cxx11, cxx14, cxx1z) cxx1z == 0 ? defined(__cpp_##macro) : __cpp_##macro != cxx1z
#endif

// --- C++17 features ---

#if check(variadic_using, 0, 0, 0, 201611) // FIXME: provisional name
#error "wrong value for __cpp_variadic_using"
#endif

#if check(hex_float, 0, 0, 0, 201603)
#error "wrong value for __cpp_hex_float"
#endif

#if check(inline_variables, 0, 0, 0, 201606) // FIXME: provisional name
#error "wrong value for __cpp_inline_variables"
#endif

#if check(aligned_new, 0, 0, 0, 201606) // FIXME: provisional name
#error "wrong value for __cpp_aligned_new"
#endif

#if check(noexcept_function_type, 0, 0, 0, 201510)
#error "wrong value for __cpp_noexcept_function_type"
#endif

#if check(fold_expressions, 0, 0, 0, 201603)
#error "wrong value for __cpp_fold_expressions"
#endif

#if check(capture_star_this, 0, 0, 0, 201603)
#error "wrong value for __cpp_capture_star_this"
#endif

// constexpr checked below

#if check(if_constexpr, 0, 0, 0, 201606) // FIXME: provisional name
#error "wrong value for __cpp_if_constexpr"
#endif

// range_based_for checked below

// static_assert checked below

#if check(template_auto, 0, 0, 0, 201606) // FIXME: provisional name
#error "wrong value for __cpp_template_auto"
#endif

#if check(namespace_attributes, 0, 0, 0, 201411)
// FIXME: allowed without warning in C++14 and C++11
#error "wrong value for __cpp_namespace_attributes"
#endif

#if check(enumerator_attributes, 0, 0, 0, 201411)
// FIXME: allowed without warning in C++14 and C++11
#error "wrong value for __cpp_enumerator_attributes"
#endif

#if check(nested_namespace_definitions, 0, 0, 0, 201411)
#error "wrong value for __cpp_nested_namespace_definitions"
#endif

// inheriting_constructors checked below

#if check(aggregate_bases, 0, 0, 0, 201603)
#error "wrong value for __cpp_aggregate_bases"
#endif

#if check(structured_bindings, 0, 0, 0, 201606)
#error "wrong value for __cpp_structured_bindings"
#endif

#if check(nontype_template_args, 0, 0, 0, 201411)
#error "wrong value for __cpp_nontype_template_args"
#endif

#if check(template_template_args, 0, 0, 0, 0) // FIXME: should be 201611 when feature is enabled
#error "wrong value for __cpp_template_template_args"
#endif

#if check(deduction_guides, 0, 0, 0, 201611) // FIXME: provisional name
#error "wrong value for __cpp_deduction_guides"
#endif

// --- C++14 features ---

#if check(binary_literals, 0, 0, 201304, 201304)
#error "wrong value for __cpp_binary_literals"
#endif

// (Removed from SD-6.)
#if check(digit_separators, 0, 0, 201309, 201309)
#error "wrong value for __cpp_digit_separators"
#endif

#if check(init_captures, 0, 0, 201304, 201304)
#error "wrong value for __cpp_init_captures"
#endif

#if check(generic_lambdas, 0, 0, 201304, 201304)
#error "wrong value for __cpp_generic_lambdas"
#endif

#if check(sized_deallocation, 0, 0, 201309, 201309)
#error "wrong value for __cpp_sized_deallocation"
#endif

// constexpr checked below

#if check(decltype_auto, 0, 0, 201304, 201304)
#error "wrong value for __cpp_decltype_auto"
#endif

#if check(return_type_deduction, 0, 0, 201304, 201304)
#error "wrong value for __cpp_return_type_deduction"
#endif

#if check(runtime_arrays, 0, 0, 0, 0)
#error "wrong value for __cpp_runtime_arrays"
#endif

#if check(aggregate_nsdmi, 0, 0, 201304, 201304)
#error "wrong value for __cpp_aggregate_nsdmi"
#endif

#if check(variable_templates, 0, 0, 201304, 201304)
#error "wrong value for __cpp_variable_templates"
#endif

// --- C++11 features ---

#if check(unicode_characters, 0, 200704, 200704, 200704)
#error "wrong value for __cpp_unicode_characters"
#endif

#if check(raw_strings, 0, 200710, 200710, 200710)
#error "wrong value for __cpp_raw_strings"
#endif

#if check(unicode_literals, 0, 200710, 200710, 200710)
#error "wrong value for __cpp_unicode_literals"
#endif

#if check(user_defined_literals, 0, 200809, 200809, 200809)
#error "wrong value for __cpp_user_defined_literals"
#endif

#if check(lambdas, 0, 200907, 200907, 200907)
#error "wrong value for __cpp_lambdas"
#endif

#if check(constexpr, 0, 200704, 201304, 201603)
#error "wrong value for __cpp_constexpr"
#endif

#if check(range_based_for, 0, 200907, 200907, 201603)
#error "wrong value for __cpp_range_based_for"
#endif

#if check(static_assert, 0, 200410, 200410, 201411)
#error "wrong value for __cpp_static_assert"
#endif

#if check(decltype, 0, 200707, 200707, 200707)
#error "wrong value for __cpp_decltype"
#endif

#if check(attributes, 0, 200809, 200809, 200809)
#error "wrong value for __cpp_attributes"
#endif

#if check(rvalue_references, 0, 200610, 200610, 200610)
#error "wrong value for __cpp_rvalue_references"
#endif

#if check(variadic_templates, 0, 200704, 200704, 200704)
#error "wrong value for __cpp_variadic_templates"
#endif

#if check(initializer_lists, 0, 200806, 200806, 200806)
#error "wrong value for __cpp_initializer_lists"
#endif

#if check(delegating_constructors, 0, 200604, 200604, 200604)
#error "wrong value for __cpp_delegating_constructors"
#endif

#if check(nsdmi, 0, 200809, 200809, 200809)
#error "wrong value for __cpp_nsdmi"
#endif

#if check(inheriting_constructors, 0, 201511, 201511, 201511)
#error "wrong value for __cpp_inheriting_constructors"
#endif

#if check(ref_qualifiers, 0, 200710, 200710, 200710)
#error "wrong value for __cpp_ref_qualifiers"
#endif

#if check(alias_templates, 0, 200704, 200704, 200704)
#error "wrong value for __cpp_alias_templates"
#endif

// --- C++98 features ---

#if defined(NO_RTTI) ? check(rtti, 0, 0, 0, 0) : check(rtti, 199711, 199711, 199711, 199711)
#error "wrong value for __cpp_rtti"
#endif

#if defined(NO_EXCEPTIONS) ? check(exceptions, 0, 0, 0, 0) : check(exceptions, 199711, 199711, 199711, 199711)
#error "wrong value for __cpp_exceptions"
#endif

// --- TS features --

#if check(experimental_concepts, 0, 0, CONCEPTS_TS, CONCEPTS_TS)
#error "wrong value for __cpp_experimental_concepts"
#endif

#if defined(COROUTINES) ? check(coroutines, 201703L, 201703L, 201703L, 201703L) : check(coroutines, 0, 0, 0, 0)
#error "wrong value for __cpp_coroutines"
#endif
<commit_msg>Reorder tests to match latest SD-6 draft.<commit_after>// RUN: %clang_cc1 -std=c++98 -fcxx-exceptions -verify %s
// RUN: %clang_cc1 -std=c++11 -fcxx-exceptions -verify %s
// RUN: %clang_cc1 -std=c++1y -fcxx-exceptions -fsized-deallocation -verify %s
// RUN: %clang_cc1 -std=c++14 -fcxx-exceptions -fsized-deallocation -verify %s
// RUN: %clang_cc1 -std=c++1z -fcxx-exceptions -fsized-deallocation -verify %s
// RUN: %clang_cc1 -std=c++1z -fcxx-exceptions -fsized-deallocation -fconcepts-ts -DCONCEPTS_TS=1 -verify %s
// RUN: %clang_cc1 -fno-rtti -verify %s -DNO_EXCEPTIONS -DNO_RTTI
// RUN: %clang_cc1 -fcoroutines-ts -DNO_EXCEPTIONS -DCOROUTINES -verify %s

// expected-no-diagnostics

// FIXME using `defined` in a macro has undefined behavior.
#if __cplusplus < 201103L
#define check(macro, cxx98, cxx11, cxx14, cxx1z) cxx98 == 0 ? defined(__cpp_##macro) : __cpp_##macro != cxx98
#elif __cplusplus < 201402L
#define check(macro, cxx98, cxx11, cxx14, cxx1z) cxx11 == 0 ? defined(__cpp_##macro) : __cpp_##macro != cxx11
#elif __cplusplus < 201406L
#define check(macro, cxx98, cxx11, cxx14, cxx1z) cxx14 == 0 ? defined(__cpp_##macro) : __cpp_##macro != cxx14
#else
#define check(macro, cxx98, cxx11, cxx14, cxx1z) cxx1z == 0 ? defined(__cpp_##macro) : __cpp_##macro != cxx1z
#endif

// --- C++17 features ---

#if check(hex_float, 0, 0, 0, 201603)
#error "wrong value for __cpp_hex_float"
#endif

#if check(inline_variables, 0, 0, 0, 201606) // FIXME: provisional name
#error "wrong value for __cpp_inline_variables"
#endif

#if check(aligned_new, 0, 0, 0, 201606) // FIXME: provisional name
#error "wrong value for __cpp_aligned_new"
#endif

#if check(noexcept_function_type, 0, 0, 0, 201510)
#error "wrong value for __cpp_noexcept_function_type"
#endif

#if check(fold_expressions, 0, 0, 0, 201603)
#error "wrong value for __cpp_fold_expressions"
#endif

#if check(capture_star_this, 0, 0, 0, 201603)
#error "wrong value for __cpp_capture_star_this"
#endif

// constexpr checked below

#if check(if_constexpr, 0, 0, 0, 201606) // FIXME: provisional name
#error "wrong value for __cpp_if_constexpr"
#endif

// range_based_for checked below

// static_assert checked below

#if check(deduction_guides, 0, 0, 0, 201611) // FIXME: provisional name
#error "wrong value for __cpp_deduction_guides"
#endif

#if check(template_auto, 0, 0, 0, 201606) // FIXME: provisional name
#error "wrong value for __cpp_template_auto"
#endif

#if check(namespace_attributes, 0, 0, 0, 201411)
// FIXME: allowed without warning in C++14 and C++11
#error "wrong value for __cpp_namespace_attributes"
#endif

#if check(enumerator_attributes, 0, 0, 0, 201411)
// FIXME: allowed without warning in C++14 and C++11
#error "wrong value for __cpp_enumerator_attributes"
#endif

#if check(nested_namespace_definitions, 0, 0, 0, 201411)
#error "wrong value for __cpp_nested_namespace_definitions"
#endif

// inheriting_constructors checked below

#if check(variadic_using, 0, 0, 0, 201611) // FIXME: provisional name
#error "wrong value for __cpp_variadic_using"
#endif

#if check(aggregate_bases, 0, 0, 0, 201603)
#error "wrong value for __cpp_aggregate_bases"
#endif

#if check(structured_bindings, 0, 0, 0, 201606)
#error "wrong value for __cpp_structured_bindings"
#endif

#if check(nontype_template_args, 0, 0, 0, 201411)
#error "wrong value for __cpp_nontype_template_args"
#endif

#if check(template_template_args, 0, 0, 0, 0) // FIXME: should be 201611 when feature is enabled
#error "wrong value for __cpp_template_template_args"
#endif

// --- C++14 features ---

#if check(binary_literals, 0, 0, 201304, 201304)
#error "wrong value for __cpp_binary_literals"
#endif

// (Removed from SD-6.)
#if check(digit_separators, 0, 0, 201309, 201309)
#error "wrong value for __cpp_digit_separators"
#endif

#if check(init_captures, 0, 0, 201304, 201304)
#error "wrong value for __cpp_init_captures"
#endif

#if check(generic_lambdas, 0, 0, 201304, 201304)
#error "wrong value for __cpp_generic_lambdas"
#endif

#if check(sized_deallocation, 0, 0, 201309, 201309)
#error "wrong value for __cpp_sized_deallocation"
#endif

// constexpr checked below

#if check(decltype_auto, 0, 0, 201304, 201304)
#error "wrong value for __cpp_decltype_auto"
#endif

#if check(return_type_deduction, 0, 0, 201304, 201304)
#error "wrong value for __cpp_return_type_deduction"
#endif

#if check(runtime_arrays, 0, 0, 0, 0)
#error "wrong value for __cpp_runtime_arrays"
#endif

#if check(aggregate_nsdmi, 0, 0, 201304, 201304)
#error "wrong value for __cpp_aggregate_nsdmi"
#endif

#if check(variable_templates, 0, 0, 201304, 201304)
#error "wrong value for __cpp_variable_templates"
#endif

// --- C++11 features ---

#if check(unicode_characters, 0, 200704, 200704, 200704)
#error "wrong value for __cpp_unicode_characters"
#endif

#if check(raw_strings, 0, 200710, 200710, 200710)
#error "wrong value for __cpp_raw_strings"
#endif

#if check(unicode_literals, 0, 200710, 200710, 200710)
#error "wrong value for __cpp_unicode_literals"
#endif

#if check(user_defined_literals, 0, 200809, 200809, 200809)
#error "wrong value for __cpp_user_defined_literals"
#endif

#if check(lambdas, 0, 200907, 200907, 200907)
#error "wrong value for __cpp_lambdas"
#endif

#if check(constexpr, 0, 200704, 201304, 201603)
#error "wrong value for __cpp_constexpr"
#endif

#if check(range_based_for, 0, 200907, 200907, 201603)
#error "wrong value for __cpp_range_based_for"
#endif

#if check(static_assert, 0, 200410, 200410, 201411)
#error "wrong value for __cpp_static_assert"
#endif

#if check(decltype, 0, 200707, 200707, 200707)
#error "wrong value for __cpp_decltype"
#endif

#if check(attributes, 0, 200809, 200809, 200809)
#error "wrong value for __cpp_attributes"
#endif

#if check(rvalue_references, 0, 200610, 200610, 200610)
#error "wrong value for __cpp_rvalue_references"
#endif

#if check(variadic_templates, 0, 200704, 200704, 200704)
#error "wrong value for __cpp_variadic_templates"
#endif

#if check(initializer_lists, 0, 200806, 200806, 200806)
#error "wrong value for __cpp_initializer_lists"
#endif

#if check(delegating_constructors, 0, 200604, 200604, 200604)
#error "wrong value for __cpp_delegating_constructors"
#endif

#if check(nsdmi, 0, 200809, 200809, 200809)
#error "wrong value for __cpp_nsdmi"
#endif

#if check(inheriting_constructors, 0, 201511, 201511, 201511)
#error "wrong value for __cpp_inheriting_constructors"
#endif

#if check(ref_qualifiers, 0, 200710, 200710, 200710)
#error "wrong value for __cpp_ref_qualifiers"
#endif

#if check(alias_templates, 0, 200704, 200704, 200704)
#error "wrong value for __cpp_alias_templates"
#endif

// --- C++98 features ---

#if defined(NO_RTTI) ? check(rtti, 0, 0, 0, 0) : check(rtti, 199711, 199711, 199711, 199711)
#error "wrong value for __cpp_rtti"
#endif

#if defined(NO_EXCEPTIONS) ? check(exceptions, 0, 0, 0, 0) : check(exceptions, 199711, 199711, 199711, 199711)
#error "wrong value for __cpp_exceptions"
#endif

// --- TS features --

#if check(experimental_concepts, 0, 0, CONCEPTS_TS, CONCEPTS_TS)
#error "wrong value for __cpp_experimental_concepts"
#endif

#if defined(COROUTINES) ? check(coroutines, 201703L, 201703L, 201703L, 201703L) : check(coroutines, 0, 0, 0, 0)
#error "wrong value for __cpp_coroutines"
#endif
<|endoftext|>