<commit_before>namespace YaHTTP {
  /*! Implements a single cookie */
  class Cookie {
  public:
     Cookie() {
       secure = false;
       httponly = false;
       name = value = "";
       expires = DateTime();
     }; //!< Set the cookie to empty value

     Cookie(const Cookie &rhs) {
       name = rhs.name;
       value = rhs.value;
       domain = rhs.domain;
       path = rhs.path;
       secure = rhs.secure;
       httponly = rhs.httponly;
       expires = rhs.expires;
     }; //<! Copy cookie values

     Cookie& operator=(const Cookie &rhs) {
       name = rhs.name;
       value = rhs.value;
       domain = rhs.domain;
       path = rhs.path;
       secure = rhs.secure;
       httponly = rhs.httponly;
       expires = rhs.expires;
       return *this;
     }

     DateTime expires; /*!< Expiration date */
     std::string domain; /*!< Domain where cookie is valid */
     std::string path; /*!< Path where the cookie is valid */
     bool httponly; /*!< Whether the cookie is for server use only */
     bool secure; /*!< Whether the cookie is for HTTPS only */

     std::string name; /*!< Cookie name */
     std::string value; /*!< Cookie value */

     std::string str() const {
       std::ostringstream oss;
       oss << YaHTTP::Utility::encodeURL(name) << "=" << YaHTTP::Utility::encodeURL(value);

       if (expires.isSet)
         oss << "; expires=" << expires.cookie_str();
       if (domain.size()>0)
         oss << "; domain=" << domain;
       if (path.size()>0)
         oss << "; path=" << path;
       if (secure)
         oss << "; secure";
       if (httponly)
         oss << "; httpOnly";
       return oss.str();
     }; //!< Stringify the cookie
  };

  /*! Implements a Cookie jar for storing multiple cookies */
  class CookieJar {
    public:
    std::map<std::string, Cookie, ASCIICINullSafeComparator> cookies;  //<! cookie container

    CookieJar() {}; //<! constructs empty cookie jar
    CookieJar(const CookieJar & rhs) {
      this->cookies = rhs.cookies;
    } //<! copy cookies from another cookie jar

    CookieJar& operator=(const CookieJar& rhs) {
      this->cookies = rhs.cookies;
      return *this;
    }

    void clear() {
      this->cookies.clear();
    }

    void keyValuePair(const std::string &keyvalue, std::string &key, std::string &value) {
      size_t pos;
      pos = keyvalue.find("=");
      if (pos == std::string::npos) throw "Not a Key-Value pair (cookie)";
      key = std::string(keyvalue.begin(), keyvalue.begin()+pos);
      value = std::string(keyvalue.begin()+pos+1, keyvalue.end());
    } //<! key value pair parser

    void parseCookieHeader(const std::string &cookiestr) {
      size_t pos, npos;
      std::list<Cookie> lcookies;
      Cookie c;
      pos = 0;
      while(pos < cookiestr.size()) {
        if ((npos = cookiestr.find("; ", pos)) == std::string::npos)
          npos = cookiestr.size();
        keyValuePair(cookiestr.substr(pos, npos-pos), c.name, c.value);
        c.name = YaHTTP::Utility::decodeURL(c.name);
        c.value = YaHTTP::Utility::decodeURL(c.value);
        lcookies.push_back(c);
        pos = npos+2;
      }
      for(std::list<Cookie>::iterator i = lcookies.begin(); i != lcookies.end(); i++) {
        this->cookies[i->name] = *i;
      }
    }

    void parseSetCookieHeader(const std::string &cookiestr) {
      Cookie c;
      size_t pos,npos;
      std::string k, v;

      if ((pos = cookiestr.find("; ", 0)) == std::string::npos)
        pos = cookiestr.size();
      keyValuePair(cookiestr.substr(0, pos), c.name, c.value);
      c.name = YaHTTP::Utility::decodeURL(c.name);
      c.value = YaHTTP::Utility::decodeURL(c.value);
      if (pos < cookiestr.size()) pos+=2;

      while(pos < cookiestr.size()) {
        if ((npos = cookiestr.find("; ", pos)) == std::string::npos)
          npos = cookiestr.size();
        std::string s = cookiestr.substr(pos, npos-pos);
        if (s.find("=") != std::string::npos)
          keyValuePair(s, k, v);
        else
          k = s;
        if (k == "expires") {
          DateTime dt;
          dt.parseCookie(v);
          c.expires = dt;
        } else if (k == "domain") {
          c.domain = v;
        } else if (k == "path") {
          c.path = v;
        } else if (k == "httpOnly") {
          c.httponly = true;
        } else if (k == "secure") {
          c.secure = true;
        } else {
          // ignore crap
          break;
        }
        pos = npos+2;
      }

      this->cookies[c.name] = c;
    }; //<! Parse multiple cookies from header
  };
};
<commit_msg>cookie: Throw a ParseError exception on a invalid cookie<commit_after>namespace YaHTTP {
  /*! Implements a single cookie */
  class Cookie {
  public:
     Cookie() {
       secure = false;
       httponly = false;
       name = value = "";
       expires = DateTime();
     }; //!< Set the cookie to empty value

     Cookie(const Cookie &rhs) {
       name = rhs.name;
       value = rhs.value;
       domain = rhs.domain;
       path = rhs.path;
       secure = rhs.secure;
       httponly = rhs.httponly;
       expires = rhs.expires;
     }; //<! Copy cookie values

     Cookie& operator=(const Cookie &rhs) {
       name = rhs.name;
       value = rhs.value;
       domain = rhs.domain;
       path = rhs.path;
       secure = rhs.secure;
       httponly = rhs.httponly;
       expires = rhs.expires;
       return *this;
     }

     DateTime expires; /*!< Expiration date */
     std::string domain; /*!< Domain where cookie is valid */
     std::string path; /*!< Path where the cookie is valid */
     bool httponly; /*!< Whether the cookie is for server use only */
     bool secure; /*!< Whether the cookie is for HTTPS only */

     std::string name; /*!< Cookie name */
     std::string value; /*!< Cookie value */

     std::string str() const {
       std::ostringstream oss;
       oss << YaHTTP::Utility::encodeURL(name) << "=" << YaHTTP::Utility::encodeURL(value);

       if (expires.isSet)
         oss << "; expires=" << expires.cookie_str();
       if (domain.size()>0)
         oss << "; domain=" << domain;
       if (path.size()>0)
         oss << "; path=" << path;
       if (secure)
         oss << "; secure";
       if (httponly)
         oss << "; httpOnly";
       return oss.str();
     }; //!< Stringify the cookie
  };

  /*! Implements a Cookie jar for storing multiple cookies */
  class CookieJar {
    public:
    std::map<std::string, Cookie, ASCIICINullSafeComparator> cookies;  //<! cookie container

    CookieJar() {}; //<! constructs empty cookie jar
    CookieJar(const CookieJar & rhs) {
      this->cookies = rhs.cookies;
    } //<! copy cookies from another cookie jar

    CookieJar& operator=(const CookieJar& rhs) {
      this->cookies = rhs.cookies;
      return *this;
    }

    void clear() {
      this->cookies.clear();
    }

    void keyValuePair(const std::string &keyvalue, std::string &key, std::string &value) {
      size_t pos;
      pos = keyvalue.find("=");
      if (pos == std::string::npos) throw ParseError("Not a Key-Value pair (cookie)");
      key = std::string(keyvalue.begin(), keyvalue.begin()+pos);
      value = std::string(keyvalue.begin()+pos+1, keyvalue.end());
    } //<! key value pair parser

    void parseCookieHeader(const std::string &cookiestr) {
      size_t pos, npos;
      std::list<Cookie> lcookies;
      Cookie c;
      pos = 0;
      while(pos < cookiestr.size()) {
        if ((npos = cookiestr.find("; ", pos)) == std::string::npos)
          npos = cookiestr.size();
        keyValuePair(cookiestr.substr(pos, npos-pos), c.name, c.value);
        c.name = YaHTTP::Utility::decodeURL(c.name);
        c.value = YaHTTP::Utility::decodeURL(c.value);
        lcookies.push_back(c);
        pos = npos+2;
      }
      for(std::list<Cookie>::iterator i = lcookies.begin(); i != lcookies.end(); i++) {
        this->cookies[i->name] = *i;
      }
    }

    void parseSetCookieHeader(const std::string &cookiestr) {
      Cookie c;
      size_t pos,npos;
      std::string k, v;

      if ((pos = cookiestr.find("; ", 0)) == std::string::npos)
        pos = cookiestr.size();
      keyValuePair(cookiestr.substr(0, pos), c.name, c.value);
      c.name = YaHTTP::Utility::decodeURL(c.name);
      c.value = YaHTTP::Utility::decodeURL(c.value);
      if (pos < cookiestr.size()) pos+=2;

      while(pos < cookiestr.size()) {
        if ((npos = cookiestr.find("; ", pos)) == std::string::npos)
          npos = cookiestr.size();
        std::string s = cookiestr.substr(pos, npos-pos);
        if (s.find("=") != std::string::npos)
          keyValuePair(s, k, v);
        else
          k = s;
        if (k == "expires") {
          DateTime dt;
          dt.parseCookie(v);
          c.expires = dt;
        } else if (k == "domain") {
          c.domain = v;
        } else if (k == "path") {
          c.path = v;
        } else if (k == "httpOnly") {
          c.httponly = true;
        } else if (k == "secure") {
          c.secure = true;
        } else {
          // ignore crap
          break;
        }
        pos = npos+2;
      }

      this->cookies[c.name] = c;
    }; //<! Parse multiple cookies from header
  };
};
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2011-2013, "Kira"
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 *   list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *   this list of conditions and the following disclaimer in the documentation
 *   and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "precompiled_headers.hpp"

#include "logger_thread.hpp"
#include "logging.hpp"
#include "fjson.hpp"
#include "startup_config.hpp"

#include <time.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <string>

using std::string;

static void sock_nonblock(int socket) {
    int flags = 0;
    flags = fcntl(socket, F_GETFL, 0);
    if (flags != -1)
        fcntl(socket, F_SETFL, flags | O_NONBLOCK);
}

void LogEntry::toJSON() {
    if (!jsonCopy.empty())
        return;
    json_t* root = json_object();
    json_object_set_new_nocheck(root, "message_type", json_string_nocheck(messageType.c_str()));
    json_object_set_new_nocheck(root, "from_character", json_string_nocheck(fromCharacter.c_str()));
    json_object_set_new_nocheck(root, "to_character",
                                toCharacter.length() ? json_string_nocheck(toCharacter.c_str()) : json_null());
    json_object_set_new_nocheck(root, "body",
                                messageBody.length() ? json_string_nocheck(messageBody.c_str()) : json_null());
    json_object_set_new_nocheck(root, "to_character_id",
                                toCharacterID != -1 ? json_integer(toCharacterID) : json_null());
    json_object_set_new_nocheck(root, "to_account_id", toAccountID != -1 ? json_integer(toAccountID) : json_null());
    json_object_set_new_nocheck(root, "from_character_id", json_integer(fromCharacterID));
    json_object_set_new_nocheck(root, "from_account_id", json_integer(fromAccountID));
    json_object_set_new_nocheck(root, "channel",
                                toChannel.length() ? json_string_nocheck(toChannel.c_str()) : json_null());
    json_object_set_new_nocheck(root, "channel_title",
                                toChannelTitle.length() ? json_string_nocheck(toChannelTitle.c_str()) : json_null());

    char date_buffer[512];
    int marker = snprintf(date_buffer, sizeof(date_buffer), "%llu", time);
    date_buffer[marker] = 0;
    json_object_set_new_nocheck(root, "date", json_string_nocheck(date_buffer));

    jsonCopy = json_dumps(root, JSON_COMPACT);
    json_decref(root);
    jsonCopy.append("\n");
}

LoggerConnection::LoggerConnection(int fd, struct ev_loop* loop, ChatLogThread* instance) :
        loop(loop),
        writer_io(0),
        fd(fd),
        writeOffset(0),
        logger(instance) {
    writer_io = new ev_io;
    ev_io_init(writer_io, LoggerConnection::writeCallback, fd, EV_WRITE);
    writer_io->data = this;
    logger->addConnection(this);
}

LoggerConnection::~LoggerConnection() {
    ev_io_stop(loop, writer_io);
    delete writer_io;
    close(fd);
    logger->removeConnection(this);
}

void LoggerConnection::sendEntry(LogEntryPtr entry) {
    entryQueue.push(entry);
    ev_io_start(loop, writer_io);
}

void LoggerConnection::writeCallback(struct ev_loop* loop, ev_io* w, int events) {
    auto con = (LoggerConnection*) w->data;

    if (events & EV_ERROR) {
        delete con;
        return;
    }

    if (events & EV_WRITE) {
        while (!con->entryQueue.empty()) {
            LogEntryPtr entry = con->entryQueue.front();
            const char* entryValue = entry->jsonCopy.c_str();
            ssize_t len = entry->jsonCopy.length() - con->writeOffset;
            if(len < 0) {
                LOG(ERROR) << "Invalid write offset during logging write, resulting in negative write length.";
                delete con;
                return;
            }
            ssize_t sent = send(w->fd, entryValue + con->writeOffset, (size_t)len, 0);
            if (sent < 0 && (errno == EAGAIN || errno == EWOULDBLOCK)) {
                return;
            } else if (sent <= 0) {
                // Send failure
                delete con;
                return;
            } else if (sent != len) {
                // Partial send
                con->writeOffset += sent;
                return;
            } else {
                // Complete send
                con->entryQueue.pop();
                con->writeOffset = 0;
            }
        }
        ev_io_stop(loop, w);
    }
}

void ChatLogThread::addConnection(LoggerConnection* connection) {
    connectionList.push_back(connection);
}

void ChatLogThread::removeConnection(LoggerConnection* connection) {
    connectionList.remove(connection);
}

void ChatLogThread::startThread() {
    if(doRun) {
        LOG(WARNING) << "Attempting to start another logging instance while one already exists.";
        return;
    }
    doRun = true;
    pthread_attr_t loggingAttr;
    pthread_attr_init(&loggingAttr);
    pthread_attr_setdetachstate(&loggingAttr, PTHREAD_CREATE_JOINABLE);
    pthread_create(&logThread, &loggingAttr, &ChatLogThread::runThread, this);
}

void* ChatLogThread::runThread(void* params) {
    auto instance = (ChatLogThread*) params;
    instance->runner();
    pthread_exit(NULL);
}

void ChatLogThread::stopThread() {
    DLOG(INFO) << "Stopping logging thread.";
    doRun = false;
    list<LoggerConnection*> list_copy;

    for (auto &it : connectionList) {
        list_copy.push_back(it);
    }
    for (auto &it : list_copy) {
        delete it;
    }
    connectionList.clear();
    ev_async_send(logger_loop, logger_async);
    pthread_join(logThread, 0);
}

void ChatLogThread::runner() {
    DLOG(INFO) << "Starting chat log thread.";

    int listen_socket = createSocket();
    if (!listen_socket) {
        LOG(ERROR) << "Failed to create logging socket.";
        doRun = false;
        pthread_exit(NULL);
    }

    logger_loop = ev_loop_new(EVFLAG_AUTO);

    logger_async = new ev_async;
    ev_async_init(logger_async, ChatLogThread::processQueue);
    logger_async->data = this;
    ev_async_start(logger_loop, logger_async);

    logger_accept_io = new ev_io;
    ev_io_init(logger_accept_io, ChatLogThread::acceptCallback, listen_socket, EV_READ);
    logger_accept_io->data = this;
    ev_io_start(logger_loop, logger_accept_io);
    ev_loop(logger_loop, 0);

    ev_io_stop(logger_loop, logger_accept_io);
    delete logger_accept_io;
    logger_accept_io = 0;

    ev_async_stop(logger_loop, logger_async);
    delete logger_async;
    logger_async = 0;

    close(listen_socket);

    ev_loop_destroy(logger_loop);
    logger_loop = 0;
    DLOG(INFO) << "Exiting chat log thread.";
}

void ChatLogThread::acceptCallback(struct ev_loop* loop, ev_io* w, int events) {
    if (!(events & EV_READ))
        return;

    ChatLogThread* instance = (ChatLogThread*) w->data;
    LOG(INFO) << "Accepting connection for logging thread.";
    struct sockaddr_un remote_addr{};
    int socklen = sizeof(remote_addr);
    int newfd = accept(w->fd, (sockaddr*) &remote_addr, (socklen_t*) &socklen);
    if (newfd < 0)
        return;

    sock_nonblock(newfd);
    new LoggerConnection(newfd, loop, instance);
}

int ChatLogThread::createSocket() {
    string path = StartupConfig::getString("log_socket_path");
    struct sockaddr_un address{};
    address.sun_family = AF_UNIX;
    strncpy(address.sun_path, path.c_str(), path.length());
    address.sun_path[path.length()] = 0;

    int listen_socket = socket(AF_UNIX, SOCK_STREAM, 0);
    sock_nonblock(listen_socket);
    unlink(path.c_str());
    int ret = bind(listen_socket, (sockaddr*) (&address), sizeof(address));
    if (ret < 0) {
        LOG(WARNING) << "Failed to bind to logging socket. Errno: " << errno << " Path: " << path;
        close(listen_socket);
        return 0;
    }
    ret = listen(listen_socket, 128);
    if (ret < 0)
        LOG(WARNING) << "Failed to listen on logging socket.";

    return listen_socket;
}

void ChatLogThread::processEntry(LogEntry* entry) {
    // Ownership of the log entry is taken here. Automatic reference counting will clean it up after this point.
    LogEntryPtr log_entry(entry);
    entry->toJSON();
    for (auto con : connectionList) {
        con->sendEntry(log_entry);
    }
}

void ChatLogThread::processQueue(struct ev_loop* loop, ev_async* w, int revents) {
    DLOG(INFO) << "Process Queue";
    ChatLogThread* instance = (ChatLogThread*)w->data;
    if (!instance->doRun) {
        DLOG(INFO) << "Unlooping from process queue";
        ev_unloop(loop, EVUNLOOP_ONE);
        return;
    }

    LogEntry* entry = instance->getQueueEntry();
    while (entry) {
        instance->processEntry(entry);
        entry = instance->getQueueEntry();
    }
}

LogEntry* ChatLogThread::getQueueEntry() {
    LogEntry* ret = nullptr;
    MUT_LOCK(requestMutex);
    if (!requestQueue.empty()) {
        ret = requestQueue.front();
        requestQueue.pop();
    }
    MUT_UNLOCK(requestMutex);
    return ret;
}

bool ChatLogThread::addLogEntry(LogEntry* newEntry) {
    if (!doRun)
        return false;
    DLOG(INFO) << "Adding log entry;";
    struct timespec abs_time{};
    clock_gettime(CLOCK_REALTIME, &abs_time);
    abs_time.tv_nsec += LOGGER_MUTEX_TIMEOUT;
    if (MUT_TIMEDLOCK(requestMutex, abs_time)) {
        DLOG(INFO) << "Failed to get lock to add queue entry.";
        return false;
    }
    if (requestQueue.size() >= MAX_PENDING_LOG_ENTRIES) {
        MUT_UNLOCK(requestMutex);
        DLOG(WARNING) << "Dropping log message because queue overflowed.";
        return false;
    }
    requestQueue.push(newEntry);
    MUT_UNLOCK(requestMutex);
    return true;
}

void ChatLogThread::sendWakeup() {
    if (doRun && logger_loop && logger_async)
        ev_async_send(logger_loop, logger_async);
}

<commit_msg>Fix for memory leak when converting to JSON.<commit_after>/*
 * Copyright (c) 2011-2013, "Kira"
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 *   list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *   this list of conditions and the following disclaimer in the documentation
 *   and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "precompiled_headers.hpp"

#include "logger_thread.hpp"
#include "logging.hpp"
#include "fjson.hpp"
#include "startup_config.hpp"

#include <time.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <string>

using std::string;

static void sock_nonblock(int socket) {
    int flags = 0;
    flags = fcntl(socket, F_GETFL, 0);
    if (flags != -1)
        fcntl(socket, F_SETFL, flags | O_NONBLOCK);
}

void LogEntry::toJSON() {
    if (!jsonCopy.empty())
        return;
    json_t* root = json_object();
    json_object_set_new_nocheck(root, "message_type", json_string_nocheck(messageType.c_str()));
    json_object_set_new_nocheck(root, "from_character", json_string_nocheck(fromCharacter.c_str()));
    json_object_set_new_nocheck(root, "to_character",
                                toCharacter.length() ? json_string_nocheck(toCharacter.c_str()) : json_null());
    json_object_set_new_nocheck(root, "body",
                                messageBody.length() ? json_string_nocheck(messageBody.c_str()) : json_null());
    json_object_set_new_nocheck(root, "to_character_id",
                                toCharacterID != -1 ? json_integer(toCharacterID) : json_null());
    json_object_set_new_nocheck(root, "to_account_id", toAccountID != -1 ? json_integer(toAccountID) : json_null());
    json_object_set_new_nocheck(root, "from_character_id", json_integer(fromCharacterID));
    json_object_set_new_nocheck(root, "from_account_id", json_integer(fromAccountID));
    json_object_set_new_nocheck(root, "channel",
                                toChannel.length() ? json_string_nocheck(toChannel.c_str()) : json_null());
    json_object_set_new_nocheck(root, "channel_title",
                                toChannelTitle.length() ? json_string_nocheck(toChannelTitle.c_str()) : json_null());

    char date_buffer[512];
    int marker = snprintf(date_buffer, sizeof(date_buffer), "%llu", time);
    date_buffer[marker] = 0;
    json_object_set_new_nocheck(root, "date", json_string_nocheck(date_buffer));

    const char* jsonString = json_dumps(root, JSON_COMPACT);
    jsonCopy = jsonString;
    json_decref(root);
    free((void*)jsonString);
    jsonCopy.append("\n");
}

LoggerConnection::LoggerConnection(int fd, struct ev_loop* loop, ChatLogThread* instance) :
        loop(loop),
        writer_io(0),
        fd(fd),
        writeOffset(0),
        logger(instance) {
    writer_io = new ev_io;
    ev_io_init(writer_io, LoggerConnection::writeCallback, fd, EV_WRITE);
    writer_io->data = this;
    logger->addConnection(this);
}

LoggerConnection::~LoggerConnection() {
    ev_io_stop(loop, writer_io);
    delete writer_io;
    close(fd);
    logger->removeConnection(this);
}

void LoggerConnection::sendEntry(LogEntryPtr entry) {
    entryQueue.push(entry);
    ev_io_start(loop, writer_io);
}

void LoggerConnection::writeCallback(struct ev_loop* loop, ev_io* w, int events) {
    auto con = (LoggerConnection*) w->data;

    if (events & EV_ERROR) {
        delete con;
        return;
    }

    if (events & EV_WRITE) {
        while (!con->entryQueue.empty()) {
            LogEntryPtr entry = con->entryQueue.front();
            const char* entryValue = entry->jsonCopy.c_str();
            ssize_t len = entry->jsonCopy.length() - con->writeOffset;
            if(len < 0) {
                LOG(ERROR) << "Invalid write offset during logging write, resulting in negative write length.";
                delete con;
                return;
            }
            ssize_t sent = send(w->fd, entryValue + con->writeOffset, (size_t)len, 0);
            if (sent < 0 && (errno == EAGAIN || errno == EWOULDBLOCK)) {
                return;
            } else if (sent <= 0) {
                // Send failure
                delete con;
                return;
            } else if (sent != len) {
                // Partial send
                con->writeOffset += sent;
                return;
            } else {
                // Complete send
                con->entryQueue.pop();
                con->writeOffset = 0;
            }
        }
        ev_io_stop(loop, w);
    }
}

void ChatLogThread::addConnection(LoggerConnection* connection) {
    connectionList.push_back(connection);
}

void ChatLogThread::removeConnection(LoggerConnection* connection) {
    connectionList.remove(connection);
}

void ChatLogThread::startThread() {
    if(doRun) {
        LOG(WARNING) << "Attempting to start another logging instance while one already exists.";
        return;
    }
    doRun = true;
    pthread_attr_t loggingAttr;
    pthread_attr_init(&loggingAttr);
    pthread_attr_setdetachstate(&loggingAttr, PTHREAD_CREATE_JOINABLE);
    pthread_create(&logThread, &loggingAttr, &ChatLogThread::runThread, this);
}

void* ChatLogThread::runThread(void* params) {
    auto instance = (ChatLogThread*) params;
    instance->runner();
    pthread_exit(NULL);
}

void ChatLogThread::stopThread() {
    DLOG(INFO) << "Stopping logging thread.";
    doRun = false;
    list<LoggerConnection*> list_copy;

    for (auto &it : connectionList) {
        list_copy.push_back(it);
    }
    for (auto &it : list_copy) {
        delete it;
    }
    connectionList.clear();
    ev_async_send(logger_loop, logger_async);
    pthread_join(logThread, 0);
}

void ChatLogThread::runner() {
    DLOG(INFO) << "Starting chat log thread.";

    int listen_socket = createSocket();
    if (!listen_socket) {
        LOG(ERROR) << "Failed to create logging socket.";
        doRun = false;
        pthread_exit(NULL);
    }

    logger_loop = ev_loop_new(EVFLAG_AUTO);

    logger_async = new ev_async;
    ev_async_init(logger_async, ChatLogThread::processQueue);
    logger_async->data = this;
    ev_async_start(logger_loop, logger_async);

    logger_accept_io = new ev_io;
    ev_io_init(logger_accept_io, ChatLogThread::acceptCallback, listen_socket, EV_READ);
    logger_accept_io->data = this;
    ev_io_start(logger_loop, logger_accept_io);
    ev_loop(logger_loop, 0);

    ev_io_stop(logger_loop, logger_accept_io);
    delete logger_accept_io;
    logger_accept_io = 0;

    ev_async_stop(logger_loop, logger_async);
    delete logger_async;
    logger_async = 0;

    close(listen_socket);

    ev_loop_destroy(logger_loop);
    logger_loop = 0;
    DLOG(INFO) << "Exiting chat log thread.";
}

void ChatLogThread::acceptCallback(struct ev_loop* loop, ev_io* w, int events) {
    if (!(events & EV_READ))
        return;

    ChatLogThread* instance = (ChatLogThread*) w->data;
    LOG(INFO) << "Accepting connection for logging thread.";
    struct sockaddr_un remote_addr{};
    int socklen = sizeof(remote_addr);
    int newfd = accept(w->fd, (sockaddr*) &remote_addr, (socklen_t*) &socklen);
    if (newfd < 0)
        return;

    sock_nonblock(newfd);
    new LoggerConnection(newfd, loop, instance);
}

int ChatLogThread::createSocket() {
    string path = StartupConfig::getString("log_socket_path");
    struct sockaddr_un address{};
    address.sun_family = AF_UNIX;
    strncpy(address.sun_path, path.c_str(), path.length());
    address.sun_path[path.length()] = 0;

    int listen_socket = socket(AF_UNIX, SOCK_STREAM, 0);
    sock_nonblock(listen_socket);
    unlink(path.c_str());
    int ret = bind(listen_socket, (sockaddr*) (&address), sizeof(address));
    if (ret < 0) {
        LOG(WARNING) << "Failed to bind to logging socket. Errno: " << errno << " Path: " << path;
        close(listen_socket);
        return 0;
    }
    ret = listen(listen_socket, 128);
    if (ret < 0)
        LOG(WARNING) << "Failed to listen on logging socket.";

    return listen_socket;
}

void ChatLogThread::processEntry(LogEntry* entry) {
    // Ownership of the log entry is taken here. Automatic reference counting will clean it up after this point.
    LogEntryPtr log_entry(entry);
    entry->toJSON();
    for (auto con : connectionList) {
        con->sendEntry(log_entry);
    }
}

void ChatLogThread::processQueue(struct ev_loop* loop, ev_async* w, int revents) {
    DLOG(INFO) << "Process Queue";
    ChatLogThread* instance = (ChatLogThread*)w->data;
    if (!instance->doRun) {
        DLOG(INFO) << "Unlooping from process queue";
        ev_unloop(loop, EVUNLOOP_ONE);
        return;
    }

    LogEntry* entry = instance->getQueueEntry();
    while (entry) {
        instance->processEntry(entry);
        entry = instance->getQueueEntry();
    }
}

LogEntry* ChatLogThread::getQueueEntry() {
    LogEntry* ret = nullptr;
    MUT_LOCK(requestMutex);
    if (!requestQueue.empty()) {
        ret = requestQueue.front();
        requestQueue.pop();
    }
    MUT_UNLOCK(requestMutex);
    return ret;
}

bool ChatLogThread::addLogEntry(LogEntry* newEntry) {
    if (!doRun)
        return false;
    DLOG(INFO) << "Adding log entry;";
    struct timespec abs_time{};
    clock_gettime(CLOCK_REALTIME, &abs_time);
    abs_time.tv_nsec += LOGGER_MUTEX_TIMEOUT;
    if (MUT_TIMEDLOCK(requestMutex, abs_time)) {
        DLOG(INFO) << "Failed to get lock to add queue entry.";
        return false;
    }
    if (requestQueue.size() >= MAX_PENDING_LOG_ENTRIES) {
        MUT_UNLOCK(requestMutex);
        DLOG(WARNING) << "Dropping log message because queue overflowed.";
        return false;
    }
    requestQueue.push(newEntry);
    MUT_UNLOCK(requestMutex);
    return true;
}

void ChatLogThread::sendWakeup() {
    if (doRun && logger_loop && logger_async)
        ev_async_send(logger_loop, logger_async);
}

<|endoftext|>


<commit_before>//=======================================================================
// Copyright Baptiste Wicht 2011-2012.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include "ltac/Operator.hpp"

using namespace eddic;
using eddic::ltac::Operator;

bool ltac::erase_result(ltac::Operator op){
   return op == Operator::MOV
       || op == Operator::FMOV
       || op == Operator::XOR
       || op == Operator::OR
       || (op >= Operator::LEA && op <= Operator::CMOVLE);
}

bool ltac::erase_result_complete(ltac::Operator op){
    return op == Operator::MOV || op == Operator::FMOV;
}
<commit_msg>LEA erase completely the result register<commit_after>//=======================================================================
// Copyright Baptiste Wicht 2011-2012.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include "ltac/Operator.hpp"

using namespace eddic;
using eddic::ltac::Operator;

bool ltac::erase_result(ltac::Operator op){
   return op == Operator::MOV
       || op == Operator::FMOV
       || op == Operator::XOR
       || op == Operator::OR
       || (op >= Operator::LEA && op <= Operator::CMOVLE);
}

bool ltac::erase_result_complete(ltac::Operator op){
    return op == Operator::MOV || op == Operator::FMOV || op == Operator::LEA;
}
<|endoftext|>


<commit_before>// Copyright (c) 2011 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/site_instance.h"

#include "content/browser/browsing_instance.h"
#include "content/browser/content_browser_client.h"
#include "content/browser/renderer_host/browser_render_process_host.h"
#include "content/browser/webui/web_ui_factory.h"
#include "content/common/content_client.h"
#include "content/common/notification_service.h"
#include "content/public/common/url_constants.h"
#include "net/base/registry_controlled_domain.h"

static bool IsURLSameAsAnySiteInstance(const GURL& url) {
  if (!url.is_valid())
    return false;

  // We treat javascript: as the same site as any URL since it is actually
  // a modifier on existing pages.
  if (url.SchemeIs(chrome::kJavaScriptScheme))
    return true;

  return
      content::GetContentClient()->browser()->IsURLSameAsAnySiteInstance(url);
}

int32 SiteInstance::next_site_instance_id_ = 1;

SiteInstance::SiteInstance(BrowsingInstance* browsing_instance)
    : id_(next_site_instance_id_++),
      browsing_instance_(browsing_instance),
      render_process_host_factory_(NULL),
      process_(NULL),
      max_page_id_(-1),
      has_site_(false) {
  DCHECK(browsing_instance);

  registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_TERMINATED,
                 NotificationService::AllSources());
}

SiteInstance::~SiteInstance() {
  NotificationService::current()->Notify(
      content::NOTIFICATION_SITE_INSTANCE_DELETED,
      Source<SiteInstance>(this),
      NotificationService::NoDetails());

  // Now that no one is referencing us, we can safely remove ourselves from
  // the BrowsingInstance.  Any future visits to a page from this site
  // (within the same BrowsingInstance) can safely create a new SiteInstance.
  if (has_site_)
    browsing_instance_->UnregisterSiteInstance(this);
}

bool SiteInstance::HasProcess() const {
  return (process_ != NULL);
}

RenderProcessHost* SiteInstance::GetProcess() {
  // TODO(erikkay) It would be nice to ensure that the renderer type had been
  // properly set before we get here.  The default tab creation case winds up
  // with no site set at this point, so it will default to TYPE_NORMAL.  This
  // may not be correct, so we'll wind up potentially creating a process that
  // we then throw away, or worse sharing a process with the wrong process type.
  // See crbug.com/43448.

  // Create a new process if ours went away or was reused.
  if (!process_) {
    // See if we should reuse an old process
    if (RenderProcessHost::ShouldTryToUseExistingProcessHost())
      process_ = RenderProcessHost::GetExistingProcessHost(
          browsing_instance_->browser_context(), site_);

    // Otherwise (or if that fails), create a new one.
    if (!process_) {
      if (render_process_host_factory_) {
        process_ = render_process_host_factory_->CreateRenderProcessHost(
            browsing_instance_->browser_context());
      } else {
        process_ =
            new BrowserRenderProcessHost(browsing_instance_->browser_context());
      }
    }

    // Make sure the process starts at the right max_page_id
    process_->UpdateMaxPageID(max_page_id_);
  }
  DCHECK(process_);

  return process_;
}

void SiteInstance::SetSite(const GURL& url) {
  // A SiteInstance's site should not change.
  // TODO(creis): When following links or script navigations, we can currently
  // render pages from other sites in this SiteInstance.  This will eventually
  // be fixed, but until then, we should still not set the site of a
  // SiteInstance more than once.
  DCHECK(!has_site_);

  // Remember that this SiteInstance has been used to load a URL, even if the
  // URL is invalid.
  has_site_ = true;
  site_ = GetSiteForURL(browsing_instance_->browser_context(), url);

  // Now that we have a site, register it with the BrowsingInstance.  This
  // ensures that we won't create another SiteInstance for this site within
  // the same BrowsingInstance, because all same-site pages within a
  // BrowsingInstance can script each other.
  browsing_instance_->RegisterSiteInstance(this);
}

bool SiteInstance::HasRelatedSiteInstance(const GURL& url) {
  return browsing_instance_->HasSiteInstance(url);
}

SiteInstance* SiteInstance::GetRelatedSiteInstance(const GURL& url) {
  return browsing_instance_->GetSiteInstanceForURL(url);
}

bool SiteInstance::HasWrongProcessForURL(const GURL& url) const {
  // Having no process isn't a problem, since we'll assign it correctly.
  if (!HasProcess())
    return false;

  // If the site URL is an extension (e.g., for hosted apps) but the
  // process is not (or vice versa), make sure we notice and fix it.
  GURL site_url = GetSiteForURL(browsing_instance_->browser_context(), url);
  content::ContentBrowserClient* browser =
      content::GetContentClient()->browser();
  return !browser->IsSuitableHost(process_, site_url);
}

/*static*/
SiteInstance* SiteInstance::CreateSiteInstance(
    content::BrowserContext* browser_context) {
  return new SiteInstance(new BrowsingInstance(browser_context));
}

/*static*/
SiteInstance* SiteInstance::CreateSiteInstanceForURL(
    content::BrowserContext* browser_context, const GURL& url) {
  // This BrowsingInstance may be deleted if it returns an existing
  // SiteInstance.
  scoped_refptr<BrowsingInstance> instance(
      new BrowsingInstance(browser_context));
  return instance->GetSiteInstanceForURL(url);
}

/*static*/
GURL SiteInstance::GetSiteForURL(content::BrowserContext* browser_context,
                                 const GURL& real_url) {
  GURL url = GetEffectiveURL(browser_context, real_url);

  // URLs with no host should have an empty site.
  GURL site;

  // TODO(creis): For many protocols, we should just treat the scheme as the
  // site, since there is no host.  e.g., file:, about:, chrome:

  // If the url has a host, then determine the site.
  if (url.has_host()) {
    // Only keep the scheme and registered domain as given by GetOrigin.  This
    // may also include a port, which we need to drop.
    site = url.GetOrigin();

    // Remove port, if any.
    if (site.has_port()) {
      GURL::Replacements rep;
      rep.ClearPort();
      site = site.ReplaceComponents(rep);
    }

    // If this URL has a registered domain, we only want to remember that part.
    std::string domain =
        net::RegistryControlledDomainService::GetDomainAndRegistry(url);
    if (!domain.empty()) {
      GURL::Replacements rep;
      rep.SetHostStr(domain);
      site = site.ReplaceComponents(rep);
    }
  }
  return site;
}

/*static*/
bool SiteInstance::IsSameWebSite(content::BrowserContext* browser_context,
                                 const GURL& real_url1, const GURL& real_url2) {
  GURL url1 = GetEffectiveURL(browser_context, real_url1);
  GURL url2 = GetEffectiveURL(browser_context, real_url2);

  // We infer web site boundaries based on the registered domain name of the
  // top-level page and the scheme.  We do not pay attention to the port if
  // one is present, because pages served from different ports can still
  // access each other if they change their document.domain variable.

  // Some special URLs will match the site instance of any other URL. This is
  // done before checking both of them for validity, since we want these URLs
  // to have the same site instance as even an invalid one.
  if (IsURLSameAsAnySiteInstance(url1) || IsURLSameAsAnySiteInstance(url2))
    return true;

  // If either URL is invalid, they aren't part of the same site.
  if (!url1.is_valid() || !url2.is_valid())
    return false;

  // If the schemes differ, they aren't part of the same site.
  if (url1.scheme() != url2.scheme())
    return false;

  return net::RegistryControlledDomainService::SameDomainOrHost(url1, url2);
}

/*static*/
GURL SiteInstance::GetEffectiveURL(content::BrowserContext* browser_context,
                                   const GURL& url) {
  return content::GetContentClient()->browser()->
      GetEffectiveURL(browser_context, url);
}

void SiteInstance::Observe(int type,
                           const NotificationSource& source,
                           const NotificationDetails& details) {
  DCHECK(type == content::NOTIFICATION_RENDERER_PROCESS_TERMINATED);
  RenderProcessHost* rph = Source<RenderProcessHost>(source).ptr();
  if (rph == process_)
    process_ = NULL;
}
<commit_msg>Change AllSources to AllBrowserContextsAndSources in site_instance.cc, as these usages are safe for multi-profiles.<commit_after>// Copyright (c) 2011 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/site_instance.h"

#include "content/browser/browsing_instance.h"
#include "content/browser/content_browser_client.h"
#include "content/browser/renderer_host/browser_render_process_host.h"
#include "content/browser/webui/web_ui_factory.h"
#include "content/common/content_client.h"
#include "content/common/notification_service.h"
#include "content/public/common/url_constants.h"
#include "net/base/registry_controlled_domain.h"

static bool IsURLSameAsAnySiteInstance(const GURL& url) {
  if (!url.is_valid())
    return false;

  // We treat javascript: as the same site as any URL since it is actually
  // a modifier on existing pages.
  if (url.SchemeIs(chrome::kJavaScriptScheme))
    return true;

  return
      content::GetContentClient()->browser()->IsURLSameAsAnySiteInstance(url);
}

int32 SiteInstance::next_site_instance_id_ = 1;

SiteInstance::SiteInstance(BrowsingInstance* browsing_instance)
    : id_(next_site_instance_id_++),
      browsing_instance_(browsing_instance),
      render_process_host_factory_(NULL),
      process_(NULL),
      max_page_id_(-1),
      has_site_(false) {
  DCHECK(browsing_instance);

  registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_TERMINATED,
                 NotificationService::AllBrowserContextsAndSources());
}

SiteInstance::~SiteInstance() {
  NotificationService::current()->Notify(
      content::NOTIFICATION_SITE_INSTANCE_DELETED,
      Source<SiteInstance>(this),
      NotificationService::NoDetails());

  // Now that no one is referencing us, we can safely remove ourselves from
  // the BrowsingInstance.  Any future visits to a page from this site
  // (within the same BrowsingInstance) can safely create a new SiteInstance.
  if (has_site_)
    browsing_instance_->UnregisterSiteInstance(this);
}

bool SiteInstance::HasProcess() const {
  return (process_ != NULL);
}

RenderProcessHost* SiteInstance::GetProcess() {
  // TODO(erikkay) It would be nice to ensure that the renderer type had been
  // properly set before we get here.  The default tab creation case winds up
  // with no site set at this point, so it will default to TYPE_NORMAL.  This
  // may not be correct, so we'll wind up potentially creating a process that
  // we then throw away, or worse sharing a process with the wrong process type.
  // See crbug.com/43448.

  // Create a new process if ours went away or was reused.
  if (!process_) {
    // See if we should reuse an old process
    if (RenderProcessHost::ShouldTryToUseExistingProcessHost())
      process_ = RenderProcessHost::GetExistingProcessHost(
          browsing_instance_->browser_context(), site_);

    // Otherwise (or if that fails), create a new one.
    if (!process_) {
      if (render_process_host_factory_) {
        process_ = render_process_host_factory_->CreateRenderProcessHost(
            browsing_instance_->browser_context());
      } else {
        process_ =
            new BrowserRenderProcessHost(browsing_instance_->browser_context());
      }
    }

    // Make sure the process starts at the right max_page_id
    process_->UpdateMaxPageID(max_page_id_);
  }
  DCHECK(process_);

  return process_;
}

void SiteInstance::SetSite(const GURL& url) {
  // A SiteInstance's site should not change.
  // TODO(creis): When following links or script navigations, we can currently
  // render pages from other sites in this SiteInstance.  This will eventually
  // be fixed, but until then, we should still not set the site of a
  // SiteInstance more than once.
  DCHECK(!has_site_);

  // Remember that this SiteInstance has been used to load a URL, even if the
  // URL is invalid.
  has_site_ = true;
  site_ = GetSiteForURL(browsing_instance_->browser_context(), url);

  // Now that we have a site, register it with the BrowsingInstance.  This
  // ensures that we won't create another SiteInstance for this site within
  // the same BrowsingInstance, because all same-site pages within a
  // BrowsingInstance can script each other.
  browsing_instance_->RegisterSiteInstance(this);
}

bool SiteInstance::HasRelatedSiteInstance(const GURL& url) {
  return browsing_instance_->HasSiteInstance(url);
}

SiteInstance* SiteInstance::GetRelatedSiteInstance(const GURL& url) {
  return browsing_instance_->GetSiteInstanceForURL(url);
}

bool SiteInstance::HasWrongProcessForURL(const GURL& url) const {
  // Having no process isn't a problem, since we'll assign it correctly.
  if (!HasProcess())
    return false;

  // If the site URL is an extension (e.g., for hosted apps) but the
  // process is not (or vice versa), make sure we notice and fix it.
  GURL site_url = GetSiteForURL(browsing_instance_->browser_context(), url);
  content::ContentBrowserClient* browser =
      content::GetContentClient()->browser();
  return !browser->IsSuitableHost(process_, site_url);
}

/*static*/
SiteInstance* SiteInstance::CreateSiteInstance(
    content::BrowserContext* browser_context) {
  return new SiteInstance(new BrowsingInstance(browser_context));
}

/*static*/
SiteInstance* SiteInstance::CreateSiteInstanceForURL(
    content::BrowserContext* browser_context, const GURL& url) {
  // This BrowsingInstance may be deleted if it returns an existing
  // SiteInstance.
  scoped_refptr<BrowsingInstance> instance(
      new BrowsingInstance(browser_context));
  return instance->GetSiteInstanceForURL(url);
}

/*static*/
GURL SiteInstance::GetSiteForURL(content::BrowserContext* browser_context,
                                 const GURL& real_url) {
  GURL url = GetEffectiveURL(browser_context, real_url);

  // URLs with no host should have an empty site.
  GURL site;

  // TODO(creis): For many protocols, we should just treat the scheme as the
  // site, since there is no host.  e.g., file:, about:, chrome:

  // If the url has a host, then determine the site.
  if (url.has_host()) {
    // Only keep the scheme and registered domain as given by GetOrigin.  This
    // may also include a port, which we need to drop.
    site = url.GetOrigin();

    // Remove port, if any.
    if (site.has_port()) {
      GURL::Replacements rep;
      rep.ClearPort();
      site = site.ReplaceComponents(rep);
    }

    // If this URL has a registered domain, we only want to remember that part.
    std::string domain =
        net::RegistryControlledDomainService::GetDomainAndRegistry(url);
    if (!domain.empty()) {
      GURL::Replacements rep;
      rep.SetHostStr(domain);
      site = site.ReplaceComponents(rep);
    }
  }
  return site;
}

/*static*/
bool SiteInstance::IsSameWebSite(content::BrowserContext* browser_context,
                                 const GURL& real_url1, const GURL& real_url2) {
  GURL url1 = GetEffectiveURL(browser_context, real_url1);
  GURL url2 = GetEffectiveURL(browser_context, real_url2);

  // We infer web site boundaries based on the registered domain name of the
  // top-level page and the scheme.  We do not pay attention to the port if
  // one is present, because pages served from different ports can still
  // access each other if they change their document.domain variable.

  // Some special URLs will match the site instance of any other URL. This is
  // done before checking both of them for validity, since we want these URLs
  // to have the same site instance as even an invalid one.
  if (IsURLSameAsAnySiteInstance(url1) || IsURLSameAsAnySiteInstance(url2))
    return true;

  // If either URL is invalid, they aren't part of the same site.
  if (!url1.is_valid() || !url2.is_valid())
    return false;

  // If the schemes differ, they aren't part of the same site.
  if (url1.scheme() != url2.scheme())
    return false;

  return net::RegistryControlledDomainService::SameDomainOrHost(url1, url2);
}

/*static*/
GURL SiteInstance::GetEffectiveURL(content::BrowserContext* browser_context,
                                   const GURL& url) {
  return content::GetContentClient()->browser()->
      GetEffectiveURL(browser_context, url);
}

void SiteInstance::Observe(int type,
                           const NotificationSource& source,
                           const NotificationDetails& details) {
  DCHECK(type == content::NOTIFICATION_RENDERER_PROCESS_TERMINATED);
  RenderProcessHost* rph = Source<RenderProcessHost>(source).ptr();
  if (rph == process_)
    process_ = NULL;
}
<|endoftext|>


<commit_before>// Copyright (c) 2008 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 "config.h"
#include "ChromiumBridge.h"

#include "ClipboardUtilitiesChromium.h"
#include "Cursor.h"
#include "Frame.h"
#include "FrameView.h"
#include "HostWindow.h"
#include "KURL.h"
#include "NativeImageSkia.h"
#include "Page.h"
#include "PasteboardPrivate.h"
#include "PlatformString.h"
#include "PlatformWidget.h"
#include "PluginData.h"
#include "PluginInfoStore.h"
#include "ScrollbarTheme.h"
#include "ScrollView.h"
#include "Widget.h"

#undef LOG
#include "base/clipboard.h"
#include "base/file_util.h"
#include "base/stats_counters.h"
#include "base/string_util.h"
#include "base/trace_event.h"
#include "net/base/mime_util.h"
#if USE(V8)
#include <v8.h>
#endif
#include "webkit/glue/chrome_client_impl.h"
#include "webkit/glue/glue_util.h"
#include "webkit/glue/scoped_clipboard_writer_glue.h"
#include "webkit/glue/webcursor.h"
#include "webkit/glue/webkit_glue.h"
#include "webkit/glue/webplugin.h"
#include "webkit/glue/webkit_resources.h"
#include "webkit/glue/webview_impl.h"
#include "webkit/glue/webview_delegate.h"

namespace {

PlatformWidget ToPlatform(WebCore::Widget* widget) {
  return widget ? widget->root()->hostWindow()->platformWindow() : 0;
}

ChromeClientImpl* ToChromeClient(WebCore::Widget* widget) {
  WebCore::FrameView* view;
  if (widget->isFrameView()) {
    view = static_cast<WebCore::FrameView*>(widget);
  } else if (widget->parent() && widget->parent()->isFrameView()) {
    view = static_cast<WebCore::FrameView*>(widget->parent());
  } else {
    return NULL;
  }

  WebCore::Page* page = view->frame() ? view->frame()->page() : NULL;
  if (!page)
    return NULL;

  return static_cast<ChromeClientImpl*>(page->chrome()->client());
}

std::wstring UrlToImageMarkup(const WebCore::KURL& url,
                              const WebCore::String& alt_str) {
  std::wstring markup(L"");
  return markup;
}

}  // namespace

namespace WebCore {

bool ChromiumBridge::clipboardIsFormatAvailable(
    PasteboardPrivate::ClipboardFormat format) {
  switch (format) {
    case PasteboardPrivate::HTMLFormat:
      return webkit_glue::ClipboardIsFormatAvailable(
          ::Clipboard::GetHtmlFormatType());

    case PasteboardPrivate::WebSmartPasteFormat:
      return webkit_glue::ClipboardIsFormatAvailable(
          ::Clipboard::GetWebKitSmartPasteFormatType());

    case PasteboardPrivate::BookmarkFormat:
#if defined(OS_WIN) || defined(OS_MACOSX)
      return webkit_glue::ClipboardIsFormatAvailable(
          ::Clipboard::GetUrlWFormatType());
#endif

    default:
      NOTREACHED();
      return false;
  }
}

String ChromiumBridge::clipboardReadPlainText() {
  if (webkit_glue::ClipboardIsFormatAvailable(
      ::Clipboard::GetPlainTextWFormatType())) {
    std::wstring text;
    webkit_glue::ClipboardReadText(&text);
    if (!text.empty())
      return webkit_glue::StdWStringToString(text);
  }

  if (webkit_glue::ClipboardIsFormatAvailable(
      ::Clipboard::GetPlainTextFormatType())) {
    std::string text;
    webkit_glue::ClipboardReadAsciiText(&text);
    if (!text.empty())
      return webkit_glue::StdStringToString(text);
  }

  return String();
}

void ChromiumBridge::clipboardReadHTML(String* html, KURL* url) {
  std::wstring html_stdstr;
  GURL gurl;
  webkit_glue::ClipboardReadHTML(&html_stdstr, &gurl);
  *html = webkit_glue::StdWStringToString(html_stdstr);
  *url = webkit_glue::GURLToKURL(gurl);
}

void ChromiumBridge::clipboardWriteSelection(const String& html,
                                             const KURL& url,
                                             const String& plain_text,
                                             bool can_smart_copy_or_delete) {
  ScopedClipboardWriterGlue scw(webkit_glue::ClipboardGetClipboard());
  scw.WriteHTML(webkit_glue::StringToStdWString(html),
                webkit_glue::CStringToStdString(url.utf8String()));
  scw.WriteText(webkit_glue::StringToStdWString(plain_text));

  if (can_smart_copy_or_delete)
    scw.WriteWebSmartPaste();
}

void ChromiumBridge::clipboardWriteURL(const KURL& url, const String& title) {
  ScopedClipboardWriterGlue scw(webkit_glue::ClipboardGetClipboard());

  GURL gurl = webkit_glue::KURLToGURL(url);
  scw.WriteBookmark(webkit_glue::StringToStdWString(title), gurl.spec());

  std::wstring link(webkit_glue::StringToStdWString(urlToMarkup(url, title)));
  scw.WriteHTML(link, "");

  scw.WriteText(ASCIIToWide(gurl.spec()));
}

void ChromiumBridge::clipboardWriteImage(const NativeImageSkia* bitmap,
    const KURL& url, const String& title) {
  ScopedClipboardWriterGlue scw(webkit_glue::ClipboardGetClipboard());

#if defined(OS_WIN)
  if (bitmap)
    scw.WriteBitmap(*bitmap);
#endif
  if (!url.isEmpty()) {
    GURL gurl = webkit_glue::KURLToGURL(url);
    scw.WriteBookmark(webkit_glue::StringToStdWString(title), gurl.spec());

    scw.WriteHTML(UrlToImageMarkup(url, title), "");

    scw.WriteText(ASCIIToWide(gurl.spec()));
  }
}

//

// Cookies --------------------------------------------------------------------

void ChromiumBridge::setCookies(
    const KURL& url, const KURL& policy_url, const String& cookie) {
  webkit_glue::SetCookie(
      webkit_glue::KURLToGURL(url),
      webkit_glue::KURLToGURL(policy_url),
      webkit_glue::StringToStdString(cookie));
}

String ChromiumBridge::cookies(const KURL& url, const KURL& policy_url) {
  return webkit_glue::StdStringToString(webkit_glue::GetCookies(
      webkit_glue::KURLToGURL(url),
      webkit_glue::KURLToGURL(policy_url)));
}

// DNS ------------------------------------------------------------------------

void ChromiumBridge::prefetchDNS(const String& hostname) {
  webkit_glue::PrefetchDns(webkit_glue::StringToStdString(hostname));
}

// Font -----------------------------------------------------------------------

#if defined(OS_WIN)
bool ChromiumBridge::ensureFontLoaded(HFONT font) {
  return webkit_glue::EnsureFontLoaded(font);
}
#endif

// Forms ----------------------------------------------------------------------

void ChromiumBridge::notifyFormStateChanged(const Document* doc) {
  webkit_glue::NotifyFormStateChanged(doc);
}

// JavaScript -----------------------------------------------------------------

void ChromiumBridge::notifyJSOutOfMemory(Frame* frame) {
  webkit_glue::NotifyJSOutOfMemory(frame);
}

// Language -------------------------------------------------------------------

String ChromiumBridge::computedDefaultLanguage() {
  return webkit_glue::StdWStringToString(webkit_glue::GetWebKitLocale());
}

// LayoutTestMode -------------------------------------------------------------

bool ChromiumBridge::layoutTestMode() {
  return webkit_glue::IsLayoutTestMode();
}

// MimeType -------------------------------------------------------------------

bool ChromiumBridge::matchesMIMEType(const String& pattern,
                                     const String& type) {
  return net::MatchesMimeType(webkit_glue::StringToStdString(pattern),
                              webkit_glue::StringToStdString(type));
}

String ChromiumBridge::mimeTypeForExtension(const String& ext) {
  if (ext.isEmpty())
    return String();

  std::string type;
  webkit_glue::GetMimeTypeFromExtension(webkit_glue::StringToStdWString(ext),
                                        &type);
  return webkit_glue::StdStringToString(type);
}

String ChromiumBridge::mimeTypeFromFile(const String& file_path) {
  if (file_path.isEmpty())
    return String();

  std::string type;
  webkit_glue::GetMimeTypeFromFile(webkit_glue::StringToStdWString(file_path),
                                   &type);
  return webkit_glue::StdStringToString(type);
}

String ChromiumBridge::preferredExtensionForMIMEType(const String& mime_type) {
  if (mime_type.isEmpty())
    return String();

  std::wstring stdext;
  webkit_glue::GetPreferredExtensionForMimeType(
      webkit_glue::StringToStdString(mime_type), &stdext);
  return webkit_glue::StdWStringToString(stdext);
}

// Plugin ---------------------------------------------------------------------

bool ChromiumBridge::getPlugins(bool refresh, Vector<PluginInfo*>* plugins) {
  std::vector< ::WebPluginInfo> glue_plugins;
  if (!webkit_glue::GetPlugins(refresh, &glue_plugins))
    return false;
  for (size_t i = 0; i < glue_plugins.size(); ++i) {
    WebCore::PluginInfo* rv = new WebCore::PluginInfo;
    const ::WebPluginInfo& plugin = glue_plugins[i];
    rv->name = webkit_glue::StdWStringToString(plugin.name);
    rv->desc = webkit_glue::StdWStringToString(plugin.desc);
    rv->file = webkit_glue::StdWStringToString(
        file_util::GetFilenameFromPath(plugin.file));
    for (size_t j = 0; j < plugin.mime_types.size(); ++ j) {
      WebCore::MimeClassInfo* new_mime = new WebCore::MimeClassInfo();
      const WebPluginMimeType& mime_type = plugin.mime_types[j];
      new_mime->desc = webkit_glue::StdWStringToString(mime_type.description);

      for (size_t k = 0; k < mime_type.file_extensions.size(); ++k) {
        if (new_mime->suffixes.length())
          new_mime->suffixes.append(",");

        new_mime->suffixes.append(webkit_glue::StdStringToString(
            mime_type.file_extensions[k]));
      }

      new_mime->type = webkit_glue::StdStringToString(mime_type.mime_type);
      new_mime->plugin = rv;
      rv->mimes.append(new_mime);
    }
    plugins->append(rv);
  }
  return true;
}

// Protocol -------------------------------------------------------------------

String ChromiumBridge::uiResourceProtocol() {
  return webkit_glue::StdStringToString(webkit_glue::GetUIResourceProtocol());
}

// Screen ---------------------------------------------------------------------

int ChromiumBridge::screenDepth(Widget* widget) {
  return webkit_glue::GetScreenInfo(ToPlatform(widget)).depth;
}

int ChromiumBridge::screenDepthPerComponent(Widget* widget) {
  return webkit_glue::GetScreenInfo(ToPlatform(widget)).depth_per_component;
}

bool ChromiumBridge::screenIsMonochrome(Widget* widget) {
  return webkit_glue::GetScreenInfo(ToPlatform(widget)).is_monochrome;
}

IntRect ChromiumBridge::screenRect(Widget* widget) {
  return webkit_glue::ToIntRect(
      webkit_glue::GetScreenInfo(ToPlatform(widget)).rect);
}

IntRect ChromiumBridge::screenAvailableRect(Widget* widget) {
  return webkit_glue::ToIntRect(
      webkit_glue::GetScreenInfo(ToPlatform(widget)).available_rect);
}

// StatsCounters --------------------------------------------------------------
void ChromiumBridge::decrementStatsCounter(const wchar_t* name) {
  StatsCounter(name).Decrement();
}

void ChromiumBridge::incrementStatsCounter(const wchar_t* name) {
  StatsCounter(name).Increment();
}

#if USE(V8)
void ChromiumBridge::initV8CounterFunction() {
  v8::V8::SetCounterFunction(StatsTable::FindLocation);
}
#endif

// Trace Event ----------------------------------------------------------------
void ChromiumBridge::traceEventBegin(const char* name,
                                     void* id,
                                     const char* extra) {
  TRACE_EVENT_BEGIN(name, id, extra);
}

void ChromiumBridge::traceEventEnd(const char* name,
                                   void* id,
                                   const char* extra) {
  TRACE_EVENT_END(name, id, extra);
}

// URL ------------------------------------------------------------------------
KURL ChromiumBridge::inspectorURL() {
  return webkit_glue::GURLToKURL(webkit_glue::GetInspectorURL());
}

// Widget ---------------------------------------------------------------------

void ChromiumBridge::widgetSetCursor(Widget* widget, const Cursor& cursor) {
  ChromeClientImpl* chrome_client = ToChromeClient(widget);
  if (chrome_client)
    chrome_client->SetCursor(WebCursor(cursor.impl()));
}

void ChromiumBridge::widgetSetFocus(Widget* widget) {
  ChromeClientImpl* chrome_client = ToChromeClient(widget);
  if (chrome_client)
    chrome_client->focus();
}

}  // namespace WebCore
<commit_msg>Minor whitespace cleanup.<commit_after>// Copyright (c) 2008 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 "config.h"
#include "ChromiumBridge.h"

#include "ClipboardUtilitiesChromium.h"
#include "Cursor.h"
#include "Frame.h"
#include "FrameView.h"
#include "HostWindow.h"
#include "KURL.h"
#include "NativeImageSkia.h"
#include "Page.h"
#include "PasteboardPrivate.h"
#include "PlatformString.h"
#include "PlatformWidget.h"
#include "PluginData.h"
#include "PluginInfoStore.h"
#include "ScrollbarTheme.h"
#include "ScrollView.h"
#include "Widget.h"

#undef LOG
#include "base/clipboard.h"
#include "base/file_util.h"
#include "base/stats_counters.h"
#include "base/string_util.h"
#include "base/trace_event.h"
#include "net/base/mime_util.h"
#if USE(V8)
#include <v8.h>
#endif
#include "webkit/glue/chrome_client_impl.h"
#include "webkit/glue/glue_util.h"
#include "webkit/glue/scoped_clipboard_writer_glue.h"
#include "webkit/glue/webcursor.h"
#include "webkit/glue/webkit_glue.h"
#include "webkit/glue/webplugin.h"
#include "webkit/glue/webkit_resources.h"
#include "webkit/glue/webview_impl.h"
#include "webkit/glue/webview_delegate.h"

namespace {

PlatformWidget ToPlatform(WebCore::Widget* widget) {
  return widget ? widget->root()->hostWindow()->platformWindow() : 0;
}

ChromeClientImpl* ToChromeClient(WebCore::Widget* widget) {
  WebCore::FrameView* view;
  if (widget->isFrameView()) {
    view = static_cast<WebCore::FrameView*>(widget);
  } else if (widget->parent() && widget->parent()->isFrameView()) {
    view = static_cast<WebCore::FrameView*>(widget->parent());
  } else {
    return NULL;
  }

  WebCore::Page* page = view->frame() ? view->frame()->page() : NULL;
  if (!page)
    return NULL;

  return static_cast<ChromeClientImpl*>(page->chrome()->client());
}

std::wstring UrlToImageMarkup(const WebCore::KURL& url,
                              const WebCore::String& alt_str) {
  std::wstring markup(L"");
  return markup;
}

}  // namespace

namespace WebCore {

bool ChromiumBridge::clipboardIsFormatAvailable(
    PasteboardPrivate::ClipboardFormat format) {
  switch (format) {
    case PasteboardPrivate::HTMLFormat:
      return webkit_glue::ClipboardIsFormatAvailable(
          ::Clipboard::GetHtmlFormatType());

    case PasteboardPrivate::WebSmartPasteFormat:
      return webkit_glue::ClipboardIsFormatAvailable(
          ::Clipboard::GetWebKitSmartPasteFormatType());

    case PasteboardPrivate::BookmarkFormat:
#if defined(OS_WIN) || defined(OS_MACOSX)
      return webkit_glue::ClipboardIsFormatAvailable(
          ::Clipboard::GetUrlWFormatType());
#endif

    default:
      NOTREACHED();
      return false;
  }
}

String ChromiumBridge::clipboardReadPlainText() {
  if (webkit_glue::ClipboardIsFormatAvailable(
      ::Clipboard::GetPlainTextWFormatType())) {
    std::wstring text;
    webkit_glue::ClipboardReadText(&text);
    if (!text.empty())
      return webkit_glue::StdWStringToString(text);
  }

  if (webkit_glue::ClipboardIsFormatAvailable(
      ::Clipboard::GetPlainTextFormatType())) {
    std::string text;
    webkit_glue::ClipboardReadAsciiText(&text);
    if (!text.empty())
      return webkit_glue::StdStringToString(text);
  }

  return String();
}

void ChromiumBridge::clipboardReadHTML(String* html, KURL* url) {
  std::wstring html_stdstr;
  GURL gurl;
  webkit_glue::ClipboardReadHTML(&html_stdstr, &gurl);
  *html = webkit_glue::StdWStringToString(html_stdstr);
  *url = webkit_glue::GURLToKURL(gurl);
}

void ChromiumBridge::clipboardWriteSelection(const String& html,
                                             const KURL& url,
                                             const String& plain_text,
                                             bool can_smart_copy_or_delete) {
  ScopedClipboardWriterGlue scw(webkit_glue::ClipboardGetClipboard());
  scw.WriteHTML(webkit_glue::StringToStdWString(html),
                webkit_glue::CStringToStdString(url.utf8String()));
  scw.WriteText(webkit_glue::StringToStdWString(plain_text));

  if (can_smart_copy_or_delete)
    scw.WriteWebSmartPaste();
}

void ChromiumBridge::clipboardWriteURL(const KURL& url, const String& title) {
  ScopedClipboardWriterGlue scw(webkit_glue::ClipboardGetClipboard());

  GURL gurl = webkit_glue::KURLToGURL(url);
  scw.WriteBookmark(webkit_glue::StringToStdWString(title), gurl.spec());

  std::wstring link(webkit_glue::StringToStdWString(urlToMarkup(url, title)));
  scw.WriteHTML(link, "");

  scw.WriteText(ASCIIToWide(gurl.spec()));
}

void ChromiumBridge::clipboardWriteImage(const NativeImageSkia* bitmap,
    const KURL& url, const String& title) {
  ScopedClipboardWriterGlue scw(webkit_glue::ClipboardGetClipboard());

#if defined(OS_WIN)
  if (bitmap)
    scw.WriteBitmap(*bitmap);
#endif
  if (!url.isEmpty()) {
    GURL gurl = webkit_glue::KURLToGURL(url);
    scw.WriteBookmark(webkit_glue::StringToStdWString(title), gurl.spec());

    scw.WriteHTML(UrlToImageMarkup(url, title), "");

    scw.WriteText(ASCIIToWide(gurl.spec()));
  }
}

// Cookies --------------------------------------------------------------------

void ChromiumBridge::setCookies(
    const KURL& url, const KURL& policy_url, const String& cookie) {
  webkit_glue::SetCookie(
      webkit_glue::KURLToGURL(url),
      webkit_glue::KURLToGURL(policy_url),
      webkit_glue::StringToStdString(cookie));
}

String ChromiumBridge::cookies(const KURL& url, const KURL& policy_url) {
  return webkit_glue::StdStringToString(webkit_glue::GetCookies(
      webkit_glue::KURLToGURL(url),
      webkit_glue::KURLToGURL(policy_url)));
}

// DNS ------------------------------------------------------------------------

void ChromiumBridge::prefetchDNS(const String& hostname) {
  webkit_glue::PrefetchDns(webkit_glue::StringToStdString(hostname));
}

// Font -----------------------------------------------------------------------

#if defined(OS_WIN)
bool ChromiumBridge::ensureFontLoaded(HFONT font) {
  return webkit_glue::EnsureFontLoaded(font);
}
#endif

// Forms ----------------------------------------------------------------------

void ChromiumBridge::notifyFormStateChanged(const Document* doc) {
  webkit_glue::NotifyFormStateChanged(doc);
}

// JavaScript -----------------------------------------------------------------

void ChromiumBridge::notifyJSOutOfMemory(Frame* frame) {
  webkit_glue::NotifyJSOutOfMemory(frame);
}

// Language -------------------------------------------------------------------

String ChromiumBridge::computedDefaultLanguage() {
  return webkit_glue::StdWStringToString(webkit_glue::GetWebKitLocale());
}

// LayoutTestMode -------------------------------------------------------------

bool ChromiumBridge::layoutTestMode() {
  return webkit_glue::IsLayoutTestMode();
}

// MimeType -------------------------------------------------------------------

bool ChromiumBridge::matchesMIMEType(const String& pattern,
                                     const String& type) {
  return net::MatchesMimeType(webkit_glue::StringToStdString(pattern),
                              webkit_glue::StringToStdString(type));
}

String ChromiumBridge::mimeTypeForExtension(const String& ext) {
  if (ext.isEmpty())
    return String();

  std::string type;
  webkit_glue::GetMimeTypeFromExtension(webkit_glue::StringToStdWString(ext),
                                        &type);
  return webkit_glue::StdStringToString(type);
}

String ChromiumBridge::mimeTypeFromFile(const String& file_path) {
  if (file_path.isEmpty())
    return String();

  std::string type;
  webkit_glue::GetMimeTypeFromFile(webkit_glue::StringToStdWString(file_path),
                                   &type);
  return webkit_glue::StdStringToString(type);
}

String ChromiumBridge::preferredExtensionForMIMEType(const String& mime_type) {
  if (mime_type.isEmpty())
    return String();

  std::wstring stdext;
  webkit_glue::GetPreferredExtensionForMimeType(
      webkit_glue::StringToStdString(mime_type), &stdext);
  return webkit_glue::StdWStringToString(stdext);
}

// Plugin ---------------------------------------------------------------------

bool ChromiumBridge::getPlugins(bool refresh, Vector<PluginInfo*>* plugins) {
  std::vector< ::WebPluginInfo> glue_plugins;
  if (!webkit_glue::GetPlugins(refresh, &glue_plugins))
    return false;
  for (size_t i = 0; i < glue_plugins.size(); ++i) {
    WebCore::PluginInfo* rv = new WebCore::PluginInfo;
    const ::WebPluginInfo& plugin = glue_plugins[i];
    rv->name = webkit_glue::StdWStringToString(plugin.name);
    rv->desc = webkit_glue::StdWStringToString(plugin.desc);
    rv->file = webkit_glue::StdWStringToString(
        file_util::GetFilenameFromPath(plugin.file));
    for (size_t j = 0; j < plugin.mime_types.size(); ++ j) {
      WebCore::MimeClassInfo* new_mime = new WebCore::MimeClassInfo();
      const WebPluginMimeType& mime_type = plugin.mime_types[j];
      new_mime->desc = webkit_glue::StdWStringToString(mime_type.description);

      for (size_t k = 0; k < mime_type.file_extensions.size(); ++k) {
        if (new_mime->suffixes.length())
          new_mime->suffixes.append(",");

        new_mime->suffixes.append(webkit_glue::StdStringToString(
            mime_type.file_extensions[k]));
      }

      new_mime->type = webkit_glue::StdStringToString(mime_type.mime_type);
      new_mime->plugin = rv;
      rv->mimes.append(new_mime);
    }
    plugins->append(rv);
  }
  return true;
}

// Protocol -------------------------------------------------------------------

String ChromiumBridge::uiResourceProtocol() {
  return webkit_glue::StdStringToString(webkit_glue::GetUIResourceProtocol());
}

// Screen ---------------------------------------------------------------------

int ChromiumBridge::screenDepth(Widget* widget) {
  return webkit_glue::GetScreenInfo(ToPlatform(widget)).depth;
}

int ChromiumBridge::screenDepthPerComponent(Widget* widget) {
  return webkit_glue::GetScreenInfo(ToPlatform(widget)).depth_per_component;
}

bool ChromiumBridge::screenIsMonochrome(Widget* widget) {
  return webkit_glue::GetScreenInfo(ToPlatform(widget)).is_monochrome;
}

IntRect ChromiumBridge::screenRect(Widget* widget) {
  return webkit_glue::ToIntRect(
      webkit_glue::GetScreenInfo(ToPlatform(widget)).rect);
}

IntRect ChromiumBridge::screenAvailableRect(Widget* widget) {
  return webkit_glue::ToIntRect(
      webkit_glue::GetScreenInfo(ToPlatform(widget)).available_rect);
}

// StatsCounters --------------------------------------------------------------

void ChromiumBridge::decrementStatsCounter(const wchar_t* name) {
  StatsCounter(name).Decrement();
}

void ChromiumBridge::incrementStatsCounter(const wchar_t* name) {
  StatsCounter(name).Increment();
}

#if USE(V8)
void ChromiumBridge::initV8CounterFunction() {
  v8::V8::SetCounterFunction(StatsTable::FindLocation);
}
#endif

// Trace Event ----------------------------------------------------------------

void ChromiumBridge::traceEventBegin(const char* name,
                                     void* id,
                                     const char* extra) {
  TRACE_EVENT_BEGIN(name, id, extra);
}

void ChromiumBridge::traceEventEnd(const char* name,
                                   void* id,
                                   const char* extra) {
  TRACE_EVENT_END(name, id, extra);
}

// URL ------------------------------------------------------------------------

KURL ChromiumBridge::inspectorURL() {
  return webkit_glue::GURLToKURL(webkit_glue::GetInspectorURL());
}

// Widget ---------------------------------------------------------------------

void ChromiumBridge::widgetSetCursor(Widget* widget, const Cursor& cursor) {
  ChromeClientImpl* chrome_client = ToChromeClient(widget);
  if (chrome_client)
    chrome_client->SetCursor(WebCursor(cursor.impl()));
}

void ChromiumBridge::widgetSetFocus(Widget* widget) {
  ChromeClientImpl* chrome_client = ToChromeClient(widget);
  if (chrome_client)
    chrome_client->focus();
}

}  // namespace WebCore
<|endoftext|>


<commit_before>#include "optimizer.h"

TLANG_NAMESPACE_BEGIN

bool Optimizer::search_and_replace(Expr &expr) {
  for (auto &ch : expr->ch) {
    bool ret = search_and_replace(ch);
    if (ret)
      return true;
  }

  if (expr->type == NodeType::load || expr->type == NodeType::store) {
    auto &ptr = expr._pointer();
    auto &addr_node = expr._pointer()._address();
    bool all_same = true;

    for (int i = 0; i < addr_node->lanes; i++) {
      if (addr_node->new_addresses(i) != addr_node->new_addresses(0))
        all_same = false;
    }

    bool incremental = true;

    // only consider the last one.
    auto &index_node = expr._pointer()->ch.back();

    // TODO: check non-last indices are uniform
    if (true || index_node->type == NodeType::index) {
      /*
      int offset_start = index_node->index_offset(0);
      int offset_inc = index_node->index_offset(1) - offset_start;
      for (int i = 0; i + 1 < addr_node->lanes; i++) {
        if (index_node->index_offset(i) + offset_inc !=
            index_node->index_offset(i + 1)) {
          incremental = false;
        }
      }

      bool regular_elements = true;
      for (int i = 0; i < addr_node->lanes; i++) {
        auto p = addr_node->new_addresses(i)->parent;
        if (p != addr_node->new_addresses(0)->parent)
          regular_elements = false;
        if (p->child_id(addr_node->new_addresses(i)) != i)
          regular_elements = false;
      }

      auto snode = addr_node->new_addresses(0);
      // continuous index, same element
      bool vpointer_case_1 =
          incremental && offset_start == 0 && offset_inc == 1 &&
          snode->parent->type == SNodeType::fixed && all_same;
      // continuous element, same index
      bool vpointer_case_2 = regular_elements && incremental && offset_inc == 0;
      bool vpointer = vpointer_case_1 || vpointer_case_2;
      if (regular_elements && incremental) {
        TC_P(all_same);
        TC_P(offset_start);
        TC_P(offset_inc);
        TC_P(vpointer_case_2);
        TC_P(vpointer);
      }
       */

      if (true) {
        // replace load with vload
        if (expr->type == NodeType::load) {
          TC_INFO("Optimized load");
          auto vload = Expr::create(NodeType::vload, addr_node);
          vload->ch.resize(ptr->ch.size());
          for (int i = 1; i < (int)ptr->ch.size(); i++) {
            auto c = Expr::copy_from(ptr->ch[i]);
            TC_ASSERT(c->lanes == 8);
            if (c->type == NodeType::index)
              c->set_lanes(1);
            vload->ch[i] = c;
          }
          vload->set_similar(expr);
          expr = vload;
          return true;
        } else {
          TC_INFO("Optimized store");
          auto vstore = Expr::create(NodeType::vstore, addr_node, expr->ch[1]);
          vstore->ch.resize(ptr->ch.size() + 1);
          for (int i = 1; i < (int)ptr->ch.size(); i++) {
            auto c = Expr::copy_from(ptr->ch[i]);
            TC_ASSERT(c->lanes == 8);
            if (c->type == NodeType::index)
              c->set_lanes(1);
            vstore->ch[i + 1] = c;
          }
          vstore->set_similar(expr);
          expr = vstore;
          return true;
        }
      }
    }
  }

  return false;
}

TLANG_NAMESPACE_END
<commit_msg>restored optimizer hack...will fix it tomorrow<commit_after>#include "optimizer.h"

TLANG_NAMESPACE_BEGIN

bool Optimizer::search_and_replace(Expr &expr) {
  for (auto &ch : expr->ch) {
    bool ret = search_and_replace(ch);
    if (ret)
      return true;
  }

  if (expr->type == NodeType::load || expr->type == NodeType::store) {
    auto &ptr = expr._pointer();
    auto &addr_node = expr._pointer()._address();
    bool all_same = true;

    for (int i = 0; i < addr_node->lanes; i++) {
      if (addr_node->new_addresses(i) != addr_node->new_addresses(0))
        all_same = false;
    }

    bool incremental = true;

    // only consider the last one.
    auto &index_node = expr._pointer()->ch.back();

    // TODO: check non-last indices are uniform
    if (index_node->type == NodeType::index) {
      int offset_start = index_node->index_offset(0);
      int offset_inc = index_node->index_offset(1) - offset_start;
      for (int i = 0; i + 1 < addr_node->lanes; i++) {
        if (index_node->index_offset(i) + offset_inc !=
            index_node->index_offset(i + 1)) {
          incremental = false;
        }
      }

      bool regular_elements = true;
      for (int i = 0; i < addr_node->lanes; i++) {
        auto p = addr_node->new_addresses(i)->parent;
        if (p != addr_node->new_addresses(0)->parent)
          regular_elements = false;
        if (p->child_id(addr_node->new_addresses(i)) != i)
          regular_elements = false;
      }

      auto snode = addr_node->new_addresses(0);
      // continuous index, same element
      bool vpointer_case_1 =
          incremental && offset_start == 0 && offset_inc == 1 &&
          snode->parent->type == SNodeType::fixed && all_same;
      // continuous element, same index
      bool vpointer_case_2 = regular_elements && incremental && offset_inc == 0;
      bool vpointer = vpointer_case_1 || vpointer_case_2;
      if (regular_elements && incremental) {
        TC_P(all_same);
        TC_P(offset_start);
        TC_P(offset_inc);
        TC_P(vpointer_case_2);
        TC_P(vpointer);
      }

      if (vpointer) {
        // replace load with vload
        if (expr->type == NodeType::load) {
          TC_INFO("Optimized load");
          auto vload = Expr::create(NodeType::vload, addr_node);
          vload->ch.resize(ptr->ch.size());
          for (int i = 1; i < (int)ptr->ch.size(); i++) {
            auto c = Expr::copy_from(ptr->ch[i]);
            TC_ASSERT(c->lanes == 8);
            c->set_lanes(1);
            vload->ch[i] = c;
          }
          vload->set_similar(expr);
          expr = vload;
          return true;
        } else {
          TC_INFO("Optimized store");
          auto vstore = Expr::create(NodeType::vstore, addr_node, expr->ch[1]);
          vstore->ch.resize(ptr->ch.size() + 1);
          for (int i = 1; i < (int)ptr->ch.size(); i++) {
            auto c = Expr::copy_from(ptr->ch[i]);
            TC_ASSERT(c->lanes == 8);
            c->set_lanes(1);
            vstore->ch[i + 1] = c;
          }
          vstore->set_similar(expr);
          expr = vstore;
          return true;
        }
      }
    }
  }

  return false;
}

TLANG_NAMESPACE_END
<|endoftext|>