<commit_before>#include "contentmanager.h"

// Model Classes
#include "Earth.h"
#include "Sputnik.h"

/* initialize : Initializes the ContentManager.
 *
 * Models described in the external proplist are loaded into the
 * ContentManagers proplist
 */
bool ContentManager::initialize()
{
    path = "proplist.csv";

    if (!load_prop_list(path)) {
        printf("Failed to read prop list, cannot render scene.\n");
        return false;
    }

    _running = true;
    return true;
} // initialize()

/* shutdown : Shuts down the ContentManager
 *
 * Sets the ContentManager to stop running
 */
void ContentManager::shutdown()
{
    _running = false;
} // shutdown()

/* update : Updates all tracked objects
 *
 * Updates objects in the proplist
 */
void ContentManager::update(float deltaTime)
{
    // TODO: Implement Props updating
} // update(float deltaTime)

/* prop_list_size : Returns the size of prop_list
*
* returns the size of prop_list
*/
int ContentManager::prop_list_size()
{
    return prop_list.size();
} // prop_list_size()

/* get_prop_at : Returns prop at the given index
 *
 * Parameter (int index) - index of prop
 *
 * Gets the prop at the index provided from
 * prop_list
 */
mesh ContentManager::get_prop_at(int index)
{
    mesh result = prop_list.at(index);
    return result;
} // get_prop_at()

/* register_prop : Adds prop to prop_list
 *
 * Register object with scene manager for rendering
 */
void ContentManager::register_prop(mesh mesh)
{
    prop_list.push_back(mesh);
} // register_prop()

/*  unregister_prop : Removes prop from prop_list
 *
 * Unregister object with scene manager
 */
void ContentManager::unregister_prop(mesh mesh)
{
    prop_list.push_back(mesh);
} // unregister_prop()

/* load_prop_list : Loads props from propList.csv
 *
 * DEPRECATED:
 *
 * Parameter string path - Path for external proplist
 *
 * Loads models from external proplist in to the ContentManagers
 * interal proplist
 */
bool ContentManager::load_prop_list(string path)
{
    vector<string> modelPath;
    vector<vec3> modelPosition;
    vector<vec3> modelRotation;
    vector<string> modelVert, modelFrag;

    try {
        unsigned int i;
        csv::Parser file = csv::Parser(path);
        for (i = 0; i < file.rowCount(); ++i) {
            modelPath.push_back(file[i][0]);
            modelPosition.push_back(vec3(stof(file[i][1]), stof(file[i][2]), stof(file[i][3])));
            modelRotation.push_back(vec3(stof(file[i][4]), stof(file[i][5]), stof(file[i][6])));
            modelVert.push_back(file[i][7]);
            modelFrag.push_back(file[i][8]);
        }

        for (i=0; i < modelPath.size(); ++i) {
            if (!load_model(modelPath.at(i), modelPosition.at(i),
                modelRotation.at(i), modelVert.at(i), modelFrag.at(i))) {
                    return false;
            }
        }
    } catch (csv::Error &e) {
        std::cerr << e.what() << std::endl;
        return false;
    }

    return true;
} // load_prop_list()

/* load_props : loads the props for the scene
 *
 * Loads Earth, Sputnik, Moon and Sun for the scene
 */
bool ContentManager::load_props()
{
    Earth earth = Earth();
    Sputnik sputnik = Sputnik();

    // Load Earth
    if (!load_model(&sputnik, sputnik.get_path())) {
        return false;
    }

    // Load Sputnik
    if (!load_model(&sputnik, sputnik.get_path())) {
        return false;
    }

    return false;
} // load_props()

/* load_model : Loads the meshs for a Prop
 *
 * Uses tinyobj to load the models from their .obj file
 * then assigns the values extracted to the objects
 */
bool ContentManager::load_model(Prop* prop, string modelPath)
{
    // Load .OBJ
    std::vector<tinyobj::shape_t> shapes;
    std::string err = tinyobj::LoadObj(shapes, modelPath.c_str());

    // If an error occured stop
    if (!err.empty()) {
        std::cerr << err << std::endl;
        return false;
    }

    // Create mesh
    shared_ptr<mesh> model = make_shared<mesh>();

    unsigned int i;
    for (i=0; i < shapes.size(); ++i) {
        tinyobj::shape_t* shape = &shapes[i];
        load_vertices(shape, model.get());
        load_normals(shape, model.get());
        load_texcoords(shape, model.get());
        load_indices(shape, model.get());

        // Initialise all loaded geometry data
        geometry_builder::initialise_geometry(model->geom);

        // Created effect for mesh
        auto eff = make_shared<effect>();
        eff->add_shader(prop->get_vert_path(), GL_VERTEX_SHADER);
        eff->add_shader(prop->get_vert_path(), GL_FRAGMENT_SHADER);
        // Build effect
        if (!effect_loader::build_effect(eff)) {
            return false;
        }

        // Create material and add effect
        model->mat = make_shared<material>();
        model->mat->effect = eff;

        // Set "eye position" and lighting for shader
        model->mat->set_uniform_value("eye_position", CameraManager::get_instance().currentCamera->get_position());
        model->mat->set_uniform_value("directional_light", SceneManager::get_instance().light);

        auto tex = texture_loader::load(shape->material.diffuse_texname);
        model->mat->set_texture("tex", tex);
        // build material
        if (!model->mat->build()) {
            return false;
        }

        model->trans.position = prop->get_position();
        quat rot(prop->get_rotation());
        model->trans.orientation = model->trans.orientation * rot;

        prop->add_mesh(model.get());
    } // for each in shapes[]

    return true;
} // load_model()

/** load_vertices : Loads vertices from shape
 *
 * Loads all shape positions and produces the vertices for the mesh
 */
void ContentManager::load_vertices(tinyobj::shape_t * shape, mesh * model)
{
    // Check ptrs are not null.
    if (shape != nullptr && model != nullptr) {
        // Check there are enough points to make full vertexes
        assert((shape->mesh.positions.size() % 3) == 0);
        unsigned int i;
        for (i=0; i < shape->mesh.positions.size() / 3 ; ++i) {
            model->geom->positions.push_back(vec3(shape->mesh.positions[3*i+0],
                                                  shape->mesh.positions[3*i+1],
                                                  shape->mesh.positions[3*i+2]));
        }
    }
} // load_vertices()

/** load_normals : Loads vertices from shape
 *
 * Loads all shape normals and add them to the mesh
 */
void ContentManager::load_normals(tinyobj::shape_t * shape, mesh * model)
{
    // Check ptrs are not null.
    if (shape != nullptr && model != nullptr) {
        // Check there are enough points for normals
        assert((shape->mesh.positions.size() % 3) == 0);
        unsigned int i;
        for (i=0; i < shape->mesh.positions.size() / 3 ; ++i) {
            model->geom->normals.push_back(vec3(shape->mesh.normals[3*i+0],
                                                shape->mesh.normals[3*i+1],
                                                shape->mesh.normals[3*i+2]));
        }
    }
} // load_normals()

/** load_texcoords : Loads vertices from shape
 *
 * Loads all shape tex coords and add them to the mesh
 */
void ContentManager::load_texcoords(tinyobj::shape_t * shape, mesh * model)
{
    // Check ptrs are not null.
    if (shape != nullptr && model != nullptr) {
        // Check there are enough points to make tex coords
        assert((shape->mesh.texcoords.size() % 2) == 0);
        unsigned int i;
        for (i = 0; i < shape->mesh.texcoords.size() / 2; ++i) {
            // Invert texture coordinates due to 3d max exporting issues
            model->geom->tex_coords.push_back(vec2(-shape->mesh.texcoords[2*i+0],
                                                   -shape->mesh.texcoords[2*i+1]));
        }
    }
} // load_texcoords()

/** load_indices : Loads vertices from shape
 *
 * Loads all shape indices and add them to the mesh
 */
void ContentManager::load_indices(tinyobj::shape_t * shape, mesh * model)
{
    // Check ptrs are not null.
    if (shape != nullptr && model != nullptr) {
        assert((shape->mesh.indices.size() % 3) == 0);
        model->geom->indices = shape->mesh.indices;
    }
} // load_indices()

/* load_shader_data : Loads shader data
 *
 * Loads shader data from shape and applies it to the effect for model
 */
void load_shader_data(tinyobj::shape_t * shape, mesh * model)
{
    // Set shader values for object
    model->mat->data.emissive            = vec4(shape->material.emission[0],
                                                shape->material.emission[1],
                                                shape->material.emission[2],
                                                // current used .mtl files only store
                                                // one value for Tr (transmittance)
                                                shape->material.transmittance[0]);

    model->mat->data.diffuse_reflection  = vec4(shape->material.diffuse[0],
                                                shape->material.diffuse[1],
                                                shape->material.diffuse[2],
                                                // current used .mtl files only store
                                                // one value for Tr (transmittance)
                                                shape->material.transmittance[0]);

    model->mat->data.specular_reflection = vec4(shape->material.specular[0],
                                                shape->material.specular[1],
                                                shape->material.specular[2],
                                                // current used .mtl files only store
                                                // one value for Tr (transmittance)
                                                shape->material.transmittance[0]);

    model->mat->data.shininess = shape->material.shininess;
} // load_shader_data()

/* load_model : Loads models
*
* DEPRECATED:
*
* Uses tinyobj to load the models from their .obj file
* then assigns the values extracted to the objects
*/
bool ContentManager::load_model(string modelPath, vec3 modelPosition, vec3 modelRotation,
    string modelVert, string modelFrag)
{
    // Create and load .OBJ
    std::vector<tinyobj::shape_t> shapes;
    std::string err = tinyobj::LoadObj(shapes, modelPath.c_str());

    // If an error occured stop
    if (!err.empty()) {
        std::cerr << err << std::endl;
        return false;
    }

    unsigned int i, j;
    for (i=0; i < shapes.size(); ++i) {
        assert((shapes[i].mesh.positions.size() % 3) == 0);
        shared_ptr<mesh> model = make_shared<mesh>();
        model->geom = make_shared<geometry>();

        for (j=0; j < shapes[i].mesh.positions.size() / 3 ; ++j) {
            model->geom->positions.push_back(vec3(shapes[i].mesh.positions[3*j+0],
                shapes[i].mesh.positions[3*j+1],
                shapes[i].mesh.positions[3*j+2]));

            model->geom->normals.push_back(vec3(shapes[i].mesh.normals[3*j+0],
                shapes[i].mesh.normals[3*j+1],
                shapes[i].mesh.normals[3*j+2]));
        }

        assert((shapes[i].mesh.texcoords.size() % 2) == 0);
        for (j=0; j < shapes[i].mesh.texcoords.size() / 2; ++j) {
            // Invert texture coordinates due to 3d max exporting issues
            model->geom->tex_coords.push_back(vec2(-shapes[i].mesh.texcoords[2*j+0],
                -shapes[i].mesh.texcoords[2*j+1]));
        }

        assert((shapes[i].mesh.indices.size() % 3) == 0);
        model->geom->indices = shapes[i].mesh.indices;

        geometry_builder::initialise_geometry(model->geom);

        auto eff = make_shared<effect>();
        eff->add_shader(modelVert, GL_VERTEX_SHADER);
        eff->add_shader(modelFrag, GL_FRAGMENT_SHADER);
        if (!effect_loader::build_effect(eff)) {
            return false;
        }

        model->mat = make_shared<material>();
        model->mat->effect = eff;

        // Set shader values for object
        model->mat->data.emissive = vec4(shapes[i].material.emission[0],
            shapes[i].material.emission[1],
            shapes[i].material.emission[2],
            shapes[i].material.transmittance[i]);

        model->mat->data.diffuse_reflection = vec4(shapes[i].material.diffuse[0],
            shapes[i].material.diffuse[1],
            shapes[i].material.diffuse[2],
            shapes[i].material.transmittance[i]);

        model->mat->data.specular_reflection = vec4(shapes[i].material.specular[0],
            shapes[i].material.specular[1],
            shapes[i].material.specular[2],
            shapes[i].material.transmittance[i]);

        model->mat->data.shininess = shapes[i].material.shininess;
        model->mat->set_uniform_value("eye_position", CameraManager::get_instance().currentCamera->get_position());

        model->mat->set_uniform_value("directional_light", SceneManager::get_instance().light);

        auto tex = texture_loader::load(shapes[i].material.diffuse_texname);
        model->mat->set_texture("tex", tex);

        if (!model->mat->build()) {
            return false;
        }

        model->trans.position = modelPosition;
        quat rot(modelRotation);
        model->trans.orientation = model->trans.orientation * rot;

        register_prop(*model);
    } // for shapes.size()

    return true;
} // load_model()<commit_msg>Fixed ContentManager not initialising<commit_after>#include "contentmanager.h"

// Model Classes
#include "Earth.h"
#include "Sputnik.h"

/* initialize : Initializes the ContentManager.
 *
 * Models described in the external proplist are loaded into the
 * ContentManagers proplist
 */
bool ContentManager::initialize()
{
    path = "proplist.csv";

    if (!load_props()) {
        cout << "Props failed to load" << '\n';
        return false;
    }

    _running = true;
    return true;
} // initialize()

/* shutdown : Shuts down the ContentManager
 *
 * Sets the ContentManager to stop running
 */
void ContentManager::shutdown()
{
    _running = false;
} // shutdown()

/* update : Updates all tracked objects
 *
 * Updates objects in the proplist
 */
void ContentManager::update(float deltaTime)
{
    // TODO: Implement Props updating
} // update(float deltaTime)

/* prop_list_size : Returns the size of prop_list
*
* returns the size of prop_list
*/
int ContentManager::prop_list_size()
{
    return prop_list.size();
} // prop_list_size()

/* get_prop_at : Returns prop at the given index
 *
 * Parameter (int index) - index of prop
 *
 * Gets the prop at the index provided from
 * prop_list
 */
mesh ContentManager::get_prop_at(int index)
{
    mesh result = prop_list.at(index);
    return result;
} // get_prop_at()

/* register_prop : Adds prop to prop_list
 *
 * Register object with scene manager for rendering
 */
void ContentManager::register_prop(mesh mesh)
{
    prop_list.push_back(mesh);
} // register_prop()

/*  unregister_prop : Removes prop from prop_list
 *
 * Unregister object with scene manager
 */
void ContentManager::unregister_prop(mesh mesh)
{
    prop_list.push_back(mesh);
} // unregister_prop()

/* load_prop_list : Loads props from propList.csv
 *
 * DEPRECATED:
 *
 * Parameter string path - Path for external proplist
 *
 * Loads models from external proplist in to the ContentManagers
 * interal proplist
 */
bool ContentManager::load_prop_list(string path)
{
    vector<string> modelPath;
    vector<vec3> modelPosition;
    vector<vec3> modelRotation;
    vector<string> modelVert, modelFrag;

    try {
        unsigned int i;
        csv::Parser file = csv::Parser(path);
        for (i = 0; i < file.rowCount(); ++i) {
            modelPath.push_back(file[i][0]);
            modelPosition.push_back(vec3(stof(file[i][1]), stof(file[i][2]), stof(file[i][3])));
            modelRotation.push_back(vec3(stof(file[i][4]), stof(file[i][5]), stof(file[i][6])));
            modelVert.push_back(file[i][7]);
            modelFrag.push_back(file[i][8]);
        }

        for (i=0; i < modelPath.size(); ++i) {
            if (!load_model(modelPath.at(i), modelPosition.at(i),
                modelRotation.at(i), modelVert.at(i), modelFrag.at(i))) {
                    return false;
            }
        }
    } catch (csv::Error &e) {
        std::cerr << e.what() << std::endl;
        return false;
    }

    return true;
} // load_prop_list()

/* load_props : loads the props for the scene
 *
 * Loads Earth, Sputnik, Moon and Sun for the scene
 */
bool ContentManager::load_props()
{
    Earth earth = Earth();
    Sputnik sputnik = Sputnik();

    // Load Earth
    if (!load_model(&sputnik, sputnik.get_path())) {
        return false;
    }

    // Load Sputnik
    if (!load_model(&sputnik, sputnik.get_path())) {
        return false;
    }

    return true;
} // load_props()

/* load_model : Loads the meshs for a Prop
 *
 * Uses tinyobj to load the models from their .obj file
 * then assigns the values extracted to the objects
 */
bool ContentManager::load_model(Prop* prop, string modelPath)
{
    // Load .OBJ
    std::vector<tinyobj::shape_t> shapes;
    std::string err = tinyobj::LoadObj(shapes, modelPath.c_str());

    // If an error occured stop
    if (!err.empty()) {
        std::cerr << err << std::endl;
        return false;
    }

    // Create mesh
    shared_ptr<mesh> model = make_shared<mesh>();
    model->geom = make_shared<geometry>();

    unsigned int i;
    for (i=0; i < shapes.size(); ++i) {
        tinyobj::shape_t* shape = &shapes[i];
        load_vertices(shape, model.get());
        load_normals(shape, model.get());
        load_texcoords(shape, model.get());
        load_indices(shape, model.get());

        // Initialise all loaded geometry data
        geometry_builder::initialise_geometry(model->geom);

        // Created effect for mesh
        auto eff = make_shared<effect>();
        eff->add_shader(prop->get_vert_path(), GL_VERTEX_SHADER);
        eff->add_shader(prop->get_frag_path(), GL_FRAGMENT_SHADER);
        // Build effect
        if (!effect_loader::build_effect(eff)) {
            return false;
        }

        // Create material and add effect
        model->mat = make_shared<material>();
        model->mat->effect = eff;

        // Set "eye position" and lighting for shader
        model->mat->set_uniform_value("eye_position", CameraManager::get_instance().currentCamera->get_position());
        model->mat->set_uniform_value("directional_light", SceneManager::get_instance().light);

        auto tex = texture_loader::load(shape->material.diffuse_texname);
        model->mat->set_texture("tex", tex);
        // build material
        if (!model->mat->build()) {
            return false;
        }

        model->trans.position = prop->get_position();
        quat rot(prop->get_rotation());
        model->trans.orientation = model->trans.orientation * rot;

        prop->add_mesh(model.get());
    } // for each in shapes[]

    return true;
} // load_model()

/** load_vertices : Loads vertices from shape
 *
 * Loads all shape positions and produces the vertices for the mesh
 */
void ContentManager::load_vertices(tinyobj::shape_t * shape, mesh * model)
{
    // Check ptrs are not null.
    if (shape != nullptr && model != nullptr) {
        // Check there are enough points to make full vertexes
        assert((shape->mesh.positions.size() % 3) == 0);
        unsigned int i;
        for (i=0; i < shape->mesh.positions.size() / 3 ; ++i) {
            model->geom->positions.push_back(vec3(shape->mesh.positions[3*i+0],
                                                  shape->mesh.positions[3*i+1],
                                                  shape->mesh.positions[3*i+2]));
        }
    }
} // load_vertices()

/** load_normals : Loads vertices from shape
 *
 * Loads all shape normals and add them to the mesh
 */
void ContentManager::load_normals(tinyobj::shape_t * shape, mesh * model)
{
    // Check ptrs are not null.
    if (shape != nullptr && model != nullptr) {
        // Check there are enough points for normals
        assert((shape->mesh.positions.size() % 3) == 0);
        unsigned int i;
        for (i=0; i < shape->mesh.positions.size() / 3 ; ++i) {
            model->geom->normals.push_back(vec3(shape->mesh.normals[3*i+0],
                                                shape->mesh.normals[3*i+1],
                                                shape->mesh.normals[3*i+2]));
        }
    }
} // load_normals()

/** load_texcoords : Loads vertices from shape
 *
 * Loads all shape tex coords and add them to the mesh
 */
void ContentManager::load_texcoords(tinyobj::shape_t * shape, mesh * model)
{
    // Check ptrs are not null.
    if (shape != nullptr && model != nullptr) {
        // Check there are enough points to make tex coords
        assert((shape->mesh.texcoords.size() % 2) == 0);
        unsigned int i;
        for (i = 0; i < shape->mesh.texcoords.size() / 2; ++i) {
            // Invert texture coordinates due to 3d max exporting issues
            model->geom->tex_coords.push_back(vec2(-shape->mesh.texcoords[2*i+0],
                                                   -shape->mesh.texcoords[2*i+1]));
        }
    }
} // load_texcoords()

/** load_indices : Loads vertices from shape
 *
 * Loads all shape indices and add them to the mesh
 */
void ContentManager::load_indices(tinyobj::shape_t * shape, mesh * model)
{
    // Check ptrs are not null.
    if (shape != nullptr && model != nullptr) {
        assert((shape->mesh.indices.size() % 3) == 0);
        model->geom->indices = shape->mesh.indices;
    }
} // load_indices()

/* load_shader_data : Loads shader data
 *
 * Loads shader data from shape and applies it to the effect for model
 */
void load_shader_data(tinyobj::shape_t * shape, mesh * model)
{
    // Set shader values for object
    model->mat->data.emissive            = vec4(shape->material.emission[0],
                                                shape->material.emission[1],
                                                shape->material.emission[2],
                                                // current used .mtl files only store
                                                // one value for Tr (transmittance)
                                                shape->material.transmittance[0]);

    model->mat->data.diffuse_reflection  = vec4(shape->material.diffuse[0],
                                                shape->material.diffuse[1],
                                                shape->material.diffuse[2],
                                                // current used .mtl files only store
                                                // one value for Tr (transmittance)
                                                shape->material.transmittance[0]);

    model->mat->data.specular_reflection = vec4(shape->material.specular[0],
                                                shape->material.specular[1],
                                                shape->material.specular[2],
                                                // current used .mtl files only store
                                                // one value for Tr (transmittance)
                                                shape->material.transmittance[0]);

    model->mat->data.shininess = shape->material.shininess;
} // load_shader_data()

/* load_model : Loads models
*
* DEPRECATED:
*
* Uses tinyobj to load the models from their .obj file
* then assigns the values extracted to the objects
*/
bool ContentManager::load_model(string modelPath, vec3 modelPosition, vec3 modelRotation,
    string modelVert, string modelFrag)
{
    // Create and load .OBJ
    std::vector<tinyobj::shape_t> shapes;
    std::string err = tinyobj::LoadObj(shapes, modelPath.c_str());

    // If an error occured stop
    if (!err.empty()) {
        std::cerr << err << std::endl;
        return false;
    }

    unsigned int i, j;
    for (i=0; i < shapes.size(); ++i) {
        assert((shapes[i].mesh.positions.size() % 3) == 0);
        shared_ptr<mesh> model = make_shared<mesh>();
        model->geom = make_shared<geometry>();

        for (j=0; j < shapes[i].mesh.positions.size() / 3 ; ++j) {
            model->geom->positions.push_back(vec3(shapes[i].mesh.positions[3*j+0],
                shapes[i].mesh.positions[3*j+1],
                shapes[i].mesh.positions[3*j+2]));

            model->geom->normals.push_back(vec3(shapes[i].mesh.normals[3*j+0],
                shapes[i].mesh.normals[3*j+1],
                shapes[i].mesh.normals[3*j+2]));
        }

        assert((shapes[i].mesh.texcoords.size() % 2) == 0);
        for (j=0; j < shapes[i].mesh.texcoords.size() / 2; ++j) {
            // Invert texture coordinates due to 3d max exporting issues
            model->geom->tex_coords.push_back(vec2(-shapes[i].mesh.texcoords[2*j+0],
                -shapes[i].mesh.texcoords[2*j+1]));
        }

        assert((shapes[i].mesh.indices.size() % 3) == 0);
        model->geom->indices = shapes[i].mesh.indices;

        geometry_builder::initialise_geometry(model->geom);

        auto eff = make_shared<effect>();
        eff->add_shader(modelVert, GL_VERTEX_SHADER);
        eff->add_shader(modelFrag, GL_FRAGMENT_SHADER);
        if (!effect_loader::build_effect(eff)) {
            return false;
        }

        model->mat = make_shared<material>();
        model->mat->effect = eff;

        // Set shader values for object
        model->mat->data.emissive = vec4(shapes[i].material.emission[0],
            shapes[i].material.emission[1],
            shapes[i].material.emission[2],
            shapes[i].material.transmittance[i]);

        model->mat->data.diffuse_reflection = vec4(shapes[i].material.diffuse[0],
            shapes[i].material.diffuse[1],
            shapes[i].material.diffuse[2],
            shapes[i].material.transmittance[i]);

        model->mat->data.specular_reflection = vec4(shapes[i].material.specular[0],
            shapes[i].material.specular[1],
            shapes[i].material.specular[2],
            shapes[i].material.transmittance[i]);

        model->mat->data.shininess = shapes[i].material.shininess;
        model->mat->set_uniform_value("eye_position", CameraManager::get_instance().currentCamera->get_position());

        model->mat->set_uniform_value("directional_light", SceneManager::get_instance().light);

        auto tex = texture_loader::load(shapes[i].material.diffuse_texname);
        model->mat->set_texture("tex", tex);

        if (!model->mat->build()) {
            return false;
        }

        model->trans.position = modelPosition;
        quat rot(modelRotation);
        model->trans.orientation = model->trans.orientation * rot;

        register_prop(*model);
    } // for shapes.size()

    return true;
} // load_model()<|endoftext|>


<commit_before>/*
 * Copyright 2016 Andrei Pangin
 *
 * 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 <dlfcn.h>
#include <stdlib.h>
#include <string.h>
#include "vmEntry.h"
#include "arguments.h"
#include "javaApi.h"
#include "os.h"
#include "profiler.h"
#include "instrument.h"
#include "lockTracer.h"
#include "log.h"
#include "vmStructs.h"

// JVM TI agent return codes
const int ARGUMENTS_ERROR = 100;
const int COMMAND_ERROR = 200;

static Arguments _agent_args;

JavaVM* VM::_vm;
jvmtiEnv* VM::_jvmti = NULL;
int VM::_hotspot_version = 0;
void* VM::_libjvm;
void* VM::_libjava;
AsyncGetCallTrace VM::_asyncGetCallTrace;
JVM_GetManagement VM::_getManagement;
jvmtiError (JNICALL *VM::_orig_RedefineClasses)(jvmtiEnv*, jint, const jvmtiClassDefinition*);
jvmtiError (JNICALL *VM::_orig_RetransformClasses)(jvmtiEnv*, jint, const jclass* classes);
jvmtiError (JNICALL *VM::_orig_GenerateEvents)(jvmtiEnv* jvmti, jvmtiEvent event_type);
volatile int VM::_in_redefine_classes = 0;

bool VM::init(JavaVM* vm, bool attach) {
    if (_jvmti != NULL) return true;

    _vm = vm;
    if (_vm->GetEnv((void**)&_jvmti, JVMTI_VERSION_1_0) != 0) {
        return false;
    }

    char* prop;
    if (_jvmti->GetSystemProperty("java.vm.name", &prop) == 0) {
        bool is_hotspot = strstr(prop, "OpenJDK") != NULL ||
                          strstr(prop, "HotSpot") != NULL ||
                          strstr(prop, "GraalVM") != NULL;
        _jvmti->Deallocate((unsigned char*)prop);

        if (is_hotspot && _jvmti->GetSystemProperty("java.vm.version", &prop) == 0) {
            if (strncmp(prop, "25.", 3) == 0) {
                _hotspot_version = 8;
            } else if (strncmp(prop, "24.", 3) == 0) {
                _hotspot_version = 7;
            } else if (strncmp(prop, "20.", 3) == 0) {
                _hotspot_version = 6;
            } else if ((_hotspot_version = atoi(prop)) < 9) {
                _hotspot_version = 9;
            }
            _jvmti->Deallocate((unsigned char*)prop);
        }
    }

    _libjvm = getLibraryHandle("libjvm.so");
    _asyncGetCallTrace = (AsyncGetCallTrace)dlsym(_libjvm, "AsyncGetCallTrace");
    _getManagement = (JVM_GetManagement)dlsym(_libjvm, "JVM_GetManagement");

    if (attach) {
        ready();
    }

    jvmtiCapabilities capabilities = {0};
    capabilities.can_generate_all_class_hook_events = 1;
    capabilities.can_retransform_classes = 1;
    capabilities.can_retransform_any_class = 1;
    capabilities.can_get_bytecodes = 1;
    capabilities.can_get_constant_pool = 1;
    capabilities.can_get_source_file_name = 1;
    capabilities.can_get_line_numbers = 1;
    capabilities.can_generate_compiled_method_load_events = 1;
    capabilities.can_generate_monitor_events = 1;
    capabilities.can_tag_objects = 1;
    _jvmti->AddCapabilities(&capabilities);

    jvmtiEventCallbacks callbacks = {0};
    callbacks.VMInit = VMInit;
    callbacks.VMDeath = VMDeath;
    callbacks.ClassLoad = ClassLoad;
    callbacks.ClassPrepare = ClassPrepare;
    callbacks.ClassFileLoadHook = Instrument::ClassFileLoadHook;
    callbacks.CompiledMethodLoad = Profiler::CompiledMethodLoad;
    callbacks.CompiledMethodUnload = Profiler::CompiledMethodUnload;
    callbacks.DynamicCodeGenerated = Profiler::DynamicCodeGenerated;
    callbacks.ThreadStart = Profiler::ThreadStart;
    callbacks.ThreadEnd = Profiler::ThreadEnd;
    callbacks.MonitorContendedEnter = LockTracer::MonitorContendedEnter;
    callbacks.MonitorContendedEntered = LockTracer::MonitorContendedEntered;
    _jvmti->SetEventCallbacks(&callbacks, sizeof(callbacks));

    _jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_VM_INIT, NULL);
    _jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_VM_DEATH, NULL);
    _jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_CLASS_LOAD, NULL);
    _jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_CLASS_PREPARE, NULL);
    _jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_COMPILED_METHOD_LOAD, NULL);
    _jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_COMPILED_METHOD_UNLOAD, NULL);
    _jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_DYNAMIC_CODE_GENERATED, NULL);

    if (attach) {
        loadAllMethodIDs(jvmti(), jni());
        _jvmti->GenerateEvents(JVMTI_EVENT_DYNAMIC_CODE_GENERATED);
        _jvmti->GenerateEvents(JVMTI_EVENT_COMPILED_METHOD_LOAD);
    }

    if (hotspot_version() > 0 && hotspot_version() < 11) {
        // Avoid GenerateEvents conflict with another agent
        JVMTIFunctions* functions = *(JVMTIFunctions**)_jvmti;
        _orig_GenerateEvents = functions->GenerateEvents;
        functions->GenerateEvents = GenerateEventsHook;
    }

    return true;
}

// Run late initialization when JVM is ready
void VM::ready() {
    Profiler::_instance.updateSymbols(false);
    NativeCodeCache* libjvm = Profiler::_instance.findNativeLibrary((const void*)_asyncGetCallTrace);
    if (libjvm != NULL) {
        JitWriteProtection jit(true);  // workaround for JDK-8262896
        VMStructs::init(libjvm);
    }

    Profiler::_instance.setupTrapHandler();

    _libjava = getLibraryHandle("libjava.so");

    // Make sure we reload method IDs upon class retransformation
    JVMTIFunctions* functions = *(JVMTIFunctions**)_jvmti;
    _orig_RedefineClasses = functions->RedefineClasses;
    _orig_RetransformClasses = functions->RetransformClasses;
    functions->RedefineClasses = RedefineClassesHook;
    functions->RetransformClasses = RetransformClassesHook;
}

void* VM::getLibraryHandle(const char* name) {
    if (!OS::isJavaLibraryVisible()) {
        void* handle = dlopen(name, RTLD_LAZY);
        if (handle != NULL) {
            return handle;
        }
        Log::warn("Failed to load %s: %s", name, dlerror());
    }
    return RTLD_DEFAULT;
}

void VM::loadMethodIDs(jvmtiEnv* jvmti, JNIEnv* jni, jclass klass) {
    if (VMStructs::hasClassLoaderData()) {
        VMKlass* vmklass = VMKlass::fromJavaClass(jni, klass);
        int method_count = vmklass->methodCount();
        if (method_count > 0) {
            ClassLoaderData* cld = vmklass->classLoaderData();
            cld->lock();
            // Workaround for JVM bug: preallocate space for jmethodIDs
            // at the beginning of the list (rather than at the end)
            for (int i = 0; i < method_count; i += MethodList::SIZE) {
                *cld->methodList() = new MethodList(*cld->methodList());
            }
            cld->unlock();
        }
    }

    jint method_count;
    jmethodID* methods;
    if (jvmti->GetClassMethods(klass, &method_count, &methods) == 0) {
        jvmti->Deallocate((unsigned char*)methods);
    }
}

void VM::loadAllMethodIDs(jvmtiEnv* jvmti, JNIEnv* jni) {
    jint class_count;
    jclass* classes;
    if (jvmti->GetLoadedClasses(&class_count, &classes) == 0) {
        for (int i = 0; i < class_count; i++) {
            loadMethodIDs(jvmti, jni, classes[i]);
        }
        jvmti->Deallocate((unsigned char*)classes);
    }
}

void JNICALL VM::VMInit(jvmtiEnv* jvmti, JNIEnv* jni, jthread thread) {
    ready();
    loadAllMethodIDs(jvmti, jni);

    // Delayed start of profiler if agent has been loaded at VM bootstrap
    Error error = Profiler::_instance.run(_agent_args);
    if (error) {
        Log::error(error.message());
    }
}

void JNICALL VM::VMDeath(jvmtiEnv* jvmti, JNIEnv* jni) {
    Profiler::_instance.shutdown(_agent_args);
}

jvmtiError VM::RedefineClassesHook(jvmtiEnv* jvmti, jint class_count, const jvmtiClassDefinition* class_definitions) {
    atomicInc(_in_redefine_classes);
    jvmtiError result = _orig_RedefineClasses(jvmti, class_count, class_definitions);

    // jmethodIDs are invalidated after RedefineClasses
    JNIEnv* env = jni();
    for (int i = 0; i < class_count; i++) {
        if (class_definitions[i].klass != NULL) {
            loadMethodIDs(jvmti, env, class_definitions[i].klass);
        }
    }

    atomicInc(_in_redefine_classes, -1);
    return result;
}

jvmtiError VM::RetransformClassesHook(jvmtiEnv* jvmti, jint class_count, const jclass* classes) {
    atomicInc(_in_redefine_classes);
    jvmtiError result = _orig_RetransformClasses(jvmti, class_count, classes);

    // jmethodIDs are invalidated after RetransformClasses
    JNIEnv* env = jni();
    for (int i = 0; i < class_count; i++) {
        if (classes[i] != NULL) {
            loadMethodIDs(jvmti, env, classes[i]);
        }
    }

    atomicInc(_in_redefine_classes, -1);
    return result;
}

jvmtiError VM::GenerateEventsHook(jvmtiEnv* jvmti, jvmtiEvent event_type) {
    if (event_type == JVMTI_EVENT_COMPILED_METHOD_LOAD) {
        // Workaround for JDK-8222072: prepare to receive events designated for another agent
        Log::warn("async-profiler conflicts with another agent calling GenerateEvents()");
        Profiler::_instance.resetJavaMethods();
    }
    return _orig_GenerateEvents(jvmti, event_type);
}

extern "C" JNIEXPORT jint JNICALL
Agent_OnLoad(JavaVM* vm, char* options, void* reserved) {
    Error error = _agent_args.parse(options);
    Log::open(_agent_args._log);
    if (error) {
        Log::error(error.message());
        return ARGUMENTS_ERROR;
    }

    if (!VM::init(vm, false)) {
        Log::error("JVM does not support Tool Interface");
        return COMMAND_ERROR;
    }

    return 0;
}

extern "C" JNIEXPORT jint JNICALL
Agent_OnAttach(JavaVM* vm, char* options, void* reserved) {
    Arguments args;
    Error error = args.parse(options);
    Log::open(args._log);
    if (error) {
        Log::error(error.message());
        return ARGUMENTS_ERROR;
    }

    if (!VM::init(vm, true)) {
        Log::error("JVM does not support Tool Interface");
        return COMMAND_ERROR;
    }

    // Save the arguments in case of shutdown
    if (args._action == ACTION_START || args._action == ACTION_RESUME) {
        _agent_args.save(args);
    }

    error = Profiler::_instance.run(args);
    if (error) {
        Log::error(error.message());
        return COMMAND_ERROR;
    }

    return 0;
}

extern "C" JNIEXPORT jint JNICALL
JNI_OnLoad(JavaVM* vm, void* reserved) {
    if (!VM::init(vm, true)) {
        return 0;
    }

    JavaAPI::registerNatives(VM::jvmti(), VM::jni());
    return JNI_VERSION_1_6;
}
<commit_msg>#440: Fixed crash when RetransformClasses is called with invalid arguments<commit_after>/*
 * Copyright 2016 Andrei Pangin
 *
 * 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 <dlfcn.h>
#include <stdlib.h>
#include <string.h>
#include "vmEntry.h"
#include "arguments.h"
#include "javaApi.h"
#include "os.h"
#include "profiler.h"
#include "instrument.h"
#include "lockTracer.h"
#include "log.h"
#include "vmStructs.h"

// JVM TI agent return codes
const int ARGUMENTS_ERROR = 100;
const int COMMAND_ERROR = 200;

static Arguments _agent_args;

JavaVM* VM::_vm;
jvmtiEnv* VM::_jvmti = NULL;
int VM::_hotspot_version = 0;
void* VM::_libjvm;
void* VM::_libjava;
AsyncGetCallTrace VM::_asyncGetCallTrace;
JVM_GetManagement VM::_getManagement;
jvmtiError (JNICALL *VM::_orig_RedefineClasses)(jvmtiEnv*, jint, const jvmtiClassDefinition*);
jvmtiError (JNICALL *VM::_orig_RetransformClasses)(jvmtiEnv*, jint, const jclass* classes);
jvmtiError (JNICALL *VM::_orig_GenerateEvents)(jvmtiEnv* jvmti, jvmtiEvent event_type);
volatile int VM::_in_redefine_classes = 0;

bool VM::init(JavaVM* vm, bool attach) {
    if (_jvmti != NULL) return true;

    _vm = vm;
    if (_vm->GetEnv((void**)&_jvmti, JVMTI_VERSION_1_0) != 0) {
        return false;
    }

    char* prop;
    if (_jvmti->GetSystemProperty("java.vm.name", &prop) == 0) {
        bool is_hotspot = strstr(prop, "OpenJDK") != NULL ||
                          strstr(prop, "HotSpot") != NULL ||
                          strstr(prop, "GraalVM") != NULL;
        _jvmti->Deallocate((unsigned char*)prop);

        if (is_hotspot && _jvmti->GetSystemProperty("java.vm.version", &prop) == 0) {
            if (strncmp(prop, "25.", 3) == 0) {
                _hotspot_version = 8;
            } else if (strncmp(prop, "24.", 3) == 0) {
                _hotspot_version = 7;
            } else if (strncmp(prop, "20.", 3) == 0) {
                _hotspot_version = 6;
            } else if ((_hotspot_version = atoi(prop)) < 9) {
                _hotspot_version = 9;
            }
            _jvmti->Deallocate((unsigned char*)prop);
        }
    }

    _libjvm = getLibraryHandle("libjvm.so");
    _asyncGetCallTrace = (AsyncGetCallTrace)dlsym(_libjvm, "AsyncGetCallTrace");
    _getManagement = (JVM_GetManagement)dlsym(_libjvm, "JVM_GetManagement");

    if (attach) {
        ready();
    }

    jvmtiCapabilities capabilities = {0};
    capabilities.can_generate_all_class_hook_events = 1;
    capabilities.can_retransform_classes = 1;
    capabilities.can_retransform_any_class = 1;
    capabilities.can_get_bytecodes = 1;
    capabilities.can_get_constant_pool = 1;
    capabilities.can_get_source_file_name = 1;
    capabilities.can_get_line_numbers = 1;
    capabilities.can_generate_compiled_method_load_events = 1;
    capabilities.can_generate_monitor_events = 1;
    capabilities.can_tag_objects = 1;
    _jvmti->AddCapabilities(&capabilities);

    jvmtiEventCallbacks callbacks = {0};
    callbacks.VMInit = VMInit;
    callbacks.VMDeath = VMDeath;
    callbacks.ClassLoad = ClassLoad;
    callbacks.ClassPrepare = ClassPrepare;
    callbacks.ClassFileLoadHook = Instrument::ClassFileLoadHook;
    callbacks.CompiledMethodLoad = Profiler::CompiledMethodLoad;
    callbacks.CompiledMethodUnload = Profiler::CompiledMethodUnload;
    callbacks.DynamicCodeGenerated = Profiler::DynamicCodeGenerated;
    callbacks.ThreadStart = Profiler::ThreadStart;
    callbacks.ThreadEnd = Profiler::ThreadEnd;
    callbacks.MonitorContendedEnter = LockTracer::MonitorContendedEnter;
    callbacks.MonitorContendedEntered = LockTracer::MonitorContendedEntered;
    _jvmti->SetEventCallbacks(&callbacks, sizeof(callbacks));

    _jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_VM_INIT, NULL);
    _jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_VM_DEATH, NULL);
    _jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_CLASS_LOAD, NULL);
    _jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_CLASS_PREPARE, NULL);
    _jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_COMPILED_METHOD_LOAD, NULL);
    _jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_COMPILED_METHOD_UNLOAD, NULL);
    _jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_DYNAMIC_CODE_GENERATED, NULL);

    if (attach) {
        loadAllMethodIDs(jvmti(), jni());
        _jvmti->GenerateEvents(JVMTI_EVENT_DYNAMIC_CODE_GENERATED);
        _jvmti->GenerateEvents(JVMTI_EVENT_COMPILED_METHOD_LOAD);
    }

    if (hotspot_version() > 0 && hotspot_version() < 11) {
        // Avoid GenerateEvents conflict with another agent
        JVMTIFunctions* functions = *(JVMTIFunctions**)_jvmti;
        _orig_GenerateEvents = functions->GenerateEvents;
        functions->GenerateEvents = GenerateEventsHook;
    }

    return true;
}

// Run late initialization when JVM is ready
void VM::ready() {
    Profiler::_instance.updateSymbols(false);
    NativeCodeCache* libjvm = Profiler::_instance.findNativeLibrary((const void*)_asyncGetCallTrace);
    if (libjvm != NULL) {
        JitWriteProtection jit(true);  // workaround for JDK-8262896
        VMStructs::init(libjvm);
    }

    Profiler::_instance.setupTrapHandler();

    _libjava = getLibraryHandle("libjava.so");

    // Make sure we reload method IDs upon class retransformation
    JVMTIFunctions* functions = *(JVMTIFunctions**)_jvmti;
    _orig_RedefineClasses = functions->RedefineClasses;
    _orig_RetransformClasses = functions->RetransformClasses;
    functions->RedefineClasses = RedefineClassesHook;
    functions->RetransformClasses = RetransformClassesHook;
}

void* VM::getLibraryHandle(const char* name) {
    if (!OS::isJavaLibraryVisible()) {
        void* handle = dlopen(name, RTLD_LAZY);
        if (handle != NULL) {
            return handle;
        }
        Log::warn("Failed to load %s: %s", name, dlerror());
    }
    return RTLD_DEFAULT;
}

void VM::loadMethodIDs(jvmtiEnv* jvmti, JNIEnv* jni, jclass klass) {
    if (VMStructs::hasClassLoaderData()) {
        VMKlass* vmklass = VMKlass::fromJavaClass(jni, klass);
        int method_count = vmklass->methodCount();
        if (method_count > 0) {
            ClassLoaderData* cld = vmklass->classLoaderData();
            cld->lock();
            // Workaround for JVM bug: preallocate space for jmethodIDs
            // at the beginning of the list (rather than at the end)
            for (int i = 0; i < method_count; i += MethodList::SIZE) {
                *cld->methodList() = new MethodList(*cld->methodList());
            }
            cld->unlock();
        }
    }

    jint method_count;
    jmethodID* methods;
    if (jvmti->GetClassMethods(klass, &method_count, &methods) == 0) {
        jvmti->Deallocate((unsigned char*)methods);
    }
}

void VM::loadAllMethodIDs(jvmtiEnv* jvmti, JNIEnv* jni) {
    jint class_count;
    jclass* classes;
    if (jvmti->GetLoadedClasses(&class_count, &classes) == 0) {
        for (int i = 0; i < class_count; i++) {
            loadMethodIDs(jvmti, jni, classes[i]);
        }
        jvmti->Deallocate((unsigned char*)classes);
    }
}

void JNICALL VM::VMInit(jvmtiEnv* jvmti, JNIEnv* jni, jthread thread) {
    ready();
    loadAllMethodIDs(jvmti, jni);

    // Delayed start of profiler if agent has been loaded at VM bootstrap
    Error error = Profiler::_instance.run(_agent_args);
    if (error) {
        Log::error(error.message());
    }
}

void JNICALL VM::VMDeath(jvmtiEnv* jvmti, JNIEnv* jni) {
    Profiler::_instance.shutdown(_agent_args);
}

jvmtiError VM::RedefineClassesHook(jvmtiEnv* jvmti, jint class_count, const jvmtiClassDefinition* class_definitions) {
    atomicInc(_in_redefine_classes);
    jvmtiError result = _orig_RedefineClasses(jvmti, class_count, class_definitions);

    if (result == 0) {
        // jmethodIDs are invalidated after RedefineClasses
        JNIEnv* env = jni();
        for (int i = 0; i < class_count; i++) {
            if (class_definitions[i].klass != NULL) {
                loadMethodIDs(jvmti, env, class_definitions[i].klass);
            }
        }
    }

    atomicInc(_in_redefine_classes, -1);
    return result;
}

jvmtiError VM::RetransformClassesHook(jvmtiEnv* jvmti, jint class_count, const jclass* classes) {
    atomicInc(_in_redefine_classes);
    jvmtiError result = _orig_RetransformClasses(jvmti, class_count, classes);

    if (result == 0) {
        // jmethodIDs are invalidated after RetransformClasses
        JNIEnv* env = jni();
        for (int i = 0; i < class_count; i++) {
            if (classes[i] != NULL) {
                loadMethodIDs(jvmti, env, classes[i]);
            }
        }
    }

    atomicInc(_in_redefine_classes, -1);
    return result;
}

jvmtiError VM::GenerateEventsHook(jvmtiEnv* jvmti, jvmtiEvent event_type) {
    if (event_type == JVMTI_EVENT_COMPILED_METHOD_LOAD) {
        // Workaround for JDK-8222072: prepare to receive events designated for another agent
        Log::warn("async-profiler conflicts with another agent calling GenerateEvents()");
        Profiler::_instance.resetJavaMethods();
    }
    return _orig_GenerateEvents(jvmti, event_type);
}

extern "C" JNIEXPORT jint JNICALL
Agent_OnLoad(JavaVM* vm, char* options, void* reserved) {
    Error error = _agent_args.parse(options);
    Log::open(_agent_args._log);
    if (error) {
        Log::error(error.message());
        return ARGUMENTS_ERROR;
    }

    if (!VM::init(vm, false)) {
        Log::error("JVM does not support Tool Interface");
        return COMMAND_ERROR;
    }

    return 0;
}

extern "C" JNIEXPORT jint JNICALL
Agent_OnAttach(JavaVM* vm, char* options, void* reserved) {
    Arguments args;
    Error error = args.parse(options);
    Log::open(args._log);
    if (error) {
        Log::error(error.message());
        return ARGUMENTS_ERROR;
    }

    if (!VM::init(vm, true)) {
        Log::error("JVM does not support Tool Interface");
        return COMMAND_ERROR;
    }

    // Save the arguments in case of shutdown
    if (args._action == ACTION_START || args._action == ACTION_RESUME) {
        _agent_args.save(args);
    }

    error = Profiler::_instance.run(args);
    if (error) {
        Log::error(error.message());
        return COMMAND_ERROR;
    }

    return 0;
}

extern "C" JNIEXPORT jint JNICALL
JNI_OnLoad(JavaVM* vm, void* reserved) {
    if (!VM::init(vm, true)) {
        return 0;
    }

    JavaAPI::registerNatives(VM::jvmti(), VM::jni());
    return JNI_VERSION_1_6;
}
<|endoftext|>


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

#include <string.h>

#include "chrome/browser/chromeos/bluetooth/bluetooth_adapter.h"
#include "chrome/browser/chromeos/bluetooth/test/mock_bluetooth_adapter.h"
#include "chrome/browser/chromeos/bluetooth/test/mock_bluetooth_device.h"
#include "chrome/browser/chromeos/extensions/bluetooth_event_router.h"
#include "chrome/browser/extensions/api/bluetooth/bluetooth_api.h"
#include "chrome/browser/extensions/extension_apitest.h"
#include "chrome/browser/extensions/extension_function_test_utils.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_test_message_listener.h"
#include "chrome/browser/ui/browser.h"
#include "chromeos/dbus/bluetooth_out_of_band_client.h"
#include "testing/gmock/include/gmock/gmock.h"

using extensions::Extension;

namespace utils = extension_function_test_utils;
namespace api = extensions::api;

namespace chromeos {

class BluetoothAdapater;

}  // namespace chromeos

namespace {

class BluetoothApiTest : public PlatformAppApiTest {
 public:
  BluetoothApiTest() : empty_extension_(utils::CreateEmptyExtension()) {}

  virtual void SetUpOnMainThread() OVERRIDE {
    // The browser will clean this up when it is torn down
    mock_adapter_ = new testing::StrictMock<chromeos::MockBluetoothAdapter>;
    event_router()->SetAdapterForTest(mock_adapter_);
  }

  void expectBooleanResult(bool expected,
                           UIThreadExtensionFunction* function,
                           const std::string& args) {
    scoped_ptr<base::Value> result(
        utils::RunFunctionAndReturnResult(function, args, browser()));
    ASSERT_TRUE(result.get() != NULL);
    ASSERT_EQ(base::Value::TYPE_BOOLEAN, result->GetType());
    bool boolean_value;
    result->GetAsBoolean(&boolean_value);
    EXPECT_EQ(expected, boolean_value);
  }

  template <class T>
  T* setupFunction(T* function) {
    function->set_extension(empty_extension_.get());
    function->set_has_callback(true);
    return function;
  }

 protected:
  testing::StrictMock<chromeos::MockBluetoothAdapter>* mock_adapter_;

 private:
  chromeos::ExtensionBluetoothEventRouter* event_router() {
    return browser()->profile()->GetExtensionService()->
        bluetooth_event_router();
  }

  chromeos::BluetoothAdapter* original_adapter_;
  scoped_refptr<Extension> empty_extension_;
};

static const char kOutOfBandPairingDataHash[] = "0123456789ABCDEh";
static const char kOutOfBandPairingDataRandomizer[] = "0123456789ABCDEr";

static chromeos::BluetoothOutOfBandPairingData GetOutOfBandPairingData() {
  chromeos::BluetoothOutOfBandPairingData data;
  memcpy(&(data.hash), kOutOfBandPairingDataHash,
      chromeos::kBluetoothOutOfBandPairingDataSize);
  memcpy(&(data.randomizer), kOutOfBandPairingDataRandomizer,
      chromeos::kBluetoothOutOfBandPairingDataSize);
  return data;
}

static bool CallClosure(const base::Closure& callback) {
  callback.Run();
  return true;
}

static bool CallOutOfBandPairingDataCallback(
      const chromeos::BluetoothAdapter::BluetoothOutOfBandPairingDataCallback&
          callback) {
  callback.Run(GetOutOfBandPairingData());
  return true;
}

}  // namespace

IN_PROC_BROWSER_TEST_F(BluetoothApiTest, IsAvailable) {
  EXPECT_CALL(*mock_adapter_, IsPresent())
      .WillOnce(testing::Return(false));

  scoped_refptr<api::BluetoothIsAvailableFunction> is_available;

  is_available = setupFunction(new api::BluetoothIsAvailableFunction);
  expectBooleanResult(false, is_available, "[]");

  testing::Mock::VerifyAndClearExpectations(mock_adapter_);
  EXPECT_CALL(*mock_adapter_, IsPresent())
      .WillOnce(testing::Return(true));

  is_available = setupFunction(new api::BluetoothIsAvailableFunction);
  expectBooleanResult(true, is_available, "[]");
}

IN_PROC_BROWSER_TEST_F(BluetoothApiTest, IsPowered) {
  EXPECT_CALL(*mock_adapter_, IsPowered())
      .WillOnce(testing::Return(false));

  scoped_refptr<api::BluetoothIsPoweredFunction> is_powered;

  is_powered = setupFunction(new api::BluetoothIsPoweredFunction);
  expectBooleanResult(false, is_powered, "[]");

  testing::Mock::VerifyAndClearExpectations(mock_adapter_);
  EXPECT_CALL(*mock_adapter_, IsPowered())
      .WillOnce(testing::Return(true));

  is_powered = setupFunction(new api::BluetoothIsPoweredFunction);
  expectBooleanResult(true, is_powered, "[]");
}

IN_PROC_BROWSER_TEST_F(BluetoothApiTest, GetDevicesWithServiceUUID) {
  testing::NiceMock<chromeos::MockBluetoothDevice> device1(
      mock_adapter_, "d1", "11:12:13:14:15:16",
      true /* paired */, false /* bonded */, true /* connected */);
  testing::NiceMock<chromeos::MockBluetoothDevice> device2(
      mock_adapter_, "d2", "21:22:23:24:25:26",
      false /* paired */, true /* bonded */, false /* connected */);
  chromeos::BluetoothAdapter::ConstDeviceList devices;
  devices.push_back(&device1);
  devices.push_back(&device2);

  EXPECT_CALL(device1, ProvidesServiceWithUUID("foo"))
      .WillOnce(testing::Return(false));
  EXPECT_CALL(device2, ProvidesServiceWithUUID("foo"))
      .WillOnce(testing::Return(true));

  EXPECT_CALL(*mock_adapter_, GetDevices())
      .WillOnce(testing::Return(devices));

  scoped_refptr<api::BluetoothGetDevicesWithServiceUUIDFunction> get_devices;

  get_devices =
      setupFunction(new api::BluetoothGetDevicesWithServiceUUIDFunction);
  scoped_ptr<base::Value> result(
      utils::RunFunctionAndReturnResult(get_devices, "[\"foo\"]", browser()));

  ASSERT_EQ(base::Value::TYPE_LIST, result->GetType());
  base::ListValue* list;
  ASSERT_TRUE(result->GetAsList(&list));

  EXPECT_EQ(1u, list->GetSize());
  base::Value* device_value;
  EXPECT_TRUE(list->Get(0, &device_value));
  EXPECT_EQ(base::Value::TYPE_DICTIONARY, device_value->GetType());
  base::DictionaryValue* device;
  ASSERT_TRUE(device_value->GetAsDictionary(&device));

  std::string name;
  ASSERT_TRUE(device->GetString("name", &name));
  EXPECT_EQ("d2", name);
  std::string address;
  ASSERT_TRUE(device->GetString("address", &address));
  EXPECT_EQ("21:22:23:24:25:26", address);
  bool paired;
  ASSERT_TRUE(device->GetBoolean("paired", &paired));
  EXPECT_EQ(false, paired);
  bool bonded;
  ASSERT_TRUE(device->GetBoolean("bonded", &bonded));
  EXPECT_EQ(true, bonded);
  bool connected;
  ASSERT_TRUE(device->GetBoolean("connected", &connected));
  EXPECT_EQ(false, connected);
}

IN_PROC_BROWSER_TEST_F(BluetoothApiTest, GetLocalOutOfBandPairingData) {
  EXPECT_CALL(*mock_adapter_,
              ReadLocalOutOfBandPairingData(
                  testing::Truly(CallOutOfBandPairingDataCallback),
                  testing::_));

  scoped_refptr<api::BluetoothGetLocalOutOfBandPairingDataFunction>
      get_oob_function(setupFunction(
            new api::BluetoothGetLocalOutOfBandPairingDataFunction));

  scoped_ptr<base::Value> result(
      utils::RunFunctionAndReturnResult(get_oob_function, "[]", browser()));

  base::DictionaryValue* dict;
  EXPECT_TRUE(result->GetAsDictionary(&dict));

  base::BinaryValue* binary_value;
  EXPECT_TRUE(dict->GetBinary("hash", &binary_value));
  EXPECT_STREQ(kOutOfBandPairingDataHash,
      std::string(binary_value->GetBuffer(), binary_value->GetSize()).c_str());
  EXPECT_TRUE(dict->GetBinary("randomizer", &binary_value));
  EXPECT_STREQ(kOutOfBandPairingDataRandomizer,
      std::string(binary_value->GetBuffer(), binary_value->GetSize()).c_str());

  // Try again with an error
  testing::Mock::VerifyAndClearExpectations(mock_adapter_);
  EXPECT_CALL(*mock_adapter_,
              ReadLocalOutOfBandPairingData(
                  testing::_,
                  testing::Truly(CallClosure)));

  get_oob_function =
      setupFunction(new api::BluetoothGetLocalOutOfBandPairingDataFunction);

  std::string error(
      utils::RunFunctionAndReturnError(get_oob_function, "[]", browser()));
  EXPECT_FALSE(error.empty());
}

IN_PROC_BROWSER_TEST_F(BluetoothApiTest, DISABLED_SetOutOfBandPairingData) {
  // TODO(bryeung): Fill in this test once it is possible to include an
  // ArrayBuffer in the arguments to the RunFunctionAnd* methods.
  // crbug.com/132796
}

IN_PROC_BROWSER_TEST_F(BluetoothApiTest, ClearOutOfBandPairingData) {
  std::string device_address("11:12:13:14:15:16");
  testing::NiceMock<chromeos::MockBluetoothDevice> device(
      mock_adapter_, "d1", device_address,
      true /* paired */, false /* bonded */, true /* connected */);
  EXPECT_CALL(*mock_adapter_, GetDevice(device_address))
      .WillOnce(testing::Return(&device));
  EXPECT_CALL(device,
              ClearOutOfBandPairingData(
                  testing::Truly(CallClosure),
                  testing::_));

  char buf[32];
  snprintf(buf, sizeof(buf), "[\"%s\"]", device_address.c_str());
  std::string params(buf);

  scoped_refptr<api::BluetoothClearOutOfBandPairingDataFunction>
      clear_oob_function;
  clear_oob_function = setupFunction(
      new api::BluetoothClearOutOfBandPairingDataFunction);
  // There isn't actually a result.
  (void)utils::RunFunctionAndReturnResult(
      clear_oob_function, params, browser());

  // Try again with an error
  testing::Mock::VerifyAndClearExpectations(mock_adapter_);
  testing::Mock::VerifyAndClearExpectations(&device);
  EXPECT_CALL(*mock_adapter_, GetDevice(device_address))
      .WillOnce(testing::Return(&device));
  EXPECT_CALL(device,
              ClearOutOfBandPairingData(
                  testing::_,
                  testing::Truly(CallClosure)));

  clear_oob_function = setupFunction(
      new api::BluetoothClearOutOfBandPairingDataFunction);
  std::string error(
      utils::RunFunctionAndReturnError(clear_oob_function, params, browser()));
  EXPECT_FALSE(error.empty());
}
<commit_msg>Fix ChromiumOS compile.<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <string.h>

#include "chrome/browser/chromeos/bluetooth/bluetooth_adapter.h"
#include "chrome/browser/chromeos/bluetooth/test/mock_bluetooth_adapter.h"
#include "chrome/browser/chromeos/bluetooth/test/mock_bluetooth_device.h"
#include "chrome/browser/chromeos/extensions/bluetooth_event_router.h"
#include "chrome/browser/extensions/api/bluetooth/bluetooth_api.h"
#include "chrome/browser/extensions/extension_apitest.h"
#include "chrome/browser/extensions/extension_function_test_utils.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_test_message_listener.h"
#include "chrome/browser/ui/browser.h"
#include "chromeos/dbus/bluetooth_out_of_band_client.h"
#include "testing/gmock/include/gmock/gmock.h"

using extensions::Extension;

namespace utils = extension_function_test_utils;
namespace api = extensions::api;

namespace chromeos {

class BluetoothAdapater;

}  // namespace chromeos

namespace {

class BluetoothApiTest : public PlatformAppApiTest {
 public:
  BluetoothApiTest() : empty_extension_(utils::CreateEmptyExtension()) {}

  virtual void SetUpOnMainThread() OVERRIDE {
    // The browser will clean this up when it is torn down
    mock_adapter_ = new testing::StrictMock<chromeos::MockBluetoothAdapter>;
    event_router()->SetAdapterForTest(mock_adapter_);
  }

  void expectBooleanResult(bool expected,
                           UIThreadExtensionFunction* function,
                           const std::string& args) {
    scoped_ptr<base::Value> result(
        utils::RunFunctionAndReturnResult(function, args, browser()));
    ASSERT_TRUE(result.get() != NULL);
    ASSERT_EQ(base::Value::TYPE_BOOLEAN, result->GetType());
    bool boolean_value;
    result->GetAsBoolean(&boolean_value);
    EXPECT_EQ(expected, boolean_value);
  }

  template <class T>
  T* setupFunction(T* function) {
    function->set_extension(empty_extension_.get());
    function->set_has_callback(true);
    return function;
  }

 protected:
  testing::StrictMock<chromeos::MockBluetoothAdapter>* mock_adapter_;

 private:
  chromeos::ExtensionBluetoothEventRouter* event_router() {
    return browser()->profile()->GetExtensionService()->
        bluetooth_event_router();
  }

  chromeos::BluetoothAdapter* original_adapter_;
  scoped_refptr<Extension> empty_extension_;
};

static const char kOutOfBandPairingDataHash[] = "0123456789ABCDEh";
static const char kOutOfBandPairingDataRandomizer[] = "0123456789ABCDEr";

static chromeos::BluetoothOutOfBandPairingData GetOutOfBandPairingData() {
  chromeos::BluetoothOutOfBandPairingData data;
  memcpy(&(data.hash), kOutOfBandPairingDataHash,
      chromeos::kBluetoothOutOfBandPairingDataSize);
  memcpy(&(data.randomizer), kOutOfBandPairingDataRandomizer,
      chromeos::kBluetoothOutOfBandPairingDataSize);
  return data;
}

static bool CallClosure(const base::Closure& callback) {
  callback.Run();
  return true;
}

static bool CallOutOfBandPairingDataCallback(
      const chromeos::BluetoothAdapter::BluetoothOutOfBandPairingDataCallback&
          callback) {
  callback.Run(GetOutOfBandPairingData());
  return true;
}

}  // namespace

IN_PROC_BROWSER_TEST_F(BluetoothApiTest, IsAvailable) {
  EXPECT_CALL(*mock_adapter_, IsPresent())
      .WillOnce(testing::Return(false));

  scoped_refptr<api::BluetoothIsAvailableFunction> is_available;

  is_available = setupFunction(new api::BluetoothIsAvailableFunction);
  expectBooleanResult(false, is_available, "[]");

  testing::Mock::VerifyAndClearExpectations(mock_adapter_);
  EXPECT_CALL(*mock_adapter_, IsPresent())
      .WillOnce(testing::Return(true));

  is_available = setupFunction(new api::BluetoothIsAvailableFunction);
  expectBooleanResult(true, is_available, "[]");
}

IN_PROC_BROWSER_TEST_F(BluetoothApiTest, IsPowered) {
  EXPECT_CALL(*mock_adapter_, IsPowered())
      .WillOnce(testing::Return(false));

  scoped_refptr<api::BluetoothIsPoweredFunction> is_powered;

  is_powered = setupFunction(new api::BluetoothIsPoweredFunction);
  expectBooleanResult(false, is_powered, "[]");

  testing::Mock::VerifyAndClearExpectations(mock_adapter_);
  EXPECT_CALL(*mock_adapter_, IsPowered())
      .WillOnce(testing::Return(true));

  is_powered = setupFunction(new api::BluetoothIsPoweredFunction);
  expectBooleanResult(true, is_powered, "[]");
}

IN_PROC_BROWSER_TEST_F(BluetoothApiTest, GetDevicesWithServiceUUID) {
  testing::NiceMock<chromeos::MockBluetoothDevice> device1(
      mock_adapter_, "d1", "11:12:13:14:15:16",
      true /* paired */, false /* bonded */, true /* connected */);
  testing::NiceMock<chromeos::MockBluetoothDevice> device2(
      mock_adapter_, "d2", "21:22:23:24:25:26",
      false /* paired */, true /* bonded */, false /* connected */);
  chromeos::BluetoothAdapter::ConstDeviceList devices;
  devices.push_back(&device1);
  devices.push_back(&device2);

  EXPECT_CALL(device1, ProvidesServiceWithUUID("foo"))
      .WillOnce(testing::Return(false));
  EXPECT_CALL(device2, ProvidesServiceWithUUID("foo"))
      .WillOnce(testing::Return(true));

  EXPECT_CALL(*mock_adapter_, GetDevices())
      .WillOnce(testing::Return(devices));

  scoped_refptr<api::BluetoothGetDevicesWithServiceUUIDFunction> get_devices;

  get_devices =
      setupFunction(new api::BluetoothGetDevicesWithServiceUUIDFunction);
  scoped_ptr<base::Value> result(
      utils::RunFunctionAndReturnResult(get_devices, "[\"foo\"]", browser()));

  ASSERT_EQ(base::Value::TYPE_LIST, result->GetType());
  base::ListValue* list;
  ASSERT_TRUE(result->GetAsList(&list));

  EXPECT_EQ(1u, list->GetSize());
  base::Value* device_value;
  EXPECT_TRUE(list->Get(0, &device_value));
  EXPECT_EQ(base::Value::TYPE_DICTIONARY, device_value->GetType());
  base::DictionaryValue* device;
  ASSERT_TRUE(device_value->GetAsDictionary(&device));

  std::string name;
  ASSERT_TRUE(device->GetString("name", &name));
  EXPECT_EQ("d2", name);
  std::string address;
  ASSERT_TRUE(device->GetString("address", &address));
  EXPECT_EQ("21:22:23:24:25:26", address);
  bool paired;
  ASSERT_TRUE(device->GetBoolean("paired", &paired));
  EXPECT_FALSE(paired);
  bool bonded;
  ASSERT_TRUE(device->GetBoolean("bonded", &bonded));
  EXPECT_TRUE(bonded);
  bool connected;
  ASSERT_TRUE(device->GetBoolean("connected", &connected));
  EXPECT_FALSE(connected);
}

IN_PROC_BROWSER_TEST_F(BluetoothApiTest, GetLocalOutOfBandPairingData) {
  EXPECT_CALL(*mock_adapter_,
              ReadLocalOutOfBandPairingData(
                  testing::Truly(CallOutOfBandPairingDataCallback),
                  testing::_));

  scoped_refptr<api::BluetoothGetLocalOutOfBandPairingDataFunction>
      get_oob_function(setupFunction(
            new api::BluetoothGetLocalOutOfBandPairingDataFunction));

  scoped_ptr<base::Value> result(
      utils::RunFunctionAndReturnResult(get_oob_function, "[]", browser()));

  base::DictionaryValue* dict;
  EXPECT_TRUE(result->GetAsDictionary(&dict));

  base::BinaryValue* binary_value;
  EXPECT_TRUE(dict->GetBinary("hash", &binary_value));
  EXPECT_STREQ(kOutOfBandPairingDataHash,
      std::string(binary_value->GetBuffer(), binary_value->GetSize()).c_str());
  EXPECT_TRUE(dict->GetBinary("randomizer", &binary_value));
  EXPECT_STREQ(kOutOfBandPairingDataRandomizer,
      std::string(binary_value->GetBuffer(), binary_value->GetSize()).c_str());

  // Try again with an error
  testing::Mock::VerifyAndClearExpectations(mock_adapter_);
  EXPECT_CALL(*mock_adapter_,
              ReadLocalOutOfBandPairingData(
                  testing::_,
                  testing::Truly(CallClosure)));

  get_oob_function =
      setupFunction(new api::BluetoothGetLocalOutOfBandPairingDataFunction);

  std::string error(
      utils::RunFunctionAndReturnError(get_oob_function, "[]", browser()));
  EXPECT_FALSE(error.empty());
}

IN_PROC_BROWSER_TEST_F(BluetoothApiTest, DISABLED_SetOutOfBandPairingData) {
  // TODO(bryeung): Fill in this test once it is possible to include an
  // ArrayBuffer in the arguments to the RunFunctionAnd* methods.
  // crbug.com/132796
}

IN_PROC_BROWSER_TEST_F(BluetoothApiTest, ClearOutOfBandPairingData) {
  std::string device_address("11:12:13:14:15:16");
  testing::NiceMock<chromeos::MockBluetoothDevice> device(
      mock_adapter_, "d1", device_address,
      true /* paired */, false /* bonded */, true /* connected */);
  EXPECT_CALL(*mock_adapter_, GetDevice(device_address))
      .WillOnce(testing::Return(&device));
  EXPECT_CALL(device,
              ClearOutOfBandPairingData(
                  testing::Truly(CallClosure),
                  testing::_));

  char buf[32];
  snprintf(buf, sizeof(buf), "[\"%s\"]", device_address.c_str());
  std::string params(buf);

  scoped_refptr<api::BluetoothClearOutOfBandPairingDataFunction>
      clear_oob_function;
  clear_oob_function = setupFunction(
      new api::BluetoothClearOutOfBandPairingDataFunction);
  // There isn't actually a result.
  (void)utils::RunFunctionAndReturnResult(
      clear_oob_function, params, browser());

  // Try again with an error
  testing::Mock::VerifyAndClearExpectations(mock_adapter_);
  testing::Mock::VerifyAndClearExpectations(&device);
  EXPECT_CALL(*mock_adapter_, GetDevice(device_address))
      .WillOnce(testing::Return(&device));
  EXPECT_CALL(device,
              ClearOutOfBandPairingData(
                  testing::_,
                  testing::Truly(CallClosure)));

  clear_oob_function = setupFunction(
      new api::BluetoothClearOutOfBandPairingDataFunction);
  std::string error(
      utils::RunFunctionAndReturnError(clear_oob_function, params, browser()));
  EXPECT_FALSE(error.empty());
}
<|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 "chrome/browser/ui/views/tab_contents/native_tab_contents_view_aura.h"

#include "chrome/browser/ui/views/tab_contents/native_tab_contents_view_delegate.h"
#include "chrome/browser/ui/views/tab_contents/native_tab_contents_view_views.h"
#include "content/browser/renderer_host/render_widget_host_view_aura.h"
#include "content/browser/tab_contents/tab_contents.h"
#include "content/browser/tab_contents/tab_contents_view.h"
#include "ui/aura/event.h"
#include "ui/aura/window.h"
#include "views/views_delegate.h"
#include "views/widget/widget.h"

////////////////////////////////////////////////////////////////////////////////
// NativeTabContentsViewAura, public:

NativeTabContentsViewAura::NativeTabContentsViewAura(
    internal::NativeTabContentsViewDelegate* delegate)
    : views::NativeWidgetAura(delegate->AsNativeWidgetDelegate()),
      delegate_(delegate) {
}

NativeTabContentsViewAura::~NativeTabContentsViewAura() {
}

TabContents* NativeTabContentsViewAura::GetTabContents() const {
  return delegate_->GetTabContents();
}

void NativeTabContentsViewAura::EndDragging() {
  delegate_->OnNativeTabContentsViewDraggingEnded();
  // TODO(beng):
  NOTIMPLEMENTED();
}

////////////////////////////////////////////////////////////////////////////////
// NativeTabContentsViewAura, NativeTabContentsView implementation:

void NativeTabContentsViewAura::InitNativeTabContentsView() {
  views::Widget::InitParams params(views::Widget::InitParams::TYPE_CONTROL);
  params.native_widget = this;
  params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
  params.parent = NULL;
  GetWidget()->Init(params);
}

void NativeTabContentsViewAura::Unparent() {
  // Nothing to do.
}

RenderWidgetHostView* NativeTabContentsViewAura::CreateRenderWidgetHostView(
    RenderWidgetHost* render_widget_host) {
  RenderWidgetHostViewAura* view =
      new RenderWidgetHostViewAura(render_widget_host);
  view->Init();
  GetNativeView()->AddChild(view->GetNativeView());
  view->Show();
  return view;
}

gfx::NativeWindow NativeTabContentsViewAura::GetTopLevelNativeWindow() const {
  // TODO(beng):
  NOTIMPLEMENTED();
  return NULL;
}

void NativeTabContentsViewAura::SetPageTitle(const string16& title) {
  // TODO(beng):
  NOTIMPLEMENTED();
}

void NativeTabContentsViewAura::StartDragging(const WebDropData& drop_data,
                                             WebKit::WebDragOperationsMask ops,
                                             const SkBitmap& image,
                                             const gfx::Point& image_offset) {
  // TODO(beng):
  NOTIMPLEMENTED();
}

void NativeTabContentsViewAura::CancelDrag() {
  // TODO(beng):
  NOTIMPLEMENTED();
}

bool NativeTabContentsViewAura::IsDoingDrag() const {
  // TODO(beng):
  NOTIMPLEMENTED();
  return false;
}

void NativeTabContentsViewAura::SetDragCursor(
    WebKit::WebDragOperation operation) {
  // TODO(beng):
  NOTIMPLEMENTED();
}

views::NativeWidget* NativeTabContentsViewAura::AsNativeWidget() {
  return this;
}

////////////////////////////////////////////////////////////////////////////////
// NativeTabContentsViewAura, views::NativeWidgetAura overrides:

void NativeTabContentsViewAura::OnBoundsChanged(const gfx::Rect& old_bounds,
                                                const gfx::Rect& new_bounds) {
  delegate_->OnNativeTabContentsViewSized(new_bounds.size());
  views::NativeWidgetAura::OnBoundsChanged(old_bounds, new_bounds);
}

bool NativeTabContentsViewAura::OnMouseEvent(aura::MouseEvent* event) {
  if (!delegate_->IsShowingSadTab()) {
    switch (event->type()) {
      case ui::ET_MOUSE_EXITED:
        delegate_->OnNativeTabContentsViewMouseMove(false);
        break;
      case ui::ET_MOUSE_MOVED:
        delegate_->OnNativeTabContentsViewMouseMove(true);
        break;
      default:
        // TODO(oshima): mouse wheel
        break;
    }
  }
  // Pass all mouse event to renderer.
  return views::NativeWidgetAura::OnMouseEvent(event);
}

#if !defined(TOUCH_UI)
////////////////////////////////////////////////////////////////////////////////
// NativeTabContentsView, public:

// static
NativeTabContentsView* NativeTabContentsView::CreateNativeTabContentsView(
    internal::NativeTabContentsViewDelegate* delegate) {
  // return new NativeTabContentsViewViews(delegate);
  // TODO(beng): switch over to this.
  return new NativeTabContentsViewAura(delegate);
}
#endif
<commit_msg>Prevent Instant TabContentsViews from appearing upon creation by hiding all TCVs when they're created.<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 "chrome/browser/ui/views/tab_contents/native_tab_contents_view_aura.h"

#include "chrome/browser/ui/views/tab_contents/native_tab_contents_view_delegate.h"
#include "chrome/browser/ui/views/tab_contents/native_tab_contents_view_views.h"
#include "content/browser/renderer_host/render_widget_host_view_aura.h"
#include "content/browser/tab_contents/tab_contents.h"
#include "content/browser/tab_contents/tab_contents_view.h"
#include "ui/aura/event.h"
#include "ui/aura/window.h"
#include "views/views_delegate.h"
#include "views/widget/widget.h"

////////////////////////////////////////////////////////////////////////////////
// NativeTabContentsViewAura, public:

NativeTabContentsViewAura::NativeTabContentsViewAura(
    internal::NativeTabContentsViewDelegate* delegate)
    : views::NativeWidgetAura(delegate->AsNativeWidgetDelegate()),
      delegate_(delegate) {
}

NativeTabContentsViewAura::~NativeTabContentsViewAura() {
}

TabContents* NativeTabContentsViewAura::GetTabContents() const {
  return delegate_->GetTabContents();
}

void NativeTabContentsViewAura::EndDragging() {
  delegate_->OnNativeTabContentsViewDraggingEnded();
  // TODO(beng):
  NOTIMPLEMENTED();
}

////////////////////////////////////////////////////////////////////////////////
// NativeTabContentsViewAura, NativeTabContentsView implementation:

void NativeTabContentsViewAura::InitNativeTabContentsView() {
  views::Widget::InitParams params(views::Widget::InitParams::TYPE_CONTROL);
  params.native_widget = this;
  params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
  params.parent = NULL;
  GetWidget()->Init(params);

  // Hide the widget to prevent it from showing up on the desktop. This is
  // needed for TabContentses that aren't immediately added to the tabstrip,
  // e.g. the Instant preview contents.
  // TODO(beng): investigate if control-type windows shouldn't be hidden by
  //             default if they are created with no parent. Pending oshima's
  //             change to reflect Widget types onto a ViewProp.
  GetWidget()->Hide();
}

void NativeTabContentsViewAura::Unparent() {
  // Nothing to do.
}

RenderWidgetHostView* NativeTabContentsViewAura::CreateRenderWidgetHostView(
    RenderWidgetHost* render_widget_host) {
  RenderWidgetHostViewAura* view =
      new RenderWidgetHostViewAura(render_widget_host);
  view->Init();
  GetNativeView()->AddChild(view->GetNativeView());
  view->Show();
  return view;
}

gfx::NativeWindow NativeTabContentsViewAura::GetTopLevelNativeWindow() const {
  // TODO(beng):
  NOTIMPLEMENTED();
  return NULL;
}

void NativeTabContentsViewAura::SetPageTitle(const string16& title) {
  // TODO(beng):
  NOTIMPLEMENTED();
}

void NativeTabContentsViewAura::StartDragging(const WebDropData& drop_data,
                                             WebKit::WebDragOperationsMask ops,
                                             const SkBitmap& image,
                                             const gfx::Point& image_offset) {
  // TODO(beng):
  NOTIMPLEMENTED();
}

void NativeTabContentsViewAura::CancelDrag() {
  // TODO(beng):
  NOTIMPLEMENTED();
}

bool NativeTabContentsViewAura::IsDoingDrag() const {
  // TODO(beng):
  NOTIMPLEMENTED();
  return false;
}

void NativeTabContentsViewAura::SetDragCursor(
    WebKit::WebDragOperation operation) {
  // TODO(beng):
  NOTIMPLEMENTED();
}

views::NativeWidget* NativeTabContentsViewAura::AsNativeWidget() {
  return this;
}

////////////////////////////////////////////////////////////////////////////////
// NativeTabContentsViewAura, views::NativeWidgetAura overrides:

void NativeTabContentsViewAura::OnBoundsChanged(const gfx::Rect& old_bounds,
                                                const gfx::Rect& new_bounds) {
  delegate_->OnNativeTabContentsViewSized(new_bounds.size());
  views::NativeWidgetAura::OnBoundsChanged(old_bounds, new_bounds);
}

bool NativeTabContentsViewAura::OnMouseEvent(aura::MouseEvent* event) {
  if (!delegate_->IsShowingSadTab()) {
    switch (event->type()) {
      case ui::ET_MOUSE_EXITED:
        delegate_->OnNativeTabContentsViewMouseMove(false);
        break;
      case ui::ET_MOUSE_MOVED:
        delegate_->OnNativeTabContentsViewMouseMove(true);
        break;
      default:
        // TODO(oshima): mouse wheel
        break;
    }
  }
  // Pass all mouse event to renderer.
  return views::NativeWidgetAura::OnMouseEvent(event);
}

#if !defined(TOUCH_UI)
////////////////////////////////////////////////////////////////////////////////
// NativeTabContentsView, public:

// static
NativeTabContentsView* NativeTabContentsView::CreateNativeTabContentsView(
    internal::NativeTabContentsViewDelegate* delegate) {
  // return new NativeTabContentsViewViews(delegate);
  // TODO(beng): switch over to this.
  return new NativeTabContentsViewAura(delegate);
}
#endif
<|endoftext|>