JSObject *
WrapperFactory::Rewrap(JSContext *cx, JSObject *existing, JSObject *obj,
                       JSObject *wrappedProto, JSObject *parent,
                       unsigned flags)
{
    MOZ_ASSERT(!IsWrapper(obj) ||
               GetProxyHandler(obj) == &XrayWaiver ||
               js::GetObjectClass(obj)->ext.innerObject,
               "wrapped object passed to rewrap");
    MOZ_ASSERT(JS_GetClass(obj) != &XrayUtils::HolderClass, "trying to wrap a holder");
    MOZ_ASSERT(!js::IsInnerObject(obj));
    // We sometimes end up here after nsContentUtils has been shut down but before
    // XPConnect has been shut down, so check the context stack the roundabout way.
    MOZ_ASSERT(XPCJSRuntime::Get()->GetJSContextStack()->Peek() == cx);

    // Compute the information we need to select the right wrapper.
    JSCompartment *origin = js::GetObjectCompartment(obj);
    JSCompartment *target = js::GetContextCompartment(cx);
    bool originIsChrome = AccessCheck::isChrome(origin);
    bool targetIsChrome = AccessCheck::isChrome(target);
    bool originSubsumesTarget = AccessCheck::subsumes(origin, target);
    bool targetSubsumesOrigin = AccessCheck::subsumes(target, origin);
    bool sameOrigin = targetSubsumesOrigin && originSubsumesTarget;
    XrayType xrayType = GetXrayType(obj);

    // By default we use the wrapped proto of the underlying object as the
    // prototype for our wrapper, but we may select something different below.
    JSObject *proxyProto = wrappedProto;

    Wrapper *wrapper;
    CompartmentPrivate *targetdata = EnsureCompartmentPrivate(target);

    //
    // First, handle the special cases.
    //

    // If UniversalXPConnect is enabled, this is just some dumb mochitest. Use
    // a vanilla CCW.
    if (xpc::IsUniversalXPConnectEnabled(target)) {
        wrapper = &CrossCompartmentWrapper::singleton;

    // If this is a chrome object being exposed to content without Xrays, use
    // a COW.
    } else if (originIsChrome && !targetIsChrome && xrayType == NotXray) {
        wrapper = &ChromeObjectWrapper::singleton;

    // If content is accessing a Components object or NAC, we need a special filter,
    // even if the object is same origin.
    } else if (IsComponentsObject(obj) && !AccessCheck::isChrome(target)) {
        wrapper = &FilteringWrapper<CrossCompartmentSecurityWrapper,
                                    ComponentsObjectPolicy>::singleton;
    } else if (AccessCheck::needsSystemOnlyWrapper(obj) &&
               !(targetIsChrome || (targetSubsumesOrigin && nsContentUtils::IsCallerXBL())))
    {
        wrapper = &FilteringWrapper<CrossCompartmentSecurityWrapper,
                                    OnlyIfSubjectIsSystem>::singleton;
    }

    //
    // Now, handle the regular cases.
    //
    // These are wrappers we can compute using a rule-based approach. In order
    // to do so, we need to compute some parameters.
    //
    else {

        // The wrapper is a security wrapper (protecting the wrappee) if and
        // only if the target does not subsume the origin.
        bool securityWrapper = !targetSubsumesOrigin;

        // Xrays are warranted if either the target or the origin don't trust
        // each other. This is generally the case, unless the two are same-origin
        // and the caller has not requested same-origin Xrays.
        //
        // Xrays are a bidirectional protection, since it affords clarity to the
        // caller and privacy to the callee.
        bool wantXrays = !(sameOrigin && !targetdata->wantXrays);

        // If Xrays are warranted, the caller may waive them for non-security
        // wrappers.
        bool waiveXrays = wantXrays && !securityWrapper &&
                          (flags & WAIVE_XRAY_WRAPPER_FLAG);

        wrapper = SelectWrapper(securityWrapper, wantXrays, xrayType, waiveXrays);
    }



    // If the prototype of a chrome object being wrapped in content is a prototype
    // for a standard class, use the one from the content compartment so
    // that we can safely take advantage of things like .forEach().
    //
    // If the prototype chain of chrome object |obj| looks like this:
    //
    // obj => foo => bar => chromeWin.StandardClass.prototype
    //
    // The prototype chain of COW(obj) looks lke this:
    //
    // COW(obj) => COW(foo) => COW(bar) => contentWin.StandardClass.prototype
    if (wrapper == &ChromeObjectWrapper::singleton) {
        JSProtoKey key = JSProto_Null;
        {
            JSAutoCompartment ac(cx, obj);
            JSObject *unwrappedProto;
            if (!js::GetObjectProto(cx, obj, &unwrappedProto))
                return NULL;
            if (unwrappedProto && IsCrossCompartmentWrapper(unwrappedProto))
                unwrappedProto = Wrapper::wrappedObject(unwrappedProto);
            if (unwrappedProto) {
                JSAutoCompartment ac2(cx, unwrappedProto);
                key = JS_IdentifyClassPrototype(cx, unwrappedProto);
            }
        }
        if (key != JSProto_Null) {
            JSObject *homeProto;
            if (!JS_GetClassPrototype(cx, key, &homeProto))
                return NULL;
            MOZ_ASSERT(homeProto);
            proxyProto = homeProto;
        }

        // This shouldn't happen, but do a quick check to make some dumb addon
        // doesn't expose chrome eval or Function().
        JSFunction *fun = JS_GetObjectFunction(obj);
        if (fun) {
            if (JS_IsBuiltinEvalFunction(fun) || JS_IsBuiltinFunctionConstructor(fun)) {
                JS_ReportError(cx, "Not allowed to access chrome eval or Function from content");
                return nullptr;
            }
        }
    }

    DEBUG_CheckUnwrapSafety(obj, wrapper, origin, target);

    if (existing && proxyProto == wrappedProto)
        return Wrapper::Renew(cx, existing, obj, wrapper);

    return Wrapper::New(cx, obj, proxyProto, parent, wrapper);
}
Example #2
0
bool
ExposedPropertiesOnly::check(JSContext* cx, HandleObject wrapper, HandleId id, Wrapper::Action act)
{
    RootedObject wrappedObject(cx, Wrapper::wrappedObject(wrapper));

    if (act == Wrapper::CALL)
        return false;

    // For the case of getting a property descriptor, we allow if either GET or SET
    // is allowed, and rely on FilteringWrapper to filter out any disallowed accessors.
    if (act == Wrapper::GET_PROPERTY_DESCRIPTOR) {
        return check(cx, wrapper, id, Wrapper::GET) ||
               check(cx, wrapper, id, Wrapper::SET);
    }

    RootedId exposedPropsId(cx, GetJSIDByIndex(cx, XPCJSContext::IDX_EXPOSEDPROPS));

    // We need to enter the wrappee's compartment to look at __exposedProps__,
    // but we want to be in the wrapper's compartment if we call Deny().
    //
    // Unfortunately, |cx| can be in either compartment when we call ::check. :-(
    JSAutoCompartment ac(cx, wrappedObject);

    bool found = false;
    if (!JS_HasPropertyById(cx, wrappedObject, exposedPropsId, &found))
        return false;

    // If no __exposedProps__ existed, deny access.
    if (!found) {
        // Previously we automatically granted access to indexed properties and
        // .length for Array COWs. We're not doing that anymore, so make sure to
        // let people know what's going on.
        bool isArray;
        if (!JS_IsArrayObject(cx, wrappedObject, &isArray))
            return false;
        if (!isArray)
            isArray = JS_IsTypedArrayObject(wrappedObject);
        bool isIndexedAccessOnArray = isArray && JSID_IS_INT(id) && JSID_TO_INT(id) >= 0;
        bool isLengthAccessOnArray = isArray && JSID_IS_STRING(id) &&
                                     JS_FlatStringEqualsAscii(JSID_TO_FLAT_STRING(id), "length");
        if (isIndexedAccessOnArray || isLengthAccessOnArray) {
            JSAutoCompartment ac2(cx, wrapper);
            ReportWrapperDenial(cx, id, WrapperDenialForCOW,
                                "Access to elements and length of privileged Array not permitted");
        }

        return false;
    }

    if (id == JSID_VOID)
        return true;

    Rooted<PropertyDescriptor> desc(cx);
    if (!JS_GetPropertyDescriptorById(cx, wrappedObject, exposedPropsId, &desc))
        return false;

    if (!desc.object())
        return false;

    if (desc.hasGetterOrSetter()) {
        EnterAndThrowASCII(cx, wrapper, "__exposedProps__ must be a value property");
        return false;
    }

    RootedValue exposedProps(cx, desc.value());
    if (exposedProps.isNullOrUndefined())
        return false;

    if (!exposedProps.isObject()) {
        EnterAndThrowASCII(cx, wrapper, "__exposedProps__ must be undefined, null, or an Object");
        return false;
    }

    RootedObject hallpass(cx, &exposedProps.toObject());

    if (!AccessCheck::subsumes(js::UncheckedUnwrap(hallpass), wrappedObject)) {
        EnterAndThrowASCII(cx, wrapper, "Invalid __exposedProps__");
        return false;
    }

    Access access = NO_ACCESS;

    if (!JS_GetPropertyDescriptorById(cx, hallpass, id, &desc)) {
        return false; // Error
    }
    if (!desc.object() || !desc.enumerable())
        return false;

    if (!desc.value().isString()) {
        EnterAndThrowASCII(cx, wrapper, "property must be a string");
        return false;
    }

    JSFlatString* flat = JS_FlattenString(cx, desc.value().toString());
    if (!flat)
        return false;

    size_t length = JS_GetStringLength(JS_FORGET_STRING_FLATNESS(flat));

    for (size_t i = 0; i < length; ++i) {
        char16_t ch = JS_GetFlatStringCharAt(flat, i);
        switch (ch) {
        case 'r':
            if (access & READ) {
                EnterAndThrowASCII(cx, wrapper, "duplicate 'readable' property flag");
                return false;
            }
            access = Access(access | READ);
            break;

        case 'w':
            if (access & WRITE) {
                EnterAndThrowASCII(cx, wrapper, "duplicate 'writable' property flag");
                return false;
            }
            access = Access(access | WRITE);
            break;

        default:
            EnterAndThrowASCII(cx, wrapper, "properties can only be readable or read and writable");
            return false;
        }
    }

    if (access == NO_ACCESS) {
        EnterAndThrowASCII(cx, wrapper, "specified properties must have a permission bit set");
        return false;
    }

    if ((act == Wrapper::SET && !(access & WRITE)) ||
        (act != Wrapper::SET && !(access & READ))) {
        return false;
    }

    // Inspect the property on the underlying object to check for red flags.
    if (!JS_GetPropertyDescriptorById(cx, wrappedObject, id, &desc))
        return false;

    // Reject accessor properties.
    if (desc.hasGetterOrSetter()) {
        EnterAndThrowASCII(cx, wrapper, "Exposing privileged accessor properties is prohibited");
        return false;
    }

    // Reject privileged or cross-origin callables.
    if (desc.value().isObject()) {
        RootedObject maybeCallable(cx, js::UncheckedUnwrap(&desc.value().toObject()));
        if (JS::IsCallable(maybeCallable) && !AccessCheck::subsumes(wrapper, maybeCallable)) {
            EnterAndThrowASCII(cx, wrapper, "Exposing privileged or cross-origin callable is prohibited");
            return false;
        }
    }

    return true;
}
int main(int argc, char** argv){

	ros::init(argc, argv, "simple_navigation_goals");
	//tell the action client that we want to spin a thread by default
	MoveBaseClient ac("move_base", true);
	move_base_msgs::MoveBaseGoal goal;
	goal.target_pose.header.frame_id = "map";
	goal.target_pose.header.stamp = ros::Time::now();
	MoveBaseClient ac2("move_base", true);
	MoveBaseClient ac0("move_base", true);


	ros::Rate r(100);
	ros::NodeHandle n;
	int flag = 0;

	int sum = 0;

	ros::Publisher updown_flag = n.advertise<std_msgs::UInt8>("updown_flag",1);
	//std_msgs::UInt8 ud_flag;

	while(ros::ok())
		
	{

		ROS_INFO("sum \t%d",sum);
		ROS_INFO("flag \t%d",flag);
		sum ++;
		switch(flag)
			
		{	
				
		case 0:{
						ROS_INFO("Hooray, the base moved 0 meter forward 0");

						//wait for the action server to come up

						while(!ac.waitForServer(ros::Duration(5.0))){
							ROS_INFO("Waiting for the move_base action server to come up");
						} 

						goal.target_pose.pose.position.x = 20;
						goal.target_pose.pose.position.y = 2.1;
						goal.target_pose.pose.orientation.z = 0;
						goal.target_pose.pose.orientation.w = 1;

						ROS_INFO("Sending goal");
						ac.sendGoal(goal);

						ac.waitForResult();

						if(ac.getState() == actionlib::SimpleClientGoalState::SUCCEEDED)
						{
							ROS_INFO("Hooray, the base moved 0 meter forward ");

							//ud_flag.data = 1;
							//updown_flag.publish(ud_flag);
							ros::Duration(120).sleep();
							//ud_flag.data = 2;
							//updown_flag.publish(ud_flag);
							//ros::Duration(23).sleep();

							flag = 1;

						}

						else
							ROS_INFO("The base failed to move forward 0 meter for some reason");
						break;
			   }
		case 1:{
				   //wait for the action server to come up
				   while(!ac.waitForServer(ros::Duration(5.0))){
					   ROS_INFO("Waiting for the move_base action server to come up");
				   }

				   goal.target_pose.pose.position.x = 0;
				   goal.target_pose.pose.position.y = 0;
				   goal.target_pose.pose.orientation.z = 0;
				   goal.target_pose.pose.orientation.w = 1;

				   ROS_INFO("Sending goal");
				   ac.sendGoal(goal);

				   ac.waitForResult();

				   if(ac.getState() == actionlib::SimpleClientGoalState::SUCCEEDED)
				   {
					   ROS_INFO("Hooray, the base moved 1 meter forward");

					   //ud_flag.data = 1;
					   //updown_flag.publish(ud_flag);
					   ros::Duration(2000).sleep();
					   //ud_flag.data = 2;
					   //updown_flag.publish(ud_flag);
					   //ros::Duration(23).sleep();
					   flag = 2;

				   }

				   else
					   ROS_INFO("The base failed to move forward 1 meter for some reason");
				   break;
			   }

		
		case 2:	{
					ROS_INFO("Hooray, the base moved 2 meter forward 0");
					//wait for the action server to come up

					while(!ac.waitForServer(ros::Duration(5.0))){
						ROS_INFO("Waiting for the move_base action server to come up");
					}


					goal.target_pose.pose.position.x = 0;
					goal.target_pose.pose.position.y = 0;
					goal.target_pose.pose.orientation.z = 0;
					goal.target_pose.pose.orientation.w = 1;

					ROS_INFO("Sending goal");
					ac.sendGoal(goal);

					ac.waitForResult();

					if(ac.getState() == actionlib::SimpleClientGoalState::SUCCEEDED)
					{
						ROS_INFO("Hooray, the base moved 2 meter forward");

							//ud_flag.data = 1;
							//updown_flag.publish(ud_flag);
							ros::Duration(20).sleep();
							//ud_flag.data = 2;
							//updown_flag.publish(ud_flag);
							//ros::Duration(60).sleep();
						flag = 0;

					}

					else
						ROS_INFO("The base failed to move forward 2 meter for some reason");
					break;
				}


		}


	}

	return 0;
}