text:
// 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/browser/service_worker/service_worker_provider_host.h"

#include <utility>

#include "base/guid.h"
#include "base/memory/ptr_util.h"
#include "base/stl_util.h"
#include "base/time/time.h"
#include "content/browser/message_port_message_filter.h"
#include "content/browser/service_worker/embedded_worker_status.h"
#include "content/browser/service_worker/service_worker_context_core.h"
#include "content/browser/service_worker/service_worker_context_request_handler.h"
#include "content/browser/service_worker/service_worker_controllee_request_handler.h"
#include "content/browser/service_worker/service_worker_dispatcher_host.h"
#include "content/browser/service_worker/service_worker_handle.h"
#include "content/browser/service_worker/service_worker_registration_handle.h"
#include "content/browser/service_worker/service_worker_version.h"
#include "content/common/resource_request_body_impl.h"
#include "content/common/service_worker/service_worker_messages.h"
#include "content/common/service_worker/service_worker_types.h"
#include "content/common/service_worker/service_worker_utils.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/common/browser_side_navigation_policy.h"
#include "content/public/common/child_process_host.h"
#include "content/public/common/content_client.h"
#include "content/public/common/origin_util.h"
#include "net/base/url_util.h"

namespace content {

namespace {

// PlzNavigate
// Next ServiceWorkerProviderHost ID for navigations, starts at -2 and keeps
// going down.
int g_next_navigation_provider_id = -2;

// A request handler derivative used to handle navigation requests when
// skip_service_worker flag is set. It tracks the document URL and sets the url
// to the provider host.
class ServiceWorkerURLTrackingRequestHandler
    : public ServiceWorkerRequestHandler {
 public:
  ServiceWorkerURLTrackingRequestHandler(
      base::WeakPtr<ServiceWorkerContextCore> context,
      base::WeakPtr<ServiceWorkerProviderHost> provider_host,
      base::WeakPtr<storage::BlobStorageContext> blob_storage_context,
      ResourceType resource_type)
      : ServiceWorkerRequestHandler(context,
                                    provider_host,
                                    blob_storage_context,
                                    resource_type) {}
  ~ServiceWorkerURLTrackingRequestHandler() override {}

  // Called via custom URLRequestJobFactory.
  net::URLRequestJob* MaybeCreateJob(
      net::URLRequest* request,
      net::NetworkDelegate* network_delegate,
      ResourceContext* resource_context) override {
    const GURL stripped_url = net::SimplifyUrlForRequest(request->url());
    provider_host_->SetDocumentUrl(stripped_url);
    provider_host_->SetTopmostFrameUrl(request->first_party_for_cookies());
    return nullptr;
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(ServiceWorkerURLTrackingRequestHandler);
};

}  // anonymous namespace

ServiceWorkerProviderHost::OneShotGetReadyCallback::OneShotGetReadyCallback(
    const GetRegistrationForReadyCallback& callback)
    : callback(callback),
      called(false) {
}

ServiceWorkerProviderHost::OneShotGetReadyCallback::~OneShotGetReadyCallback() {
}

// static
std::unique_ptr<ServiceWorkerProviderHost>
ServiceWorkerProviderHost::PreCreateNavigationHost(
    base::WeakPtr<ServiceWorkerContextCore> context,
    bool are_ancestors_secure,
    const WebContentsGetter& web_contents_getter) {
  CHECK(IsBrowserSideNavigationEnabled());
  // Generate a new browser-assigned id for the host.
  int provider_id = g_next_navigation_provider_id--;
  auto host = base::MakeUnique<ServiceWorkerProviderHost>(
      ChildProcessHost::kInvalidUniqueID, MSG_ROUTING_NONE, provider_id,
      SERVICE_WORKER_PROVIDER_FOR_WINDOW,
      are_ancestors_secure ? FrameSecurityLevel::SECURE
                           : FrameSecurityLevel::INSECURE,
      context, nullptr);
  host->web_contents_getter_ = web_contents_getter;
  return host;
}

ServiceWorkerProviderHost::ServiceWorkerProviderHost(
    int render_process_id,
    int route_id,
    int provider_id,
    ServiceWorkerProviderType provider_type,
    FrameSecurityLevel parent_frame_security_level,
    base::WeakPtr<ServiceWorkerContextCore> context,
    ServiceWorkerDispatcherHost* dispatcher_host)
    : client_uuid_(base::GenerateGUID()),
      render_process_id_(render_process_id),
      route_id_(route_id),
      render_thread_id_(kDocumentMainThreadId),
      provider_id_(provider_id),
      provider_type_(provider_type),
      parent_frame_security_level_(parent_frame_security_level),
      context_(context),
      dispatcher_host_(dispatcher_host),
      allow_association_(true) {
  DCHECK_NE(SERVICE_WORKER_PROVIDER_UNKNOWN, provider_type_);

  // PlzNavigate
  CHECK(render_process_id != ChildProcessHost::kInvalidUniqueID ||
        IsBrowserSideNavigationEnabled());

  if (provider_type_ == SERVICE_WORKER_PROVIDER_FOR_CONTROLLER) {
    // Actual thread id is set when the service worker context gets started.
    render_thread_id_ = kInvalidEmbeddedWorkerThreadId;
  }
  context_->RegisterProviderHostByClientID(client_uuid_, this);
}

ServiceWorkerProviderHost::~ServiceWorkerProviderHost() {
  if (context_)
    context_->UnregisterProviderHostByClientID(client_uuid_);

  // Clear docurl so the deferred activation of a waiting worker
  // won't associate the new version with a provider being destroyed.
  document_url_ = GURL();
  if (controlling_version_.get())
    controlling_version_->RemoveControllee(this);

  RemoveAllMatchingRegistrations();

  for (const GURL& pattern : associated_patterns_)
    DecreaseProcessReference(pattern);
}

int ServiceWorkerProviderHost::frame_id() const {
  if (provider_type_ == SERVICE_WORKER_PROVIDER_FOR_WINDOW)
    return route_id_;
  return MSG_ROUTING_NONE;
}

bool ServiceWorkerProviderHost::IsContextSecureForServiceWorker() const {
  // |document_url_| may be empty if loading has not begun, or
  // ServiceWorkerRequestHandler didn't handle the load (because e.g. another
  // handler did first, or the initial request URL was such that
  // OriginCanAccessServiceWorkers returned false).
  if (!document_url_.is_valid())
    return false;
  if (!OriginCanAccessServiceWorkers(document_url_))
    return false;

  if (is_parent_frame_secure())
    return true;

  std::set<std::string> schemes;
  GetContentClient()->browser()->GetSchemesBypassingSecureContextCheckWhitelist(
      &schemes);
  return schemes.find(document_url().scheme()) != schemes.end();
}

void ServiceWorkerProviderHost::OnVersionAttributesChanged(
    ServiceWorkerRegistration* registration,
    ChangedVersionAttributesMask changed_mask,
    const ServiceWorkerRegistrationInfo& info) {
  if (!get_ready_callback_ || get_ready_callback_->called)
    return;
  if (changed_mask.active_changed() && registration->active_version()) {
    // Wait until the state change so we don't send the get for ready
    // registration complete message before set version attributes message.
    registration->active_version()->RegisterStatusChangeCallback(base::Bind(
          &ServiceWorkerProviderHost::ReturnRegistrationForReadyIfNeeded,
          AsWeakPtr()));
  }
}

void ServiceWorkerProviderHost::OnRegistrationFailed(
    ServiceWorkerRegistration* registration) {
  if (associated_registration_ == registration)
    DisassociateRegistration();
  RemoveMatchingRegistration(registration);
}

void ServiceWorkerProviderHost::OnRegistrationFinishedUninstalling(
    ServiceWorkerRegistration* registration) {
  RemoveMatchingRegistration(registration);
}

void ServiceWorkerProviderHost::OnSkippedWaiting(
    ServiceWorkerRegistration* registration) {
  if (associated_registration_ != registration)
    return;
  // A client is "using" a registration if it is controlled by the active
  // worker of the registration. skipWaiting doesn't cause a client to start
  // using the registration.
  if (!controlling_version_)
    return;
  ServiceWorkerVersion* active_version = registration->active_version();
  DCHECK(active_version);
  DCHECK_EQ(active_version->status(), ServiceWorkerVersion::ACTIVATING);
  SetControllerVersionAttribute(active_version,
                                true /* notify_controllerchange */);
}

void ServiceWorkerProviderHost::SetDocumentUrl(const GURL& url) {
  DCHECK(!url.has_ref());
  document_url_ = url;
  if (IsProviderForClient())
    SyncMatchingRegistrations();
}

void ServiceWorkerProviderHost::SetTopmostFrameUrl(const GURL& url) {
  topmost_frame_url_ = url;
}

void ServiceWorkerProviderHost::SetControllerVersionAttribute(
    ServiceWorkerVersion* version,
    bool notify_controllerchange) {
  CHECK(!version || IsContextSecureForServiceWorker());
  if (version == controlling_version_.get())
    return;

  scoped_refptr<ServiceWorkerVersion> previous_version = controlling_version_;
  controlling_version_ = version;
  if (version)
    version->AddControllee(this);
  if (previous_version.get())
    previous_version->RemoveControllee(this);

  if (!dispatcher_host_)
    return;  // Could be NULL in some tests.

  // SetController message should be sent only for controllees.
  DCHECK(IsProviderForClient());
  Send(new ServiceWorkerMsg_SetControllerServiceWorker(
      render_thread_id_, provider_id(), GetOrCreateServiceWorkerHandle(version),
      notify_controllerchange));
}

void ServiceWorkerProviderHost::SetHostedVersion(
    ServiceWorkerVersion* version) {
  DCHECK(!IsProviderForClient());
  DCHECK_EQ(EmbeddedWorkerStatus::STARTING, version->running_status());
  DCHECK_EQ(render_process_id_, version->embedded_worker()->process_id());
  running_hosted_version_ = version;
}

bool ServiceWorkerProviderHost::IsProviderForClient() const {
  switch (provider_type_) {
    case SERVICE_WORKER_PROVIDER_FOR_WINDOW:
    case SERVICE_WORKER_PROVIDER_FOR_WORKER:
    case SERVICE_WORKER_PROVIDER_FOR_SHARED_WORKER:
      return true;
    case SERVICE_WORKER_PROVIDER_FOR_CONTROLLER:
      return false;
    case SERVICE_WORKER_PROVIDER_UNKNOWN:
      NOTREACHED() << provider_type_;
  }
  NOTREACHED() << provider_type_;
  return false;
}

blink::WebServiceWorkerClientType ServiceWorkerProviderHost::client_type()
    const {
  switch (provider_type_) {
    case SERVICE_WORKER_PROVIDER_FOR_WINDOW:
      return blink::WebServiceWorkerClientTypeWindow;
    case SERVICE_WORKER_PROVIDER_FOR_WORKER:
      return blink::WebServiceWorkerClientTypeWorker;
    case SERVICE_WORKER_PROVIDER_FOR_SHARED_WORKER:
      return blink::WebServiceWorkerClientTypeSharedWorker;
    case SERVICE_WORKER_PROVIDER_FOR_CONTROLLER:
    case SERVICE_WORKER_PROVIDER_UNKNOWN:
      NOTREACHED() << provider_type_;
  }
  NOTREACHED() << provider_type_;
  return blink::WebServiceWorkerClientTypeWindow;
}

void ServiceWorkerProviderHost::AssociateRegistration(
    ServiceWorkerRegistration* registration,
    bool notify_controllerchange) {
  CHECK(IsContextSecureForServiceWorker());
  DCHECK(CanAssociateRegistration(registration));
  associated_registration_ = registration;
  AddMatchingRegistration(registration);
  SendAssociateRegistrationMessage();
  SetControllerVersionAttribute(registration->active_version(),
                                notify_controllerchange);
}

void ServiceWorkerProviderHost::DisassociateRegistration() {
  queued_events_.clear();
  if (!associated_registration_.get())
    return;
  associated_registration_ = NULL;
  SetControllerVersionAttribute(NULL, false /* notify_controllerchange */);

  if (!dispatcher_host_)
    return;

  // Disassociation message should be sent only for controllees.
  DCHECK(IsProviderForClient());
  Send(new ServiceWorkerMsg_DisassociateRegistration(
      render_thread_id_, provider_id()));
}

void ServiceWorkerProviderHost::AddMatchingRegistration(
    ServiceWorkerRegistration* registration) {
  DCHECK(
      ServiceWorkerUtils::ScopeMatches(registration->pattern(), document_url_));
  if (!IsContextSecureForServiceWorker())
    return;
  size_t key = registration->pattern().spec().size();
  if (base::ContainsKey(matching_registrations_, key))
    return;
  IncreaseProcessReference(registration->pattern());
  registration->AddListener(this);
  matching_registrations_[key] = registration;
  ReturnRegistrationForReadyIfNeeded();
}

void ServiceWorkerProviderHost::RemoveMatchingRegistration(
    ServiceWorkerRegistration* registration) {
  size_t key = registration->pattern().spec().size();
  DCHECK(base::ContainsKey(matching_registrations_, key));
  DecreaseProcessReference(registration->pattern());
  registration->RemoveListener(this);
  matching_registrations_.erase(key);
}

ServiceWorkerRegistration*
ServiceWorkerProviderHost::MatchRegistration() const {
  ServiceWorkerRegistrationMap::const_reverse_iterator it =
      matching_registrations_.rbegin();
  for (; it != matching_registrations_.rend(); ++it) {
    if (it->second->is_uninstalled())
      continue;
    if (it->second->is_uninstalling())
      return nullptr;
    return it->second.get();
  }
  return nullptr;
}

void ServiceWorkerProviderHost::NotifyControllerLost() {
  SetControllerVersionAttribute(nullptr, true /* notify_controllerchange */);
}

std::unique_ptr<ServiceWorkerRequestHandler>
ServiceWorkerProviderHost::CreateRequestHandler(
    FetchRequestMode request_mode,
    FetchCredentialsMode credentials_mode,
    FetchRedirectMode redirect_mode,
    ResourceType resource_type,
    RequestContextType request_context_type,
    RequestContextFrameType frame_type,
    base::WeakPtr<storage::BlobStorageContext> blob_storage_context,
    scoped_refptr<ResourceRequestBodyImpl> body,
    bool skip_service_worker) {
  // |skip_service_worker| is meant to apply to requests that could be handled
  // by a service worker, as opposed to requests for the service worker script
  // itself. So ignore it here for the service worker script and its imported
  // scripts.
  // TODO(falken): Really it should be treated as an error to set
  // |skip_service_worker| for requests to start the service worker, but it's
  // difficult to fix that renderer-side, since we don't know whether a request
  // is for a service worker without access to IsHostToRunningServiceWorker() as
  // that state is stored browser-side.
  if (IsHostToRunningServiceWorker() &&
      (resource_type == RESOURCE_TYPE_SERVICE_WORKER ||
       resource_type == RESOURCE_TYPE_SCRIPT)) {
    skip_service_worker = false;
  }
  if (skip_service_worker) {
    if (!ServiceWorkerUtils::IsMainResourceType(resource_type))
      return std::unique_ptr<ServiceWorkerRequestHandler>();
    return base::MakeUnique<ServiceWorkerURLTrackingRequestHandler>(
        context_, AsWeakPtr(), blob_storage_context, resource_type);
  }
  if (IsHostToRunningServiceWorker()) {
    return base::MakeUnique<ServiceWorkerContextRequestHandler>(
        context_, AsWeakPtr(), blob_storage_context, resource_type);
  }
  if (ServiceWorkerUtils::IsMainResourceType(resource_type) ||
      controlling_version()) {
    return base::MakeUnique<ServiceWorkerControlleeRequestHandler>(
        context_, AsWeakPtr(), blob_storage_context, request_mode,
        credentials_mode, redirect_mode, resource_type, request_context_type,
        frame_type, body);
  }
  return std::unique_ptr<ServiceWorkerRequestHandler>();
}

ServiceWorkerObjectInfo
ServiceWorkerProviderHost::GetOrCreateServiceWorkerHandle(
    ServiceWorkerVersion* version) {
  DCHECK(dispatcher_host_);
  if (!context_ || !version)
    return ServiceWorkerObjectInfo();
  ServiceWorkerHandle* handle = dispatcher_host_->FindServiceWorkerHandle(
      provider_id(), version->version_id());
  if (handle) {
    handle->IncrementRefCount();
    return handle->GetObjectInfo();
  }

  std::unique_ptr<ServiceWorkerHandle> new_handle(
      ServiceWorkerHandle::Create(context_, AsWeakPtr(), version));
  handle = new_handle.get();
  dispatcher_host_->RegisterServiceWorkerHandle(std::move(new_handle));
  return handle->GetObjectInfo();
}

bool ServiceWorkerProviderHost::CanAssociateRegistration(
    ServiceWorkerRegistration* registration) {
  if (!context_)
    return false;
  if (running_hosted_version_.get())
    return false;
  if (!registration || associated_registration_.get() || !allow_association_)
    return false;
  return true;
}

void ServiceWorkerProviderHost::PostMessageToClient(
    ServiceWorkerVersion* version,
    const base::string16& message,
    const std::vector<int>& sent_message_ports) {
  if (!dispatcher_host_)
    return;  // Could be NULL in some tests.

  std::vector<int> new_routing_ids;
  dispatcher_host_->message_port_message_filter()->
      UpdateMessagePortsWithNewRoutes(sent_message_ports,
                                      &new_routing_ids);

  ServiceWorkerMsg_MessageToDocument_Params params;
  params.thread_id = kDocumentMainThreadId;
  params.provider_id = provider_id();
  params.service_worker_info = GetOrCreateServiceWorkerHandle(version);
  params.message = message;
  params.message_ports = sent_message_ports;
  params.new_routing_ids = new_routing_ids;
  Send(new ServiceWorkerMsg_MessageToDocument(params));
}

void ServiceWorkerProviderHost::AddScopedProcessReferenceToPattern(
    const GURL& pattern) {
  associated_patterns_.push_back(pattern);
  IncreaseProcessReference(pattern);
}

void ServiceWorkerProviderHost::ClaimedByRegistration(
    ServiceWorkerRegistration* registration) {
  DCHECK(registration->active_version());
  if (registration == associated_registration_) {
    SetControllerVersionAttribute(registration->active_version(),
                                  true /* notify_controllerchange */);
  } else if (allow_association_) {
    DisassociateRegistration();
    AssociateRegistration(registration, true /* notify_controllerchange */);
  }
}

bool ServiceWorkerProviderHost::GetRegistrationForReady(
    const GetRegistrationForReadyCallback& callback) {
  if (get_ready_callback_)
    return false;
  get_ready_callback_.reset(new OneShotGetReadyCallback(callback));
  ReturnRegistrationForReadyIfNeeded();
  return true;
}

void ServiceWorkerProviderHost::PrepareForCrossSiteTransfer() {
  DCHECK_NE(ChildProcessHost::kInvalidUniqueID, render_process_id_);
  DCHECK_NE(MSG_ROUTING_NONE, route_id_);
  DCHECK_EQ(kDocumentMainThreadId, render_thread_id_);
  DCHECK_NE(SERVICE_WORKER_PROVIDER_UNKNOWN, provider_type_);

  for (const GURL& pattern : associated_patterns_)
    DecreaseProcessReference(pattern);

  for (auto& key_registration : matching_registrations_)
    DecreaseProcessReference(key_registration.second->pattern());

  if (associated_registration_.get()) {
    if (dispatcher_host_) {
      Send(new ServiceWorkerMsg_DisassociateRegistration(
          render_thread_id_, provider_id()));
    }
  }

  render_process_id_ = ChildProcessHost::kInvalidUniqueID;
  route_id_ = MSG_ROUTING_NONE;
  render_thread_id_ = kInvalidEmbeddedWorkerThreadId;
  provider_id_ = kInvalidServiceWorkerProviderId;
  provider_type_ = SERVICE_WORKER_PROVIDER_UNKNOWN;
  dispatcher_host_ = nullptr;
}

void ServiceWorkerProviderHost::CompleteCrossSiteTransfer(
    int new_process_id,
    int new_frame_id,
    int new_provider_id,
    ServiceWorkerProviderType new_provider_type,
    ServiceWorkerDispatcherHost* new_dispatcher_host) {
  DCHECK_EQ(ChildProcessHost::kInvalidUniqueID, render_process_id_);
  DCHECK_NE(ChildProcessHost::kInvalidUniqueID, new_process_id);
  DCHECK_NE(MSG_ROUTING_NONE, new_frame_id);

  render_thread_id_ = kDocumentMainThreadId;
  provider_id_ = new_provider_id;
  provider_type_ = new_provider_type;

  FinalizeInitialization(new_process_id, new_frame_id, new_dispatcher_host);
}

// PlzNavigate
void ServiceWorkerProviderHost::CompleteNavigationInitialized(
    int process_id,
    int frame_routing_id,
    ServiceWorkerDispatcherHost* dispatcher_host) {
  CHECK(IsBrowserSideNavigationEnabled());
  DCHECK_EQ(ChildProcessHost::kInvalidUniqueID, render_process_id_);
  DCHECK_EQ(SERVICE_WORKER_PROVIDER_FOR_WINDOW, provider_type_);
  DCHECK_EQ(kDocumentMainThreadId, render_thread_id_);

  DCHECK_NE(ChildProcessHost::kInvalidUniqueID, process_id);
  DCHECK_NE(MSG_ROUTING_NONE, frame_routing_id);

  FinalizeInitialization(process_id, frame_routing_id, dispatcher_host);
}

void ServiceWorkerProviderHost::SendUpdateFoundMessage(
    int registration_handle_id) {
  if (!dispatcher_host_)
    return;  // Could be nullptr in some tests.

  if (!IsReadyToSendMessages()) {
    queued_events_.push_back(
        base::Bind(&ServiceWorkerProviderHost::SendUpdateFoundMessage,
                   AsWeakPtr(), registration_handle_id));
    return;
  }

  Send(new ServiceWorkerMsg_UpdateFound(
      render_thread_id_, registration_handle_id));
}

void ServiceWorkerProviderHost::SendSetVersionAttributesMessage(
    int registration_handle_id,
    ChangedVersionAttributesMask changed_mask,
    ServiceWorkerVersion* installing_version,
    ServiceWorkerVersion* waiting_version,
    ServiceWorkerVersion* active_version) {
  if (!dispatcher_host_)
    return;  // Could be nullptr in some tests.
  if (!changed_mask.changed())
    return;

  if (!IsReadyToSendMessages()) {
    queued_events_.push_back(base::Bind(
        &ServiceWorkerProviderHost::SendSetVersionAttributesMessage,
        AsWeakPtr(), registration_handle_id, changed_mask,
        base::RetainedRef(installing_version),
        base::RetainedRef(waiting_version), base::RetainedRef(active_version)));
    return;
  }

  ServiceWorkerVersionAttributes attrs;
  if (changed_mask.installing_changed())
    attrs.installing = GetOrCreateServiceWorkerHandle(installing_version);
  if (changed_mask.waiting_changed())
    attrs.waiting = GetOrCreateServiceWorkerHandle(waiting_version);
  if (changed_mask.active_changed())
    attrs.active = GetOrCreateServiceWorkerHandle(active_version);

  Send(new ServiceWorkerMsg_SetVersionAttributes(
      render_thread_id_, registration_handle_id, changed_mask.changed(),
      attrs));
}

void ServiceWorkerProviderHost::SendServiceWorkerStateChangedMessage(
    int worker_handle_id,
    blink::WebServiceWorkerState state) {
  if (!dispatcher_host_)
    return;

  if (!IsReadyToSendMessages()) {
    queued_events_.push_back(base::Bind(
        &ServiceWorkerProviderHost::SendServiceWorkerStateChangedMessage,
        AsWeakPtr(), worker_handle_id, state));
    return;
  }

  Send(new ServiceWorkerMsg_ServiceWorkerStateChanged(
      render_thread_id_, worker_handle_id, state));
}

void ServiceWorkerProviderHost::SetReadyToSendMessagesToWorker(
    int render_thread_id) {
  DCHECK(!IsReadyToSendMessages());
  render_thread_id_ = render_thread_id;

  for (const auto& event : queued_events_)
    event.Run();
  queued_events_.clear();
}

void ServiceWorkerProviderHost::SendAssociateRegistrationMessage() {
  if (!dispatcher_host_)
    return;

  ServiceWorkerRegistrationHandle* handle =
      dispatcher_host_->GetOrCreateRegistrationHandle(
          AsWeakPtr(), associated_registration_.get());

  ServiceWorkerVersionAttributes attrs;
  attrs.installing = GetOrCreateServiceWorkerHandle(
      associated_registration_->installing_version());
  attrs.waiting = GetOrCreateServiceWorkerHandle(
      associated_registration_->waiting_version());
  attrs.active = GetOrCreateServiceWorkerHandle(
      associated_registration_->active_version());

  // Association message should be sent only for controllees.
  DCHECK(IsProviderForClient());
  dispatcher_host_->Send(new ServiceWorkerMsg_AssociateRegistration(
      render_thread_id_, provider_id(), handle->GetObjectInfo(), attrs));
}

void ServiceWorkerProviderHost::SyncMatchingRegistrations() {
  DCHECK(context_);
  RemoveAllMatchingRegistrations();
  const auto& registrations = context_->GetLiveRegistrations();
  for (const auto& key_registration : registrations) {
    ServiceWorkerRegistration* registration = key_registration.second;
    if (!registration->is_uninstalled() &&
        ServiceWorkerUtils::ScopeMatches(registration->pattern(),
                                         document_url_))
      AddMatchingRegistration(registration);
  }
}

void ServiceWorkerProviderHost::RemoveAllMatchingRegistrations() {
  for (const auto& it : matching_registrations_) {
    ServiceWorkerRegistration* registration = it.second.get();
    DecreaseProcessReference(registration->pattern());
    registration->RemoveListener(this);
  }
  matching_registrations_.clear();
}

void ServiceWorkerProviderHost::IncreaseProcessReference(
    const GURL& pattern) {
  if (context_ && context_->process_manager()) {
    context_->process_manager()->AddProcessReferenceToPattern(
        pattern, render_process_id_);
  }
}

void ServiceWorkerProviderHost::DecreaseProcessReference(
    const GURL& pattern) {
  if (context_ && context_->process_manager()) {
    context_->process_manager()->RemoveProcessReferenceFromPattern(
        pattern, render_process_id_);
  }
}

void ServiceWorkerProviderHost::ReturnRegistrationForReadyIfNeeded() {
  if (!get_ready_callback_ || get_ready_callback_->called)
    return;
  ServiceWorkerRegistration* registration = MatchRegistration();
  if (!registration)
    return;
  if (registration->active_version()) {
    get_ready_callback_->callback.Run(registration);
    get_ready_callback_->callback.Reset();
    get_ready_callback_->called = true;
    return;
  }
}

bool ServiceWorkerProviderHost::IsReadyToSendMessages() const {
  return render_thread_id_ != kInvalidEmbeddedWorkerThreadId;
}

bool ServiceWorkerProviderHost::IsContextAlive() {
  return context_ != nullptr;
}

void ServiceWorkerProviderHost::Send(IPC::Message* message) const {
  DCHECK(dispatcher_host_);
  DCHECK(IsReadyToSendMessages());
  dispatcher_host_->Send(message);
}

void ServiceWorkerProviderHost::FinalizeInitialization(
    int process_id,
    int frame_routing_id,
    ServiceWorkerDispatcherHost* dispatcher_host) {
  render_process_id_ = process_id;
  route_id_ = frame_routing_id;
  dispatcher_host_ = dispatcher_host;

  for (const GURL& pattern : associated_patterns_)
    IncreaseProcessReference(pattern);

  for (auto& key_registration : matching_registrations_)
    IncreaseProcessReference(key_registration.second->pattern());

  if (associated_registration_.get()) {
    SendAssociateRegistrationMessage();
    if (dispatcher_host_ && associated_registration_->active_version()) {
      Send(new ServiceWorkerMsg_SetControllerServiceWorker(
          render_thread_id_, provider_id(),
          GetOrCreateServiceWorkerHandle(
              associated_registration_->active_version()),
          false /* shouldNotifyControllerChange */));
    }
  }
}

}  // namespace content


text:
/**
 * @author Bart Whiteley
 * @author Dan Nuffer
 */

#include "OW_config.h"
#include "OW_ClientAuthCBIFC.hpp"

namespace OW_NAMESPACE
{

//////////////////////////////////////////////////////////////////////////////
ClientAuthCBIFC::~ClientAuthCBIFC()
{
}

} // end namespace OW_NAMESPACE

redpajama_set_name: RedPajamaGithub


text:
package com.jw.cool.xuanmusicplayer.utils;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.channels.FileChannel;
import java.util.List;

//import org.apache.http.util.EncodingUtils;

public class HandlerFile {
	static String SDCardPath;
	static{
		SDCardPath = HandlerSDCard.getSDCardPath();
	}
	static String DEFAULT_ENCODE = "UTF-8";
	public static boolean isEmpty(String path){
		if(path == null || path.length() == 0){
			return true;
		}
		return false;
	}

	/**
     * 新建文件.
     *
     * @param path 文件路径
     * @throws Exception
     */
    public static File createFile(String path) throws Exception {
        // 获得文件对象
        File f = new File(path);
        if (f.exists()) {
        	// 如果路径不存在,则创建
            if (!f.getParentFile().exists()) {
                f.getParentFile().mkdirs();
            }
            f.createNewFile();
        }

        return f;
    }

	/**
     * 新建目录.
     *
     * @param path 文件路径
     * @throws Exception
     */
    public static File createDirectory(String path) throws Exception {
        // 获得文件对象
        File f = new File(path);
        if (!f.exists()) {
            // 如果路径不存在,则创建
            f.mkdirs();
        }

        return f;
    }

    //读文件
    public static String readFile(String fileName) throws IOException {
        File file = new File(fileName);
        FileInputStream fis = new FileInputStream(file);
        int length = fis.available();
        byte [] buffer = new byte[length];
		fis.read(buffer);
		String res = new String(buffer, DEFAULT_ENCODE);
		fis.close();
		return res;
    }

    //写文件
    public static void writeFile(String fileName, String write_str) throws IOException{
        File file = new File(fileName);
        FileOutputStream fos = new FileOutputStream(file);
        byte [] bytes = write_str.getBytes(DEFAULT_ENCODE);
        fos.write(bytes);
        fos.close();
    }

//    /**
//     * 读取文件中内容
//     *
//     * @param path
//     * @return
//     * @throws IOException
//     */
//    public static String readFileToString(String path) throws IOException {
//        String resultStr = null;
//        FileInputStream fis = null;
//        try {
//            fis = new FileInputStream(path);
//            byte[] inBuf = new byte[2048];
//            int len = inBuf.length;
//            int off = 0;
//            int ret = 0;
//            while ((ret = fis.read(inBuf, off, len)) > 0) {
//                off += ret;
//                len -= ret;
//            }
//            resultStr = new String(new String(inBuf, 0, off, DEFAULT_ENCODE).getBytes());
//        } finally {
//            if (fis != null)
//                fis.close();
//        }
//        return resultStr;
//    }

    /**
     * 文件转成字节数组
     *
     * @param path
     * @return
     * @throws IOException
     */
    public static byte[] readFileToBytes(String path) throws IOException {
        byte[] b = null;
        InputStream is = null;
        File f = new File(path);
        try {
            is = new FileInputStream(f);
            b = new byte[(int) f.length()];
            is.read(b);
        } finally {
            if (is != null)
                is.close();
        }
        return b;
    }

    /**
     * 将byte写入文件中
     *
     * @param fileByte
     * @param filePath
     * @throws IOException
     */
    public static void byteToFile(byte[] fileByte, String filePath) throws IOException {
        OutputStream os = null;
        try {
            os = new FileOutputStream(new File(filePath));
            os.write(fileByte);
            os.flush();
        } finally {
            if (os != null)
                os.close();
        }
    }

    /**
     * 保存文件(文件不存在会自动创建).
     *
     * @param path 文件路径
     * @param content 文件内容
     * @throws Exception
     */
    public static void saveFile(String path, String content) throws Exception {
        saveFile(path, content, DEFAULT_ENCODE);
    }

    /**
     * 保存文件(文件不存在会自动创建).
     *
     * @param path 文件路径
     * @param content 文件内容
     * @param encoding 编码(UTF-8/gb2312/...)
     * @throws Exception
     */
    public static void saveFile(String path, String content, String encoding) throws Exception {
        FileOutputStream fileOutputStream = null;
        BufferedOutputStream bw = null;
        try {
            // 获得文件对象
            File f = new File(path);
            // 默认编码UTF-8
            encoding = (isEmpty(encoding)) ? DEFAULT_ENCODE : encoding;
            // 如果路径不存在,则创建
            if (!f.getParentFile().exists()) {
                f.getParentFile().mkdirs();
            }
            // 开始保存文件
            fileOutputStream = new FileOutputStream(path);
            bw = new BufferedOutputStream(fileOutputStream);
            bw.write(content.getBytes(encoding));
        } catch (Exception e) {
//            L.d("保存文件错误.path=" + path + ",content=" + content + ",encoding=" + encoding, e);
            throw e;
        } finally {
            if (bw != null) {
                try {
                    bw.close();
                } catch (IOException e1) {
                }
            }
            if (fileOutputStream != null) {
                try {
                    fileOutputStream.close();
                } catch (IOException e1) {
                }
            }
        }
    }

    //递归删除该路径对应的所有文件
    public static boolean delete(String path){
    	System.out.println("path " + path);
    	Boolean isDelSuccessfully = true;
    	File file = new File(path);
    	if(file.isDirectory()){
    		String[] fileList = file.list();
    		for(int i = 0; i < fileList.length; i++){
    			isDelSuccessfully = isDelSuccessfully && delete(file.getAbsolutePath() + file.separator + fileList[i]);
    		}
    	}else{
    		System.out.println("file is not a dir " + file.getAbsolutePath());
    	}

    	System.out.println("file " + file.getAbsolutePath());
    	file.delete();
    	return isDelSuccessfully;
    }

    //按文件路径删除多个文件
    public static boolean delete(List<String> pathList){
        Boolean isDelSuccessfully = true;
        File file;
        for (String path:pathList) {
            file = new File(path);
            if(file != null){
                isDelSuccessfully = isDelSuccessfully && file.delete();
            }
        }
        return true;
    }

    /**
     * 使用文件通道的方式复制文件
     *
     * @param source 源文件
     * @param dest 复制到的新文件
     */

     public static void fileChannelCopy(File source, File dest) {
    	 System.out.println("source " + source.getAbsolutePath());
    	 System.out.println("dest " + dest.getAbsolutePath());
         FileInputStream fi = null;
         FileOutputStream fo = null;
         FileChannel in = null;
         FileChannel out = null;
         try {
             fi = new FileInputStream(source);
             fo = new FileOutputStream(dest);
             in = fi.getChannel();//得到对应的文件通道
             out = fo.getChannel();//得到对应的文件通道
             in.transferTo(0, in.size(), out);//连接两个通道,并且从in通道读取,然后写入out通道
         } catch (IOException e) {
             e.printStackTrace();
         } finally {
             try {
                 fi.close();
                 in.close();
                 fo.close();
                 out.close();
             } catch (IOException e) {
                 e.printStackTrace();
             }
         }
     }

  //复制一个文件夹下所有的文件到另一个文件夹下
    public static void copy(String source, String destDir){
    	System.out.println("source " + source + " destDir " + destDir);
    	File tempSourceFile = new File(source);
    	System.out.println("tempSourceFile " + tempSourceFile.getAbsolutePath());
    	File tempDestFile = null;

    	if(tempSourceFile.isDirectory()){
    		String[] fileList = tempSourceFile.list();
    		System.out.println("fileList " + fileList);
    		for(int i = 0; i < fileList.length; i++){
//    			System.out.println("fileList[i] " + fileList[i]);
//    			System.out.println("tempSourceFile.getname " + tempSourceFile.getName());
//    			System.out.println("tempSourceFile.getAbsolutePath " + tempSourceFile.getAbsolutePath());
    			copy(tempSourceFile.getAbsolutePath() + File.separator + fileList[i], destDir + File.separator + tempSourceFile.getName());
    		}
    	}else{
    		try {
				tempDestFile = createFile(destDir  + File.separator + tempSourceFile.getName());
				fileChannelCopy(tempSourceFile, tempDestFile);
			} catch (Exception e) {
				// TODO Auto-generated catch block
//				System.out.println("destDir" + destDir);
				e.printStackTrace();
			}

    	}
    }

//	void test(){
//
//		//7.读取文件
//		//import java.io.*;
//		// 逐行读取数据
//		FileReader fr = new FileReader(str1);
//		BufferedReader br = new BufferedReader(fr);
//		String str2 = br.readLine();
//		while (str2 != null) {
//			str2 = br.readLine();
//		}
//		br.close();
//		fr.close();
//
//		//8.写入文件
//		//import java.io.*;
//		// 将数据写入文件
//		try {
//			FileWriter fw = new FileWriter(str1);
//			fw.write(str2);
//			fw.flush();
//			fw.close();
//		} catch (IOException e) {
//			e.printStackTrace();
//		}
//
//		//9.写入随机文件
//		//import java.io.*;
//		try {
//			RandomAccessFile logFile=new RandomAccessFile(str1,"rw");
//			long lg=logFile.length();
//			logFile.seek(str2);
//			logFile.writeByte(str3);
//		}catch(IOException ioe){
//			System.out.println("无法写入文件:"+ioe.getMessage());
//		}
//
//		//10.读取文件属性
//		//import java.io.*;
//		// 文件属性的取得
//		File f = new File(str1);
//		if (af.exists()) {
//			System.out.println(f.getName() + "的属性如下: 文件长度为:" + f.length());
//			System.out.println(f.isFile() ? "是文件" : "不是文件");
//			System.out.println(f.isDirectory() ? "是目录" : "不是目录");
//			System.out.println(f.canRead() ? "可读取" : "不");
//			System.out.println(f.canWrite() ? "是隐藏文件" : "");
//			System.out.println("文件夹的最后修改日期为:" + new Date(f.lastModified()));
//			} else {
//			System.out.println(f.getName() + "的属性如下:");
//			System.out.println(f.isFile() ? "是文件" : "不是文件");
//			System.out.println(f.isDirectory() ? "是目录" : "不是目录");
//			System.out.println(f.canRead() ? "可读取" : "不");
//			System.out.println(f.canWrite() ? "是隐藏文件" : "");
//			System.out.println("文件的最后修改日期为:" + new Date(f.lastModified()));
//		}
//		if(f.canRead()){
//			str2
//		}
//		if(f.canWrite()){
//			str3
//		}
//
//		//11.写入属性
//		//import java.io.*;
//		File filereadonly=new File(str1);
//		try {
//			boolean b=filereadonly.setReadOnly();
//		}
//		catch (Exception e) {
//			System.out.println("拒绝写访问:"+ e.printStackTrace());
//		}
//
}


text:
//
//  LoadingStyleProgressView.m
//  MierMilitaryNews
//
//  Created by 李响 on 15/9/11.
//  Copyright (c) 2015年 miercn. All rights reserved.
//

#import "LoadingStyleProgressView.h"

#import "LXProgressView.h"

@interface LoadingStyleProgressView ()

@property (nonatomic , strong ) UIImageView *circleImageView;//圆形图片视图

@property (nonatomic , strong ) UILabel *titleLabel;//标题Label

@property (nonatomic , strong ) UIImageView *titleImageView;//标题图片视图

@end

@implementation LoadingStyleProgressView

-(void)dealloc{

    _circleImageView = nil;

    _titleLabel = nil;

    _titleImageView = nil;

}

- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {

        NSMutableArray *images = [NSMutableArray array];

        for (NSInteger i = 1 ; i < 14; i ++) {

            [images addObject:[UIImage imageNamed:[NSString stringWithFormat:@"no_network%ld" , (long)i]]];
        }

        //初始化圆形图片视图

        _circleImageView = [[UIImageView alloc]initWithFrame:CGRectMake(0 , 0 , 100 , 100 )];

        _circleImageView.center = CGPointMake(CGRectGetWidth(self.frame) / 2 , CGRectGetHeight(self.frame) / 2 - 40 );

        _circleImageView.backgroundColor = [UIColor clearColor];

        _circleImageView.animationImages = images;

        _circleImageView.animationDuration = 1.0f;

        [self addSubview:_circleImageView];

        //初始化标题Label

        _titleLabel = [[UILabel alloc]initWithFrame:CGRectMake(0 ,  _circleImageView.frame.origin.y + CGRectGetHeight(_circleImageView.frame) + 10, CGRectGetWidth(self.frame), 30)];

        _titleLabel.font = [UIFont systemFontOfSize:14.0f];

        _titleLabel.textColor = [UIColor lightGrayColor];

        _titleLabel.textAlignment = NSTextAlignmentCenter;

        [self addSubview:_titleLabel];

        [self addSubview:self.titleImageView];

        self.titleImageView.hidden = YES;

    }

    return self;
}

-(void)layoutSubviews{

    [super layoutSubviews];

    _titleLabel.frame = CGRectMake(0 ,  _circleImageView.frame.origin.y + CGRectGetHeight(_circleImageView.frame) + 10, CGRectGetWidth(self.frame), 30);

    _titleImageView.frame = CGRectMake(0 , _circleImageView.frame.origin.y + CGRectGetHeight(_circleImageView.frame) + 10, 117 , 32);

    _titleImageView.center = CGPointMake(CGRectGetWidth(self.frame) / 2 , _titleImageView.center.y);

    _circleImageView.center = CGPointMake(CGRectGetWidth(self.frame) / 2 , CGRectGetHeight(self.frame) / 2 - 40 );

}

#pragma mark ---获取标题

-(void)setTitle:(NSString *)title{

    if (_title != title) {

        _title = title;

    }

    _titleLabel.text = title;

}

#pragma mark ---开启加载动画

- (void)startLoadingAnimation{

    //判断是否设置了标题文字 如果没有 显示标题图片

    if (!_title) {

        self.titleImageView.hidden = NO;

    }

//    [_circleImageView.layer addAnimation:[self rotationGear:- M_PI * 6.0f] forKey:@"Rotation"];

    [_circleImageView startAnimating];

}

#pragma mark ---停止加载动画

- (void)stopLoadingAnimation{

//    [_circleImageView.layer removeAnimationForKey:@"Rotation"];

    [_circleImageView stopAnimating];

}

#pragma mark ---旋转动画

-(CABasicAnimation *)rotationGear:(float)degree{

    CABasicAnimation* rotationAnimation;

    rotationAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];

    rotationAnimation.toValue = [NSNumber numberWithFloat: degree ];

    [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];

    rotationAnimation.duration = 2;

    rotationAnimation.repeatCount = INT_MAX;//设置到最大的整数值

    rotationAnimation.cumulative = NO;

    rotationAnimation.removedOnCompletion = NO;

    rotationAnimation.fillMode = kCAFillModeForwards;

    return rotationAnimation;

}

#pragma mark ---LazyLoading

- (UIImageView *)titleImageView{

    if (!_titleImageView) {

        _titleImageView = [[UIImageView alloc]initWithFrame:CGRectMake(0 , _circleImageView.frame.origin.y + CGRectGetHeight(_circleImageView.frame) + 10, 117 , 32)];

        _titleImageView.center = CGPointMake(CGRectGetWidth(self.frame) / 2 , _titleImageView.center.y);

        _titleImageView.image = LEEImageFromIdentifier([LEETheme currentThemeTag], detail_load_image);
    }

    return _titleImageView;

}

/*
 // Only override drawRect: if you perform custom drawing.
 // An empty implementation adversely affects performance during animation.
 - (void)drawRect:(CGRect)rect {
 // Drawing code
 }
 */

@end


text:
1. If you wish to call the API directly
1.1 Set the `API_URL` to the desired url
1.2 Run the dev server with `ng serve`

2. If you wish to proxy pass the /api URL you need to do the followings:
    2.1 Change the `API_URL` to `/api`
    2.2 Change the `target` from `proxy.conf.json`
    2.3 Run the dev server with `npm start`
* `API_URL` can be found in `src/app/app.config.ts`

## Description

Basic book keeping for small business.In->Out with barcode scan functionality.
This project was generated with [angular-cli](https://github.com/angular/angular-cli) version 1.0.0-beta.26.


text:
/*
 * DBeaver - Universal Database Manager
 * Copyright (C) 2010-2017 Serge Rider (serge@jkiss.org)
 *
 * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.jkiss.dbeaver.ui.controls;
/*
 *  CustomSashForm
 */

import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.events.*;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.*;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * A SashForm that allows hide/restore controls on sash.
 *
 * It only works with one sash (two children). It doesn't make sense
 * for the arrows when there is more than one sash. Things get confusing for
 * a restore position.
 *
 */
public class CustomSashForm extends SashForm {

	/**
	 * Custom style bits. They set whether hide to one side of the other
	 * is not permitted. For example, if NO_HIDE_UP, then there will be only
	 * one arrow. When not hidden, it will point down (and will do a hide down),
	 * and when hidden down, it will point up (and will do a restore to the
	 * previous weight). There won't be a hide to the top arrow.
	 */
	public static final int
		NO_HIDE_LEFT = 0x1,			// Custom style bit for not allow hide left
		NO_HIDE_UP = NO_HIDE_LEFT,	// Custom style bit for not allow hide up
		NO_HIDE_RIGHT = 0x2,			// Custom style bit for not allow hide right
		NO_HIDE_DOWN = NO_HIDE_RIGHT;	// Custom style bit for not allow hide down

	private static final int NO_WEIGHT = -1;
	private static final int NO_ARROW = -1;
	private class SashInfo {
		public Sash sash;
		public boolean enabled;	// Whether this sashinfo is enabled (i.e. if there is more than one, this will be disabled).
		public int restoreWeight = NO_WEIGHT;	// If slammed to an edge this is the restore weight. -1 means not slammed. This is the restoreWeight in the 2nd section form, i.e. weights[1].
		public int cursorOver = NO_ARROW;	// Which arrow is cursor over,
		public boolean sashBorderLeft;	// Draw sash border left/top
		public boolean sashBorderRight;	// Draw sash border right/bottom
		public int[][] sashLocs;	// There is one entry for each arrow, It is arrowType/arrowDrawn/x/y/height/width of the arrow area.
									// There may not be a second entry, in which case we have only one arrow.
		public Point[] savedSizes = new Point[2];  // Saved sizes of controls - saved whenever a control is hidden or restored
		public SashInfo(Sash sash) {
			this.sash = sash;
		}
	};

	public interface ICustomSashFormListener{
		void dividerMoved(int firstControlWeight, int secondControlWeight);
	}

	protected SashInfo currentSashInfo = null;	// When the sash goes away, its entry is made null.
	protected boolean inMouseClick = false;	// Because we can't stop drag even when we are in the arrow area, we need
												// to know that mouse down is in process so that when drag is completed, we
												// know not to recompute our position because a mouse up is about to happen
												// and we want the correct arrow handled correctly.

	protected boolean sashBorders[];	// Whether corresponding control needs a sash border

	protected boolean noHideUp, noHideDown;
	protected List customSashFormListeners = null;

	protected static final int
		UP_RESTORE_ARROW = 0,
		UP_HIDE_ARROW = 1,
		DOWN_RESTORE_ARROW = 2,
		DOWN_HIDE_ARROW = 3,

		HIDE_ARROWS = 4;

	protected static final int
		ARROW_TYPE_INDEX = 0,
		ARROW_DRAWN_INDEX = 1,
		X_INDEX = 2,
		Y_INDEX = 3,
		WIDTH_INDEX = 4,
		HEIGHT_INDEX = 5;

	// These are for the up/down arrow. Just swap them for left/right arrow.
	protected static final int
		ARROW_WIDTH = 8,
		ARROW_HEIGHT = 8,
		ARROW_MARGIN = 3;	// Margin on each side of arrow

	protected Color arrowColor, borderColor;

	public CustomSashForm(Composite parent, int style) {
		this(parent, style, SWT.NONE);
	}

	/**
	 * Constructor taking a custom style too.
	 * Or in the Custom style bits defined above (e.g. NO_HIDE_RIGHT,...)
	 */
	public CustomSashForm(Composite parent, int style, int customStyle) {
		super(parent, style);

		// Need listener to force a layout
		this.addListener(SWT.Resize, new Listener() {
			public void handleEvent(Event e) {
				layout(true);
			}
		});

		noHideUp = ((customStyle & NO_HIDE_UP) != 0);
		noHideDown = ((customStyle & NO_HIDE_DOWN) != 0);

		if (noHideUp & noHideDown)
			return;	// If you can't hide up or down, there there is no need for arrows.

		SASH_WIDTH = 3 + getOrientation() == SWT.VERTICAL ? ARROW_HEIGHT : ARROW_WIDTH;

		arrowColor = new Color(parent.getDisplay(), 99, 101, 156);
		borderColor = new Color(parent.getDisplay(), 132, 130, 132);

		addDisposeListener(new DisposeListener() {
			/**
			 * @see org.eclipse.swt.events.DisposeListener#widgetDisposed(DisposeEvent)
			 */
			public void widgetDisposed(DisposeEvent e) {
				arrowColor.dispose();
				borderColor.dispose();
				arrowColor = borderColor = null;
			}

		});
	}

	/**
	 * Returns the noHideUp setting for vertical CustomSashForm.
	 */
	public boolean isNoHideUp(){
		return noHideUp;
	}

	/**
	 * Returns the noHideDown setting for vertical CustomSashForm.
	 */
	public boolean isNoHideDown(){
		return noHideDown;
	}

	/**
	 * Returns the noHideLeft setting for horizontal CustomSashForm.
	 */
	public boolean isNoHideLeft(){
		return noHideUp;
	}

	/**
	 * Returns the noHideRight setting for horizontal CustomSashForm.
	 */
	public boolean isNoHideRight(){
		return noHideDown;
	}

	/**
	 * Sets the noHideUp setting for vertical CustomSashForm.
	 */
	public void setNoHideUp(boolean bHide) {
		noHideUp = bHide;
	}

	/**
	 * Sets the noHideDown setting for vertical CustomSashForm.
	 */
	public void setNoHideDown(boolean bHide) {
		noHideDown = bHide;
	}

	/**
	 * Sets the noHideLeft setting for horizontal CustomSashForm.
	 */
	public void setNoHideLeft(boolean bHide) {
		setNoHideUp(bHide);
	}

	/**
	 * Sets the noHideRight setting for horizontal CustomSashForm.
	 */
	public void setNoHideRight(boolean bHide) {
		setNoHideDown(bHide);
	}

	/**
	 * Call to set to hide up
	 */
	public void hideUp() {
		if (noHideUp)
			return;

		if (currentSashInfo == null)
			currentSashInfo = new SashInfo(null);
		upHideClicked(currentSashInfo);
	}

	/**
	 * Call to set to hide left
	 */
	public void hideLeft() {
		hideUp();
	}

	/**
	 * Call to set to hide down
	 */
	public void hideDown() {
		if (noHideDown)
			return;

		if (currentSashInfo == null)
			currentSashInfo = new SashInfo(null);

		downHideClicked(currentSashInfo);
	}

	/**
	 * Call to set to hide right
	 */
	public void hideRight() {
		hideDown();
	}

	/**
	 * Set the need sash borders for the controls.
	 */
	public void setSashBorders(boolean[] sashBorders) {
		int[] weights = getWeights();	// KLUDGE This is a kludge just to see how many controls we have.
		if (weights.length != 2 || (sashBorders != null && sashBorders.length != 2)) {
			SWT.error(SWT.ERROR_INVALID_ARGUMENT);
		}
		this.sashBorders = sashBorders;
	}

	/**
	 * @see org.eclipse.swt.widgets.Composite#layout(boolean)
	 */
	public void layout(boolean changed) {
		super.layout(changed);

		if (noHideUp && noHideDown)
			return;	// No arrows to handle in this case.

		if (getMaximizedControl() != null)
			return;	// We have a maximized control, so we don't need to worry about the sash.

		// Let's get the list of all sashes the sash form now has. If there is more than one then just disable the sashinfo.
		// If there is no current sash, and there is only one sash, then create the sashinfo for it.
		Control[] children = getChildren();
		Sash newSash = null;
		for (int i = 0; i < children.length; i++) {
			if (children[i] instanceof Sash)
				if (newSash == null)
					newSash = (Sash) children[i];
				else {
					// We have more than one sash, so need to disable current sash, if we have one.
					if (currentSashInfo != null)
						currentSashInfo.enabled = false;
					return;	// Don't go on.
				}
		}

		if (newSash == null)
			return;	// We have no sashes at all.

		// Now we need to see if this is a new sash.
		if (currentSashInfo == null || currentSashInfo.sash == null) {
			if (currentSashInfo == null)
				currentSashInfo = new SashInfo(newSash);
			else
				currentSashInfo.sash = newSash;
			newSash.addPaintListener(new PaintListener() {
				/**
				 * @see org.eclipse.swt.events.PaintListener#paintControl(PaintEvent)
				 */
				public void paintControl(PaintEvent e) {
					// Need to find the index of the sash we're interested in.

					GC gc = e.gc;
					Color oldFg = gc.getForeground();
					Color oldBg = gc.getBackground();

					drawArrow(gc, currentSashInfo.sashLocs[0], currentSashInfo.cursorOver == 0);	// Draw first arrow
					if (currentSashInfo.sashLocs.length > 1)
						drawArrow(gc, currentSashInfo.sashLocs[1], currentSashInfo.cursorOver == 1);	// Draw second arrow

					if (currentSashInfo.sashBorderLeft)
						drawSashBorder(gc, currentSashInfo.sash, true);
					if (currentSashInfo.sashBorderRight)
						drawSashBorder(gc, currentSashInfo.sash, false);

					gc.setForeground(oldFg);
					gc.setBackground(oldBg);
				}

			});

			newSash.addControlListener(new ControlListener() {
				/**
				 * @see org.eclipse.swt.events.ControlAdapter#controlMoved(ControlEvent)
				 */
				public void controlMoved(ControlEvent e) {
					//System.out.println("controlMoved");
					recomputeSashInfo();
				}

				/**
				 * @see org.eclipse.swt.events.ControlAdapter#controlResized(ControlEvent)
				 */
				public void controlResized(ControlEvent e) {
					recomputeSashInfo();
				}

			});

			newSash.addDisposeListener(new DisposeListener() {
				/**
				 * @see org.eclipse.swt.events.DisposeListener#widgetDisposed(DisposeEvent)
				 */
				public void widgetDisposed(DisposeEvent e) {
					// Need to clear out the widget from current.
					currentSashInfo= null;
				}
			});

			// This is a kludge because we can't override the set cursor hit test.
			newSash.addMouseMoveListener(new MouseMoveListener() {
				/**
				 * @see org.eclipse.swt.events.MouseMoveListener#mouseMove(MouseEvent)
				 */
				public void mouseMove(MouseEvent e) {
					// See if within one of the arrows.
					int x = e.x;
					int y = e.y;
					for (int i=0; i<currentSashInfo.sashLocs.length; i++) {
						int[] locs = currentSashInfo.sashLocs[i];
						boolean vertical = getOrientation() == SWT.VERTICAL;
						int loc = vertical ? x : y;
						int locIndex = vertical ? X_INDEX : Y_INDEX;
						int sizeIndex = vertical ? WIDTH_INDEX : HEIGHT_INDEX;
						// Does the mouse position lie within the bounds of the arrow?
						if (locs[locIndex] <= loc && loc <= locs[locIndex]+locs[sizeIndex]) {
							if (currentSashInfo.cursorOver == NO_ARROW) {
								currentSashInfo.sash.setCursor(getDisplay().getSystemCursor(SWT.CURSOR_ARROW));
							}
							if (currentSashInfo.cursorOver != i) {
								currentSashInfo.cursorOver = i;
								currentSashInfo.sash.redraw();
								switch (locs[ARROW_TYPE_INDEX]) {
									case UP_RESTORE_ARROW:
									case DOWN_RESTORE_ARROW:
										currentSashInfo.sash.setToolTipText("Restore");
										break;
									case UP_HIDE_ARROW:
									case DOWN_HIDE_ARROW:
										currentSashInfo.sash.setToolTipText("Hide");
										break;
								}
							}
							return;
						}
					}
					// If we got here, the mouse position does not lie within the bounds of an arrow
					if (currentSashInfo.cursorOver != NO_ARROW) {
						currentSashInfo.sash.setCursor(null);
						currentSashInfo.cursorOver = NO_ARROW;
						currentSashInfo.sash.redraw();
						currentSashInfo.sash.setToolTipText(null);
					}
				}

			});

			// Need to know when we leave so that we can clear the cursor feedback if set.
			newSash.addMouseTrackListener(new MouseTrackAdapter() {
				/**
				 * @see org.eclipse.swt.events.MouseTrackAdapter#mouseExit(MouseEvent)
				 */
				public void mouseExit(MouseEvent e) {
					if (currentSashInfo.cursorOver != NO_ARROW) {
						// Undo the cursor.
						currentSashInfo.sash.setCursor(null);
						currentSashInfo.cursorOver = NO_ARROW;
						currentSashInfo.sash.redraw();
						currentSashInfo.sash.setToolTipText(null);
					}
				}
			});

			// Want to handle mouse down as a selection.
			newSash.addMouseListener(new MouseAdapter() {
				/**
				 * @see org.eclipse.swt.events.MouseAdapter#mouseDown(MouseEvent)
				 */
				public void mouseDown(MouseEvent e) {
					//System.out.println("mouseDown");
					inMouseClick = true;
					// If we're within a button, then redraw to wipe out stipple and get button push effect.
					int x = e.x;
					int y = e.y;
					for (int i=0; i<currentSashInfo.sashLocs.length; i++) {
						int[] locs = currentSashInfo.sashLocs[i];
						boolean vertical = getOrientation() == SWT.VERTICAL;
						int loc = vertical ? x : y;
						int locIndex = vertical ? X_INDEX : Y_INDEX;
						int sizeIndex = vertical ? WIDTH_INDEX : HEIGHT_INDEX;
						if (locs[locIndex] <= loc && loc <= locs[locIndex]+locs[sizeIndex]) {
							currentSashInfo.sash.redraw();
							break;
						}
					}
				}

				/**
				 * @see org.eclipse.swt.events.MouseListener#mouseDown(MouseEvent)
				 */
				public void mouseUp(MouseEvent e) {
					//System.out.println("mouseUp");
					// See if within one of the arrows.
					inMouseClick = false;	// No longer in down click
					int x = e.x;
					int y = e.y;
					for (int i=0; i<currentSashInfo.sashLocs.length; i++) {
						int[] locs = currentSashInfo.sashLocs[i];
						boolean vertical = getOrientation() == SWT.VERTICAL;
						int loc = vertical ? x : y;
						int locIndex = vertical ? X_INDEX : Y_INDEX;
						int sizeIndex = vertical ? WIDTH_INDEX : HEIGHT_INDEX;
						// Does the mouse position lie within the bounds of the arrow?
						if (locs[locIndex] <= loc && loc <= locs[locIndex]+locs[sizeIndex]) {
							// We found it.
							switch (locs[ARROW_TYPE_INDEX]) {
								case UP_RESTORE_ARROW:
									upRestoreClicked(currentSashInfo);
									break;
								case UP_HIDE_ARROW:
									upHideClicked(currentSashInfo);
									break;
								case DOWN_RESTORE_ARROW:
									downRestoreClicked(currentSashInfo);
									break;
								case DOWN_HIDE_ARROW:
									downHideClicked(currentSashInfo);
									break;
							}
							break;
						}
					}

					currentSashInfo.sash.redraw();	// Make sure stipple goes away from the mouse up if not over an arrow button.
					fireDividerMoved();
				}

			});
			recomputeSashInfo();	// Get initial setting
		}

	}

	/*
	 * Constants for recording whether the sash is slammed to the top/bottom or not slammed
	 */
	private final static int NOT_SLAMMED = 1;
	private final static int SLAMMED_TO_BOTTOM = 2;
	private final static int SLAMMED_TO_TOP = 3;

	protected void recomputeSashInfo() {
		if (inMouseClick && currentSashInfo.cursorOver != NO_ARROW){
			return;	// Don't process because we are in the down mouse button on an arrow.
		}

		// addArrows are the types of the arrows - hide/restore/up/down and
		// drawArrows are the types of the arrows actually drawn. Here
		// drawArrows are always RESTORE arrow types, so that the UI only
		// has a single arrow type showing.
		int[] addArrows;
		int[] drawArrows;

		// We need to refigure size for the sash arrows.
		int[] weights = getWeights();	// This should be two entries only. We shouldn't have got here if there were more than two.

		// TODO: Use of DRAG_MINIMUM is a kludge, required because SashForm only allows you to close each part so far
		final int DRAG_MINIMUM = 20; // TODO: kludge see SashForm.DRAG_MINIMUM
		Rectangle sashBounds = currentSashInfo.sash.getBounds();
		Rectangle clientArea = getClientArea();
		boolean vertical = getOrientation() == SWT.VERTICAL;

		//
		// Work out whether the sash is slammed to the top / bottom or not slammed
		//
		int slammed = NOT_SLAMMED;
		if (weights[1] == 0){
			slammed = SLAMMED_TO_BOTTOM;
		}
		else if (weights[0] == 0){
			slammed = SLAMMED_TO_TOP;
		}
		else if (vertical){
			if (currentSashInfo.restoreWeight != NO_WEIGHT && sashBounds.y <= DRAG_MINIMUM){
				slammed = SLAMMED_TO_TOP;
			}
			else if (currentSashInfo.restoreWeight != NO_WEIGHT && sashBounds.y+sashBounds.height >= clientArea.height-DRAG_MINIMUM){
				slammed = SLAMMED_TO_BOTTOM;
			}
		}
		else {
			if (currentSashInfo.restoreWeight != NO_WEIGHT && sashBounds.x <= DRAG_MINIMUM){
				slammed = SLAMMED_TO_TOP;
			}
			else if (currentSashInfo.restoreWeight != NO_WEIGHT && sashBounds.x+sashBounds.width >= clientArea.width-DRAG_MINIMUM){
				slammed = SLAMMED_TO_BOTTOM;
			}
		}

		//
		// Now decide which arrows to add, according to whether noHideUp, noHideDown and the slammed status.
		//
		if (noHideUp) {
			if (slammed == SLAMMED_TO_BOTTOM) {
				addArrows = new int[1];
				drawArrows = new int[1];

				addArrows[0] = UP_RESTORE_ARROW;
				drawArrows[0] = UP_RESTORE_ARROW;
				currentSashInfo.sashBorderLeft = sashBorders != null && sashBorders[0];
				currentSashInfo.sashBorderRight = false;
			} else {
				//Not slammed
				addArrows = new int[1];
				drawArrows = new int[1];

				addArrows[0] = DOWN_HIDE_ARROW;
				drawArrows[0] = DOWN_RESTORE_ARROW;
				currentSashInfo.restoreWeight = NO_WEIGHT;	// Since we are in the middle, there is no restoreWeight. We've could of been dragged here.
				currentSashInfo.sashBorderLeft = sashBorders != null && sashBorders[0];
				currentSashInfo.sashBorderRight = sashBorders != null && sashBorders[1];
			}
		} else if (noHideDown) {
			if (slammed == SLAMMED_TO_TOP) {
				addArrows = new int[1];
				drawArrows = new int[1];

				addArrows[0] = DOWN_RESTORE_ARROW;
				drawArrows[0] = DOWN_RESTORE_ARROW;
				currentSashInfo.sashBorderLeft = false;
				currentSashInfo.sashBorderRight = sashBorders != null && sashBorders[1];
			} else {
				//Not slammed
				addArrows = new int[1];
				drawArrows = new int[1];

				addArrows[0] = UP_HIDE_ARROW;
				drawArrows[0] = UP_RESTORE_ARROW;
				currentSashInfo.restoreWeight = NO_WEIGHT;	// Since we are in the middle, there is no restoreWeight. We've could of been dragged here.
				currentSashInfo.sashBorderLeft = sashBorders != null && sashBorders[0];
				currentSashInfo.sashBorderRight = sashBorders != null && sashBorders[1];
			}
		} else {
			if (slammed == SLAMMED_TO_TOP) {
				addArrows = new int[1];
				drawArrows = new int[1];

				addArrows[0] = DOWN_RESTORE_ARROW;
				drawArrows[0] = DOWN_RESTORE_ARROW;
				currentSashInfo.sashBorderLeft = false;
				currentSashInfo.sashBorderRight = sashBorders != null && sashBorders[1];
			} else if (slammed == SLAMMED_TO_BOTTOM) {
				addArrows = new int[1];
				drawArrows = new int[1];

				addArrows[0] = UP_RESTORE_ARROW;
				drawArrows[0] = UP_RESTORE_ARROW;
				currentSashInfo.sashBorderLeft = sashBorders != null && sashBorders[0];
				currentSashInfo.sashBorderRight = false;
			} else {
				//Not slammed
				addArrows = new int[2];
				drawArrows = new int[2];

				addArrows[0] = UP_HIDE_ARROW;
				drawArrows[0] = UP_RESTORE_ARROW;
				addArrows[1] = DOWN_HIDE_ARROW;
				drawArrows[1] = DOWN_RESTORE_ARROW;
				currentSashInfo.restoreWeight = NO_WEIGHT;	// Since we are in the middle, there is no restoreWeight. We've could of been dragged here.
				currentSashInfo.sashBorderLeft = sashBorders != null && sashBorders[0];
				currentSashInfo.sashBorderRight = sashBorders != null && sashBorders[1];
			}
		}
		getNewSashArray(currentSashInfo, addArrows, drawArrows);

		currentSashInfo.sash.redraw();	// Need to schedule a redraw because it has already drawn the old ones during the set bounds in super layout.
	}

	protected void upRestoreClicked(SashInfo sashinfo) {
		// This means restore just the sash below restoreWeight and reduce the above restoreWeight by the right amount.
		int[] weights = getWeights();

		weights[0] = 1000-sashinfo.restoreWeight;	// Assume weights are always in units of 1000.
		weights[1] = sashinfo.restoreWeight;
		sashinfo.restoreWeight = NO_WEIGHT;

		setWeights(weights);
		fireDividerMoved();
	}

	protected void upHideClicked(SashInfo sashinfo) {
		int[] weights = getWeights();

		// Up hide, so save the current restoreWeight of 1 into the sash info, and move to the top.
		if (currentSashInfo.restoreWeight == NO_WEIGHT){
			currentSashInfo.restoreWeight = weights[1];	// Not currently maxed, save position.

			saveChildControlSizes();
		}
		weights[0] = 0;
		weights[1] = 1000;

		// If the upper panel has focus, flip focus to the lower panel because the upper panel is now hidden.
		Control[] children = getChildren();
		boolean upperFocus = isFocusAncestorA(children[0]);
		setWeights(weights);
		if (upperFocus)
			children[1].setFocus();
		fireDividerMoved();
	}

	protected void downRestoreClicked(SashInfo sashinfo) {
		// This means restore just the sash below restoreWeight and increase the above restoreWeight by that amount.
		int[] weights = getWeights();

		weights[0] = 1000-sashinfo.restoreWeight;	// Assume weights are always in units of 1000.
		weights[1] = sashinfo.restoreWeight;
		sashinfo.restoreWeight = NO_WEIGHT;

		setWeights(weights);
		fireDividerMoved();
	}

	protected void downHideClicked(SashInfo sashinfo) {
		int[] weights = getWeights();

		// Down hide, so save the current restoreWeight of 1 into the sash info, and move to the bottom.
		if (currentSashInfo.restoreWeight == NO_WEIGHT) {
			currentSashInfo.restoreWeight = weights[1];	// Not currently maxed, save current restoreWeight.
			saveChildControlSizes();
		}
		weights[0] = 1000;
		weights[1] = 0;

		// If the lower panel has focus, flip focus to the upper panel because the lower panel is now hidden.
		Control[] children = getChildren();
		boolean lowerFocus = isFocusAncestorA(children[1]);
		setWeights(weights);
		if (lowerFocus)
			children[0].setFocus();
		fireDividerMoved();
	}

	/*
	 * Helper method for upHideClicked / downHideClicked
	 */
	private void saveChildControlSizes() {
		// Save control sizes
		Control [] children = getChildren();
		int iChildToSave = 0;
		for (int i = 0; i < children.length && iChildToSave < 2; i++){
			Control child = children[i];
			if (! (child instanceof Sash)){
				currentSashInfo.savedSizes[iChildToSave] = child.getSize();
				iChildToSave++;
			}
		}
	}

	/*
	 * This determines if the control or one of its children
	 * has the focus. Control.isFocusAncestor is hidden by SWT, but it is really useful.
	 */
	protected boolean isFocusAncestorA (Control control) {
		Display display = getDisplay ();
		Control focusControl = display.getFocusControl ();
		while (focusControl != null && focusControl != control) {
			focusControl = focusControl. getParent();
		}
		return control == focusControl;
	}

	protected void getNewSashArray(SashInfo sashInfo, int[] addArrowTypes, int[] drawArrowTypes) {

//		int[][] thisSash = sashInfo.sashLocs;
//		if (thisSash == null)
		sashInfo.sashLocs = new int[addArrowTypes.length][];
		int[][] thisSash = sashInfo.sashLocs;

		int aSize = ARROW_WIDTH;	// Width of arrow
		int tSize = aSize+2*ARROW_MARGIN;		// Total Width (arrow + margin)
		int neededSize = tSize*addArrowTypes.length;

		boolean vertical = getOrientation() == SWT.VERTICAL;
		Point s = sashInfo.sash.getSize();
		int start;
		int x;
		int y;
		int width;
		int height;
		if (vertical) {
			start = (s.x - neededSize) / 2;
			x = start;
			y = (s.y - ARROW_HEIGHT) / 2;	// Center vertically, no margin required.
			width = tSize;
			height = aSize;
		} else {
			start = (s.y - neededSize) / 2;
			y = start;
			x = (s.x - ARROW_HEIGHT) / 2;	// Center horizontally, no margin required.
			width = aSize;
			height = tSize;
		}
		for (int j=0; j<addArrowTypes.length; j++) {
			if (thisSash[j] == null)
				thisSash[j] = new int[] {addArrowTypes[j], drawArrowTypes[j], x, y, width, height};
			else {
				// Reuse the array
				thisSash[j][ARROW_TYPE_INDEX] = addArrowTypes[j];
				thisSash[j][ARROW_DRAWN_INDEX] = drawArrowTypes[j];
				thisSash[j][X_INDEX] = x;
				thisSash[j][Y_INDEX] = y;
				thisSash[j][WIDTH_INDEX] = width;
				thisSash[j][HEIGHT_INDEX] = height;
			}
			if (vertical)
				x+=tSize;
			else
				y+=tSize;
		}
	}

	protected void drawSashBorder(GC gc, Sash sash, boolean leftBorder) {
		gc.setForeground(borderColor);
		if (getOrientation() == SWT.VERTICAL) {
			Point s = sash.getSize();
			if (leftBorder) // i.e. top for VERTICAL sash
				gc.drawLine(0, 0, s.x-1, 0);
			else  // i.e. bottom for VERTICAL sash
				gc.drawLine(0, s.y-1, s.x-1, s.y-1);
		} else {
			Point s = sash.getSize();
			if (leftBorder)
				gc.drawLine(0, 0, 0, s.y-1);
			else
				gc.drawLine(s.x-1, 0, s.x-1, s.y-1);
		}
	}

	protected void drawArrow(GC gc, int[] sashLoc, boolean selected) {
		int indent = 0;
		if (selected) {
			if (!inMouseClick) {
				// Draw the selection box.
				Color highlightShadow = getDisplay().getSystemColor(SWT.COLOR_WIDGET_HIGHLIGHT_SHADOW);
				Color normalShadow = getDisplay().getSystemColor(SWT.COLOR_WIDGET_NORMAL_SHADOW);
				gc.setForeground(highlightShadow);
				gc.drawLine(sashLoc[X_INDEX], sashLoc[Y_INDEX]+sashLoc[HEIGHT_INDEX], sashLoc[X_INDEX], sashLoc[Y_INDEX]);
				gc.drawLine(sashLoc[X_INDEX], sashLoc[Y_INDEX], sashLoc[X_INDEX]+sashLoc[WIDTH_INDEX], sashLoc[Y_INDEX]);

				gc.setForeground(normalShadow);
				gc.drawLine(sashLoc[X_INDEX], sashLoc[Y_INDEX]+sashLoc[HEIGHT_INDEX], sashLoc[X_INDEX]+sashLoc[WIDTH_INDEX], sashLoc[Y_INDEX]+sashLoc[HEIGHT_INDEX]);
				gc.drawLine(sashLoc[X_INDEX]+sashLoc[WIDTH_INDEX], sashLoc[Y_INDEX]+sashLoc[HEIGHT_INDEX], sashLoc[X_INDEX]+sashLoc[WIDTH_INDEX], sashLoc[Y_INDEX]);
			} else {
				// Draw pushed selection box.
				indent = 1;
				Color highlightShadow = getDisplay().getSystemColor(SWT.COLOR_WIDGET_HIGHLIGHT_SHADOW);
				Color normalShadow = getDisplay().getSystemColor(SWT.COLOR_WIDGET_NORMAL_SHADOW);
				gc.setForeground(normalShadow);
				gc.drawLine(sashLoc[X_INDEX], sashLoc[Y_INDEX]+sashLoc[HEIGHT_INDEX], sashLoc[X_INDEX], sashLoc[Y_INDEX]);
				gc.drawLine(sashLoc[X_INDEX], sashLoc[Y_INDEX], sashLoc[X_INDEX]+sashLoc[WIDTH_INDEX], sashLoc[Y_INDEX]);

				gc.setForeground(highlightShadow);
				gc.drawLine(sashLoc[X_INDEX], sashLoc[Y_INDEX]+sashLoc[HEIGHT_INDEX], sashLoc[X_INDEX]+sashLoc[WIDTH_INDEX], sashLoc[Y_INDEX]+sashLoc[HEIGHT_INDEX]);
				gc.drawLine(sashLoc[X_INDEX]+sashLoc[WIDTH_INDEX], sashLoc[Y_INDEX]+sashLoc[HEIGHT_INDEX], sashLoc[X_INDEX]+sashLoc[WIDTH_INDEX], sashLoc[Y_INDEX]);
			}
		}
		if (getOrientation() == SWT.VERTICAL) {
			switch (sashLoc[ARROW_DRAWN_INDEX]) {
				case UP_RESTORE_ARROW:
					drawUpRestoreArrow(gc, sashLoc[X_INDEX]+indent, sashLoc[Y_INDEX]+indent);
					break;
				case DOWN_RESTORE_ARROW:
					drawDownRestoreArrow(gc, sashLoc[X_INDEX]+indent, sashLoc[Y_INDEX]+indent);
					break;
				case UP_HIDE_ARROW:
					drawUpHideArrow(gc, sashLoc[X_INDEX]+indent, sashLoc[Y_INDEX]+indent);
					break;
				case DOWN_HIDE_ARROW:
					drawDownHideArrow(gc, sashLoc[X_INDEX]+indent, sashLoc[Y_INDEX]+indent);
					break;
			}
		} else {
			switch (sashLoc[ARROW_DRAWN_INDEX]) {
				case UP_RESTORE_ARROW:
					drawLeftRestoreArrow(gc, sashLoc[X_INDEX]+indent, sashLoc[Y_INDEX]+indent);
					break;
				case DOWN_RESTORE_ARROW:
					drawRightRestoreArrow(gc, sashLoc[X_INDEX]+indent, sashLoc[Y_INDEX]+indent);
					break;
				case UP_HIDE_ARROW:
					drawLeftHideArrow(gc, sashLoc[X_INDEX]+indent, sashLoc[Y_INDEX]+indent);
					break;
				case DOWN_HIDE_ARROW:
					drawRightHideArrow(gc, sashLoc[X_INDEX]+indent, sashLoc[Y_INDEX]+indent);
					break;
			}
		}
	}

	// Draw at the given x/y (upper left corner of arrow area).
	protected void drawUpRestoreArrow(GC gc, int x, int y) {
		gc.setForeground(arrowColor);

		x+=ARROW_MARGIN;
		gc.drawLine(x+4, y+2, x+7, y+5);
		gc.drawLine(x+3, y+2, x+3, y+2);

		gc.drawLine(x+2, y+3, x+4, y+3);
		gc.drawLine(x+1, y+4, x+5, y+4);
		gc.drawLine(x,   y+5, x+6, y+5);
	}

	// Draw at the given x/y (upper left corner of arrow area).
	protected void drawUpHideArrow(GC gc, int x, int y) {
		gc.setForeground(arrowColor);

		x+=ARROW_MARGIN;
		gc.drawLine(x,   y,   x+7, y);
		gc.drawLine(x,   y+1, x+7, y+1);

		gc.drawLine(x+4, y+2, x+7, y+5);
		gc.drawLine(x+3, y+2, x+3, y+2);

		gc.drawLine(x+2, y+3, x+4, y+3);
		gc.drawLine(x+1, y+4, x+5, y+4);
		gc.drawLine(x,   y+5, x+6, y+5);
	}

	// Draw at the given x/y (upper left corner of arrow area).
	protected void drawDownRestoreArrow(GC gc, int x, int y) {
		gc.setForeground(arrowColor);

		x+=ARROW_MARGIN;
		gc.drawLine(x,   y+2, x+3, y+5);
		gc.drawLine(x+4, y+5, x+4, y+5);

		gc.drawLine(x+3, y+4, x+5, y+4);
		gc.drawLine(x+1, y+3, x+6, y+3);
		gc.drawLine(x+1, y+2, x+7, y+2);
	}

	// Draw at the given x/y (upper left corner of arrow area).
	protected void drawDownHideArrow(GC gc, int x, int y) {
		gc.setForeground(arrowColor);

		x+=ARROW_MARGIN;
		gc.drawLine(x,   y+6, x+7, y+6);
		gc.drawLine(x,   y+7, x+7, y+7);

		gc.drawLine(x,   y+2, x+3, y+5);
		gc.drawLine(x+4, y+5, x+4, y+5);

		gc.drawLine(x+3, y+4, x+5, y+4);
		gc.drawLine(x+1, y+3, x+6, y+3);
		gc.drawLine(x+1, y+2, x+7, y+2);
	}

	// Draw at the given x/y (upper left corner of arrow area).
	protected void drawLeftRestoreArrow(GC gc, int x, int y) {
		gc.setForeground(arrowColor);

		y+=ARROW_MARGIN;
		gc.drawLine(x+2, y+4, x+5, y+7);
		gc.drawLine(x+2, y+3, x+2, y+3);

		gc.drawLine(x+3, y+2, x+3, y+4);
		gc.drawLine(x+4, y+1, x+4, y+5);
		gc.drawLine(x+5, y,   x+5, y+6);
	}

	// Draw at the given x/y (upper left corner of arrow area).
	protected void drawLeftHideArrow(GC gc, int x, int y) {
		gc.setForeground(arrowColor);

		y+=ARROW_MARGIN;
		gc.drawLine(x,   y, x,   y+7);
		gc.drawLine(x+1, y, x+1, y+7);

		gc.drawLine(x+2, y+4, x+5, y+7);
		gc.drawLine(x+2, y+3, x+2, y+3);

		gc.drawLine(x+3, y+2, x+3, y+4);
		gc.drawLine(x+4, y+1, x+4, y+5);
		gc.drawLine(x+5, y,   x+5, y+6);
	}

	// Draw at the given x/y (upper left corner of arrow area).
	protected void drawRightRestoreArrow(GC gc, int x, int y) {
		gc.setForeground(arrowColor);

		y+=ARROW_MARGIN;
		gc.drawLine(x+2, y,   x+5, y+3);
		gc.drawLine(x+5, y+4, x+5, y+4);

		gc.drawLine(x+4, y+3, x+4, y+5);
		gc.drawLine(x+3, y+1, x+3, y+6);
		gc.drawLine(x+2, y+1, x+2, y+7);
	}

	// Draw at the given x/y (upper left corner of arrow area).
	protected void drawRightHideArrow(GC gc, int x, int y) {
		gc.setForeground(arrowColor);

		y+=ARROW_MARGIN;
		gc.drawLine(x+6, y,   x+6, y+7);
		gc.drawLine(x+7, y,   x+7, y+7);

		gc.drawLine(x+2, y,   x+5, y+3);
		gc.drawLine(x+5, y+4, x+5, y+4);

		gc.drawLine(x+4, y+3, x+4, y+5);
		gc.drawLine(x+3, y+1, x+3, y+6);
		gc.drawLine(x+2, y+1, x+2, y+7);
	}

	public int getRestoreWeight() {
		if (currentSashInfo!=null)
			return currentSashInfo.restoreWeight;
		else
			return -1;
	}

	protected Sash getSash() {
		Control[] kids = getChildren();
		for (int i = 0; i < kids.length; i++) {
			if (kids[i] instanceof Sash)
				return (Sash)kids[i];
		}
		return null;
	}

	public void setRestoreWeight(int weight) {
		if (weight>=0 && currentSashInfo!=null) {
			//recomputeSashInfo();
			currentSashInfo.restoreWeight=weight;
		}
	}

	public Point[] getSavedSizes(){
		if (currentSashInfo!=null){
			return currentSashInfo.savedSizes;
		}
		else {
			return null;
		}
	}

	/**
	 * Adds a custom sashform listener. This listener will be removed when
	 * this control is disposed.
	 *
	 * @since 1.2.0
	 */
	public void addCustomSashFormListener(ICustomSashFormListener listener){
		if(customSashFormListeners==null)
			customSashFormListeners = new ArrayList();
		customSashFormListeners.add(listener);
	}

	/**
	 * Removes the custom sashform listener.
	 *
	 * @since 1.2.0
	 */
	public void removeCustomSashFormListener(ICustomSashFormListener listener){
		if(customSashFormListeners!=null){
			customSashFormListeners.remove(listener);
		}
	}

	protected void fireDividerMoved(){
		if(customSashFormListeners!=null && customSashFormListeners.size()>0){
			int[] weights = getWeights();
			if(weights!=null && weights.length==2){
				int firstControlWeight = weights[0];
				int secondControlWeight = weights[1];
				for (Iterator listenerItr = customSashFormListeners.iterator(); listenerItr.hasNext();) {
					ICustomSashFormListener listener = (ICustomSashFormListener) listenerItr.next();
					listener.dividerMoved(firstControlWeight, secondControlWeight);
				}
			}
		}
	}

}


text:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <item
        android:id="@+id/menu_search"
        android:icon="@drawable/ic_toolbar_search"
        android:title="@string/menu_search"
        app:showAsAction="always|collapseActionView"
        app:actionViewClass="android.support.v7.widget.SearchView" />

    <item
        android:id="@+id/menu_sort"
        android:title="@string/menu_sort"
        android:icon="@drawable/ic_toolbar_sort"
        app:showAsAction="always" />

</menu>


text:
package client

import (
	"github.com/keybase/client/go/libkb"
	keybase1 "github.com/keybase/client/go/protocol/keybase1"
	"github.com/keybase/go-framed-msgpack-rpc/rpc"
	"golang.org/x/net/context"
)

type SecretUIServer struct {
	eng libkb.SecretUI
}

func NewSecretUIProtocol(g *libkb.GlobalContext) rpc.Protocol {
	return keybase1.SecretUiProtocol(&SecretUIServer{g.UI.GetSecretUI()})
}

func (s *SecretUIServer) GetPassphrase(_ context.Context, arg keybase1.GetPassphraseArg) (keybase1.GetPassphraseRes, error) {
	return s.eng.GetPassphrase(arg.Pinentry, arg.Terminal)
}


text:
"""Testing methods that need no server access."""

import sys
if sys.version_info < (2, 7):
    import unittest2 as unittest
else:
    import unittest

import json
import pyhandle
from pyhandle.handlesystemconnector import HandleSystemConnector
from pyhandle.handleexceptions import HandleSyntaxError, CredentialsFormatError
from pyhandle.utilhandle import check_handle_syntax, check_handle_syntax_with_index, remove_index_from_handle

# Load some data that is needed for testing
PATH_CRED = pyhandle.util.get_neighbour_directory(__file__, 'testcredentials')
FILE_BOTH = PATH_CRED+'/fake_certs_and_keys/fake_certi_and_bothkeys.pem'
FILE_KEY = PATH_CRED+'/fake_certs_and_keys/fake_privatekey.pem'
FILE_CERT = PATH_CRED+'/fake_certs_and_keys/fake_certificate.pem'

class RESTHandleConnectorNoaccessTestCase(unittest.TestCase):

    def setUp(self):
        self.inst = HandleSystemConnector()

    def tearDown(self):
        pass

    # make_handle_url

    def test_make_handle_url(self):

        url = self.inst.make_handle_URL('testhandle')
        self.assertIn('/api/handles/', url,
            'No REST API path specified in URL: '+url)
        self.assertIn('handle.net', url,
            'handle.net missing in URL: '+url)
        self.assertNotIn('index=', url,
            'Index specified in URL: '+url)
        #self.assertIn('overwrite=false', url,
        #    'overwrite=false is missing: '+url)

    def test_make_handle_url_with_indices(self):

        url = self.inst.make_handle_URL('testhandle', [2,3,5])
        self.assertIn('/api/handles/', url,
            'No REST API path specified in URL: '+url)
        self.assertIn('index=2', url,
            'Index 2 specified in URL: '+url)
        self.assertIn('index=3', url,
            'Index 3 specified in URL: '+url)
        self.assertIn('index=5', url,
            'Index 5 specified in URL: '+url)
        #self.assertIn('overwrite=false', url,
        #    'overwrite=false is missing: '+url)

    def test_make_handle_url_overwrite_true(self):

        url = self.inst.make_handle_URL('testhandle', overwrite=True)
        self.assertIn('/api/handles/', url,
            'No REST API path specified in URL: '+url)
        self.assertIn('overwrite=true', url,
            'overwrite=true is missing: '+url)

    def test_make_handle_url_overwrite_false(self):

        url = self.inst.make_handle_URL('testhandle', overwrite=False)
        self.assertIn('/api/handles/', url,
            'No REST API path specified in URL: '+url)
        self.assertIn('overwrite=false', url,
            'overwrite=false is missing: '+url)

    def test_make_handle_url_otherurl(self):

        other = 'http://foo.foo'
        url = self.inst.make_handle_URL('testhandle', other_url=other)
        self.assertNotIn('/api/handles/', url,
            'REST API path should not be specified in URL: '+url)
        self.assertIn(other, url,
            'Other URL missing in URL: '+url)
        self.assertNotIn('handle.net', url,
            'handle.net should not be in URL: '+url)
        self.assertNotIn('index=', url,
            'Index specified in URL: '+url)
        #self.assertIn('overwrite=false', url,
        #    'overwrite=false is missing: '+url)

    # Initiating:

    def test_init_cert_onefile(self):

        inst = HandleSystemConnector(
            certificate_and_key=FILE_BOTH,
            handle_server_url='http://foo.com'
        )
        self.assertIsInstance(inst, HandleSystemConnector)

    def test_init_cert_twofiles(self):

        inst = HandleSystemConnector(
            certificate_only=FILE_CERT,
            private_key=FILE_KEY,
            handle_server_url='http://foo.com'
        )
        self.assertIsInstance(inst, HandleSystemConnector)

    def test_init_cert_serverurl_missing(self):

        with self.assertRaises(TypeError):
            inst = HandleSystemConnector(FILE_BOTH)

    def test_init_privatekey_missing(self):

        inst = HandleSystemConnector(
            certificate_only=FILE_BOTH,
            handle_server_url='http://foo.com'
        )
        self.assertIsInstance(inst, HandleSystemConnector)

    def test_init_certificate_missing(self):

        inst = HandleSystemConnector(
            handle_server_url='http://foo.com',
            private_key=FILE_KEY
        )
        self.assertIsInstance(inst, HandleSystemConnector)

    def test_init_cert_onefile_wrongpath(self):

        with self.assertRaises(CredentialsFormatError):
            inst = HandleSystemConnector(
                certificate_and_key=PATH_CRED+'/noexist.pem',
                handle_server_url='http://foo.com'
            )


text:
package fit

import (
	"bytes"
	"encoding/binary"
	"math/rand"
	"testing"

	"github.com/stretchr/testify/require"
)

func randBytes(size uint) []byte {
	rand.Seed(0)
	b := make([]byte, int(size))
	rand.Read(b)
	return b
}

func TestEntrySACM_ParseData(t *testing.T) {
	sizeOffset := EntrySACMDataCommon{}.SizeBinaryOffset()
	sizeEndOffset := sizeOffset + uint(binary.Size(EntrySACMDataCommon{}.Size))

	versionOffset := EntrySACMDataCommon{}.HeaderVersionBinaryOffset()
	versionEndOffset := versionOffset + uint(binary.Size(EntrySACMDataCommon{}.HeaderVersion))

	keySizeOffset := EntrySACMDataCommon{}.KeySizeBinaryOffset()
	keySizeEndOffset := keySizeOffset + uint(binary.Size(EntrySACMDataCommon{}.KeySize))

	entry := EntrySACM{
		EntryBase: EntryBase{
			DataSegmentBytes: randBytes(65536),
			HeadersErrors:    nil,
		},
	}

	testPositive := func(t *testing.T, headersSize int) {
		data, err := entry.ParseData()
		require.NoError(t, err)

		_ = data.GetRSAPubKey()
		require.Zero(t, len(data.UserArea))
		require.Zero(t, len(entry.DataSegmentBytes)-headersSize)
		require.NotZero(t, data.GetKeySize())

		var buf bytes.Buffer
		_, err = data.WriteTo(&buf)
		require.NoError(t, err)

		dataCopy, err := ParseSACMData(&buf)
		require.NoError(t, err)

		require.Equal(t, data, dataCopy)
	}

	t.Run("SACMv0", func(t *testing.T) {
		binary.LittleEndian.PutUint32(entry.DataSegmentBytes[versionOffset:versionEndOffset], uint32(ACHeaderVersion0))
		binary.LittleEndian.PutUint32(entry.DataSegmentBytes[sizeOffset:sizeEndOffset], uint32(entrySACMData0Size)>>2)
		dataSize, err := EntrySACMParseSize(entry.DataSegmentBytes[:65536])
		require.NoError(t, err)
		entry.DataSegmentBytes = entry.DataSegmentBytes[:dataSize]
		t.Run("positive", func(t *testing.T) {
			binary.LittleEndian.PutUint32(entry.DataSegmentBytes[keySizeOffset:keySizeEndOffset], 256>>2)
			testPositive(t, int(entrySACMData0Size))
		})
	})

	t.Run("SACMv3", func(t *testing.T) {
		binary.LittleEndian.PutUint32(entry.DataSegmentBytes[versionOffset:versionEndOffset], uint32(ACHeaderVersion3))
		binary.LittleEndian.PutUint32(entry.DataSegmentBytes[sizeOffset:sizeEndOffset], uint32(entrySACMData3Size)>>2)
		dataSize, err := EntrySACMParseSize(entry.DataSegmentBytes[:65536])
		require.NoError(t, err)
		entry.DataSegmentBytes = entry.DataSegmentBytes[:dataSize]
		t.Run("positive", func(t *testing.T) {
			binary.LittleEndian.PutUint32(entry.DataSegmentBytes[keySizeOffset:keySizeEndOffset], 384>>2)
			testPositive(t, int(entrySACMData3Size))
		})
		t.Run("negative_keySize", func(t *testing.T) {
			binary.LittleEndian.PutUint32(entry.DataSegmentBytes[keySizeOffset:keySizeEndOffset], 256>>2)

			_, err := entry.ParseData()
			require.Error(t, err)
		})
	})

	t.Run("SACM_invalidVersion", func(t *testing.T) {
		binary.LittleEndian.PutUint32(entry.DataSegmentBytes[versionOffset:versionEndOffset], 0x12345678)
		binary.LittleEndian.PutUint32(entry.DataSegmentBytes[sizeOffset:sizeEndOffset], uint32(entrySACMData0Size)>>2)
		dataSize, err := EntrySACMParseSize(entry.DataSegmentBytes[:65536])
		require.NoError(t, err)
		entry.DataSegmentBytes = entry.DataSegmentBytes[:dataSize]

		_, err = entry.ParseData()
		require.Error(t, err)
	})
}


text:
import itertools
import matplotlib.pyplot as plt
import numpy as np

# TODO change to directly use mpl's OOP interface (no pyplot)

def grid_of_grids(ary, ax_kwargs={}, im_kwargs={}, grid_dims={}):
  nrows, ncols = compute_grid_dimensions(len(ary), **grid_dims)
  plt.figure()
  indices = list(itertools.product(range(nrows), range(ncols)))[:len(ary)]
  for i,j in indices:
    ax = plt.subplot2grid((nrows, ncols), (i,j), **ax_kwargs)
    ax.imshow(ary[i*ncols+j], **im_kwargs)
  return plt.gcf()

def compute_grid_dimensions(min_cells, nrows=None, ncols=None):
  if nrows == None and ncols == None:
    nrows = int(np.ceil(np.sqrt(min_cells)))
    ncols = nrows if min_cells > nrows*nrows-1 else nrows-1
    return (int(np.ceil(nrows)), int(ncols))
  elif nrows == None:
    return int(np.ceil(min_cells / ncols)), int(ncols)
  elif ncols == None:
    return int(nrows), int(np.ceil(min_cells / nrows))
  else:
    return int(nrows), int(ncols)


text:
module susiApp.Services {
    'use strict';

    export class HomeService {
        httpService: ng.IHttpService;
        qService: ng.IQService;

        static $inject = ['$http', '$q'];

        constructor($http: ng.IHttpService, $q: ng.IQService) {
            this.httpService = $http;
            this.qService = $q;
        }

        getArticles(): ng.IPromise<Array<susiApp.Models.IArticleViewModel>> {
            var defer = this.qService.defer<Array<susiApp.Models.IArticleViewModel>>();

            this.httpService.get<Array<susiApp.Models.IArticleViewModel>>(
                '/api/home?index=1', {
                    responseType: 'json'
                }).then((response) => {
                defer.resolve(response.data);
            });

            return defer.promise;
        }
        getWebsites(): ng.IPromise<Array<susiApp.Models.IWebsite>> {
            var defer = this.qService.defer<Array<susiApp.Models.IWebsite>>();

            this.httpService.get<Array<susiApp.Models.IWebsite>>(
                '/api/home?websites=1', {
                    responseType: 'json'
                }).then((response) => {
                defer.resolve(response.data);
            });

            return defer.promise;
        }
    }

    export class NewsService implements susiApp.Interfaces.INewsService {
        firstFew: Array<susiApp.Models.IArticleViewModel>;
        article: susiApp.Models.IArticleViewModel;
        httpService: ng.IHttpService;
        qService: ng.IQService;

        static $inject = ['$http', '$q'];

        constructor($http: ng.IHttpService, $q: ng.IQService) {
            this.httpService = $http;
            this.qService = $q;
        }

        getFirstFew(): ng.IPromise<Array<susiApp.Models.IArticleViewModel>> {
            var defer = this.qService.defer<Array<susiApp.Models.IArticleViewModel>>();

            this.httpService.get<Array<susiApp.Models.IArticleViewModel>>(
                '/api/news', {
                    responseType: 'json'
                }).then((response) => {
                defer.resolve(response.data);
                });

            return defer.promise;
        }

        getArticle(id: number): ng.IPromise<susiApp.Models.IArticleViewModel> {
            var defer = this.qService.defer<susiApp.Models.IArticleViewModel>();

            this.httpService.get<susiApp.Models.IArticleViewModel>(
                '/api/article?id=' + id, {
                    responseType: 'json'
                }).then((response) => {
                defer.resolve(response.data);
            });

            return defer.promise;
        }
    }

    export class SUSIService implements susiApp.Interfaces.ISUSIService {
        httpService: ng.IHttpService;
        qService: ng.IQService;

        static $inject = ['$http', '$q'];

        constructor($http: ng.IHttpService, $q: ng.IQService) {
            this.httpService = $http;
            this.qService = $q;
        }

        getStudentInfo(): ng.IPromise<susiApp.Models.IStudentViewModel> {
            var defer = this.qService.defer<susiApp.Models.IStudentViewModel>();

            this.httpService.get<susiApp.Models.IStudentViewModel>(
                '/api/susi', {
                    responseType: 'json'
                }).then((response) => {
                defer.resolve(response.data);
            });

            return defer.promise;
        }

        getCourses(): ng.IPromise<Array<susiApp.Models.ICourseResultViewModel>> {
            var defer = this.qService.defer<Array<susiApp.Models.ICourseResultViewModel>>();

            this.httpService.get<Array<susiApp.Models.ICourseResultViewModel>>(
                '/api/susi?courses', {
                    responseType: 'json'
                }).then((response) => {
                defer.resolve(response.data);
            });

            return defer.promise;
        }
    }

    export class AdminService {

    }

    angular.module('susiApp')
        .service('susiApp.Services.HomeService', HomeService)
        .service('susiApp.Services.NewsService', NewsService)
        .service('susiApp.Services.SUSIService', SUSIService);
}


text:
module Test where

import Lib

import Distribution.TestSuite

tests :: IO [Test]
tests = return [Test bar]
  where
    bar = TestInstance
        { run = return $ Finished run
        , name = "test"
        , tags = []
        , options = []
        , setOption = \_ _ -> Right bar
        }
    run = if foo then Pass else Fail "should pass"


text:
/* { dg-do compile } */

struct timespec
{
  long tv_sec;
  long tv_nsec;
};
struct inode
{
  struct timespec i_atime;
  struct timespec i_mtime;
};
struct afs_vnode
{
  struct inode vfs_inode;
};
static inline
  struct inode *AFS_VNODE_TO_I (struct afs_vnode *vnode)
{
  return &vnode->vfs_inode;
};
afs_inode_map_status (struct afs_vnode *vnode)
{
  struct inode *inode = AFS_VNODE_TO_I (vnode);
  inode->i_atime = inode->i_mtime;
}


text:
<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateNodeProducerBlacklistTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('node_producer_blacklist', function (Blueprint $table) {
            $table->integer('node_id')->required();
            $table->string('producer_id')->required();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::drop('node_producer_blacklist');
    }
}


text:
import {NgModule} from '@angular/core';
import {BrowserModule} from '@angular/platform-browser';
import {AttributesModule} from '../attributes.module';
import {ProgressbarBComponent, ProgressbarBDirective} from './progressbar.bcomponent';

var directives = [
    ProgressbarBComponent,
    ProgressbarBDirective
];

@NgModule({
    imports: [BrowserModule, AttributesModule],
    declarations: directives,
    exports: directives
})
export class ProgressbarModule {}


text:
using System;
using CoreGraphics;
using Foundation;
using UIKit;
using WebKit;

namespace Xamarin.iOS.FileExplorer.ViewControllers
{
	public sealed class WebViewController : UIViewController
	{
		private readonly NSUrl _url;

		public WebViewController(NSUrl url)
		{
			_url = url;
		}

		public WebViewController(IntPtr handle) : base(handle)
		{
		}

		public override void ViewDidLoad()
		{
			base.ViewDidLoad();

			var webView = new WKWebView(new CGRect(), new WKWebViewConfiguration());
			webView.TranslatesAutoresizingMaskIntoConstraints = false;
			View.Add(webView);
			webView.LoadFileUrl(_url, _url);
		}
	}
}


text:
**Multithreaded task scheduler experiments. Now with integrated profiler!**
![alt tag](https://raw.githubusercontent.com/SergeyMakeev/TaskScheduler/master/Images/profiler_ui.jpg)

**Written under the influence by great GDC talk "Parallelizing the Naughty Dog engine using fibers" by Christian Gyrling**

Compiled and worked on : **Clang 3.4, GCC 4.8.2, MSVC 2010**

## Build status

![alt tag](https://api.travis-ci.org/SergeyMakeev/TaskScheduler.svg?branch=master)

## Useful reading (in random order):

Parallelizing the Naughty Dog engine using fibers
http://www.swedishcoding.com/wp-content/uploads/2015/03/parallelizing_the_naughty_dog_engine_using_fibers.pdf

id Tech 5 Challenges
From Texture Virtualization to Massive Parallelization
http://s09.idav.ucdavis.edu/talks/05-JP_id_Tech_5_Challenges.pdf

Doom3 BFG Source Code Review: Multi-threading
http://fabiensanglard.net/doom3_bfg/threading.php

How Ubisoft Develops Games for Multicore - Before and After C++11
http://www.youtube.com/watch?v=X1T3IQ4N-3g

Killzone Shadow Fall: Threading the Entity Update on PS4
http://www.slideshare.net/jrouwe/killzone-shadow-fall-threading-the-entity-update-on-ps4

Killzone Shadow Fall Demo Postmortem
http://www.guerrilla-games.com/presentations/Valient_Killzone_Shadow_Fall_Demo_Postmortem.pdf

Infamous Second Son : Engine Postmortem
http://adruab.net/wp-images/GDC14_infamous_second_son_engine_postmortem.pdf

Multithreading the Entire Destiny Engine - GDC 2015
http://www.gdcvault.com/play/1022164/Multithreading-the-Entire-Destiny (members only)
http://chomikuj.pl/dexio21/GDC+2015/GDC+Vault+-+Multithreading+the+Entire+Destiny+Engine,4690817362.mp4%28video%29

Molecule Engine - Building a load-balanced task scheduler
https://molecularmusings.wordpress.com/2012/04/05/building-a-load-balanced-task-scheduler-part-1-basics/

Intel Threading Building Blocks - Scheduling Algorithm
https://www.threadingbuildingblocks.org/docs/help/reference/task_scheduler/scheduling_algorithm.htm

CILK/CILK++ and Reducers
http://www.slideshare.net/yunmingzhang/yunming-zhang-presentations

Task Scheduling Strategies
http://www.1024cores.net/home/scalable-architecture/task-scheduling-strategies

Implementing a Work-Stealing Task Scheduler on the ARM11 MPCore
http://www.rtcgroup.com/arm/2007/presentations/211%20-%20Implementing%20a%20Work-Stealing%20Task%20Scheduler.pdf

Lost Planet graphics course for 3D game fan of Nishikawa Zenji
http://game.watch.impress.co.jp/docs/20070131/3dlp.htm

Dragged Kicking and Screaming: Source Multicore
http://www.valvesoftware.com/publications/2007/GDC2007_SourceMulticore.pdf

Games: Playing with Threads
http://www2.epcc.ed.ac.uk/downloads/lectures/BenNicholson/BenNicholson.pdf


text:
package org.apache.hc.client5.http.entity.mime;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.nio.charset.StandardCharsets;

import org.apache.hc.core5.http.ContentType;
import org.apache.hc.core5.http.HeaderElement;
import org.apache.hc.core5.http.HttpEntity;
import org.apache.hc.core5.http.NameValuePair;
import org.apache.hc.core5.http.message.BasicHeaderValueParser;
import org.apache.hc.core5.http.message.ParserCursor;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

public class TestMultipartFormHttpEntity {

    @Test
    public void testExplictContractorParams() throws Exception {
        final HttpEntity entity = MultipartEntityBuilder.create()
                .setLaxMode()
                .setBoundary("whatever")
                .setCharset(StandardCharsets.UTF_8)
                .build();

        Assertions.assertNull(entity.getContentEncoding());
        final String contentType = entity.getContentType();
        final HeaderElement elem = BasicHeaderValueParser.INSTANCE.parseHeaderElement(contentType,
                new ParserCursor(0, contentType.length()));
        Assertions.assertEquals("multipart/mixed", elem.getName());
        final NameValuePair p1 = elem.getParameterByName("boundary");
        Assertions.assertNotNull(p1);
        Assertions.assertEquals("whatever", p1.getValue());
        final NameValuePair p2 = elem.getParameterByName("charset");
        Assertions.assertNotNull(p2);
        Assertions.assertEquals("UTF-8", p2.getValue());
    }

    @Test
    public void testImplictContractorParams() throws Exception {
        final HttpEntity entity = MultipartEntityBuilder.create().build();
        Assertions.assertNull(entity.getContentEncoding());
        final String contentType = entity.getContentType();
        final HeaderElement elem = BasicHeaderValueParser.INSTANCE.parseHeaderElement(contentType,
                new ParserCursor(0, contentType.length()));
        Assertions.assertEquals("multipart/mixed", elem.getName());
        final NameValuePair p1 = elem.getParameterByName("boundary");
        Assertions.assertNotNull(p1);

        final String boundary = p1.getValue();
        Assertions.assertNotNull(boundary);

        Assertions.assertTrue(boundary.length() >= 30);
        Assertions.assertTrue(boundary.length() <= 40);

        final NameValuePair p2 = elem.getParameterByName("charset");
        Assertions.assertNull(p2);
    }

    @Test
    public void testRepeatable() throws Exception {
        final HttpEntity entity = MultipartEntityBuilder.create()
                .addTextBody("p1", "blah blah", ContentType.DEFAULT_TEXT)
                .addTextBody("p2", "yada yada", ContentType.DEFAULT_TEXT)
                .build();
        Assertions.assertTrue(entity.isRepeatable());
        Assertions.assertFalse(entity.isChunked());
        Assertions.assertFalse(entity.isStreaming());

        final long len = entity.getContentLength();
        Assertions.assertEquals(len, entity.getContentLength());

        ByteArrayOutputStream out = new ByteArrayOutputStream();
        entity.writeTo(out);
        out.close();

        byte[] bytes = out.toByteArray();
        Assertions.assertNotNull(bytes);
        Assertions.assertEquals(bytes.length, len);

        Assertions.assertEquals(len, entity.getContentLength());

        out = new ByteArrayOutputStream();
        entity.writeTo(out);
        out.close();

        bytes = out.toByteArray();
        Assertions.assertNotNull(bytes);
        Assertions.assertEquals(bytes.length, len);
    }

    @Test
    public void testNonRepeatable() throws Exception {
        final HttpEntity entity = MultipartEntityBuilder.create()
            .addPart("p1", new InputStreamBody(
                new ByteArrayInputStream("blah blah".getBytes()), ContentType.DEFAULT_BINARY))
            .addPart("p2", new InputStreamBody(
                new ByteArrayInputStream("yada yada".getBytes()), ContentType.DEFAULT_BINARY))
            .build();
        Assertions.assertFalse(entity.isRepeatable());
        Assertions.assertTrue(entity.isChunked());
        Assertions.assertTrue(entity.isStreaming());

        Assertions.assertEquals(-1, entity.getContentLength());
    }

}