<commit_before>/**
 * @copyright
 * ====================================================================
 * Copyright (c) 2007 CollabNet.  All rights reserved.
 *
 * This software is licensed as described in the file COPYING, which
 * you should have received as part of this distribution.  The terms
 * are also available at http://subversion.tigris.org/license-1.html.
 * If newer versions of this license are posted there, you may use a
 * newer version instead, at your option.
 *
 * This software consists of voluntary contributions made by many
 * individuals.  For exact contribution history, see the revision
 * history and logs, available at http://subversion.tigris.org/.
 * ====================================================================
 * @endcopyright
 *
 * @file StatusCallback.cpp
 * @brief Implementation of the class StatusCallback
 */

#include "StatusCallback.h"
#include "EnumMapper.h"
#include "SVNClient.h"
#include "JNIUtil.h"
#include "svn_time.h"
#include "../include/org_tigris_subversion_javahl_NodeKind.h"
#include "../include/org_tigris_subversion_javahl_Revision.h"
#include "../include/org_tigris_subversion_javahl_StatusKind.h"

/**
 * Create a StatusCallback object
 * @param jcallback the Java callback object.
 */
StatusCallback::StatusCallback(jobject jcallback)
{
  m_callback = jcallback;
}

/**
 * Destroy a StatusCallback object
 */
StatusCallback::~StatusCallback()
{
  // the m_callback does not need to be destroyed, because it is the passed
  // in parameter to the Java SVNClient.status method.
}

svn_error_t *
StatusCallback::callback(void *baton,
                         const char *path,
                         svn_wc_status2_t *status,
                         apr_pool_t *pool)
{
  if (baton)
    ((StatusCallback *)baton)->doStatus(path, status);
}

/**
 * Callback called for a single status item.
 */
svn_error_t *
StatusCallback::doStatus(const char *path, svn_wc_status2_t *status)
{
  JNIEnv *env = JNIUtil::getEnv();

  static jmethodID mid = 0; // the method id will not change during
  // the time this library is loaded, so
  // it can be cached.
  if (mid == 0)
    {
      jclass clazz = env->FindClass(JAVA_PACKAGE"/StatusCallback");
      if (JNIUtil::isJavaExceptionThrown())
        return SVN_NO_ERROR;

      mid = env->GetMethodID(clazz, "doStatus",
                             "(L"JAVA_PACKAGE"/Status;)V");
      if (JNIUtil::isJavaExceptionThrown() || mid == 0)
        return SVN_NO_ERROR;

      env->DeleteLocalRef(clazz);
      if (JNIUtil::isJavaExceptionThrown())
        return SVN_NO_ERROR;
    }

  jobject jStatus = createJavaStatus(path, status);
  if (JNIUtil::isJavaExceptionThrown())
    return SVN_NO_ERROR;

  env->CallVoidMethod(m_callback, mid, jStatus);
  if (JNIUtil::isJavaExceptionThrown())
    return SVN_NO_ERROR;

  env->DeleteLocalRef(jStatus);
  // We return here regardless of whether an exception is thrown or not,
  // so we do not need to explicitly check for one.
  return SVN_NO_ERROR;
}

jobject
StatusCallback::createJavaStatus(const char *path,
                                 svn_wc_status2_t *status)
{
  JNIEnv *env = JNIUtil::getEnv();
  jclass clazz = env->FindClass(JAVA_PACKAGE"/Status");
  if (JNIUtil::isJavaExceptionThrown())
    return NULL;

  static jmethodID mid = 0;
  if (mid == 0)
    {
      mid = env->GetMethodID(clazz, "<init>",
                             "(Ljava/lang/String;Ljava/lang/String;"
                             "IJJJLjava/lang/String;IIIIZZ"
                             "Ljava/lang/String;Ljava/lang/String;"
                             "Ljava/lang/String;Ljava/lang/String;"
                             "JZLjava/lang/String;Ljava/lang/String;"
                             "Ljava/lang/String;"
                             "JLorg/tigris/subversion/javahl/Lock;"
                             "JJILjava/lang/String;Ljava/lang/String;)V");
      if (JNIUtil::isJavaExceptionThrown())
        return NULL;
    }
  jstring jPath = JNIUtil::makeJString(path);
  if (JNIUtil::isJavaExceptionThrown())
    return NULL;

  jstring jUrl = NULL;
  jint jNodeKind = org_tigris_subversion_javahl_NodeKind_unknown;
  jlong jRevision = org_tigris_subversion_javahl_Revision_SVN_INVALID_REVNUM;
  jlong jLastChangedRevision =
    org_tigris_subversion_javahl_Revision_SVN_INVALID_REVNUM;
  jlong jLastChangedDate = 0;
  jstring jLastCommitAuthor = NULL;
  jint jTextType = org_tigris_subversion_javahl_StatusKind_none;
  jint jPropType = org_tigris_subversion_javahl_StatusKind_none;
  jint jRepositoryTextType = org_tigris_subversion_javahl_StatusKind_none;
  jint jRepositoryPropType = org_tigris_subversion_javahl_StatusKind_none;
  jboolean jIsLocked = JNI_FALSE;
  jboolean jIsCopied = JNI_FALSE;
  jboolean jIsSwitched = JNI_FALSE;
  jstring jConflictOld = NULL;
  jstring jConflictNew = NULL;
  jstring jConflictWorking = NULL;
  jstring jURLCopiedFrom = NULL;
  jlong jRevisionCopiedFrom =
    org_tigris_subversion_javahl_Revision_SVN_INVALID_REVNUM;
  jstring jLockToken = NULL;
  jstring jLockComment = NULL;
  jstring jLockOwner = NULL;
  jlong jLockCreationDate = 0;
  jobject jLock = NULL;
  jlong jOODLastCmtRevision =
    org_tigris_subversion_javahl_Revision_SVN_INVALID_REVNUM;
  jlong jOODLastCmtDate = 0;
  jint jOODKind = org_tigris_subversion_javahl_NodeKind_none;
  jstring jOODLastCmtAuthor = NULL;
  jstring jChangelist = NULL;
  if (status != NULL)
    {
      jTextType = EnumMapper::mapStatusKind(status->text_status);
      jPropType = EnumMapper::mapStatusKind(status->prop_status);
      jRepositoryTextType = EnumMapper::mapStatusKind(
                                                      status->repos_text_status);
      jRepositoryPropType = EnumMapper::mapStatusKind(
                                                      status->repos_prop_status);
      jIsCopied = (status->copied == 1) ? JNI_TRUE: JNI_FALSE;
      jIsLocked = (status->locked == 1) ? JNI_TRUE: JNI_FALSE;
      jIsSwitched = (status->switched == 1) ? JNI_TRUE: JNI_FALSE;
      jLock = SVNClient::createJavaLock(status->repos_lock);
      if (JNIUtil::isJavaExceptionThrown())
        return NULL;

      jUrl = JNIUtil::makeJString(status->url);
      if (JNIUtil::isJavaExceptionThrown())
        return NULL;

      jOODLastCmtRevision = status->ood_last_cmt_rev;
      jOODLastCmtDate = status->ood_last_cmt_date;
      jOODKind = EnumMapper::mapNodeKind(status->ood_kind);
      jOODLastCmtAuthor = JNIUtil::makeJString(status->ood_last_cmt_author);
      if (JNIUtil::isJavaExceptionThrown())
        return NULL;

      svn_wc_entry_t *entry = status->entry;
      if (entry != NULL)
        {
          jNodeKind = EnumMapper::mapNodeKind(entry->kind);
          jRevision = entry->revision;
          jLastChangedRevision = entry->cmt_rev;
          jLastChangedDate = entry->cmt_date;
          jLastCommitAuthor = JNIUtil::makeJString(entry->cmt_author);
          if (JNIUtil::isJavaExceptionThrown())
            return NULL;

          jConflictNew = JNIUtil::makeJString(entry->conflict_new);
          if (JNIUtil::isJavaExceptionThrown())
            return NULL;

          jConflictOld = JNIUtil::makeJString(entry->conflict_old);
          if (JNIUtil::isJavaExceptionThrown())
            return NULL;

          jConflictWorking= JNIUtil::makeJString(entry->conflict_wrk);
          if (JNIUtil::isJavaExceptionThrown())
            return NULL;

          jURLCopiedFrom = JNIUtil::makeJString(entry->copyfrom_url);
          if (JNIUtil::isJavaExceptionThrown())
            return NULL;

          jRevisionCopiedFrom = entry->copyfrom_rev;
          jLockToken = JNIUtil::makeJString(entry->lock_token);
          if (JNIUtil::isJavaExceptionThrown())
            return NULL;

          jLockComment = JNIUtil::makeJString(entry->lock_comment);
          if (JNIUtil::isJavaExceptionThrown())
            return NULL;

          jLockOwner = JNIUtil::makeJString(entry->lock_owner);
          if (JNIUtil::isJavaExceptionThrown())
            return NULL;

          jLockCreationDate = entry->lock_creation_date;

          jChangelist = JNIUtil::makeJString(entry->changelist);
          if (JNIUtil::isJavaExceptionThrown())
            return NULL;
        }
    }

  jobject ret = env->NewObject(clazz, mid, jPath, jUrl, jNodeKind, jRevision,
                               jLastChangedRevision, jLastChangedDate,
                               jLastCommitAuthor, jTextType, jPropType,
                               jRepositoryTextType, jRepositoryPropType,
                               jIsLocked, jIsCopied, jConflictOld,
                               jConflictNew, jConflictWorking,
                               jURLCopiedFrom, jRevisionCopiedFrom,
                               jIsSwitched, jLockToken, jLockOwner,
                               jLockComment, jLockCreationDate, jLock,
                               jOODLastCmtRevision, jOODLastCmtDate,
                               jOODKind, jOODLastCmtAuthor, jChangelist);
  if (JNIUtil::isJavaExceptionThrown())
    return NULL;

  env->DeleteLocalRef(clazz);
  if (JNIUtil::isJavaExceptionThrown())
    return NULL;

  env->DeleteLocalRef(jPath);
  if (JNIUtil::isJavaExceptionThrown())
    return NULL;

  env->DeleteLocalRef(jUrl);
  if (JNIUtil::isJavaExceptionThrown())
    return NULL;

  env->DeleteLocalRef(jLastCommitAuthor);
  if (JNIUtil::isJavaExceptionThrown())
    return NULL;

  env->DeleteLocalRef(jConflictNew);
  if (JNIUtil::isJavaExceptionThrown())
    return NULL;

  env->DeleteLocalRef(jConflictOld);
  if (JNIUtil::isJavaExceptionThrown())
    return NULL;

  env->DeleteLocalRef(jConflictWorking);
  if (JNIUtil::isJavaExceptionThrown())
    return NULL;

  env->DeleteLocalRef(jURLCopiedFrom);
  if (JNIUtil::isJavaExceptionThrown())
    return NULL;

  env->DeleteLocalRef(jLockComment);
  if (JNIUtil::isJavaExceptionThrown())
    return NULL;

  env->DeleteLocalRef(jLockOwner);
  if (JNIUtil::isJavaExceptionThrown())
    return NULL;

  env->DeleteLocalRef(jLockToken);
  if (JNIUtil::isJavaExceptionThrown())
    return NULL;

  env->DeleteLocalRef(jLock);
  if (JNIUtil::isJavaExceptionThrown())
    return NULL;

  env->DeleteLocalRef(jOODLastCmtAuthor);
  if (JNIUtil::isJavaExceptionThrown())
    return NULL;

  env->DeleteLocalRef(jChangelist);
  if (JNIUtil::isJavaExceptionThrown())
    return NULL;

  return ret;
}
<commit_msg>* subversion/bindings/javahl/native/StatusCallback.cpp   (StatusCallback::callback): Following up on r33739, return SVN_NO_ERROR     to fix compilation.<commit_after>/**
 * @copyright
 * ====================================================================
 * Copyright (c) 2007 CollabNet.  All rights reserved.
 *
 * This software is licensed as described in the file COPYING, which
 * you should have received as part of this distribution.  The terms
 * are also available at http://subversion.tigris.org/license-1.html.
 * If newer versions of this license are posted there, you may use a
 * newer version instead, at your option.
 *
 * This software consists of voluntary contributions made by many
 * individuals.  For exact contribution history, see the revision
 * history and logs, available at http://subversion.tigris.org/.
 * ====================================================================
 * @endcopyright
 *
 * @file StatusCallback.cpp
 * @brief Implementation of the class StatusCallback
 */

#include "StatusCallback.h"
#include "EnumMapper.h"
#include "SVNClient.h"
#include "JNIUtil.h"
#include "svn_time.h"
#include "../include/org_tigris_subversion_javahl_NodeKind.h"
#include "../include/org_tigris_subversion_javahl_Revision.h"
#include "../include/org_tigris_subversion_javahl_StatusKind.h"

/**
 * Create a StatusCallback object
 * @param jcallback the Java callback object.
 */
StatusCallback::StatusCallback(jobject jcallback)
{
  m_callback = jcallback;
}

/**
 * Destroy a StatusCallback object
 */
StatusCallback::~StatusCallback()
{
  // the m_callback does not need to be destroyed, because it is the passed
  // in parameter to the Java SVNClient.status method.
}

svn_error_t *
StatusCallback::callback(void *baton,
                         const char *path,
                         svn_wc_status2_t *status,
                         apr_pool_t *pool)
{
  if (baton)
    ((StatusCallback *)baton)->doStatus(path, status);

  return SVN_NO_ERROR;
}

/**
 * Callback called for a single status item.
 */
svn_error_t *
StatusCallback::doStatus(const char *path, svn_wc_status2_t *status)
{
  JNIEnv *env = JNIUtil::getEnv();

  static jmethodID mid = 0; // the method id will not change during
  // the time this library is loaded, so
  // it can be cached.
  if (mid == 0)
    {
      jclass clazz = env->FindClass(JAVA_PACKAGE"/StatusCallback");
      if (JNIUtil::isJavaExceptionThrown())
        return SVN_NO_ERROR;

      mid = env->GetMethodID(clazz, "doStatus",
                             "(L"JAVA_PACKAGE"/Status;)V");
      if (JNIUtil::isJavaExceptionThrown() || mid == 0)
        return SVN_NO_ERROR;

      env->DeleteLocalRef(clazz);
      if (JNIUtil::isJavaExceptionThrown())
        return SVN_NO_ERROR;
    }

  jobject jStatus = createJavaStatus(path, status);
  if (JNIUtil::isJavaExceptionThrown())
    return SVN_NO_ERROR;

  env->CallVoidMethod(m_callback, mid, jStatus);
  if (JNIUtil::isJavaExceptionThrown())
    return SVN_NO_ERROR;

  env->DeleteLocalRef(jStatus);
  // We return here regardless of whether an exception is thrown or not,
  // so we do not need to explicitly check for one.
  return SVN_NO_ERROR;
}

jobject
StatusCallback::createJavaStatus(const char *path,
                                 svn_wc_status2_t *status)
{
  JNIEnv *env = JNIUtil::getEnv();
  jclass clazz = env->FindClass(JAVA_PACKAGE"/Status");
  if (JNIUtil::isJavaExceptionThrown())
    return NULL;

  static jmethodID mid = 0;
  if (mid == 0)
    {
      mid = env->GetMethodID(clazz, "<init>",
                             "(Ljava/lang/String;Ljava/lang/String;"
                             "IJJJLjava/lang/String;IIIIZZ"
                             "Ljava/lang/String;Ljava/lang/String;"
                             "Ljava/lang/String;Ljava/lang/String;"
                             "JZLjava/lang/String;Ljava/lang/String;"
                             "Ljava/lang/String;"
                             "JLorg/tigris/subversion/javahl/Lock;"
                             "JJILjava/lang/String;Ljava/lang/String;)V");
      if (JNIUtil::isJavaExceptionThrown())
        return NULL;
    }
  jstring jPath = JNIUtil::makeJString(path);
  if (JNIUtil::isJavaExceptionThrown())
    return NULL;

  jstring jUrl = NULL;
  jint jNodeKind = org_tigris_subversion_javahl_NodeKind_unknown;
  jlong jRevision = org_tigris_subversion_javahl_Revision_SVN_INVALID_REVNUM;
  jlong jLastChangedRevision =
    org_tigris_subversion_javahl_Revision_SVN_INVALID_REVNUM;
  jlong jLastChangedDate = 0;
  jstring jLastCommitAuthor = NULL;
  jint jTextType = org_tigris_subversion_javahl_StatusKind_none;
  jint jPropType = org_tigris_subversion_javahl_StatusKind_none;
  jint jRepositoryTextType = org_tigris_subversion_javahl_StatusKind_none;
  jint jRepositoryPropType = org_tigris_subversion_javahl_StatusKind_none;
  jboolean jIsLocked = JNI_FALSE;
  jboolean jIsCopied = JNI_FALSE;
  jboolean jIsSwitched = JNI_FALSE;
  jstring jConflictOld = NULL;
  jstring jConflictNew = NULL;
  jstring jConflictWorking = NULL;
  jstring jURLCopiedFrom = NULL;
  jlong jRevisionCopiedFrom =
    org_tigris_subversion_javahl_Revision_SVN_INVALID_REVNUM;
  jstring jLockToken = NULL;
  jstring jLockComment = NULL;
  jstring jLockOwner = NULL;
  jlong jLockCreationDate = 0;
  jobject jLock = NULL;
  jlong jOODLastCmtRevision =
    org_tigris_subversion_javahl_Revision_SVN_INVALID_REVNUM;
  jlong jOODLastCmtDate = 0;
  jint jOODKind = org_tigris_subversion_javahl_NodeKind_none;
  jstring jOODLastCmtAuthor = NULL;
  jstring jChangelist = NULL;
  if (status != NULL)
    {
      jTextType = EnumMapper::mapStatusKind(status->text_status);
      jPropType = EnumMapper::mapStatusKind(status->prop_status);
      jRepositoryTextType = EnumMapper::mapStatusKind(
                                                      status->repos_text_status);
      jRepositoryPropType = EnumMapper::mapStatusKind(
                                                      status->repos_prop_status);
      jIsCopied = (status->copied == 1) ? JNI_TRUE: JNI_FALSE;
      jIsLocked = (status->locked == 1) ? JNI_TRUE: JNI_FALSE;
      jIsSwitched = (status->switched == 1) ? JNI_TRUE: JNI_FALSE;
      jLock = SVNClient::createJavaLock(status->repos_lock);
      if (JNIUtil::isJavaExceptionThrown())
        return NULL;

      jUrl = JNIUtil::makeJString(status->url);
      if (JNIUtil::isJavaExceptionThrown())
        return NULL;

      jOODLastCmtRevision = status->ood_last_cmt_rev;
      jOODLastCmtDate = status->ood_last_cmt_date;
      jOODKind = EnumMapper::mapNodeKind(status->ood_kind);
      jOODLastCmtAuthor = JNIUtil::makeJString(status->ood_last_cmt_author);
      if (JNIUtil::isJavaExceptionThrown())
        return NULL;

      svn_wc_entry_t *entry = status->entry;
      if (entry != NULL)
        {
          jNodeKind = EnumMapper::mapNodeKind(entry->kind);
          jRevision = entry->revision;
          jLastChangedRevision = entry->cmt_rev;
          jLastChangedDate = entry->cmt_date;
          jLastCommitAuthor = JNIUtil::makeJString(entry->cmt_author);
          if (JNIUtil::isJavaExceptionThrown())
            return NULL;

          jConflictNew = JNIUtil::makeJString(entry->conflict_new);
          if (JNIUtil::isJavaExceptionThrown())
            return NULL;

          jConflictOld = JNIUtil::makeJString(entry->conflict_old);
          if (JNIUtil::isJavaExceptionThrown())
            return NULL;

          jConflictWorking= JNIUtil::makeJString(entry->conflict_wrk);
          if (JNIUtil::isJavaExceptionThrown())
            return NULL;

          jURLCopiedFrom = JNIUtil::makeJString(entry->copyfrom_url);
          if (JNIUtil::isJavaExceptionThrown())
            return NULL;

          jRevisionCopiedFrom = entry->copyfrom_rev;
          jLockToken = JNIUtil::makeJString(entry->lock_token);
          if (JNIUtil::isJavaExceptionThrown())
            return NULL;

          jLockComment = JNIUtil::makeJString(entry->lock_comment);
          if (JNIUtil::isJavaExceptionThrown())
            return NULL;

          jLockOwner = JNIUtil::makeJString(entry->lock_owner);
          if (JNIUtil::isJavaExceptionThrown())
            return NULL;

          jLockCreationDate = entry->lock_creation_date;

          jChangelist = JNIUtil::makeJString(entry->changelist);
          if (JNIUtil::isJavaExceptionThrown())
            return NULL;
        }
    }

  jobject ret = env->NewObject(clazz, mid, jPath, jUrl, jNodeKind, jRevision,
                               jLastChangedRevision, jLastChangedDate,
                               jLastCommitAuthor, jTextType, jPropType,
                               jRepositoryTextType, jRepositoryPropType,
                               jIsLocked, jIsCopied, jConflictOld,
                               jConflictNew, jConflictWorking,
                               jURLCopiedFrom, jRevisionCopiedFrom,
                               jIsSwitched, jLockToken, jLockOwner,
                               jLockComment, jLockCreationDate, jLock,
                               jOODLastCmtRevision, jOODLastCmtDate,
                               jOODKind, jOODLastCmtAuthor, jChangelist);
  if (JNIUtil::isJavaExceptionThrown())
    return NULL;

  env->DeleteLocalRef(clazz);
  if (JNIUtil::isJavaExceptionThrown())
    return NULL;

  env->DeleteLocalRef(jPath);
  if (JNIUtil::isJavaExceptionThrown())
    return NULL;

  env->DeleteLocalRef(jUrl);
  if (JNIUtil::isJavaExceptionThrown())
    return NULL;

  env->DeleteLocalRef(jLastCommitAuthor);
  if (JNIUtil::isJavaExceptionThrown())
    return NULL;

  env->DeleteLocalRef(jConflictNew);
  if (JNIUtil::isJavaExceptionThrown())
    return NULL;

  env->DeleteLocalRef(jConflictOld);
  if (JNIUtil::isJavaExceptionThrown())
    return NULL;

  env->DeleteLocalRef(jConflictWorking);
  if (JNIUtil::isJavaExceptionThrown())
    return NULL;

  env->DeleteLocalRef(jURLCopiedFrom);
  if (JNIUtil::isJavaExceptionThrown())
    return NULL;

  env->DeleteLocalRef(jLockComment);
  if (JNIUtil::isJavaExceptionThrown())
    return NULL;

  env->DeleteLocalRef(jLockOwner);
  if (JNIUtil::isJavaExceptionThrown())
    return NULL;

  env->DeleteLocalRef(jLockToken);
  if (JNIUtil::isJavaExceptionThrown())
    return NULL;

  env->DeleteLocalRef(jLock);
  if (JNIUtil::isJavaExceptionThrown())
    return NULL;

  env->DeleteLocalRef(jOODLastCmtAuthor);
  if (JNIUtil::isJavaExceptionThrown())
    return NULL;

  env->DeleteLocalRef(jChangelist);
  if (JNIUtil::isJavaExceptionThrown())
    return NULL;

  return ret;
}
<|endoftext|>


<commit_before>/* Ameba implementation of NetworkInterfaceAPI
 * Copyright (c) 2015 ARM Limited
 *
 * 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.
 */

#include "mbed.h"
#include "rtos.h"

#include "RTWInterface.h"
#include "mbed_interface.h"
#include "rtw_emac.h"

#include "wifi_constants.h"
#include "wifi_conf.h"
#include "lwip_stack.h"

#include "osdep_service.h"

struct netif *xnetif[2];
static struct netif lwap_netif;
extern struct netif *netif_default;

RTWInterface::RTWInterface()
    : _dhcp(true), _ip_address(), _netmask(), _gateway()
{
	nsapi_error_t ret;
	ret = init();
	if (ret != NSAPI_ERROR_OK){
		printf("Error init RTWInterface!(%d)\r\n", ret);
	}
}

static void *scan_sema;
static const signed int maxApNum = 4;
static signed int ApNum;
static WiFiAccessPoint *SCANED_AP[maxApNum]; /*maximum store 15 APs*/

nsapi_error_t RTWInterface::set_network(const char *ip_address, const char *netmask, const char *gateway)
{
    _dhcp = false;
    strncpy(_ip_address, ip_address ? ip_address : "", sizeof(_ip_address));
    strncpy(_netmask, netmask ? netmask : "", sizeof(_netmask));
    strncpy(_gateway, gateway ? gateway : "", sizeof(_gateway));
    return NSAPI_ERROR_OK;
}

nsapi_error_t RTWInterface::set_dhcp(bool dhcp)
{
    _dhcp = dhcp;
    return NSAPI_ERROR_OK;
}

nsapi_error_t RTWInterface::init()
{
    emac_interface_t *emac;
    int ret;

    //printf("\r\nInitializing emac ...\r\n");
    emac = wlan_emac_init_interface();
    if (!emac) {
        return NSAPI_ERROR_DEVICE_ERROR;
    }
    emac->ops.power_up(emac);
    //printf("Initializing lwip ...\r\n");
    ret = mbed_lwip_init(emac);
    if (ret != 0) {
        return ret;
    }
    xnetif[0] = netif_default;
    return NSAPI_ERROR_OK;
}

nsapi_error_t RTWInterface::deinit()
{
    return mbed_lwip_bringdown();
}

/*
 * we may call connect multiple times
 */
nsapi_error_t RTWInterface::set_credentials(const char *ssid, const char *pass, nsapi_security_t security)
{
    strncpy(_ssid, ssid, 255);
    strncpy(_pass, pass, 255);
    _security = security;

    return NSAPI_ERROR_OK;
}

nsapi_error_t RTWInterface::connect()
{
    int ret;
    rtw_security_t sec;

    if (!_ssid || (!_pass && _security != NSAPI_SECURITY_NONE)) {
        printf("Invalid credentials\r\n");
        return NSAPI_ERROR_PARAMETER;
    }

    switch (_security) {
	    case NSAPI_SECURITY_WPA2:
	        sec = RTW_SECURITY_WPA2_MIXED_PSK;
	        break;
	    case NSAPI_SECURITY_NONE:
	    default:
	        sec = RTW_SECURITY_OPEN;
	        break;
    }

    printf("Connecting to: %s ... \r\n", _ssid);
    ret = wifi_connect(_ssid, sec, _pass, strlen(_ssid), strlen(_pass), 0, (void *)NULL);
    if (ret != RTW_SUCCESS) {
        printf("failed: %d\r\n", ret);
        return NSAPI_ERROR_NO_CONNECTION;
    }
    //printf("connected\r\n");

    wlan_emac_link_up(0);
    return mbed_lwip_bringup(_dhcp,
                             _ip_address[0] ? _ip_address : 0,
                             _netmask[0] ? _netmask : 0,
                             _gateway[0] ? _gateway : 0);
}

static rtw_result_t scan_result_handler( rtw_scan_handler_result_t* malloced_scan_result )
{
	if (malloced_scan_result->scan_complete != RTW_TRUE) {
		rtw_scan_result_t* record = &malloced_scan_result->ap_details;
		record->SSID.val[record->SSID.len] = 0; /* Ensure the SSID is null terminated */
		if(ApNum>maxApNum)
			return RTW_SUCCESS;
		nsapi_wifi_ap_t ap;

		memset((void*)&ap, 0x00, sizeof(nsapi_wifi_ap_t));
		memcpy(ap.ssid, record->SSID.val, record->SSID.len);
		memcpy(ap.bssid, record->BSSID.octet, 6);
		ap.security = (record->security == RTW_SECURITY_OPEN)?NSAPI_SECURITY_NONE :
						  (record->security == RTW_SECURITY_WEP_PSK)?NSAPI_SECURITY_WEP:
						  (record->security == RTW_SECURITY_WPA_TKIP_PSK || record->security == RTW_SECURITY_WPA_AES_PSK)? NSAPI_SECURITY_WPA:
						  (record->security == RTW_SECURITY_WPA2_AES_PSK || \
						   record->security == RTW_SECURITY_WPA2_TKIP_PSK || \
						   record->security == RTW_SECURITY_WPA2_MIXED_PSK)?NSAPI_SECURITY_WPA2:
						  (record->security == RTW_SECURITY_WPA_WPA2_MIXED)?NSAPI_SECURITY_WPA_WPA2:NSAPI_SECURITY_UNKNOWN;
		ap.rssi = record->signal_strength;
		ap.channel = record->channel;

		SCANED_AP[ApNum++] = new WiFiAccessPoint(ap);

	} else{
		// scan done

		rtw_up_sema(&scan_sema);
	}
	return RTW_SUCCESS;
}

nsapi_error_t RTWInterface::scan(WiFiAccessPoint *res, unsigned count)
{
	// blocked
	if(count == 0){
		ApNum = 0;

		rtw_init_sema(&scan_sema, 0);
		if(wifi_scan_networks(scan_result_handler, NULL) != RTW_SUCCESS){
			printf("wifi scan failed\n\r");
			//return NSAPI_ERROR_DEVICE_ERROR;
			goto error;
		}

		if(rtw_down_timeout_sema( &scan_sema, 15000 ) == RTW_FALSE) {
			printf("wifi scan timeout\r\n");
			//return NSAPI_ERROR_DEVICE_ERROR;
			goto error;
		}
		rtw_free_sema(&scan_sema);
		return ApNum;

	}else if(count > 0 && res != NULL){
		count = count < maxApNum ? count : maxApNum;
		for(int i = 0; i < count; i++){
			memcpy(&res[i], SCANED_AP[i], sizeof(WiFiAccessPoint));
			delete[] SCANED_AP[i];
 		}
		return (signed int)count;
	}
    return NSAPI_ERROR_OK;
error:
	rtw_free_sema(&scan_sema);
	return NSAPI_ERROR_DEVICE_ERROR;
}

nsapi_error_t RTWInterface::set_channel(uint8_t channel)
{
	if(wifi_set_channel(channel) == 0)
		return NSAPI_ERROR_OK;
    return NSAPI_ERROR_DEVICE_ERROR;
}

int8_t RTWInterface::get_rssi()
{
    return NSAPI_ERROR_UNSUPPORTED;
}

nsapi_error_t RTWInterface::connect(const char *ssid, const char *pass,
                           nsapi_security_t security, uint8_t channel)
{
    set_credentials(ssid, pass, security);
    return connect();
}

nsapi_error_t RTWInterface::disconnect()
{
	char essid[33];

    if(wifi_is_connected_to_ap() != RTW_SUCCESS)
		return NSAPI_ERROR_NO_CONNECTION;
	printf("Deassociating AP ...\r\n");
	if(wifi_disconnect()<0){
		return NSAPI_ERROR_DEVICE_ERROR;
	}

	while(1){
		if(wext_get_ssid(WLAN0_NAME, (unsigned char *) essid) < 0) {
			printf("WIFI disconnected\n\r");
			break;
		}
	}

    return NSAPI_ERROR_OK;
}

int RTWInterface::is_connected()
{
    // wifi_is_connected_to_ap return 0 on connected
    return !wifi_is_connected_to_ap();
}

const char *RTWInterface::get_mac_address()
{
    return mbed_lwip_get_mac_address();
}

const char *RTWInterface::get_ip_address()
{
    if (mbed_lwip_get_ip_address(_ip_address, sizeof _ip_address)) {
        return _ip_address;
    }
    return 0;
}

const char *RTWInterface::get_netmask()
{
    if (mbed_lwip_get_netmask(_netmask, sizeof _netmask)) {
        return _netmask;
    }
    return 0;
}

const char *RTWInterface::get_gateway()
{
    if (mbed_lwip_get_gateway(_gateway, sizeof _gateway)) {
        return _gateway;
    }
    return 0;
}

NetworkStack *RTWInterface::get_stack()
{
    return nsapi_create_stack(&lwip_stack);
}
<commit_msg>Update RTWInterface.cpp<commit_after>/* Ameba implementation of NetworkInterfaceAPI
 * Copyright (c) 2015 ARM Limited
 *
 * 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.
 */

#include "mbed.h"
#include "rtos.h"

#include "RTWInterface.h"
#include "mbed_interface.h"
#include "rtw_emac.h"

#include "wifi_constants.h"
#include "wifi_conf.h"
#include "lwip_stack.h"

#include "osdep_service.h"

struct netif *xnetif[2];
static struct netif lwap_netif;
extern struct netif *netif_default;

RTWInterface::RTWInterface()
    : _dhcp(true), _ip_address(), _netmask(), _gateway()
{
	nsapi_error_t ret;
	ret = init();
	if (ret != NSAPI_ERROR_OK){
		printf("Error init RTWInterface!(%d)\r\n", ret);
	}
}

static void *scan_sema;
static const signed int maxApNum = 4;
static signed int ApNum;
static WiFiAccessPoint *SCANED_AP[maxApNum]; /*maximum store 15 APs*/

nsapi_error_t RTWInterface::set_network(const char *ip_address, const char *netmask, const char *gateway)
{
    _dhcp = false;
    strncpy(_ip_address, ip_address ? ip_address : "", sizeof(_ip_address));
    strncpy(_netmask, netmask ? netmask : "", sizeof(_netmask));
    strncpy(_gateway, gateway ? gateway : "", sizeof(_gateway));
    return NSAPI_ERROR_OK;
}

nsapi_error_t RTWInterface::set_dhcp(bool dhcp)
{
    _dhcp = dhcp;
    return NSAPI_ERROR_OK;
}

nsapi_error_t RTWInterface::init()
{
    emac_interface_t *emac;
    int ret;

    //printf("\r\nInitializing emac ...\r\n");
    emac = wlan_emac_init_interface();
    if (!emac) {
        return NSAPI_ERROR_DEVICE_ERROR;
    }
    emac->ops.power_up(emac);
    //printf("Initializing lwip ...\r\n");
    ret = mbed_lwip_init(emac);
    if (ret != 0) {
        return ret;
    }
    xnetif[0] = netif_default;
    return NSAPI_ERROR_OK;
}

nsapi_error_t RTWInterface::deinit()
{
    return mbed_lwip_bringdown();
}

/*
 * we may call connect multiple times
 */
nsapi_error_t RTWInterface::set_credentials(const char *ssid, const char *pass, nsapi_security_t security)
{
    strncpy(_ssid, ssid, 255);
    strncpy(_pass, pass, 255);
    _security = security;

    return NSAPI_ERROR_OK;
}

nsapi_error_t RTWInterface::connect()
{
    int ret;
    rtw_security_t sec;

    if (!_ssid || (!_pass && _security != NSAPI_SECURITY_NONE)) {
        printf("Invalid credentials\r\n");
        return NSAPI_ERROR_PARAMETER;
    }

    switch (_security) {
	    case NSAPI_SECURITY_WPA2:
	        sec = RTW_SECURITY_WPA2_MIXED_PSK;
	        break;
	    case NSAPI_SECURITY_NONE:
	    default:
	        sec = RTW_SECURITY_OPEN;
	        break;
    }

    printf("Connecting to: %s ... \r\n", _ssid);
    ret = wifi_connect(_ssid, sec, _pass, strlen(_ssid), strlen(_pass), 0, (void *)NULL);
    if (ret != RTW_SUCCESS) {
        printf("failed: %d\r\n", ret);
        return NSAPI_ERROR_NO_CONNECTION;
    }
    //printf("connected\r\n");

    wlan_emac_link_up(0);
    return mbed_lwip_bringup(_dhcp,
                             _ip_address[0] ? _ip_address : 0,
                             _netmask[0] ? _netmask : 0,
                             _gateway[0] ? _gateway : 0);
}

static rtw_result_t scan_result_handler( rtw_scan_handler_result_t* malloced_scan_result )
{
	if (malloced_scan_result->scan_complete != RTW_TRUE) {
		rtw_scan_result_t* record = &malloced_scan_result->ap_details;
		record->SSID.val[record->SSID.len] = 0; /* Ensure the SSID is null terminated */
		if(ApNum>maxApNum)
			return RTW_SUCCESS;
		nsapi_wifi_ap_t ap;

		memset((void*)&ap, 0x00, sizeof(nsapi_wifi_ap_t));
		memcpy(ap.ssid, record->SSID.val, record->SSID.len);
		memcpy(ap.bssid, record->BSSID.octet, 6);
		ap.security = (record->security == RTW_SECURITY_OPEN)?NSAPI_SECURITY_NONE :
						  (record->security == RTW_SECURITY_WEP_PSK)?NSAPI_SECURITY_WEP:
						  (record->security == RTW_SECURITY_WPA_TKIP_PSK || record->security == RTW_SECURITY_WPA_AES_PSK)? NSAPI_SECURITY_WPA:
						  (record->security == RTW_SECURITY_WPA2_AES_PSK || \
						   record->security == RTW_SECURITY_WPA2_TKIP_PSK || \
						   record->security == RTW_SECURITY_WPA2_MIXED_PSK)?NSAPI_SECURITY_WPA2:
						  (record->security == RTW_SECURITY_WPA_WPA2_MIXED)?NSAPI_SECURITY_WPA_WPA2:NSAPI_SECURITY_UNKNOWN;
		ap.rssi = record->signal_strength;
		ap.channel = record->channel;

		SCANED_AP[ApNum++] = new WiFiAccessPoint(ap);

	} else{
		// scan done

		rtw_up_sema(&scan_sema);
	}
	return RTW_SUCCESS;
}

nsapi_error_t RTWInterface::scan(WiFiAccessPoint *res, unsigned count)
{
	// blocked
	if(count == 0){
		ApNum = 0;

		rtw_init_sema(&scan_sema, 0);
		if(wifi_scan_networks(scan_result_handler, NULL) != RTW_SUCCESS){
			printf("wifi scan failed\n\r");
			//return NSAPI_ERROR_DEVICE_ERROR;
			goto error;
		}

		if(rtw_down_timeout_sema( &scan_sema, 15000 ) == RTW_FALSE) {
			printf("wifi scan timeout\r\n");
			//return NSAPI_ERROR_DEVICE_ERROR;
			goto error;
		}
		rtw_free_sema(&scan_sema);
		return ApNum;
	}else if(count > 0 && res != NULL){
		count = count < maxApNum ? count : maxApNum;
		for(int i = 0; i < count; i++){
			memcpy(&res[i], SCANED_AP[i], sizeof(WiFiAccessPoint));
			delete[] SCANED_AP[i];
 		}
		return (signed int)count;
	}
    return NSAPI_ERROR_OK;
error:
	rtw_free_sema(&scan_sema);
	return NSAPI_ERROR_DEVICE_ERROR;
}

nsapi_error_t RTWInterface::set_channel(uint8_t channel)
{
	if(wifi_set_channel(channel) == 0)
		return NSAPI_ERROR_OK;
    return NSAPI_ERROR_DEVICE_ERROR;
}

int8_t RTWInterface::get_rssi()
{
    return NSAPI_ERROR_UNSUPPORTED;
}

nsapi_error_t RTWInterface::connect(const char *ssid, const char *pass,
                           nsapi_security_t security, uint8_t channel)
{
    set_credentials(ssid, pass, security);
    return connect();
}

nsapi_error_t RTWInterface::disconnect()
{
	char essid[33];

    if(wifi_is_connected_to_ap() != RTW_SUCCESS)
		return NSAPI_ERROR_NO_CONNECTION;
	printf("Deassociating AP ...\r\n");
	if(wifi_disconnect()<0){
		return NSAPI_ERROR_DEVICE_ERROR;
	}

	while(1){
		if(wext_get_ssid(WLAN0_NAME, (unsigned char *) essid) < 0) {
			printf("WIFI disconnected\n\r");
			break;
		}
	}

    return NSAPI_ERROR_OK;
}

int RTWInterface::is_connected()
{
    // wifi_is_connected_to_ap return 0 on connected
    return !wifi_is_connected_to_ap();
}

const char *RTWInterface::get_mac_address()
{
    return mbed_lwip_get_mac_address();
}

const char *RTWInterface::get_ip_address()
{
    if (mbed_lwip_get_ip_address(_ip_address, sizeof _ip_address)) {
        return _ip_address;
    }
    return 0;
}

const char *RTWInterface::get_netmask()
{
    if (mbed_lwip_get_netmask(_netmask, sizeof _netmask)) {
        return _netmask;
    }
    return 0;
}

const char *RTWInterface::get_gateway()
{
    if (mbed_lwip_get_gateway(_gateway, sizeof _gateway)) {
        return _gateway;
    }
    return 0;
}

NetworkStack *RTWInterface::get_stack()
{
    return nsapi_create_stack(&lwip_stack);
}
<|endoftext|>


<commit_before>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/browser.h"
#include "chrome/browser/download/download_manager.h"
#include "chrome/browser/extensions/extension_error_reporter.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/renderer_host/site_instance.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/notification_details.h"
#include "chrome/common/notification_observer.h"
#include "chrome/common/notification_registrar.h"
#include "chrome/common/notification_service.h"
#include "chrome/common/notification_type.h"
#include "chrome/test/in_process_browser_test.h"
#include "chrome/test/ui_test_utils.h"
#include "net/base/net_util.h"

class RenderViewHostManagerTest : public InProcessBrowserTest {
 public:
  RenderViewHostManagerTest() {
    EnableDOMAutomation();
  }
};

// Test for crbug.com/24447.  Following a cross-site link with rel=noreferrer
// and target=_blank should create a new SiteInstance.
IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest,
                       SwapProcessWithRelNoreferrerAndTargetBlank) {
  // Start two servers with different sites.
  const wchar_t kDocRoot[] = L"chrome/test/data";
  scoped_refptr<HTTPTestServer> http_server =
      HTTPTestServer::CreateServer(kDocRoot, NULL);
  scoped_refptr<HTTPSTestServer> https_server =
      HTTPSTestServer::CreateGoodServer(kDocRoot);

  // Load a page with links that open in a new window.
  ui_test_utils::NavigateToURL(browser(), http_server->TestServerPage(
      "files/click-noreferrer-links.html"));

  // Get the original SiteInstance for later comparison.
  scoped_refptr<SiteInstance> orig_site_instance(
      browser()->GetSelectedTabContents()->GetSiteInstance());
  EXPECT_TRUE(orig_site_instance != NULL);

  // Test clicking a rel=noreferrer + target=blank link.
  bool success = false;
  EXPECT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool(
      browser()->GetSelectedTabContents()->render_view_host(), L"",
      L"window.domAutomationController.send(clickNoRefTargetBlankLink());",
      &success));
  EXPECT_TRUE(success);
  // Wait for the cross-site transition to finish.
  ui_test_utils::WaitForLoadStop(
      &(browser()->GetSelectedTabContents()->controller()));

  // Opens in new tab.
  EXPECT_EQ(2, browser()->tab_count());
  EXPECT_EQ(1, browser()->selected_index());
  EXPECT_EQ(L"Title Of Awesomeness",
      browser()->GetSelectedTabContents()->GetTitle());

  // Should have a new SiteInstance.
  scoped_refptr<SiteInstance> noref_blank_site_instance(
      browser()->GetSelectedTabContents()->GetSiteInstance());
  EXPECT_NE(orig_site_instance, noref_blank_site_instance);
}

// Test for crbug.com/24447.  Following a cross-site link with just
// target=_blank should not create a new SiteInstance.
IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest,
                       DontSwapProcessWithOnlyTargetBlank) {
  // Start two servers with different sites.
  const wchar_t kDocRoot[] = L"chrome/test/data";
  scoped_refptr<HTTPTestServer> http_server =
      HTTPTestServer::CreateServer(kDocRoot, NULL);
  scoped_refptr<HTTPSTestServer> https_server =
      HTTPSTestServer::CreateGoodServer(kDocRoot);

  // Load a page with links that open in a new window.
  ui_test_utils::NavigateToURL(browser(), http_server->TestServerPage(
      "files/click-noreferrer-links.html"));

  // Get the original SiteInstance for later comparison.
  scoped_refptr<SiteInstance> orig_site_instance(
      browser()->GetSelectedTabContents()->GetSiteInstance());
  EXPECT_TRUE(orig_site_instance != NULL);

  // Test clicking a target=blank link.
  bool success = false;
  EXPECT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool(
      browser()->GetSelectedTabContents()->render_view_host(), L"",
      L"window.domAutomationController.send(clickTargetBlankLink());",
      &success));
  EXPECT_TRUE(success);
  // Wait for the cross-site transition to finish.
  ui_test_utils::WaitForLoadStop(
      &(browser()->GetSelectedTabContents()->controller()));

  // Opens in new tab.
  EXPECT_EQ(2, browser()->tab_count());
  EXPECT_EQ(1, browser()->selected_index());
  EXPECT_EQ(L"Title Of Awesomeness",
      browser()->GetSelectedTabContents()->GetTitle());

  // Should have the same SiteInstance.
  scoped_refptr<SiteInstance> blank_site_instance(
      browser()->GetSelectedTabContents()->GetSiteInstance());
  EXPECT_EQ(orig_site_instance, blank_site_instance);
}

// Test for crbug.com/24447.  Following a cross-site link with rel=noreferrer
// and no target=_blank should not create a new SiteInstance.
IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest,
                       DontSwapProcessWithOnlyRelNoreferrer) {
  // Start two servers with different sites.
  const wchar_t kDocRoot[] = L"chrome/test/data";
  scoped_refptr<HTTPTestServer> http_server =
      HTTPTestServer::CreateServer(kDocRoot, NULL);
  scoped_refptr<HTTPSTestServer> https_server =
      HTTPSTestServer::CreateGoodServer(kDocRoot);

  // Load a page with links that open in a new window.
  ui_test_utils::NavigateToURL(browser(), http_server->TestServerPage(
      "files/click-noreferrer-links.html"));

  // Get the original SiteInstance for later comparison.
  scoped_refptr<SiteInstance> orig_site_instance(
      browser()->GetSelectedTabContents()->GetSiteInstance());
  EXPECT_TRUE(orig_site_instance != NULL);

  // Test clicking a rel=noreferrer link.
  bool success = false;
  EXPECT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool(
      browser()->GetSelectedTabContents()->render_view_host(), L"",
      L"window.domAutomationController.send(clickNoRefLink());",
      &success));
  EXPECT_TRUE(success);
  // Wait for the cross-site transition to finish.
  ui_test_utils::WaitForLoadStop(
      &(browser()->GetSelectedTabContents()->controller()));

  // Opens in same tab.
  EXPECT_EQ(1, browser()->tab_count());
  EXPECT_EQ(0, browser()->selected_index());
  EXPECT_EQ(L"Title Of Awesomeness",
      browser()->GetSelectedTabContents()->GetTitle());

  // Should have the same SiteInstance.
  scoped_refptr<SiteInstance> noref_site_instance(
      browser()->GetSelectedTabContents()->GetSiteInstance());
  EXPECT_EQ(orig_site_instance, noref_site_instance);
}

// Test for crbug.com/14505. This tests that chrome:// urls are still functional
// after download of a file while viewing another chrome://.
IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest, ChromeURLAfterDownload) {
  GURL downloads_url("chrome://downloads");
  GURL extensions_url("chrome://extensions");
  FilePath zip_download;
  ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &zip_download));
  zip_download = zip_download.AppendASCII("zip").AppendASCII("test.zip");
  GURL zip_url = net::FilePathToFileURL(zip_download);

  ui_test_utils::NavigateToURL(browser(), downloads_url);
  ui_test_utils::NavigateToURL(browser(), zip_url);
  ui_test_utils::WaitForDownloadCount(
      browser()->profile()->GetDownloadManager(), 1);
  ui_test_utils::NavigateToURL(browser(), extensions_url);

  TabContents *contents = browser()->GetSelectedTabContents();
  ASSERT_TRUE(contents);
  bool domui_responded = false;
  EXPECT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool(
      contents->render_view_host(),
      L"",
      L"window.domAutomationController.send(window.domui_responded_);",
      &domui_responded));
  EXPECT_TRUE(domui_responded);
}

class BrowserClosedObserver : public NotificationObserver {
 public:
  explicit BrowserClosedObserver(Browser* browser) {
    registrar_.Add(this, NotificationType::BROWSER_CLOSED,
        Source<Browser>(browser));
    ui_test_utils::RunMessageLoop();
  }

  // NotificationObserver
  virtual void Observe(NotificationType type,
                       const NotificationSource& source,
                       const NotificationDetails& details) {
    switch (type.value) {
      case NotificationType::BROWSER_CLOSED:
        MessageLoopForUI::current()->Quit();
        break;
    }
  }

 private:
  NotificationRegistrar registrar_;
};

// Test for crbug.com/12745. This tests that if a download is initiated from
// a chrome:// page that has registered and onunload handler, the browser
// will be able to close.
// TODO(rafaelw): The fix for 12745 has now also been reverted. Another fix
// must be found before this can be re-enabled.
IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest,
                       DISABLED_BrowserCloseAfterDownload) {
  GURL downloads_url("chrome://downloads");
  FilePath zip_download;
  ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &zip_download));
  zip_download = zip_download.AppendASCII("zip").AppendASCII("test.zip");
  ASSERT_TRUE(file_util::PathExists(zip_download));
  GURL zip_url = net::FilePathToFileURL(zip_download);

  ui_test_utils::NavigateToURL(browser(), downloads_url);
  TabContents *contents = browser()->GetSelectedTabContents();
  ASSERT_TRUE(contents);
  bool result = false;
  EXPECT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool(
      contents->render_view_host(),
      L"",
      L"window.onunload = function() { var do_nothing = 0; }; "
      L"window.domAutomationController.send(true);",
      &result));
  EXPECT_TRUE(result);
  ui_test_utils::NavigateToURL(browser(), zip_url);

  ui_test_utils::WaitForDownloadCount(
    browser()->profile()->GetDownloadManager(), 1);

  browser()->CloseWindow();
  BrowserClosedObserver wait_for_close(browser());
}
<commit_msg>Disable RenderViewHostManagerTest.ChromeURLAfterDownload because it hangs flakily in Windows.<commit_after>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/browser.h"
#include "chrome/browser/download/download_manager.h"
#include "chrome/browser/extensions/extension_error_reporter.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/renderer_host/site_instance.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/notification_details.h"
#include "chrome/common/notification_observer.h"
#include "chrome/common/notification_registrar.h"
#include "chrome/common/notification_service.h"
#include "chrome/common/notification_type.h"
#include "chrome/test/in_process_browser_test.h"
#include "chrome/test/ui_test_utils.h"
#include "net/base/net_util.h"

class RenderViewHostManagerTest : public InProcessBrowserTest {
 public:
  RenderViewHostManagerTest() {
    EnableDOMAutomation();
  }
};

// Test for crbug.com/24447.  Following a cross-site link with rel=noreferrer
// and target=_blank should create a new SiteInstance.
IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest,
                       SwapProcessWithRelNoreferrerAndTargetBlank) {
  // Start two servers with different sites.
  const wchar_t kDocRoot[] = L"chrome/test/data";
  scoped_refptr<HTTPTestServer> http_server =
      HTTPTestServer::CreateServer(kDocRoot, NULL);
  scoped_refptr<HTTPSTestServer> https_server =
      HTTPSTestServer::CreateGoodServer(kDocRoot);

  // Load a page with links that open in a new window.
  ui_test_utils::NavigateToURL(browser(), http_server->TestServerPage(
      "files/click-noreferrer-links.html"));

  // Get the original SiteInstance for later comparison.
  scoped_refptr<SiteInstance> orig_site_instance(
      browser()->GetSelectedTabContents()->GetSiteInstance());
  EXPECT_TRUE(orig_site_instance != NULL);

  // Test clicking a rel=noreferrer + target=blank link.
  bool success = false;
  EXPECT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool(
      browser()->GetSelectedTabContents()->render_view_host(), L"",
      L"window.domAutomationController.send(clickNoRefTargetBlankLink());",
      &success));
  EXPECT_TRUE(success);
  // Wait for the cross-site transition to finish.
  ui_test_utils::WaitForLoadStop(
      &(browser()->GetSelectedTabContents()->controller()));

  // Opens in new tab.
  EXPECT_EQ(2, browser()->tab_count());
  EXPECT_EQ(1, browser()->selected_index());
  EXPECT_EQ(L"Title Of Awesomeness",
      browser()->GetSelectedTabContents()->GetTitle());

  // Should have a new SiteInstance.
  scoped_refptr<SiteInstance> noref_blank_site_instance(
      browser()->GetSelectedTabContents()->GetSiteInstance());
  EXPECT_NE(orig_site_instance, noref_blank_site_instance);
}

// Test for crbug.com/24447.  Following a cross-site link with just
// target=_blank should not create a new SiteInstance.
IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest,
                       DontSwapProcessWithOnlyTargetBlank) {
  // Start two servers with different sites.
  const wchar_t kDocRoot[] = L"chrome/test/data";
  scoped_refptr<HTTPTestServer> http_server =
      HTTPTestServer::CreateServer(kDocRoot, NULL);
  scoped_refptr<HTTPSTestServer> https_server =
      HTTPSTestServer::CreateGoodServer(kDocRoot);

  // Load a page with links that open in a new window.
  ui_test_utils::NavigateToURL(browser(), http_server->TestServerPage(
      "files/click-noreferrer-links.html"));

  // Get the original SiteInstance for later comparison.
  scoped_refptr<SiteInstance> orig_site_instance(
      browser()->GetSelectedTabContents()->GetSiteInstance());
  EXPECT_TRUE(orig_site_instance != NULL);

  // Test clicking a target=blank link.
  bool success = false;
  EXPECT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool(
      browser()->GetSelectedTabContents()->render_view_host(), L"",
      L"window.domAutomationController.send(clickTargetBlankLink());",
      &success));
  EXPECT_TRUE(success);
  // Wait for the cross-site transition to finish.
  ui_test_utils::WaitForLoadStop(
      &(browser()->GetSelectedTabContents()->controller()));

  // Opens in new tab.
  EXPECT_EQ(2, browser()->tab_count());
  EXPECT_EQ(1, browser()->selected_index());
  EXPECT_EQ(L"Title Of Awesomeness",
      browser()->GetSelectedTabContents()->GetTitle());

  // Should have the same SiteInstance.
  scoped_refptr<SiteInstance> blank_site_instance(
      browser()->GetSelectedTabContents()->GetSiteInstance());
  EXPECT_EQ(orig_site_instance, blank_site_instance);
}

// Test for crbug.com/24447.  Following a cross-site link with rel=noreferrer
// and no target=_blank should not create a new SiteInstance.
IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest,
                       DontSwapProcessWithOnlyRelNoreferrer) {
  // Start two servers with different sites.
  const wchar_t kDocRoot[] = L"chrome/test/data";
  scoped_refptr<HTTPTestServer> http_server =
      HTTPTestServer::CreateServer(kDocRoot, NULL);
  scoped_refptr<HTTPSTestServer> https_server =
      HTTPSTestServer::CreateGoodServer(kDocRoot);

  // Load a page with links that open in a new window.
  ui_test_utils::NavigateToURL(browser(), http_server->TestServerPage(
      "files/click-noreferrer-links.html"));

  // Get the original SiteInstance for later comparison.
  scoped_refptr<SiteInstance> orig_site_instance(
      browser()->GetSelectedTabContents()->GetSiteInstance());
  EXPECT_TRUE(orig_site_instance != NULL);

  // Test clicking a rel=noreferrer link.
  bool success = false;
  EXPECT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool(
      browser()->GetSelectedTabContents()->render_view_host(), L"",
      L"window.domAutomationController.send(clickNoRefLink());",
      &success));
  EXPECT_TRUE(success);
  // Wait for the cross-site transition to finish.
  ui_test_utils::WaitForLoadStop(
      &(browser()->GetSelectedTabContents()->controller()));

  // Opens in same tab.
  EXPECT_EQ(1, browser()->tab_count());
  EXPECT_EQ(0, browser()->selected_index());
  EXPECT_EQ(L"Title Of Awesomeness",
      browser()->GetSelectedTabContents()->GetTitle());

  // Should have the same SiteInstance.
  scoped_refptr<SiteInstance> noref_site_instance(
      browser()->GetSelectedTabContents()->GetSiteInstance());
  EXPECT_EQ(orig_site_instance, noref_site_instance);
}

// Hangs flakily in Win, http://crbug.com/45040.
#if defined(OS_WIN)
#define MAYBE_ChromeURLAfterDownload DISABLED_ChromeURLAfterDownload
#else
#defne MAYBE_ChromeURLAfterDownload ChromeURLAfterDownload
#endif  // defined(OS_WIN)

// Test for crbug.com/14505. This tests that chrome:// urls are still functional
// after download of a file while viewing another chrome://.
IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest,
                       MAYBE_ChromeURLAfterDownload) {
  GURL downloads_url("chrome://downloads");
  GURL extensions_url("chrome://extensions");
  FilePath zip_download;
  ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &zip_download));
  zip_download = zip_download.AppendASCII("zip").AppendASCII("test.zip");
  GURL zip_url = net::FilePathToFileURL(zip_download);

  ui_test_utils::NavigateToURL(browser(), downloads_url);
  ui_test_utils::NavigateToURL(browser(), zip_url);
  ui_test_utils::WaitForDownloadCount(
      browser()->profile()->GetDownloadManager(), 1);
  ui_test_utils::NavigateToURL(browser(), extensions_url);

  TabContents *contents = browser()->GetSelectedTabContents();
  ASSERT_TRUE(contents);
  bool domui_responded = false;
  EXPECT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool(
      contents->render_view_host(),
      L"",
      L"window.domAutomationController.send(window.domui_responded_);",
      &domui_responded));
  EXPECT_TRUE(domui_responded);
}

class BrowserClosedObserver : public NotificationObserver {
 public:
  explicit BrowserClosedObserver(Browser* browser) {
    registrar_.Add(this, NotificationType::BROWSER_CLOSED,
        Source<Browser>(browser));
    ui_test_utils::RunMessageLoop();
  }

  // NotificationObserver
  virtual void Observe(NotificationType type,
                       const NotificationSource& source,
                       const NotificationDetails& details) {
    switch (type.value) {
      case NotificationType::BROWSER_CLOSED:
        MessageLoopForUI::current()->Quit();
        break;
    }
  }

 private:
  NotificationRegistrar registrar_;
};

// Test for crbug.com/12745. This tests that if a download is initiated from
// a chrome:// page that has registered and onunload handler, the browser
// will be able to close.
// TODO(rafaelw): The fix for 12745 has now also been reverted. Another fix
// must be found before this can be re-enabled.
IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest,
                       DISABLED_BrowserCloseAfterDownload) {
  GURL downloads_url("chrome://downloads");
  FilePath zip_download;
  ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &zip_download));
  zip_download = zip_download.AppendASCII("zip").AppendASCII("test.zip");
  ASSERT_TRUE(file_util::PathExists(zip_download));
  GURL zip_url = net::FilePathToFileURL(zip_download);

  ui_test_utils::NavigateToURL(browser(), downloads_url);
  TabContents *contents = browser()->GetSelectedTabContents();
  ASSERT_TRUE(contents);
  bool result = false;
  EXPECT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool(
      contents->render_view_host(),
      L"",
      L"window.onunload = function() { var do_nothing = 0; }; "
      L"window.domAutomationController.send(true);",
      &result));
  EXPECT_TRUE(result);
  ui_test_utils::NavigateToURL(browser(), zip_url);

  ui_test_utils::WaitForDownloadCount(
    browser()->profile()->GetDownloadManager(), 1);

  browser()->CloseWindow();
  BrowserClosedObserver wait_for_close(browser());
}
<|endoftext|>


<commit_before>/* Copyright 2015 The TensorFlow Authors. All Rights Reserved.

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.
==============================================================================*/

// See docs in ../ops/array_ops.cc.

#define EIGEN_USE_THREADS

#if GOOGLE_CUDA || TENSORFLOW_USE_ROCM
#define EIGEN_USE_GPU
#endif  // GOOGLE_CUDA || TENSORFLOW_USE_ROCM

#include "tensorflow/core/kernels/linalg/matrix_set_diag_op.h"

#include "third_party/eigen3/unsupported/Eigen/CXX11/Tensor"
#include "tensorflow/core/framework/op_kernel.h"
#include "tensorflow/core/framework/register_types.h"
#include "tensorflow/core/framework/tensor.h"
#include "tensorflow/core/framework/tensor_shape.h"
#include "tensorflow/core/framework/tensor_types.h"
#include "tensorflow/core/framework/types.h"
#include "tensorflow/core/kernels/linalg/matrix_diag_op.h"
#include "tensorflow/core/lib/core/threadpool.h"
#include "tensorflow/core/platform/logging.h"
#include "tensorflow/core/platform/macros.h"

namespace tensorflow {

typedef Eigen::ThreadPoolDevice CPUDevice;
typedef Eigen::GpuDevice GPUDevice;

template <typename Device, typename T>
class MatrixSetDiagOp : public OpKernel {
 public:
  explicit MatrixSetDiagOp(OpKernelConstruction* context) : OpKernel(context) {
    // MatrixSetDiagV3-specific.
    if (context->HasAttr("align")) {
      functor::ReadAlignment(context, &left_align_superdiagonal_,
                             &left_align_subdiagonal_);
    }
  }

  void Compute(OpKernelContext* context) override {
    const Tensor& input = context->input(0);
    const Tensor& diag = context->input(1);

    // MatrixSetDiag and MatrixSetDiagV2 both use this OpKernel. MatrixSetDiag
    // only has two inputs, so we have to check the number of inputs before
    // reading additional parameters in MatrixSetDiagV2.
    int32_t lower_diag_index = 0;
    int32_t upper_diag_index = 0;

    // MatrixSetDiagV2-specific.
    if (context->num_inputs() > kNumV1Inputs) {
      auto& diag_index = context->input(2);
      OP_REQUIRES(context,
                  TensorShapeUtils::IsScalar(diag_index.shape()) ||
                      TensorShapeUtils::IsVector(diag_index.shape()),
                  errors::InvalidArgument(
                      "diag_index must be a scalar or vector, received shape: ",
                      diag_index.shape().DebugString()));
      lower_diag_index = diag_index.flat<int32>()(0);
      upper_diag_index = lower_diag_index;
      if (TensorShapeUtils::IsVector(diag_index.shape())) {
        auto diag_index_size = diag_index.dim_size(0);
        OP_REQUIRES(
            context, 0 < diag_index_size && diag_index_size <= 2,
            errors::InvalidArgument(
                "diag_index must have only one or two elements, received ",
                diag_index_size, " elements."));
        if (diag_index_size > 1) {
          upper_diag_index = diag_index.flat<int32>()(1);
        }
      }
    }

    const TensorShape& input_shape = input.shape();
    const TensorShape& diag_shape = diag.shape();
    const int input_rank = input_shape.dims();

    // Preliminary validation of sizes.
    OP_REQUIRES(context, TensorShapeUtils::IsMatrixOrHigher(input_shape),
                errors::InvalidArgument(
                    "input must be at least 2-dim, received shape: ",
                    input.shape().DebugString()));
    OP_REQUIRES(context, TensorShapeUtils::IsVectorOrHigher(diag_shape),
                errors::InvalidArgument(
                    "diagonal must be at least 1-dim, received shape: ",
                    diag_shape.DebugString()));

    // Make sure lower_diag_index and upper_diag_index is valid.
    const Eigen::Index num_rows = input_shape.dim_size(input_rank - 2);
    const Eigen::Index num_cols = input_shape.dim_size(input_rank - 1);
    OP_REQUIRES(  // Checks lower_diag_index == 0 for when matrix shape = 0.
        context,
        (-num_rows < lower_diag_index && lower_diag_index < num_cols) ||
            lower_diag_index == 0,
        errors::InvalidArgument(
            "lower_diag_index is out of bound: ", lower_diag_index,
            " It must be between ", -num_rows, " and ", num_cols));
    OP_REQUIRES(context,
                (-num_rows < upper_diag_index && upper_diag_index < num_cols) ||
                    upper_diag_index == 0,
                errors::InvalidArgument(
                    "upper_diag_index is out of bound: ", upper_diag_index,
                    " It must be between ", -num_rows, " and ", num_cols));
    OP_REQUIRES(
        context, lower_diag_index <= upper_diag_index,
        errors::InvalidArgument(
            "lower_diag_index must not be larger than upper_diag_index: ",
            lower_diag_index, " > ", upper_diag_index));

    // Check if diag size is consistent with input.
    const Eigen::Index num_diags = upper_diag_index - lower_diag_index + 1;
    OP_REQUIRES(
        context,
        lower_diag_index == upper_diag_index ||
            (diag_shape.dim_size(input_rank - 2) == num_diags),
        errors::InvalidArgument("The number of diagonals provided in `diag` "
                                "is not consistent with `lower_diag_index` and "
                                "`upper_diag_index`"));

    TensorShape expected_diag_shape = input_shape;
    expected_diag_shape.RemoveLastDims(2);
    if (num_diags > 1) expected_diag_shape.AddDim(num_diags);
    const int32_t max_diag_len =
        std::min(num_rows + std::min(upper_diag_index, 0),
                 num_cols - std::max(lower_diag_index, 0));
    expected_diag_shape.AddDim(max_diag_len);
    OP_REQUIRES(
        context, expected_diag_shape == diag_shape,
        errors::InvalidArgument(
            "Either first dimensions of diagonal don't match input.shape[:-2], "
            "or diagonal.shape[:-1] is not equal to the longests diagonal in "
            "range [lower_diag_index:upper_diag_index].\nInput shape: ",
            input_shape.DebugString(),
            "\nDiagonal shape: ", diag_shape.DebugString(),
            "\nExpected diagonal shape: ", expected_diag_shape.DebugString()));

    if (input.NumElements() == 0) {
      // This is a no-op.
      context->set_output(0, input);
      return;
    }

    auto input_reshaped = input.flat_inner_dims<T, 3>();
    auto diag_reshaped = diag.flat<T>();
    Tensor* output = nullptr;
    OP_REQUIRES_OK(context, context->forward_input_or_allocate_output(
                                {0}, 0, input_shape, &output));
    auto output_reshaped = output->flat_inner_dims<T, 3>();
    functor::MatrixSetDiag<Device, T>::Compute(
        context, context->eigen_device<Device>(), input_reshaped, diag_reshaped,
        output_reshaped, lower_diag_index, upper_diag_index, max_diag_len,
        left_align_superdiagonal_, left_align_subdiagonal_);
  }

 private:
  bool left_align_superdiagonal_ = true;
  bool left_align_subdiagonal_ = true;
  static constexpr int kNumV1Inputs = 2;
  TF_DISALLOW_COPY_AND_ASSIGN(MatrixSetDiagOp);
};

#define REGISTER_MATRIX_SET_DIAG(type)                                      \
  REGISTER_KERNEL_BUILDER(                                                  \
      Name("MatrixSetDiag").Device(DEVICE_CPU).TypeConstraint<type>("T"),   \
      MatrixSetDiagOp<CPUDevice, type>);                                    \
  REGISTER_KERNEL_BUILDER(                                                  \
      Name("MatrixSetDiagV2").Device(DEVICE_CPU).TypeConstraint<type>("T"), \
      MatrixSetDiagOp<CPUDevice, type>);                                    \
  REGISTER_KERNEL_BUILDER(                                                  \
      Name("MatrixSetDiagV3").Device(DEVICE_CPU).TypeConstraint<type>("T"), \
      MatrixSetDiagOp<CPUDevice, type>);

TF_CALL_POD_TYPES(REGISTER_MATRIX_SET_DIAG);
#undef REGISTER_MATRIX_SET_DIAG

// Registration of the deprecated kernel.
// Delete after 10mar2017.
#define REGISTER_BATCH_MATRIX_SET_DIAG(type)                                   \
  REGISTER_KERNEL_BUILDER(                                                     \
      Name("BatchMatrixSetDiag").Device(DEVICE_CPU).TypeConstraint<type>("T"), \
      MatrixSetDiagOp<CPUDevice, type>);
TF_CALL_POD_TYPES(REGISTER_BATCH_MATRIX_SET_DIAG);
#undef REGISTER_BATCH_MATRIX_SET_DIAG

namespace functor {

// Implementation of the functor specialization for CPU.
template <typename T>
struct MatrixSetDiag<CPUDevice, T> {
  static void Compute(OpKernelContext* context, const CPUDevice& device,
                      typename TTypes<T, 3>::ConstTensor& input,
                      typename TTypes<T>::ConstTensor& diag,
                      typename TTypes<T, 3>::Tensor& output,
                      const Eigen::Index lower_diag_index,
                      const Eigen::Index upper_diag_index,
                      const Eigen::Index max_diag_len,
                      const bool left_align_superdiagonal,
                      const bool left_align_subdiagonal) {
    if (input.data() != output.data()) {
      output.device(device) = input;
    }
    const Eigen::Index num_diags = upper_diag_index - lower_diag_index + 1;
    auto compute_shard = [&output, &diag, &upper_diag_index, &max_diag_len,
                          &num_diags, &left_align_superdiagonal,
                          &left_align_subdiagonal](Eigen::Index begin,
                                                   Eigen::Index end) {
      const Eigen::Index num_rows = output.dimension(1);
      const Eigen::Index num_cols = output.dimension(2);
      Eigen::Index diag_base_index = begin * num_diags * max_diag_len;
      for (Eigen::Index batch = begin; batch < end; ++batch) {
        for (Eigen::Index m = 0; m < num_diags; ++m) {
          const Eigen::Index diag_index = upper_diag_index - m;
          int diag_len, content_offset;
          std::tie(diag_len, content_offset) = ComputeDiagLenAndContentOffset(
              diag_index, max_diag_len, num_rows, num_cols,
              left_align_superdiagonal, left_align_subdiagonal);

          // Make two separate cases to save some index calculations.
          if (diag_index >= 0) {
            for (Eigen::Index n = 0; n < diag_len; ++n) {
              output(batch, n, n + diag_index) =
                  diag(diag_base_index + n + content_offset);
            }
          } else {
            for (Eigen::Index n = 0; n < diag_len; ++n) {
              output(batch, n - diag_index, n) =
                  diag(diag_base_index + n + content_offset);
            }
          }
          diag_base_index += max_diag_len;
        }
      }
    };
    auto thread_pool =
        context->device()->tensorflow_cpu_worker_threads()->workers;
    // TODO(penporn): Tune for the best constant in cost_per_batch.
    const Eigen::Index cost_per_batch = 10 * num_diags * max_diag_len;
    thread_pool->ParallelFor(output.dimension(0), cost_per_batch,
                             std::move(compute_shard));
  }
};

}  // namespace functor

#if GOOGLE_CUDA || TENSORFLOW_USE_ROCM

// Forward declarations of the functor specializations for GPU.
namespace functor {
#define DECLARE_GPU_SPEC(T)                                                    \
  template <>                                                                  \
  void MatrixSetDiag<GPUDevice, T>::Compute(                                   \
      OpKernelContext* context, const GPUDevice& device,                       \
      typename TTypes<T, 3>::ConstTensor& input,                               \
      typename TTypes<T>::ConstTensor& diag,                                   \
      typename TTypes<T, 3>::Tensor& output,                                   \
      const Eigen::Index lower_diag_index,                                     \
      const Eigen::Index upper_diag_index, const Eigen::Index max_diag_len,    \
      const bool left_align_superdiagonal, const bool left_align_subdiagonal); \
  extern template struct MatrixSetDiag<GPUDevice, T>;

TF_CALL_GPU_ALL_TYPES(DECLARE_GPU_SPEC);

}  // namespace functor

// Registration of the GPU implementations.
#define REGISTER_MATRIX_SET_DIAG_GPU(type)                                \
  REGISTER_KERNEL_BUILDER(                                                \
      Name("MatrixSetDiag").Device(DEVICE_GPU).TypeConstraint<type>("T"), \
      MatrixSetDiagOp<GPUDevice, type>);                                  \
  REGISTER_KERNEL_BUILDER(Name("MatrixSetDiagV2")                         \
                              .Device(DEVICE_GPU)                         \
                              .TypeConstraint<type>("T")                  \
                              .HostMemory("k"),                           \
                          MatrixSetDiagOp<GPUDevice, type>);              \
  REGISTER_KERNEL_BUILDER(Name("MatrixSetDiagV3")                         \
                              .Device(DEVICE_GPU)                         \
                              .TypeConstraint<type>("T")                  \
                              .HostMemory("k"),                           \
                          MatrixSetDiagOp<GPUDevice, type>);

TF_CALL_GPU_ALL_TYPES(REGISTER_MATRIX_SET_DIAG_GPU);
#undef REGISTER_MATRIX_SET_DIAG_GPU

// Registration of the deprecated kernel.
// Delete after 10mar2017.
#define REGISTER_BATCH_MATRIX_SET_DIAG_GPU(type)                               \
  REGISTER_KERNEL_BUILDER(                                                     \
      Name("BatchMatrixSetDiag").Device(DEVICE_GPU).TypeConstraint<type>("T"), \
      MatrixSetDiagOp<GPUDevice, type>);
TF_CALL_GPU_NUMBER_TYPES(REGISTER_BATCH_MATRIX_SET_DIAG_GPU);
#undef REGISTER_BATCH_MATRIX_SET_DIAG_GPU

#endif  // GOOGLE_CUDA || TENSORFLOW_USE_ROCM

}  // namespace tensorflow
<commit_msg>Add one missing valdiation to `matrix_set_diag_op.cc`<commit_after>/* Copyright 2015 The TensorFlow Authors. All Rights Reserved.

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.
==============================================================================*/

// See docs in ../ops/array_ops.cc.

#define EIGEN_USE_THREADS

#if GOOGLE_CUDA || TENSORFLOW_USE_ROCM
#define EIGEN_USE_GPU
#endif  // GOOGLE_CUDA || TENSORFLOW_USE_ROCM

#include "tensorflow/core/kernels/linalg/matrix_set_diag_op.h"

#include "third_party/eigen3/unsupported/Eigen/CXX11/Tensor"
#include "tensorflow/core/framework/op_kernel.h"
#include "tensorflow/core/framework/register_types.h"
#include "tensorflow/core/framework/tensor.h"
#include "tensorflow/core/framework/tensor_shape.h"
#include "tensorflow/core/framework/tensor_types.h"
#include "tensorflow/core/framework/types.h"
#include "tensorflow/core/kernels/linalg/matrix_diag_op.h"
#include "tensorflow/core/lib/core/threadpool.h"
#include "tensorflow/core/platform/logging.h"
#include "tensorflow/core/platform/macros.h"

namespace tensorflow {

typedef Eigen::ThreadPoolDevice CPUDevice;
typedef Eigen::GpuDevice GPUDevice;

template <typename Device, typename T>
class MatrixSetDiagOp : public OpKernel {
 public:
  explicit MatrixSetDiagOp(OpKernelConstruction* context) : OpKernel(context) {
    // MatrixSetDiagV3-specific.
    if (context->HasAttr("align")) {
      functor::ReadAlignment(context, &left_align_superdiagonal_,
                             &left_align_subdiagonal_);
    }
  }

  void Compute(OpKernelContext* context) override {
    const Tensor& input = context->input(0);
    const Tensor& diag = context->input(1);

    // MatrixSetDiag and MatrixSetDiagV2 both use this OpKernel. MatrixSetDiag
    // only has two inputs, so we have to check the number of inputs before
    // reading additional parameters in MatrixSetDiagV2.
    int32_t lower_diag_index = 0;
    int32_t upper_diag_index = 0;

    // MatrixSetDiagV2-specific.
    if (context->num_inputs() > kNumV1Inputs) {
      auto& diag_index = context->input(2);
      OP_REQUIRES(context,
                  TensorShapeUtils::IsScalar(diag_index.shape()) ||
                      TensorShapeUtils::IsVector(diag_index.shape()),
                  errors::InvalidArgument(
                      "diag_index must be a scalar or vector, received shape: ",
                      diag_index.shape().DebugString()));
      OP_REQUIRES(
          context, diag_index.NumElements() > 0,
          errors::InvalidArgument("diag_index must have at least one element"));
      lower_diag_index = diag_index.flat<int32>()(0);
      upper_diag_index = lower_diag_index;
      if (TensorShapeUtils::IsVector(diag_index.shape())) {
        auto diag_index_size = diag_index.dim_size(0);
        OP_REQUIRES(
            context, 0 < diag_index_size && diag_index_size <= 2,
            errors::InvalidArgument(
                "diag_index must have only one or two elements, received ",
                diag_index_size, " elements."));
        if (diag_index_size > 1) {
          upper_diag_index = diag_index.flat<int32>()(1);
        }
      }
    }

    const TensorShape& input_shape = input.shape();
    const TensorShape& diag_shape = diag.shape();
    const int input_rank = input_shape.dims();

    // Preliminary validation of sizes.
    OP_REQUIRES(context, TensorShapeUtils::IsMatrixOrHigher(input_shape),
                errors::InvalidArgument(
                    "input must be at least 2-dim, received shape: ",
                    input.shape().DebugString()));
    OP_REQUIRES(context, TensorShapeUtils::IsVectorOrHigher(diag_shape),
                errors::InvalidArgument(
                    "diagonal must be at least 1-dim, received shape: ",
                    diag_shape.DebugString()));

    // Make sure lower_diag_index and upper_diag_index is valid.
    const Eigen::Index num_rows = input_shape.dim_size(input_rank - 2);
    const Eigen::Index num_cols = input_shape.dim_size(input_rank - 1);
    OP_REQUIRES(  // Checks lower_diag_index == 0 for when matrix shape = 0.
        context,
        (-num_rows < lower_diag_index && lower_diag_index < num_cols) ||
            lower_diag_index == 0,
        errors::InvalidArgument(
            "lower_diag_index is out of bound: ", lower_diag_index,
            " It must be between ", -num_rows, " and ", num_cols));
    OP_REQUIRES(context,
                (-num_rows < upper_diag_index && upper_diag_index < num_cols) ||
                    upper_diag_index == 0,
                errors::InvalidArgument(
                    "upper_diag_index is out of bound: ", upper_diag_index,
                    " It must be between ", -num_rows, " and ", num_cols));
    OP_REQUIRES(
        context, lower_diag_index <= upper_diag_index,
        errors::InvalidArgument(
            "lower_diag_index must not be larger than upper_diag_index: ",
            lower_diag_index, " > ", upper_diag_index));

    // Check if diag size is consistent with input.
    const Eigen::Index num_diags = upper_diag_index - lower_diag_index + 1;
    OP_REQUIRES(
        context,
        lower_diag_index == upper_diag_index ||
            (diag_shape.dim_size(input_rank - 2) == num_diags),
        errors::InvalidArgument("The number of diagonals provided in `diag` "
                                "is not consistent with `lower_diag_index` and "
                                "`upper_diag_index`"));

    TensorShape expected_diag_shape = input_shape;
    expected_diag_shape.RemoveLastDims(2);
    if (num_diags > 1) expected_diag_shape.AddDim(num_diags);
    const int32_t max_diag_len =
        std::min(num_rows + std::min(upper_diag_index, 0),
                 num_cols - std::max(lower_diag_index, 0));
    expected_diag_shape.AddDim(max_diag_len);
    OP_REQUIRES(
        context, expected_diag_shape == diag_shape,
        errors::InvalidArgument(
            "Either first dimensions of diagonal don't match input.shape[:-2], "
            "or diagonal.shape[:-1] is not equal to the longests diagonal in "
            "range [lower_diag_index:upper_diag_index].\nInput shape: ",
            input_shape.DebugString(),
            "\nDiagonal shape: ", diag_shape.DebugString(),
            "\nExpected diagonal shape: ", expected_diag_shape.DebugString()));

    if (input.NumElements() == 0) {
      // This is a no-op.
      context->set_output(0, input);
      return;
    }

    auto input_reshaped = input.flat_inner_dims<T, 3>();
    auto diag_reshaped = diag.flat<T>();
    Tensor* output = nullptr;
    OP_REQUIRES_OK(context, context->forward_input_or_allocate_output(
                                {0}, 0, input_shape, &output));
    auto output_reshaped = output->flat_inner_dims<T, 3>();
    functor::MatrixSetDiag<Device, T>::Compute(
        context, context->eigen_device<Device>(), input_reshaped, diag_reshaped,
        output_reshaped, lower_diag_index, upper_diag_index, max_diag_len,
        left_align_superdiagonal_, left_align_subdiagonal_);
  }

 private:
  bool left_align_superdiagonal_ = true;
  bool left_align_subdiagonal_ = true;
  static constexpr int kNumV1Inputs = 2;
  TF_DISALLOW_COPY_AND_ASSIGN(MatrixSetDiagOp);
};

#define REGISTER_MATRIX_SET_DIAG(type)                                      \
  REGISTER_KERNEL_BUILDER(                                                  \
      Name("MatrixSetDiag").Device(DEVICE_CPU).TypeConstraint<type>("T"),   \
      MatrixSetDiagOp<CPUDevice, type>);                                    \
  REGISTER_KERNEL_BUILDER(                                                  \
      Name("MatrixSetDiagV2").Device(DEVICE_CPU).TypeConstraint<type>("T"), \
      MatrixSetDiagOp<CPUDevice, type>);                                    \
  REGISTER_KERNEL_BUILDER(                                                  \
      Name("MatrixSetDiagV3").Device(DEVICE_CPU).TypeConstraint<type>("T"), \
      MatrixSetDiagOp<CPUDevice, type>);

TF_CALL_POD_TYPES(REGISTER_MATRIX_SET_DIAG);
#undef REGISTER_MATRIX_SET_DIAG

// Registration of the deprecated kernel.
// Delete after 10mar2017.
#define REGISTER_BATCH_MATRIX_SET_DIAG(type)                                   \
  REGISTER_KERNEL_BUILDER(                                                     \
      Name("BatchMatrixSetDiag").Device(DEVICE_CPU).TypeConstraint<type>("T"), \
      MatrixSetDiagOp<CPUDevice, type>);
TF_CALL_POD_TYPES(REGISTER_BATCH_MATRIX_SET_DIAG);
#undef REGISTER_BATCH_MATRIX_SET_DIAG

namespace functor {

// Implementation of the functor specialization for CPU.
template <typename T>
struct MatrixSetDiag<CPUDevice, T> {
  static void Compute(OpKernelContext* context, const CPUDevice& device,
                      typename TTypes<T, 3>::ConstTensor& input,
                      typename TTypes<T>::ConstTensor& diag,
                      typename TTypes<T, 3>::Tensor& output,
                      const Eigen::Index lower_diag_index,
                      const Eigen::Index upper_diag_index,
                      const Eigen::Index max_diag_len,
                      const bool left_align_superdiagonal,
                      const bool left_align_subdiagonal) {
    if (input.data() != output.data()) {
      output.device(device) = input;
    }
    const Eigen::Index num_diags = upper_diag_index - lower_diag_index + 1;
    auto compute_shard = [&output, &diag, &upper_diag_index, &max_diag_len,
                          &num_diags, &left_align_superdiagonal,
                          &left_align_subdiagonal](Eigen::Index begin,
                                                   Eigen::Index end) {
      const Eigen::Index num_rows = output.dimension(1);
      const Eigen::Index num_cols = output.dimension(2);
      Eigen::Index diag_base_index = begin * num_diags * max_diag_len;
      for (Eigen::Index batch = begin; batch < end; ++batch) {
        for (Eigen::Index m = 0; m < num_diags; ++m) {
          const Eigen::Index diag_index = upper_diag_index - m;
          int diag_len, content_offset;
          std::tie(diag_len, content_offset) = ComputeDiagLenAndContentOffset(
              diag_index, max_diag_len, num_rows, num_cols,
              left_align_superdiagonal, left_align_subdiagonal);

          // Make two separate cases to save some index calculations.
          if (diag_index >= 0) {
            for (Eigen::Index n = 0; n < diag_len; ++n) {
              output(batch, n, n + diag_index) =
                  diag(diag_base_index + n + content_offset);
            }
          } else {
            for (Eigen::Index n = 0; n < diag_len; ++n) {
              output(batch, n - diag_index, n) =
                  diag(diag_base_index + n + content_offset);
            }
          }
          diag_base_index += max_diag_len;
        }
      }
    };
    auto thread_pool =
        context->device()->tensorflow_cpu_worker_threads()->workers;
    // TODO(penporn): Tune for the best constant in cost_per_batch.
    const Eigen::Index cost_per_batch = 10 * num_diags * max_diag_len;
    thread_pool->ParallelFor(output.dimension(0), cost_per_batch,
                             std::move(compute_shard));
  }
};

}  // namespace functor

#if GOOGLE_CUDA || TENSORFLOW_USE_ROCM

// Forward declarations of the functor specializations for GPU.
namespace functor {
#define DECLARE_GPU_SPEC(T)                                                    \
  template <>                                                                  \
  void MatrixSetDiag<GPUDevice, T>::Compute(                                   \
      OpKernelContext* context, const GPUDevice& device,                       \
      typename TTypes<T, 3>::ConstTensor& input,                               \
      typename TTypes<T>::ConstTensor& diag,                                   \
      typename TTypes<T, 3>::Tensor& output,                                   \
      const Eigen::Index lower_diag_index,                                     \
      const Eigen::Index upper_diag_index, const Eigen::Index max_diag_len,    \
      const bool left_align_superdiagonal, const bool left_align_subdiagonal); \
  extern template struct MatrixSetDiag<GPUDevice, T>;

TF_CALL_GPU_ALL_TYPES(DECLARE_GPU_SPEC);

}  // namespace functor

// Registration of the GPU implementations.
#define REGISTER_MATRIX_SET_DIAG_GPU(type)                                \
  REGISTER_KERNEL_BUILDER(                                                \
      Name("MatrixSetDiag").Device(DEVICE_GPU).TypeConstraint<type>("T"), \
      MatrixSetDiagOp<GPUDevice, type>);                                  \
  REGISTER_KERNEL_BUILDER(Name("MatrixSetDiagV2")                         \
                              .Device(DEVICE_GPU)                         \
                              .TypeConstraint<type>("T")                  \
                              .HostMemory("k"),                           \
                          MatrixSetDiagOp<GPUDevice, type>);              \
  REGISTER_KERNEL_BUILDER(Name("MatrixSetDiagV3")                         \
                              .Device(DEVICE_GPU)                         \
                              .TypeConstraint<type>("T")                  \
                              .HostMemory("k"),                           \
                          MatrixSetDiagOp<GPUDevice, type>);

TF_CALL_GPU_ALL_TYPES(REGISTER_MATRIX_SET_DIAG_GPU);
#undef REGISTER_MATRIX_SET_DIAG_GPU

// Registration of the deprecated kernel.
// Delete after 10mar2017.
#define REGISTER_BATCH_MATRIX_SET_DIAG_GPU(type)                               \
  REGISTER_KERNEL_BUILDER(                                                     \
      Name("BatchMatrixSetDiag").Device(DEVICE_GPU).TypeConstraint<type>("T"), \
      MatrixSetDiagOp<GPUDevice, type>);
TF_CALL_GPU_NUMBER_TYPES(REGISTER_BATCH_MATRIX_SET_DIAG_GPU);
#undef REGISTER_BATCH_MATRIX_SET_DIAG_GPU

#endif  // GOOGLE_CUDA || TENSORFLOW_USE_ROCM

}  // namespace tensorflow
<|endoftext|>