<commit_before>// Copyright 2013 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/child/npapi/np_channel_base.h"

#include "base/auto_reset.h"
#include "base/containers/hash_tables.h"
#include "base/lazy_instance.h"
#include "base/strings/string_number_conversions.h"
#include "base/threading/thread_local.h"
#include "ipc/ipc_sync_message.h"

#if defined(OS_POSIX)
#include "ipc/ipc_channel_posix.h"
#endif

namespace content {

namespace {

typedef base::hash_map<std::string, scoped_refptr<NPChannelBase> > ChannelMap;

struct ChannelGlobals {
  ChannelMap channel_map;
  scoped_refptr<NPChannelBase> current_channel;
};

#if defined(OS_ANDROID)
// Workaround for http://crbug.com/298179 - NPChannelBase is only intended
// for use on one thread per process. Using TLS to store the globals removes the
// worst thread hostility in this class, especially needed for webview which
// runs in single-process mode. TODO(joth): Make a complete fix, most likely
// as part of addressing http://crbug.com/258510.
base::LazyInstance<base::ThreadLocalPointer<ChannelGlobals> >::Leaky
    g_channels_tls_ptr = LAZY_INSTANCE_INITIALIZER;

ChannelGlobals* GetChannelGlobals() {
  ChannelGlobals* globals = g_channels_tls_ptr.Get().Get();
  if (!globals) {
    globals = new ChannelGlobals;
    g_channels_tls_ptr.Get().Set(globals);
  }
  return globals;
}

#else

base::LazyInstance<ChannelGlobals>::Leaky g_channels_globals =
    LAZY_INSTANCE_INITIALIZER;

ChannelGlobals* GetChannelGlobals() { return g_channels_globals.Pointer(); }

#endif  // OS_ANDROID

ChannelMap* GetChannelMap() {
  return &GetChannelGlobals()->channel_map;
}

}  // namespace

NPChannelBase* NPChannelBase::GetChannel(
    const IPC::ChannelHandle& channel_handle, IPC::Channel::Mode mode,
    ChannelFactory factory, base::MessageLoopProxy* ipc_message_loop,
    bool create_pipe_now, base::WaitableEvent* shutdown_event) {
  scoped_refptr<NPChannelBase> channel;
  std::string channel_key = channel_handle.name;
  ChannelMap::const_iterator iter = GetChannelMap()->find(channel_key);
  if (iter == GetChannelMap()->end()) {
    channel = factory();
  } else {
    channel = iter->second;
  }

  DCHECK(channel.get() != NULL);

  if (!channel->channel_valid()) {
    channel->channel_handle_ = channel_handle;
    if (mode & IPC::Channel::MODE_SERVER_FLAG) {
      channel->channel_handle_.name =
          IPC::Channel::GenerateVerifiedChannelID(channel_key);
    }
    channel->mode_ = mode;
    if (channel->Init(ipc_message_loop, create_pipe_now, shutdown_event)) {
      (*GetChannelMap())[channel_key] = channel;
    } else {
      channel = NULL;
    }
  }

  return channel.get();
}<commit_msg>Fix a fd leak in NPChannelBase on Posix<commit_after>// Copyright 2013 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/child/npapi/np_channel_base.h"

#include "base/auto_reset.h"
#include "base/containers/hash_tables.h"
#include "base/lazy_instance.h"
#include "base/strings/string_number_conversions.h"
#include "base/threading/thread_local.h"
#include "ipc/ipc_sync_message.h"

#if defined(OS_POSIX)
#include "base/file_util.h"
#include "ipc/ipc_channel_posix.h"
#endif

namespace content {

namespace {

typedef base::hash_map<std::string, scoped_refptr<NPChannelBase> > ChannelMap;

struct ChannelGlobals {
  ChannelMap channel_map;
  scoped_refptr<NPChannelBase> current_channel;
};

#if defined(OS_ANDROID)
// Workaround for http://crbug.com/298179 - NPChannelBase is only intended
// for use on one thread per process. Using TLS to store the globals removes the
// worst thread hostility in this class, especially needed for webview which
// runs in single-process mode. TODO(joth): Make a complete fix, most likely
// as part of addressing http://crbug.com/258510.
base::LazyInstance<base::ThreadLocalPointer<ChannelGlobals> >::Leaky
    g_channels_tls_ptr = LAZY_INSTANCE_INITIALIZER;

ChannelGlobals* GetChannelGlobals() {
  ChannelGlobals* globals = g_channels_tls_ptr.Get().Get();
  if (!globals) {
    globals = new ChannelGlobals;
    g_channels_tls_ptr.Get().Set(globals);
  }
  return globals;
}

#else

base::LazyInstance<ChannelGlobals>::Leaky g_channels_globals =
    LAZY_INSTANCE_INITIALIZER;

ChannelGlobals* GetChannelGlobals() { return g_channels_globals.Pointer(); }

#endif  // OS_ANDROID

ChannelMap* GetChannelMap() {
  return &GetChannelGlobals()->channel_map;
}

}  // namespace

NPChannelBase* NPChannelBase::GetChannel(
    const IPC::ChannelHandle& channel_handle, IPC::Channel::Mode mode,
    ChannelFactory factory, base::MessageLoopProxy* ipc_message_loop,
    bool create_pipe_now, base::WaitableEvent* shutdown_event) {
#if defined(OS_POSIX)
  // On POSIX the channel_handle conveys an FD (socket) which is duped by the
  // kernel during the IPC message exchange (via the SCM_RIGHTS mechanism).
  // Ensure we do not leak this FD.
  int fd = channel_handle.socket.auto_close ? channel_handle.socket.fd : -1;
  file_util::ScopedFD auto_close_fd(&fd);
#endif

  scoped_refptr<NPChannelBase> channel;
  std::string channel_key = channel_handle.name;
  ChannelMap::const_iterator iter = GetChannelMap()->find(channel_key);
  if (iter == GetChannelMap()->end()) {
    channel = factory();
  } else {
    channel = iter->second;
  }

  DCHECK(channel.get() != NULL);

  if (!channel->channel_valid()) {
    channel->channel_handle_ = channel_handle;
#if defined(OS_POSIX)
    ignore_result(auto_close_fd.release());
#endif
    if (mode & IPC::Channel::MODE_SERVER_FLAG) {
      channel->channel_handle_.name =
          IPC::Channel::GenerateVerifiedChannelID(channel_key);
    }
    channel->mode_ = mode;
    if (channel->Init(ipc_message_loop, create_pipe_now, shutdown_event)) {
      (*GetChannelMap())[channel_key] = channel;
    } else {
      channel = NULL;
    }
  }

  return channel.get();
}
{'fraction_non_alphanumeric': 0.1158173395102581, 'fraction_numerical': 0.0054599602911978825, 'mean_word_length': 4.8180943214629455, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 35, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5699799', 'n_tokens_mistral': 2037, 'n_tokens_neox': 1983, 'n_words': 449}