// Copyright (c) 2012 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 "content/common/plugin_list.h"

#import <Carbon/Carbon.h>
#import <Foundation/Foundation.h>

#include "base/files/file_enumerator.h"
#include "base/files/file_util.h"
#include "base/mac/mac_util.h"
#include "base/mac/scoped_cftyperef.h"
#include "base/memory/scoped_ptr.h"
#include "base/native_library.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/sys_string_conversions.h"
#include "base/strings/utf_string_conversions.h"

using base::ScopedCFTypeRef;

namespace content {

namespace {

void GetPluginCommonDirectory(std::vector<base::FilePath>* plugin_dirs,
                              bool user) {
  // Note that there are no NSSearchPathDirectory constants for these
  // directories so we can't use Cocoa's NSSearchPathForDirectoriesInDomains().
  // Interestingly, Safari hard-codes the location (see
  // WebKit/WebKit/mac/Plugins/WebPluginDatabase.mm's +_defaultPlugInPaths).
  FSRef ref;
  OSErr err = FSFindFolder(user ? kUserDomain : kLocalDomain,
                           kInternetPlugInFolderType, false, &ref);

  if (err)
    return;

  plugin_dirs->push_back(base::FilePath(base::mac::PathFromFSRef(ref)));
}

// Returns true if the plugin should be prevented from loading.
bool IsBlacklistedPlugin(const WebPluginInfo& info) {
  // We blacklist Gears by included MIME type, since that is more stable than
  // its name. Be careful about adding any more plugins to this list though,
  // since it's easy to accidentally blacklist plugins that support lots of
  // MIME types.
  for (std::vector<WebPluginMimeType>::const_iterator i =
           info.mime_types.begin(); i != info.mime_types.end(); ++i) {
    // The Gears plugin is Safari-specific, so don't load it.
    if (i->mime_type == "application/x-googlegears")
      return true;
  }

  // Versions of Flip4Mac 2.3 before 2.3.6 often hang the renderer, so don't
  // load them.
  if (StartsWith(info.name,
                 base::ASCIIToUTF16("Flip4Mac Windows Media"), false) &&
      StartsWith(info.version, base::ASCIIToUTF16("2.3"), false)) {
    std::vector<base::string16> components;
    base::SplitString(info.version, '.', &components);
    int bugfix_version = 0;
    return (components.size() >= 3 &&
            base::StringToInt(components[2], &bugfix_version) &&
            bugfix_version < 6);
  }

  return false;
}

NSDictionary* GetMIMETypes(CFBundleRef bundle) {
  NSString* mime_filename =
      (NSString*)CFBundleGetValueForInfoDictionaryKey(bundle,
                     CFSTR("WebPluginMIMETypesFilename"));

  if (mime_filename) {

    // get the file

    NSString* mime_path =
        [NSString stringWithFormat:@"%@/Library/Preferences/%@",
         NSHomeDirectory(), mime_filename];
    NSDictionary* mime_file_dict =
        [NSDictionary dictionaryWithContentsOfFile:mime_path];

    // is it valid?

    bool valid_file = false;
    if (mime_file_dict) {
      NSString* l10n_name =
          [mime_file_dict objectForKey:@"WebPluginLocalizationName"];
      NSString* preferred_l10n = [[NSLocale currentLocale] localeIdentifier];
      if ([l10n_name isEqualToString:preferred_l10n])
        valid_file = true;
    }

    if (valid_file)
      return [mime_file_dict objectForKey:@"WebPluginMIMETypes"];

    // dammit, I didn't want to have to do this

    typedef void (*CreateMIMETypesPrefsPtr)(void);
    CreateMIMETypesPrefsPtr create_prefs_file =
        (CreateMIMETypesPrefsPtr)CFBundleGetFunctionPointerForName(
        bundle, CFSTR("BP_CreatePluginMIMETypesPreferences"));
    if (!create_prefs_file)
      return nil;
    create_prefs_file();

    // one more time

    mime_file_dict = [NSDictionary dictionaryWithContentsOfFile:mime_path];
    if (mime_file_dict)
      return [mime_file_dict objectForKey:@"WebPluginMIMETypes"];
    else
      return nil;

  } else {
    return (NSDictionary*)CFBundleGetValueForInfoDictionaryKey(bundle,
                              CFSTR("WebPluginMIMETypes"));
  }
}

bool ReadPlistPluginInfo(const base::FilePath& filename, CFBundleRef bundle,
                         WebPluginInfo* info) {
  NSDictionary* mime_types = GetMIMETypes(bundle);
  if (!mime_types)
    return false;  // no type info here; try elsewhere

  for (NSString* mime_type in [mime_types allKeys]) {
    NSDictionary* mime_dict = [mime_types objectForKey:mime_type];
    NSNumber* type_enabled = [mime_dict objectForKey:@"WebPluginTypeEnabled"];
    NSString* mime_desc = [mime_dict objectForKey:@"WebPluginTypeDescription"];
    NSArray* mime_exts = [mime_dict objectForKey:@"WebPluginExtensions"];

    // Skip any disabled types.
    if (type_enabled && ![type_enabled boolValue])
      continue;

    WebPluginMimeType mime;
    mime.mime_type = base::SysNSStringToUTF8([mime_type lowercaseString]);
    // Remove PDF from the list of types handled by QuickTime, since it provides
    // a worse experience than just downloading the PDF.
    if (mime.mime_type == "application/pdf" &&
        StartsWithASCII(filename.BaseName().value(), "QuickTime", false)) {
      continue;
    }

    if (mime_desc)
      mime.description = base::SysNSStringToUTF16(mime_desc);
    for (NSString* ext in mime_exts)
      mime.file_extensions.push_back(
          base::SysNSStringToUTF8([ext lowercaseString]));

    info->mime_types.push_back(mime);
  }

  NSString* plugin_name =
      (NSString*)CFBundleGetValueForInfoDictionaryKey(bundle,
      CFSTR("WebPluginName"));
  NSString* plugin_vers =
      (NSString*)CFBundleGetValueForInfoDictionaryKey(bundle,
      CFSTR("CFBundleShortVersionString"));
  NSString* plugin_desc =
      (NSString*)CFBundleGetValueForInfoDictionaryKey(bundle,
      CFSTR("WebPluginDescription"));

  if (plugin_name)
    info->name = base::SysNSStringToUTF16(plugin_name);
  else
    info->name = base::UTF8ToUTF16(filename.BaseName().value());
  info->path = filename;
  if (plugin_vers)
    info->version = base::SysNSStringToUTF16(plugin_vers);
  if (plugin_desc)
    info->desc = base::SysNSStringToUTF16(plugin_desc);
  else
    info->desc = base::UTF8ToUTF16(filename.BaseName().value());

  return true;
}

}  // namespace

bool PluginList::ReadWebPluginInfo(const base::FilePath &filename,
                                   WebPluginInfo* info) {
  // There are three ways to get information about plugin capabilities:
  // 1) a set of Info.plist keys, documented at
  // http://developer.apple.com/documentation/InternetWeb/Conceptual/WebKit_PluginProgTopic/Concepts/AboutPlugins.html .
  // 2) a set of STR# resources, documented at
  // https://developer.mozilla.org/En/Gecko_Plugin_API_Reference/Plug-in_Development_Overview .
  // 3) a NP_GetMIMEDescription() entry point, documented at
  // https://developer.mozilla.org/en/NP_GetMIMEDescription
  //
  // Mozilla supported (3), but WebKit never has, so no plugins rely on it. Most
  // browsers supported (2) and then added support for (1); Chromium originally
  // supported (2) and (1), but now supports only (1) as (2) is deprecated.
  //
  // For the Info.plist version, the data is formatted as follows (in text plist
  // format):
  //  {
  //    ... the usual plist keys ...
  //    WebPluginDescription = <<plugindescription>>;
  //    WebPluginMIMETypes = {
  //      <<type0mimetype>> = {
  //        WebPluginExtensions = (
  //                               <<type0fileextension0>>,
  //                               ...
  //                               <<type0fileextensionk>>,
  //                               );
  //        WebPluginTypeDescription = <<type0description>>;
  //      };
  //      <<type1mimetype>> = { ... };
  //      ...
  //      <<typenmimetype>> = { ... };
  //    };
  //    WebPluginName = <<pluginname>>;
  //  }
  //
  // Alternatively (and this is undocumented), rather than a WebPluginMIMETypes
  // key, there may be a WebPluginMIMETypesFilename key. If it is present, then
  // it is the name of a file in the user's preferences folder in which to find
  // the WebPluginMIMETypes key. If the key is present but the file doesn't
  // exist, we must load the plugin and call a specific function to have the
  // plugin create the file.

  ScopedCFTypeRef<CFURLRef> bundle_url(CFURLCreateFromFileSystemRepresentation(
      kCFAllocatorDefault, (const UInt8*)filename.value().c_str(),
      filename.value().length(), true));
  if (!bundle_url) {
    LOG_IF(ERROR, PluginList::DebugPluginLoading())
        << "PluginLib::ReadWebPluginInfo could not create bundle URL";
    return false;
  }
  ScopedCFTypeRef<CFBundleRef> bundle(CFBundleCreate(kCFAllocatorDefault,
                                                     bundle_url.get()));
  if (!bundle) {
    LOG_IF(ERROR, PluginList::DebugPluginLoading())
        << "PluginLib::ReadWebPluginInfo could not create CFBundleRef";
    return false;
  }

  // preflight

  OSType type = 0;
  CFBundleGetPackageInfo(bundle.get(), &type, NULL);
  if (type != FOUR_CHAR_CODE('BRPL')) {
    LOG_IF(ERROR, PluginList::DebugPluginLoading())
        << "PluginLib::ReadWebPluginInfo bundle is not BRPL, is " << type;
    return false;
  }

  CFErrorRef error;
  Boolean would_load = CFBundlePreflightExecutable(bundle.get(), &error);
  if (!would_load) {
    ScopedCFTypeRef<CFStringRef> error_string(CFErrorCopyDescription(error));
    LOG_IF(ERROR, PluginList::DebugPluginLoading())
        << "PluginLib::ReadWebPluginInfo bundle failed preflight: "
        << base::SysCFStringRefToUTF8(error_string);
    return false;
  }

  // get the info

  if (ReadPlistPluginInfo(filename, bundle.get(), info))
    return true;

  // ... or not

  return false;
}

void PluginList::GetPluginDirectories(
    std::vector<base::FilePath>* plugin_dirs) {
  if (PluginList::plugins_discovery_disabled_)
    return;

  // Load from the user's area
  GetPluginCommonDirectory(plugin_dirs, true);

  // Load from the machine-wide area
  GetPluginCommonDirectory(plugin_dirs, false);
}

void PluginList::GetPluginsInDir(
    const base::FilePath& path, std::vector<base::FilePath>* plugins) {
  base::FileEnumerator enumerator(path,
                                  false, // not recursive
                                  base::FileEnumerator::DIRECTORIES);
  for (base::FilePath path = enumerator.Next(); !path.value().empty();
       path = enumerator.Next()) {
    plugins->push_back(path);
  }
}

bool PluginList::ShouldLoadPluginUsingPluginList(
    const WebPluginInfo& info,
    std::vector<WebPluginInfo>* plugins) {
  return !IsBlacklistedPlugin(info);
}

}  // namespace content
